CEGUI 动画

最新的版本支持动画,使用Animation类.项目中使用的是7.1的版本,不支持动画,leader说不使用最新版本的CEGUI库,就使用7.1,无奈,自己写一个动画类吧.
CEGUI中播放动画是将一个动画的每帧连续不断的画到屏幕上,就形成了动画.
就像小时候在书的边页上面画的小人,每一页都画一个小人,每个小人的动作都有点不同,这样快速翻书的时候,小人就成了动画.
源代码如最后所贴,原理性的东西就不多讲,这个可以看书,或者自己分析源代码.
在此把整个过程概述一下,记录一下我在这个过程遇到的难点.
1. 定义自己的动画窗口类,继承自Window类,class DynamicImage : public Window {...}
2. 给DynamicImage添加两个属性:TimeInterval,每帧播放的时间间隔.FrameImage,设置某一帧的图像.
  TimeInterval属性就是保存一个时间间隔值在成员变量中.FrameImage属性就是插入一帧图像,设置的格式就像其它控件一样"set:setname image:imagename".比如一个动画由10帧组成,那设置10个这个属性,每一个属性值是其中的一帧图像.
3. 在DynamicImage类中重载一下updateSelf()这个函数,渲染过程就在这个函数中实现. 在windows窗口消息的过程中会调用injectTimePulse(),而在injectTimePulse()中又调用了updateSelf(),所以在窗口消息循环中就可以连续不断的绘制动态的表情了.详细请看源码.
  用一个成员变量将所有的帧保存起来,所谓绘制动画就是在固定的间隔时间内连续不断的绘制出这些帧.就形成了动画.
4. 为了方便使用,用tolua++,将DynamicImage打包一下,这样在lua/layout_xml中就可以直接使用这个窗口类了.由于这个窗口类并没有定义自己的WindowRender,所以不需要在scheme中添加对应的解析项.
  打包的方式:准备工作 一.CEGUI的解决方案中有一个叫tolua++cegui的项目,生成这个项目,并将生成的可执行文件以及运行所需要的dll文件放在\cegui\src\ScriptingModules\LuaScriptModule\package目录下面.在这个目录下面有一个叫make.bat的批处理文件,将它里面的内容修改一下,将第一行改成:tolua++cegui_d -o lua_CEGUI.cpp -L exceptions.lua CEGUI.pkg, 意思就是说,使用exceptions.lua和CEGUI.pkg这两个文件来生成一个叫lua_CEGUI.cpp的文件放在当前目录下.
  准备工作 二. 在上面说的那个目录下面有一个叫elements的目录,在这个目录中添加自己定义的窗口pkg文件.至于里面的格式,参考其它文件怎么写的,这个pkg里面写的函数就是可以在lua中使用的函数. 再在CEGUI.pkg这个文件中添加刚才那个文件的名称$pfile "elements/DynamicImage.pkg", 再在HelperFunctions.pkg文件中添加支持在lua创建这个类的函数:
  function CEGUI.toDynamicImage(w)
      return tolua.cast(w,"CEGUI::DynamicImage")
  end
  准备工作完成. 运行make.bat文件,将生成的lua_CEGUI.cpp文件放到上级目录下面,然后生成一下CEGUI的库,OK了,然后就可以在自己的项目中使用这个类了.

补充一下:在要System里面添加一个这个类的的Factory:WindowFactoryManager::addFactory< TplWindowFactory<DynamicImage> >();

View Code
#ifndef _CEGUIDynamicImage_h_
#define _CEGUIDynamicImage_h_

#include "../CEGUIBase.h"
#include "../CEGUIWindow.h"
#include "../CEGUIImage.h"
#include "CEGUIDynamicImageProperties.h"
#include <vector>

#if defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable : 4251)
#endif


namespace CEGUI
{
class CEGUIEXPORT DynamicImage : public Window
{
public:
static const String EventNamespace;
static const String WidgetTypeName;

void addFrameImage(const String& frameImage); // 添加帧图像
void setTimeInterval(unsigned int timeInterval); // 设置每帧播放间隔时间
unsigned int getTimeInterval() const; // 获取每帧播放时间间隔

DynamicImage(const String &type, const String &name);
virtual ~DynamicImage(void);

protected:
virtual bool testClassName_impl(const String& class_name) const
{
if (class_name=="DynamicImage") return true;
return Window::testClassName_impl(class_name);
}

virtual void updateSelf(float elapsed);

private:
unsigned int m_timeInterval; // 每帧播放的时间间隔
unsigned int m_render_frame_id; // 待渲染的帧ID
std::vector<Image> m_frameVector; // 帧容器;

private:
static DynamicImageProperties::TimeInterval d_timeInterval;
static DynamicImageProperties::FrameImage d_frameImage;

void addDynamicImageProperties(void);
};
}

#endif
View Code
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <Windows.h>
#include "elements/CEGUIDynamicImage.h"
#include "CEGUIImagesetManager.h"
#include "CEGUIExceptions.h"
#include "CEGUIPropertyHelper.h"
#include "CEGUIGeometryBuffer.h"


namespace CEGUI
{
const String DynamicImage::EventNamespace("DynamicImage");
const String DynamicImage::WidgetTypeName("CEGUI/DynamicImage");

DynamicImageProperties::TimeInterval DynamicImage::d_timeInterval;
DynamicImageProperties::FrameImage DynamicImage::d_frameImage;

DynamicImage::DynamicImage(const String &type, const String &name):
Window(type, name),
m_timeInterval(1)
{
addDynamicImageProperties();
d_textParsingEnabled = false;
}

DynamicImage::~DynamicImage(void)
{

}

//-------------------------------------------------------------------------------------------------------------
// 添加帧图像
void DynamicImage::addFrameImage(const String& frameImage)
{
m_frameVector.push_back(*PropertyHelper::stringToImage(frameImage));
}

//-------------------------------------------------------------------------------------------------------------
// 设置每帧播放间隔时间
void DynamicImage::setTimeInterval(unsigned int timeInterval)
{
m_timeInterval = timeInterval;
}

//-------------------------------------------------------------------------------------------------------------
// 获取每帧播放时间间隔
unsigned int DynamicImage::getTimeInterval() const
{
return m_timeInterval;
}

//-------------------------------------------------------------------------------------------------------------
// 更新自己
void DynamicImage::updateSelf(float elapsed)
{
if (m_frameVector.size() > 0)
{
Window::updateSelf(elapsed);

static int frameId = 0; // 帧ID
if (frameId >= m_frameVector.size())
frameId = 0;

static unsigned int t_lastTime = 0;
unsigned int t_nowTime = GetTickCount();
unsigned int t_elapsed = t_nowTime - t_lastTime;

Size t_image_size = m_frameVector[frameId].getSize(); // 图像的大小(从图像对应的xml文件中读取出来)
Rect t_win_clip_rect = getClipRect(); // 此窗口的裁剪区域,即此窗口的position&size定义的区域
d_geometry->setClippingRegion(t_win_clip_rect); // 设置裁剪的区域,即,窗口的裁剪区域
Rect t_image_rect(Point(0,0),t_image_size); // Image在此窗口中显示的区域(从0点开始,即左上角,尺寸为图像的尺寸)
d_geometry->reset(); // 清空原来的图像

if (t_elapsed >= m_timeInterval)
{
t_lastTime = t_nowTime;
m_frameVector[frameId].draw(*d_geometry, t_image_rect,0); // 在指定范围内画出此帧图像
frameId++;
}
else
{
m_frameVector[frameId].draw(*d_geometry, t_image_rect,0); // 在指定范围内画出此帧图像
}
}
}

//-------------------------------------------------------------------------------------------------------------
// 添加属性
void DynamicImage::addDynamicImageProperties(void)
{
addProperty(&d_frameImage);
addProperty(&d_timeInterval);
}
}
View Code
#ifndef _CEGUIDynamicImageProperties_h_
#define _CEGUIDynamicImageProperties_h_

#include "../CEGUIProperty.h"

namespace CEGUI
{
namespace DynamicImageProperties
{
// 每帧播放的间隔时间
class TimeInterval : public Property
{
public:
TimeInterval() : Property("TimeInterval","每帧播放的间隔时间,值为毫秒.","1"){}
String get(const PropertyReceiver* receiver) const;
void set(PropertyReceiver* receiver, const String& value);
};

// 某一帧图像
class FrameImage : public Property
{
public:
FrameImage() : Property("FrameImage","某一帧播放的图像.格式:set:[imageset name] image:[image name].",""){}
String get(const PropertyReceiver* receiver) const;
void set(PropertyReceiver* receiver, const String& value);
};
}
}

#endif
View Code
#include "elements/CEGUIDynamicImageProperties.h"
#include "elements/CEGUIDynamicImage.h"
#include "CEGUIPropertyHelper.h"
#include "CEGUIExceptions.h"

namespace CEGUI
{
namespace DynamicImageProperties
{
// 每帧播放的间隔时间
String TimeInterval::get(const PropertyReceiver* receiver) const
{
return PropertyHelper::uintToString(static_cast<const DynamicImage*>(receiver)->getTimeInterval());
}

void TimeInterval::set(PropertyReceiver* receiver, const String& value)
{
static_cast<DynamicImage*>(receiver)->setTimeInterval(PropertyHelper::stringToUint(value));
}

// 某一帧图像
String FrameImage::get(const PropertyReceiver* receiver) const
{
return "";
}

void FrameImage::set(PropertyReceiver* receiver, const String& value)
{
static_cast<DynamicImage*>(receiver)->addFrameImage(value);
}
}
}

上面是CEGUI自定义类的源码,下面是使用这个类的demo.这个是直接使用C++方式创建窗口

View Code
void mywin()
{
using namespace CEGUI;

WindowManager& winmgr = WindowManager::getSingleton();
SchemeManager::getSingleton().create("TaharezLook.scheme");

Window* background = winmgr.createWindow("CEGUI/DynamicImage", "root_wnd");
background->subscribeEvent(DynamicImage::EventMouseClick, Event::Subscriber(&handleMouseClicked));
background->setProperty("UnifiedPosition", "{{0,100},{0,100}}");
background->setProperty("UnifiedSize", "{{0,32},{0,32}}");
background->setProperty("TimeInterval", "100");
background->setProperty("FrameImage", "set:FaceImageset image:Face5_1");
background->setProperty("FrameImage", "set:FaceImageset image:Face5_2");
background->setProperty("FrameImage", "set:FaceImageset image:Face5_3");
background->setProperty("FrameImage", "set:FaceImageset image:Face5_4");
System::getSingleton().setGUISheet(background);
}

这个使用lua+xml

View Code
local winmgr = CEGUI.WindowManager:getSingleton();
local system = CEGUI.System:getSingleton();
local schmgr = CEGUI.SchemeManager:getSingleton();
schmgr:create("TaharezLook.scheme");

function select_mode(mode)
local face = nil;
if (mode == 1) then
------------------------------------------------------------------------------
-- 直接使用xml来创建动画窗口
print("mode : 1.");
face = winmgr:loadWindowLayout("CEGUIWin1.xml");
else
------------------------------------------------------------------------------
-- 使用lua来创建窗口
print("mode : not 1.");
face = winmgr:createWindow("CEGUI/DynamicImage");
face:subscribeEvent("MouseClick", "handleMouseClicked");
face:setProperty("UnifiedPosition", "{{0,100},{0,100}}");
face:setProperty("UnifiedSize", "{{0,32},{0,32}}");
face:setProperty("TimeInterval", "100");
face:setProperty("FrameImage", "set:FaceImageset image:Face5_1");
face:setProperty("FrameImage", "set:FaceImageset image:Face5_2");
face:setProperty("FrameImage", "set:FaceImageset image:Face5_3");
face:setProperty("FrameImage", "set:FaceImageset image:Face5_4");
end

system:setGUISheet(face);
end

function handleMouseClicked(event)
print("face clicked.");
end

select_mode(1);
View Code
<?xml version="1.0" encoding="UTF-8"?>
<GUILayout >
<Window Type="CEGUI/DynamicImage" Name="Root">
<Property Name="UnifiedPosition" Value ="{{0,0},{0,0}}" />
<Property Name="UnifiedSize" Value ="{{0,32},{0,32}}" />
<Property Name="TimeInterval" Value ="100" />
<Property Name="FrameImage" Value ="set:FaceImageset image:Face5_1" />
<Property Name="FrameImage" Value ="set:FaceImageset image:Face5_2" />
<Property Name="FrameImage" Value ="set:FaceImageset image:Face5_3" />
<Property Name="FrameImage" Value ="set:FaceImageset image:Face5_4" />
<Event Name="MouseClick" Function ="handleMouseClicked" />
</Window>
</GUILayout>
原文地址:https://www.cnblogs.com/emyueguang/p/2315643.html