更新ENode

This commit is contained in:
Nomango 2017-10-14 18:43:32 +08:00
parent 7f402c7593
commit 489fa780ca
13 changed files with 420 additions and 173 deletions

View File

@ -23,7 +23,7 @@
<ProjectGuid>{9D85A92F-BCCE-4EF0-BAD3-601C0086661C}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>Demo</RootNamespace>
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

View File

@ -10,37 +10,26 @@ int WINAPI WinMain(
{
EApp app;
if (app.init(L"Easy2D Demo", 640, 480, true))
if (app.init(L"Easy2D Demo", 640, 480))
{
auto scene = new EScene();
auto node = new ENode();
auto node = new ENode(L"node1");
node->setPos(50, 80);
node->setSize(30, 180);
node->setSize(30, 30);
scene->add(node);
auto mlistener = new EMouseClickListener([=](EPoint) {
node->setPos(EMouseMsg::getPos());
});
auto node2 = new ENode(L"node2");
node2->setPos(20, 20);
node2->setSize(40, 40);
node->addChild(node2);
auto klistener = new EKeyPressListener([=] {
if (EKeyMsg::isCapitalLockOn())
{
if (EKeyMsg::getVal() == EKeyMsg::KEY::LEFT)
{
node->move(-3, 0);
}
if (EKeyMsg::getVal() == EKeyMsg::KEY::RIGHT)
{
node->move(3, 0);
}
}
auto mlistener = new EMouseClickListener([](EPoint) {
EApp::getCurrentScene()->getChild(L"node1")->setPos(EMouseMsg::getPos());
});
mlistener->bindWith(node);
scene->bindListener(klistener);
app.enterScene(scene);
app.run();

View File

@ -21,7 +21,6 @@ std::stack<e2d::EScene*> s_SceneStack;
e2d::EApp::EApp()
: m_bRunning(false)
, m_ClearColor(EColor::Black)
, m_bSaveScene(true)
, m_pCurrentScene(nullptr)
, m_pNextScene(nullptr)
{
@ -340,15 +339,22 @@ void e2d::EApp::enterScene(EScene * scene, bool save /* = true */)
// 保存下一场景的指针
get()->m_pNextScene = scene;
// 切换场景时,是否保存当前场景
get()->m_bSaveScene = save;
if (get()->m_pCurrentScene)
{
get()->m_pCurrentScene->m_bWillSave = save;
}
}
void e2d::EApp::backScene()
{
// 从栈顶取出场景指针,作为下一场景
get()->m_pNextScene = s_SceneStack.top();
s_SceneStack.pop();
// 不保存当前场景
get()->m_bSaveScene = false;
if (get()->m_pCurrentScene)
{
get()->m_pCurrentScene->m_bWillSave = false;
}
}
void e2d::EApp::clearScene()
@ -404,7 +410,7 @@ void e2d::EApp::free()
SafeDelete(&temp);
s_SceneStack.pop();
}
// 删除所有定时器、监听器
// 删除所有定时器、监听器和动画
//Timer::clearAllTimers();
EMsgManager::clearAllKeyboardListeners();
EMsgManager::clearAllMouseListeners();
@ -425,36 +431,18 @@ void e2d::EApp::end()
void e2d::EApp::_enterNextScene()
{
// 若下一场景处于栈顶,说明正在返回上一场景
if (s_SceneStack.size() && m_pNextScene == s_SceneStack.top())
{
// 返回上一场景时,恢复场景上的定时器
//Timer::notifyAllSceneTimers(m_pNextScene);
EMsgManager::notifyAllListenersBindWithScene(m_pNextScene);
//ActionManager::notifyAllSceneActions(m_pNextScene);
// 删除栈顶场景
s_SceneStack.pop();
}
// 执行当前场景的 onExit 函数
if (m_pCurrentScene)
{
m_pCurrentScene->onExit();
if (m_bSaveScene)
if (m_pCurrentScene->m_bWillSave)
{
// 若要保存当前场景,把它放入栈中
s_SceneStack.push(m_pCurrentScene);
// 暂停当前场景上运行的所有定时器
//Timer::waitAllSceneTimers(m_pCurrentScene);
EMsgManager::waitAllListenersBindWithScene(m_pCurrentScene);
//ActionManager::waitAllSceneActions(m_pCurrentScene);
}
else
{
// 不保存场景时,停止当前场景上运行的所有定时器,并删除当前场景
//Timer::clearAllSceneTimers(m_pCurrentScene);
EMsgManager::clearAllListenersBindWithScene(m_pCurrentScene);
//ActionManager::stopAllSceneActions(m_pCurrentScene);
SafeDelete(&m_pCurrentScene);
}
}

View File

@ -1,79 +1,91 @@
#include "..\ebase.h"
#include "..\enodes.h"
#include "..\emsg.h"
#include <algorithm>
e2d::EScene::EScene()
: m_bWillSave(true)
, m_bSortNeeded(false)
{
}
e2d::EScene::~EScene()
{
clearAllChildren();
}
/*void e2d::EScene::_exec()
{
// active 标志画面是否取得焦点
bool active = true;
// 逆序执行,最后绘制的节点(即位于画面最上方)最先被访问
for (int i = int(m_vChildren.size()) - 1; i >= 0; i--)
{
if (m_vChildren[i]->_exec(active)) // 执行节点程序
{
active = false; // 若子节点取得焦点,将标志置 false
}
}
}*/
void e2d::EScene::_onRender()
{
// 绘制所有节点
this->_sortChildren();
// 访问所有节点
for (auto child : m_vChildren)
{
child->_onRender();
child->callOn();
}
}
void e2d::EScene::_sortChildren()
{
if (m_bSortNeeded)
{
m_bSortNeeded = false;
// 子节点排序
std::sort(
std::begin(m_vChildren),
std::end(m_vChildren),
[](ENode * n1, ENode * n2) {
return n1->getOrder() < n2->getOrder();
}
);
}
}
void e2d::EScene::onEnter()
{
// 启用场景上的所有定时器、监听器和动画
//Timer::notifyAllSceneTimers(m_pNextScene);
EMsgManager::notifyAllListenersBindWithScene(this);
//ActionManager::notifyAllSceneActions(m_pNextScene);
}
void e2d::EScene::onExit()
{
}
void e2d::EScene::add(ENode * child, int zOrder /* = 0 */)
{
// 断言添加的节点非空
ASSERT(child != nullptr, "Scene::add NULL pointer exception.");
// 忽略空指针
if (child == nullptr) return;
// 设置节点的父场景
child->setParentScene(this);
// 设置 z 轴顺序
child->setZOrder(zOrder);
// 对象的引用计数加一
child->retain();
// 按 z 轴顺序插入节点
size_t size = m_vChildren.size();
for (unsigned i = 0; i <= size; i++)
if (m_bWillSave)
{
if (i == size)
{
m_vChildren.push_back(child);
break;
}
else
{
auto temp = m_vChildren.at(i);
if (temp->getZOrder() > zOrder)
{
m_vChildren.insert(m_vChildren.begin() + i, child);
break;
}
}
//Timer::waitAllSceneTimers(m_pCurrentScene);
EMsgManager::waitAllListenersBindWithScene(this);
//ActionManager::waitAllSceneActions(m_pCurrentScene);
}
else
{
//Timer::clearAllSceneTimers(m_pCurrentScene);
EMsgManager::clearAllListenersBindWithScene(this);
//ActionManager::stopAllSceneActions(m_pCurrentScene);
}
}
bool e2d::EScene::del(ENode * child, bool autoRelease /* = true */)
void e2d::EScene::add(ENode * child, int order /* = 0 */)
{
ASSERT(child != nullptr, "Scene::add NULL pointer exception.");
ASSERT(child->getParentScene() == nullptr, "Child already added. It can't be added again!");
if (child)
{
child->setParentScene(this);
child->setOrder(order);
child->retain();
m_vChildren.push_back(child);
m_bSortNeeded = true;
}
}
bool e2d::EScene::remove(ENode * child, bool autoRelease /* = true */)
{
if (child == nullptr) return false;
@ -84,7 +96,8 @@ bool e2d::EScene::del(ENode * child, bool autoRelease /* = true */)
// 找到相同节点
if (*iter == child)
{
if (autoRelease) (*iter)->autoRelease();
if (autoRelease)
(*iter)->autoRelease();
// 对象的引用计数减一
(*iter)->release();
// 去掉该节点
@ -101,6 +114,16 @@ std::vector<e2d::ENode*>& e2d::EScene::getChildren()
return m_vChildren;
}
size_t e2d::EScene::getChildrenCount() const
{
return m_vChildren.size();
}
e2d::ENode * e2d::EScene::getChild(EString childName) const
{
return ENode::getChild(childName, m_vChildren);
}
void e2d::EScene::clearAllChildren()
{
// 所有节点的引用计数减一

View File

@ -23,7 +23,7 @@
<ProjectGuid>{FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>Easy2D</RootNamespace>
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@ -203,6 +203,7 @@
<ClCompile Include="Msg\Listener\EMouseDraggedListener.cpp" />
<ClCompile Include="Msg\Listener\EMouseListener.cpp" />
<ClCompile Include="Node\ENode.cpp" />
<ClCompile Include="Node\ERectangle.cpp" />
<ClCompile Include="Tool\EObjectManager.cpp" />
<ClCompile Include="Tool\ETimerManager.cpp" />
<ClCompile Include="Win\winbase.cpp" />

View File

@ -63,6 +63,9 @@
<ClCompile Include="Msg\Listener\EKeyPressListener.cpp">
<Filter>Msg\Listener</Filter>
</ClCompile>
<ClCompile Include="Node\ERectangle.cpp">
<Filter>Node</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Win\winbase.h">

View File

@ -1,12 +1,15 @@
#include "..\enodes.h"
#include "..\Win\winbase.h"
#include <algorithm>
e2d::ENode::ENode()
: m_nZOrder(0)
: m_nOrder(0)
, m_bVisiable(true)
, m_pParent(nullptr)
, m_pParentScene(nullptr)
, m_nHashName(0)
, m_bSortNeeded(false)
, m_bTransformNeeded(false)
{
}
@ -20,46 +23,114 @@ e2d::ENode::~ENode()
{
}
void e2d::ENode::callOn()
{
if (!m_bVisiable)
{
return;
}
this->_transfrom();
if (!m_vChildren.empty())
{
this->_sortChildren();
size_t size = m_vChildren.size();
size_t i;
for (i = 0; i < size; i++)
{
auto child = m_vChildren[i];
// 访问 Order 小于零的节点
if (child->getOrder() < 0)
{
child->callOn();
}
else
{
break;
}
}
// 渲染自身
this->_onRender();
// 访问剩余节点
for (; i < size; i++)
m_vChildren[i]->callOn();
}
else
{
// 渲染自身
this->_onRender();
}
}
void e2d::ENode::_onRender()
{
D2D1_RECT_F rectangle = D2D1::RectF(
m_Rect.left,
m_Rect.top,
m_Rect.right,
m_Rect.bottom
);
ID2D1SolidColorBrush* m_pLightSlateGrayBrush;
GetRenderTarget()->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::LightSlateGray),
&m_pLightSlateGrayBrush
);
GetRenderTarget()->FillRectangle(&rectangle, m_pLightSlateGrayBrush);
}
void e2d::ENode::_onTransfrom()
{
}
void e2d::ENode::_sortChildren()
{
if (m_bSortNeeded)
{
// 子节点排序
std::sort(
std::begin(m_vChildren),
std::end(m_vChildren),
[](ENode * n1, ENode * n2) {
return n1->getOrder() < n2->getOrder();
}
);
m_bSortNeeded = false;
}
}
void e2d::ENode::_transfrom()
{
if (m_bTransformNeeded)
{
// 更新自身属性
if (m_pParent)
{
this->setPos(m_pParent->getX() + m_Pos.x, m_pParent->getY() + m_Pos.y);
}
// 根据子节点特殊性进行更新
_onTransfrom();
// 提示子节点更新属性
for (const auto &child : m_vChildren)
{
child->m_bTransformNeeded = true;
}
m_bTransformNeeded = false;
}
}
bool e2d::ENode::isVisiable() const
{
return m_bVisiable;
}
int e2d::ENode::getX() const
{
if (m_pParent)
{
return m_pParent->getX() + m_Rect.TopLeft().x;
}
return m_Rect.TopLeft().x;
}
int e2d::ENode::getY() const
{
if (m_pParent)
{
return m_pParent->getY() + m_Rect.TopLeft().y;
}
return m_Rect.TopLeft().y;
}
CPoint e2d::ENode::getPos() const
{
if (m_pParent)
{
return m_pParent->getPos() + m_Rect.TopLeft();
}
return m_Rect.TopLeft();
}
@ -85,22 +156,31 @@ e2d::ERect e2d::ENode::getRect() const
void e2d::ENode::setX(int x)
{
m_Rect.MoveToX(x);
this->setPos(x, m_Rect.TopLeft().y);
}
void e2d::ENode::setY(int y)
{
m_Rect.MoveToY(y);
}
void e2d::ENode::setPos(int x, int y)
{
m_Rect.MoveToXY(x, y);
this->setPos(m_Rect.TopLeft().x, y);
}
void e2d::ENode::setPos(EPoint p)
{
m_Rect.MoveToXY(p.x, p.y);
this->setPos(p.x, p.y);
}
void e2d::ENode::setPos(int x, int y)
{
if (getX() == x && getY() == y)
return;
if (!m_bTransformNeeded)
{
m_Pos.x = x;
m_Pos.y = y;
m_bTransformNeeded = true;
}
m_Rect.MoveToXY(x, y);
}
void e2d::ENode::move(int x, int y)
@ -125,13 +205,13 @@ void e2d::ENode::setHeight(UINT32 height)
void e2d::ENode::setSize(UINT32 width, UINT32 height)
{
setWidth(width);
setHeight(height);
m_Rect.BottomRight().x = m_Rect.TopLeft().x + width;
m_Rect.BottomRight().y = m_Rect.TopLeft().y + height;
}
void e2d::ENode::setSize(ESize size)
{
setSize(size.cx, size.cy);
this->setSize(size.cx, size.cy);
}
void e2d::ENode::setRect(int x1, int y1, int x2, int y2)
@ -150,40 +230,58 @@ void e2d::ENode::setRect(ERect rect)
m_Rect = rect;
}
int e2d::ENode::getZOrder() const
int e2d::ENode::getOrder() const
{
return m_nZOrder;
return m_nOrder;
}
void e2d::ENode::setZOrder(int z)
void e2d::ENode::setOrder(int order)
{
m_nZOrder = z;
m_nOrder = order;
}
void e2d::ENode::setParent(ENode * parent)
{
m_pParent = parent;
if (m_pParent)
{
m_pParent->addChild(this);
}
else
{
removeFromParent();
}
}
void e2d::ENode::addChild(ENode * child)
void e2d::ENode::addChild(ENode * child, int order /* = 0 */)
{
WARN_IF(child == nullptr, "NULL ENode pointer exception.");
WARN_IF(child == nullptr, "ENode::addChild NULL pointer exception.");
ASSERT(child->m_pParent == nullptr, "Child already added. It can't be added again!");
if (child)
{
for (ENode * parent = this; parent != nullptr; parent = parent->getParent())
{
ASSERT(child != parent, "A ENode cannot be the child of his own children");
ASSERT(child != parent, "A ENode cannot be the child of his own children!");
}
m_vChildren.push_back(child);
child->m_pParent = this;
child->setOrder(order);
child->retain();
m_bSortNeeded = true;
}
}
e2d::ENode *& e2d::ENode::getParent()
e2d::ENode * e2d::ENode::getParent() const
{
return m_pParent;
}
e2d::EScene * &e2d::ENode::getParentScene()
e2d::EScene * e2d::ENode::getParentScene() const
{
return m_pParentScene;
}
@ -193,19 +291,24 @@ std::vector<e2d::ENode*>& e2d::ENode::getChildren()
return m_vChildren;
}
int e2d::ENode::getChildrenCount() const
size_t e2d::ENode::getChildrenCount() const
{
return m_vChildren.size();
}
e2d::ENode * e2d::ENode::getChild(EString name)
e2d::ENode * e2d::ENode::getChild(EString name) const
{
return ENode::getChild(name, this->m_vChildren);
}
e2d::ENode * e2d::ENode::getChild(EString name, const std::vector<ENode*> &children)
{
WARN_IF(name.empty(), "Invalid ENode name.");
std::hash<EString> h;
size_t hash = h(name);
for (const auto& child : m_vChildren)
for (const auto& child : children)
{
// 不同的名称可能会有相同的 Hash 值,但是先比较 Hash 可以提升搜索速度
if (child->m_nHashName == hash && child->m_sName == name)
@ -216,19 +319,72 @@ e2d::ENode * e2d::ENode::getChild(EString name)
void e2d::ENode::setParentScene(EScene * scene)
{
m_pParentScene = scene;
if (m_pParentScene)
{
m_pParentScene = scene;
}
}
void e2d::ENode::removeFromParent(bool release)
void e2d::ENode::removeFromParent(bool release /* = false */)
{
if (m_pParent)
{
m_pParent->removeChild(this, release);
}
}
void e2d::ENode::removeChild(ENode * child, bool release)
void e2d::ENode::removeChild(ENode * child, bool release /* = false */)
{
WARN_IF(child == nullptr, "ENode::removeChild NULL pointer exception.");
if (m_vChildren.empty())
{
return;
}
if (child)
{
size_t size = m_vChildren.size();
for (size_t i = 0; i < size; i++)
{
if (m_vChildren[i] == child)
{
m_vChildren.erase(m_vChildren.begin() + i);
child->m_pParent = nullptr;
child->release();
if (release)
child->autoRelease();
return;
}
}
}
}
void e2d::ENode::removeChild(EString childName, bool release)
void e2d::ENode::removeChild(EString childName, bool release /* = false */)
{
WARN_IF(childName.empty(), "Invalid ENode name.");
if (m_vChildren.empty())
{
return;
}
std::hash<EString> h;
size_t hash = h(childName);
size_t size = m_vChildren.size();
for (size_t i = 0; i < size; i++)
{
auto child = m_vChildren[i];
if (child->m_nHashName == hash && child->m_sName == childName)
{
m_vChildren.erase(m_vChildren.begin() + i);
child->m_pParent = nullptr;
child->release();
if (release)
child->autoRelease();
return;
}
}
}
void e2d::ENode::setVisiable(bool value)
@ -249,8 +405,3 @@ void e2d::ENode::setName(EString name)
m_nHashName = h(name);
}
}
bool e2d::ENode::isVisiable() const
{
return m_bVisiable;
}

View File

@ -0,0 +1,19 @@
#include "..\enodes.h"
#include "..\Win\winbase.h"
void e2d::ERectangle::_onRender()
{
static D2D1_RECT_F rectangle = D2D1::RectF(
m_Rect.left,
m_Rect.top,
m_Rect.right,
m_Rect.bottom
);
GetRenderTarget()->FillRectangle(&rectangle, GetSolidColorBrush(D2D1::ColorF(D2D1::ColorF::LightSlateGray)));
}
void e2d::ERectangle::_onTransfrom()
{
}

View File

@ -4,6 +4,7 @@
HWND hwnd = nullptr;
ID2D1Factory * pDirect2dFactory = nullptr;
ID2D1HwndRenderTarget * pRenderTarget = nullptr;
ID2D1SolidColorBrush * m_pSolidBrush = nullptr;
HWND &GetHWnd()
@ -21,3 +22,9 @@ ID2D1HwndRenderTarget * &GetRenderTarget()
return pRenderTarget;
}
ID2D1SolidColorBrush *& GetSolidColorBrush(D2D1_COLOR_F & color)
{
pRenderTarget->CreateSolidColorBrush(color, &m_pSolidBrush);
return m_pSolidBrush;
}

View File

@ -12,6 +12,8 @@ ID2D1Factory * &GetFactory();
ID2D1HwndRenderTarget * &GetRenderTarget();
ID2D1SolidColorBrush * &GetSolidColorBrush(D2D1_COLOR_F &color);
template<class Interface>
inline void SafeReleaseInterface(

View File

@ -149,7 +149,6 @@ protected:
protected:
bool m_bRunning;
bool m_bSaveScene;
EString m_sTitle;
EString m_sAppName;
EColor::Enum m_ClearColor;
@ -164,7 +163,7 @@ class EScene
friend EApp;
public:
EScene() = default;
EScene();
~EScene();
@ -181,7 +180,7 @@ public:
);
// 删除子成员
bool del(
bool remove(
e2d::ENode * child,
bool autoRelease = true
);
@ -189,6 +188,14 @@ public:
// 获取所有子节点
std::vector<e2d::ENode*> &getChildren();
// 获取子节点数量
size_t getChildrenCount() const;
// 根据名称获取子节点
ENode * getChild(
EString childName
) const;
// 清空所有子成员
void clearAllChildren();
@ -202,7 +209,12 @@ protected:
// 渲染场景画面
void _onRender();
// 子节点排序
void _sortChildren();
protected:
bool m_bSortNeeded;
bool m_bWillSave;
std::vector<e2d::ENode*> m_vChildren;
};

View File

@ -7,8 +7,6 @@ namespace e2d
class ENode :
public EObject
{
friend EScene;
public:
ENode();
@ -22,7 +20,7 @@ public:
virtual bool isVisiable() const;
// 获取节点绘图顺序
virtual int getZOrder() const;
virtual int getOrder() const;
// 获取节点横坐标
virtual int getX() const;
@ -46,19 +44,27 @@ public:
virtual ERect getRect() const;
// 获取父节点
virtual ENode * &getParent();
virtual ENode * getParent() const;
// 获取节点所在场景
virtual EScene * &getParentScene();
virtual EScene * getParentScene() const;
// 获取所有子节点
virtual std::vector<ENode*> &getChildren();
// 获取子节点数量
virtual int getChildrenCount() const;
virtual size_t getChildrenCount() const;
// 根据名字获取子节点
virtual ENode * getChild(EString name);
virtual ENode * getChild(
EString name
) const;
// 根据名字获取子节点
static ENode * getChild(
EString name,
const std::vector<ENode*> &children
);
// 设置节点是否显示
virtual void setVisiable(
@ -66,7 +72,9 @@ public:
);
// 设置节点名称
virtual void setName(EString name);
virtual void setName(
EString name
);
// 设置节点横坐标
virtual void setX(
@ -140,9 +148,9 @@ public:
ERect rect
);
// 设置节点绘图顺序0为最先绘制显示在最底层
virtual void setZOrder(
int z
// 设置节点绘图顺序
virtual void setOrder(
int order
);
// 设置节点所在场景
@ -156,30 +164,66 @@ public:
);
// 添加子节点
virtual void addChild(ENode * child);
virtual void addChild(
ENode * child,
int order = 0
);
// 从父节点移除
virtual void removeFromParent(bool release = false);
virtual void removeFromParent(
bool release = false
);
// 移除子节点
virtual void removeChild(ENode * child, bool release = false);
virtual void removeChild(
ENode * child,
bool release = false
);
// 移除子节点
virtual void removeChild(EString childName, bool release = false);
virtual void removeChild(
EString childName,
bool release = false
);
// 访问节点
virtual void callOn();
protected:
// 渲染节点
virtual void _onRender();
// 节点状态转换
virtual void _onTransfrom();
// 子节点排序
void _sortChildren();
// 节点状态转换
void _transfrom();
protected:
EString m_sName;
size_t m_nHashName;
int m_nZOrder;
int m_nOrder;
bool m_bVisiable;
bool m_bSortNeeded;
bool m_bTransformNeeded;
ERect m_Rect;
EPoint m_Pos;
EScene * m_pParentScene;
ENode * m_pParent;
std::vector<ENode*> m_vChildren;
};
class ERectangle :
public ENode
{
protected:
virtual void _onRender() override;
virtual void _onTransfrom() override;
};
}

View File

@ -27,6 +27,14 @@ private:
};
// 定时器
class ETimer :
public EObject
{
};
// 定时器管理器
class ETimerManager
{