Пример #1
0
 /// <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);
     }
 }
Пример #2
0
 /// <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);
     }
 }
Пример #3
0
 /// <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);
     }
 }
Пример #4
0
 /// <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);
     }
 }
Пример #5
0
 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);
    }
Пример #7
0
    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();
    }
Пример #9
0
    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);
        }
    }
Пример #10
0
    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);
    }
Пример #11
0
    /// <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);
    }
Пример #12
0
    /// <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);
    }
Пример #13
0
// ~~ 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
                    );
            }
        }
    }