IAPCtlShopUI.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. //
  2. // IAPCtlShopUI.cpp
  3. // TileManor
  4. //
  5. // Created by 徐炼新 on 2024/1/16.
  6. //
  7. #include "IAPCtlShop.hpp"
  8. #include "RUUtils.h"
  9. #include "RUPlatform.h"
  10. #include "IAPConf.hpp"
  11. #include "IAPCtlShopUI.hpp"
  12. #include "IAPCtlShopItem.hpp"
  13. #include <regex>
  14. IAPCtlShopUI* IAPCtlShopUI::_instance = nullptr;
  15. IAPCtlShopUI* IAPCtlShopUI::getInstance() {
  16. if (_instance == nullptr) {
  17. _instance = new IAPCtlShopUI();
  18. _instance->autorelease();
  19. _instance->retain();
  20. }
  21. return _instance;
  22. }
  23. IAPCtlShopUI::IAPCtlShopUI() {
  24. }
  25. IAPCtlShopUI::~IAPCtlShopUI() {
  26. }
  27. bool IAPCtlShopUI::isShowing() {
  28. return _bUIShowing;
  29. }
  30. void IAPCtlShopUI::clear() {
  31. _goodsInfo.clear();
  32. for (auto& gi : _goodsItems) {
  33. gi->release();
  34. }
  35. _goodsItems.clear();
  36. _allSizes.clear();
  37. _cb = nullptr;
  38. }
  39. bool IAPCtlShopUI::create(Node* pNode, IAPConf* cfg, iap::ShopRequirement& requirement,int placementId) {
  40. redutils::Platform::getInstance()->reportLog("open iap");
  41. _cfg = cfg;
  42. _bUIShowing = true;
  43. _placementId = placementId;
  44. clear();
  45. _layer = redutils::RUReboltLayer::createReboltLayer("shop_interface.redream");
  46. pNode->addChild(_layer, 3);
  47. _layer->registerOnNotify([this](const redutils::ReboltNotifyData& data){
  48. _onNotifyDevelopment(data);
  49. });
  50. _layer->runBehaviacWhitFunName("初始化");
  51. // _igCoin->doOwnInit();
  52. if (_goodsInfo.size() == 0) {
  53. IAPConf::getInstance()->getAllGoods(_goodsInfo);
  54. }
  55. // 过滤掉不符合的金币
  56. filterGoods(requirement);
  57. // 构建 list 区域
  58. constructShopItem(false);
  59. cocos2d::Size size = _ndScrollArea->getContentSize();
  60. _tableView = redutils::RUTableView::create(&_tableData, cocos2d::Size(size.width, size.height));
  61. _tableView->setCascadeOpacityEnabled(true);
  62. _tableView->setCascadeColorEnabled(true);
  63. _tableView->setDirection(ScrollViewSmooth::Direction::VERTICAL);
  64. _tableView->setVerticalFillOrder(TableViewSmooth::VerticalFillOrder::TOP_DOWN, false);
  65. _tableView->setDelegate(&_tableData);
  66. _tableView->setBounceable(true);
  67. // _tableView->setOutSightClean(false);
  68. _ndScrollArea->addChild(_tableView);
  69. return true;
  70. }
  71. bool IAPCtlShopUI::addAPlacement(const iap::IAPPlacement &plInfo){
  72. // 如果该活动ID存在,则添加失败
  73. if(_placements.count(plInfo.id) != 0)return false;
  74. _placements[plInfo.id] = plInfo;
  75. return true;
  76. }
  77. void IAPCtlShopUI::removePlacement(const std::string &id){
  78. _placements.erase(id);
  79. }
  80. void IAPCtlShopUI::clearPlacement(){
  81. _placements.clear();
  82. }
  83. size_t IAPCtlShopUI::getPlacementCount(){
  84. return _placements.size();
  85. }
  86. void IAPCtlShopUI::_onNotifyDevelopment(const redutils::ReboltNotifyData& data) {
  87. if (data.notify == "绑定显示区域") {
  88. _ndScrollArea = data.outNode;
  89. } else if (data.notify == "绑定coin节点") {
  90. // _igCoin = new MapIGCoin(data.reboltRedManager);
  91. } else if (data.notify == "退出") {
  92. auto rm = RemoveSelf::create();
  93. auto cf = CallFunc::create([=]() {
  94. _layer->removeFromParent();
  95. _layer = nullptr;
  96. _bUIShowing = false;
  97. redutils::Platform::getInstance()->reportLog("iap closed");
  98. });
  99. _layer->runAction(Sequence::create(rm, cf, NULL));
  100. if (_cb) {
  101. _cb();
  102. }
  103. _cb = nullptr;
  104. }
  105. }
  106. void IAPCtlShopUI::constructShopItem(bool bShowAll) {
  107. int index = 0;
  108. _tableData.setCascadeOpacity(true);
  109. _tableData.clear();
  110. cocos2d::Size size = _ndScrollArea->getContentSize();
  111. auto delayIdx = 0;
  112. cocos2d::Vec2 offset(size.width, 0);
  113. float dur = 0.4;
  114. int height = 0;
  115. // 加入一个表头
  116. {
  117. Node* nd = Node::create();
  118. _tableData.insertCell(index++, nd);
  119. int h = size.height*0.08;
  120. _allSizes.push_back(cocos2d::Size(size.width, h));
  121. height += h;
  122. }
  123. // 重新获取
  124. if(bShowAll)IAPConf::getInstance()->getAllGoods(_goodsInfo);
  125. // 根据用户类型进行礼包排序
  126. switch (iap::IAPCtlShop::createWith()->getUserBuyType()) {
  127. case iap::UserBuyType::NoShopping:
  128. sortGoods(true);
  129. break;
  130. case iap::UserBuyType::LittleShopping:
  131. sortGoods(true);
  132. break;
  133. case iap::UserBuyType::NormalShopping:
  134. sortGoods(true);
  135. break;
  136. case iap::UserBuyType::LotShopping:
  137. sortGoods(false);
  138. break;
  139. default:
  140. break;
  141. }
  142. // 当前有效的区域
  143. int bigPackCount,smallPackCount; // 需要显示的礼包
  144. auto iapCtlShop = iap::IAPCtlShop::createWith();
  145. int leval = iapCtlShop->getDeviceLevel();
  146. size_t placementCount = iapCtlShop->getPlacementCount();
  147. switch(leval){
  148. case 1:
  149. // 低等级
  150. bigPackCount = 2;
  151. smallPackCount = 1;
  152. break;
  153. case 2:
  154. // 中等级
  155. break;
  156. case 3:
  157. if(placementCount >= 2){
  158. bigPackCount = 3;
  159. smallPackCount = 0;
  160. }else{
  161. bigPackCount = 2;
  162. smallPackCount = 2;
  163. }
  164. // 高等级
  165. break;
  166. default:
  167. break;
  168. }
  169. // 展示活动商品
  170. if(_placements.size() != 0){
  171. // 展示活动
  172. for(const auto& placement : _placements){
  173. if(bigPackCount <= 0)break;
  174. bool bNeedAnim = height <= size.height;
  175. Node* nd = Node::create();
  176. nd->setCascadeOpacityEnabled(true);
  177. nd->setCascadeColorEnabled(true);
  178. // 创建活动卡片
  179. auto cards = placement.second.cards;
  180. for(const auto& card : cards){
  181. auto si = card->create();
  182. auto sz = cocos2d::Size(584,280);
  183. cocos2d::Vec2 pos(size.width/2.0, sz.height/2.0);
  184. nd->addChild(si);
  185. si->setPosition(bNeedAnim ? pos+offset : pos);
  186. _tableData.insertCell(index++, nd);
  187. _allSizes.push_back(sz);
  188. height += sz.height;
  189. if (bNeedAnim) {
  190. // 加入动画
  191. auto d = DelayTime::create(delayIdx*dur/8.0);
  192. auto m = EaseBackOut::create(MoveBy::create(dur, cocos2d::Vec2(-offset.x, offset.y)));
  193. si->runAction(Sequence::create(d, m, NULL));
  194. delayIdx ++;
  195. }
  196. }
  197. bigPackCount--;
  198. }
  199. }
  200. // 判断是否还有版位
  201. if(bigPackCount != 0 || smallPackCount != 0 || bShowAll){
  202. // 显示常规商品
  203. for (const auto& gi : _goodsInfo) {
  204. // 判断是否显示
  205. bool isShow = false;
  206. if (bShowAll) {
  207. isShow = true;
  208. }else{
  209. if(gi.type == "panel" && bigPackCount > 0){
  210. isShow = true;
  211. bigPackCount--;
  212. }
  213. if(gi.type == "bar" && smallPackCount > 0){
  214. isShow = true;
  215. smallPackCount--;
  216. }
  217. }
  218. // 商品显示
  219. if (isShow) {
  220. bool bNeedAnim = height <= size.height;
  221. Node* nd = Node::create();
  222. nd->setCascadeOpacityEnabled(true);
  223. nd->setCascadeColorEnabled(true);
  224. auto si = IAPCtlShopItem::create(gi, _placementId);
  225. auto sz = si->getSize();
  226. cocos2d::Vec2 pos(size.width/2.0, sz.height/2.0);
  227. nd->addChild(si);
  228. si->setPosition(bNeedAnim ? pos+offset : pos);
  229. _goodsItems.push_back(si);
  230. _tableData.insertCell(index++, nd);
  231. _allSizes.push_back(sz);
  232. height += sz.height;
  233. if (bNeedAnim) {
  234. // 加入动画
  235. auto d = DelayTime::create(delayIdx*dur/8.0);
  236. auto m = EaseBackOut::create(MoveBy::create(dur, cocos2d::Vec2(-offset.x, offset.y)));
  237. si->runAction(Sequence::create(d, m, NULL));
  238. delayIdx ++;
  239. }
  240. }
  241. }
  242. }
  243. // 添加展示所有按钮
  244. if (!bShowAll) {
  245. // 加入show All btn, 这个是一定会有动画的
  246. auto sz = cocos2d::Size(584, 130);
  247. Node* nd = Node::create();
  248. nd->setCascadeOpacityEnabled(true);
  249. nd->setCascadeColorEnabled(true);
  250. _btnShowAll = redutils::RUReboltLayer::createReboltLayer("shop_more_btn.redream");
  251. nd->addChild(_btnShowAll);
  252. _btnShowAll->setPosition(Vec2(size.width/2.0, sz.height/2.0) + offset);
  253. _tableData.insertCell(index++, nd);
  254. _btnShowAll->registerOnNotify([this](const redutils::ReboltNotifyData& data){
  255. if (data.notify == "点击") {
  256. auto rm = RemoveSelf::create();
  257. auto cf = CallFunc::create([=](){
  258. _btnShowAll = NULL;
  259. _tableData.clear();
  260. _goodsItems.clear();
  261. _allSizes.clear();
  262. constructShopItem(true);
  263. _tableView->reloadData(true);
  264. });
  265. _btnShowAll->runAction(Sequence::create(rm, cf, NULL));
  266. }
  267. });
  268. redutils::iterateNode(nd, [](Node* nd){
  269. nd->setCascadeOpacityEnabled(true);
  270. nd->setCascadeColorEnabled(true);
  271. });
  272. _btnShowAll->runBehaviacWhitFunName("初始化");
  273. _allSizes.push_back(sz);
  274. // 加入动画
  275. auto d = DelayTime::create(delayIdx*dur/8.0);
  276. auto m = EaseBackOut::create(MoveBy::create(dur, cocos2d::Vec2(-offset.x, offset.y)));
  277. _btnShowAll->runAction(Sequence::create(d, m, NULL));
  278. delayIdx ++;
  279. } else {
  280. // 底部添加一个额外节点(一个是底部的广告,还有就是美观一些)
  281. _tableData.insertCell(index++, Node::create());
  282. _allSizes.push_back(cocos2d::Size(584, 150));
  283. }
  284. _tableData._numberOfCellsInTableView = [=](cocos2d::extension::TableViewSmooth*)->ssize_t{
  285. return _allSizes.size();
  286. };
  287. _tableData._tableCellSizeForIndex = [=](cocos2d::extension::TableViewSmooth*, ssize_t idx)->Size{
  288. if (idx < _allSizes.size()) {
  289. return _allSizes[idx];
  290. } else {
  291. return Size(0,0);
  292. }
  293. };
  294. // 防止拉动的时候才创建
  295. _layer->scheduleOnce([=](float){
  296. for (int i=0; i<_allSizes.size(); i++) {
  297. _tableView->updateCellAtIndex(i);
  298. }
  299. }, 0.05, "SCH_Update_Cells");
  300. }
  301. void IAPCtlShopUI::filterGoods(iap::ShopRequirement &requirement){
  302. std::map<int, bool> m;
  303. int cnt = 0;
  304. for(const auto& goodInfo : _goodsInfo){
  305. if(goodInfo.getCoinNumber() >= requirement.coinsMin){
  306. m[cnt] = true;
  307. }
  308. cnt++;
  309. }
  310. std::vector<GoodsInfo> newGoodsInfo;
  311. // 添加符合条件的礼包
  312. for(int i = 0;i < _goodsInfo.size(); i++){
  313. if(m[i]){
  314. newGoodsInfo.push_back(_goodsInfo[i]);
  315. }
  316. }
  317. // 添加不符合条件的礼包(不清楚是不是需要显示,暂放到列表末尾)
  318. // for(int i = 0;i < _goodsInfo.size(); i++){
  319. // if(!m[i]){
  320. // newGoodsInfo.push_back(_goodsInfo[i]);
  321. // }
  322. // }
  323. _goodsInfo = newGoodsInfo;
  324. }
  325. void IAPCtlShopUI::sortGoods(bool flag){
  326. sort(_goodsInfo.begin(), _goodsInfo.end(), [flag](GoodsInfo a, GoodsInfo b){
  327. if(a.getTypeValue() != b.getTypeValue())return a.getTypeValue() > b.getTypeValue();
  328. if(flag) return a.getCostNumber() < b.getCostNumber();
  329. else return a.getCostNumber() > b.getCostNumber();
  330. });
  331. }
  332. void IAPCtlShopUI::quit() {
  333. if (_layer) {
  334. _layer->runBehaviacWhitFunName("退出");
  335. }
  336. }