• 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>
  • 相关阅读:
    vue中使用vuepdf插件显示pdf
    vuecirclemenu漂亮的圆形菜单
    console.log输出彩色字,图片等
    项目开发之使用 maven
    用 C 扩展 python
    Flash 与 php 使用 amfphp
    纯命令行的编辑利器:用好 awk 与 sed
    远程调试Java程序
    .net core 项目文件结构浅析
    初识Redis系列之一:简单介绍
  • 原文地址:https://www.cnblogs.com/emyueguang/p/2315643.html
Copyright © 2020-2023  润新知