Skip to content

Commit

Permalink
Add model[] formspec element (#10320)
Browse files Browse the repository at this point in the history
Formspec element to display models, written by @kilbith, rebased and tweaked.

Co-authored-by: Jean-Patrick Guerrero <jeanpatrick.guerrero@gmail.com>
Co-authored-by: sfan5 <sfan5@live.de>
  • Loading branch information
3 people committed Nov 4, 2020
1 parent e3bd670 commit 3356da0
Show file tree
Hide file tree
Showing 16 changed files with 545 additions and 1 deletion.
16 changes: 16 additions & 0 deletions doc/lua_api.txt
Expand Up @@ -2272,6 +2272,18 @@ Elements
* `frame duration`: Milliseconds between each frame. `0` means the frames don't advance.
* `frame start` (Optional): The index of the frame to start on. Default `1`.

### `model[<X>,<Y>;<W>,<H>;<name>;<mesh>;<textures>;<rotation X,Y>;<continuous>;<mouse control>]`

* Show a mesh model.
* `name`: Element name that can be used for styling
* `mesh`: The mesh model to use.
* `textures`: The mesh textures to use according to the mesh materials.
Texture names must be separated by commas.
* `rotation {X,Y}` (Optional): Initial rotation of the camera.
The axes are euler angles in degrees.
* `continuous` (Optional): Whether the rotation is continuous. Default `false`.
* `mouse control` (Optional): Whether the model can be controlled with the mouse. Default `true`.

### `item_image[<X>,<Y>;<W>,<H>;<item name>]`

* Show an inventory image of registered item/node
Expand Down Expand Up @@ -2842,6 +2854,10 @@ Some types may inherit styles from parent types.
* font_size - Sets font size. See button `font_size` property for more information.
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
* textcolor - color. Default white.
* model
* bgcolor - color, sets background color.
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
* Default to false in formspec_version version 3 or higher
* image
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
* Default to false in formspec_version version 3 or higher
Expand Down
14 changes: 14 additions & 0 deletions games/devtest/mods/testformspec/LICENSE.txt
@@ -0,0 +1,14 @@
License of media files
----------------------
Content imported from minetest_game.


BlockMen (CC BY-SA 3.0)
default_chest_front.png
default_chest_lock.png
default_chest_side.png
default_chest_top.png

stujones11 (CC BY-SA 3.0)
An0n3m0us (CC BY-SA 3.0)
testformspec_character.b3d
4 changes: 4 additions & 0 deletions games/devtest/mods/testformspec/formspec.lua
Expand Up @@ -327,6 +327,10 @@ Number]
animated_image[3,4.25;1,1;;testformspec_animation.png;4;0;3]
animated_image[5.5,0.5;5,2;;testformspec_animation.png;4;100]
animated_image[5.5,2.75;5,2;;testformspec_animation.jpg;4;100]
style[m1;bgcolor=black]
model[0.5,6;4,4;m1;testformspec_character.b3d;testformspec_character.png]
model[5,6;4,4;m2;testformspec_chest.obj;default_chest_top.png,default_chest_top.png,default_chest_side.png,default_chest_side.png,default_chest_front.png,default_chest_inside.png;30,1;true;true]
]],

-- Scroll containers
Expand Down
Binary file not shown.
79 changes: 79 additions & 0 deletions games/devtest/mods/testformspec/models/testformspec_chest.obj
@@ -0,0 +1,79 @@
# Blender v2.78 (sub 0) OBJ File: 'chest-open.blend'
# www.blender.org
o Top_Cube.002_None_Top_Cube.002_None_bottom
v -0.500000 0.408471 0.720970
v -0.500000 1.115578 0.013863
v -0.500000 0.894607 -0.207108
v -0.500000 0.187501 0.499999
v 0.500000 1.115578 0.013863
v 0.500000 0.408471 0.720970
v 0.500000 0.187501 0.499999
v 0.500000 0.894607 -0.207108
v -0.500000 0.187500 -0.500000
v -0.500000 -0.500000 -0.500000
v -0.500000 -0.500000 0.500000
v 0.500000 0.187500 -0.500000
v 0.500000 -0.500000 0.500000
v 0.500000 -0.500000 -0.500000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 0.0000 1.0000
vt 1.0000 1.0000
vt 1.0000 0.6875
vt 0.0000 0.6875
vt 1.0000 1.0000
vt 0.0000 0.6875
vt 1.0000 0.6875
vt 1.0000 0.6875
vt 1.0000 0.0000
vt 0.0000 0.0000
vt 1.0000 0.6875
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 1.0000 0.6875
vt 1.0000 0.0000
vt 0.0000 1.0000
vt 0.0000 0.6875
vt 0.0000 0.6875
vt 0.0000 0.0000
vt 1.0000 0.5000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.5000
vt 0.0000 0.0000
vt 1.0000 0.0000
vn 0.0000 0.7071 0.7071
vn -0.0000 -1.0000 -0.0000
vn -1.0000 0.0000 0.0000
vn 1.0000 0.0000 -0.0000
vn 0.0000 -0.7071 0.7071
vn 0.0000 0.0000 1.0000
vn -0.0000 0.7071 -0.7071
vn -0.0000 0.0000 -1.0000
vn -0.0000 -0.7071 -0.7071
vn -0.0000 1.0000 -0.0000
g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Top
s off
f 6/1/1 5/2/1 2/3/1 1/4/1
g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Bottom
f 11/5/2 10/6/2 14/7/2 13/8/2
g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Right-Left
f 1/9/3 2/10/3 3/11/3 4/12/3
f 5/13/4 6/1/4 7/14/4 8/15/4
f 4/12/3 9/16/3 10/17/3 11/18/3
f 12/19/4 7/14/4 13/8/4 14/20/4
g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Back
f 6/21/5 1/9/5 4/12/5 7/22/5
f 7/22/6 4/12/6 11/18/6 13/23/6
g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Front
f 2/10/7 5/24/7 8/25/7 3/11/7
f 9/16/8 12/26/8 14/27/8 10/17/8
g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Inside
f 4/28/9 3/29/9 8/30/9 7/31/9
f 7/31/10 12/32/10 9/33/10 4/28/10
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/gui/CMakeLists.txt
Expand Up @@ -15,6 +15,7 @@ set(gui_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/guiKeyChangeMenu.cpp
${CMAKE_CURRENT_SOURCE_DIR}/guiPasswordChange.cpp
${CMAKE_CURRENT_SOURCE_DIR}/guiPathSelectMenu.cpp
${CMAKE_CURRENT_SOURCE_DIR}/guiScene.cpp
${CMAKE_CURRENT_SOURCE_DIR}/guiScrollBar.cpp
${CMAKE_CURRENT_SOURCE_DIR}/guiScrollContainer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/guiSkin.cpp
Expand Down
86 changes: 86 additions & 0 deletions src/gui/guiFormSpecMenu.cpp
Expand Up @@ -65,6 +65,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "guiScrollContainer.h"
#include "intlGUIEditBox.h"
#include "guiHyperText.h"
#include "guiScene.h"

#define MY_CHECKPOS(a,b) \
if (v_pos.size() != 2) { \
Expand Down Expand Up @@ -2695,6 +2696,86 @@ void GUIFormSpecMenu::parseSetFocus(const std::string &element)
<< "'" << std::endl;
}

void GUIFormSpecMenu::parseModel(parserData *data, const std::string &element)
{
std::vector<std::string> parts = split(element, ';');

if (parts.size() < 5 || (parts.size() > 8 &&
m_formspec_version <= FORMSPEC_API_VERSION)) {
errorstream << "Invalid model element (" << parts.size() << "): '" << element
<< "'" << std::endl;
return;
}

// Avoid length checks by resizing
if (parts.size() < 8)
parts.resize(8);

std::vector<std::string> v_pos = split(parts[0], ',');
std::vector<std::string> v_geom = split(parts[1], ',');
std::string name = unescape_string(parts[2]);
std::string meshstr = unescape_string(parts[3]);
std::vector<std::string> textures = split(parts[4], ',');
std::vector<std::string> vec_rot = split(parts[5], ',');
bool inf_rotation = is_yes(parts[6]);
bool mousectrl = is_yes(parts[7]) || parts[7].empty(); // default true

MY_CHECKPOS("model", 0);
MY_CHECKGEOM("model", 1);

v2s32 pos;
v2s32 geom;

if (data->real_coordinates) {
pos = getRealCoordinateBasePos(v_pos);
geom = getRealCoordinateGeometry(v_geom);
} else {
pos = getElementBasePos(&v_pos);
geom.X = stof(v_geom[0]) * (float)imgsize.X;
geom.Y = stof(v_geom[1]) * (float)imgsize.Y;
}

if (!data->explicit_size)
warningstream << "invalid use of model without a size[] element" << std::endl;

scene::IAnimatedMesh *mesh = m_client->getMesh(meshstr);

if (!mesh) {
errorstream << "Invalid model element: Unable to load mesh:"
<< std::endl << "\t" << meshstr << std::endl;
return;
}

FieldSpec spec(
name,
L"",
L"",
258 + m_fields.size()
);

core::rect<s32> rect(pos, pos + geom);

GUIScene *e = new GUIScene(Environment, RenderingEngine::get_scene_manager(),
data->current_parent, rect, spec.fid);

auto meshnode = e->setMesh(mesh);

for (u32 i = 0; i < textures.size() && i < meshnode->getMaterialCount(); ++i)
e->setTexture(i, m_tsrc->getTexture(textures[i]));

if (vec_rot.size() >= 2)
e->setRotation(v2f(stof(vec_rot[0]), stof(vec_rot[1])));

e->enableContinuousRotation(inf_rotation);
e->enableMouseControl(mousectrl);

auto style = getStyleForElement("model", spec.fname);
e->setStyles(style);
e->drop();

m_fields.push_back(spec);
}

void GUIFormSpecMenu::parseElement(parserData* data, const std::string &element)
{
//some prechecks
Expand Down Expand Up @@ -2891,6 +2972,11 @@ void GUIFormSpecMenu::parseElement(parserData* data, const std::string &element)
return;
}

if (type == "model") {
parseModel(data, description);
return;
}

// Ignore others
infostream << "Unknown DrawSpec: type=" << type << ", data=\"" << description << "\""
<< std::endl;
Expand Down
2 changes: 1 addition & 1 deletion src/gui/guiFormSpecMenu.h
Expand Up @@ -38,7 +38,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
class InventoryManager;
class ISimpleTextureSource;
class Client;
class TexturePool;
class GUIScrollContainer;

typedef enum {
Expand Down Expand Up @@ -444,6 +443,7 @@ class GUIFormSpecMenu : public GUIModalMenu
void parseAnchor(parserData *data, const std::string &element);
bool parseStyle(parserData *data, const std::string &element, bool style_type);
void parseSetFocus(const std::string &element);
void parseModel(parserData *data, const std::string &element);

void tryClose();

Expand Down

0 comments on commit 3356da0

Please sign in to comment.