| 93 | */ |
| 94 | static EventListenerCustom* s_captureScreenListener; |
| 95 | void captureScreen(std::function<void(RefPtr<Image>)> imageCallback) |
| 96 | { |
| 97 | if (s_captureScreenListener) |
| 98 | { |
| 99 | AXLOGW("Warning: CaptureScreen has been called already, don't call more than once in one frame."); |
| 100 | return; |
| 101 | } |
| 102 | |
| 103 | auto director = Director::getInstance(); |
| 104 | auto renderer = director->getRenderer(); |
| 105 | auto eventDispatcher = director->getEventDispatcher(); |
| 106 | |
| 107 | // !!!Metal: needs setFrameBufferOnly before draw |
| 108 | #if defined(AX_USE_METAL) |
| 109 | s_captureScreenListener = |
| 110 | eventDispatcher->addCustomEventListener(Director::EVENT_BEFORE_DRAW, [=](EventCustom* /*event*/) { |
| 111 | #else |
| 112 | s_captureScreenListener = |
| 113 | eventDispatcher->addCustomEventListener(Director::EVENT_AFTER_DRAW, [=](EventCustom* /*event*/) { |
| 114 | #endif |
| 115 | eventDispatcher->removeEventListener(s_captureScreenListener); |
| 116 | s_captureScreenListener = nullptr; |
| 117 | // !!!GL: AFTER_DRAW and BEFORE_END_FRAME |
| 118 | renderer->readPixels(renderer->getDefaultRenderTarget(), [=](const backend::PixelBufferDescriptor& pbd) { |
| 119 | if (pbd) |
| 120 | { |
| 121 | auto image = utils::makeInstance<Image>(&Image::initWithRawData, pbd._data.getBytes(), |
| 122 | pbd._data.getSize(), pbd._width, pbd._height, 8, false); |
| 123 | imageCallback(image); |
| 124 | } |
| 125 | else |
| 126 | imageCallback(nullptr); |
| 127 | }); |
| 128 | }); |
| 129 | } |
| 130 | |
| 131 | static std::unordered_map<Node*, EventListenerCustom*> s_captureNodeListener; |
| 132 | void captureNode(Node* startNode, std::function<void(RefPtr<Image>)> imageCallback, float scale) |
| 133 | { |
| 134 | if (s_captureNodeListener.find(startNode) != s_captureNodeListener.end()) |
| 135 | { |
| 136 | AXLOGW("Warning: current node has been captured already"); |
| 137 | return; |
| 138 | } |
| 139 | |
| 140 | auto callback = [startNode, scale, imageCallback](EventCustom* /*event*/) { |
| 141 | auto director = Director::getInstance(); |
| 142 | auto captureNodeListener = s_captureNodeListener[startNode]; |
| 143 | director->getEventDispatcher()->removeEventListener((EventListener*)(captureNodeListener)); |
| 144 | s_captureNodeListener.erase(startNode); |
| 145 | auto& size = startNode->getContentSize(); |
| 146 | |
| 147 | director->setNextDeltaTimeZero(true); |
| 148 | |
| 149 | RenderTexture* finalRtx = nullptr; |
| 150 | |
| 151 | auto rtx = |
| 152 | RenderTexture::create(size.width, size.height, backend::PixelFormat::RGBA8, PixelFormat::D24S8, false); |