/// <summary> /// Adds an error message to the root element and explains it /// </summary> /// <param name="message"></param> /// <param name="explain"></param> public virtual void AddErrorAndExplain(string message, ExplanationPart explain) { if (RootLog != null) { RootLog.AddError(message); } }
/// <summary> /// Adds an error message to the root element /// </summary> /// <param name="message"></param> public void AddWarning(string message) { if (RootLog != null) { RootLog.AddWarning(message); } }
/// <summary> /// Adds an error message to the root element /// </summary> /// <param name="message"></param> /// <param name="id"></param> public void AddError(string message, RuleCheck.RuleChecksEnum id) { if (RootLog != null) { RootLog.AddRuleCheckMessage(id, ElementLog.LevelEnum.Error, message); } }
/// <summary> /// Adds an error message to the root element and explains it /// </summary> /// <param name="message"></param> /// <param name="explain"></param> public override void AddErrorAndExplain(string message, ExplanationPart explain) { if (RootLog != null) { ExplanationPart.CreateSubExplanation(explain, message); RootLog.AddErrorAndExplain(message, explain); } }
protected void NotifyNoListeners() { if (ShowWarnings) { RootLog.Log( "Event had no listeners.", Severity.Warning, "RootLog" ); } }
// ~~ private // ~ Non-Static // ~~ public // ~~ private private void Awake() { if (!InstanceValidation.SingleInstanceExists <EventSystem>()) { RootLog.Log( "No event system.", Severity.Warning ); } gameObject.name = "Root Windows"; _windowManager = gameObject.AddComponent <WindowManager>(); Debug.Log("Subscribing WindowManager to RootWindows events."); _subjectEvent = new RootEvent <string, ISubject>(); _registerDataEvent = new RootEvent <string, IViewData, string>(); _registerSelfAbilityEvent = new RootEvent <string, Action, Action, string>(); _registerLocationAbilityEvent = new RootEvent <string, Action, Action <Vector3>, string>(); _registerObjectAbilityEvent = new RootEvent <string, Action, Action <GameObject[]>, string>(); _deregisterDataEvent = new RootEvent <string, IViewData, string>(); _deregisterSelfAbilityEvent = new RootEvent <string, Action, Action, string>(); _deregisterLocationAbilityEvent = new RootEvent <string, Action, Action <Vector3>, string>(); _deregisterObjectAbilityEvent = new RootEvent <string, Action, Action <GameObject[]>, string>(); _setBGColorEvent = new RootEvent <string, Color, string>(); _subjectEvent.Subscribe(HandleSubject); _registerDataEvent.Subscribe(HandleRegisterData); _registerSelfAbilityEvent.Subscribe(HandleRegisterSelfAbility); _registerLocationAbilityEvent.Subscribe(HandleRegisterLocationAbility); _registerObjectAbilityEvent.Subscribe(HandleRegisterObjectAbility); _deregisterDataEvent.Subscribe(HandleDeregisterData); _deregisterSelfAbilityEvent.Subscribe(HandleDeregisterSelfAbility); _deregisterLocationAbilityEvent.Subscribe(HandleDeregisterLocationAbility); _deregisterObjectAbilityEvent.Subscribe(HandleDeregisterObjectAbility); _setBGColorEvent.Subscribe(HandleSetBGColor); }
public void Draw( float hexOuterRadius ) { if (HexGrid == null) { throw new NullHexGridException(); } _hexShaderData.Initialize( HexOffsetColumns, HexOffsetRows ); foreach (Hex hex in HexGrid.Hexes) { _hexShaderData.RefreshTerrain(hex); } string diagnostic = "Mesh Triangulation Diagnostics\n\n"; Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); foreach (MapMeshChunk chunk in HexMeshChunks) { chunk.Triangulate( this, hexOuterRadius, AdjacencyGraph, RiverDigraph, RoadUndirectedGraph, CreateElevationDigraph ); } stopwatch.Stop(); diagnostic += "All mesh chunks triangulated in: " + stopwatch.Elapsed; RootLog.Log( diagnostic, Severity.Information, "Diagnostic" ); }
/// <summary> /// Serializes the instance to JSON and saves to Application.persistentDataPath. /// </summary> /// <param fileName="configName">The name of the config.</param> public void ToJson(string fileName) { if (HasDigits(fileName)) { RootLog.Log( "Attempted to serialize a RootGenConfig to JSON with a" + " file name containing digits. Removing digits from file name." ); fileName = RemoveDigits(fileName); } string json = JsonUtility.ToJson(this, true); string path = Path.Combine(Application.persistentDataPath, fileName + ".json"); int numDuplicate = 0; while (File.Exists(path)) { numDuplicate++; path = Path.Combine(Application.persistentDataPath, fileName + numDuplicate + ".json"); RootLog.Log( "Serialized RootGenConfig data with file name " + fileName + " already exists. Attempting to " + " write as " + fileName + numDuplicate, Severity.Warning ); } StreamWriter sw = new StreamWriter(path, false); sw.Write(json); string instances = numDuplicate > 0 ? numDuplicate.ToString() : ""; RootLog.Log( "RootGenConfigData serialized to " + Application.persistentDataPath + " as " + fileName + instances, Severity.Information ); sw.Close(); }
public bool AddHex(int index, Hex hex) { try { Hexes[index] = hex; hex.chunk = this; // Set WorldPositionStays to false for both the hexes transform and // ui rect or they will not move initally to be oriented with the // chunk. hex.transform.SetParent(transform, false); hex.uiRect.SetParent(WorldSpaceUICanvas.transform, false); return(true); } catch (System.IndexOutOfRangeException) { RootLog.Log( "The specified hex " + hex + " could not be added to " + " the mesh chunk because the specified index " + index + " was outside the bounds of the chunks hex array." ); return(false); } }
public List <MapRegionRect> SubdivideVertical(int border = 0) { if (this.OffsetSizeZ - border < 3) { RootLog.Log( "Border cannot reduce z dimension below 3 or divison " + "will be impossible. Setting border to 0.", Severity.Debug, "MapGenerator" ); border = 0; } List <MapRegionRect> result = new List <MapRegionRect>(); result.Add( new MapRegionRect( this.OffsetXMin, this.OffsetXCenter - border, this.OffsetZMin, this.OffsetZMax ) ); result.Add( new MapRegionRect( this.OffsetXCenter + border, this.OffsetXMax, this.OffsetZMin, this.OffsetZMax ) ); return(result); }
/// <summary> /// Initialize the hex map to an empty flat plain. /// </summary> /// <param name="bounds"> /// A bounds object representing the dimensions of the hex map. Will /// be scaled to fit within a multiple of MeshConstants.ChunkSize. /// </param> /// <param name="wrapping"> /// Should the horizontal bounds of the grid wrap into their opposite /// side? /// </param> /// <param name="editMode"> /// Should the map be editable immediately after being initialized? /// </param> /// <param name="hexOuterRadius"> /// The distance of each hex from its center to a circle /// intersecting each corner of the hexagon. Scales the size of all /// other visual elements on the hex map. /// </param> /// <param name="seed"> /// The random seed used to initialize the hash grid for the map. /// </param> public HexMap Initialize( Rect bounds, int seed, float hexOuterRadius, bool wrapping, bool editMode ) { if (!GetComponent <HexMapShaderData>()) { _hexShaderData = gameObject.AddComponent <HexMapShaderData>(); _hexShaderData.HexMap = this; } if (!_hexLabelPrefab) { // TODO: This is a presentation concern and should not be in this class. _hexLabelPrefab = Resources.Load <Text>("Hex Label"); } ClearHexUnits(_units); ClearColumnTransforms(HexMeshColumnTransforms); int columns, rows; if ( bounds.x < 0 || bounds.y < 0 || !bounds.size.IsFactorOf(HexMeshConstants.ChunkSize) ) { RootLog.Log( "Unsupported map size. Clamping dimensions to chunk size.", Severity.Warning, "HexMap" ); Vector2 clamped = bounds.size.ClampToFactorOf(HexMeshConstants.ChunkSize); bounds = new Rect( 0, 0, clamped.x, clamped.y ); } columns = (int)bounds.width; rows = (int)bounds.height; // Set to -1 so new maps always gets centered. CenterHexMeshColumnIndex = -1; HexagonPoint.InitializeHashGrid(seed); if (!_terrainMaterial) { _terrainMaterial = Resources.Load <Material>("Terrain"); } HexGrid = new HexGrid <Hex>( rows, columns, wrapping ); for ( int index = 0, column = 0; column < HexOffsetColumns; column++ ) { for ( int row = 0; row < HexOffsetRows; row++ ) { HexGrid[column, row] = CreateHexFromOffsetCoordinates( column, row, index++, hexOuterRadius, HexGrid ); } } HexMeshChunks = GetHexMeshChunks( HexGrid, hexOuterRadius ); HexMeshColumnTransforms = GetHexMeshChunkColumns(HexMeshChunks); EditMode = editMode; return(this); }
/// <summary> /// Generate a HexMap using the standard RootGen algorithm. /// </summary> /// <param name="config"> /// The configuration data for the map to be generated. /// </param> /// <returns> ///A randomly generated HexMap object. /// </returns> public HexMap GenerateMap( RootGenConfig config, bool editMode = true ) { string diagnostics = "Generate Map Performance Diagnostics\n\n"; HexMap result = HexMap.CreateHexMapGameObject(); int seed; if (config.useFixedSeed) { seed = config.seed; } else { config.seed = Random.Range(0, int.MaxValue); config.seed ^= (int)System.DateTime.Now.Ticks; config.seed ^= (int)Time.time; config.seed &= int.MaxValue; seed = config.seed; } // Snapshot the initial random state before consuming the random // sequence. Random.State snapshot = RandomState.Snapshot(seed); result.Initialize( new Rect(0, 0, config.width, config.height), seed, config.hexSize, config.wrapping, editMode ); foreach (Hex hex in result.Hexes) { hex.WaterLevel = config.waterLevel; } Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); HexMapTectonics hexMapTectonics = new HexMapTectonics( result, config.regionBorder, config.mapBorderX, config.mapBorderZ, config.numRegions ); int landBudget = Mathf.RoundToInt( result.SizeSquared * config.landPercentage * 0.01f ); TectonicParameters tectonicParameters = new TectonicParameters( config.hexSize, config.highRiseProbability, config.jitterProbability, config.sinkProbability, config.elevationMax, config.elevationMin, config.waterLevel, landBudget, config.maximumRegionDensity, config.minimumRegionDensity ); string logString = "Tectonic Statistics\n"; for (int i = 0; i < MAX_TECTONIC_STEPS; i++) { tectonicParameters.LandBudget = hexMapTectonics.Step( tectonicParameters ); //result.Draw(config.hexSize); logString += "Step " + i + ", Land Hexes: " + result.LandHexes.Count + " / Land Budget: " + tectonicParameters.LandBudget + " Total: " + (result.LandHexes.Count + tectonicParameters.LandBudget) + "\n"; if (tectonicParameters.LandBudget == 0) { break; } } RootLog.Log(logString, Severity.Information, "Diagnostics"); // If land budget is greater than 0, all land hexes specified to // be allocated were not allocated successfully. Log a warning, // decrement the remaining land budget from the result, and return // the result as the number of land hexes allocated. if (tectonicParameters.LandBudget > 0) { RootLog.Log( "Failed to use up " + tectonicParameters.LandBudget + " land budget.", Severity.Warning, "MapGenerator" ); } stopwatch.Stop(); diagnostics += "Generate Tectonics: " + stopwatch.Elapsed + "\n"; stopwatch.Start(); HexMapErosion erosion = new HexMapErosion(result); int erodibleHexes = erosion.ErodibleHexes.Count; // Calculate the target number of uneroded hexes. int targetUnerodedHexes = (int)( erodibleHexes * (100 - config.erosionPercentage) * 0.01f ); while (erosion.ErodibleHexes.Count > targetUnerodedHexes) { erosion.Step( config.hexSize ); } stopwatch.Stop(); diagnostics += "Generate Erosion: " + stopwatch.Elapsed + "\n"; stopwatch.Start(); HexMapClimate hexMapClimate = new HexMapClimate( result, config.startingMoisture ); ClimateParameters climateParameters = new ClimateParameters( config.hemisphere, config.windDirection, config.evaporationFactor, config.highTemperature, config.lowTemperature, config.precipitationFactor, config.runoffFactor, config.seepageFactor, config.temperatureJitter, config.windStrength, config.hexSize, config.elevationMax, config.waterLevel ); for (int i = 0; i < config.initialClimateSteps; i++) { hexMapClimate.Step(climateParameters); } List <ClimateData> climates = hexMapClimate.List; stopwatch.Stop(); diagnostics += "Generate Climate: " + stopwatch.Elapsed + "\n"; stopwatch.Start(); HexMapRivers hexMapRivers = new HexMapRivers( result, climates, config.waterLevel, config.elevationMax ); for (int i = 0; i < config.numInitialRivers; i++) { hexMapRivers.StartRiver(); } for (int i = 0; i < config.numInitialRiverSteps; i++) { hexMapRivers.Step( config.waterLevel, config.elevationMax, config.extraLakeProbability, config.hexSize, climates ); } result.RiverDigraph = hexMapRivers.RiverDigraph; stopwatch.Stop(); diagnostics += "Generate Rivers: " + stopwatch.Elapsed + "\n"; stopwatch.Start(); hexMapClimate.RefreshTerrainTypes( climateParameters, result.RiverDigraph ); stopwatch.Stop(); diagnostics += "Assign Terrain Types: " + stopwatch.Elapsed + "\n"; RootLog.Log( diagnostics, Severity.Information, "Diagonstics" ); // Restore the snapshot of the random state taken before consuming // the random sequence. Random.state = snapshot; return(result); }
// ~~ private // INDEXERS ~~~~~~~~~~ // ~ Static // ~~ public // ~~ private // ~ Non-Static // ~~ public // ~~ private // METHODS ~~~~~~~~~ // ~ Static // ~~ public // ~~ private // ~ Non-Static // ~~ public public static void AttachCamera(HexMap map, float hexSize) { HexGridCamera resultMono; _hexOuterRadius = hexSize; if (InstanceValidation.InstanceExists <HexGridCamera>()) { resultMono = InstanceValidation.GetFirstInstance <HexGridCamera>(); resultMono.transform.SetParent(map.transform, false); resultMono.TargetGrid = map; resultMono.enabled = true; if (InstanceValidation.SingleInstanceExists <HexGridCamera>()) { RootLog.Log( "Single instance of camera already exists. " + "Attaching instance to grid.", Severity.Information, "HexGridCamera" ); } else { RootLog.Log( "Multiple instances of camera already exist. " + "Attaching first instance to grid.", Severity.Information, "HexGridCamera" ); } } else { GameObject resultObj = new GameObject("HexGridCamera"); resultMono = resultObj.AddComponent <HexGridCamera>(); resultMono.transform.SetParent(map.transform, false); resultMono.TargetGrid = map; resultMono.enabled = true; GameObject swivelObj = new GameObject("Swivel"); swivelObj.SetParent(resultObj, false); swivelObj.transform.localRotation = Quaternion.Euler(45, 0, 0); resultMono.Swivel = swivelObj.transform; GameObject stickObj = new GameObject("Stick"); stickObj.SetParent(swivelObj, false); stickObj.transform.localPosition = new Vector3( 0, 0, -45 ); resultMono.Stick = stickObj.transform; GameObject cameraObj = new GameObject("Camera"); cameraObj.SetParent(stickObj, false); cameraObj.tag = "MainCamera"; cameraObj.transform.localRotation = Quaternion.Euler(5, 0, 0); Camera cameraMono = cameraObj.AddComponent <Camera>(); cameraObj.AddComponent <PhysicsRaycaster>(); cameraMono.nearClipPlane = 0.3f; cameraMono.farClipPlane = 1000f; cameraMono.depth = -1f; resultMono.transform.SetParent(map.transform, false); if (map.GridCenter) { resultMono.SetPosition( map, map.GridCenter.transform.position.x, map.GridCenter.transform.position.z, _hexOuterRadius ); } } }