/// <summary> /// Returns a copy of the supplied style modified to apply a selected random value to extruded /// buildings that do not have a server provided height. /// </summary> /// <param name="suppliedStyle">Style to use as a template.</param> /// <returns>A modified copy of suppliedStyle.</returns> private ExtrudedStructureStyle RandomizeBuildingHeight(ExtrudedStructureStyle suppliedStyle) { ExtrudedStructureStyle.Builder builder = new ExtrudedStructureStyle.Builder(suppliedStyle); builder.ExtrudedBuildingFootprintHeight = Random.Range(MinRandomBuildingHeight, MaxRandomBuildingHeight); return(builder.Build()); }
/// <summary> /// Use <see cref="DynamicMapsService"/> to load geometry, replacing any buildings as needed. /// </summary> private void Awake() { // Make sure a prefab has been specified. if (Prefab == null) { Debug.LogError(ExampleErrors.MissingParameter(this, Prefab, "Prefab", "to replace specific buildings with")); return; } // Get required DynamicMapsService component on this GameObject. DynamicMapsService dynamicMapsService = GetComponent <DynamicMapsService>(); // See if any options have been set indicating which types of buildings to replace, signing up // to WillCreate events if so. if (ReplaceBars || ReplaceBanks || ReplaceLodgings || ReplaceCafes || ReplaceRestaurants || ReplaceEventVenues || ReplaceTouristDestinations || ReplaceShops || ReplaceSchools || ReplaceUnspecifieds) { // Create styles for ExtrudedStructure and ModeledStructure type buildings that are to be // replaced with a prefab. ExtrudedStructureStyle extrudedPrefabStyle = new ExtrudedStructureStyle.Builder { Prefab = Prefab }.Build(); ModeledStructureStyle modeledPrefabStyle = new ModeledStructureStyle.Builder { Prefab = Prefab }.Build(); // Sign up to events called just before any new building is loaded, so we can check each // building's usage type and replace it with prefab if needed. Note that: // - DynamicMapsService.MapsService is auto-found on first access (so will not be null). // - These events must be set now during Awake, so that when DynamicMapsService starts // loading the map during Start, these event will be triggered for all ExtrudedStructures // and ModeledStructures. dynamicMapsService.MapsService.Events.ExtrudedStructureEvents.WillCreate.AddListener(args => { if (ShouldReplaceBuilding(args.MapFeature.Metadata.Usage)) { args.Style = extrudedPrefabStyle; } }); dynamicMapsService.MapsService.Events.ModeledStructureEvents.WillCreate.AddListener(args => { if (ShouldReplaceBuilding(args.MapFeature.Metadata.Usage)) { args.Style = modeledPrefabStyle; } }); } // See if we should be replacing any suppressed buildings with prefab, signing up to DidCreate // event if so. if (ReplaceSuppressed) { // Sign up to event called just after any new building is loaded, so we can check if the // building's mesh has been suppressed and should be replaced with a prefab. dynamicMapsService.MapsService.Events.ExtrudedStructureEvents.DidCreate.AddListener( args => TryReplaceSuppressedBuilding(args.GameObject)); dynamicMapsService.MapsService.Events.ModeledStructureEvents.DidCreate.AddListener( args => TryReplaceSuppressedBuilding(args.GameObject)); } }
private static void addPrefabForType(StructureMetadata.UsageType type, string path, Dictionary <StructureMetadata.UsageType, ExtrudedStructureStyle> mapping) { Object prefabModel = Resources.Load(path); GameObject prefab = (GameObject)Instantiate(prefabModel, Vector3.zero, Quaternion.identity); ExtrudedStructureStyle extrudedPrefabStyle = new ExtrudedStructureStyle.Builder { Prefab = prefab }.Build(); mapping.Add(type, extrudedPrefabStyle); }
public void OnWillCreateExtrudedStructure(WillCreateExtrudedStructureArgs args) { if (!enabled) { return; } ExtrudedStructureStyle.Builder builder = args.Style.AsBuilder(); builder.ApplyFixedHeight = false; //builder.FixedHeight = 0; args.Style = builder.Build(); }
/// <summary> /// Randomize building heights deterministically based on a random seed plus the structure's /// place id. /// </summary> public void OnWillCreateExtrudedStructure(WillCreateExtrudedStructureArgs args) { if (!enabled) { return; } string placeId = args.MapFeature.MapFeatureMetadata.PlaceId; PRNG prng = new PRNG(RandomSeed); for (int i = 0; i < placeId.Length; i++) { prng.Mix(placeId[i]); } ExtrudedStructureStyle.Builder builder = args.Style.AsBuilder(); builder.ApplyFixedHeight = true; int minHeight = MinExtrudedStructureHeight; int maxHeight = MaxExtrudedStructureHeight; builder.FixedHeight = minHeight + prng.NextRandomFloat() * (maxHeight - minHeight); args.Style = builder.Build(); }
/// <summary> /// Setup default <see cref="GameObjectOptions"/>. /// </summary> static ExampleDefaults() { // Find shaders that will be used to create required Materials for rendering geometry // generated by the Maps SDK for Unity. Shader standardShader = Shader.Find("Google/Maps/Shaders/Standard"); if (standardShader == null) { // Try to find the Unity Standard Shader as a backup. standardShader = Shader.Find("Standard"); if (standardShader == null) { // Try to find the Legacy Diffuse Shader as a backup-backup. standardShader = Shader.Find("Diffuse"); if (standardShader == null) { Debug.LogErrorFormat( "Unable to find Maps SDK for Unity Standard Shader (named " + "\"Google/Maps/Shaders/Standard\"), or as a backup the Unity Standard " + "Shader (named \"Standard\"), or as a backup-backup the Legacy Unity " + "Standard Shader (named \"Diffuse\"), so cannot setup default materials in {0}", typeof(ExampleDefaults)); return; } Debug.LogWarningFormat( "Unable to find Maps SDK for Unity Standard Shader (named " + "\"Google/Maps/Shaders/Standard\"), or as a backup the Unity Standard Shader " + "(named \"Standard\")\nDefaulting to Legacy Unity Standard Shader (named" + "\"Diffuse\") as a backup-backup for setting up default materials in {0}", typeof(ExampleDefaults)); } else { Debug.LogWarningFormat( "Unable to find Maps SDK for Unity Standard Shader (named " + "\"Google/Maps/Shaders/Standard\").\nDefaulting to the Unity Standard Shader " + "(named \"Standard\") as a backup for setting up default materials in {0}", typeof(ExampleDefaults)); } } // Find BaseMaps Shader. Note that this Shader does not have a backup, as it has unique // behaviour needed for BaseMap level geometry to show in the correct render order. Shader baseMapShader = Shader.Find("Google/Maps/Shaders/BaseMap Color"); if (baseMapShader == null) { Debug.LogErrorFormat( "Unable to find Maps SDK for Unity Base Map Shader (named " + "\"Google/Maps/Shaders/BaseMap Color\"), so unable to setup default materials in " + "{0}", typeof(ExampleDefaults)); return; } // Create default materials for use by buildings, as well as other materials for use by water, // ground, roads, etc. Material wallMaterial = new Material(standardShader) { color = new Color(1f, 0.75f, 0.5f) }; Material roofMaterial = new Material(standardShader) { color = new Color(1f, 0.8f, 0.6f) }; Material regionMaterial = new Material(baseMapShader) { color = new Color(0.5f, 0.7f, 0.5f), }; regionMaterial.SetFloat("_Glossiness", 1f); Material waterMaterial = new Material(baseMapShader) { color = new Color(0.0f, 1.0f, 1.0f), }; waterMaterial.SetFloat("_Glossiness", 1f); Material segmentMaterial = new Material(baseMapShader) { color = new Color(0.5f, 0.5f, 0.5f), }; segmentMaterial.SetFloat("_Glossiness", 0.5f); // Create style for buildings made from extruded shapes (most buildings). ExtrudedStructureStyle extrudedStructureStyle = new ExtrudedStructureStyle .Builder { WallMaterial = wallMaterial, RoofMaterial = roofMaterial } .Build(); // Create style for buildings with detailed vertex/triangle data (such as the Statue of // Liberty). ModeledStructureStyle modeledStructureStyle = new ModeledStructureStyle.Builder { Material = wallMaterial }.Build(); // Create style for regions (such as parks). RegionStyle regionStyle = new RegionStyle.Builder { FillMaterial = regionMaterial }.Build(); // Create style for bodies of water (such as oceans). AreaWaterStyle areaWaterStyle = new AreaWaterStyle.Builder { FillMaterial = waterMaterial }.Build(); // Create style for lines of water (such as narrow rivers). LineWaterStyle lineWaterStyle = new LineWaterStyle.Builder { Material = waterMaterial }.Build(); // Create style for segments (such as roads). SegmentStyle segmentStyle = new SegmentStyle.Builder { Material = segmentMaterial, Width = 7.0f }.Build(); // Collect styles into a form that can be given to map loading function. DefaultGameObjectOptions = new GameObjectOptions { ExtrudedStructureStyle = extrudedStructureStyle, ModeledStructureStyle = modeledStructureStyle, RegionStyle = regionStyle, AreaWaterStyle = areaWaterStyle, LineWaterStyle = lineWaterStyle, SegmentStyle = segmentStyle, }; }
/// <summary> /// Returns a new <see cref="GameObjectOptions"/> instance reflecting the properties on /// this component. /// </summary> private GameObjectOptions CreateGameObjectOptions() { GameObjectOptions gameObjectOptions = new GameObjectOptions(); // Terrain style TerrainStyle.Builder terrainStyleBuilder = new TerrainStyle.Builder() { AlphaMapResolutionMetersPerPixel = AlphaMapResolutionMetersPerPixel, BaseMapResolutionMetersPerPixel = BaseMapResolutionMetersPerPixel, BaseMapDistance = BaseMapDistance, TerrainLayers = new List <TerrainLayer>(TerrainLayers), }; gameObjectOptions.TerrainStyle = terrainStyleBuilder.Build(); // Segment style SegmentStyle.Builder segmentStyleBuilder = new SegmentStyle.Builder() { Material = SegmentMaterial, IntersectionMaterial = IntersectionMaterial, GameObjectLayer = gameObjectOptions.TerrainStyle.TerrainPaintingLayer }; gameObjectOptions.SegmentStyle = segmentStyleBuilder.Build(); // Area water style AreaWaterStyle.Builder areaWaterStyleBuilder = new AreaWaterStyle.Builder() { FillMaterial = AreaWaterMaterial, GameObjectLayer = gameObjectOptions.TerrainStyle.TerrainPaintingLayer }; gameObjectOptions.AreaWaterStyle = areaWaterStyleBuilder.Build(); // Region style RegionStyle.Builder regionStyleBuilder = new RegionStyle.Builder() { FillMaterial = RegionMaterial, GameObjectLayer = gameObjectOptions.TerrainStyle.TerrainPaintingLayer }; gameObjectOptions.RegionStyle = regionStyleBuilder.Build(); // Line water style LineWaterStyle.Builder lineWaterStyleBuilder = new LineWaterStyle.Builder() { Material = LineWaterMaterial, GameObjectLayer = gameObjectOptions.TerrainStyle.TerrainPaintingLayer }; gameObjectOptions.LineWaterStyle = lineWaterStyleBuilder.Build(); // Extruded structure style ExtrudedStructureStyle.Builder extrudedStructureStyleBuilder = new ExtrudedStructureStyle.Builder() { RoofMaterial = BuildingMaterial, WallMaterial = BuildingMaterial }; gameObjectOptions.ExtrudedStructureStyle = extrudedStructureStyleBuilder.Build(); // Modeled structure style ModeledStructureStyle.Builder modeledStructureStyleBuilder = new ModeledStructureStyle.Builder() { Material = BuildingMaterial }; gameObjectOptions.ModeledStructureStyle = modeledStructureStyleBuilder.Build(); return(gameObjectOptions); }
/// <summary> /// Connect to <see cref="FloatingOriginUpdater.OnFloatingOriginUpdate"/>, so that whenever the /// world's Floating Origin is moved, all controlled world space textured /// <see cref="WorldspaceMaterials"/> are realigned to the world's new Floating Origin. /// </summary> private void Start() { // Verify all required parameters are defined, skipping further setup if not. if (!VerifyParameters()) { enabled = false; return; } // Get the required Floating Origin component on this GameObject. FloatingOriginUpdater floatingOriginUpdater = GetComponent <FloatingOriginUpdater>(); // Make sure that whenever the Floating Origin is updated, Materials are updated in sync. floatingOriginUpdater.OnFloatingOriginUpdate.AddListener(UpdateWorldspaceMaterialOffsets); // Store all Materials that are to be updated. This function only stores Materials that have an // _Offset Vector, which will be used to offset the Material's world space coordinates to align // to the world's moved Floating Origin. TryAddMaterial(Buildings); TryAddMaterial(Roads); TryAddMaterial(Ground); TryAddMaterial(Water); // Because the Floating Origin has not yet been moved, there is no need to apply an _Offset to // these Materials yet. Instead we make sure these Material's _Offsets start at (0, 0, 0). UpdateWorldspaceMaterialOffsets(Vector3.zero); // Create styles to assign world space textured Materials to geometry as it is created. ExtrudedStructureStyle extrudedStructureStyle = new ExtrudedStructureStyle.Builder { WallMaterial = Buildings, RoofMaterial = Buildings }.Build(); ModeledStructureStyle modeledStructureStyle = new ModeledStructureStyle.Builder { Material = Buildings }.Build(); SegmentStyle roadsStyle = new SegmentStyle.Builder { Material = Roads, BorderMaterial = Borders, Width = 7.0f, BorderWidth = BorderWidth }.Build(); RegionStyle groundStyle = new RegionStyle.Builder { FillMaterial = Ground }.Build(); AreaWaterStyle areaWaterStyle = new AreaWaterStyle.Builder { FillMaterial = Water }.Build(); LineWaterStyle lineWaterStyle = new LineWaterStyle.Builder { Material = Water, Width = 7.0f }.Build(); GameObjectOptions renderingStyles = ExampleDefaults.DefaultGameObjectOptions; renderingStyles.ExtrudedStructureStyle = extrudedStructureStyle; renderingStyles.ModeledStructureStyle = modeledStructureStyle; renderingStyles.SegmentStyle = roadsStyle; renderingStyles.RegionStyle = groundStyle; renderingStyles.AreaWaterStyle = areaWaterStyle; renderingStyles.LineWaterStyle = lineWaterStyle; DynamicMapsService dynamicMapsService = floatingOriginUpdater.DynamicMapsService; dynamicMapsService.RenderingStyles = renderingStyles; // Make sure that if any new Materials are cloned by the Maps Service (which can occur to // resolve z-fighting issues), that these new cloned materials are added to the list of managed // Materials. MapsService mapsService = dynamicMapsService.MapsService; mapsService.Events.RegionEvents.DidCreate.AddListener( args => TryAddMaterialFrom(args.GameObject)); mapsService.Events.AreaWaterEvents.DidCreate.AddListener( args => TryAddMaterialFrom(args.GameObject)); mapsService.Events.LineWaterEvents.DidCreate.AddListener( args => TryAddMaterialFrom(args.GameObject)); mapsService.Events.SegmentEvents.DidCreate.AddListener( args => TryAddMaterialFrom(args.GameObject)); mapsService.Events.ModeledStructureEvents.DidCreate.AddListener( args => TryAddMaterialFrom(args.GameObject)); // For extruded buildings, also create borders around the edges of these buildings, to match // borders around roads. mapsService.Events.ExtrudedStructureEvents.DidCreate.AddListener(args => { Debug.Log(args.MapFeature.MapFeatureMetadata.PlaceId); TryAddMaterialFrom(args.GameObject); Extruder.AddBuildingBorder(args.GameObject, args.MapFeature.Shape, Borders, BorderWidth); }); }
public void Init(MapsService mapsService, PlacesService placesService) { this._placesService = placesService; mapsService.Events.ExtrudedStructureEvents.WillCreate.AddListener(args => { if (buildingModels.TryGetValue(args.MapFeature.Metadata.Usage, out var model)) { if (args.MapFeature.GetShape() is ExtrudedArea area && area.Extrusions.Length == 1) { var vertices = area.Extrusions[0].FootPrint.Vertices; if (vertices.Length >= 2) { var edge = vertices[1] - vertices[0]; float angle = Vector2.Angle(edge, Vector2.right); var rotation = Quaternion.AngleAxis(angle + 90, Vector3.up); GameObject prefab = (GameObject)Instantiate(model, Vector3.zero, rotation); Bounds bounds = prefab.GetComponent <Renderer>().bounds; float minBoundsSize = Math.Min(bounds.size.x, bounds.size.z); float minEdgeSize = float.MaxValue; for (int i = 0; i < vertices.Length - 1; i++) { var edgeSize = (vertices[i + 1] - vertices[i]).magnitude; if (edgeSize < minEdgeSize) { minEdgeSize = edgeSize; } } float scale = minEdgeSize / minBoundsSize; prefab.transform.localScale = new Vector3(scale, scale, scale); ExtrudedStructureStyle style = new ExtrudedStructureStyle.Builder { Prefab = prefab }.Build(); args.Style = style; } } } }); mapsService.Events.ExtrudedStructureEvents.DidCreate.AddListener(args => { var placeName = args.MapFeature.Metadata.Name; if (placeName.IsEmpty()) { return; } if (args.MapFeature.Metadata.Usage != StructureMetadata.UsageType.Unspecified) { return; } var mapObject = args.GameObject; var nameObject = Instantiate(labelPrefab, labelsCanvas.transform); nameObject.gameObject.name = "Name: " + placeName; nameObject.SetText(placeName); nameObject.transform.position = mapObject.transform.position; nameObject.FadeWithView = true; nameObject.StartFadingIn(); args.GameObject.OnDestroyAsObservable().Subscribe(_ => Destroy(nameObject)); }); // Sign up to event called after each new building is loaded, so can assign Materials to this // new building. Note that: // - DynamicMapsService.MapsService is auto-found on first access (so will not be null). // - This event must be set now during Awake, so that when Dynamic Maps Service starts loading // the map during Start, this event will be triggered for all Extruded Structures. mapsService.Events.ExtrudedStructureEvents.DidCreate.AddListener( args => { if (!buildingModels.ContainsKey(args.MapFeature.Metadata.Usage)) { AssignNineSlicedMaterials(args.GameObject); } }); }