public LevelEntity_Media(short index, Media media, LevelEntity_Level level) { NativeIndex = index; NativeObject = media; ParentLevel = level; BeginRuntimeStyleBehavior(); }
public virtual void InitializeEntity(LevelEntity_Level parentLevel, short nativeIndex, object nativeObject) { ParentLevel = parentLevel; NativeIndex = nativeIndex; this.NativeObject = nativeObject; AssembleEntity(); }
private async Task BuildLevel() { #if !UNITY_EDITOR GarbageCollector.GCMode = GarbageCollector.Mode.Disabled; #endif var initializeLevelStartTime = DateTime.Now; runtimeLevel = new GameObject($"Level ({LevelName})").AddComponent <LevelEntity_Level>(); runtimeLevel.Level = level; runtimeLevel.Index = (short)LevelIndex; runtimeLevel.Polygons = new Dictionary <short, LevelEntity_Polygon>(); runtimeLevel.Lines = new Dictionary <short, LevelEntity_Line>(); runtimeLevel.Sides = new Dictionary <short, LevelEntity_Side>(); runtimeLevel.Lights = new Dictionary <short, LevelEntity_Light>(); runtimeLevel.Medias = new Dictionary <short, LevelEntity_Media>(); runtimeLevel.CeilingPlatforms = new Dictionary <short, LevelEntity_Platform>(); runtimeLevel.FloorPlatforms = new Dictionary <short, LevelEntity_Platform>(); runtimeLevel.MapObjects = new Dictionary <short, LevelEntity_MapObject>(); runtimeLevel.Annotations = new Dictionary <short, LevelEntity_Annotation>(); runtimeLevel.EditableSurface_Polygons = new List <EditableSurface_Polygon>(); runtimeLevel.EditableSurface_Sides = new List <EditableSurface_Side>(); runtimeLevel.EditableSurface_Medias = new List <EditableSurface_Media>(); // Clear out Walls Materials so it can be repopulated with the correct set MaterialGeneration_Geometry.ClearCollection(); Debug.Log($"--- LevelBuild: Initialized Level in timespan: {DateTime.Now - initializeLevelStartTime}"); await Task.Yield(); #region Initialization_Textures var buildTexturesStartTime = DateTime.Now; #if !NO_EDITING // Initialize Textures here so they in proper index order for the texturing interface var landscapeShapeDescriptor = new ShapeDescriptor(); // Note: Landscape collections in Shapes are respectively sequential to Landscape map info starting at 27 landscapeShapeDescriptor.Collection = (byte)(level.Landscape + 27); MaterialGeneration_Geometry.GetTexture(landscapeShapeDescriptor, returnPlaceholderIfNotFound: false); var wallShapeDescriptor = new ShapeDescriptor(); // Note: Walls collections in Shapes are respectively sequential to Environment map info starting at 17 wallShapeDescriptor.Collection = (byte)(level.Environment + 17); for (var i = 0; i < 256; i++) { wallShapeDescriptor.Bitmap = (byte)i; if (!MaterialGeneration_Geometry.GetTexture(wallShapeDescriptor, returnPlaceholderIfNotFound: false)) { break; } } #endif Debug.Log($"--- LevelBuild: Built Textures in timespan: {DateTime.Now - buildTexturesStartTime}"); #endregion Initialization_Textures await Task.Yield(); #region Initialization_Lights var buildLightsStartTime = DateTime.Now; // Initialize Lights here so they are in proper index order for (var i = 0; i < level.Lights.Count; i++) { runtimeLevel.Lights[(short)i] = new LevelEntity_Light((short)i, level.Lights[i], runtimeLevel); } Debug.Log($"--- LevelBuild: Built & started Lights in timespan: {DateTime.Now - buildLightsStartTime}"); #endregion Initialization_Lights await Task.Yield(); #region Initialization_Medias var buildMediasStartTime = DateTime.Now; // Initialize Medias here so they are in proper index order for (var i = 0; i < level.Medias.Count; i++) { runtimeLevel.Medias[(short)i] = new LevelEntity_Media((short)i, level.Medias[i], runtimeLevel); } Debug.Log($"--- LevelBuild: Built & started Medias in timespan: {DateTime.Now - buildMediasStartTime}"); #endregion Initialization_Medias await Task.Yield(); #if USE_TEXTURE_ARRAYS MaterialGeneration_Geometry.TextureArraysArePopulating = true; #endif var chunkLoadStartTime = DateTime.Now; #region Polygons_And_Media var buildPolygonsStartTime = DateTime.Now; var polygonsGroupGO = new GameObject("Polygons"); polygonsGroupGO.transform.SetParent(runtimeLevel.transform); for (short polygonIndex = 0; polygonIndex < level.Polygons.Count; polygonIndex++) { var polygon = level.Polygons[polygonIndex]; var polygonRootGO = new GameObject($"Polygon ({polygonIndex})"); polygonRootGO.transform.SetParent(polygonsGroupGO.transform); var runtimePolygon = polygonRootGO.AddComponent <LevelEntity_Polygon>(); runtimeLevel.Polygons[polygonIndex] = runtimePolygon; runtimePolygon.InitializeEntity(runtimeLevel, polygonIndex, polygon); chunkLoadStartTime = await ChunkLoadYield(chunkLoadStartTime); } Debug.Log($"--- LevelBuild: Built Polygons, Medias, & Platforms in timespan: {DateTime.Now - buildPolygonsStartTime}"); #endregion Polygons_And_Media await Task.Yield(); #region Lines_And_Sides var buildSidesStartTime = DateTime.Now; var linesGroupGO = new GameObject("Lines"); linesGroupGO.transform.SetParent(runtimeLevel.transform); for (short lineIndex = 0; lineIndex < level.Lines.Count; lineIndex++) { GameObject lineRootGO = new GameObject($"Line ({lineIndex})"); lineRootGO.transform.SetParent(linesGroupGO.transform); var line = level.Lines[lineIndex]; var runtimeLine = lineRootGO.AddComponent <LevelEntity_Line>(); runtimeLevel.Lines[lineIndex] = runtimeLine; runtimeLine.NativeIndex = lineIndex; runtimeLine.NativeObject = line; runtimeLine.ParentLevel = runtimeLevel; runtimeLine.GenerateSurfaces(); chunkLoadStartTime = await ChunkLoadYield(chunkLoadStartTime); } Debug.Log($"--- LevelBuild: Built Lines & Sides in timespan: {DateTime.Now - buildSidesStartTime}"); #endregion Lines_And_Sides await Task.Yield(); #if USE_TEXTURE_ARRAYS MaterialGeneration_Geometry.ApplyTextureArrays(); MaterialGeneration_Geometry.TextureArraysArePopulating = false; await Task.Yield(); #endif #region Objects_And_Placements var buildObjectsStartTime = DateTime.Now; var mapObjectsGroupGO = new GameObject("MapObjects"); mapObjectsGroupGO.transform.SetParent(runtimeLevel.transform); for (short objectIndex = 0; objectIndex < level.Objects.Count; objectIndex++) { var mapObject = level.Objects[objectIndex]; var mapObjectRootGO = new GameObject($"MapObject: {mapObject.Type} ({objectIndex})"); mapObjectRootGO.transform.SetParent(mapObjectsGroupGO.transform); var runtimeMapObject = mapObjectRootGO.AddComponent <LevelEntity_MapObject>(); runtimeLevel.MapObjects[(short)objectIndex] = runtimeMapObject; runtimeMapObject.NativeIndex = (short)objectIndex; runtimeMapObject.NativeObject = mapObject; runtimeMapObject.ParentLevel = runtimeLevel; runtimeMapObject.GenerateObject(); chunkLoadStartTime = await ChunkLoadYield(chunkLoadStartTime); } Debug.Log($"--- LevelBuild: Built Objects in timespan: {DateTime.Now - buildObjectsStartTime}"); #endregion Objects_And_Placements await Task.Yield(); #region Annotations var annotationsGroupGO = new GameObject("Annotations"); annotationsGroupGO.transform.SetParent(runtimeLevel.transform); for (var i = 0; i < level.Annotations.Count; i++) { var annotation = level.Annotations[i]; var annotationInstance = UnityEngine.Object.Instantiate(LevelEntity_Annotation.Prefab); annotationInstance.NativeIndex = (short)i; annotationInstance.NativeObject = annotation; annotationInstance.ParentLevel = runtimeLevel; annotationInstance.RefreshLabel(); var positionalHeight = (runtimeLevel.Polygons[annotation.PolygonIndex].NativeObject.FloorHeight + runtimeLevel.Polygons[annotation.PolygonIndex].NativeObject.CeilingHeight) / 2f / GeometryUtilities.WorldUnitIncrementsPerMeter; annotationInstance.transform.position = new Vector3(annotation.X / GeometryUtilities.WorldUnitIncrementsPerMeter, positionalHeight, -annotation.Y / GeometryUtilities.WorldUnitIncrementsPerMeter); annotationInstance.transform.SetParent(annotationsGroupGO.transform, worldPositionStays: true); runtimeLevel.Annotations[(short)i] = annotationInstance; } #endregion Annotations await Task.Yield(); #if !UNITY_EDITOR GarbageCollector.GCMode = GarbageCollector.Mode.Enabled; #endif }
public override void InitializeEntity(LevelEntity_Level parentLevel, short nativeIndex, object nativeObject) { base.InitializeEntity(parentLevel, nativeIndex, nativeObject); }
public static LevelEntity_Side AssembleEntity(LevelEntity_Level level, bool isClockwise, short lineIndex) { var line = level.Level.Lines[lineIndex]; var sideIndex = isClockwise ? line.ClockwisePolygonSideIndex : line.CounterclockwisePolygonSideIndex; // Note: A null-side may still be created as an untextured side var side = sideIndex < level.Level.Sides.Count && sideIndex >= 0 ? level.Level.Sides[sideIndex] : null; #region Facing_Elevations var facingPolygonIndex = isClockwise ? line.ClockwisePolygonOwner : line.CounterclockwisePolygonOwner; if (facingPolygonIndex < 0) { return(null); } var facingPolygon = level.Level.Polygons[facingPolygonIndex]; Platform facingPlatform; facingPlatform = GeometryUtilities.GetPlatformForPolygon(level.Level, facingPolygon); var highestFacingCeiling = facingPolygon.CeilingHeight; var lowestFacingFloor = facingPolygon.FloorHeight; if (facingPlatform != null) { if (facingPlatform.ComesFromFloor && facingPlatform.ComesFromCeiling) { var roundedMidpoint = (short)Mathf.RoundToInt((facingPlatform.RuntimeMinimumHeight(level.Level) + facingPlatform.RuntimeMaximumHeight(level.Level)) * 0.5f); highestFacingCeiling = (short)Mathf.Max(highestFacingCeiling, roundedMidpoint); lowestFacingFloor = (short)Mathf.Min(lowestFacingFloor, roundedMidpoint); } else if (facingPlatform.ComesFromFloor) { lowestFacingFloor = (short)Mathf.Min(lowestFacingFloor, facingPlatform.RuntimeMinimumHeight(level.Level)); } else if (facingPlatform.ComesFromCeiling) { highestFacingCeiling = (short)Mathf.Max(highestFacingCeiling, facingPlatform.RuntimeMaximumHeight(level.Level)); } } #endregion Facing_Elevations #region Opposing_Elevations var opposingPolygonIndex = isClockwise ? line.CounterclockwisePolygonOwner : line.ClockwisePolygonOwner; var hasOpposingPolygon = opposingPolygonIndex >= 0; var opposingPolygon = hasOpposingPolygon ? level.Level.Polygons[opposingPolygonIndex] : null; Platform opposingPlatform = null; if (opposingPolygon != null) { opposingPlatform = GeometryUtilities.GetPlatformForPolygon(level.Level, opposingPolygon); } var lowestOpposingCeiling = hasOpposingPolygon ? opposingPolygon.CeilingHeight : highestFacingCeiling; var highestOpposingCeiling = lowestOpposingCeiling; var highestOpposingFloor = hasOpposingPolygon ? opposingPolygon.FloorHeight : lowestFacingFloor; var lowestOpposingFloor = highestOpposingFloor; if (opposingPlatform != null) { if (opposingPlatform.ComesFromFloor && opposingPlatform.ComesFromCeiling) { var roundedMidpoint = (short)Mathf.RoundToInt((opposingPlatform.RuntimeMinimumHeight(level.Level) + opposingPlatform.RuntimeMaximumHeight(level.Level)) * 0.5f); highestOpposingFloor = (short)Mathf.Max(highestOpposingFloor, roundedMidpoint); lowestOpposingCeiling = (short)Mathf.Min(lowestOpposingCeiling, roundedMidpoint); } else if (opposingPlatform.ComesFromFloor) { highestOpposingFloor = (short)Mathf.Max(highestOpposingFloor, opposingPlatform.RuntimeMaximumHeight(level.Level)); lowestOpposingFloor = opposingPlatform.RuntimeMinimumHeight(level.Level); } else if (opposingPlatform.ComesFromCeiling) { highestOpposingCeiling = opposingPlatform.RuntimeMaximumHeight(level.Level); lowestOpposingCeiling = (short)Mathf.Min(lowestOpposingCeiling, opposingPlatform.RuntimeMinimumHeight(level.Level)); } } #endregion Opposing_Elevations #region Exposure_Determination // Data-driven surface-exposure var dataExpectsFullSide = side != null && side.Type == SideType.Full && !side.Primary.Texture.IsEmpty(); var dataExpectsTop = !dataExpectsFullSide && side != null && (side.Type == SideType.High || side.Type == SideType.Split); // Geometry-driven surface-exposure var exposesTop = !dataExpectsFullSide && hasOpposingPolygon && highestFacingCeiling > lowestOpposingCeiling; var exposesMiddle = (!hasOpposingPolygon || (line.Flags & LineFlags.HasTransparentSide) != 0 || dataExpectsFullSide) && highestFacingCeiling > lowestFacingFloor && (highestOpposingCeiling > lowestOpposingFloor || dataExpectsFullSide); var exposesBottom = !dataExpectsFullSide && hasOpposingPolygon && highestOpposingFloor > lowestFacingFloor; #endregion Exposure_Determination #region Surface_Assembly LevelEntity_Side runtimeSide = null; if (exposesTop) { // Top is always Primary var sideDataSource = DataSources.Primary; var highHeight = highestFacingCeiling; var lowHeight = lowestOpposingCeiling; CreateSideRoot(ref runtimeSide, isClockwise, sideIndex, side, level, lineIndex); runtimeSide.PrimaryHighElevation = highHeight; runtimeSide.PrimaryLowElevation = lowHeight; var surface = new GameObject($"Side Top ({sideIndex}) (High - Source:{sideDataSource})").AddComponent <RuntimeSurfaceGeometry>(); surface.transform.SetParent(runtimeSide.transform); surface.InitializeRuntimeSurface(runtimeSide, sideDataSource); runtimeSide.PrimarySurface = surface; runtimeSide.TopSurface = surface; } if (exposesMiddle) { // Primary if there's no opposing polygon or it's explicitly "full", Transparent otherwise var sideDataSource = (!hasOpposingPolygon || dataExpectsFullSide) ? DataSources.Primary : DataSources.Transparent; var hasLayeredTransparentSide = side.HasLayeredTransparentSide(level.Level); var highHeight = dataExpectsFullSide ? highestFacingCeiling : line.LowestAdjacentCeiling; var lowHeight = dataExpectsFullSide ? lowestFacingFloor : line.HighestAdjacentFloor; var typeDescriptor = hasOpposingPolygon ? $"Transparent - HasTransparentSide - Source:{sideDataSource}" : $"Full - Unopposed - Source:{sideDataSource}"; CreateSideRoot(ref runtimeSide, isClockwise, sideIndex, side, level, lineIndex); if (sideDataSource == DataSources.Primary) { runtimeSide.PrimaryHighElevation = highHeight; runtimeSide.PrimaryLowElevation = lowHeight; } if (sideDataSource == DataSources.Transparent || hasLayeredTransparentSide) { runtimeSide.TransparentHighElevation = highHeight; runtimeSide.TransparentLowElevation = lowHeight; } var surface = new GameObject($"Side Middle ({sideIndex}) - ({typeDescriptor})").AddComponent <RuntimeSurfaceGeometry>(); surface.transform.SetParent(runtimeSide.transform); surface.InitializeRuntimeSurface(runtimeSide, sideDataSource); if (sideDataSource == DataSources.Primary) { runtimeSide.PrimarySurface = surface; } if (sideDataSource == DataSources.Transparent || hasLayeredTransparentSide) { runtimeSide.TransparentSurface = surface; } runtimeSide.MiddleSurface = surface; } if (exposesBottom) { // Secondary if there is an exposable or expected (in data) top section var sideDataSource = dataExpectsTop ? DataSources.Secondary : DataSources.Primary; var highHeight = highestOpposingFloor; var lowHeight = lowestFacingFloor; CreateSideRoot(ref runtimeSide, isClockwise, sideIndex, side, level, lineIndex); if (sideDataSource == DataSources.Primary) { runtimeSide.PrimaryHighElevation = highHeight; runtimeSide.PrimaryLowElevation = lowHeight; } else { runtimeSide.SecondaryHighElevation = highHeight; runtimeSide.SecondaryLowElevation = lowHeight; } var surface = new GameObject($"Side Bottom ({sideIndex}) (Low - Source:{sideDataSource})").AddComponent <RuntimeSurfaceGeometry>(); surface.transform.SetParent(runtimeSide.transform); surface.InitializeRuntimeSurface(runtimeSide, sideDataSource); if (sideDataSource == DataSources.Primary) { runtimeSide.PrimarySurface = surface; } else { runtimeSide.SecondarySurface = surface; } runtimeSide.BottomSurface = surface; } #endregion Surface_Assembly return(runtimeSide); }
private static void CreateSideRoot(ref LevelEntity_Side runtimeSide, bool isClockwise, short sideIndex, Side side, LevelEntity_Level parentLevel, short parentLineIndex) { if (!runtimeSide) { var sideGO = new GameObject(isClockwise ? $"Clockwise ({sideIndex})" : $"Counterclockwise ({sideIndex})"); runtimeSide = sideGO.AddComponent <LevelEntity_Side>(); runtimeSide.ParentLineIndex = parentLineIndex; runtimeSide.IsClockwise = isClockwise; runtimeSide.InitializeEntity(parentLevel, sideIndex, side); parentLevel.Sides[sideIndex] = runtimeSide; } }