cocos2d-x 不规则触摸解决方案
.h
#ifndef __UI_BUTTON_PIXEL_H__ #define __UI_BUTTON_PIXEL_H__ 1 #include <iostream> #include <string> #include <string.h> using namespace std; #include <cocos2d.h> #include <ui/CocosGUI.h> class CC_GUI_DLL UIButton_pixel : public cocos2d::ui::Button { bool isPixelTouch; ccWidgetTouchCallback m_ccWidgetTouchCallback; cocos2d::Image *m_Image; public: UIButton_pixel(); ~UIButton_pixel(); static UIButton_pixel* create(const std::string& normalImage, const std::string& selectedImage = "", const std::string& disableImage = "", TextureResType texType = TextureResType::LOCAL); void setPixelTouch(bool is); void addPixelTouchEventListener_s(const ccWidgetTouchCallback& callback); private: //获取图片内的左边 cocos2d::Vec2 getTouchImagePosition(cocos2d::Vec2 &TouchEndPos); // bool indexPixelLogic(cocos2d::Vec2 &pos); }; #endif // !__UI_BUTTON_PIXEL_H__
.cpp
#include "UIButton_pixel.h" UIButton_pixel::UIButton_pixel() :isPixelTouch(false), m_Image(nullptr) { } UIButton_pixel::~UIButton_pixel() { if (m_Image) { delete m_Image; m_Image = nullptr; } } UIButton_pixel* UIButton_pixel::create(const std::string& normalImage, const std::string& selectedImage, const std::string& disableImage, TextureResType texType) { UIButton_pixel *btn = new (std::nothrow) UIButton_pixel; if (btn && btn->init(normalImage, selectedImage, disableImage, texType)) { btn->autorelease(); return btn; } CC_SAFE_DELETE(btn); return btn; } void UIButton_pixel::setPixelTouch(bool is) { isPixelTouch = is; } void UIButton_pixel::addPixelTouchEventListener_s(const ccWidgetTouchCallback& callback) { if (m_ccWidgetTouchCallback) { return; } m_ccWidgetTouchCallback = callback; static ccWidgetTouchCallback tmp = [&](Ref *ref, cocos2d::ui::Widget::TouchEventType e) { if (isPixelTouch && m_ccWidgetTouchCallback && e == cocos2d::ui::Widget::TouchEventType::ENDED) { auto b_pos = this->getTouchBeganPosition(); auto e_pos = this->getTouchEndPosition(); auto pos = this->getWorldPosition(); cocos2d::log("=============\n\ pos(%f,%f) \nb_pos(%f,%f) \ne_pos(%f,%f)\n\ ============ = \n", pos.x, pos.y, b_pos.x, b_pos.y, e_pos.x, e_pos.y); auto imagePos = this->getTouchImagePosition(e_pos); if (this->indexPixelLogic(imagePos)) { m_ccWidgetTouchCallback(ref, e); } } }; this->addTouchEventListener(tmp); } cocos2d::Vec2 UIButton_pixel::getTouchImagePosition(cocos2d::Vec2 &TouchEndPos) { auto size = this->getContentSize(); auto ret = cocos2d::Vec2::ZERO; auto worldPosition = this->getWorldPosition(); auto anchorPoint = this->getAnchorPoint(); auto offset = worldPosition - TouchEndPos; /** equals to Vec2(0.5, 0.5) */ if (anchorPoint == cocos2d::Vec2::ANCHOR_MIDDLE) { ret = cocos2d::Vec2(size.width * 0.5f - offset.x, size.height * 0.5f + offset.y); } /** equals to Vec2(0, 0) */ else if (anchorPoint == cocos2d::Vec2::ANCHOR_BOTTOM_LEFT) { ret = cocos2d::Vec2(-(offset.x), size.height + offset.y); } /** equals to Vec2(0, 1) */ else if (anchorPoint == cocos2d::Vec2::ANCHOR_TOP_LEFT) { ret = cocos2d::Vec2(-(offset.x), +offset.y); } /** equals to Vec2(1, 0) */ else if (anchorPoint == cocos2d::Vec2::ANCHOR_BOTTOM_RIGHT) { ret = cocos2d::Vec2(size.width - offset.x, size.height + offset.y); } /** equals to Vec2(1, 1) */ else if (anchorPoint == cocos2d::Vec2::ANCHOR_TOP_RIGHT) { ret = cocos2d::Vec2(size.width - offset.x, +offset.y); } /** equals to Vec2(1, 0.5) */ else if (anchorPoint == cocos2d::Vec2::ANCHOR_MIDDLE_RIGHT) { ret = cocos2d::Vec2(size.width - offset.x, size.height * 0.5f + offset.y); } /** equals to Vec2(0, 0.5) */ else if (anchorPoint == cocos2d::Vec2::ANCHOR_MIDDLE_LEFT) { ret = cocos2d::Vec2(-(offset.x), size.height * 0.5f + offset.y); } /** equals to Vec2(0.5, 1) */ else if (anchorPoint == cocos2d::Vec2::ANCHOR_MIDDLE_TOP) { ret = cocos2d::Vec2(size.width * 0.5f - offset.x, offset.y); } /** equals to Vec2(0.5, 0) */ else if (anchorPoint == cocos2d::Vec2::ANCHOR_MIDDLE_BOTTOM) { ret = cocos2d::Vec2(size.width * 0.5f - offset.x, size.height + offset.y); } else { cocos2d::log("anchorPoint error \n"); return ret = cocos2d::Vec2(-1, -1); } return ret; } bool UIButton_pixel::indexPixelLogic(cocos2d::Vec2 &pos) { auto texture = this->getRendererNormal()->getTexture(); auto size = cocos2d::Size(texture->getPixelsWide(), texture->getPixelsHigh()); if (pos != cocos2d::Vec2(-1, -1) && pos.x <= size.width &&pos.y <= size.height) { std::cout << " pixel pos : " << pos.x << " " << pos.y << std::endl; auto path = texture->getPath(); if (!m_Image) { m_Image = new (std::nothrow) cocos2d::Image(); } if (m_Image) { auto b = m_Image->initWithImageFile(path); if (b && m_Image->getRenderFormat() == cocos2d::Texture2D::PixelFormat::RGBA8888) { auto data = m_Image->getData(); auto dataLen = m_Image->getDataLen(); if ((int)(size.width * size.height * 4) == dataLen) { auto offsetPixel = (int)(((int)(pos.y) * size.width + (int)(pos.x))); auto rgba = data + offsetPixel * 4; int r = (unsigned char)rgba[0]; int g = (unsigned char)rgba[1]; int b = (unsigned char)rgba[2]; int a = (unsigned char)rgba[3]; printf("R: %d G: %d B: %d A: %d\n", r, g, b, a); if (a == 255) { return true; } } } } } return false; }
tolua.cpp
#include "lua_cocos2d_Ex.h" #include <iostream> #include "cocos2d.h" using namespace cocos2d; #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS) && !defined(CC_TARGET_OS_TVOS) #include "scripting/lua-bindings/auto/lua_cocos2dx_experimental_video_auto.hpp" #include "scripting/lua-bindings/manual/ui/lua_cocos2dx_experimental_video_manual.hpp" #include "scripting/lua-bindings/auto/lua_cocos2dx_experimental_webview_auto.hpp" #include "scripting/lua-bindings/manual/ui/lua_cocos2dx_experimental_webview_manual.hpp" #endif #include "scripting/lua-bindings/manual/tolua_fix.h" #include "scripting/lua-bindings/manual/LuaBasicConversions.h" #include "scripting/lua-bindings/manual/cocos2d/LuaScriptHandlerMgr.h" #include "scripting/lua-bindings/manual/CCLuaValue.h" #include "ui/CocosGUI.h" #include "scripting/lua-bindings/manual/CCLuaEngine.h" #include "base/CCEventListenerFocus.h" #include "UIButton_pixel.h" static int handleUIEvent(int handler, cocos2d::Ref* sender, int eventType) { LuaStack* stack = LuaEngine::getInstance()->getLuaStack(); stack->pushObject(sender, "cc.Ref"); stack->pushInt(eventType); stack->executeFunctionByHandler(handler, 2); stack->clean(); return 0; } int lua_cocos2d_Ex_create(lua_State *tolua_S) { int argc = 0; //UIButton_pixel* cobj = nullptr; bool ok = true; #if COCOS2D_DEBUG >= 1 tolua_Error tolua_err; #endif //cobj = (UIButton_pixel*)tolua_tousertype(tolua_S, 1, 0); #if COCOS2D_DEBUG >= 1 if (!tolua_isusertable(tolua_S, 1, "ccui.UIButton_pixel", 0, &tolua_err)) goto tolua_lerror; #endif argc = lua_gettop(tolua_S) - 1; if (argc == 4) { std::string arg0, arg1, arg2; int arg3; ok &= luaval_to_std_string(tolua_S, 2, &arg0, "ccui.UIButton_pixel:create"); if (!ok) { tolua_error(tolua_S, "invalid arguments in function 'lua_cocos2d_Ex_create'", nullptr); return 0; } ok &= luaval_to_std_string(tolua_S, 3, &arg1, "ccui.UIButton_pixel:create"); if (!ok) { tolua_error(tolua_S, "invalid arguments in function 'lua_cocos2d_Ex_create'", nullptr); return 0; } ok &= luaval_to_std_string(tolua_S, 4, &arg2, "ccui.UIButton_pixel:create"); if (!ok) { tolua_error(tolua_S, "invalid arguments in function 'lua_cocos2d_Ex_create'", nullptr); return 0; } ok &= luaval_to_int32(tolua_S, 5, &arg3, "ccui.UIButton_pixel:create"); if (!ok) { tolua_error(tolua_S, "invalid arguments in function 'lua_cocos2d_Ex_create'", nullptr); return 0; } UIButton_pixel *ret = UIButton_pixel::create(arg0, arg1, arg2, (cocos2d::ui::TextureResType)arg3); object_to_luaval<UIButton_pixel>(tolua_S, "ccui.UIButton_pixel", (UIButton_pixel*)ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ccui.UIButton_pixel:create", argc, 0); return 0; #if COCOS2D_DEBUG >= 1 tolua_lerror: tolua_error(tolua_S, "#ferror in function 'lua_cocos2d_Ex_create'.", &tolua_err); #endif return 0; } int lua_cocos2d_Ex_setPixelTouch(lua_State *tolua_S) { int argc = 0; UIButton_pixel* cobj = nullptr; bool ok = true; #if COCOS2D_DEBUG >= 1 tolua_Error tolua_err; #endif cobj = (UIButton_pixel*)tolua_tousertype(tolua_S, 1, 0); #if COCOS2D_DEBUG >= 1 if (!tolua_isusertable(tolua_S, 1, "ccui.UIButton_pixel", 0, &tolua_err)) goto tolua_lerror; #endif #if COCOS2D_DEBUG >= 1 if (nullptr == self) { tolua_error(L, "invalid 'self' in function 'lua_cocos2d_Ex_setPixelTouch'\n", NULL); return 0; } #endif argc = lua_gettop(tolua_S) - 1; if (argc == 1) { bool arg0; ok &= luaval_to_boolean(tolua_S, 2, &arg0, "ccui.UIButton_pixel:setPixelTouch"); if (!ok) { tolua_error(tolua_S, "invalid arguments in function 'lua_cocos2d_Ex_setPixelTouch'", nullptr); return 0; } cobj->setPixelTouch(arg0); return 0; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ccui.UIButton_pixel:setPixelTouch", argc, 0); return 0; #if COCOS2D_DEBUG >= 1 tolua_lerror: tolua_error(tolua_S, "#ferror in function 'lua_cocos2d_Ex_setPixelTouch'.", &tolua_err); #endif return 0; } int lua_cocos2d_Ex_addPixelTouchEventListener_s(lua_State *tolua_S) { int argc = 0; UIButton_pixel* cobj = nullptr; bool ok = true; #if COCOS2D_DEBUG >= 1 tolua_Error tolua_err; #endif cobj = (UIButton_pixel*)tolua_tousertype(tolua_S, 1, 0); #if COCOS2D_DEBUG >= 1 if (!tolua_isusertable(tolua_S, 1, "ccui.UIButton_pixel", 0, &tolua_err)) goto tolua_lerror; #endif #if COCOS2D_DEBUG >= 1 if (nullptr == self) { tolua_error(L, "invalid 'self' in function 'lua_cocos2d_Ex_addPixelTouchEventListener_s'\n", NULL); return 0; } #endif argc = lua_gettop(tolua_S) - 1; if (argc == 1) { #if COCOS2D_DEBUG >= 1 if (!toluafix_isfunction(L, 2, "LUA_FUNCTION", 0, &tolua_err)) { goto tolua_lerror; } #endif LUA_FUNCTION handler = (toluafix_ref_function(tolua_S, 2, 0)); cobj->addPixelTouchEventListener_s([=](cocos2d::Ref* ref, cocos2d::ui::Widget::TouchEventType eventType) { handleUIEvent(handler, ref, (int)eventType); }); ScriptHandlerMgr::getInstance()->addCustomHandler((void*)cobj, handler); return 0; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ccui.UIButton_pixel:addPixelTouchEventListener_s", argc, 0); return 0; #if COCOS2D_DEBUG >= 1 tolua_lerror: tolua_error(tolua_S, "#ferror in function 'lua_cocos2d_Ex_addPixelTouchEventListener_s'.", &tolua_err); #endif return 0; } int lua_register_cocos2d_Ex(lua_State* tolua_S) { tolua_usertype(tolua_S, "ccui.UIButton_pixel"); tolua_cclass(tolua_S, "UIButton_pixel", "ccui.UIButton_pixel", "ccui.Button", nullptr); tolua_beginmodule(tolua_S, "UIButton_pixel"); if (true) { tolua_function(tolua_S, "create", lua_cocos2d_Ex_create); tolua_function(tolua_S, "setPixelTouch", lua_cocos2d_Ex_setPixelTouch); tolua_function(tolua_S, "addPixelTouchEventListener_s", lua_cocos2d_Ex_addPixelTouchEventListener_s); } tolua_endmodule(tolua_S); std::string typeName = typeid(UIButton_pixel).name(); g_luaType[typeName] = "ccui.UIButton_pixel"; g_typeCast["UIButton_pixel"] = "ccui.UIButton_pixel"; return 1; } int register_cocos2d_Ex(lua_State* tolua_S) { tolua_open(tolua_S); tolua_module(tolua_S, "ccui", 0); tolua_beginmodule(tolua_S, "ccui"); lua_register_cocos2d_Ex(tolua_S); tolua_endmodule(tolua_S); return 1; } int lua_cocos2d_Ex(lua_State* L) { lua_getglobal(L, "_G"); if (lua_istable(L, -1)) { register_cocos2d_Ex(L); if (L) { lua_pushstring(L, "ccui.UIButton_pixel"); lua_rawget(L, LUA_REGISTRYINDEX); lua_pop(L, 1); } } lua_pop(L, 1); return 0; }
test
local filename = "res/GameList/GameAni/_12/skeleton.png" local btn = ccui.UIButton_pixel:create(filename,filename,filename,0) btn:setPixelTouch(true) btn:addPixelTouchEventListener_s(function(ref,type) print("UIButton_pixel touch"); end) btn:setPosition(display.center) self:addChild(btn)