CEGUI 动画

2022-09-15 11:20:20 浏览数 (1)

大家好,又见面了,我是你们的朋友全栈君。

最新的版本支持动画,使用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文件放在ceguisrcScriptingModulesLuaScriptModulepackage目录下面.在这个目录下面有一个叫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

代码语言:javascript复制
#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

代码语言:javascript复制
#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

代码语言:javascript复制
#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

代码语言:javascript复制
#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

代码语言:javascript复制
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

代码语言:javascript复制
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

代码语言:javascript复制
<?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://javaforall.cn/163724.html原文链接:https://javaforall.cn

0 人点赞