-- 处理3D相机的移动控制 require("CSharpConstants") local Camera3DControllerTool = class("Camera3DControllerTool") function Camera3DControllerTool:ctor() -- 相机的球面坐标系 -- 半径,离原点的距离,一般是一个正数 -- 经度,0~2PI,0代表正前方,PI代表正后方 -- 纬度,HALF_PI代表水平位置,+PI代表底,0代表顶 self.spherical = cc.vec3(30,1.4,1.4); -- 相机旋转中心点 self.rotationCenter = cc.vec3(0,0,0); end function Camera3DControllerTool:moveTo(button , offsetPos) -- ALT + 鼠标右键拉近拉远 if button == MouseButtons.Right then --local offset = (offsetPos.x + -offsetPos.y) * 0.1; local offset = -offsetPos.x + offsetPos.y; self.spherical.x = math.max(self.spherical.x + offset * 0.00075 * self.spherical.x); -- 拉得太近了,就把原点丢远一点 if self.spherical.x <= 1 then -- 丢10格 local fullOut = 30; local ray = app.mainCamera:pickRay(0.5,0.5); -- 沿着屏幕射线把旋转中心点往前移动 self.rotationCenter = cc.vec3Add(cc.vec3Mul(ray:getDirection() , fullOut) , self.rotationCenter); self.spherical.x = self.spherical.x + fullOut; end -- ALT + 鼠标中键平移 elseif button == MouseButtons.Middle then local offset = app.mainCamera:moveByViewPlane(cc.vec3(offsetPos.x * 0.00075 * self.spherical.x , -offsetPos.y * 0.00075 * self.spherical.x, 0)); self.rotationCenter.x = self.rotationCenter.x + offset.x; self.rotationCenter.y = self.rotationCenter.y + offset.y; self.rotationCenter.z = self.rotationCenter.z + offset.z; -- ALT + 鼠标左键旋转 elseif button == MouseButtons.Left then self.spherical.y = self.spherical.y + offsetPos.x * 0.003; self.spherical.z = self.spherical.z + offsetPos.y * 0.003; end self:update(); end function Camera3DControllerTool:update() -- 计算相对rotationCenter的位置 local pos = Math.SphericalToCartesian(cc.vec3(self.spherical.x , self.spherical.y , self.spherical.z)); pos.x = pos.x + self.rotationCenter.x pos.y = pos.y + self.rotationCenter.y pos.z = pos.z + self.rotationCenter.z app.mainCamera:getNode():setTranslation(pos); app.mainCamera:lookAt(self.rotationCenter); end function Camera3DControllerTool:MoveDown(button, x, y) -- 按下ALT控制相机 if app.cs.getModifierKeys() ~= Keys.Alt then return end -- 鼠标的按下位置 self.startPos = app.visibleRect:convertScreenToGLView(x, y); -- 相机的位置 self.originPos = app.mainCamera:getNode():getPosition(); end function Camera3DControllerTool:MouseMove(button , x , y) local glViewPos = app.visibleRect:convertScreenToGLView(x, y); if self.startPos then local delta = cc.pSub(glViewPos , self.startPos); -- 计算结束点 self:moveTo(button , delta); self.startPos = glViewPos; end local point = self:convertScreenToWorldPos(x, y); local strMapCoord = ""; if app.editor and app.editor.Map then local tilePos = app.editor.Map:getTilePosition(point.x , point.z); strMapCoord = string.format(" TilePos:%d,%d" , tilePos.x , tilePos.y); end local ort = cc.Orientation:new(); ort:fromQuaternion(app.mainCamera:getNode():getQuaternion()); local dir = ort:toDirection(); return string.format("Mouse:%d,%d Coordinate:%.2f,%.2f,%.2f GLView:%d,%d CameraPos:%.2f,%.2f,%.2f CameraDir:%.2f,%.2f,%.2f" .. strMapCoord , x , y , point.x , point.y , point.z , glViewPos.x , glViewPos.y , app.mainCamera:getNode():getTranslationX() , app.mainCamera:getNode():getTranslationY() , app.mainCamera:getNode():getTranslationZ() , dir.x , dir.y , dir.z ); end function Camera3DControllerTool:MoveUp(button, x, y) if not self.startPos then return end -- 计算结束点 --self:moveTo(app.visibleRect:convertScreenToGLView(x, y)); self.startPos = nil; self.originPos = nil; end function Camera3DControllerTool:KeyDown(Control , Alt , Shift , KeyCode) -- F按下 if Control == false and Alt == false and Shift == false and KeyCode == Keys.F then local node; -- 如果有物件被选中,就定位到第一个物件 if app.editor and app.editor.SelectedNodes and next(app.editor.SelectedNodes) then node = next(app.editor.SelectedNodes); end -- 如果没物件被选中,则定位到当前物件 if not node and app.editor and app.editor.node then node = app.editor.node; end if node then self.rotationCenter = node:getWorldTranslation(); local box = node:getSelectBox(); local max = box:getMax(); local distance = math.max(max.x , max.y , max.z , 1) self.spherical = cc.vec3(distance ,1.4,1.4); else self.rotationCenter = cc.vec3(0,0,0); self.spherical = cc.vec3(30,1.4,1.4); end self:update(); end end -- 摆放物件时使用这个函数计算物件应该放在什么位置 function Camera3DControllerTool:convertScreenToWorldPos(mouseX , mouseY) local floorPlane = cc.Plane:new(cc.vec3(0,1,0) , 0); -- 计算出mainlayer的世界位置 local screenSize = cc.Director:getInstance():getWinSizeInPixels(); local ray = app.mainCamera:pickRay(mouseX / screenSize.width , mouseY / screenSize.height); local distance = ray:intersectsPlane(floorPlane); if distance >= 0 then return ray:getPoint(distance); else return ray:getPoint(0); end end -- 刷新设置时调用 function Camera3DControllerTool:refreshSetting() app.background:removeAllChildren(); -- 画手机外壳 if app.setting.ShowIPhone5 then local bgIphone5 = cc.Sprite:create("Editor/iphone5.png"); app.background:addChild(bgIphone5) end -- 设置OpenGL背景颜色 gl.clearColor(app.setting.BackgroundColor.r / 255 , app.setting.BackgroundColor.g / 255 , app.setting.BackgroundColor.b / 255 ,0); if app.setting.ShowGrid then -- 创建网格 local vertexFormat = {}; table.insert(vertexFormat , {size = 3 , usage = cc.VertexFormatUsage.POSITION}); table.insert(vertexFormat , {size = 4 , usage = cc.VertexFormatUsage.COLOR}); local vertices = ManualVertices:new(vertexFormat); vertices:setColor(app.setting.GridColor); local viewSize = cc.size(100,100); local gridWidth = app.setting.GridSize.width local gridHeight = app.setting.GridSize.height local gridCountY = math.floor(viewSize.height / gridHeight); vertices:setColor(app.setting.GridColor); -- 画横向网格 for i = -gridCountY , gridCountY do if i ~= 0 then vertices:drawLine(cc.vec3(-viewSize.width , 0 , i * gridHeight) , cc.vec3(viewSize.width , 0 , i * gridHeight)) end end vertices:setColor(app.setting.GridColor); -- 画竖向网格 local gridCountX = math.floor(viewSize.width / gridWidth); for i = -gridCountX , gridCountX do if i ~= 0 then vertices:drawLine(cc.vec3(i * gridWidth , 0 , -viewSize.height) , cc.vec3(i * gridWidth , 0 , viewSize.height)) end end vertices:setColor(app.setting.AxisColor); -- 画轴 vertices:drawLine(cc.vec3(-viewSize.width , 0 , 0) , cc.vec3(viewSize.width , 0 , 0)) vertices:drawLine(cc.vec3(0 , 0 , -viewSize.height) , cc.vec3(0 , 0 , viewSize.height)) local mesh = cc.Mesh:createMesh(vertexFormat , vertices:getVertexCount()); mesh:setPrimitiveType(cc.PrimitiveType.LINES); mesh:setVertexData(vertices:getVertices() , 0 , vertices:getVertexCount()); mesh:setBoundingBox(vertices:getBoundingBox()); local model = cc.Model:create(mesh); local material = cc.Material:create("core/preload/shaders/ccDefault.material#ShaderPositionColor3D"); material:setParameterAutoBinding("CC_MVPMatrix" , "WORLD_VIEW_PROJECTION_MATRIX"); model:setMaterialPointer(material); local node = cc.Node3D:create(); node:addComponent(model); app.background:addChild(node); end end return Camera3DControllerTool;