You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

421 lines
12 KiB

  1. require("luaScript.Extension.CCExt")
  2. require("luaScript.Extension.MathExt")
  3. require("luaScript.cc.debug")
  4. require("luaScript.Tools.Nodes.Transform")
  5. cc.Node.ClassName = "Node";
  6. function cc.Node:cloneLua(node)
  7. end
  8. function cc.Node:loadFromXmlNode(xmlNode)
  9. cc.Transform.loadFromXmlNode(self , xmlNode);
  10. self:setName(xmlNode.Name);
  11. self:setLocalZOrder(xmlNode.LocalZOrder)
  12. if xmlNode.RenderOffset ~= nil then
  13. self:setRenderOffset(xmlNode.RenderOffset)
  14. end
  15. end
  16. function cc.Node:createNode()
  17. local node = cc.Node:create();
  18. return node;
  19. end
  20. function cc.StreamObject:saveToBinaryString()
  21. return string.toLuaString(self:saveToStream());
  22. end
  23. function cc.StreamObject:createFromBinaryString(str)
  24. local func , err = loadstring("return " .. str);
  25. if func == nil then
  26. error(err);
  27. end
  28. local data = func();
  29. return cc.StreamObject:loadFromStream(data);
  30. end
  31. -- 获得选择用的世界包围盒,用来编辑器框选的
  32. function cc.Node:getSelectBox()
  33. return self:getSelfBoundingBox();
  34. end
  35. -- 计算矩形rect是否跟节点相交,用来给编辑器框选的
  36. -- rect 的坐标系是0-1
  37. function cc.Node:selectTest(rect)
  38. local frustum = cc.Frustum:new(app.mainCamera:pickRectVPMatrix(rect));
  39. return frustum:intersectsBoundingBox(self:getSelectBox());
  40. end
  41. -- 遍历所有子节点
  42. function cc.Node:visitNode(func)
  43. if func(self) == false then
  44. return false;
  45. end
  46. local children = self:getChildren();
  47. if children then
  48. for i , v in ipairs(children) do
  49. local child = v;
  50. if cc.Node.visitNode(child , func) == false then
  51. return false;
  52. end
  53. end
  54. end
  55. return true;
  56. end
  57. -- 获得根节点
  58. function cc.Node:getRootNode()
  59. local parent = self:getParent();
  60. if parent then
  61. return parent:getRootNode();
  62. else
  63. return self;
  64. end
  65. end
  66. -- 获得这个节点的世界位置
  67. function cc.Node:getWorldPosition()
  68. local parent = self:getParent();
  69. if parent then
  70. return parent:convertToWorldSpace(self:getTranslation());
  71. else
  72. return self:getTranslation();
  73. end
  74. end
  75. -- 设置这个节点的世界位置
  76. function cc.Node:setWorldPosition(pos)
  77. local parent = self:getParent();
  78. if parent then
  79. self:setTranslation(parent:convertToNodeSpace(pos));
  80. else
  81. self:setTranslation(pos);
  82. end
  83. end
  84. -- 获得这个节点的世界位置
  85. function cc.Node:getWorldPositionX()
  86. return self:getWorldPosition().x;
  87. end
  88. -- 获得这个节点的世界位置
  89. function cc.Node:getWorldPositionY()
  90. return self:getWorldPosition().y;
  91. end
  92. -- 设置这个节点的世界位置
  93. function cc.Node:setWorldPositionX(x)
  94. local pos = self:getWorldPosition();
  95. pos.x = x;
  96. self:setWorldPosition(pos);
  97. end
  98. -- 设置这个节点的世界位置
  99. function cc.Node:setWorldPositionY(y)
  100. local pos = self:getWorldPosition();
  101. pos.y = y;
  102. self:setWorldPosition(pos);
  103. end
  104. -- 运行静态时间的actions
  105. function cc.Node:runActions(...)
  106. local action = createActionArray(...);
  107. self:runAction(action);
  108. return action;
  109. end
  110. -- 每帧运行一次
  111. function cc.Node:runEveryFrame(func)
  112. local action = cc.RepeatForever:create(cc.Sequence:create(cc.CallFunc:create(func)));
  113. self:runAction(action);
  114. return action;
  115. end
  116. -- 下一帧运行一次
  117. function cc.Node:runInNextFrame(func)
  118. local action = cc.Sequence:create(cc.CallFunc:create(func));
  119. self:runAction(action);
  120. return action;
  121. end
  122. -- 延迟几秒后执行
  123. function cc.Node:runDelay(delay , func)
  124. return self:runActions(cc.DelayTime:create(delay) , func);
  125. end
  126. -- 运行动态时间的actions
  127. function cc.Node:runDynamicTimeActions(...)
  128. local action = createDynamicTimeActionArray(...);
  129. self:runAction(action);
  130. return action;
  131. end
  132. function cc.Node:runSpawnActions(...)
  133. local action = createSpawnActions(...);
  134. self:runAction(action);
  135. return action;
  136. end
  137. -- 注册点击事件(不管节点大小,全屏的,但是会根据渲染顺序派发),所有参数都可为空
  138. function cc.Node:registerTouch(onTouchBegan , onTouchMoved , onTouchEnded , onTouchCancelled)
  139. -- 侦听鼠标触摸事件
  140. local touchListener = cc.EventListenerTouchOneByOne:create()
  141. touchListener:setSwallowTouches(true);
  142. local eventDispatcher = self:getEventDispatcher()
  143. if onTouchBegan then
  144. touchListener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN)
  145. end
  146. if onTouchMoved then
  147. touchListener:registerScriptHandler(onTouchMoved, cc.Handler.EVENT_TOUCH_MOVED)
  148. end
  149. if onTouchEnded then
  150. touchListener:registerScriptHandler(onTouchEnded, cc.Handler.EVENT_TOUCH_ENDED)
  151. end
  152. if onTouchCancelled then
  153. touchListener:registerScriptHandler(onTouchCancelled, cc.Handler.EVENT_TOUCH_CANCELLED)
  154. end
  155. eventDispatcher:addEventListenerWithSceneGraphPriority(touchListener, self)
  156. return touchListener;
  157. end
  158. -- 注册按下时的点击事件(判断节点包围盒是否与点击点相交,全屏的,会根据渲染顺序派发)
  159. -- @onClick 点击回调:onClick(clickPoint)
  160. -- boundingbox 传进来一个本地包围盒(内部会通过node的世界矩阵转换成世界包围盒),如不传则使用node的世界包围盒
  161. function cc.Node:registerClick(onClick , boundingbox)
  162. local function onTouchBegan(touch , event)
  163. if not self:isVisibleR() then
  164. return false;
  165. end
  166. -- 获取点击的射线
  167. local ray = self:convertTouchToCameraRay(touch);
  168. local distance;
  169. if boundingbox then
  170. local transformed = cc.BoundingBox:new(boundingbox:getMin() , boundingbox:getMax());
  171. transformed:transform(self:getWorldMatrix());
  172. distance = ray:intersectsBoundingBox(transformed);
  173. else
  174. distance = ray:intersectsBoundingBox(self:getBoundingBox());
  175. end
  176. if distance >= 0 then
  177. local clickPoint = ray:getPoint(distance);
  178. if onClick(clickPoint) == false then
  179. return false;
  180. end
  181. return true;
  182. else
  183. return false;
  184. end
  185. return false;
  186. end
  187. self:setTouchEnabled(true);
  188. self:registerTouch(onTouchBegan);
  189. end
  190. -- 注册弹起时的点击事件(判断节点包围盒是否与点击点相交,全屏的,会根据渲染顺序派发)
  191. -- @onClick 点击回调:onClick(clickPoint)
  192. -- boundingbox 传进来一个本地包围盒(内部会通过node的世界矩阵转换成世界包围盒),如不传则使用node的世界包围盒
  193. function cc.Node:registerMouseUp(onClick , boundingbox)
  194. local function onTouchBegan(touch , event)
  195. if not self:isVisibleR() then
  196. return false;
  197. end
  198. -- 获取点击的射线
  199. local ray = self:convertTouchToCameraRay(touch);
  200. local distance;
  201. if boundingbox then
  202. local transformed = cc.BoundingBox:new(boundingbox:getMin() , boundingbox:getMax());
  203. transformed:transform(self:getWorldMatrix());
  204. distance = ray:intersectsBoundingBox(transformed);
  205. else
  206. distance = ray:intersectsBoundingBox(self:getBoundingBox());
  207. end
  208. if distance >= 0 then
  209. return true;
  210. else
  211. return false;
  212. end
  213. return false;
  214. end
  215. local function onTouchEnded(touch , event)
  216. if not self:isVisibleR() then
  217. return false;
  218. end
  219. -- 获取点击的射线
  220. local ray = self:convertTouchToCameraRay(touch);
  221. local distance;
  222. if boundingbox then
  223. local transformed = cc.BoundingBox:new(boundingbox:getMin() , boundingbox:getMax());
  224. transformed:transform(self:getWorldMatrix());
  225. distance = ray:intersectsBoundingBox(transformed);
  226. else
  227. distance = ray:intersectsBoundingBox(self:getBoundingBox());
  228. end
  229. if distance >= 0 then
  230. local clickPoint = ray:getPoint(distance);
  231. if onClick(clickPoint) == false then
  232. return false;
  233. end
  234. return true;
  235. else
  236. return false;
  237. end
  238. return false;
  239. end
  240. self:registerTouch(onTouchBegan , nil , onTouchEnded);
  241. end
  242. -- 显示包围盒
  243. -- boundingbox 传进来一个本地包围盒(内部会通过node的世界矩阵转换成世界包围盒),如不传则使用node的世界包围盒
  244. function cc.Node:showBoundingBox(boundingbox)
  245. local glNode = gl.glNodeCreate()
  246. glNode:setAnchorPoint(cc.p(0.5, 0.5))
  247. local material3d = cc.MaterialCache:getInstance():load("preload/shaders/ccDefault.material#ShaderPosition_uColor3D");
  248. cc.Default2DMaterials:getInstance():bindValue(material3d:getParameter("CC_MVPMatrix") , "WORLD_VIEW_PROJECTION_MATRIX");
  249. local function primitivesDraw(transform, transformUpdated)
  250. if not tolua.isnull(self) then
  251. cc.DrawPrimitives.setMaterial(material3d);
  252. -- 绑定相机、世界矩阵
  253. cc.DrawPrimitives.setCamera(self:getActiveCamera());
  254. cc.DrawPrimitives.setWorldTransform(cc.Mat4:identity());
  255. -- 画矩形
  256. gl.lineWidth( 1 )
  257. cc.DrawPrimitives.drawColor4B(0, 255, 0, 255)
  258. if boundingbox then
  259. local transformed = cc.BoundingBox:new(boundingbox:getMin() , boundingbox:getMax());
  260. transformed:transform(self:getWorldMatrix());
  261. cc.DrawPrimitives.drawBoundingBox(transformed)
  262. else
  263. cc.DrawPrimitives.drawBoundingBox(self:getBoundingBox())
  264. end
  265. -- 状态恢复
  266. gl.lineWidth(1)
  267. cc.DrawPrimitives.drawColor4B(255,255,255,255)
  268. cc.DrawPrimitives.setPointSize(1)
  269. -- 材质状态恢复
  270. cc.DrawPrimitives.setCamera(nil);
  271. cc.DrawPrimitives.setMaterial(nil);
  272. end
  273. end
  274. glNode:registerScriptDrawHandler(primitivesDraw)
  275. self:addChild(glNode);
  276. return glNode
  277. end
  278. -- 使用这个节点当作源模型和源点来播放一个ce
  279. function cc.Node:playCE(ceFile , onPlayEnd)
  280. -- 创建一个源模型、源点、目标模型、目标点
  281. local params = createDefaultCombineEffectParams();
  282. params.ParentNode = self:getParent();
  283. table.insert(params.SourceNode, self);
  284. table.insert(params.SourcePos, self:getTranslation());
  285. local ce = createCombineEffect(ceFile);
  286. local action = nil
  287. if ce then
  288. action = cc.CombineEffectAction:createWithInstance(ce, params, nil, function()if onPlayEnd then onPlayEnd()end; end)
  289. self:runAction(action)
  290. end
  291. return action
  292. end
  293. -- 兼容老接口
  294. function cc.Node:registerScriptHandler(listener)
  295. local function callback(node , eventType)
  296. if eventType == cc.NodeEvent.OnEnter then
  297. listener("enter");
  298. elseif eventType == cc.NodeEvent.OnExit then
  299. listener("exit");
  300. elseif eventType == cc.NodeEvent.OnEnterTransitionDidFinish then
  301. listener("enterTransitionFinish");
  302. elseif eventType == cc.NodeEvent.OnExitTransitionDidStart then
  303. listener("exitTransitionStart");
  304. elseif eventType == cc.NodeEvent.OnCleanup then
  305. listener("cleanup");
  306. elseif eventType == cc.NodeEvent.OnDestruct then
  307. listener("destruct");
  308. end
  309. end
  310. return self:addNodeEventListener(callback);
  311. end
  312. function cc.Node:unregisterScriptHandler(eventId)
  313. if eventId then
  314. self:removeNodeEventListener(eventId);
  315. else
  316. self:removeAllNodeEventListener();
  317. end
  318. end
  319. -- 禁用这个Widget下的所有点击
  320. function cc.Node:disableAllTouch()
  321. local function visit(node)
  322. if node.setTouchEnabled then
  323. if node:isTouchEnabled() then
  324. node.OldTouchEnabled = node:isTouchEnabled();
  325. node:setTouchEnabled(false);
  326. end
  327. end
  328. end
  329. self:visitNode(visit);
  330. end
  331. -- 恢复这个Widget下的所有点击
  332. function cc.Node:restoreAllTouch()
  333. local function visit(node)
  334. if node.setTouchEnabled then
  335. if node.OldTouchEnabled == true then
  336. node:setTouchEnabled(true);
  337. node.OldTouchEnabled = nil;
  338. end
  339. end
  340. end
  341. self:visitNode(visit);
  342. end
  343. -- 设置一个剩余时间,并且每秒倒数,callback(ui , value)
  344. function cc.Node:startRemainTime(seconds , callback)
  345. -- 打印一下,是哪个地方在调用这个接口
  346. logD("cc.Node:startRemainTime()", debug.traceback())
  347. seconds = tonumber(seconds)
  348. if not seconds or seconds <= 0 then
  349. return
  350. end
  351. -- 设置倒计时
  352. local remainTimePacket = RemainTimePacket:new();
  353. remainTimePacket.remainTime:setRemainTime(math.floor(seconds))
  354. self:bind(remainTimePacket.remainTime, "Value", callback)
  355. end
  356. -- 把节点基本信息dump到一个表里返回(调试用)
  357. function dumpNode(node)
  358. local dumped = {};
  359. dumped.Name = node:getName();
  360. dumped.ClassName = tolua.type(node);
  361. local children = {};
  362. for i , v in ipairs(node:getChildren()) do
  363. table.insert(children , dumpNode(v));
  364. end
  365. dumped.Children = children;
  366. return dumped;
  367. end
  368. -- 把节点基本信息dump到一个文件(调试用)
  369. function dumpNodeToFile(node , filename)
  370. local dumped = dumpNode(node);
  371. table.saveFile(dumped , filename);
  372. end