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

View File

@ -10,7 +10,7 @@
NS_CC_EXT_BEGIN
class ImGuiEXTRenderer;
class ImGuiEXTEventTracker;
class ImGuiEXT
{
friend class ImGuiEXTRenderer;
@ -52,9 +52,9 @@ public:
/// Add a ImGui render loop to specific scene
/// </summary>
/// <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>
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>
/// Remove ImGui render loop
@ -137,7 +137,7 @@ private:
static std::function<void(ImGuiEXT*)> _onInit;
struct RenderPipline {
ImGuiEXTRenderer* renderer;
ImGuiEXTEventTracker* tracker;
std::function<void()> frame;
};