前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CEGUI 动画

CEGUI 动画

作者头像
全栈程序员站长
发布2022-09-15 11:20:20
1800
发布2022-09-15 11:20:20
举报
文章被收录于专栏:全栈程序员必看

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

最新的版本支持动画,使用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> >();

CEGUI 动画
CEGUI 动画
CEGUI 动画
CEGUI 动画

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
CEGUI 动画
CEGUI 动画
CEGUI 动画
CEGUI 动画

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);
    }
}
CEGUI 动画
CEGUI 动画
CEGUI 动画
CEGUI 动画

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
CEGUI 动画
CEGUI 动画
CEGUI 动画
CEGUI 动画

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++方式创建窗口

CEGUI 动画
CEGUI 动画
CEGUI 动画
CEGUI 动画

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

CEGUI 动画
CEGUI 动画
CEGUI 动画
CEGUI 动画

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);
CEGUI 动画
CEGUI 动画
CEGUI 动画
CEGUI 动画

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档