Formspec: Allow to specify frame loop for model[] (#10679)
Add the ability to specify an animation frame loop range for the model[] formspec element.
This commit is contained in:
parent
3ed940ff13
commit
d0a38f694d
@ -2277,7 +2277,7 @@ Elements
|
|||||||
* `frame duration`: Milliseconds between each frame. `0` means the frames don't advance.
|
* `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`.
|
* `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>]`
|
### `model[<X>,<Y>;<W>,<H>;<name>;<mesh>;<textures>;<rotation X,Y>;<continuous>;<mouse control>;<frame loop range>]`
|
||||||
|
|
||||||
* Show a mesh model.
|
* Show a mesh model.
|
||||||
* `name`: Element name that can be used for styling
|
* `name`: Element name that can be used for styling
|
||||||
@ -2288,6 +2288,9 @@ Elements
|
|||||||
The axes are euler angles in degrees.
|
The axes are euler angles in degrees.
|
||||||
* `continuous` (Optional): Whether the rotation is continuous. Default `false`.
|
* `continuous` (Optional): Whether the rotation is continuous. Default `false`.
|
||||||
* `mouse control` (Optional): Whether the model can be controlled with the mouse. Default `true`.
|
* `mouse control` (Optional): Whether the model can be controlled with the mouse. Default `true`.
|
||||||
|
* `frame loop range` (Optional): Range of the animation frames.
|
||||||
|
* Defaults to the full range of all available frames.
|
||||||
|
* Syntax: `<begin>,<end>`
|
||||||
|
|
||||||
### `item_image[<X>,<Y>;<W>,<H>;<item name>]`
|
### `item_image[<X>,<Y>;<W>,<H>;<item name>]`
|
||||||
|
|
||||||
@ -2789,6 +2792,7 @@ Some types may inherit styles from parent types.
|
|||||||
* image_button
|
* image_button
|
||||||
* item_image_button
|
* item_image_button
|
||||||
* label
|
* label
|
||||||
|
* model
|
||||||
* pwdfield, inherits from field
|
* pwdfield, inherits from field
|
||||||
* scrollbar
|
* scrollbar
|
||||||
* tabheader
|
* tabheader
|
||||||
|
@ -70,7 +70,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
#define MY_CHECKPOS(a,b) \
|
#define MY_CHECKPOS(a,b) \
|
||||||
if (v_pos.size() != 2) { \
|
if (v_pos.size() != 2) { \
|
||||||
errorstream<< "Invalid pos for element " << a << "specified: \"" \
|
errorstream<< "Invalid pos for element " << a << " specified: \"" \
|
||||||
<< parts[b] << "\"" << std::endl; \
|
<< parts[b] << "\"" << std::endl; \
|
||||||
return; \
|
return; \
|
||||||
}
|
}
|
||||||
@ -78,7 +78,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#define MY_CHECKGEOM(a,b) \
|
#define MY_CHECKGEOM(a,b) \
|
||||||
if (v_geom.size() != 2) { \
|
if (v_geom.size() != 2) { \
|
||||||
errorstream<< "Invalid geometry for element " << a << \
|
errorstream<< "Invalid geometry for element " << a << \
|
||||||
"specified: \"" << parts[b] << "\"" << std::endl; \
|
" specified: \"" << parts[b] << "\"" << std::endl; \
|
||||||
return; \
|
return; \
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -2725,7 +2725,7 @@ void GUIFormSpecMenu::parseModel(parserData *data, const std::string &element)
|
|||||||
{
|
{
|
||||||
std::vector<std::string> parts = split(element, ';');
|
std::vector<std::string> parts = split(element, ';');
|
||||||
|
|
||||||
if (parts.size() < 5 || (parts.size() > 8 &&
|
if (parts.size() < 5 || (parts.size() > 9 &&
|
||||||
m_formspec_version <= FORMSPEC_API_VERSION)) {
|
m_formspec_version <= FORMSPEC_API_VERSION)) {
|
||||||
errorstream << "Invalid model element (" << parts.size() << "): '" << element
|
errorstream << "Invalid model element (" << parts.size() << "): '" << element
|
||||||
<< "'" << std::endl;
|
<< "'" << std::endl;
|
||||||
@ -2733,8 +2733,8 @@ void GUIFormSpecMenu::parseModel(parserData *data, const std::string &element)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Avoid length checks by resizing
|
// Avoid length checks by resizing
|
||||||
if (parts.size() < 8)
|
if (parts.size() < 9)
|
||||||
parts.resize(8);
|
parts.resize(9);
|
||||||
|
|
||||||
std::vector<std::string> v_pos = split(parts[0], ',');
|
std::vector<std::string> v_pos = split(parts[0], ',');
|
||||||
std::vector<std::string> v_geom = split(parts[1], ',');
|
std::vector<std::string> v_geom = split(parts[1], ',');
|
||||||
@ -2744,6 +2744,7 @@ void GUIFormSpecMenu::parseModel(parserData *data, const std::string &element)
|
|||||||
std::vector<std::string> vec_rot = split(parts[5], ',');
|
std::vector<std::string> vec_rot = split(parts[5], ',');
|
||||||
bool inf_rotation = is_yes(parts[6]);
|
bool inf_rotation = is_yes(parts[6]);
|
||||||
bool mousectrl = is_yes(parts[7]) || parts[7].empty(); // default true
|
bool mousectrl = is_yes(parts[7]) || parts[7].empty(); // default true
|
||||||
|
std::vector<std::string> frame_loop = split(parts[8], ',');
|
||||||
|
|
||||||
MY_CHECKPOS("model", 0);
|
MY_CHECKPOS("model", 0);
|
||||||
MY_CHECKGEOM("model", 1);
|
MY_CHECKGEOM("model", 1);
|
||||||
@ -2794,6 +2795,16 @@ void GUIFormSpecMenu::parseModel(parserData *data, const std::string &element)
|
|||||||
e->enableContinuousRotation(inf_rotation);
|
e->enableContinuousRotation(inf_rotation);
|
||||||
e->enableMouseControl(mousectrl);
|
e->enableMouseControl(mousectrl);
|
||||||
|
|
||||||
|
s32 frame_loop_begin = 0;
|
||||||
|
s32 frame_loop_end = 0x7FFFFFFF;
|
||||||
|
|
||||||
|
if (frame_loop.size() == 2) {
|
||||||
|
frame_loop_begin = stoi(frame_loop[0]);
|
||||||
|
frame_loop_end = stoi(frame_loop[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
e->setFrameLoop(frame_loop_begin, frame_loop_end);
|
||||||
|
|
||||||
auto style = getStyleForElement("model", spec.fname);
|
auto style = getStyleForElement("model", spec.fname);
|
||||||
e->setStyles(style);
|
e->setStyles(style);
|
||||||
e->drop();
|
e->drop();
|
||||||
|
@ -152,6 +152,15 @@ void GUIScene::setStyles(const std::array<StyleSpec, StyleSpec::NUM_STATES> &sty
|
|||||||
setBackgroundColor(style.getColor(StyleSpec::BGCOLOR, m_bgcolor));
|
setBackgroundColor(style.getColor(StyleSpec::BGCOLOR, m_bgcolor));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the frame loop range for the mesh
|
||||||
|
*/
|
||||||
|
void GUIScene::setFrameLoop(s32 begin, s32 end)
|
||||||
|
{
|
||||||
|
if (m_mesh->getStartFrame() != begin || m_mesh->getEndFrame() != end)
|
||||||
|
m_mesh->setFrameLoop(begin, end);
|
||||||
|
}
|
||||||
|
|
||||||
/* Camera control functions */
|
/* Camera control functions */
|
||||||
|
|
||||||
inline void GUIScene::calcOptimalDistance()
|
inline void GUIScene::calcOptimalDistance()
|
||||||
|
@ -36,6 +36,7 @@ public:
|
|||||||
scene::IAnimatedMeshSceneNode *setMesh(scene::IAnimatedMesh *mesh = nullptr);
|
scene::IAnimatedMeshSceneNode *setMesh(scene::IAnimatedMesh *mesh = nullptr);
|
||||||
void setTexture(u32 idx, video::ITexture *texture);
|
void setTexture(u32 idx, video::ITexture *texture);
|
||||||
void setBackgroundColor(const video::SColor &color) noexcept { m_bgcolor = color; };
|
void setBackgroundColor(const video::SColor &color) noexcept { m_bgcolor = color; };
|
||||||
|
void setFrameLoop(s32 begin, s32 end);
|
||||||
void enableMouseControl(bool enable) noexcept { m_mouse_ctrl = enable; };
|
void enableMouseControl(bool enable) noexcept { m_mouse_ctrl = enable; };
|
||||||
void setRotation(v2f rot) noexcept { m_custom_rot = rot; };
|
void setRotation(v2f rot) noexcept { m_custom_rot = rot; };
|
||||||
void enableContinuousRotation(bool enable) noexcept { m_inf_rot = enable; };
|
void enableContinuousRotation(bool enable) noexcept { m_inf_rot = enable; };
|
||||||
|
Loading…
x
Reference in New Issue
Block a user