From d1492eb04cf44b3ca47c8353c701680be8cb6aac Mon Sep 17 00:00:00 2001 From: hyperion51 Date: Sun, 12 Apr 2020 11:05:36 +0100 Subject: [PATCH] Tech Tree Improvements --- .../.idea/contentModel.xml | 1 + Assembly-CSharp.csproj | 1 + Assets/Materials/Tech Arrow.mat | 98 +++++++++ Assets/Materials/Tech Arrow.mat.meta | 8 + Assets/Materials/Tech Line.mat | 4 +- Assets/Materials/Tech Node Stroke.mat | 2 +- .../Resources/Sprites/Icons/Stroked/Arrow.png | 3 + .../Sprites/Icons/Stroked/Arrow.png.meta | 110 ++++++++++ Assets/Scenes/Main.unity | 166 +++++++++++--- Assets/Scripts/Galaxy.cs | 1 + Assets/Scripts/ServerShared/Extensions.cs | 37 ++++ Assets/Scripts/TechTreeTest.cs | 206 ++++++++++++++++-- Assets/Scripts/UI/TechArrow.cs | 8 + Assets/Scripts/UI/TechArrow.cs.meta | 11 + Assets/Scripts/UI/TechNode.cs | 2 + README.md | 2 +- 16 files changed, 616 insertions(+), 44 deletions(-) create mode 100644 Assets/Materials/Tech Arrow.mat create mode 100644 Assets/Materials/Tech Arrow.mat.meta create mode 100644 Assets/Resources/Sprites/Icons/Stroked/Arrow.png create mode 100644 Assets/Resources/Sprites/Icons/Stroked/Arrow.png.meta create mode 100644 Assets/Scripts/UI/TechArrow.cs create mode 100644 Assets/Scripts/UI/TechArrow.cs.meta diff --git a/.idea/.idea.Aetheria-Economy/.idea/contentModel.xml b/.idea/.idea.Aetheria-Economy/.idea/contentModel.xml index 4cc1c992f..3f7010721 100644 --- a/.idea/.idea.Aetheria-Economy/.idea/contentModel.xml +++ b/.idea/.idea.Aetheria-Economy/.idea/contentModel.xml @@ -1278,6 +1278,7 @@ + diff --git a/Assembly-CSharp.csproj b/Assembly-CSharp.csproj index fe5ca3abb..690530951 100644 --- a/Assembly-CSharp.csproj +++ b/Assembly-CSharp.csproj @@ -524,6 +524,7 @@ + diff --git a/Assets/Materials/Tech Arrow.mat b/Assets/Materials/Tech Arrow.mat new file mode 100644 index 000000000..116a5a112 --- /dev/null +++ b/Assets/Materials/Tech Arrow.mat @@ -0,0 +1,98 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Tech Arrow + m_Shader: {fileID: 203, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: + m_LightmapFlags: 0 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 2800000, guid: 2108d278f9e8734469689c30c590ef76, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BlendOp: 0 + - _BumpScale: 1 + - _CameraFadingEnabled: 0 + - _CameraFarFadeDistance: 2 + - _CameraNearFadeDistance: 1 + - _ColorMode: 0 + - _Cull: 2 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DistortionBlend: 0.5 + - _DistortionEnabled: 0 + - _DistortionStrength: 1 + - _DistortionStrengthScaled: 0 + - _DstBlend: 0 + - _EmissionEnabled: 0 + - _FlipbookMode: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _InvFade: 1 + - _LightingEnabled: 0 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SoftParticlesEnabled: 0 + - _SoftParticlesFarFadeDistance: 1 + - _SoftParticlesNearFadeDistance: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _CameraFadeParams: {r: 0, g: Infinity, b: 0, a: 0} + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _ColorAddSubDiff: {r: 0, g: 0, b: 0, a: 0} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _SoftParticleFadeParams: {r: 0, g: 0, b: 0, a: 0} + - _TintColor: {r: 0.09800005, g: 0.47383344, b: 1, a: 1} diff --git a/Assets/Materials/Tech Arrow.mat.meta b/Assets/Materials/Tech Arrow.mat.meta new file mode 100644 index 000000000..f7f2aba7e --- /dev/null +++ b/Assets/Materials/Tech Arrow.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2a2ec810cb24ddb4d869e73fe8a1510a +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Materials/Tech Line.mat b/Assets/Materials/Tech Line.mat index 2d37f4b24..2b9358b13 100644 --- a/Assets/Materials/Tech Line.mat +++ b/Assets/Materials/Tech Line.mat @@ -8,7 +8,7 @@ Material: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: Tech Line - m_Shader: {fileID: 203, guid: 0000000000000000f000000000000000, type: 0} + m_Shader: {fileID: 200, guid: 0000000000000000f000000000000000, type: 0} m_ShaderKeywords: m_LightmapFlags: 0 m_EnableInstancingVariants: 0 @@ -95,4 +95,4 @@ Material: - _ColorAddSubDiff: {r: 0, g: 0, b: 0, a: 0} - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} - _SoftParticleFadeParams: {r: 0, g: 0, b: 0, a: 0} - - _TintColor: {r: 1, g: 1, b: 1, a: 1} + - _TintColor: {r: 1, g: 1, b: 1, a: 0.5019608} diff --git a/Assets/Materials/Tech Node Stroke.mat b/Assets/Materials/Tech Node Stroke.mat index 0cb0558b9..026a8a416 100644 --- a/Assets/Materials/Tech Node Stroke.mat +++ b/Assets/Materials/Tech Node Stroke.mat @@ -76,4 +76,4 @@ Material: m_Colors: - _Color: {r: 1, g: 1, b: 1, a: 1} - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} - - _TintColor: {r: 0.5019608, g: 0.5019608, b: 0.5019608, a: 1} + - _TintColor: {r: 0.503, g: 0.503, b: 0.503, a: 1} diff --git a/Assets/Resources/Sprites/Icons/Stroked/Arrow.png b/Assets/Resources/Sprites/Icons/Stroked/Arrow.png new file mode 100644 index 000000000..ab2eff247 --- /dev/null +++ b/Assets/Resources/Sprites/Icons/Stroked/Arrow.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a5ccaefae8b78b658193fa1de41c2aa943f3fe9e629e65a7f6fc9229d2ef1a6f +size 4179 diff --git a/Assets/Resources/Sprites/Icons/Stroked/Arrow.png.meta b/Assets/Resources/Sprites/Icons/Stroked/Arrow.png.meta new file mode 100644 index 000000000..306f8afaf --- /dev/null +++ b/Assets/Resources/Sprites/Icons/Stroked/Arrow.png.meta @@ -0,0 +1,110 @@ +fileFormatVersion: 2 +guid: 2108d278f9e8734469689c30c590ef76 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 9 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: WebGL + maxTextureSize: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: a122cda7ba7cb784c99317d4116e382d + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/Main.unity b/Assets/Scenes/Main.unity index 11a68cc2b..a38f4124c 100644 --- a/Assets/Scenes/Main.unity +++ b/Assets/Scenes/Main.unity @@ -10462,7 +10462,7 @@ Transform: - {fileID: 874726172} - {fileID: 904172349} m_Father: {fileID: 712278634} - m_RootOrder: 1 + m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &586612707 MonoBehaviour: @@ -10478,6 +10478,8 @@ MonoBehaviour: m_EditorClassIdentifier: Label: {fileID: 904172350} Icon: {fileID: 874726173} + Fill: {fileID: 555365874} + Glow: {fileID: 1343232809} --- !u!114 &586612708 MonoBehaviour: m_ObjectHideFlags: 0 @@ -13800,7 +13802,7 @@ Transform: m_LocalScale: {x: 1, y: 1, z: 1} m_Children: [] m_Father: {fileID: 712278634} - m_RootOrder: 2 + m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &680383218 MonoBehaviour: @@ -13877,7 +13879,7 @@ LineRenderer: m_Curve: - serializedVersion: 3 time: 0 - value: 0.067736894 + value: 0.20457771 inSlope: 0 outSlope: 0 tangentMode: 0 @@ -14318,25 +14320,47 @@ MonoBehaviour: Tech: {fileID: 586612708} Link: {fileID: 1941419275} RadialLink: {fileID: 1417816149} + Arrow: {fileID: 1083812776} Algorithm: 1 - TechCount: 50 - SeedTechs: 5 + TechCount: 1000 + SeedTechs: 15 + RollingWindowSize: 50 + EliminateIslands: 0 DisconnectedMultiplier: 2 K: 0.25 LengthFactor: 1 - Iterations: 250 + Iterations: 100 LayerDistance: 1 - VertexDistance: 1 + VertexDistance: 0.1 WidthPerHeight: 1 PositionMode: -1 Radial: 1 + MinimizeEdgeLength: 0 + OptimizeWidth: 0 Sections: 360 PaddingRadians: 3.14 - StartTier: 3 - Scale: 1.5 + StartTier: 10 + Scale: 2 LinkPoints: 32 LinkDepth: 5 + LinkTargetDistance: 0.75 RingDepth: 6 + ArrowDepth: 3 + Saturation: 0.95 + HueMin: 0.5 + HueMax: 1 + Brightness: 1 + RingInnerSaturation: 1 + RingOuterSaturation: 0.25 + RingInnerBrightness: 1 + RingOuterBrightness: 0.1 + RingColorKeys: 8 + FillOpacity: 0.15 + GlowOpacity: 0.6 + TechFillMaterial: {fileID: 2100000, guid: c3c13ba00125fdf4c92bd96210dc7230, type: 2} + TechGlowMaterial: {fileID: 2100000, guid: 1426b25e088759647b77658321197be7, type: 2} + TechArrowMaterial: {fileID: 2100000, guid: 2a2ec810cb24ddb4d869e73fe8a1510a, type: 2} + TechLinkMaterial: {fileID: 2100000, guid: 67e23cda35beab546a57003dd2d33de1, type: 2} --- !u!114 &712278633 MonoBehaviour: m_ObjectHideFlags: 0 @@ -14362,6 +14386,7 @@ Transform: m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_Children: + - {fileID: 1083812780} - {fileID: 1941419274} - {fileID: 586612706} - {fileID: 680383217} @@ -21345,6 +21370,110 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1081687107} m_CullTransparentMesh: 0 +--- !u!1 &1083812775 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1083812780} + - component: {fileID: 1083812779} + - component: {fileID: 1083812778} + - component: {fileID: 1083812776} + - component: {fileID: 1083812777} + m_Layer: 0 + m_Name: Arrow + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1083812776 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1083812775} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1281fe44325f9b548aa42dc331b17266, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!114 &1083812777 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1083812775} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d54298fa75eb6304489e19a84af3413f, type: 3} + m_Name: + m_EditorClassIdentifier: + Icon: {fileID: 1083812778} +--- !u!23 &1083812778 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1083812775} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 2a2ec810cb24ddb4d869e73fe8a1510a, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &1083812779 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1083812775} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1083812780 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1083812775} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -4, y: 0, z: 1} + m_LocalScale: {x: 0.66, y: 0.66, z: 1} + m_Children: [] + m_Father: {fileID: 712278634} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1084879508 GameObject: m_ObjectHideFlags: 0 @@ -28301,7 +28430,7 @@ Transform: m_LocalScale: {x: 1, y: 1, z: 1} m_Children: [] m_Father: {fileID: 712278634} - m_RootOrder: 3 + m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1424588006 GameObject: @@ -36507,7 +36636,6 @@ GameObject: - component: {fileID: 1813193644} - component: {fileID: 1813193647} - component: {fileID: 1813193646} - - component: {fileID: 1813193645} m_Layer: 0 m_Name: Quad m_TagString: Untagged @@ -36529,20 +36657,6 @@ Transform: m_Father: {fileID: 1941419274} m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!64 &1813193645 -MeshCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1813193643} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 3 - m_Convex: 0 - m_CookingOptions: 14 - m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} --- !u!23 &1813193646 MeshRenderer: m_ObjectHideFlags: 0 @@ -39878,7 +39992,7 @@ Transform: m_Children: - {fileID: 1813193644} m_Father: {fileID: 712278634} - m_RootOrder: 0 + m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &1941419275 MonoBehaviour: diff --git a/Assets/Scripts/Galaxy.cs b/Assets/Scripts/Galaxy.cs index ff8e6ad17..70b9aa9d5 100644 --- a/Assets/Scripts/Galaxy.cs +++ b/Assets/Scripts/Galaxy.cs @@ -6,6 +6,7 @@ using System.Linq; using UnityEngine; using NaughtyAttributes; using JM.LinqFaster; +using QuickGraph; using Unity.Mathematics; using static Unity.Mathematics.math; using static Unity.Mathematics.noise; diff --git a/Assets/Scripts/ServerShared/Extensions.cs b/Assets/Scripts/ServerShared/Extensions.cs index 66b82679a..7a8138f1b 100644 --- a/Assets/Scripts/ServerShared/Extensions.cs +++ b/Assets/Scripts/ServerShared/Extensions.cs @@ -6,6 +6,7 @@ using System.Reflection; using System.Text.RegularExpressions; using LiteNetLib; using MessagePack; +using QuickGraph; using Unity.Mathematics; using static Unity.Mathematics.math; using Random = Unity.Mathematics.Random; @@ -291,6 +292,42 @@ public static class ObjectExtensions return (r2.x + r2.width >= r1.x && r2.x <= r1.x + r1.width) && (r2.y + r2.height >= r1.y && r2.y <= r1.y + r1.height); } + + public static IEnumerable FindPath(this IEnumerable> data, T source, T target, Func costFunction, bool bestFirst = true) where T : class + { + List> members = new List>{new DijkstraVertex{Vertex = source}}; + List searched = new List(); + while (true) + { + var v = members.Where(m=>!searched.Contains(m.Vertex)).OrderBy(m=>bestFirst?m.Heuristic:m.Cost).FirstOrDefault(); + if (v == null) return null; // No vertices left unsearched + if (v.Vertex == target) + { + Stack> path = new Stack>(); + path.Push(v); + while(path.Peek().Parent!=null) + path.Push(path.Peek().Parent); + return path.Select(dv => dv.Vertex).ToList(); + } + members.AddRange(data.Where(l => l.Source == v.Vertex).Select(l => l.Target).Concat(data.Where(l => l.Target == v.Vertex).Select(l => l.Source)) + .Where(n => members.All(m => m.Vertex != n)).Select(n => + { + var c = new DijkstraVertex {Parent = v, Vertex = n, Cost = v.Cost + costFunction(v.Vertex,n)}; + if (bestFirst) + c.Heuristic = c.Cost + costFunction(c.Vertex,target); + return c; + })); + searched.Add(v.Vertex); + } + } + + class DijkstraVertex + { + public double Cost; + public double Heuristic; + public DijkstraVertex Parent; + public T Vertex; + } } public class ReferenceEqualityComparer : EqualityComparer diff --git a/Assets/Scripts/TechTreeTest.cs b/Assets/Scripts/TechTreeTest.cs index d481642b8..259713797 100644 --- a/Assets/Scripts/TechTreeTest.cs +++ b/Assets/Scripts/TechTreeTest.cs @@ -1,4 +1,5 @@ -using System.Collections; +using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using GraphSharp.Algorithms.Layout; @@ -25,9 +26,15 @@ public class TechTreeTest : MonoBehaviour public Prototype Tech; public Prototype Link; public Prototype RadialLink; + public Prototype Arrow; public LayoutAlgorithm Algorithm; public int TechCount = 50; public int SeedTechs = 5; + public int RollingWindowSize = 50; + public bool EliminateIslands = false; + // public float MultipleDependencyProbability = .25f; + // public int MaxDependencyDistance = 4; + // public int MaxDependencyTierDifference = 2; [Section("Kamada-Kawai")] public float DisconnectedMultiplier; @@ -41,6 +48,8 @@ public class TechTreeTest : MonoBehaviour public float WidthPerHeight; public int PositionMode; public bool Radial; + public bool MinimizeEdgeLength; + public bool OptimizeWidth; [Section("Radial")] public int Sections; @@ -49,11 +58,31 @@ public class TechTreeTest : MonoBehaviour public float Scale = 1; public int LinkPoints = 16; public int LinkDepth = 5; + public float LinkTargetDistance = .75f; public int RingDepth = 6; + public float ArrowDepth = 3; + + [Section("Colors")] + public float Saturation = .95f; + public float HueMin = 0; + public float HueMax = 1; + public float Brightness = 1; + public float RingInnerSaturation; + public float RingOuterSaturation; + public float RingInnerBrightness; + public float RingOuterBrightness; + public int RingColorKeys; + public float FillOpacity = .25f; + public float GlowOpacity = .5f; + public Material TechFillMaterial; + public Material TechGlowMaterial; + public Material TechArrowMaterial; + public Material TechLinkMaterial; private List _ringInstances = new List(); private List _techInstances = new List(); private List _linkInstances = new List(); + private List _arrowInstances = new List(); private Texture2D[] _icons; void Start() @@ -77,6 +106,9 @@ public class TechTreeTest : MonoBehaviour foreach (var instance in _linkInstances) instance.ReturnToPool(); _linkInstances.Clear(); + + foreach (var instance in _arrowInstances) instance.ReturnToPool(); + _arrowInstances.Clear(); var vertices = new List(); var edges = new List>(); @@ -86,7 +118,7 @@ public class TechTreeTest : MonoBehaviour { var vertex = new IntVertex(i); vertices.Add(vertex); - if(i>loose) edges.Add(new Edge(vertices[Random.Range(0,i-1)], vertex)); + if(i>loose) edges.Add(new Edge(vertices[Random.Range(max(0,i-RollingWindowSize),i-1)], vertex)); } foreach (var vertex in vertices.Where(v=>!edges.Any(e=>e.Source!=v&&e.Target!=v))) { @@ -101,13 +133,82 @@ public class TechTreeTest : MonoBehaviour // } var islands = new Dictionary(); var islandCount = graph.WeaklyConnectedComponents(islands); - if(islandCount>1) - for (int i = 1; i < islandCount; i++) - { - var i1 = islands.Where(x => x.Value == i - 1).Select(x=>x.Key).ToArray(); - var i2 = islands.Where(x => x.Value == i).Select(x=>x.Key).ToArray(); - edges.Add(new Edge(i1[Random.Range(0,i1.Length-1)],i2[Random.Range(0,i2.Length-1)])); - } + var islandsInverse = islands + .GroupBy(i => i.Value) + .ToDictionary( + i => i.Key, + i => i.Select(g => g.Key).ToArray()); + + // var vertexTiers = new Dictionary(); + // foreach (var island in islandsInverse.Values) + // { + // vertexTiers[island[0]] = 0; + // foreach (var vertex in island.Skip(1)) + // { + // vertexTiers[vertex] = edges.FindPath(vertex, island[0], (v1, v2) => 1).Count(); + // // var tryGetPath = graph.ShortestPathsDijkstra(edge => 1, vertex); + // // if (tryGetPath(island[0], out var path)) + // // { + // // vertexTiers[vertex] = path.Count(); + // // } + // // else Debug.Log("Path to root not found?"); + // } + // } + // + // foreach (var island in islandsInverse.Values) + // { + // foreach (var vertex in island.Skip(1)) + // { + // //var tryGetPath = graph.ShortestPathsDijkstra(edge => 1, vertex); + // //var ancestors = island.Take(Array.IndexOf(island, vertex) - 1); + // var possibleDependencies = island.Where(v => + // { + // return v != vertex && + // vertexTiers[v] < vertexTiers[vertex] && + // abs(vertexTiers[v] - vertexTiers[vertex]) < MaxDependencyTierDifference && + // edges.FindPath(vertex, v, (v1, v2) => 1).Count() < MaxDependencyDistance; + // // if (v != vertex && tryGetPath(v, out var path)) + // // { + // // return path.Count() > 1 && path.Count() < MaxDependencyDistance; + // // } + // // + // // return false; + // }).ToArray(); + // var dependencies = new List(); + // while (dependencies.Count < possibleDependencies.Length && Random.value < MultipleDependencyProbability) + // { + // var depIndex = Random.Range(0, possibleDependencies.Length); + // dependencies.Add(depIndex); + // edges.Add(new Edge(possibleDependencies[depIndex], vertex)); + // } + // // while (Random.value < MultipleDependencyProbability) + // // { + // // var index = Array.IndexOf(island, vertex); + // // int depIndex; + // // int tries = 0; + // // do + // // { + // // depIndex = Random.Range(max(0, index - MultipleDependencyRollingWindow), index); + // // } while (tries < 10 && dependencies.Contains(depIndex)); + // // + // // if (tries < 10) + // // edges.Add(new Edge(island[depIndex], vertex)); + // // else break; + // // } + // } + // } + + if (EliminateIslands) + { + if(islandCount>1) + for (int i = 1; i < islandCount; i++) + { + var i1 = islands.Where(x => x.Value == i - 1).Select(x=>x.Key).ToArray(); + var i2 = islands.Where(x => x.Value == i).Select(x=>x.Key).ToArray(); + edges.Add(new Edge(i1[Random.Range(0,i1.Length-1)],i2[Random.Range(0,i2.Length-1)])); + } + } + graph = edges.ToBidirectionalGraph>(); LayoutAlgorithmBase, BidirectionalGraph>> layout = @@ -121,8 +222,8 @@ public class TechTreeTest : MonoBehaviour { EdgeRouting = SugiyamaEdgeRoutings.Traditional, LayerDistance = LayerDistance, - MinimizeEdgeLength = true, - OptimizeWidth = true, + MinimizeEdgeLength = MinimizeEdgeLength, + OptimizeWidth = OptimizeWidth, VertexDistance = VertexDistance, PositionMode = PositionMode, WidthPerHeight = WidthPerHeight @@ -147,12 +248,55 @@ public class TechTreeTest : MonoBehaviour }); layout.Compute(); IDictionary positions = layout.VertexPositions; + var islandCenters = islandsInverse.ToDictionary(i => i.Key, + i => i.Value.Aggregate(float2(0, 0), (total, v) => total + positions[v]) / i.Value.Length); Rect bounds = Rect.MinMaxRect( layout.VertexPositions.Values.Min(v=>v.x), layout.VertexPositions.Values.Min(v=>v.y), layout.VertexPositions.Values.Max(v=>v.x), layout.VertexPositions.Values.Max(v=>v.y)); + + var islandColors = islandCenters.ToDictionary( + i=>i.Key, + i=>Color.HSVToRGB(HueMin + (HueMax - HueMin) * 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 (Algorithm == LayoutAlgorithm.Sugiyama && Radial) { int tiers = Mathf.RoundToInt(bounds.height / LayerDistance); @@ -177,6 +321,19 @@ public class TechTreeTest : MonoBehaviour ring.positionCount = Sections; ring.SetPositions(ringPositions); + var tierLerp = (float) i / (tiers / 2 - 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()); } @@ -193,7 +350,12 @@ public class TechTreeTest : MonoBehaviour var tech = Tech.Instantiate(); tech.transform.position = (Vector2) positions[vertex]; tech.Label.text = $"{vertex.N}"; + var gradient = tech.Label.colorGradient; + gradient.bottomLeft = gradient.bottomRight = islandColors[islands[vertex]]; + tech.Label.colorGradient = gradient; tech.Icon.material.SetTexture("_MainTex", _icons[Random.Range(0,_icons.Length-1)]); + tech.Fill.material = islandFillMaterials[islands[vertex]]; + tech.Glow.material = islandGlowMaterials[islands[vertex]]; _techInstances.Add(tech.GetComponent()); } @@ -202,19 +364,35 @@ public class TechTreeTest : MonoBehaviour foreach (var edge in edges) { var link = RadialLink.Instantiate(); + link.material = islandLinkMaterials[islands[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); - var angle = math.lerp(p1a, p2a, ease_out_quad(lerp)); + var lerp = (float) i / (LinkPoints-1) * distProp; + var angle = math.lerp(p1a, p2a, (lerp)); var radius = math.lerp(p1r, p2r, lerp); - return new Vector3(sin(angle) * radius, -cos(angle) * radius, LinkDepth); + var pos = float2(sin(angle) * radius, -cos(angle) * radius); + dir = normalize(pos - lastPos); + lastPos = pos; + return (Vector3) float3(lastPos, LinkDepth); }).ToArray()); _linkInstances.Add(link.GetComponent()); + + var arrow = Arrow.Instantiate(); + 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[islands[edge.Source]]; + _arrowInstances.Add(arrow.GetComponent()); } } else diff --git a/Assets/Scripts/UI/TechArrow.cs b/Assets/Scripts/UI/TechArrow.cs new file mode 100644 index 000000000..ebdfe25e4 --- /dev/null +++ b/Assets/Scripts/UI/TechArrow.cs @@ -0,0 +1,8 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class TechArrow : MonoBehaviour +{ + public MeshRenderer Icon; +} diff --git a/Assets/Scripts/UI/TechArrow.cs.meta b/Assets/Scripts/UI/TechArrow.cs.meta new file mode 100644 index 000000000..9f8dbc7ed --- /dev/null +++ b/Assets/Scripts/UI/TechArrow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d54298fa75eb6304489e19a84af3413f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/UI/TechNode.cs b/Assets/Scripts/UI/TechNode.cs index f456efdb9..1ead1058d 100644 --- a/Assets/Scripts/UI/TechNode.cs +++ b/Assets/Scripts/UI/TechNode.cs @@ -7,4 +7,6 @@ public class TechNode : MonoBehaviour { public TextMeshPro Label; public MeshRenderer Icon; + public MeshRenderer Fill; + public MeshRenderer Glow; } diff --git a/README.md b/README.md index ed942e72f..ce92e8e02 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Aetheria -This repository is the home of Aetheria, a sci-fi hybrid ARPG/RTS MMO about a group of corporations colonizing a hostile alien galaxy, with a satirical narrative critiquing late-stage capitalism. +This repository is the home of Aetheria, an economy focused RTS MMO where you control the production, research, supply chains and actions of a corporation tasked with colonizing an alien galaxy. Control over your minions is indirect, like in Rimworld, and gameplay takes place over months as your production and tasks continue acting on the world even when you're offline.