Exemple #1
0
    void Start()
    {
        _outputImage = GetComponent <Image>();
        _sectorBackgroundTransform = SectorBackgroundRenderer.transform;
        _sectorBackgroundDepth     = _sectorBackgroundTransform.position.z;
        _sectorCameraTransform     = SectorCamera.transform;
        _sectorCameraDepth         = _sectorCameraTransform.position.z;
        Raycaster.OnClickMiss     += data =>
        {
            Properties.gameObject.SetActive(false);
        };
        Map.ZoneClicked.Subscribe(zone =>
        {
            Properties.gameObject.SetActive(true);
            Properties.Clear();
            Properties.Title.text = zone.Name;
            Properties.AddProperty("Owner", () => zone.Owner?.Name ?? "None");
            var otherFactions = zone.Factions
                                .Where(f => f.ID != zone.Owner?.ID)
                                .Select(f => f.Name).ToArray();
            if (otherFactions.Length > 0)
            {
                Properties.AddProperty("Factions Present", () => string.Join(", ", otherFactions));
            }
            var density = saturate(ActionGameManager.CurrentGalaxy.Background.CloudDensity(zone.Position) / 2);
            var radius  = GameManager.Settings.ZoneSettings.ZoneRadius.Evaluate(density);
            var mass    = GameManager.Settings.ZoneSettings.ZoneMass.Evaluate(density);
            Properties.AddProperty("Mass", () => ActionGameManager.PlayerSettings.Format(mass));
            Properties.AddProperty("Radius", () => ActionGameManager.PlayerSettings.Format(radius));
            if (zone.PackedContents == null)
            {
                Properties.AddProperty(() => "Has not been visited");
            }
            else
            {
                var planetCount = zone.PackedContents.Planets.Count(body => body is PlanetData).ToString();
                Properties.AddProperty("Planets", () => planetCount);

                var beltCount = zone.PackedContents.Planets.Count(body => body is AsteroidBeltData).ToString();
                Properties.AddProperty("Asteroid Belts", () => beltCount);

                var giantCount = zone.PackedContents.Planets.Count(body => body is GasGiantData && !(body is SunData)).ToString();
                Properties.AddProperty("Gas Giants", () => giantCount);

                var starCount = zone.PackedContents.Planets.Count(body => body is SunData).ToString();
                Properties.AddProperty("Stars", () => starCount);

                var stationCount = zone.PackedContents.Entities
                                   .Count(entity => ((HullData)entity.Hull.Data.Value).HullType == HullType.Ship)
                                   .ToString();
                Properties.AddProperty("Stations", () => stationCount);

                var turretCount = zone.PackedContents.Entities
                                  .Count(entity => ((HullData)entity.Hull.Data.Value).HullType == HullType.Ship)
                                  .ToString();
                Properties.AddProperty("Turrets", () => turretCount);

                var shipCount = zone.PackedContents.Entities
                                .Count(entity => ((HullData)entity.Hull.Data.Value).HullType == HullType.Ship)
                                .ToString();
                Properties.AddProperty("Ships", () => shipCount);
            }
        });

        // PathAnimationButton.onClick.AddListener(() =>
        // {
        //     Map.StartCoroutine(AnimatePath());
        // });
    }
Exemple #2
0
    public void GenerateTechs()
    {
        foreach (var instance in _ringInstances)
        {
            instance.ReturnToPool();
        }
        _ringInstances.Clear();

        foreach (var instance in _techInstances)
        {
            instance.ReturnToPool();
        }
        _techInstances.Clear();

        foreach (var instance in _linkInstances)
        {
            instance.ReturnToPool();
        }
        _linkInstances.Clear();

        foreach (var instance in _arrowInstances)
        {
            instance.ReturnToPool();
        }
        _arrowInstances.Clear();

        var graph = new GeometryGraph();

        var settings = new SugiyamaLayoutSettings();

        if (TestMode)
        {
            for (int i = 0; i < TechCount; i++)
            {
                var node = NewNode(i);
                graph.Nodes.Add(node);
                if (i > SeedTechs)
                {
                    graph.Edges.Add(new Edge(graph.Nodes[Random.Range(max(0, i - RollingWindowSize), i - 1)], node));
                }
            }
            foreach (var vertex in graph.Nodes.Where(v => !graph.Edges.Any(e => e.Source == v || e.Target == v)))
            {
                graph.Edges.Add(new Edge(vertex, graph.Nodes[Random.Range(0, TechCount - 1)]));
            }
        }
        else
        {
            var nodeMap = new Dictionary <BlueprintData, Node>();
            foreach (var blueprint in Blueprints)
            {
                var node = NewNode(blueprint);
                nodeMap[blueprint] = node;
                graph.Nodes.Add(node);
            }

            foreach (var targetBlueprint in Blueprints)
            {
                foreach (var sourceBlueprint in Blueprints.Where(sb =>
                                                                 targetBlueprint.Dependencies.Any(dep => sb.ID == dep)))
                {
                    var edge = new Edge(nodeMap[sourceBlueprint], nodeMap[targetBlueprint]);
                    graph.Edges.Add(edge);
                    var splitName = sourceBlueprint.Name.Split(' ');
                    if (splitName.Length > 1)
                    {
                        var nameStart = string.Join(" ", splitName.Take(splitName.Length - 1));
                        if (targetBlueprint.Name.StartsWith(nameStart))
                        {
                            edge.Weight *= 10;
                        }
                    }
                }
            }
        }

        settings.BrandesThreshold = 9999;

        var islands   = graph.GetClusteredConnectedComponents();
        var islandMap =
            graph.Nodes.ToDictionary(n => n, n => islands.Find(c => c.Nodes.Any(cn => cn.UserData == n)));

        if (TestMode)
        {
            foreach (var island in islands)
            {
                foreach (var node in island.Nodes)
                {
                    var region = GetRegion(island, node, DependencyAncestorDepth, DependencyDepth);
                    while (Random.value < MultipleDependencyProbability && region.Count > 0)
                    {
                        var dependency = region[Random.Range(0, region.Count)];
                        graph.Edges.Add(new Edge(dependency.UserData as Node, node.UserData as Node));
                        region.Remove(dependency);
                    }
                }
            }
        }

        var islandsBySize = islands.OrderByDescending(i => i.Nodes.Count);
        var largestIsland = islandsBySize.First();

        foreach (var island in islandsBySize.Skip(1))
        {
            settings.VerticalConstraints.SameLayerConstraints.Insert(new Tuple <Node, Node>(
                                                                         largestIsland.Nodes[Random.Range(0, largestIsland.Nodes.Count)].UserData as Node, island.Nodes[Random.Range(0, island.Nodes.Count)].UserData as Node));
        }

        settings.PackingMethod  = PackingMethod;
        settings.Transformation = PlaneTransformation.Rotation(PI);
        var layout = new LayeredLayout(graph, settings);

        layout.Run();

        var positions     = graph.Nodes.ToDictionary(n => n, n => (float2)n.Center);
        var islandCenters = islands.ToDictionary(i => i,
                                                 i => i.Nodes.Aggregate(float2(0, 0), (total, v) => total + positions[v.UserData as Node]) / i.Nodes.Count);

        Rect bounds = Rect.MinMaxRect(
            positions.Values.Min(v => v.x),
            positions.Values.Min(v => v.y),
            positions.Values.Max(v => v.x),
            positions.Values.Max(v => v.y));

        var tiers =
            Mathf.RoundToInt(graph.Nodes.Max(n => Rect.PointToNormalized(bounds, n.Center).y) /
                             graph.Nodes.Min(n =>
        {
            var normalized = Rect.PointToNormalized(bounds, n.Center);
            return(normalized.y > .001f ? normalized.y : 1);
        }));

        // var islandsBySize = islands.OrderByDescending(i => i.Nodes.Count);
        // var largestIsland = islandsBySize.First();
        // foreach(var island in islandsBySize.Skip(1))
        //     settings.AddSameLayerNeighbors(largestIsland.Nodes.RandomElement().UserData as Node, island.Nodes.RandomElement().UserData as Node);
        //
        // layout = new LayeredLayout(graph, settings);
        // layout.Run();

        positions     = graph.Nodes.ToDictionary(n => n, n => (float2)n.Center);
        islandCenters = islands.ToDictionary(i => i,
                                             i => i.Nodes.Aggregate(float2(0, 0), (total, v) => total + positions[v.UserData as Node]) / i.Nodes.Count);

        bounds = Rect.MinMaxRect(
            positions.Values.Min(v => v.x),
            positions.Values.Min(v => v.y),
            positions.Values.Max(v => v.x),
            positions.Values.Max(v => v.y));

        Debug.Log($"Generated {tiers} tiers of techs!");

        var islandColors = islandCenters.ToDictionary(
            i => i.Key,
            i => Color.HSVToRGB(lerp(HueMin, HueMax, Rect.PointToNormalized(bounds, i.Value).x), Saturation, Brightness));

        var islandFillMaterials = islandColors.ToDictionary(i => i.Key, i =>
        {
            var mat = new Material(TechFillMaterial);
            var col = i.Value;
            col.a   = FillOpacity;
            mat.SetColor("_TintColor", col);
            return(mat);
        });

        var islandGlowMaterials = islandColors.ToDictionary(i => i.Key, i =>
        {
            var mat = new Material(TechGlowMaterial);
            var col = i.Value;
            col.a   = GlowOpacity;
            mat.SetColor("_TintColor", col);
            return(mat);
        });

        var islandArrowMaterials = islandColors.ToDictionary(i => i.Key, i =>
        {
            var mat = new Material(TechArrowMaterial);
            var col = i.Value;
            col.a   = 1;
            mat.SetColor("_TintColor", col);
            return(mat);
        });

        var islandLinkMaterials = islandColors.ToDictionary(i => i.Key, i =>
        {
            var mat = new Material(TechLinkMaterial);
            var col = i.Value;
            col.a   = 1;
            mat.SetColor("_TintColor", col);
            return(mat);
        });

        if (Radial)
        {
            positions = positions.ToDictionary(
                kvp => kvp.Key,
                kvp =>
            {
                var normalized = Rect.PointToNormalized(bounds, kvp.Value);
                var rads       = normalized.x * (PI * 2 - PaddingRadians) + PaddingRadians / 2;
                return(float2(sin(rads), -cos(rads)) * ((normalized.y * tiers + StartTier + .5f) * LayerDistance) * Scale);
            });
        }
        else
        {
            positions = positions.ToDictionary(
                kvp => kvp.Key,
                kvp =>
            {
                var normalized = Rect.PointToNormalized(bounds, kvp.Value);
                return(float2(
                           normalized.x * LayerDistance * tiers * (bounds.width / bounds.height),
                           (normalized.y * tiers / 2 + StartTier + .5f) * LayerDistance));
            });
        }

        foreach (var vertex in graph.Nodes.Where(positions.ContainsKey))
        {
            var tech = Tech.Instantiate <TechNode>();
            tech.transform.position = (Vector2)positions[vertex];
            tech.Label.text         = $"{(TestMode ? ((int) vertex.UserData).ToString() : ((BlueprintData) vertex.UserData).ID.ToString().Substring(0,2))}";
            var gradient = tech.Label.colorGradient;
            gradient.bottomLeft      = gradient.bottomRight = islandColors[islandMap[vertex]];
            tech.Label.colorGradient = gradient;
            tech.Icon.material.SetTexture("_MainTex", _icons[Random.Range(0, _icons.Length - 1)]);
            tech.Fill.material = islandFillMaterials[islandMap[vertex]];
            tech.Glow.material = islandGlowMaterials[islandMap[vertex]];
            if (!TestMode)
            {
                tech.Fill.GetComponent <ClickableCollider>().OnClick += (collider, data) =>
                {
                    PropertiesPanel.Clear();
                    var blueprint = (BlueprintData)vertex.UserData;
                    PropertiesPanel.Title.text = blueprint.Name;
                    PropertiesPanel.AddProperty("Research Time", () => $"{blueprint.ResearchTime:0.##} MH");
                    PropertiesPanel.AddProperty("Produces", () => $"{Context.Cache.Get<ItemData>(blueprint.Item).Name}");
                    PropertiesPanel.AddProperty("Production Quality", () => $"{Mathf.RoundToInt(blueprint.Quality * 100)}%");
                    PropertiesPanel.AddProperty("Production Time", () => $"{blueprint.ProductionTime:0.##} MH");

                    var ingredientsList = PropertiesPanel.AddList("Ingredients");
                    foreach (var ingredient in blueprint.Ingredients)
                    {
                        var ingredientData = Context.Cache.Get <ItemData>(ingredient.Key);
                        ingredientsList.AddProperty(ingredientData.Name, () => ingredient.Value.ToString());
                    }
                    ingredientsList.SetExpanded(true, true);

                    var dependenciesList = PropertiesPanel.AddList("Dependencies");
                    foreach (var dependency in blueprint.Dependencies)
                    {
                        var dependencyBlueprint = Context.Cache.Get <BlueprintData>(dependency);
                        dependenciesList.AddProperty(dependencyBlueprint.Name);
                    }
                    dependenciesList.SetExpanded(true, true);

                    var descendantsList = PropertiesPanel.AddList("Descendants");
                    foreach (var descendant in Blueprints.Where(bp => bp.Dependencies.Any(dep => blueprint.ID == dep)))
                    {
                        descendantsList.AddProperty(descendant.Name);
                    }
                    descendantsList.SetExpanded(true, true);
                }
            }
            ;
            _techInstances.Add(tech.GetComponent <Prototype>());
        }

        foreach (var edge in graph.Edges)
        {
            var link = RadialLink.Instantiate <LineRenderer>();
            link.material      = islandLinkMaterials[islandMap[edge.Source]];
            link.positionCount = LinkPoints;
            var p1r      = length(positions[edge.Source]);
            var p2r      = length(positions[edge.Target]);
            var p1a      = (atan2(positions[edge.Source].y, positions[edge.Source].x) + PI * 2.5f) % (PI * 2);
            var p2a      = (atan2(positions[edge.Target].y, positions[edge.Target].x) + PI * 2.5f) % (PI * 2);
            var p1       = float2(sin(p1a) * p1r, -cos(p1a) * p1r);
            var p2       = float2(sin(p2a) * p2r, -cos(p2a) * p2r);
            var dist     = length(p2 - p1);
            var distProp = (dist - LinkTargetDistance) / dist;
            var dir      = new float2();
            var lastPos  = new float2();
            link.SetPositions(Enumerable.Range(0, LinkPoints).Select(i =>
            {
                var lerp   = (float)i / (LinkPoints - 1) * distProp;
                var angle  = math.lerp(p1a, p2a, (lerp));
                var radius = math.lerp(p1r, p2r, lerp);
                var pos    = Radial ? float2(sin(angle) * radius, -cos(angle) * radius) : math.lerp(positions[edge.Source], positions[edge.Target], lerp);
                dir        = normalize(pos - lastPos);
                lastPos    = pos;
                return((Vector3)float3(lastPos, LinkDepth));
            }).ToArray());
            _linkInstances.Add(link.GetComponent <Prototype>());

            var arrow = Arrow.Instantiate <TechArrow>();
            arrow.transform.position = new Vector3(lastPos.x, lastPos.y, ArrowDepth);
            arrow.transform.rotation = Quaternion.Euler(0, 0, atan2(dir.y, dir.x) * Mathf.Rad2Deg);
            arrow.Icon.material      = islandArrowMaterials[islandMap[edge.Source]];
            _arrowInstances.Add(arrow.GetComponent <Prototype>());
        }

        if (Radial)
        {
            for (int i = 1; i <= tiers; i++)
            {
                var ring          = Ring.Instantiate <LineRenderer>();
                var ringPositions = new Vector3[Sections];
                for (int s = 0; s < Sections; s++)
                {
                    var rads = ((float)s / (Sections - 1)) * (PI * 2 - PaddingRadians) + PaddingRadians / 2;
                    ringPositions[s]   = new Vector3(sin(rads), -cos(rads), 0) * ((i + StartTier) * (LayerDistance) * Scale);
                    ringPositions[s].z = RingDepth;
                }

                ring.positionCount = Sections;
                ring.SetPositions(ringPositions);
                var tierLerp = (float)i / (tiers - 1);
                ring.colorGradient = new Gradient
                {
                    alphaKeys = new [] { new GradientAlphaKey(1, 0), new GradientAlphaKey(1, 1) },
                    colorKeys = Enumerable.Range(0, RingColorKeys).Select(x =>
                    {
                        var ringLerp = (float)x / (RingColorKeys - 1);
                        return(new GradientColorKey(
                                   Color.HSVToRGB(HueMin + (HueMax - HueMin) * ringLerp,
                                                  lerp(RingInnerSaturation, RingOuterSaturation, tierLerp),
                                                  lerp(RingInnerBrightness, RingOuterBrightness, tierLerp)), ringLerp));
                    }).ToArray()
                };

                _ringInstances.Add(ring.GetComponent <Prototype>());
            }
        }
    }
}