PGRData/Script/matrix/xentity/xplanet/xgameobject/XPlanetIScene.lua
2024-09-01 22:49:41 +02:00

1168 lines
No EOL
39 KiB
Lua

local XPlanetIObject = require("XEntity/XPlanet/XGameObject/XPlanetIObject")
local XPlanet = require("XEntity/XPlanet/XGameObject/XPlanet")
local XPlanetCamera = require("XEntity/XPlanet/XGameObject/XPlanetCamera")
local XPlanetBuilding = require("XEntity/XPlanet/XGameObject/XPlanetBuilding")
---@class XPlanetIScene:XPlanetIObject
---@field _StageId number
---@field _Planet XPlanet
---@field _PlanetRoot CS.UnityEngine.Transform
---@field _PlanetCamera XPlanetCamera
local XPlanetIScene = XClass(XPlanetIObject, "XPlanetIScene")
function XPlanetIScene:Ctor(root, stageId)
self:Init(stageId)
end
function XPlanetIScene:Init(stageId)
self._StageId = stageId
self._Planet = nil
self._Mode = XPlanetConfigs.SceneMode.None
self:_InitCurBuildParams()
end
function XPlanetIScene:ChangeMode(mode)
self._Mode = mode
end
function XPlanetIScene:CheckIsInNoneMode()
return self._Mode == XPlanetConfigs.SceneMode.None
end
--region 相机接口
function XPlanetIScene:UpdateCamInMovie(lookAtTran)
if not self:CheckIsHaveCamera() then return end
local cam = XDataCenter.PlanetManager.GetCamera(XPlanetConfigs.GetCamStageMovie())
self._PlanetCamera:ChangeMovieModeByCamera(cam, lookAtTran, true)
end
---获取当前场景的相机
---@return CS.UnityEngine.Camera
function XPlanetIScene:GetCamera()
if not self:CheckIsHaveCamera() then
return
end
return self._PlanetCamera:GetCamera()
end
---获取当前鼠标位置的地板
---@return Transfrom
function XPlanetIScene:GetCameraRay()
if not self:CheckIsHaveCamera() then
return
end
local hit = self._PlanetCamera:RayTileCast()
if XTool.UObjIsNil(hit) then
return
end
return hit
end
---获取当前鼠标位置的地板
---@return CS.Planet.PlanetTile
function XPlanetIScene:GetCameraRayTile()
if not self:CheckIsHaveCamera() then
return
end
local hit = self._PlanetCamera:RayTileCast()
if XTool.UObjIsNil(hit) then
return
end
local tile = hit:GetComponent(typeof(CS.Planet.PlanetTile))
if XTool.UObjIsNil(tile) then
return
end
return tile
end
---获取指定屏幕坐标的地板
---@param screenPoint Vector2
---@return CS.Planet.PlanetTile
function XPlanetIScene:GetCameraRayTileByScreenPoint(screenPoint)
if not self:CheckIsHaveCamera() then
return
end
local hit = self._PlanetCamera:RayTileCastByScreenPoint(screenPoint, CS.UnityEngine.LayerMask.GetMask(HomeSceneLayerMask.Room))
if XTool.UObjIsNil(hit) then
return
end
local tile = hit:GetComponent(typeof(CS.Planet.PlanetTile))
if XTool.UObjIsNil(tile) then
return
end
return tile
end
---@return boolean
function XPlanetIScene:CheckCameraIsMove()
if not self:CheckIsHaveCamera() then
return false
end
return self._PlanetCamera._IsInMove
end
---@param followTran Transform
---@param camera XPlanetSceneCamera
function XPlanetIScene:SetCameraFollow(followTran, camera, cb)
if not self:CheckIsHaveCamera() then
if cb then cb() end
return
end
self._PlanetCamera:ChangeFollowModeByCamera(followTran, camera, cb, false)
end
---@param explore XPlanetRunningExplore
function XPlanetIScene:CameraUpdate(explore, deltaTime)
if not self:CheckIsHaveCamera() then
return
end
--- 引导中时屏蔽旋转等
if XDataCenter.GuideManager.CheckIsInGuidePlus() then
return
end
self._PlanetCamera:FollowModeUpdate(explore, deltaTime)
self._PlanetCamera:FreeModeScroll()
self._PlanetCamera:FreeAfterDragUpdate()
end
function XPlanetIScene:MoveStaticCamera(position, rotation)
if not self:CheckIsHaveCamera() then
return
end
self._PlanetCamera:StaticModeMove(position, rotation)
end
---相机是否处于跟随视角
function XPlanetIScene:CheckCameraIsFollowMode()
if not self:CheckIsHaveCamera() then
return false
end
return self._PlanetCamera:CheckIsInFollowMode()
end
---相机是否处于自由旋转视角
function XPlanetIScene:CheckCameraIsFreeMode()
if not self:CheckIsHaveCamera() then
return false
end
return self._PlanetCamera:CheckIsInFreeMode()
end
---相机是否处于固定视角
function XPlanetIScene:CheckCameraIsStaticMode()
if not self:CheckIsHaveCamera() then
return false
end
return self._PlanetCamera:CheckIsInStaticMode()
end
--endregion
--region 星球建造接口
--内部接口
--=============================================================
---初始化当前预摆放建筑参数
function XPlanetIScene:_InitCurBuildParams()
---当前临时摆放的建筑列表
---@type XPlanetBuilding[]
self._CurBuildingList = {}
---当前临时摆放的建筑占地字典
---@type table<number, table>
self._CurBuildOccupyTileListDir = {}
---当前临时摆放的建筑范围地块字典
---@type table<number, table>
self._CurBuildRangeTileListDir = {}
---当前临时摆放的建筑可否摆放字典
---@type table<number, table>
self._CurBuildCanBuildDir = {}
self._CurBuildSelectTileList = {}
self._CurBuildBuildingId = 0
---当前选中的建筑是否是地板建筑
self._CurBuildIsFloor = false
end
---刷新地板的材质
---@param tileId number 地块id
---@param canBuild boolean 该地块所属的建筑能否被建造
---@param canOccupy boolean 该地块能否作为被建造建筑的占地
---@param isRange boolean 是否是建筑的范围
function XPlanetIScene:_UpdateTileMaterial(tileId, canBuild, canOccupy, isRange)
if isRange then
self._Planet:SetTileRangeMat(tileId)
return
end
local isNoneTile = self:CheckTileGridType(tileId, XPlanetWorldConfigs.GridType.None)
if not isNoneTile and canBuild and canOccupy then
self._Planet:SetTileSelectMat(tileId)
elseif not isNoneTile and (not canBuild or not canOccupy) then
self._Planet:SetTileCantBuildMat(tileId)
elseif isNoneTile and (not canBuild or not canOccupy) then
self._Planet:SetTileNoneBuildMat(tileId)
end
end
---恢复地板的材质
---@param tileId number 地块id
function XPlanetIScene:_ResetTileMaterial(tileId)
self._Planet:ResetTileMaterial(tileId)
end
function XPlanetIScene:_CreateCurBuildData(tileId, buildId)
self:_InitCurBuildParams()
local guid = self:CheckIsTalentPlanet() and XDataCenter.PlanetManager.GetTalentBuildGuid() or XDataCenter.PlanetManager.GetStageBuildIncId()
self._CurBuildIsFloor = XPlanetWorldConfigs.CheckBuildingIsType(buildId, XPlanetWorldConfigs.BuildType.FloorBuild)
self._CurBuildBuildingId = buildId
table.insert(self._CurBuildSelectTileList, tileId)
--创建建筑
if self._CurBuildIsFloor then
-- 地板型建筑
local buildMode = XDataCenter.PlanetManager.GetCurFloorSelectBuildMode(self:CheckIsTalentPlanet())
table.insert(self._CurBuildingList, XPlanetBuilding.New(self._Root, guid))
if buildMode == XPlanetConfigs.FloorBuildingBuildMode.Cycle then
local tile = self._Planet:GetTile(tileId)
for i = 0, tile:GetNeighborIds().Count - 1 do
table.insert(self._CurBuildingList, XPlanetBuilding.New(self._Root, guid + i + 1))
table.insert(self._CurBuildSelectTileList, tile:GetNeighborIds()[i])
end
end
else
-- 非地板型建筑
table.insert(self._CurBuildingList, XPlanetBuilding.New(self._Root, guid))
end
for index, building in ipairs(self._CurBuildingList) do
--占地
self._CurBuildOccupyTileListDir[index] = self:_CreateBuildOccupyTileList(self._CurBuildSelectTileList[index], buildId)
--范围
self._CurBuildRangeTileListDir[index] = self:_CreateBuildRangeTileList(self._CurBuildOccupyTileListDir[index], buildId)
--能否建造
self._CurBuildCanBuildDir[index] = self:CheckBuildingCanBeBuild(buildId, self._CurBuildOccupyTileListDir[index])
--赋值
building:SetBuildingId(self._CurBuildBuildingId)
building:SetBuildingDirection(1)
building:SetOccupyTileList(self._CurBuildOccupyTileListDir[index])
building:SetRangeTileList(self._CurBuildRangeTileListDir[index])
if self._CurBuildIsFloor then
building:SetFloorId()
else
if self:CheckIsTalentPlanet() then
building:SetFloorId(XDataCenter.PlanetManager.GetCurBuildSelectFloorId())
else
local chapterId = XPlanetStageConfigs.GetStageChapterId(self._StageId)
local chapterFloorId = XPlanetStageConfigs.GetChapterBaseRoadFloorId(chapterId)
building:SetFloorId(XTool.IsNumberValid(chapterFloorId) and chapterFloorId or XPlanetWorldConfigs.GetBuildingFloorId(building:GetBuildingId()))
end
end
end
end
---根据鼠标指向的tile获取建筑占地地块
---@param tileId number
---@param buildId number
function XPlanetIScene:_CreateBuildOccupyTileList(tileId, buildId)
local result = {}
local occupyType = XPlanetWorldConfigs.GetBuildingGridOccupyType(buildId)
local neighborIds = self._Planet:GetTile(tileId):GetNeighborIds()
local neighborMaxIndex = neighborIds.Count - 1
table.insert(result, tileId)
if occupyType == XPlanetWorldConfigs.GridOccupyType.Occupy3 then
local isFind = false
for i = 0, neighborMaxIndex do
if isFind then
break
end
for j = 0, neighborMaxIndex do
if self:CheckTileCanBeBuildOccupy(neighborIds[i], buildId) and
self:CheckTileCanBeBuildOccupy(neighborIds[j], buildId) and
self:CheckTileIsNeighbor(neighborIds[i], neighborIds[j]) then
table.insert(result, neighborIds[i])
table.insert(result, neighborIds[j])
isFind = true
break
end
end
if i == neighborMaxIndex and not isFind then
-- 找不到可用占地地块返回首两个相邻地块作为模型占地
for j = 0, neighborMaxIndex do
if self:CheckTileIsNeighbor(neighborIds[0], neighborIds[j]) then
table.insert(result, neighborIds[0])
table.insert(result, neighborIds[j])
isFind = true
break
end
end
end
end
elseif occupyType == XPlanetWorldConfigs.GridOccupyType.Occupy7 then
for i = 0, neighborMaxIndex do
table.insert(result, neighborIds[i])
end
end
return result
end
---获取占地建筑的范围地块
---@param occupyTileIdList number[]
---@param buildId number
function XPlanetIScene:_CreateBuildRangeTileList(occupyTileIdList, buildId)
return self._Planet:GetBuildRangeTileList(occupyTileIdList, buildId)
end
---旋转占地为3的建筑占地地块
---@param occupyTileIdList number[]
function XPlanetIScene:_GetRotateBuildOccupy3TileList(occupyTileIdList)
local result = {}
if #occupyTileIdList ~= 3 then
return occupyTileIdList
end
local tileId1 = occupyTileIdList[1]
local tileId2 = occupyTileIdList[2]
local tileId3 = occupyTileIdList[3]
local newTileId1 = tileId1
local newTileId2 = tileId3
local newTileId3 = tileId2
local tile1 = self._Planet:GetTile(tileId1)
local tile2 = self._Planet:GetTile(tileId2)
for i = 0, tile1:GetNeighborIds().Count - 1 do
for j = 0, tile2:GetNeighborIds().Count - 1 do
if tile1:GetNeighborIds()[i] == tile2:GetNeighborIds()[j] and tile1:GetNeighborIds()[i] ~= tileId3 then
newTileId2 = tile1:GetNeighborIds()[i]
break
end
end
end
result = { newTileId1, newTileId2, newTileId3 }
return result
end
---销毁当前预放置建筑
function XPlanetIScene:_DeleteCurBuildData()
self:ResetCurCardTileMaterial()
self:ResetCurBuildTileMaterial()
if not XTool.IsTableEmpty(self._CurBuildingList) then
for index, building in ipairs(self._CurBuildingList) do
if self._CurBuildIsFloor and self._CurBuildCanBuildDir[index] and self:CheckBuildingCanBeBuild(self._CurBuildBuildingId, building:GetOccupyTileList()) then
self._Planet:RemoveFloor(building, true)
end
building:Release()
end
end
self:_InitCurBuildParams()
end
---确认摆放建筑
function XPlanetIScene:_SetCurBuildIngList()
for key, building in ipairs(self._CurBuildingList) do
if self._CurBuildCanBuildDir[key] then
self._Planet:AddBuilding(building)
self._Planet:SetBuilding(building)
XEventManager.DispatchEvent(XEventId.EVENT_PLANET_UPDATE_BUILDING)
self:PlayEffect(XPlanetConfigs.GetBuildEffect(), self._Planet:GetBuildingPosition(building:GetOccupyTileList()), building:GetRotation())
end
end
self:ResetCurBuildTileMaterial()
self:_InitCurBuildParams()
self:ChangeMode(XPlanetConfigs.SceneMode.None)
end
function XPlanetIScene:PlayEffect(url, position, rotation, callback)
self._Planet:PlayEffect(url, position, rotation, callback)
end
---前端建造拦截判断
function XPlanetIScene:_CheckCurBuildingListCanBuild()
-- 建筑为空即束
if XTool.IsTableEmpty(self._CurBuildCanBuildDir) then
XUiManager.TipErrorWithKey("PlanetRunningCantBuild")
self:_DeleteCurBuildData()
return false
end
local isFloorCanBuild = false
-- 非地板建筑存在不可造即结束
for _, canBuild in pairs(self._CurBuildCanBuildDir) do
if not self._CurBuildIsFloor and not canBuild then
XUiManager.TipErrorWithKey("PlanetRunningCantBuild")
self:_DeleteCurBuildData()
return false
elseif self._CurBuildIsFloor and canBuild then
isFloorCanBuild = true
end
end
-- 地板建筑皆不可造即结束
if self._CurBuildIsFloor and not isFloorCanBuild then
XUiManager.TipErrorWithKey("PlanetRunningCantBuild")
self:_DeleteCurBuildData()
return false
end
return true
end
--外部接口
--=============================================================
function XPlanetIScene:DeleteBuildingByGuid(guid, cb)
if not self:CheckIsHavePlanet() then
return
end
local build = self._Planet:GetBuildingByBuildGuid(guid)
if XTool.IsTableEmpty(build) then
return
end
if not XPlanetWorldConfigs.GetBuildingCanRecovery(build:GetBuildingId()) then
XUiManager.TipErrorWithKey("PlanetRunningNoCycle")
return
end
local buildingList = {}
table.insert(buildingList, build)
self:DeleteBuilding(buildingList, cb)
end
function XPlanetIScene:DeleteBuildingByTileId(tileId, cb)
local build = self._Planet:GetBuildingByTileId(tileId)
if XTool.IsTableEmpty(build) then
return
end
if not XPlanetWorldConfigs.GetBuildingCanRecovery(build:GetBuildingId()) then
XUiManager.TipErrorWithKey("PlanetRunningNoCycle")
return
end
local buildingList = {}
table.insert(buildingList, build)
self:DeleteBuilding(buildingList, cb)
end
function XPlanetIScene:DeleteBuilding(buildingList, cb)
if not self:CheckIsHavePlanet() then
return
end
if XTool.IsTableEmpty(buildingList) then
return
end
local callBack = function()
for _, build in ipairs(buildingList) do
self._Planet:RemoveBuilding(build:GetGuid(), false)
end
if cb then
cb()
end
end
if self:CheckIsTalentPlanet() then
XDataCenter.PlanetManager.RequestTalentDeleteBuild(buildingList, callBack)
else
XDataCenter.PlanetManager.RequestStageDeleteBuild(buildingList, callBack)
end
end
---松开卡牌请求建造
---@return boolean 前端请求是否通过
function XPlanetIScene:RequestInsertBuildingList(tileId, buildId, isQuickBuild)
if not self:CheckIsHavePlanet() or not XTool.IsNumberValid(buildId) then
return false
end
self:_CreateCurBuildData(tileId, buildId)
self:ChangeMode(XPlanetConfigs.SceneMode.InBuild)
if isQuickBuild then
self:InsertCurBuildingList()
else
self:PreSetCurBuildingList()
XEventManager.DispatchEvent(XEventId.EVENT_PLANET_IN_BUILD)
end
return true
end
---预放置建筑
function XPlanetIScene:PreSetCurBuildingList()
if XTool.IsTableEmpty(self._CurBuildingList) then
return
end
for index, building in ipairs(self._CurBuildingList) do
if self._CurBuildIsFloor then
if self._CurBuildCanBuildDir[index] and self:CheckBuildingCanBeBuild(self._CurBuildBuildingId, building:GetOccupyTileList()) then
self._Planet:UpdateBuildTile(building)
end
else
self._Planet:SetTempBuildingModel(building)
end
end
self:UpdateCurBuildTileMaterial()
end
---获取当前预放置建筑坐标(二次确认面板用)
function XPlanetIScene:GetCurPreBuildingListPosition()
if XTool.IsTableEmpty(self._CurBuildingList) then
return Vector3.zero
end
if self._CurBuildIsFloor then
return self:GetTileHeightPosition(self._CurBuildingList[1]:GetOccupyTileList()[1])
else
return self._Planet:GetTempModelPosition(self._CurBuildingList[1]:GetOccupyTileList())
end
end
---获取当前预放置建筑坐标(二次确认面板用)
function XPlanetIScene:GetCurBuildingList()
return self._CurBuildingList
end
---移动预放置建筑
function XPlanetIScene:MoveCurBuildingList(tileId)
if XTool.IsTableEmpty(self._CurBuildingList) then
return
end
self:ResetCurBuildTileMaterial()
if self._CurBuildIsFloor then
for index, building in ipairs(self._CurBuildingList) do
if self._CurBuildCanBuildDir[index] and self:CheckBuildingCanBeBuild(self._CurBuildBuildingId, building:GetOccupyTileList()) then
self._Planet:RemoveFloor(building, true)
end
end
self:_CreateCurBuildData(tileId, self._CurBuildBuildingId)
else
for key, building in ipairs(self._CurBuildingList) do
self._CurBuildSelectTileList[key] = tileId
--占地
self._CurBuildOccupyTileListDir[key] = self:_CreateBuildOccupyTileList(self._CurBuildSelectTileList[key], self._CurBuildBuildingId)
--范围
self._CurBuildRangeTileListDir[key] = self:_CreateBuildRangeTileList(self._CurBuildOccupyTileListDir[key], self._CurBuildBuildingId)
--能否建造
self._CurBuildCanBuildDir[key] = self:CheckBuildingCanBeBuild(self._CurBuildBuildingId, self._CurBuildOccupyTileListDir[key])
--赋值
building:SetOccupyTileList(self._CurBuildOccupyTileListDir[key])
building:SetRangeTileList(self._CurBuildRangeTileListDir[key])
end
end
self:PreSetCurBuildingList()
end
---旋转预放置建筑
function XPlanetIScene:RotateCurBuildingList()
if XTool.IsTableEmpty(self._CurBuildingList) then
return
end
self:ResetCurBuildTileMaterial()
local occupyType = XPlanetWorldConfigs.GetBuildingGridOccupyType(self._CurBuildBuildingId)
for key, building in ipairs(self._CurBuildingList) do
if occupyType == XPlanetWorldConfigs.GridOccupyType.Occupy3 then
--占地
self._CurBuildOccupyTileListDir[key] = self:_GetRotateBuildOccupy3TileList(building:GetOccupyTileList())
--范围
self._CurBuildRangeTileListDir[key] = self:_CreateBuildRangeTileList(self._CurBuildOccupyTileListDir[key], self._CurBuildBuildingId)
--能否建造
self._CurBuildCanBuildDir[key] = self:CheckBuildingCanBeBuild(self._CurBuildBuildingId, self._CurBuildOccupyTileListDir[key])
--赋值
building:SetOccupyTileList(self._CurBuildOccupyTileListDir[key])
building:SetRangeTileList(self._CurBuildRangeTileListDir[key])
self._Planet:SetTempBuildingModel(building)
self:UpdateCurBuildTileMaterial()
return
else
self._Planet:RotateBuilding(building, building:GetBuildingDirection())
end
end
self:UpdateCurBuildTileMaterial()
end
---移除预放置建筑
function XPlanetIScene:RemoveCurBuildingList()
self:ResetCurBuildTileMaterial()
self:_DeleteCurBuildData()
self:ChangeMode(XPlanetConfigs.SceneMode.None)
end
---确认摆放预放置建筑
function XPlanetIScene:InsertCurBuildingList()
-- 检查是否可造
if not self:_CheckCurBuildingListCanBuild() then
XEventManager.DispatchEvent(XEventId.EVENT_PLANET_RESUME_RUNNING, XPlanetExploreConfigs.PAUSE_REASON.BUILD)
self:ChangeMode(XPlanetConfigs.SceneMode.None)
return
end
local buildingList = {}
-- 批量建造中过滤不可造的
local guid = self:CheckIsTalentPlanet() and XDataCenter.PlanetManager.GetTalentBuildGuid() or XDataCenter.PlanetManager.GetStageBuildIncId()
for key, building in ipairs(self._CurBuildingList) do
if self._CurBuildCanBuildDir[key] then
building:SetId(guid + #buildingList) -- 重设guid
table.insert(buildingList, building)
end
end
if self:CheckIsTalentPlanet() then
XDataCenter.PlanetManager.RequestTalentInsertBuild(buildingList, handler(self, self._SetCurBuildIngList))
else
XDataCenter.PlanetManager.RequestStageInsertBuild(buildingList, handler(self, self._SetCurBuildIngList))
end
end
---更新当前卡牌选中占地材质
function XPlanetIScene:UpdateCurCardTileMaterial()
for key, occupyTileList in pairs(self._CurBuildOccupyTileListDir) do
for _, tileId in pairs(occupyTileList) do
local canOccupy = self:CheckTileCanBeBuildOccupy(tileId, self._CurBuildBuildingId)
local canBuild = self._CurBuildCanBuildDir[key]
self:_UpdateTileMaterial(tileId, canBuild, canOccupy)
end
-- 关卡场景刷范围
if not self:CheckIsTalentPlanet() then
for _, tileIdList in pairs(self._CurBuildRangeTileListDir[key]) do
for _, tileId in ipairs(tileIdList) do
self:_UpdateTileMaterial(tileId, false, false, true)
end
end
end
end
end
---还原当前卡牌选中占地材质
function XPlanetIScene:ResetCurCardTileMaterial()
for key, occupyTileList in pairs(self._CurBuildOccupyTileListDir) do
for _, tileId in pairs(occupyTileList) do
self:_ResetTileMaterial(tileId)
end
-- 关卡场景刷范围
if not self:CheckIsTalentPlanet() then
for _, tileIdList in pairs(self._CurBuildRangeTileListDir[key]) do
for _, tileId in ipairs(tileIdList) do
self:_ResetTileMaterial(tileId)
end
end
end
end
end
---更新预摆放建筑占地材质
function XPlanetIScene:UpdateCurBuildTileMaterial()
if not XTool.IsNumberValid(self._CurBuildBuildingId) then
return
end
if XTool.IsTableEmpty(self._CurBuildingList) then
return
end
for key, _ in pairs(self._CurBuildingList) do
for _, tileId in pairs(self._CurBuildOccupyTileListDir[key]) do
local canOccupy = self:CheckTileCanBeBuildOccupy(tileId, self._CurBuildBuildingId)
local canBuild = self._CurBuildCanBuildDir[key]
self:_UpdateTileMaterial(tileId, canBuild, canOccupy)
end
-- 关卡场景刷范围
if not self:CheckIsTalentPlanet() then
for _, tileIdList in pairs(self._CurBuildRangeTileListDir[key]) do
for _, tileId in ipairs(tileIdList) do
self:_UpdateTileMaterial(tileId, false, false, true)
end
end
end
end
end
---还原当前预摆放建筑占地材质
function XPlanetIScene:ResetCurBuildTileMaterial()
if not XTool.IsNumberValid(self._CurBuildBuildingId) then
return
end
if XTool.IsTableEmpty(self._CurBuildingList) then
return
end
for key, _ in pairs(self._CurBuildingList) do
for _, tileId in pairs(self._CurBuildOccupyTileListDir[key]) do
self:_ResetTileMaterial(tileId)
end
-- 关卡场景刷范围
if not self:CheckIsTalentPlanet() then
for _, tileIdList in pairs(self._CurBuildRangeTileListDir[key]) do
for _, tileId in ipairs(tileIdList) do
self:_ResetTileMaterial(tileId)
end
end
end
end
end
---@param building XPlanetBuilding
function XPlanetIScene:ShowRangeTileMaterial(building)
if self:CheckIsTalentPlanet() or XTool.IsTableEmpty(building) or XTool.IsTableEmpty(building:GetRangeTileList()) then
return
end
for _, rangeTileList in pairs(building:GetRangeTileList()) do
for _, tileId in ipairs(rangeTileList) do
self:_UpdateTileMaterial(tileId, false, false, true)
end
end
end
---@param building XPlanetBuilding
function XPlanetIScene:ResetRangeTileMaterial(building)
if self:CheckIsTalentPlanet() or XTool.IsTableEmpty(building) or XTool.IsTableEmpty(building:GetRangeTileList()) then
return
end
for _, rangeTileList in pairs(building:GetRangeTileList()) do
for _, tileId in ipairs(rangeTileList) do
self:_ResetTileMaterial(tileId)
end
end
end
--endregion
--region 星球操作数据接口
---球Transform
---@return Transform
function XPlanetIScene:GetPlanet()
if not self:CheckIsHavePlanet() then
return Vector3.zero
end
return self._Planet:GetTransform()
end
---球心坐标
---@return Vector3
function XPlanetIScene:GetPlanetPosition()
if not self:CheckIsHavePlanet() then
return Vector3.zero
end
return self._Planet:GetTransform().position
end
---地板:获取地块上表面中心坐标
function XPlanetIScene:GetTileHeightPosition(tileId)
if not self:CheckIsHavePlanet() then
return
end
local tile = self._Planet:GetTile(tileId)
return tile:GetHeightPosition()
end
---地板:获取地块up方向向量
function XPlanetIScene:GetTileUp(tileId)
if not self:CheckIsHavePlanet() then
return
end
return self._Planet:GetTile(tileId):GetTileUp()
end
---道路:获取星球道路网格起点
function XPlanetIScene:GetRoadMapStartPoint()
return XPlanetWorldConfigs.GetRoadStartPointByStageId(self._StageId)
end
---道路:获取道路下一个目标点
function XPlanetIScene:GetNextRoadTileId(tileId)
local map = self:GetRoadMap()
local roadTile = map[tileId]
if roadTile then
return map[tileId].NextPoint
end
return 0
end
---道路:获取道路上一个目标点
function XPlanetIScene:GetBeforeRoadTileId(tileId)
local map = self:GetRoadMap()
local roadTile = map[tileId]
if roadTile then
return map[tileId].BeforePoint
end
return 0
end
---道路:读取星球道路网格
function XPlanetIScene:GetRoadMap()
return XPlanetWorldConfigs.GetPlanetRoadMap(self._StageId)
end
function XPlanetIScene:GetBuildingList()
if not self:CheckIsHavePlanet() then
return false
end
return self._Planet:GetAllBuildingObj()
end
--endregion
--region 星球操作判断
---检查是否存在星球
function XPlanetIScene:CheckIsHavePlanet()
return self._Planet ~= nil
end
---检查是否存在相机
function XPlanetIScene:CheckIsHaveCamera()
return self:CheckIsHavePlanet() and self._PlanetCamera ~= nil
end
---检测该场景是否是天赋球场景
function XPlanetIScene:CheckIsTalentPlanet()
return XPlanetWorldConfigs.GetTalentStageId() == self._StageId
end
---建造:检查某地块是否可作为建筑的占地
function XPlanetIScene:CheckTileCanBeBuildOccupy(tileId)
if not self:CheckTileGridType(tileId, XPlanetWorldConfigs.GridType.BuildingGrid) then
return false
end
if self:CheckTileIsHaveBuild(tileId) then
return false
end
--if not self:CheckTileIsHexagon(tileId) then
-- return false
--end
return true
end
---建造:检查某建筑是否可建造
---@param buildingId number
---@param occupyTileList table
function XPlanetIScene:CheckBuildingCanBeBuild(buildingId, occupyTileList)
local tileCanBeOccupy = true
for _, tileId in ipairs(occupyTileList) do
if not self:CheckTileCanBeBuildOccupy(tileId) then
tileCanBeOccupy = false
end
end
if self:CheckIsTalentPlanet() then
return tileCanBeOccupy
end
local buildType = XPlanetWorldConfigs.GetBuildingBuildType(buildingId)
if buildType == XPlanetWorldConfigs.BuildType.RoadBuild or buildType == XPlanetWorldConfigs.BuildType.RoadCallMonsterBuild then
for _, tileId in ipairs(occupyTileList) do
local neighborIds = self._Planet:GetTile(tileId):GetNeighborIds()
for i = 0, neighborIds.Count - 1 do
local id = neighborIds[i]
if self:CheckTileGridType(id, XPlanetWorldConfigs.GridType.RoadGrid) then
return tileCanBeOccupy
end
end
end
return false
end
return tileCanBeOccupy
end
---地块:检查两地块是否是相邻
function XPlanetIScene:CheckTileIsNeighbor(tileIdA, tileIdB)
if not self:CheckIsHavePlanet() then
return false
end
return self._Planet:GetTile(tileIdA):CheckIsNeighbor(tileIdB)
end
---检查地板类型
---@param gridType number XPlanetWorldConfigs.GridType
function XPlanetIScene:CheckTileGridType(tileId, gridType)
local tileData = self._Planet:GetTileData(tileId)
if XTool.IsTableEmpty(tileData) then
return false
end
return tileData:GetGridType() == gridType
end
---检查地块是否有建筑
function XPlanetIScene:CheckTileIsHaveBuild(tileId)
local tileData = self._Planet:GetTileData(tileId)
if XTool.IsTableEmpty(tileData) then
return false
end
return tileData:GetBuildingGuid() >= 0
end
---检查地块是默认建筑
function XPlanetIScene:CheckTileIsDefaultBuild(tileId)
local tileData = self._Planet:GetTileData(tileId)
if XTool.IsTableEmpty(tileData) then
return false
end
return XTool.IsNumberValid(tileData:GetBuildingCenter())
end
---检查地块是否是六边形
function XPlanetIScene:CheckTileIsHexagon(tileId)
local tile = self._Planet:GetTile(tileId)
if XTool.UObjIsNil(tile) then
return false
end
return tile.isHexagon
end
--endregion
--region 场景加载
function XPlanetIScene:OnLoadSuccess()
self:InitPlanetRoot()
self:InitAirEffect()
self:InitSceneEffect()
self:InitSkyBox()
self:InitTopNode()
self.GoInputHandler = self._PlanetRoot:GetComponent(typeof(CS.XGoInputHandler))
if XTool.UObjIsNil(self.GoInputHandler) then
self.GoInputHandler = self._PlanetRoot.gameObject:AddComponent(typeof(CS.XGoInputHandler))
end
end
function XPlanetIScene:Load(onLoadCb)
if not self:CheckBeforeLoad() then
return
end
local assetPath = self:GetAssetPath()
local resource = CS.XResourceManager.LoadAsync(assetPath)
CS.XTool.WaitCoroutine(resource, function()
if not (resource and resource.Asset) then
XLog.Error("restaurant load resource error: asset path = " .. assetPath)
return
end
self._Resource = resource
self._GameObject = XUiHelper.Instantiate(resource.Asset)
if not XTool.UObjIsNil(self._GameObject) then
self._Transform = self._GameObject.transform
self:ResetTransform()
self._GameObject.name = self:GetObjName()
end
self:OnLoadSuccess()
self:InitCamera()
self:InitPlanet(function()
self:SetSkyBox()
self:SetSceneEffect()
self:SetTopNode(self._PlanetCamera:GetCameraTransform(), self._Planet:GetTransform())
self:InitAfterLoad()
if onLoadCb then
onLoadCb()
end
end)
end)
end
---加载模型后初始化接口
function XPlanetIScene:InitAfterLoad()
end
function XPlanetIScene:Release()
self:TryDestroy(self._GameObject)
self._GameObject = nil
self._Transform = nil
if self._Resource then
self._Resource:Release()
self._Resource = nil
end
if self._Planet then
self._Planet:Release()
end
if self._PlanetCamera then
self._PlanetCamera:Release()
end
self._Planet = nil
self._PlanetCamera = nil
self._EffectStar = nil
self._EffectLiuXing = nil
self:ClearUiEventListener()
end
function XPlanetIScene:SetActive(active)
if not self:Exist() then
return
end
self._GameObject:SetActiveEx(active)
end
--endregion
--region 场景对象初始化
function XPlanetIScene:InitSceneEffect()
self._GroupParticle = self._GameObject:FindTransform("GroupParticle")
if XTool.UObjIsNil(self._GroupParticle) then
return
end
self._EffectLiuXing = self._GroupParticle.gameObject:FindTransform("Fx03604liiuxing")
end
function XPlanetIScene:SetSceneEffect()
if self._GroupParticle then
self._GroupParticle:SetParent(self._PlanetCamera:GetCameraTransform(), false)
self._GroupParticle.transform.localPosition = Vector3.zero
self._GroupParticle.transform.localRotation = CS.UnityEngine.Quaternion.identity
self._GroupParticle.transform.localScale = Vector3.one
end
if self._EffectLiuXing then
self._EffectLiuXing:SetParent(self._PlanetAirEffectRoot, false)
self._EffectLiuXing.transform.position = Vector3(0, 0, 50)
end
end
function XPlanetIScene:InitAirEffect()
self._PlanetAirEffectRoot = self._Transform:Find("GroupBase/PlanetAirEffectRoot")
if XTool.UObjIsNil(self._PlanetAirEffectRoot) then
return
end
self._AirEffect = self._PlanetAirEffectRoot:GetChild(0)
self._AirEffect.localPosition = Vector3.zero
end
function XPlanetIScene:InitPlanetRoot()
self._PlanetRoot = self._Transform:Find("GroupBase/PlanetRoot")
if XTool.UObjIsNil(self._PlanetRoot) then
local groupBase = self._Transform:Find("GroupBase")
local go = CS.UnityEngine.GameObject("PlanetRoot")
go.transform:SetParent(groupBase, false)
self:TryResetTransform(go.transform)
self._PlanetRoot = go.transform
end
end
function XPlanetIScene:InitSkyBox()
if XTool.UObjIsNil(self._XSkyBox) then
self._XSkyBox = self._GameObject:FindTransform("XSkybox")
self._XSkyBox.localPosition = Vector3.zero
end
end
function XPlanetIScene:SetSkyBox()
if self._XSkyBox then
self._XSkyBox:SetParent(self._PlanetCamera:GetCameraTransform(), false)
self._XSkyBox.transform.localPosition = XPlanetConfigs.GetPositionByKey("SkyBoxOffset")
self._XSkyBox.transform.localRotation = XPlanetConfigs.GetRotationByKey("SkyBoxRotation")
self._XSkyBox.transform.localScale = XPlanetConfigs.GetPositionByKey("SkyBoxScale")
end
end
function XPlanetIScene:InitTopNode()
local topNodeTran = self._Transform:Find("GroupBase/TopNode")
if XTool.UObjIsNil(topNodeTran) then
return
end
self._PlanetTopNode = topNodeTran.gameObject:GetComponent(typeof(CS.PlanetTopNode))
end
function XPlanetIScene:SetTopNode(camTran, planetTran)
if not self._PlanetTopNode then
return
end
self._PlanetTopNode.CameraNode = camTran
self._PlanetTopNode.PlanetNode = planetTran
end
function XPlanetIScene:InitCamera()
local cameraRoot = self._Transform:Find("CameraRoot")
if XTool.UObjIsNil(cameraRoot) then
local go = CS.UnityEngine.GameObject("CameraRoot")
go.transform:SetParent(self._Transform, false)
self:TryResetTransform(go.transform)
cameraRoot = go
end
if XTool.UObjIsNil(self._PlanetCamera) then
self._PlanetCamera = XPlanetCamera.New(self._Transform, cameraRoot)
end
self:RegisterUiEventListener(function()
self._PlanetCamera:FreeModeBeginDrag()
end, XPlanetConfigs.SceneUiEventType.OnBeginDrag)
self:RegisterUiEventListener(function(eventData)
self._PlanetCamera:FreeModeOnDrag(eventData)
end, XPlanetConfigs.SceneUiEventType.OnDrag)
self:RegisterUiEventListener(function()
self._PlanetCamera:FreeModeEndDrag()
end, XPlanetConfigs.SceneUiEventType.OnEndDrag)
end
function XPlanetIScene:InitPlanet(onLoadCb)
self._Planet = XPlanet.New(self._PlanetRoot, self._StageId)
self._Planet:Load(onLoadCb)
end
--endregion
--region 场景交互
---注册交互响应
---@param func function function(eventData)
---@param uiEventType number XPlanetConfigs.SceneUiEventType 交互类型
function XPlanetIScene:RegisterUiEventListener(func, uiEventType)
if XTool.UObjIsNil(self.GoInputHandler) then
return
end
if uiEventType == XPlanetConfigs.SceneUiEventType.OnClick then
self.GoInputHandler:AddPointerClickListener(func)
elseif uiEventType == XPlanetConfigs.SceneUiEventType.OnPointerDown then
self.GoInputHandler:AddPointerDownListener(func)
elseif uiEventType == XPlanetConfigs.SceneUiEventType.OnPointerUp then
self.GoInputHandler:AddPointerUpListener(func)
elseif uiEventType == XPlanetConfigs.SceneUiEventType.OnBeginDrag then
self.GoInputHandler:AddBeginDragListener(func)
elseif uiEventType == XPlanetConfigs.SceneUiEventType.OnDrag then
self.GoInputHandler:AddDragListener(func)
elseif uiEventType == XPlanetConfigs.SceneUiEventType.OnEndDrag then
self.GoInputHandler:AddEndDragListener(func)
end
end
---清空交互响应事件
function XPlanetIScene:ClearUiEventListener()
if XTool.UObjIsNil(self.GoInputHandler) then
return
end
self.GoInputHandler:RemoveAllListeners()
end
---当拖拽建筑卡牌时
---@param buildId number
function XPlanetIScene:OnDragBuildCard(buildId, cb, tile)
if not self:CheckIsInNoneMode() then
return
end
self:ResetCurCardTileMaterial()
if not XTool.IsNumberValid(buildId) then
return
end
if not tile then
tile = self:GetCameraRayTile()
end
if XTool.UObjIsNil(tile) then
return
end
local tileId = tile.TileId
self:_CreateCurBuildData(tileId, buildId)
self:UpdateCurCardTileMaterial()
end
---当松开建筑卡牌时
---@param buildId number
---@param isQuickBuild boolean
function XPlanetIScene:OnEndDragBuildCard(buildId, isQuickBuild, cb, tile)
if not self:CheckIsInNoneMode() then
return
end
if not XTool.IsNumberValid(buildId) then
return
end
self:ResetCurCardTileMaterial()
if not tile then
tile = self:GetCameraRayTile()
end
if XTool.UObjIsNil(tile) then
XEventManager.DispatchEvent(XEventId.EVENT_PLANET_RESUME_RUNNING, XPlanetExploreConfigs.PAUSE_REASON.BUILD)
return
end
local tileId = tile.TileId
--self._PlanetCamera:FreeModeLookAt(tile.transform.position)
if not self:RequestInsertBuildingList(tileId, buildId, isQuickBuild, cb) then
XEventManager.DispatchEvent(XEventId.EVENT_PLANET_RESUME_RUNNING, XPlanetExploreConfigs.PAUSE_REASON.BUILD)
end
end
--endregion
return XPlanetIScene