ImGUIEXT addRenderLoop support global without any target scene

This commit is contained in:
halx99 2020-09-07 23:21:15 +08:00
parent cde039b34b
commit 500e913517
2 changed files with 514 additions and 451 deletions

View File

@ -10,26 +10,27 @@ static uint32_t fourccValue(const std::string& str) {
return value; return value;
} }
// TODO: Rename to ImGuiEXTLayerBlock class ImGuiEXTEventTracker {
// Because it's only used for block event when ImGui::IsAnyWindowHovered() == 'true' public:
class ImGuiEXTRenderer : public Layer virtual ~ImGuiEXTEventTracker() {}
{ };
CC_CONSTRUCTOR_ACCESS:
bool initWithImGuiEXT()
{
if (!Layer::init())
return false;
// Track scene event and check whether routed to the scene graph
class ImGuiEXTSceneEventTracker : public ImGuiEXTEventTracker
{
public:
bool initWithScene(Scene* scene)
{
#ifdef CC_PLATFORM_PC #ifdef CC_PLATFORM_PC
_trackLayer = utils::newInstance<Layer>();
// note: when at the first click to focus the window, this will not take effect // note: when at the first click to focus the window, this will not take effect
auto listener = EventListenerTouchOneByOne::create(); auto listener = EventListenerTouchOneByOne::create();
listener->setSwallowTouches(true); listener->setSwallowTouches(true);
listener->onTouchBegan = [this](Touch* touch, Event*) -> bool { listener->onTouchBegan = [this](Touch* touch, Event*) -> bool {
if (!_visible)
return false;
return ImGui::IsAnyWindowHovered(); return ImGui::IsAnyWindowHovered();
}; };
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); _trackLayer->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, _trackLayer);
// add by halx99 // add by halx99
auto stopAnyMouse = [=](EventMouse* event) { auto stopAnyMouse = [=](EventMouse* event) {
@ -39,7 +40,8 @@ CC_CONSTRUCTOR_ACCESS:
}; };
auto mouseListener = EventListenerMouse::create(); auto mouseListener = EventListenerMouse::create();
mouseListener->onMouseDown = mouseListener->onMouseUp = stopAnyMouse; mouseListener->onMouseDown = mouseListener->onMouseUp = stopAnyMouse;
_eventDispatcher->addEventListenerWithSceneGraphPriority(mouseListener, this); _trackLayer->getEventDispatcher()->addEventListenerWithSceneGraphPriority(mouseListener, _trackLayer);
scene->addChild(_trackLayer, INT_MAX);
#endif #endif
// add an empty sprite to avoid render problem // add an empty sprite to avoid render problem
// const auto sp = Sprite::create(); // const auto sp = Sprite::create();
@ -55,12 +57,69 @@ CC_CONSTRUCTOR_ACCESS:
* And need modify engine code to call _scheduler->update(_deltaTime) even director is paused, pass 0 for update * And need modify engine code to call _scheduler->update(_deltaTime) even director is paused, pass 0 for update
* c. Director::EVENT_BEFORE_DRAW call beginFrame, EVENT_AFTER_VISIT call endFrame * c. Director::EVENT_BEFORE_DRAW call beginFrame, EVENT_AFTER_VISIT call endFrame
*/ */
return true; return true;
} }
~ImGuiEXTRenderer() ~ImGuiEXTSceneEventTracker()
{ {
#ifdef CC_PLATFORM_PC
if (_trackLayer) {
if (_trackLayer->getParent())
_trackLayer->removeFromParent();
_trackLayer->release();
} }
#endif
}
private:
Layer* _trackLayer = nullptr;
};
class ImGuiEXTGlobalEventTracker : public ImGuiEXTEventTracker
{
static const int highestPriority = (std::numeric_limits<int>::min)();
public:
bool init()
{
#ifdef CC_PLATFORM_PC
// note: when at the first click to focus the window, this will not take effect
auto eventDispatcher = Director::getInstance()->getEventDispatcher();
_touchListener = utils::newInstance<EventListenerTouchOneByOne>();
_touchListener->setSwallowTouches(true);
_touchListener->onTouchBegan = [this](Touch* touch, Event*) -> bool {
return ImGui::IsAnyWindowHovered();
};
eventDispatcher->addEventListenerWithFixedPriority(_touchListener, highestPriority);
// add by halx99
auto stopAnyMouse = [=](EventMouse* event) {
if (ImGui::IsAnyWindowHovered()) {
event->stopPropagation();
}
};
_mouseListener = utils::newInstance<EventListenerMouse>();
_mouseListener->onMouseDown = _mouseListener->onMouseUp = stopAnyMouse;
eventDispatcher->addEventListenerWithFixedPriority(_mouseListener, highestPriority);
#endif
return true;
}
~ImGuiEXTGlobalEventTracker() {
#ifdef CC_PLATFORM_PC
auto eventDispatcher = Director::getInstance()->getEventDispatcher();
eventDispatcher->removeEventListener(_mouseListener);
eventDispatcher->removeEventListener(_touchListener);
_mouseListener->release();
_touchListener->release();
#endif
}
EventListenerTouchOneByOne* _touchListener = nullptr;
EventListenerMouse* _mouseListener = nullptr;
}; };
static ImGuiEXT* _instance = nullptr; static ImGuiEXT* _instance = nullptr;
@ -79,7 +138,7 @@ void ImGuiEXT::init()
ImGuiEXT* ImGuiEXT::getInstance() ImGuiEXT* ImGuiEXT::getInstance()
{ {
if(_instance == nullptr) if (_instance == nullptr)
{ {
_instance = new ImGuiEXT(); _instance = new ImGuiEXT();
_instance->init(); _instance->init();
@ -194,7 +253,7 @@ void ImGuiEXT::update()
// commands will be processed after update // commands will be processed after update
} }
bool ImGuiEXT::addRenderLoop(const std::string& id, Scene* scene, std::function<void()> onFrame) bool ImGuiEXT::addRenderLoop(const std::string& id, std::function<void()> func, Scene* target)
{ {
// TODO: check whether exist // TODO: check whether exist
auto fourccId = fourccValue(id); auto fourccId = fourccValue(id);
@ -203,11 +262,17 @@ bool ImGuiEXT::addRenderLoop(const std::string& id, Scene* scene, std::function<
return false; return false;
} }
auto renderer = utils::newInstance<ImGuiEXTRenderer>(&ImGuiEXTRenderer::initWithImGuiEXT); ImGuiEXTEventTracker* tracker;
scene->addChild(renderer, INT_MAX, fourccId); if (target)
_renderPiplines.emplace(fourccId, RenderPipline{ renderer, std::move(onFrame) }); tracker = utils::newInstance<ImGuiEXTSceneEventTracker>(&ImGuiEXTSceneEventTracker::initWithScene, target);
else
tracker = utils::newInstance<ImGuiEXTGlobalEventTracker>();
if (tracker) {
_renderPiplines.emplace(fourccId, RenderPipline{ tracker, std::move(func) });
return true; return true;
}
return false;
} }
void ImGuiEXT::removeRenderLoop(const std::string& id) void ImGuiEXT::removeRenderLoop(const std::string& id)
@ -215,10 +280,8 @@ void ImGuiEXT::removeRenderLoop(const std::string& id)
auto fourccId = fourccValue(id); auto fourccId = fourccValue(id);
const auto iter = _renderPiplines.find(fourccId); const auto iter = _renderPiplines.find(fourccId);
if (iter != _renderPiplines.end()) { if (iter != _renderPiplines.end()) {
auto renderer = iter->second.renderer; auto tracker = iter->second.tracker;
if (renderer->getParent()) delete tracker;
renderer->removeFromParent();
renderer->release();
_renderPiplines.erase(iter); _renderPiplines.erase(iter);
} }
} }
@ -488,7 +551,7 @@ ImGui::MarkdownImageData MarkdownImageCallback(ImGui::MarkdownLinkCallbackData d
std::tie(sp, size, tint_col, border_col) = ImGuiMarkdownImageCallback( std::tie(sp, size, tint_col, border_col) = ImGuiMarkdownImageCallback(
{ data.text, (size_t)data.textLength }, { data.text, (size_t)data.textLength },
{ data.link, (size_t)data.linkLength }); { data.link, (size_t)data.linkLength });
if(!sp || !sp->getTexture()) if (!sp || !sp->getTexture())
return ImGuiMarkdownInvalidImageData; return ImGuiMarkdownInvalidImageData;
auto size_ = size; auto size_ = size;
const auto rect = sp->getTextureRect(); const auto rect = sp->getTextureRect();

View File

@ -10,7 +10,7 @@
NS_CC_EXT_BEGIN NS_CC_EXT_BEGIN
class ImGuiEXTRenderer; class ImGuiEXTEventTracker;
class ImGuiEXT class ImGuiEXT
{ {
friend class ImGuiEXTRenderer; friend class ImGuiEXTRenderer;
@ -52,9 +52,9 @@ public:
/// Add a ImGui render loop to specific scene /// Add a ImGui render loop to specific scene
/// </summary> /// </summary>
/// <param name="id">The FOURCC id of render loop, starts with '#', such as "#abcd"</id> /// <param name="id">The FOURCC id of render loop, starts with '#', such as "#abcd"</id>
/// <param name="target">the target scene to render ImGui</param>
/// <param name="func">the ImGui render loop</param> /// <param name="func">the ImGui render loop</param>
bool addRenderLoop(const std::string& id, Scene* target, std::function<void()> func); /// <param name="target">The target scene to track event, nullptr for global, useful for global GM tools</param>
bool addRenderLoop(const std::string& id, std::function<void()> func, Scene* target);
/// <summary> /// <summary>
/// Remove ImGui render loop /// Remove ImGui render loop
@ -137,7 +137,7 @@ private:
static std::function<void(ImGuiEXT*)> _onInit; static std::function<void(ImGuiEXT*)> _onInit;
struct RenderPipline { struct RenderPipline {
ImGuiEXTRenderer* renderer; ImGuiEXTEventTracker* tracker;
std::function<void()> frame; std::function<void()> frame;
}; };