Skip to content

Commit 3356da0

Browse files
SmallJokerkilbithsfan5
authoredNov 4, 2020
Add model[] formspec element (#10320)
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>
1 parent e3bd670 commit 3356da0

16 files changed

+545
-1
lines changed
 

Diff for: ‎doc/lua_api.txt

+16
Original file line numberDiff line numberDiff line change
@@ -2272,6 +2272,18 @@ Elements
22722272
* `frame duration`: Milliseconds between each frame. `0` means the frames don't advance.
22732273
* `frame start` (Optional): The index of the frame to start on. Default `1`.
22742274

2275+
### `model[<X>,<Y>;<W>,<H>;<name>;<mesh>;<textures>;<rotation X,Y>;<continuous>;<mouse control>]`
2276+
2277+
* Show a mesh model.
2278+
* `name`: Element name that can be used for styling
2279+
* `mesh`: The mesh model to use.
2280+
* `textures`: The mesh textures to use according to the mesh materials.
2281+
Texture names must be separated by commas.
2282+
* `rotation {X,Y}` (Optional): Initial rotation of the camera.
2283+
The axes are euler angles in degrees.
2284+
* `continuous` (Optional): Whether the rotation is continuous. Default `false`.
2285+
* `mouse control` (Optional): Whether the model can be controlled with the mouse. Default `true`.
2286+
22752287
### `item_image[<X>,<Y>;<W>,<H>;<item name>]`
22762288

22772289
* Show an inventory image of registered item/node
@@ -2842,6 +2854,10 @@ Some types may inherit styles from parent types.
28422854
* font_size - Sets font size. See button `font_size` property for more information.
28432855
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
28442856
* textcolor - color. Default white.
2857+
* model
2858+
* bgcolor - color, sets background color.
2859+
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
2860+
* Default to false in formspec_version version 3 or higher
28452861
* image
28462862
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
28472863
* Default to false in formspec_version version 3 or higher

Diff for: ‎games/devtest/mods/testformspec/LICENSE.txt

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
License of media files
2+
----------------------
3+
Content imported from minetest_game.
4+
5+
6+
BlockMen (CC BY-SA 3.0)
7+
default_chest_front.png
8+
default_chest_lock.png
9+
default_chest_side.png
10+
default_chest_top.png
11+
12+
stujones11 (CC BY-SA 3.0)
13+
An0n3m0us (CC BY-SA 3.0)
14+
testformspec_character.b3d

Diff for: ‎games/devtest/mods/testformspec/formspec.lua

+4
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,10 @@ Number]
327327
animated_image[3,4.25;1,1;;testformspec_animation.png;4;0;3]
328328
animated_image[5.5,0.5;5,2;;testformspec_animation.png;4;100]
329329
animated_image[5.5,2.75;5,2;;testformspec_animation.jpg;4;100]
330+
331+
style[m1;bgcolor=black]
332+
model[0.5,6;4,4;m1;testformspec_character.b3d;testformspec_character.png]
333+
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]
330334
]],
331335

332336
-- Scroll containers
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Blender v2.78 (sub 0) OBJ File: 'chest-open.blend'
2+
# www.blender.org
3+
o Top_Cube.002_None_Top_Cube.002_None_bottom
4+
v -0.500000 0.408471 0.720970
5+
v -0.500000 1.115578 0.013863
6+
v -0.500000 0.894607 -0.207108
7+
v -0.500000 0.187501 0.499999
8+
v 0.500000 1.115578 0.013863
9+
v 0.500000 0.408471 0.720970
10+
v 0.500000 0.187501 0.499999
11+
v 0.500000 0.894607 -0.207108
12+
v -0.500000 0.187500 -0.500000
13+
v -0.500000 -0.500000 -0.500000
14+
v -0.500000 -0.500000 0.500000
15+
v 0.500000 0.187500 -0.500000
16+
v 0.500000 -0.500000 0.500000
17+
v 0.500000 -0.500000 -0.500000
18+
vt 0.0000 1.0000
19+
vt 0.0000 0.0000
20+
vt 1.0000 0.0000
21+
vt 1.0000 1.0000
22+
vt 1.0000 0.0000
23+
vt 1.0000 1.0000
24+
vt 0.0000 1.0000
25+
vt 0.0000 0.0000
26+
vt 0.0000 1.0000
27+
vt 1.0000 1.0000
28+
vt 1.0000 0.6875
29+
vt 0.0000 0.6875
30+
vt 1.0000 1.0000
31+
vt 0.0000 0.6875
32+
vt 1.0000 0.6875
33+
vt 1.0000 0.6875
34+
vt 1.0000 0.0000
35+
vt 0.0000 0.0000
36+
vt 1.0000 0.6875
37+
vt 1.0000 0.0000
38+
vt 1.0000 1.0000
39+
vt 1.0000 0.6875
40+
vt 1.0000 0.0000
41+
vt 0.0000 1.0000
42+
vt 0.0000 0.6875
43+
vt 0.0000 0.6875
44+
vt 0.0000 0.0000
45+
vt 1.0000 0.5000
46+
vt 1.0000 1.0000
47+
vt 0.0000 1.0000
48+
vt 0.0000 0.5000
49+
vt 0.0000 0.0000
50+
vt 1.0000 0.0000
51+
vn 0.0000 0.7071 0.7071
52+
vn -0.0000 -1.0000 -0.0000
53+
vn -1.0000 0.0000 0.0000
54+
vn 1.0000 0.0000 -0.0000
55+
vn 0.0000 -0.7071 0.7071
56+
vn 0.0000 0.0000 1.0000
57+
vn -0.0000 0.7071 -0.7071
58+
vn -0.0000 0.0000 -1.0000
59+
vn -0.0000 -0.7071 -0.7071
60+
vn -0.0000 1.0000 -0.0000
61+
g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Top
62+
s off
63+
f 6/1/1 5/2/1 2/3/1 1/4/1
64+
g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Bottom
65+
f 11/5/2 10/6/2 14/7/2 13/8/2
66+
g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Right-Left
67+
f 1/9/3 2/10/3 3/11/3 4/12/3
68+
f 5/13/4 6/1/4 7/14/4 8/15/4
69+
f 4/12/3 9/16/3 10/17/3 11/18/3
70+
f 12/19/4 7/14/4 13/8/4 14/20/4
71+
g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Back
72+
f 6/21/5 1/9/5 4/12/5 7/22/5
73+
f 7/22/6 4/12/6 11/18/6 13/23/6
74+
g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Front
75+
f 2/10/7 5/24/7 8/25/7 3/11/7
76+
f 9/16/8 12/26/8 14/27/8 10/17/8
77+
g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Inside
78+
f 4/28/9 3/29/9 8/30/9 7/31/9
79+
f 7/31/10 12/32/10 9/33/10 4/28/10
423 Bytes
Loading
102 Bytes
Loading
375 Bytes
Loading
423 Bytes
Loading
Loading

Diff for: ‎src/gui/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ set(gui_SRCS
1515
${CMAKE_CURRENT_SOURCE_DIR}/guiKeyChangeMenu.cpp
1616
${CMAKE_CURRENT_SOURCE_DIR}/guiPasswordChange.cpp
1717
${CMAKE_CURRENT_SOURCE_DIR}/guiPathSelectMenu.cpp
18+
${CMAKE_CURRENT_SOURCE_DIR}/guiScene.cpp
1819
${CMAKE_CURRENT_SOURCE_DIR}/guiScrollBar.cpp
1920
${CMAKE_CURRENT_SOURCE_DIR}/guiScrollContainer.cpp
2021
${CMAKE_CURRENT_SOURCE_DIR}/guiSkin.cpp

Diff for: ‎src/gui/guiFormSpecMenu.cpp

+86
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
6565
#include "guiScrollContainer.h"
6666
#include "intlGUIEditBox.h"
6767
#include "guiHyperText.h"
68+
#include "guiScene.h"
6869

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

2699+
void GUIFormSpecMenu::parseModel(parserData *data, const std::string &element)
2700+
{
2701+
std::vector<std::string> parts = split(element, ';');
2702+
2703+
if (parts.size() < 5 || (parts.size() > 8 &&
2704+
m_formspec_version <= FORMSPEC_API_VERSION)) {
2705+
errorstream << "Invalid model element (" << parts.size() << "): '" << element
2706+
<< "'" << std::endl;
2707+
return;
2708+
}
2709+
2710+
// Avoid length checks by resizing
2711+
if (parts.size() < 8)
2712+
parts.resize(8);
2713+
2714+
std::vector<std::string> v_pos = split(parts[0], ',');
2715+
std::vector<std::string> v_geom = split(parts[1], ',');
2716+
std::string name = unescape_string(parts[2]);
2717+
std::string meshstr = unescape_string(parts[3]);
2718+
std::vector<std::string> textures = split(parts[4], ',');
2719+
std::vector<std::string> vec_rot = split(parts[5], ',');
2720+
bool inf_rotation = is_yes(parts[6]);
2721+
bool mousectrl = is_yes(parts[7]) || parts[7].empty(); // default true
2722+
2723+
MY_CHECKPOS("model", 0);
2724+
MY_CHECKGEOM("model", 1);
2725+
2726+
v2s32 pos;
2727+
v2s32 geom;
2728+
2729+
if (data->real_coordinates) {
2730+
pos = getRealCoordinateBasePos(v_pos);
2731+
geom = getRealCoordinateGeometry(v_geom);
2732+
} else {
2733+
pos = getElementBasePos(&v_pos);
2734+
geom.X = stof(v_geom[0]) * (float)imgsize.X;
2735+
geom.Y = stof(v_geom[1]) * (float)imgsize.Y;
2736+
}
2737+
2738+
if (!data->explicit_size)
2739+
warningstream << "invalid use of model without a size[] element" << std::endl;
2740+
2741+
scene::IAnimatedMesh *mesh = m_client->getMesh(meshstr);
2742+
2743+
if (!mesh) {
2744+
errorstream << "Invalid model element: Unable to load mesh:"
2745+
<< std::endl << "\t" << meshstr << std::endl;
2746+
return;
2747+
}
2748+
2749+
FieldSpec spec(
2750+
name,
2751+
L"",
2752+
L"",
2753+
258 + m_fields.size()
2754+
);
2755+
2756+
core::rect<s32> rect(pos, pos + geom);
2757+
2758+
GUIScene *e = new GUIScene(Environment, RenderingEngine::get_scene_manager(),
2759+
data->current_parent, rect, spec.fid);
2760+
2761+
auto meshnode = e->setMesh(mesh);
2762+
2763+
for (u32 i = 0; i < textures.size() && i < meshnode->getMaterialCount(); ++i)
2764+
e->setTexture(i, m_tsrc->getTexture(textures[i]));
2765+
2766+
if (vec_rot.size() >= 2)
2767+
e->setRotation(v2f(stof(vec_rot[0]), stof(vec_rot[1])));
2768+
2769+
e->enableContinuousRotation(inf_rotation);
2770+
e->enableMouseControl(mousectrl);
2771+
2772+
auto style = getStyleForElement("model", spec.fname);
2773+
e->setStyles(style);
2774+
e->drop();
2775+
2776+
m_fields.push_back(spec);
2777+
}
2778+
26982779
void GUIFormSpecMenu::parseElement(parserData* data, const std::string &element)
26992780
{
27002781
//some prechecks
@@ -2891,6 +2972,11 @@ void GUIFormSpecMenu::parseElement(parserData* data, const std::string &element)
28912972
return;
28922973
}
28932974

2975+
if (type == "model") {
2976+
parseModel(data, description);
2977+
return;
2978+
}
2979+
28942980
// Ignore others
28952981
infostream << "Unknown DrawSpec: type=" << type << ", data=\"" << description << "\""
28962982
<< std::endl;

Diff for: ‎src/gui/guiFormSpecMenu.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
3838
class InventoryManager;
3939
class ISimpleTextureSource;
4040
class Client;
41-
class TexturePool;
4241
class GUIScrollContainer;
4342

4443
typedef enum {
@@ -444,6 +443,7 @@ class GUIFormSpecMenu : public GUIModalMenu
444443
void parseAnchor(parserData *data, const std::string &element);
445444
bool parseStyle(parserData *data, const std::string &element, bool style_type);
446445
void parseSetFocus(const std::string &element);
446+
void parseModel(parserData *data, const std::string &element);
447447

448448
void tryClose();
449449

Diff for: ‎src/gui/guiScene.cpp

+257
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
/*
2+
Minetest
3+
Copyright (C) 2020 Jean-Patrick Guerrero <jeanpatrick.guerrero@gmail.com>
4+
5+
This program is free software; you can redistribute it and/or modify
6+
it under the terms of the GNU Lesser General Public License as published by
7+
the Free Software Foundation; either version 2.1 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public License along
16+
with this program; if not, write to the Free Software Foundation, Inc.,
17+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*/
19+
20+
#include "guiScene.h"
21+
22+
#include <SViewFrustum.h>
23+
#include <IAnimatedMeshSceneNode.h>
24+
#include <ILightSceneNode.h>
25+
#include "porting.h"
26+
27+
GUIScene::GUIScene(gui::IGUIEnvironment *env, scene::ISceneManager *smgr,
28+
gui::IGUIElement *parent, core::recti rect, s32 id)
29+
: IGUIElement(gui::EGUIET_ELEMENT, env, parent, id, rect)
30+
{
31+
m_driver = env->getVideoDriver();
32+
m_smgr = smgr->createNewSceneManager(false);
33+
34+
m_cam = m_smgr->addCameraSceneNode(0, v3f(0.f, 0.f, -100.f), v3f(0.f));
35+
m_cam->setFOV(30.f * core::DEGTORAD);
36+
37+
scene::ILightSceneNode *light = m_smgr->addLightSceneNode(m_cam);
38+
light->setRadius(1000.f);
39+
40+
m_smgr->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true);
41+
}
42+
43+
GUIScene::~GUIScene()
44+
{
45+
setMesh(nullptr);
46+
47+
m_smgr->drop();
48+
}
49+
50+
scene::IAnimatedMeshSceneNode *GUIScene::setMesh(scene::IAnimatedMesh *mesh)
51+
{
52+
if (m_mesh) {
53+
m_mesh->remove();
54+
m_mesh = nullptr;
55+
}
56+
57+
if (!mesh)
58+
return nullptr;
59+
60+
m_mesh = m_smgr->addAnimatedMeshSceneNode(mesh);
61+
m_mesh->setPosition(-m_mesh->getBoundingBox().getCenter());
62+
m_mesh->animateJoints();
63+
return m_mesh;
64+
}
65+
66+
void GUIScene::setTexture(u32 idx, video::ITexture *texture)
67+
{
68+
video::SMaterial &material = m_mesh->getMaterial(idx);
69+
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
70+
material.MaterialTypeParam = 0.5f;
71+
material.TextureLayer[0].Texture = texture;
72+
material.setFlag(video::EMF_LIGHTING, false);
73+
material.setFlag(video::EMF_FOG_ENABLE, true);
74+
material.setFlag(video::EMF_BILINEAR_FILTER, false);
75+
material.setFlag(video::EMF_BACK_FACE_CULLING, false);
76+
}
77+
78+
void GUIScene::draw()
79+
{
80+
// Control rotation speed based on time
81+
u64 new_time = porting::getTimeMs();
82+
u64 dtime_ms = 0;
83+
if (m_last_time != 0)
84+
dtime_ms = porting::getDeltaMs(m_last_time, new_time);
85+
m_last_time = new_time;
86+
87+
core::rect<s32> oldViewPort = m_driver->getViewPort();
88+
m_driver->setViewPort(getAbsoluteClippingRect());
89+
core::recti borderRect = Environment->getRootGUIElement()->getAbsoluteClippingRect();
90+
91+
if (m_bgcolor != 0) {
92+
Environment->getSkin()->draw3DSunkenPane(
93+
this, m_bgcolor, false, true, borderRect, 0);
94+
}
95+
96+
core::dimension2d<s32> size = getAbsoluteClippingRect().getSize();
97+
m_smgr->getActiveCamera()->setAspectRatio((f32)size.Width / (f32)size.Height);
98+
99+
if (!m_target) {
100+
updateCamera(m_smgr->addEmptySceneNode());
101+
rotateCamera(v3f(0.f));
102+
m_cam->bindTargetAndRotation(true);
103+
}
104+
105+
cameraLoop();
106+
107+
// Continuous rotation
108+
if (m_inf_rot)
109+
rotateCamera(v3f(0.f, -0.03f * (float)dtime_ms, 0.f));
110+
111+
m_smgr->drawAll();
112+
113+
if (m_initial_rotation && m_mesh) {
114+
rotateCamera(v3f(m_custom_rot.X, m_custom_rot.Y, 0.f));
115+
calcOptimalDistance();
116+
117+
m_initial_rotation = false;
118+
}
119+
120+
m_driver->setViewPort(oldViewPort);
121+
}
122+
123+
bool GUIScene::OnEvent(const SEvent &event)
124+
{
125+
if (m_mouse_ctrl && event.EventType == EET_MOUSE_INPUT_EVENT) {
126+
if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) {
127+
m_last_pos = v2f((f32)event.MouseInput.X, (f32)event.MouseInput.Y);
128+
return true;
129+
} else if (event.MouseInput.Event == EMIE_MOUSE_MOVED) {
130+
if (event.MouseInput.isLeftPressed()) {
131+
m_curr_pos = v2f((f32)event.MouseInput.X, (f32)event.MouseInput.Y);
132+
133+
rotateCamera(v3f(
134+
m_last_pos.Y - m_curr_pos.Y,
135+
m_curr_pos.X - m_last_pos.X, 0.f));
136+
137+
m_last_pos = m_curr_pos;
138+
return true;
139+
}
140+
}
141+
}
142+
143+
return gui::IGUIElement::OnEvent(event);
144+
}
145+
146+
void GUIScene::setStyles(const std::array<StyleSpec, StyleSpec::NUM_STATES> &styles)
147+
{
148+
StyleSpec::State state = StyleSpec::STATE_DEFAULT;
149+
StyleSpec style = StyleSpec::getStyleFromStatePropagation(styles, state);
150+
151+
setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
152+
setBackgroundColor(style.getColor(StyleSpec::BGCOLOR, m_bgcolor));
153+
}
154+
155+
/* Camera control functions */
156+
157+
inline void GUIScene::calcOptimalDistance()
158+
{
159+
core::aabbox3df box = m_mesh->getBoundingBox();
160+
f32 width = box.MaxEdge.X - box.MinEdge.X;
161+
f32 height = box.MaxEdge.Y - box.MinEdge.Y;
162+
f32 depth = box.MaxEdge.Z - box.MinEdge.Z;
163+
f32 max_width = width > depth ? width : depth;
164+
165+
const scene::SViewFrustum *f = m_cam->getViewFrustum();
166+
f32 cam_far = m_cam->getFarValue();
167+
f32 far_width = core::line3df(f->getFarLeftUp(), f->getFarRightUp()).getLength();
168+
f32 far_height = core::line3df(f->getFarLeftUp(), f->getFarLeftDown()).getLength();
169+
170+
core::recti rect = getAbsolutePosition();
171+
f32 zoomX = rect.getWidth() / max_width;
172+
f32 zoomY = rect.getHeight() / height;
173+
f32 dist;
174+
175+
if (zoomX < zoomY)
176+
dist = (max_width / (far_width / cam_far)) + (0.5f * max_width);
177+
else
178+
dist = (height / (far_height / cam_far)) + (0.5f * max_width);
179+
180+
m_cam_distance = dist;
181+
m_update_cam = true;
182+
}
183+
184+
void GUIScene::updateCamera(scene::ISceneNode *target)
185+
{
186+
m_target = target;
187+
updateTargetPos();
188+
189+
m_last_target_pos = m_target_pos;
190+
updateCameraPos();
191+
192+
m_update_cam = true;
193+
}
194+
195+
void GUIScene::updateTargetPos()
196+
{
197+
m_last_target_pos = m_target_pos;
198+
m_target->updateAbsolutePosition();
199+
m_target_pos = m_target->getAbsolutePosition();
200+
}
201+
202+
void GUIScene::setCameraRotation(v3f rot)
203+
{
204+
correctBounds(rot);
205+
206+
core::matrix4 mat;
207+
mat.setRotationDegrees(rot);
208+
209+
m_cam_pos = v3f(0.f, 0.f, m_cam_distance);
210+
mat.rotateVect(m_cam_pos);
211+
212+
m_cam_pos += m_target_pos;
213+
m_cam->setPosition(m_cam_pos);
214+
m_update_cam = false;
215+
}
216+
217+
bool GUIScene::correctBounds(v3f &rot)
218+
{
219+
const float ROTATION_MAX_1 = 60.0f;
220+
const float ROTATION_MAX_2 = 300.0f;
221+
222+
// Limit and correct the rotation when needed
223+
if (rot.X < 90.f) {
224+
if (rot.X > ROTATION_MAX_1) {
225+
rot.X = ROTATION_MAX_1;
226+
return true;
227+
}
228+
} else if (rot.X < ROTATION_MAX_2) {
229+
rot.X = ROTATION_MAX_2;
230+
return true;
231+
}
232+
233+
// Not modified
234+
return false;
235+
}
236+
237+
void GUIScene::cameraLoop()
238+
{
239+
updateCameraPos();
240+
updateTargetPos();
241+
242+
if (m_target_pos != m_last_target_pos)
243+
m_update_cam = true;
244+
245+
if (m_update_cam) {
246+
m_cam_pos = m_target_pos + (m_cam_pos - m_target_pos).normalize() * m_cam_distance;
247+
248+
v3f rot = getCameraRotation();
249+
if (correctBounds(rot))
250+
setCameraRotation(rot);
251+
252+
m_cam->setPosition(m_cam_pos);
253+
m_cam->setTarget(m_target_pos);
254+
255+
m_update_cam = false;
256+
}
257+
}

Diff for: ‎src/gui/guiScene.h

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
Minetest
3+
Copyright (C) 2020 Jean-Patrick Guerrero <jeanpatrick.guerrero@gmail.com>
4+
5+
This program is free software; you can redistribute it and/or modify
6+
it under the terms of the GNU Lesser General Public License as published by
7+
the Free Software Foundation; either version 2.1 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public License along
16+
with this program; if not, write to the Free Software Foundation, Inc.,
17+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*/
19+
20+
#pragma once
21+
22+
#include "irrlichttypes_extrabloated.h"
23+
#include "ICameraSceneNode.h"
24+
#include "StyleSpec.h"
25+
26+
using namespace irr;
27+
28+
class GUIScene : public gui::IGUIElement
29+
{
30+
public:
31+
GUIScene(gui::IGUIEnvironment *env, scene::ISceneManager *smgr,
32+
gui::IGUIElement *parent, core::recti rect, s32 id = -1);
33+
34+
~GUIScene();
35+
36+
scene::IAnimatedMeshSceneNode *setMesh(scene::IAnimatedMesh *mesh = nullptr);
37+
void setTexture(u32 idx, video::ITexture *texture);
38+
void setBackgroundColor(const video::SColor &color) noexcept { m_bgcolor = color; };
39+
void enableMouseControl(bool enable) noexcept { m_mouse_ctrl = enable; };
40+
void setRotation(v2f rot) noexcept { m_custom_rot = rot; };
41+
void enableContinuousRotation(bool enable) noexcept { m_inf_rot = enable; };
42+
void setStyles(const std::array<StyleSpec, StyleSpec::NUM_STATES> &styles);
43+
44+
virtual void draw();
45+
virtual bool OnEvent(const SEvent &event);
46+
47+
private:
48+
void calcOptimalDistance();
49+
void updateTargetPos();
50+
void updateCamera(scene::ISceneNode *target);
51+
void setCameraRotation(v3f rot);
52+
/// @return true indicates that the rotation was corrected
53+
bool correctBounds(v3f &rot);
54+
void cameraLoop();
55+
56+
void updateCameraPos() { m_cam_pos = m_cam->getPosition(); };
57+
v3f getCameraRotation() const { return (m_cam_pos - m_target_pos).getHorizontalAngle(); };
58+
void rotateCamera(const v3f &delta) { setCameraRotation(getCameraRotation() + delta); };
59+
60+
scene::ISceneManager *m_smgr;
61+
video::IVideoDriver *m_driver;
62+
scene::ICameraSceneNode *m_cam;
63+
scene::ISceneNode *m_target = nullptr;
64+
scene::IAnimatedMeshSceneNode *m_mesh = nullptr;
65+
66+
f32 m_cam_distance = 50.f;
67+
68+
u64 m_last_time = 0;
69+
70+
v3f m_cam_pos;
71+
v3f m_target_pos;
72+
v3f m_last_target_pos;
73+
// Cursor positions
74+
v2f m_curr_pos;
75+
v2f m_last_pos;
76+
// Initial rotation
77+
v2f m_custom_rot;
78+
79+
bool m_mouse_ctrl = true;
80+
bool m_update_cam = false;
81+
bool m_inf_rot = false;
82+
bool m_initial_rotation = true;
83+
84+
video::SColor m_bgcolor = 0;
85+
};

Diff for: ‎util/ci/clang-format-whitelist.txt

+2
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ src/gui/guiMainMenu.h
183183
src/gui/guiPasswordChange.cpp
184184
src/gui/guiPathSelectMenu.cpp
185185
src/gui/guiPathSelectMenu.h
186+
src/gui/guiScene.cpp
187+
src/gui/guiScene.h
186188
src/gui/guiScrollBar.cpp
187189
src/gui/guiSkin.cpp
188190
src/gui/guiSkin.h

0 commit comments

Comments
 (0)
Please sign in to comment.