mirror of
https://github.com/minetest/minetest.git
synced 2024-11-26 17:43: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)
|
||||
return (ptype == "color") or (ptype == "colorfacedir") or
|
||||
(ptype == "colorwallmounted")
|
||||
(ptype == "colorwallmounted") or (ptype == "colordegrotate")
|
||||
end
|
||||
|
||||
function core.strip_param2_color(param2, paramtype2)
|
||||
@ -168,6 +168,8 @@ function core.strip_param2_color(param2, paramtype2)
|
||||
param2 = math.floor(param2 / 32) * 32
|
||||
elseif paramtype2 == "colorwallmounted" then
|
||||
param2 = math.floor(param2 / 8) * 8
|
||||
elseif paramtype2 == "colordegrotate" then
|
||||
param2 = math.floor(param2 / 32) * 32
|
||||
end
|
||||
-- paramtype2 == "color" requires no modification.
|
||||
return param2
|
||||
@ -345,6 +347,8 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2,
|
||||
color_divisor = 8
|
||||
elseif def.paramtype2 == "colorfacedir" then
|
||||
color_divisor = 32
|
||||
elseif def.paramtype2 == "colordegrotate" then
|
||||
color_divisor = 32
|
||||
end
|
||||
if color_divisor then
|
||||
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 is (`param2` / 16) nodes.
|
||||
* `paramtype2 = "degrotate"`
|
||||
* Only valid for "plantlike" drawtype. The rotation of the node is stored in
|
||||
`param2`.
|
||||
* Values range 0 - 179. The value stored in `param2` is multiplied by two to
|
||||
* Valid for `plantlike` and `mesh` drawtypes. The rotation of the node is
|
||||
stored in `param2`.
|
||||
* Values range 0–239. The value stored in `param2` is multiplied by 1.5 to
|
||||
get the actual rotation in degrees of the node.
|
||||
* `paramtype2 = "meshoptions"`
|
||||
* 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
|
||||
and 63 being full.
|
||||
* 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"`
|
||||
* `param2` will not be used by the engine and can be used to store
|
||||
an arbitrary value
|
||||
|
@ -223,6 +223,30 @@ minetest.register_node("testnodes:plantlike_waving", {
|
||||
|
||||
|
||||
-- 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", {
|
||||
description = S("Degrotate Plantlike Drawtype Test Node"),
|
||||
drawtype = "plantlike",
|
||||
@ -230,12 +254,42 @@ minetest.register_node("testnodes:plantlike_degrotate", {
|
||||
paramtype2 = "degrotate",
|
||||
tiles = { "testnodes_plantlike_degrotate.png" },
|
||||
|
||||
|
||||
on_rightclick = rotate_on_rightclick,
|
||||
place_param2 = 7,
|
||||
walkable = false,
|
||||
sunlight_propagates = true,
|
||||
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
|
||||
minetest.register_node("testnodes:plantlike_leveled", {
|
||||
description = S("Leveled Plantlike Drawtype Test Node"),
|
||||
|
@ -968,7 +968,7 @@ void MapblockMeshGenerator::drawPlantlike()
|
||||
draw_style = PLANT_STYLE_CROSS;
|
||||
scale = BS / 2 * f->visual_scale;
|
||||
offset = v3f(0, 0, 0);
|
||||
rotate_degree = 0;
|
||||
rotate_degree = 0.0f;
|
||||
random_offset_Y = false;
|
||||
face_num = 0;
|
||||
plant_height = 1.0;
|
||||
@ -988,7 +988,8 @@ void MapblockMeshGenerator::drawPlantlike()
|
||||
break;
|
||||
|
||||
case CPT2_DEGROTATE:
|
||||
rotate_degree = n.param2 * 2;
|
||||
case CPT2_COLORED_DEGROTATE:
|
||||
rotate_degree = 1.5f * n.getDegRotate(nodedef);
|
||||
break;
|
||||
|
||||
case CPT2_LEVELED:
|
||||
@ -1343,6 +1344,7 @@ void MapblockMeshGenerator::drawMeshNode()
|
||||
u8 facedir = 0;
|
||||
scene::IMesh* mesh;
|
||||
bool private_mesh; // as a grab/drop pair is not thread-safe
|
||||
int degrotate = 0;
|
||||
|
||||
if (f->param_type_2 == CPT2_FACEDIR ||
|
||||
f->param_type_2 == CPT2_COLORED_FACEDIR) {
|
||||
@ -1354,9 +1356,12 @@ void MapblockMeshGenerator::drawMeshNode()
|
||||
facedir = n.getWallMounted(nodedef);
|
||||
if (!enable_mesh_cache)
|
||||
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
|
||||
private_mesh = false;
|
||||
mesh = f->mesh_ptr[facedir];
|
||||
@ -1364,7 +1369,10 @@ void MapblockMeshGenerator::drawMeshNode()
|
||||
// no cache, clone and rotate mesh
|
||||
private_mesh = true;
|
||||
mesh = cloneMesh(f->mesh_ptr[0]);
|
||||
if (facedir)
|
||||
rotateMeshBy6dFacedir(mesh, facedir);
|
||||
else if (degrotate)
|
||||
rotateMeshXZby(mesh, 1.5f * degrotate);
|
||||
recalculateBoundingBox(mesh);
|
||||
meshmanip->recalculateNormals(mesh, true, false);
|
||||
} else
|
||||
|
@ -139,7 +139,7 @@ public:
|
||||
// plantlike-specific
|
||||
PlantlikeStyle draw_style;
|
||||
v3f offset;
|
||||
int rotate_degree;
|
||||
float rotate_degree;
|
||||
bool random_offset_Y;
|
||||
int face_num;
|
||||
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)
|
||||
{
|
||||
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];
|
||||
param2 &= ~7;
|
||||
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;
|
||||
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);
|
||||
|
||||
/*!
|
||||
|
@ -944,7 +944,8 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
|
||||
|
||||
if (param_type_2 == CPT2_COLOR ||
|
||||
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);
|
||||
|
||||
if (drawtype == NDT_MESH && !mesh.empty()) {
|
||||
|
@ -67,7 +67,7 @@ enum ContentParamType2
|
||||
CPT2_WALLMOUNTED,
|
||||
// Block level like FLOWINGLIQUID
|
||||
CPT2_LEVELED,
|
||||
// 2D rotation for things like plants
|
||||
// 2D rotation
|
||||
CPT2_DEGROTATE,
|
||||
// Mesh options for plants
|
||||
CPT2_MESHOPTIONS,
|
||||
@ -79,6 +79,8 @@ enum ContentParamType2
|
||||
CPT2_COLORED_WALLMOUNTED,
|
||||
// Glasslike framed drawtype internal liquid level, param2 values 0 to 63
|
||||
CPT2_GLASSLIKE_LIQUID_LEVEL,
|
||||
// 3 bits of palette index, then degrotate
|
||||
CPT2_COLORED_DEGROTATE,
|
||||
};
|
||||
|
||||
enum LiquidType
|
||||
|
@ -685,7 +685,8 @@ void read_content_features(lua_State *L, ContentFeatures &f, int index)
|
||||
if (!f.palette_name.empty() &&
|
||||
!(f.param_type_2 == CPT2_COLOR ||
|
||||
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()
|
||||
<< " 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_WALLMOUNTED, "colorwallmounted"},
|
||||
{CPT2_GLASSLIKE_LIQUID_LEVEL, "glasslikeliquidlevel"},
|
||||
{CPT2_COLORED_DEGROTATE, "colordegrotate"},
|
||||
{0, NULL},
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user