From 67d2f79ab684a21e940de611aacb20de11ea1064 Mon Sep 17 00:00:00 2001 From: rh101 Date: Thu, 30 May 2019 18:59:47 +1000 Subject: [PATCH 1/4] Added RenderTexture::saveToFileAsNonPMA() to save images without PMA. Set the PMA parameter to true when calling initWithRawData() inside RenderTexture::newImage(), since textures are PMA. Renamed Image::premultipliedAlpha() to Image::premultiplyAlpha() to better reflect it's action, and made it public. Added Image::reversePremultipliedAlpha() to allow the reversing of the PMA. Updated CCImage-ios.mm to set the correct bitmapInfo for PMA and non-PMA images before saving a file. Updated RenderTextureTest::RenderTextureSave() to cater for non-PMA file saving. --- cocos/2d/CCRenderTexture.cpp | 50 ++++++++++++-- cocos/2d/CCRenderTexture.h | 27 +++++++- cocos/platform/CCImage.cpp | 27 +++++++- cocos/platform/CCImage.h | 4 +- cocos/platform/ios/CCImage-ios.mm | 9 ++- .../RenderTextureTest/RenderTextureTest.cpp | 65 ++++++++++++++++--- .../RenderTextureTest/RenderTextureTest.h | 6 +- 7 files changed, 168 insertions(+), 20 deletions(-) diff --git a/cocos/2d/CCRenderTexture.cpp b/cocos/2d/CCRenderTexture.cpp index fb63b9cac6cd..3b2b54a5d153 100644 --- a/cocos/2d/CCRenderTexture.cpp +++ b/cocos/2d/CCRenderTexture.cpp @@ -506,6 +506,28 @@ void RenderTexture::visit(Renderer *renderer, const Mat4 &parentTransform, uint3 // setOrderOfArrival(0); } +bool RenderTexture::saveToFileAsNonPMA(const std::string& filename, bool isRGBA, std::function callback) +{ + std::string basename(filename); + std::transform(basename.begin(), basename.end(), basename.begin(), ::tolower); + + if (basename.find(".png") != std::string::npos) + { + return saveToFileAsNonPMA(filename, Image::Format::PNG, isRGBA, callback); + } + else if (basename.find(".jpg") != std::string::npos) + { + if (isRGBA) CCLOG("RGBA is not supported for JPG format."); + return saveToFileAsNonPMA(filename, Image::Format::JPG, false, callback); + } + else + { + CCLOG("Only PNG and JPG format are supported now!"); + } + + return saveToFileAsNonPMA(filename, Image::Format::JPG, false, callback); +} + bool RenderTexture::saveToFile(const std::string& filename, bool isRGBA, std::function callback) { std::string basename(filename); @@ -528,6 +550,22 @@ bool RenderTexture::saveToFile(const std::string& filename, bool isRGBA, std::fu return saveToFile(filename, Image::Format::JPG, false, callback); } +bool RenderTexture::saveToFileAsNonPMA(const std::string& fileName, Image::Format format, bool isRGBA, std::function callback) +{ + CCASSERT(format == Image::Format::JPG || format == Image::Format::PNG, + "the image can only be saved as JPG or PNG format"); + if (isRGBA && format == Image::Format::JPG) CCLOG("RGBA is not supported for JPG format"); + + _saveFileCallback = callback; + + std::string fullpath = FileUtils::getInstance()->getWritablePath() + fileName; + _saveToFileCommand.init(_globalZOrder); + _saveToFileCommand.func = CC_CALLBACK_0(RenderTexture::onSaveToFile, this, fullpath, isRGBA, true); + + Director::getInstance()->getRenderer()->addCommand(&_saveToFileCommand); + return true; +} + bool RenderTexture::saveToFile(const std::string& fileName, Image::Format format, bool isRGBA, std::function callback) { CCASSERT(format == Image::Format::JPG || format == Image::Format::PNG, @@ -538,17 +576,21 @@ bool RenderTexture::saveToFile(const std::string& fileName, Image::Format format std::string fullpath = FileUtils::getInstance()->getWritablePath() + fileName; _saveToFileCommand.init(_globalZOrder); - _saveToFileCommand.func = CC_CALLBACK_0(RenderTexture::onSaveToFile, this, fullpath, isRGBA); + _saveToFileCommand.func = CC_CALLBACK_0(RenderTexture::onSaveToFile, this, fullpath, isRGBA, false); Director::getInstance()->getRenderer()->addCommand(&_saveToFileCommand); return true; } -void RenderTexture::onSaveToFile(const std::string& filename, bool isRGBA) +void RenderTexture::onSaveToFile(const std::string& filename, bool isRGBA, bool forceNonPMA) { Image *image = newImage(true); if (image) { + if (forceNonPMA && image->hasPremultipliedAlpha()) + { + image->reversePremultipliedAlpha(); + } image->saveToFile(filename, !isRGBA); } if(_saveFileCallback) @@ -620,11 +662,11 @@ Image* RenderTexture::newImage(bool flipImage) savedBufferWidth * 4); } - image->initWithRawData(buffer, savedBufferWidth * savedBufferHeight * 4, savedBufferWidth, savedBufferHeight, 8); + image->initWithRawData(buffer, savedBufferWidth * savedBufferHeight * 4, savedBufferWidth, savedBufferHeight, 8, true); } else { - image->initWithRawData(tempData, savedBufferWidth * savedBufferHeight * 4, savedBufferWidth, savedBufferHeight, 8); + image->initWithRawData(tempData, savedBufferWidth * savedBufferHeight * 4, savedBufferWidth, savedBufferHeight, 8, true); } } while (0); diff --git a/cocos/2d/CCRenderTexture.h b/cocos/2d/CCRenderTexture.h index 03a27ab334e4..771645501375 100644 --- a/cocos/2d/CCRenderTexture.h +++ b/cocos/2d/CCRenderTexture.h @@ -151,6 +151,17 @@ class CC_DLL RenderTexture : public Node CC_DEPRECATED_ATTRIBUTE Image* newCCImage(bool flipImage = true) { return newImage(flipImage); }; + /** Saves the texture into a file using JPEG format. The file will be saved in the Documents folder. + * Returns true if the operation is successful. + * + * @param filename The file name. + * @param isRGBA The file is RGBA or not. + * @param callback When the file is save finished,it will callback this function. + * @return Returns true if the operation is successful. + */ + bool saveToFileAsNonPMA(const std::string& filename, bool isRGBA = true, std::function callback = nullptr); + + /** Saves the texture into a file using JPEG format. The file will be saved in the Documents folder. * Returns true if the operation is successful. * @@ -161,6 +172,20 @@ class CC_DLL RenderTexture : public Node */ bool saveToFile(const std::string& filename, bool isRGBA = true, std::function callback = nullptr); + /** saves the texture into a file in non-PMA. The format could be JPG or PNG. The file will be saved in the Documents folder. + Returns true if the operation is successful. + * Notes: since v3.x, saveToFile will generate a custom command, which will be called in the following render->render(). + * So if this function is called in a event handler, the actual save file will be called in the next frame. If we switch to a different scene, the game will crash. + * To solve this, add Director::getInstance()->getRenderer()->render(); after this function. + * + * @param filename The file name. + * @param format The image format. + * @param isRGBA The file is RGBA or not. + * @param callback When the file is save finished,it will callback this function. + * @return Returns true if the operation is successful. + */ + bool saveToFileAsNonPMA(const std::string& fileName, Image::Format format, bool isRGBA, std::function callback); + /** saves the texture into a file. The format could be JPG or PNG. The file will be saved in the Documents folder. Returns true if the operation is successful. * Notes: since v3.x, saveToFile will generate a custom command, which will be called in the following render->render(). @@ -363,7 +388,7 @@ class CC_DLL RenderTexture : public Node void onClear(); void onClearDepth(); - void onSaveToFile(const std::string& fileName, bool isRGBA = true); + void onSaveToFile(const std::string& fileName, bool isRGBA = true, bool forceNonPMA = false); void setupDepthAndStencil(int powW, int powH); diff --git a/cocos/platform/CCImage.cpp b/cocos/platform/CCImage.cpp index 1ffb8e743462..eb01683400c0 100644 --- a/cocos/platform/CCImage.cpp +++ b/cocos/platform/CCImage.cpp @@ -1149,7 +1149,7 @@ bool Image::initWithPngData(const unsigned char * data, ssize_t dataLen) { if (PNG_PREMULTIPLIED_ALPHA_ENABLED) { - premultipliedAlpha(); + premultiplyAlpha(); } else { @@ -2454,7 +2454,7 @@ bool Image::saveImageToJPG(const std::string& filePath) #endif // CC_USE_JPEG } -void Image::premultipliedAlpha() +void Image::premultiplyAlpha() { #if CC_ENABLE_PREMULTIPLIED_ALPHA == 0 _hasPremultipliedAlpha = false; @@ -2473,6 +2473,29 @@ void Image::premultipliedAlpha() #endif } +static inline unsigned char clamp(int x) { + return (unsigned char)(x >= 0 ? (x < 255 ? x : 255) : 0); +} + +void Image::reversePremultipliedAlpha() +{ + CCASSERT(_renderFormat == Texture2D::PixelFormat::RGBA8888, "The pixel format should be RGBA8888!"); + + unsigned int* fourBytes = (unsigned int*)_data; + for (int i = 0; i < _width * _height; i++) + { + unsigned char* p = _data + i * 4; + if (p[3] > 0) + { + fourBytes[i] = clamp(int(std::ceil((p[0] * 255.0f) / p[3]))) | + clamp(int(std::ceil((p[1] * 255.0f) / p[3]))) << 8 | + clamp(int(std::ceil((p[2] * 255.0f) / p[3]))) << 16 | + p[3] << 24; + } + } + + _hasPremultipliedAlpha = false; +} void Image::setPVRImagesHavePremultipliedAlpha(bool haveAlphaPremultiplied) { diff --git a/cocos/platform/CCImage.h b/cocos/platform/CCImage.h index 6a7cebf20a53..a864944905fb 100644 --- a/cocos/platform/CCImage.h +++ b/cocos/platform/CCImage.h @@ -160,6 +160,8 @@ class CC_DLL Image : public Ref @param isToRGB whether the image is saved as RGB format. */ bool saveToFile(const std::string &filename, bool isToRGB = true); + void premultiplyAlpha(); + void reversePremultipliedAlpha(); protected: #if CC_USE_WIC @@ -182,8 +184,6 @@ class CC_DLL Image : public Ref bool saveImageToPNG(const std::string& filePath, bool isToRGB = true); bool saveImageToJPG(const std::string& filePath); - void premultipliedAlpha(); - protected: /** @brief Determine how many mipmaps can we have. diff --git a/cocos/platform/ios/CCImage-ios.mm b/cocos/platform/ios/CCImage-ios.mm index baad43f45aea..da0f1f7548fe 100644 --- a/cocos/platform/ios/CCImage-ios.mm +++ b/cocos/platform/ios/CCImage-ios.mm @@ -91,7 +91,14 @@ of this software and associated documentation files (the "Software"), to deal CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault; if (saveToPNG && hasAlpha() && (! isToRGB)) { - bitmapInfo |= kCGImageAlphaPremultipliedLast; + if (_hasPremultipliedAlpha) + { + bitmapInfo |= kCGImageAlphaPremultipliedLast; + } + else + { + bitmapInfo |= kCGImageAlphaLast; + } } CGDataProviderRef provider = CGDataProviderCreateWithData(nullptr, pixels, myDataLength, nullptr); CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); diff --git a/tests/cpp-tests/Classes/RenderTextureTest/RenderTextureTest.cpp b/tests/cpp-tests/Classes/RenderTextureTest/RenderTextureTest.cpp index da772b0dfd55..d2775645c2e4 100644 --- a/tests/cpp-tests/Classes/RenderTextureTest/RenderTextureTest.cpp +++ b/tests/cpp-tests/Classes/RenderTextureTest/RenderTextureTest.cpp @@ -62,12 +62,15 @@ RenderTextureSave::RenderTextureSave() // Save Image menu MenuItemFont::setFontSize(16); - auto item1 = MenuItemFont::create("Save Image", CC_CALLBACK_1(RenderTextureSave::saveImage, this)); - auto item2 = MenuItemFont::create("Clear", CC_CALLBACK_1(RenderTextureSave::clearImage, this)); - auto menu = Menu::create(item1, item2, nullptr); + auto item1 = MenuItemFont::create("Save Image PMA", CC_CALLBACK_1(RenderTextureSave::saveImageWithPremultipliedAlpha, this)); + auto item2 = MenuItemFont::create("Save Image Non-PMA", CC_CALLBACK_1(RenderTextureSave::saveImageWithNonPremultipliedAlpha, this)); + auto item3 = MenuItemFont::create("Add Image", CC_CALLBACK_1(RenderTextureSave::addImage, this)); + auto item4 = MenuItemFont::create("Clear to Random", CC_CALLBACK_1(RenderTextureSave::clearImage, this)); + auto item5 = MenuItemFont::create("Clear to Transparent", CC_CALLBACK_1(RenderTextureSave::clearImageTransparent, this)); + auto menu = Menu::create(item1, item2, item3, item4, item5, nullptr); this->addChild(menu); menu->alignItemsVertically(); - menu->setPosition(Vec2(VisibleRect::rightTop().x - 80, VisibleRect::rightTop().y - 30)); + menu->setPosition(Vec2(VisibleRect::rightTop().x - 80, VisibleRect::rightTop().y - 100)); } std::string RenderTextureSave::title() const @@ -80,17 +83,46 @@ std::string RenderTextureSave::subtitle() const return "Press 'Save Image' to create an snapshot of the render texture"; } -void RenderTextureSave::clearImage(cocos2d::Ref *sender) +void RenderTextureSave::clearImage(cocos2d::Ref* sender) { _target->clear(CCRANDOM_0_1(), CCRANDOM_0_1(), CCRANDOM_0_1(), CCRANDOM_0_1()); } -void RenderTextureSave::saveImage(cocos2d::Ref *sender) +void RenderTextureSave::clearImageTransparent(cocos2d::Ref* sender) +{ + _target->clear(0, 0, 0, 0); +} + +void RenderTextureSave::saveImageWithPremultipliedAlpha(cocos2d::Ref* sender) +{ + static int counter = 0; + + char png[20]; + sprintf(png, "image-pma-%d.png", counter); + + auto callback = [&](RenderTexture* rt, const std::string& path) + { + auto sprite = Sprite::create(path); + addChild(sprite); + sprite->setScale(0.3f); + sprite->setPosition(Vec2(40, 40)); + sprite->setRotation(counter * 3); + }; + + _target->saveToFile(png, Image::Format::PNG, true, callback); + //Add this function to avoid crash if we switch to a new scene. + Director::getInstance()->getRenderer()->render(); + CCLOG("Image saved %s", png); + + counter++; +} + +void RenderTextureSave::saveImageWithNonPremultipliedAlpha(cocos2d::Ref *sender) { static int counter = 0; char png[20]; - sprintf(png, "image-%d.png", counter); + sprintf(png, "image-no-pma-%d.png", counter); auto callback = [&](RenderTexture* rt, const std::string& path) { @@ -101,7 +133,7 @@ void RenderTextureSave::saveImage(cocos2d::Ref *sender) sprite->setRotation(counter * 3); }; - _target->saveToFile(png, Image::Format::PNG, true, callback); + _target->saveToFileAsNonPMA(png, Image::Format::PNG, true, callback); //Add this function to avoid crash if we switch to a new scene. Director::getInstance()->getRenderer()->render(); CCLOG("Image saved %s", png); @@ -109,6 +141,21 @@ void RenderTextureSave::saveImage(cocos2d::Ref *sender) counter++; } +void RenderTextureSave::addImage(cocos2d::Ref* sender) +{ + auto s = Director::getInstance()->getWinSize(); + + // begin drawing to the render texture + _target->begin(); + + Sprite* sprite = Sprite::create("Images/test-rgba1.png"); + sprite->setPosition(sprite->getContentSize().width + CCRANDOM_0_1() * (s.width - sprite->getContentSize().width), sprite->getContentSize().height + CCRANDOM_0_1() * (s.height - sprite->getContentSize().height)); + sprite->visit(); + + // finish drawing and return context back to the screen + _target->end(); +} + RenderTextureSave::~RenderTextureSave() { _target->release(); @@ -849,4 +896,4 @@ std::string RenderTextureWithSprite3DIssue16894::title() const std::string RenderTextureWithSprite3DIssue16894::subtitle() const { return "3 ships, 1st & 3rd are the same"; -} +} \ No newline at end of file diff --git a/tests/cpp-tests/Classes/RenderTextureTest/RenderTextureTest.h b/tests/cpp-tests/Classes/RenderTextureTest/RenderTextureTest.h index 8d0940037b76..591e5ff8ff9c 100644 --- a/tests/cpp-tests/Classes/RenderTextureTest/RenderTextureTest.h +++ b/tests/cpp-tests/Classes/RenderTextureTest/RenderTextureTest.h @@ -44,7 +44,11 @@ class RenderTextureSave : public RenderTextureTest virtual std::string subtitle() const override; void onTouchesMoved(const std::vector& touches, cocos2d::Event* event); void clearImage(cocos2d::Ref* pSender); - void saveImage(cocos2d::Ref* pSender); + void clearImageTransparent(cocos2d::Ref* sender); + void saveImageWithPremultipliedAlpha(cocos2d::Ref* pSender); + void saveImageWithNonPremultipliedAlpha(cocos2d::Ref* pSender); + + void addImage(cocos2d::Ref* sender); private: cocos2d::RenderTexture* _target; From b5bdada7e2be3a87ba950c2c29756c06f0117ba3 Mon Sep 17 00:00:00 2001 From: rh101 Date: Tue, 4 Jun 2019 16:02:39 +1000 Subject: [PATCH 2/4] [CCImage-ios.mm] Fixed indentation. --- cocos/platform/ios/CCImage-ios.mm | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cocos/platform/ios/CCImage-ios.mm b/cocos/platform/ios/CCImage-ios.mm index da0f1f7548fe..ac6b04ed3f0b 100644 --- a/cocos/platform/ios/CCImage-ios.mm +++ b/cocos/platform/ios/CCImage-ios.mm @@ -91,14 +91,14 @@ of this software and associated documentation files (the "Software"), to deal CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault; if (saveToPNG && hasAlpha() && (! isToRGB)) { - if (_hasPremultipliedAlpha) - { - bitmapInfo |= kCGImageAlphaPremultipliedLast; - } - else - { - bitmapInfo |= kCGImageAlphaLast; - } + if (_hasPremultipliedAlpha) + { + bitmapInfo |= kCGImageAlphaPremultipliedLast; + } + else + { + bitmapInfo |= kCGImageAlphaLast; + } } CGDataProviderRef provider = CGDataProviderCreateWithData(nullptr, pixels, myDataLength, nullptr); CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); From c713c383d8fd4f9a9a0c9114eb309ca86045b0dd Mon Sep 17 00:00:00 2001 From: rh101 Date: Sun, 23 Jun 2019 02:44:15 +1000 Subject: [PATCH 3/4] Added support for interface-only libraries being linked to application via target_link_libraries. Certain library properties cannot be accessed if it is an interface only library, so we need to check if they are valid library types before accessing those properties. --- cmake/Modules/CocosBuildHelpers.cmake | 42 +++++++++++++++++---------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/cmake/Modules/CocosBuildHelpers.cmake b/cmake/Modules/CocosBuildHelpers.cmake index 3758b49f1ff6..29e8b63ec8fd 100644 --- a/cmake/Modules/CocosBuildHelpers.cmake +++ b/cmake/Modules/CocosBuildHelpers.cmake @@ -57,17 +57,23 @@ function(search_depend_libs_recursive cocos_target all_depends_out) set(targets_prepare_search ${cocos_target}) while(true) foreach(tmp_target ${targets_prepare_search}) - get_target_property(tmp_depend_libs ${tmp_target} LINK_LIBRARIES) - list(REMOVE_ITEM targets_prepare_search ${tmp_target}) - list(APPEND tmp_depend_libs ${tmp_target}) - foreach(depend_lib ${tmp_depend_libs}) - if(TARGET ${depend_lib}) - list(APPEND all_depends_inner ${depend_lib}) - if(NOT (depend_lib STREQUAL tmp_target)) - list(APPEND targets_prepare_search ${depend_lib}) - endif() - endif() - endforeach() + get_target_property(target_type ${tmp_target} TYPE) + if(${target_type} STREQUAL "SHARED_LIBRARY" OR ${target_type} STREQUAL "STATIC_LIBRARY" OR ${target_type} STREQUAL "MODULE_LIBRARY" OR ${target_type} STREQUAL "EXECUTABLE") + #interface-only libraries do not support certain properties such as LINK_LIBRARIES + get_target_property(tmp_depend_libs ${tmp_target} LINK_LIBRARIES) + list(REMOVE_ITEM targets_prepare_search ${tmp_target}) + list(APPEND tmp_depend_libs ${tmp_target}) + foreach(depend_lib ${tmp_depend_libs}) + if(TARGET ${depend_lib}) + list(APPEND all_depends_inner ${depend_lib}) + if(NOT (depend_lib STREQUAL tmp_target)) + list(APPEND targets_prepare_search ${depend_lib}) + endif() + endif() + endforeach() + else() + list(REMOVE_ITEM targets_prepare_search ${tmp_target}) + endif() endforeach() list(LENGTH targets_prepare_search targets_prepare_search_size) if(targets_prepare_search_size LESS 1) @@ -85,11 +91,15 @@ function(get_target_depends_ext_dlls cocos_target all_depend_dlls_out) search_depend_libs_recursive(${cocos_target} depend_libs) foreach(depend_lib ${depend_libs}) if(TARGET ${depend_lib}) - get_target_property(found_shared_lib ${depend_lib} IMPORTED_IMPLIB) - if(found_shared_lib) - get_target_property(tmp_dlls ${depend_lib} IMPORTED_LOCATION) - list(APPEND all_depend_ext_dlls ${tmp_dlls}) - endif() + get_target_property(target_type ${depend_lib} TYPE) + if(${target_type} STREQUAL "SHARED_LIBRARY" OR ${target_type} STREQUAL "STATIC_LIBRARY" OR ${target_type} STREQUAL "MODULE_LIBRARY" OR ${target_type} STREQUAL "EXECUTABLE") + #interface-only libraries do not support certain properties such as IMPORTED_IMPLIB + get_target_property(found_shared_lib ${depend_lib} IMPORTED_IMPLIB) + if(found_shared_lib) + get_target_property(tmp_dlls ${depend_lib} IMPORTED_LOCATION) + list(APPEND all_depend_ext_dlls ${tmp_dlls}) + endif() + endif() endif() endforeach() From 2ecf8cf3e51098e614352f4a397134e0874a59fb Mon Sep 17 00:00:00 2001 From: rh101 Date: Sun, 23 Jun 2019 03:10:48 +1000 Subject: [PATCH 4/4] Fixed formatting. --- cmake/Modules/CocosBuildHelpers.cmake | 52 +++++++++++++-------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/cmake/Modules/CocosBuildHelpers.cmake b/cmake/Modules/CocosBuildHelpers.cmake index 29e8b63ec8fd..6139fd8384bb 100644 --- a/cmake/Modules/CocosBuildHelpers.cmake +++ b/cmake/Modules/CocosBuildHelpers.cmake @@ -57,23 +57,23 @@ function(search_depend_libs_recursive cocos_target all_depends_out) set(targets_prepare_search ${cocos_target}) while(true) foreach(tmp_target ${targets_prepare_search}) - get_target_property(target_type ${tmp_target} TYPE) - if(${target_type} STREQUAL "SHARED_LIBRARY" OR ${target_type} STREQUAL "STATIC_LIBRARY" OR ${target_type} STREQUAL "MODULE_LIBRARY" OR ${target_type} STREQUAL "EXECUTABLE") - #interface-only libraries do not support certain properties such as LINK_LIBRARIES - get_target_property(tmp_depend_libs ${tmp_target} LINK_LIBRARIES) - list(REMOVE_ITEM targets_prepare_search ${tmp_target}) - list(APPEND tmp_depend_libs ${tmp_target}) - foreach(depend_lib ${tmp_depend_libs}) - if(TARGET ${depend_lib}) - list(APPEND all_depends_inner ${depend_lib}) - if(NOT (depend_lib STREQUAL tmp_target)) - list(APPEND targets_prepare_search ${depend_lib}) - endif() - endif() - endforeach() - else() - list(REMOVE_ITEM targets_prepare_search ${tmp_target}) - endif() + get_target_property(target_type ${tmp_target} TYPE) + if(${target_type} STREQUAL "SHARED_LIBRARY" OR ${target_type} STREQUAL "STATIC_LIBRARY" OR ${target_type} STREQUAL "MODULE_LIBRARY" OR ${target_type} STREQUAL "EXECUTABLE") + #interface-only libraries do not support certain properties such as LINK_LIBRARIES + get_target_property(tmp_depend_libs ${tmp_target} LINK_LIBRARIES) + list(REMOVE_ITEM targets_prepare_search ${tmp_target}) + list(APPEND tmp_depend_libs ${tmp_target}) + foreach(depend_lib ${tmp_depend_libs}) + if(TARGET ${depend_lib}) + list(APPEND all_depends_inner ${depend_lib}) + if(NOT (depend_lib STREQUAL tmp_target)) + list(APPEND targets_prepare_search ${depend_lib}) + endif() + endif() + endforeach() + else() + list(REMOVE_ITEM targets_prepare_search ${tmp_target}) + endif() endforeach() list(LENGTH targets_prepare_search targets_prepare_search_size) if(targets_prepare_search_size LESS 1) @@ -91,15 +91,15 @@ function(get_target_depends_ext_dlls cocos_target all_depend_dlls_out) search_depend_libs_recursive(${cocos_target} depend_libs) foreach(depend_lib ${depend_libs}) if(TARGET ${depend_lib}) - get_target_property(target_type ${depend_lib} TYPE) - if(${target_type} STREQUAL "SHARED_LIBRARY" OR ${target_type} STREQUAL "STATIC_LIBRARY" OR ${target_type} STREQUAL "MODULE_LIBRARY" OR ${target_type} STREQUAL "EXECUTABLE") - #interface-only libraries do not support certain properties such as IMPORTED_IMPLIB - get_target_property(found_shared_lib ${depend_lib} IMPORTED_IMPLIB) - if(found_shared_lib) - get_target_property(tmp_dlls ${depend_lib} IMPORTED_LOCATION) - list(APPEND all_depend_ext_dlls ${tmp_dlls}) - endif() - endif() + get_target_property(target_type ${depend_lib} TYPE) + if(${target_type} STREQUAL "SHARED_LIBRARY" OR ${target_type} STREQUAL "STATIC_LIBRARY" OR ${target_type} STREQUAL "MODULE_LIBRARY" OR ${target_type} STREQUAL "EXECUTABLE") + #interface-only libraries do not support certain properties such as IMPORTED_IMPLIB + get_target_property(found_shared_lib ${depend_lib} IMPORTED_IMPLIB) + if(found_shared_lib) + get_target_property(tmp_dlls ${depend_lib} IMPORTED_LOCATION) + list(APPEND all_depend_ext_dlls ${tmp_dlls}) + endif() + endif() endif() endforeach()