CHANGED: #1471 CInterfaceTrack and CInterfaceAnim are now part of the NELGUI library and are under the NLGUI namespace.

--HG--
branch : gui-refactoring
This commit is contained in:
dfighter1985 2012-07-01 04:13:24 +02:00
parent cb4bc53ecd
commit 31482e873b
8 changed files with 786 additions and 777 deletions

View file

@ -0,0 +1,135 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef RZ_INTERFACE_ANIM_H
#define RZ_INTERFACE_ANIM_H
#include "nel/gui/interface_property.h"
#include "nel/gui/interface_group.h"
#include "nel/gui/interface_link.h"
#include "nel/3d/animation_time.h"
#include "nel/3d/u_track.h"
namespace NLGUI
{
/**
* class managing an animation track
* \author Matthieu 'TrapII' Besson
* \author Nevrax France
* \date 2003
*/
class CInterfaceTrack
{
public:
CInterfaceTrack();
~CInterfaceTrack();
virtual bool parse (xmlNodePtr cur, CInterfaceGroup *parentGroup);
void update (double currentTime);
bool isDynamic () { return _Dynamic; }
void eval(); // Evaluate dynamic keys
private:
enum ETrackType
{
Track_Linear,
Track_TCB,
Track_Bezier
};
struct SDynKey
{
std::string Time;
std::string Value;
std::string InTan;
std::string OutTan;
std::string Step;
std::string Tension;
std::string Continuity;
std::string Bias;
std::string EaseTo;
std::string EaseFrom;
};
bool _Dynamic;
std::vector<SDynKey> _DynKeys;
ETrackType _Type;
NL3D::UTrackKeyframer *_TrackKeyFramer;
std::vector<CInterfaceLink::CTargetInfo> _Targets;
};
/**
* class managing an animation of the interface
* \author Matthieu 'TrapII' Besson
* \author Nevrax France
* \date 2003
*/
class CInterfaceAnim
{
public:
CInterfaceAnim();
~CInterfaceAnim();
virtual bool parse (xmlNodePtr cur, CInterfaceGroup *parentGroup);
void update();
void start();
void stop();
bool isFinished() { return _Finished; }
bool isDisableButtons() { return _DisableButtons; }
protected:
CInterfaceGroup *_Parent;
// Parsed properties
double _Duration;
bool _DisableButtons;
std::string _AHOnFinish;
std::string _AHOnFinishParams;
std::string _Id;
std::vector<CInterfaceTrack*> _Tracks;
// Current anim
double _CurrentTime;
bool _Finished;
bool _AnimHasToBeStopped;
};
}
#endif // NL_INTERFACE_ANIM_H
/* End of interface_anim.h */

View file

@ -0,0 +1,647 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "nel/gui/interface_anim.h"
#include "nel/gui/widget_manager.h"
#include "nel/gui/interface_expr.h"
#include "nel/misc/xml_auto_ptr.h"
#include "nel/gui/action_handler.h"
// ----------------------------------------------------------------------------
using namespace std;
using namespace NL3D;
using namespace NLMISC;
namespace NLGUI
{
// ----------------------------------------------------------------------------
// CInterfaceTrack
// ----------------------------------------------------------------------------
CInterfaceTrack::CInterfaceTrack()
{
_Type = Track_Linear;
_TrackKeyFramer = NULL;
_Dynamic = false;
}
// ----------------------------------------------------------------------------
CInterfaceTrack::~CInterfaceTrack()
{
delete _TrackKeyFramer;
}
// ----------------------------------------------------------------------------
bool CInterfaceTrack::parse (xmlNodePtr cur, CInterfaceGroup *parentGroup)
{
CXMLAutoPtr ptr;
ptr = xmlGetProp (cur, (xmlChar*)"dynamic");
if (ptr) _Dynamic = CInterfaceElement::convertBool (ptr);
ptr = xmlGetProp (cur, (xmlChar*)"type");
string sTmp = ptr;
sTmp = strlwr(sTmp);
if (sTmp == "linear")
_Type = Track_Linear;
else if (sTmp == "bezier")
_Type = Track_Bezier;
else if (sTmp == "tcb")
_Type = Track_TCB;
else
nlwarning ("track unknown type : %s, setting linear by default", (const char*)ptr);
ptr = xmlGetProp (cur, (xmlChar*)"target");
if (!ptr)
{
nlwarning ("no target for track");
return false;
}
//
if (!CInterfaceLink::splitLinkTargets (ptr, parentGroup, _Targets))
{
nlwarning ("no target for track");
return false;
}
// Initialize the track
switch(_Type)
{
case Track_Linear: _TrackKeyFramer = UTrackKeyframer::createLinearFloatTrack(); break;
case Track_TCB: _TrackKeyFramer = UTrackKeyframer::createTCBFloatTrack(); break;
case Track_Bezier: _TrackKeyFramer = UTrackKeyframer::createBezierFloatTrack(); break;
default: nlstop; break;
}
cur = cur->children;
bool ok = true;
if (_Dynamic)
{
while (cur)
{
// Check that this is a key node
if ( stricmp((char*)cur->name,"key") != 0 )
{
cur = cur->next;
continue;
}
// Read time and value the 2 main key attributes
CXMLAutoPtr time, value;
time = xmlGetProp (cur, (xmlChar*)"time");
value = xmlGetProp (cur, (xmlChar*)"value");
if (!time || !value)
{
nlwarning("track key with no time or no value");
ok = false;
cur = cur->next;
continue;
}
SDynKey k;
k.Value = (const char*)value;
k.Time = (const char*)time;
if (isdigit(k.Time[0]) || (k.Time[0] == '-'))
{
double dTime;
fromString(k.Time, dTime);
k.Time = toString(dTime * CWidgetManager::getInstance()->getSystemOption(CWidgetManager::OptionMulCoefAnim).getValFloat());
}
// Depending on the type of the track read extra values
switch(_Type)
{
case Track_Linear:
break;
case Track_Bezier:
{
CXMLAutoPtr inTan, outTan, step;
inTan = xmlGetProp (cur, (xmlChar*)"intan");
outTan = xmlGetProp (cur, (xmlChar*)"outtan");
step = xmlGetProp (cur, (xmlChar*)"step");
if (inTan) k.InTan = (const char*)inTan;
if (outTan) k.OutTan = (const char*)outTan;
if (step) k.Step = (const char*)step;
}
break;
case Track_TCB:
{
CXMLAutoPtr tension, continuity, bias, easeto, easefrom;
tension = xmlGetProp (cur, (xmlChar*)"tension");
continuity = xmlGetProp (cur, (xmlChar*)"continuity");
bias = xmlGetProp (cur, (xmlChar*)"bias");
easeto = xmlGetProp (cur, (xmlChar*)"easeto");
easefrom = xmlGetProp (cur, (xmlChar*)"easefrom");
if (tension) k.Tension = (const char*)tension;
if (continuity) k.Continuity = (const char*)continuity;
if (bias) k.Bias = (const char*)bias;
if (easeto) k.EaseTo = (const char*)easeto;
if (easefrom) k.EaseFrom = (const char*)easefrom;
}
break;
default: nlstop; break;
}
_DynKeys.push_back(k);
cur = cur->next;
}
}
else // Static parsing
{
while (cur)
{
// Check that this is a key node
if ( stricmp((char*)cur->name,"key") != 0 )
{
cur = cur->next;
continue;
}
// Read time and value the 2 main key attributes
CXMLAutoPtr time, value;
time = xmlGetProp (cur, (xmlChar*)"time");
value = xmlGetProp (cur, (xmlChar*)"value");
if (!time || !value)
{
nlwarning("track key with no time or no value");
ok = false;
cur = cur->next;
continue;
}
float fAnimTime;
fromString((const char*)time, fAnimTime);
TAnimationTime animTime = fAnimTime * CWidgetManager::getInstance()->getSystemOption(CWidgetManager::OptionMulCoefAnim).getValFloat();
double animValue;
fromString(value, animValue);
// Depending on the type of the track add the key
switch(_Type)
{
case Track_Linear:
{
UTrackKeyframer::UKeyLinearFloat k;
k.Time = animTime;
k.Value = (float)animValue;
_TrackKeyFramer->addLinearFloatKey (k);
}
break;
case Track_Bezier:
{
UTrackKeyframer::UKeyBezierFloat k;
k.Time = animTime;
k.Value = (float)animValue;
// Read extra values
CXMLAutoPtr inTan, outTan, step;
inTan = xmlGetProp (cur, (xmlChar*)"intan");
outTan = xmlGetProp (cur, (xmlChar*)"outtan");
step = xmlGetProp (cur, (xmlChar*)"step");
k.TanIn = 0.0f;
k.TanOut = 0.0f;
k.Step = false;
if (inTan) fromString((const char*)inTan, k.TanIn);
if (outTan) fromString((const char*)outTan, k.TanOut);
if (step) k.Step = CInterfaceElement::convertBool(step);
_TrackKeyFramer->addBezierFloatKey (k);
}
break;
case Track_TCB:
{
UTrackKeyframer::UKeyTCBFloat k;
k.Time = animTime;
k.Value = (float)animValue;
// Read extra values
CXMLAutoPtr tension, continuity, bias, easeto, easefrom;
tension = xmlGetProp (cur, (xmlChar*)"tension");
continuity = xmlGetProp (cur, (xmlChar*)"continuity");
bias = xmlGetProp (cur, (xmlChar*)"bias");
easeto = xmlGetProp (cur, (xmlChar*)"easeto");
easefrom = xmlGetProp (cur, (xmlChar*)"easefrom");
k.Tension = 0.0f;
k.Continuity = 0.0f;
k.Bias = 0.0f;
k.EaseTo = 0.0f;
k.EaseFrom = 0.0f;
if (tension) fromString((const char*)tension, k.Tension);
if (continuity) fromString((const char*)continuity, k.Continuity);
if (bias) fromString((const char*)bias, k.Bias);
if (easeto) fromString((const char*)easeto, k.EaseTo);
if (easefrom) fromString((const char*)easefrom, k.EaseFrom);
_TrackKeyFramer->addTCBFloatKey (k);
}
break;
default: nlstop; break;
}
cur = cur->next;
}
}
return true;
}
// ----------------------------------------------------------------------------
void CInterfaceTrack::update (double currentTime)
{
float currentValue;
UTrack *pTrack = dynamic_cast<UTrack*>(_TrackKeyFramer);
if (pTrack == NULL) return;
pTrack->interpolate((TAnimationTime)currentTime, currentValue);
// Update the targets
CInterfaceExprValue expr;
expr.setDouble(currentValue);
for (uint i = 0; i < _Targets.size(); ++i)
_Targets[i].affect(expr);
}
// ----------------------------------------------------------------------------
void CInterfaceTrack::eval()
{
if (!_Dynamic) return;
if (_TrackKeyFramer != NULL)
delete _TrackKeyFramer;
switch(_Type)
{
case Track_Linear:
{
_TrackKeyFramer = UTrackKeyframer::createLinearFloatTrack();
for (uint i = 0; i < _DynKeys.size(); ++i)
{
SDynKey &rKey = _DynKeys[i];
UTrackKeyframer::UKeyLinearFloat k;
CInterfaceExprValue res;
if (!rKey.Time.empty() && CInterfaceExpr::eval(rKey.Time, res))
{
if (!res.toDouble())
nlwarning ("cannot convert Time to double");
else
k.Time = (TAnimationTime)res.getDouble();
}
else
{
k.Time = 0;
}
if (!rKey.Value.empty() && CInterfaceExpr::eval(rKey.Value, res))
{
if (!res.toDouble())
nlwarning ("cannot convert Value to double");
else
k.Value = (float)res.getDouble();
}
else
{
k.Value = 0;
}
_TrackKeyFramer->addLinearFloatKey (k);
}
}
break;
case Track_TCB:
{
_TrackKeyFramer = UTrackKeyframer::createTCBFloatTrack();
for (uint i = 0; i < _DynKeys.size(); ++i)
{
SDynKey &rKey = _DynKeys[i];
UTrackKeyframer::UKeyTCBFloat k;
CInterfaceExprValue res;
if (!rKey.Time.empty() && CInterfaceExpr::eval(rKey.Time, res))
{
if (!res.toDouble())
nlwarning ("cannot convert Time to double");
else
k.Time = (TAnimationTime)res.getDouble();
}
else
{
k.Time = 0;
}
if (!rKey.Value.empty() && CInterfaceExpr::eval(rKey.Value, res))
{
if (!res.toDouble())
nlwarning ("cannot convert Value to double");
else
k.Value = (float)res.getDouble();
}
else
{
k.Value = 0;
}
if (!rKey.Tension.empty() && CInterfaceExpr::eval(rKey.Tension, res))
{
if (!res.toDouble())
nlwarning ("cannot convert Tension to double");
else
k.Tension = (float)res.getDouble();
}
else
{
k.Tension = 0;
}
if (!rKey.Continuity.empty() && CInterfaceExpr::eval(rKey.Continuity, res))
{
if (!res.toDouble())
nlwarning ("cannot convert Continuity to double");
else
k.Continuity = (float)res.getDouble();
}
else
{
k.Continuity = 0;
}
if (!rKey.Bias.empty() && CInterfaceExpr::eval(rKey.Bias, res))
{
if (!res.toDouble())
nlwarning ("cannot convert Bias to double");
else
k.Bias = (float)res.getDouble();
}
else
{
k.Bias = 0;
}
if (!rKey.EaseTo.empty() && CInterfaceExpr::eval(rKey.EaseTo, res))
{
if (!res.toDouble())
nlwarning ("cannot convert EaseTo to double");
else
k.EaseTo = (float)res.getDouble();
}
else
{
k.EaseTo = 0;
}
if (!rKey.EaseFrom.empty() && CInterfaceExpr::eval(rKey.EaseFrom, res))
{
if (!res.toDouble())
nlwarning ("cannot convert EaseFrom to double");
else
k.EaseFrom = (float)res.getDouble();
}
else
{
k.EaseFrom = 0;
}
_TrackKeyFramer->addTCBFloatKey (k);
}
}
break;
case Track_Bezier:
{
_TrackKeyFramer = UTrackKeyframer::createBezierFloatTrack(); break;
for (uint i = 0; i < _DynKeys.size(); ++i)
{
SDynKey &rKey = _DynKeys[i];
UTrackKeyframer::UKeyBezierFloat k;
CInterfaceExprValue res;
if (!rKey.Time.empty() && CInterfaceExpr::eval(rKey.Time, res))
{
if (!res.toDouble())
nlwarning ("cannot convert Time to double");
else
k.Time = (TAnimationTime)res.getDouble();
}
else
{
k.Time = 0;
}
if (!rKey.Value.empty() && CInterfaceExpr::eval(rKey.Value, res))
{
if (!res.toDouble())
nlwarning ("cannot convert Value to double");
else
k.Value = (float)res.getDouble();
}
else
{
k.Value = 0;
}
if (!rKey.InTan.empty() && CInterfaceExpr::eval(rKey.InTan, res))
{
if (!res.toDouble())
nlwarning ("cannot convert TanIn to double");
else
k.TanIn = (float)res.getDouble();
}
else
{
k.TanIn = 0;
}
if (!rKey.OutTan.empty() && CInterfaceExpr::eval(rKey.OutTan, res))
{
if (!res.toDouble())
nlwarning ("cannot convert TanOut to double");
else
k.TanOut = (float)res.getDouble();
}
else
{
k.TanOut = 0;
}
if (!rKey.Step.empty() && CInterfaceExpr::eval(rKey.Step, res))
{
if (!res.toBool())
nlwarning ("cannot convert Step to bool");
else
k.Step = res.getBool();
}
else
{
k.Step = false;
}
_TrackKeyFramer->addBezierFloatKey (k);
}
}
default: nlstop; break;
}
}
// ----------------------------------------------------------------------------
// CInterfaceAnim
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
CInterfaceAnim::CInterfaceAnim()
{
_CurrentTime = 0;
_Finished = true;
_Duration = 0;
_DisableButtons = true;
_AnimHasToBeStopped = false;
_Parent = NULL;
}
// ----------------------------------------------------------------------------
CInterfaceAnim::~CInterfaceAnim()
{
for (uint i = 0; i < _Tracks.size(); ++i)
delete _Tracks[i];
}
// ----------------------------------------------------------------------------
bool CInterfaceAnim::parse (xmlNodePtr cur, CInterfaceGroup *parentGroup)
{
CXMLAutoPtr ptr;
ptr = xmlGetProp (cur, (xmlChar*)"id");
_Id = (const char*)ptr;
ptr = xmlGetProp (cur, (xmlChar*)"duration");
if (!ptr)
{
nlwarning("anim with no duration");
return false;
}
fromString((const char*)ptr, _Duration);
if (_Duration == 0)
_Duration = 1.0;
_Duration *= CWidgetManager::getInstance()->getSystemOption(CWidgetManager::OptionMulCoefAnim).getValFloat();
ptr = xmlGetProp (cur, (xmlChar*)"disable_buttons");
if (ptr)
_DisableButtons = CInterfaceElement::convertBool(ptr);
ptr = (char*) xmlGetProp( cur, (xmlChar*)"on_finish" );
if (ptr) _AHOnFinish = (const char *) ptr;
ptr = (char*) xmlGetProp( cur, (xmlChar*)"on_finish_params" );
if (ptr) _AHOnFinishParams = (const char *) ptr;
cur = cur->children;
// bool ok = true;
while (cur)
{
// Check that this is a key node
if ( stricmp((char*)cur->name,"track") != 0 )
{
cur = cur->next;
continue;
}
CInterfaceTrack *pTrack = new CInterfaceTrack;
if (!pTrack->parse(cur,parentGroup))
{
delete pTrack;
nlwarning("track not added to anim");
}
else
{
_Tracks.push_back(pTrack);
}
cur = cur->next;
}
_Parent = parentGroup;
return true;
}
// ----------------------------------------------------------------------------
void CInterfaceAnim::update()
{
if ((_Duration == 0) || (_Finished))
return;
const CWidgetManager::SInterfaceTimes &times = CWidgetManager::getInstance()->getInterfaceTimes();
// Delta time limiter
if ( ( times.frameDiffMs / 1000.0f ) > 0.1)
_CurrentTime += 0.1;
else
_CurrentTime += ( times.frameDiffMs / 1000.0f );
// Stop the anim if we have to
if (_AnimHasToBeStopped)
{
stop();
return;
}
// Do this here to let it play the last frame of the animation
if (_CurrentTime >= _Duration)
{
_CurrentTime = _Duration;
_AnimHasToBeStopped = true;
}
// Update tracks
for (uint i = 0; i < _Tracks.size(); ++i)
{
CInterfaceTrack *pTrack = _Tracks[i];
pTrack->update (_CurrentTime);
}
}
// ----------------------------------------------------------------------------
void CInterfaceAnim::start()
{
_CurrentTime = 0.0f;
_Finished = false;
_AnimHasToBeStopped = false;
// Look if there are some dynamic tracks
for (uint i = 0; i < _Tracks.size(); ++i)
if (_Tracks[i]->isDynamic())
_Tracks[i]->eval();
// Play the first frame
update();
}
// ----------------------------------------------------------------------------
void CInterfaceAnim::stop()
{
_Finished = true;
if (!_AHOnFinish.empty())
CAHManager::getInstance()->runActionHandler(_AHOnFinish, _Parent, _AHOnFinishParams);
}
}

View file

@ -1,643 +0,0 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "interface_anim.h"
#include "nel/gui/widget_manager.h"
#include "nel/gui/interface_expr.h"
#include "nel/misc/xml_auto_ptr.h"
#include "nel/gui/action_handler.h"
// ----------------------------------------------------------------------------
using namespace std;
using namespace NL3D;
using namespace NLMISC;
// ----------------------------------------------------------------------------
// CInterfaceTrack
// ----------------------------------------------------------------------------
CInterfaceTrack::CInterfaceTrack()
{
_Type = Track_Linear;
_TrackKeyFramer = NULL;
_Dynamic = false;
}
// ----------------------------------------------------------------------------
CInterfaceTrack::~CInterfaceTrack()
{
delete _TrackKeyFramer;
}
// ----------------------------------------------------------------------------
bool CInterfaceTrack::parse (xmlNodePtr cur, CInterfaceGroup *parentGroup)
{
CXMLAutoPtr ptr;
ptr = xmlGetProp (cur, (xmlChar*)"dynamic");
if (ptr) _Dynamic = CInterfaceElement::convertBool (ptr);
ptr = xmlGetProp (cur, (xmlChar*)"type");
string sTmp = ptr;
sTmp = strlwr(sTmp);
if (sTmp == "linear")
_Type = Track_Linear;
else if (sTmp == "bezier")
_Type = Track_Bezier;
else if (sTmp == "tcb")
_Type = Track_TCB;
else
nlwarning ("track unknown type : %s, setting linear by default", (const char*)ptr);
ptr = xmlGetProp (cur, (xmlChar*)"target");
if (!ptr)
{
nlwarning ("no target for track");
return false;
}
//
if (!CInterfaceLink::splitLinkTargets (ptr, parentGroup, _Targets))
{
nlwarning ("no target for track");
return false;
}
// Initialize the track
switch(_Type)
{
case Track_Linear: _TrackKeyFramer = UTrackKeyframer::createLinearFloatTrack(); break;
case Track_TCB: _TrackKeyFramer = UTrackKeyframer::createTCBFloatTrack(); break;
case Track_Bezier: _TrackKeyFramer = UTrackKeyframer::createBezierFloatTrack(); break;
default: nlstop; break;
}
cur = cur->children;
bool ok = true;
if (_Dynamic)
{
while (cur)
{
// Check that this is a key node
if ( stricmp((char*)cur->name,"key") != 0 )
{
cur = cur->next;
continue;
}
// Read time and value the 2 main key attributes
CXMLAutoPtr time, value;
time = xmlGetProp (cur, (xmlChar*)"time");
value = xmlGetProp (cur, (xmlChar*)"value");
if (!time || !value)
{
nlwarning("track key with no time or no value");
ok = false;
cur = cur->next;
continue;
}
SDynKey k;
k.Value = (const char*)value;
k.Time = (const char*)time;
if (isdigit(k.Time[0]) || (k.Time[0] == '-'))
{
double dTime;
fromString(k.Time, dTime);
k.Time = toString(dTime * CWidgetManager::getInstance()->getSystemOption(CWidgetManager::OptionMulCoefAnim).getValFloat());
}
// Depending on the type of the track read extra values
switch(_Type)
{
case Track_Linear:
break;
case Track_Bezier:
{
CXMLAutoPtr inTan, outTan, step;
inTan = xmlGetProp (cur, (xmlChar*)"intan");
outTan = xmlGetProp (cur, (xmlChar*)"outtan");
step = xmlGetProp (cur, (xmlChar*)"step");
if (inTan) k.InTan = (const char*)inTan;
if (outTan) k.OutTan = (const char*)outTan;
if (step) k.Step = (const char*)step;
}
break;
case Track_TCB:
{
CXMLAutoPtr tension, continuity, bias, easeto, easefrom;
tension = xmlGetProp (cur, (xmlChar*)"tension");
continuity = xmlGetProp (cur, (xmlChar*)"continuity");
bias = xmlGetProp (cur, (xmlChar*)"bias");
easeto = xmlGetProp (cur, (xmlChar*)"easeto");
easefrom = xmlGetProp (cur, (xmlChar*)"easefrom");
if (tension) k.Tension = (const char*)tension;
if (continuity) k.Continuity = (const char*)continuity;
if (bias) k.Bias = (const char*)bias;
if (easeto) k.EaseTo = (const char*)easeto;
if (easefrom) k.EaseFrom = (const char*)easefrom;
}
break;
default: nlstop; break;
}
_DynKeys.push_back(k);
cur = cur->next;
}
}
else // Static parsing
{
while (cur)
{
// Check that this is a key node
if ( stricmp((char*)cur->name,"key") != 0 )
{
cur = cur->next;
continue;
}
// Read time and value the 2 main key attributes
CXMLAutoPtr time, value;
time = xmlGetProp (cur, (xmlChar*)"time");
value = xmlGetProp (cur, (xmlChar*)"value");
if (!time || !value)
{
nlwarning("track key with no time or no value");
ok = false;
cur = cur->next;
continue;
}
float fAnimTime;
fromString((const char*)time, fAnimTime);
TAnimationTime animTime = fAnimTime * CWidgetManager::getInstance()->getSystemOption(CWidgetManager::OptionMulCoefAnim).getValFloat();
double animValue;
fromString(value, animValue);
// Depending on the type of the track add the key
switch(_Type)
{
case Track_Linear:
{
UTrackKeyframer::UKeyLinearFloat k;
k.Time = animTime;
k.Value = (float)animValue;
_TrackKeyFramer->addLinearFloatKey (k);
}
break;
case Track_Bezier:
{
UTrackKeyframer::UKeyBezierFloat k;
k.Time = animTime;
k.Value = (float)animValue;
// Read extra values
CXMLAutoPtr inTan, outTan, step;
inTan = xmlGetProp (cur, (xmlChar*)"intan");
outTan = xmlGetProp (cur, (xmlChar*)"outtan");
step = xmlGetProp (cur, (xmlChar*)"step");
k.TanIn = 0.0f;
k.TanOut = 0.0f;
k.Step = false;
if (inTan) fromString((const char*)inTan, k.TanIn);
if (outTan) fromString((const char*)outTan, k.TanOut);
if (step) k.Step = CInterfaceElement::convertBool(step);
_TrackKeyFramer->addBezierFloatKey (k);
}
break;
case Track_TCB:
{
UTrackKeyframer::UKeyTCBFloat k;
k.Time = animTime;
k.Value = (float)animValue;
// Read extra values
CXMLAutoPtr tension, continuity, bias, easeto, easefrom;
tension = xmlGetProp (cur, (xmlChar*)"tension");
continuity = xmlGetProp (cur, (xmlChar*)"continuity");
bias = xmlGetProp (cur, (xmlChar*)"bias");
easeto = xmlGetProp (cur, (xmlChar*)"easeto");
easefrom = xmlGetProp (cur, (xmlChar*)"easefrom");
k.Tension = 0.0f;
k.Continuity = 0.0f;
k.Bias = 0.0f;
k.EaseTo = 0.0f;
k.EaseFrom = 0.0f;
if (tension) fromString((const char*)tension, k.Tension);
if (continuity) fromString((const char*)continuity, k.Continuity);
if (bias) fromString((const char*)bias, k.Bias);
if (easeto) fromString((const char*)easeto, k.EaseTo);
if (easefrom) fromString((const char*)easefrom, k.EaseFrom);
_TrackKeyFramer->addTCBFloatKey (k);
}
break;
default: nlstop; break;
}
cur = cur->next;
}
}
return true;
}
// ----------------------------------------------------------------------------
void CInterfaceTrack::update (double currentTime)
{
float currentValue;
UTrack *pTrack = dynamic_cast<UTrack*>(_TrackKeyFramer);
if (pTrack == NULL) return;
pTrack->interpolate((TAnimationTime)currentTime, currentValue);
// Update the targets
CInterfaceExprValue expr;
expr.setDouble(currentValue);
for (uint i = 0; i < _Targets.size(); ++i)
_Targets[i].affect(expr);
}
// ----------------------------------------------------------------------------
void CInterfaceTrack::eval()
{
if (!_Dynamic) return;
if (_TrackKeyFramer != NULL)
delete _TrackKeyFramer;
switch(_Type)
{
case Track_Linear:
{
_TrackKeyFramer = UTrackKeyframer::createLinearFloatTrack();
for (uint i = 0; i < _DynKeys.size(); ++i)
{
SDynKey &rKey = _DynKeys[i];
UTrackKeyframer::UKeyLinearFloat k;
CInterfaceExprValue res;
if (!rKey.Time.empty() && CInterfaceExpr::eval(rKey.Time, res))
{
if (!res.toDouble())
nlwarning ("cannot convert Time to double");
else
k.Time = (TAnimationTime)res.getDouble();
}
else
{
k.Time = 0;
}
if (!rKey.Value.empty() && CInterfaceExpr::eval(rKey.Value, res))
{
if (!res.toDouble())
nlwarning ("cannot convert Value to double");
else
k.Value = (float)res.getDouble();
}
else
{
k.Value = 0;
}
_TrackKeyFramer->addLinearFloatKey (k);
}
}
break;
case Track_TCB:
{
_TrackKeyFramer = UTrackKeyframer::createTCBFloatTrack();
for (uint i = 0; i < _DynKeys.size(); ++i)
{
SDynKey &rKey = _DynKeys[i];
UTrackKeyframer::UKeyTCBFloat k;
CInterfaceExprValue res;
if (!rKey.Time.empty() && CInterfaceExpr::eval(rKey.Time, res))
{
if (!res.toDouble())
nlwarning ("cannot convert Time to double");
else
k.Time = (TAnimationTime)res.getDouble();
}
else
{
k.Time = 0;
}
if (!rKey.Value.empty() && CInterfaceExpr::eval(rKey.Value, res))
{
if (!res.toDouble())
nlwarning ("cannot convert Value to double");
else
k.Value = (float)res.getDouble();
}
else
{
k.Value = 0;
}
if (!rKey.Tension.empty() && CInterfaceExpr::eval(rKey.Tension, res))
{
if (!res.toDouble())
nlwarning ("cannot convert Tension to double");
else
k.Tension = (float)res.getDouble();
}
else
{
k.Tension = 0;
}
if (!rKey.Continuity.empty() && CInterfaceExpr::eval(rKey.Continuity, res))
{
if (!res.toDouble())
nlwarning ("cannot convert Continuity to double");
else
k.Continuity = (float)res.getDouble();
}
else
{
k.Continuity = 0;
}
if (!rKey.Bias.empty() && CInterfaceExpr::eval(rKey.Bias, res))
{
if (!res.toDouble())
nlwarning ("cannot convert Bias to double");
else
k.Bias = (float)res.getDouble();
}
else
{
k.Bias = 0;
}
if (!rKey.EaseTo.empty() && CInterfaceExpr::eval(rKey.EaseTo, res))
{
if (!res.toDouble())
nlwarning ("cannot convert EaseTo to double");
else
k.EaseTo = (float)res.getDouble();
}
else
{
k.EaseTo = 0;
}
if (!rKey.EaseFrom.empty() && CInterfaceExpr::eval(rKey.EaseFrom, res))
{
if (!res.toDouble())
nlwarning ("cannot convert EaseFrom to double");
else
k.EaseFrom = (float)res.getDouble();
}
else
{
k.EaseFrom = 0;
}
_TrackKeyFramer->addTCBFloatKey (k);
}
}
break;
case Track_Bezier:
{
_TrackKeyFramer = UTrackKeyframer::createBezierFloatTrack(); break;
for (uint i = 0; i < _DynKeys.size(); ++i)
{
SDynKey &rKey = _DynKeys[i];
UTrackKeyframer::UKeyBezierFloat k;
CInterfaceExprValue res;
if (!rKey.Time.empty() && CInterfaceExpr::eval(rKey.Time, res))
{
if (!res.toDouble())
nlwarning ("cannot convert Time to double");
else
k.Time = (TAnimationTime)res.getDouble();
}
else
{
k.Time = 0;
}
if (!rKey.Value.empty() && CInterfaceExpr::eval(rKey.Value, res))
{
if (!res.toDouble())
nlwarning ("cannot convert Value to double");
else
k.Value = (float)res.getDouble();
}
else
{
k.Value = 0;
}
if (!rKey.InTan.empty() && CInterfaceExpr::eval(rKey.InTan, res))
{
if (!res.toDouble())
nlwarning ("cannot convert TanIn to double");
else
k.TanIn = (float)res.getDouble();
}
else
{
k.TanIn = 0;
}
if (!rKey.OutTan.empty() && CInterfaceExpr::eval(rKey.OutTan, res))
{
if (!res.toDouble())
nlwarning ("cannot convert TanOut to double");
else
k.TanOut = (float)res.getDouble();
}
else
{
k.TanOut = 0;
}
if (!rKey.Step.empty() && CInterfaceExpr::eval(rKey.Step, res))
{
if (!res.toBool())
nlwarning ("cannot convert Step to bool");
else
k.Step = res.getBool();
}
else
{
k.Step = false;
}
_TrackKeyFramer->addBezierFloatKey (k);
}
}
default: nlstop; break;
}
}
// ----------------------------------------------------------------------------
// CInterfaceAnim
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
CInterfaceAnim::CInterfaceAnim()
{
_CurrentTime = 0;
_Finished = true;
_Duration = 0;
_DisableButtons = true;
_AnimHasToBeStopped = false;
_Parent = NULL;
}
// ----------------------------------------------------------------------------
CInterfaceAnim::~CInterfaceAnim()
{
for (uint i = 0; i < _Tracks.size(); ++i)
delete _Tracks[i];
}
// ----------------------------------------------------------------------------
bool CInterfaceAnim::parse (xmlNodePtr cur, CInterfaceGroup *parentGroup)
{
CXMLAutoPtr ptr;
ptr = xmlGetProp (cur, (xmlChar*)"id");
_Id = (const char*)ptr;
ptr = xmlGetProp (cur, (xmlChar*)"duration");
if (!ptr)
{
nlwarning("anim with no duration");
return false;
}
fromString((const char*)ptr, _Duration);
if (_Duration == 0)
_Duration = 1.0;
_Duration *= CWidgetManager::getInstance()->getSystemOption(CWidgetManager::OptionMulCoefAnim).getValFloat();
ptr = xmlGetProp (cur, (xmlChar*)"disable_buttons");
if (ptr)
_DisableButtons = CInterfaceElement::convertBool(ptr);
ptr = (char*) xmlGetProp( cur, (xmlChar*)"on_finish" );
if (ptr) _AHOnFinish = (const char *) ptr;
ptr = (char*) xmlGetProp( cur, (xmlChar*)"on_finish_params" );
if (ptr) _AHOnFinishParams = (const char *) ptr;
cur = cur->children;
// bool ok = true;
while (cur)
{
// Check that this is a key node
if ( stricmp((char*)cur->name,"track") != 0 )
{
cur = cur->next;
continue;
}
CInterfaceTrack *pTrack = new CInterfaceTrack;
if (!pTrack->parse(cur,parentGroup))
{
delete pTrack;
nlwarning("track not added to anim");
}
else
{
_Tracks.push_back(pTrack);
}
cur = cur->next;
}
_Parent = parentGroup;
return true;
}
// ----------------------------------------------------------------------------
void CInterfaceAnim::update()
{
if ((_Duration == 0) || (_Finished))
return;
const CWidgetManager::SInterfaceTimes &times = CWidgetManager::getInstance()->getInterfaceTimes();
// Delta time limiter
if ( ( times.frameDiffMs / 1000.0f ) > 0.1)
_CurrentTime += 0.1;
else
_CurrentTime += ( times.frameDiffMs / 1000.0f );
// Stop the anim if we have to
if (_AnimHasToBeStopped)
{
stop();
return;
}
// Do this here to let it play the last frame of the animation
if (_CurrentTime >= _Duration)
{
_CurrentTime = _Duration;
_AnimHasToBeStopped = true;
}
// Update tracks
for (uint i = 0; i < _Tracks.size(); ++i)
{
CInterfaceTrack *pTrack = _Tracks[i];
pTrack->update (_CurrentTime);
}
}
// ----------------------------------------------------------------------------
void CInterfaceAnim::start()
{
_CurrentTime = 0.0f;
_Finished = false;
_AnimHasToBeStopped = false;
// Look if there are some dynamic tracks
for (uint i = 0; i < _Tracks.size(); ++i)
if (_Tracks[i]->isDynamic())
_Tracks[i]->eval();
// Play the first frame
update();
}
// ----------------------------------------------------------------------------
void CInterfaceAnim::stop()
{
_Finished = true;
if (!_AHOnFinish.empty())
CAHManager::getInstance()->runActionHandler(_AHOnFinish, _Parent, _AHOnFinishParams);
}

View file

@ -1,129 +0,0 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef RZ_INTERFACE_ANIM_H
#define RZ_INTERFACE_ANIM_H
#include "nel/gui/interface_property.h"
#include "nel/gui/interface_group.h"
#include "nel/gui/interface_link.h"
#include "nel/3d/u_track.h"
/**
* class managing an animation track
* \author Matthieu 'TrapII' Besson
* \author Nevrax France
* \date 2003
*/
class CInterfaceTrack
{
public:
CInterfaceTrack();
~CInterfaceTrack();
virtual bool parse (xmlNodePtr cur, CInterfaceGroup *parentGroup);
void update (double currentTime);
bool isDynamic () { return _Dynamic; }
void eval(); // Evaluate dynamic keys
private:
enum ETrackType
{
Track_Linear,
Track_TCB,
Track_Bezier
};
struct SDynKey
{
std::string Time;
std::string Value;
std::string InTan;
std::string OutTan;
std::string Step;
std::string Tension;
std::string Continuity;
std::string Bias;
std::string EaseTo;
std::string EaseFrom;
};
bool _Dynamic;
std::vector<SDynKey> _DynKeys;
ETrackType _Type;
NL3D::UTrackKeyframer *_TrackKeyFramer;
std::vector<CInterfaceLink::CTargetInfo> _Targets;
};
/**
* class managing an animation of the interface
* \author Matthieu 'TrapII' Besson
* \author Nevrax France
* \date 2003
*/
class CInterfaceAnim
{
public:
CInterfaceAnim();
~CInterfaceAnim();
virtual bool parse (xmlNodePtr cur, CInterfaceGroup *parentGroup);
void update();
void start();
void stop();
bool isFinished() { return _Finished; }
bool isDisableButtons() { return _DisableButtons; }
protected:
CInterfaceGroup *_Parent;
// Parsed properties
double _Duration;
bool _DisableButtons;
std::string _AHOnFinish;
std::string _AHOnFinishParams;
std::string _Id;
std::vector<CInterfaceTrack*> _Tracks;
// Current anim
double _CurrentTime;
bool _Finished;
bool _AnimHasToBeStopped;
};
#endif // NL_INTERFACE_ANIM_H
/* End of interface_anim.h */

View file

@ -43,7 +43,7 @@
#include "nel/gui/action_handler.h"
#include "action_handler_misc.h"
#include "interface_observer.h"
#include "interface_anim.h"
#include "nel/gui/interface_anim.h"
#include "interface_ddx.h"
#include "action_handler_help.h"
#include "action_handler_item.h"

View file

@ -71,10 +71,9 @@ namespace NLGUI
class CInterfaceOptions;
class CGroupContainer;
class CGroupMenu;
class CInterfaceAnim;
}
class CInterfaceAnim;
/**
* class managing the interface
* \author Matthieu 'TrapII' Besson

View file

@ -33,7 +33,7 @@
#include "interface_observer.h"
#include "nel/gui/interface_options.h"
#include "interface_options_ryzom.h"
#include "interface_anim.h"
#include "nel/gui/interface_anim.h"
#include "interface_3d_scene.h"
// View
#include "nel/gui/view_bitmap.h"

View file

@ -38,9 +38,9 @@ namespace NLGUI
class CCtrlBase;
class CGroupList;
class CGroupContainer;
class CInterfaceAnim;
}
class CInterfaceAnim;
class CViewPointer;
class CBrickJob;