private const float inchesInMeters = 0.03125f; // 1/32

        /// <summary>
        /// Imports the specified world into the SabreCSG model.
        /// </summary>
        /// <param name="model">The model to import into.</param>
        /// <param name="world">The world to be imported.</param>
        /// <param name="scale">The scale modifier.</param>
        public static void Import(CSGModelBase model, VmfWorld world)
        {
            try
            {
                model.BeginUpdate();

                // create a material searcher to associate materials automatically.
                MaterialSearcher materialSearcher = new MaterialSearcher();

                // group all the brushes together.
                GroupBrush groupBrush = new GameObject("Source Engine Map").AddComponent <GroupBrush>();
                groupBrush.transform.SetParent(model.transform);

                // iterate through all world solids.
                for (int i = 0; i < world.Solids.Count; i++)
                {
#if UNITY_EDITOR
                    UnityEditor.EditorUtility.DisplayProgressBar("SabreCSG: Importing Source Engine Map", "Converting Hammer Solids To SabreCSG Brushes (" + (i + 1) + " / " + world.Solids.Count + ")...", i / (float)world.Solids.Count);
#endif
                    VmfSolid solid = world.Solids[i];

                    // don't add triggers to the scene.
                    if (solid.Sides.Count > 0 && IsSpecialMaterial(solid.Sides[0].Material))
                    {
                        continue;
                    }

                    // build a very large cube brush.
                    var go = model.CreateBrush(PrimitiveBrushType.Cube, Vector3.zero);
                    var pr = go.GetComponent <PrimitiveBrush>();
                    BrushUtility.Resize(pr, new Vector3(8192, 8192, 8192));

                    // clip all the sides out of the brush.
                    for (int j = solid.Sides.Count; j-- > 0;)
                    {
                        VmfSolidSide side = solid.Sides[j];
                        Plane        clip = new Plane(pr.transform.InverseTransformPoint(new Vector3(side.Plane.P1.X, side.Plane.P1.Z, side.Plane.P1.Y) * inchesInMeters), pr.transform.InverseTransformPoint(new Vector3(side.Plane.P2.X, side.Plane.P2.Z, side.Plane.P2.Y) * inchesInMeters), pr.transform.InverseTransformPoint(new Vector3(side.Plane.P3.X, side.Plane.P3.Z, side.Plane.P3.Y) * inchesInMeters));
                        ClipUtility.ApplyClipPlane(pr, clip, false);

                        // find the polygons associated with the clipping plane.
                        // the normal is unique and can never occur twice as that wouldn't allow the solid to be convex.
                        var polygons = pr.GetPolygons().Where(p => p.Plane.normal == clip.normal);
                        foreach (var polygon in polygons)
                        {
                            // detect excluded polygons.
                            if (IsExcludedMaterial(side.Material))
                            {
                                polygon.UserExcludeFromFinal = true;
                            }
                            // detect collision-only brushes.
                            if (IsInvisibleMaterial(side.Material))
                            {
                                pr.IsVisible = false;
                            }
                            // find the material in the unity project automatically.
                            Material material;
                            // try finding the fully qualified texture name with '/' replaced by '.' so 'BRICK.BRICKWALL052D'.
                            string materialName = side.Material.Replace("/", ".");
                            if (materialName.Contains('.'))
                            {
                                // try finding both 'BRICK.BRICKWALL052D' and 'BRICKWALL052D'.
                                string tiny = materialName.Substring(materialName.LastIndexOf('.') + 1);
                                material = materialSearcher.FindMaterial(new string[] { materialName, tiny });
                                if (material == null)
                                {
                                    Debug.Log("SabreCSG: Tried to find material '" + materialName + "' and also as '" + tiny + "' but it couldn't be found in the project.");
                                }
                            }
                            else
                            {
                                // only try finding 'BRICKWALL052D'.
                                material = materialSearcher.FindMaterial(new string[] { materialName });
                                if (material == null)
                                {
                                    Debug.Log("SabreCSG: Tried to find material '" + materialName + "' but it couldn't be found in the project.");
                                }
                            }
                            polygon.Material = material;
                            // calculate the texture coordinates.
                            int w = 256;
                            int h = 256;
                            if (polygon.Material != null && polygon.Material.mainTexture != null)
                            {
                                w = polygon.Material.mainTexture.width;
                                h = polygon.Material.mainTexture.height;
                            }
                            CalculateTextureCoordinates(pr, polygon, w, h, side.UAxis, side.VAxis);
                        }
                    }

                    // add the brush to the group.
                    pr.transform.SetParent(groupBrush.transform);
                }

                // iterate through all entities.
                for (int e = 0; e < world.Entities.Count; e++)
                {
#if UNITY_EDITOR
                    UnityEditor.EditorUtility.DisplayProgressBar("SabreCSG: Importing Source Engine Map", "Converting Hammer Entities To SabreCSG Brushes (" + (e + 1) + " / " + world.Entities.Count + ")...", e / (float)world.Entities.Count);
#endif
                    VmfEntity entity = world.Entities[e];

                    // skip entities that sabrecsg can't handle.
                    switch (entity.ClassName)
                    {
                    case "func_areaportal":
                    case "func_areaportalwindow":
                    case "func_capturezone":
                    case "func_changeclass":
                    case "func_combine_ball_spawner":
                    case "func_dustcloud":
                    case "func_dustmotes":
                    case "func_nobuild":
                    case "func_nogrenades":
                    case "func_occluder":
                    case "func_precipitation":
                    case "func_proprespawnzone":
                    case "func_regenerate":
                    case "func_respawnroom":
                    case "func_smokevolume":
                    case "func_viscluster":
                        continue;
                    }

                    // iterate through all entity solids.
                    for (int i = 0; i < entity.Solids.Count; i++)
                    {
                        VmfSolid solid = entity.Solids[i];

                        // don't add triggers to the scene.
                        if (solid.Sides.Count > 0 && IsSpecialMaterial(solid.Sides[0].Material))
                        {
                            continue;
                        }

                        // build a very large cube brush.
                        var go = model.CreateBrush(PrimitiveBrushType.Cube, Vector3.zero);
                        var pr = go.GetComponent <PrimitiveBrush>();
                        BrushUtility.Resize(pr, new Vector3(8192, 8192, 8192));

                        // clip all the sides out of the brush.
                        for (int j = solid.Sides.Count; j-- > 0;)
                        {
                            VmfSolidSide side = solid.Sides[j];
                            Plane        clip = new Plane(pr.transform.InverseTransformPoint(new Vector3(side.Plane.P1.X, side.Plane.P1.Z, side.Plane.P1.Y) * inchesInMeters), pr.transform.InverseTransformPoint(new Vector3(side.Plane.P2.X, side.Plane.P2.Z, side.Plane.P2.Y) * inchesInMeters), pr.transform.InverseTransformPoint(new Vector3(side.Plane.P3.X, side.Plane.P3.Z, side.Plane.P3.Y) * inchesInMeters));
                            ClipUtility.ApplyClipPlane(pr, clip, false);

                            // find the polygons associated with the clipping plane.
                            // the normal is unique and can never occur twice as that wouldn't allow the solid to be convex.
                            var polygons = pr.GetPolygons().Where(p => p.Plane.normal == clip.normal);
                            foreach (var polygon in polygons)
                            {
                                // detect excluded polygons.
                                if (IsExcludedMaterial(side.Material))
                                {
                                    polygon.UserExcludeFromFinal = true;
                                }
                                // detect collision-only brushes.
                                if (IsInvisibleMaterial(side.Material))
                                {
                                    pr.IsVisible = false;
                                }
                                // find the material in the unity project automatically.
                                Material material;
                                // try finding the fully qualified texture name with '/' replaced by '.' so 'BRICK.BRICKWALL052D'.
                                string materialName = side.Material.Replace("/", ".");
                                if (materialName.Contains('.'))
                                {
                                    // try finding both 'BRICK.BRICKWALL052D' and 'BRICKWALL052D'.
                                    string tiny = materialName.Substring(materialName.LastIndexOf('.') + 1);
                                    material = materialSearcher.FindMaterial(new string[] { materialName, tiny });
                                    if (material == null)
                                    {
                                        Debug.Log("SabreCSG: Tried to find material '" + materialName + "' and also as '" + tiny + "' but it couldn't be found in the project.");
                                    }
                                }
                                else
                                {
                                    // only try finding 'BRICKWALL052D'.
                                    material = materialSearcher.FindMaterial(new string[] { materialName });
                                    if (material == null)
                                    {
                                        Debug.Log("SabreCSG: Tried to find material '" + materialName + "' but it couldn't be found in the project.");
                                    }
                                }
                                polygon.Material = material;
                                // calculate the texture coordinates.
                                int w = 256;
                                int h = 256;
                                if (polygon.Material != null && polygon.Material.mainTexture != null)
                                {
                                    w = polygon.Material.mainTexture.width;
                                    h = polygon.Material.mainTexture.height;
                                }
                                CalculateTextureCoordinates(pr, polygon, w, h, side.UAxis, side.VAxis);
                            }
                        }

                        // detail brushes that do not affect the CSG world.
                        if (entity.ClassName == "func_detail")
                        {
                            pr.IsNoCSG = true;
                        }
                        // collision only brushes.
                        if (entity.ClassName == "func_vehicleclip")
                        {
                            pr.IsVisible = false;
                        }

                        // add the brush to the group.
                        pr.transform.SetParent(groupBrush.transform);
                    }
                }

#if UNITY_EDITOR
                UnityEditor.EditorUtility.ClearProgressBar();
#endif
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                model.EndUpdate();
            }
        }
        /// <summary>
        /// Imports the specified world into the SabreCSG model.
        /// </summary>
        /// <param name="model">The model to import into.</param>
        /// <param name="world">The world to be imported.</param>
        /// <param name="scale">The scale modifier.</param>
        public static void Import(CSGModelBase model, MapWorld world)
        {
            try
            {
                model.BeginUpdate();

                // create a material searcher to associate materials automatically.
                MaterialSearcher materialSearcher = new MaterialSearcher();

                // group all the brushes together.
                GroupBrush groupBrush = new GameObject("Quake 1 Map").AddComponent <GroupBrush>();
                groupBrush.transform.SetParent(model.transform);

                // iterate through all entities.
                for (int e = 0; e < world.Entities.Count; e++)
                {
#if UNITY_EDITOR
                    UnityEditor.EditorUtility.DisplayProgressBar("SabreCSG: Importing Quake 1 Map", "Converting Quake 1 Entities To SabreCSG Brushes (" + (e + 1) + " / " + world.Entities.Count + ")...", e / (float)world.Entities.Count);
#endif
                    MapEntity entity = world.Entities[e];

                    // iterate through all entity solids.
                    for (int i = 0; i < entity.Brushes.Count; i++)
                    {
                        MapBrush brush = entity.Brushes[i];
#if UNITY_EDITOR
                        if (world.Entities[e].ClassName == "worldspawn")
                        {
                            UnityEditor.EditorUtility.DisplayProgressBar("SabreCSG: Importing Quake 1 Map", "Converting Quake 1 Brushes To SabreCSG Brushes (" + (i + 1) + " / " + entity.Brushes.Count + ")...", i / (float)entity.Brushes.Count);
                        }
#endif
                        // don't add triggers to the scene.
                        if (brush.Sides.Count > 0 && IsSpecialMaterial(brush.Sides[0].Material))
                        {
                            continue;
                        }

                        // build a very large cube brush.
                        var go = model.CreateBrush(PrimitiveBrushType.Cube, Vector3.zero);
                        var pr = go.GetComponent <PrimitiveBrush>();
                        BrushUtility.Resize(pr, new Vector3(8192, 8192, 8192));

                        // clip all the sides out of the brush.
                        for (int j = brush.Sides.Count; j-- > 0;)
                        {
                            MapBrushSide side = brush.Sides[j];
                            Plane        clip = new Plane(pr.transform.InverseTransformPoint(new Vector3(side.Plane.P1.X, side.Plane.P1.Z, side.Plane.P1.Y) / (float)s_Scale), pr.transform.InverseTransformPoint(new Vector3(side.Plane.P2.X, side.Plane.P2.Z, side.Plane.P2.Y) / (float)s_Scale), pr.transform.InverseTransformPoint(new Vector3(side.Plane.P3.X, side.Plane.P3.Z, side.Plane.P3.Y) / (float)s_Scale));
                            ClipUtility.ApplyClipPlane(pr, clip, false);

                            // find the polygons associated with the clipping plane.
                            // the normal is unique and can never occur twice as that wouldn't allow the solid to be convex.
                            var polygons = pr.GetPolygons().Where(p => p.Plane.normal.EqualsWithEpsilonLower3(clip.normal));
                            foreach (var polygon in polygons)
                            {
                                // detect excluded polygons.
                                if (IsExcludedMaterial(side.Material))
                                {
                                    polygon.UserExcludeFromFinal = true;
                                }
                                // detect collision-only brushes.
                                if (IsInvisibleMaterial(side.Material))
                                {
                                    pr.IsVisible = false;
                                }
                                // find the material in the unity project automatically.
                                Material material;
                                // try finding the texture name with '*' replaced by '#' so '#teleport'.
                                string materialName = side.Material.Replace("*", "#");
                                material = materialSearcher.FindMaterial(new string[] { materialName });
                                if (material == null)
                                {
                                    Debug.Log("SabreCSG: Tried to find material '" + materialName + "' but it couldn't be found in the project.");
                                }
                                polygon.Material = material;
                                // calculate the texture coordinates.
                                int w = 256;
                                int h = 256;
                                if (polygon.Material != null && polygon.Material.mainTexture != null)
                                {
                                    w = polygon.Material.mainTexture.width;
                                    h = polygon.Material.mainTexture.height;
                                }
                                CalculateTextureCoordinates(pr, polygon, w, h, new Vector2(side.Offset.X, -side.Offset.Y), new Vector2(side.Scale.X, side.Scale.Y), side.Rotation);
                            }
                        }

                        // add the brush to the group.
                        pr.transform.SetParent(groupBrush.transform);
                    }
                }

#if UNITY_EDITOR
                UnityEditor.EditorUtility.ClearProgressBar();
#endif
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                model.EndUpdate();
            }
        }
Esempio n. 3
0
        protected override void OnApplyChanges()
        {
            // Do not proceed if no atlas texture was selected.
            if (this.inputNewAutotileArtwork == null)
            {
                EditorUtility.DisplayDialog(
                    TileLang.ParticularText("Error", "Autotile artwork was not specified"),
                    TileLang.Text("Please select artwork for autotile before proceeding."),
                    TileLang.ParticularText("Action", "Close")
                    );
                return;
            }

            // Warn user if modified atlas will contain impossible brushes.
            if (BrushUtility.WouldHaveImpossibleTilesetBrushes(this.tileset, this.inputTileWidth, this.inputTileHeight, this.inputBorderSize))
            {
                if (!EditorUtility.DisplayDialog(
                        TileLang.Text("Warning, brushes will be deleted"),
                        TileLang.Text("Modified atlas contains fewer tiles than previously. Previously created brushes that are out of range will be deleted.\n\nWould you like to proceed?"),
                        TileLang.ParticularText("Action", "Yes"),
                        TileLang.ParticularText("Action", "No")
                        ))
                {
                    return;
                }
            }

            bool refreshProceduralMeshes = !this.inputProcedural && this.autotileTileset.procedural;

            // If raw uncompressed variation of autotile is not defined generate from
            // current selection.
            if (this.inputNewAutotileArtworkUncompressed == null)
            {
                if (this.inputNewAutotileArtwork == null)
                {
                    Debug.LogError(TileLang.ParticularText("Error", "Invalid autotile artwork was specified."));
                    return;
                }
                this.inputNewAutotileArtworkUncompressed = EditorInternalUtility.LoadTextureUncompressed(this.inputNewAutotileArtwork);
            }

            this.ExpandAutotileArtwork(this.inputBorderSize);

            string tilesetBasePath = this.tilesetRecord.AssetPath.Substring(0, this.tilesetRecord.AssetPath.LastIndexOf('/') + 1);

            // Save texture asset.
            string assetPath = AssetDatabase.GetAssetPath(this.autotileTileset.AtlasTexture);

            if (string.IsNullOrEmpty(assetPath) || !assetPath.StartsWith(tilesetBasePath))
            {
                assetPath = AssetDatabase.GenerateUniqueAssetPath(tilesetBasePath + "atlas.png");
            }

            this.autotileTileset.AtlasTexture = EditorInternalUtility.SavePngAsset(assetPath, this.expandedAutotileAtlas);

            // Update and save material asset.
            if (this.autotileTileset.AtlasMaterial == null)
            {
                this.autotileTileset.AtlasMaterial             = new Material(Shader.Find("Rotorz/Tileset/Opaque Unlit"));
                this.autotileTileset.AtlasMaterial.mainTexture = this.autotileTileset.AtlasTexture;

                assetPath = AssetDatabase.GenerateUniqueAssetPath(tilesetBasePath + "atlas.mat");
                AssetDatabase.CreateAsset(this.autotileTileset.AtlasMaterial, assetPath);
                AssetDatabase.ImportAsset(assetPath);
            }
            else
            {
                this.autotileTileset.AtlasMaterial.mainTexture = this.autotileTileset.AtlasTexture;
                EditorUtility.SetDirty(this.autotileTileset.AtlasMaterial);
            }

            // Calculate metrics for tileset.
            var metrics = new TilesetMetrics(this.autotileTileset.AtlasTexture, this.inputTileWidth, this.inputTileHeight, this.inputBorderSize, this.inputDelta);

            // Update properties of tileset.
            this.autotileTileset.procedural      = this.inputProcedural;
            this.autotileTileset.ForceClampEdges = this.inputClampEdges;
            this.autotileTileset.rawTexture      = this.inputNewAutotileArtwork;
            this.autotileTileset.SetMetricsFrom(metrics);

            this.ClearExpandedAutotileAtlas();

            EditorUtility.SetDirty(this.autotileTileset);

            // Delete "impossible" tile brushes in tileset.
            // For example, an extra brush for a tile that no longer exists.
            BrushUtility.DeleteImpossibleTilesetBrushes(this.tileset);

            // Ensure that non-procedural meshes are pre-generated if missing.
            if (refreshProceduralMeshes)
            {
                BrushUtility.RefreshNonProceduralMeshes(this.tileset);
            }

            ToolUtility.RepaintBrushPalette();

            // Update procedural meshes for tile systems in scene if necessary.
            // Note: Only update if procedural mode of tileset was not modified.
            if (this.inputProcedural && this.tileset.procedural)
            {
                foreach (TileSystem tileSystem in Object.FindObjectsOfType(typeof(TileSystem)))
                {
                    tileSystem.UpdateProceduralTiles(true);
                }
            }
        }
Esempio n. 4
0
    /// <summary>
    /// Upgrades oriented brush (v1.x) into an oriented brush (v2.x).
    /// </summary>
    /// <param name="record">Record for existing v1.x brush.</param>
    private void UpgradeOrientedBrush(RtsBrushAssetRecordWrapper record)
    {
        if (useNewAssets)
        {
            // Is this the original "Smooth Platform" master brushes?
            if (record.assetPath == "Assets/Rotorz Tile System/Brushes/Smooth Platform.prefab" ||
                record.assetPath == "Assets/Rotorz Tile System/Brushes/Smooth Platform (Join).prefab" ||
                record.assetPath == "Assets/Rotorz Tile System/Brushes/Smooth Platform (Small).prefab")
            {
                // This is a special case that can be switched to new version
                // if it was imported.
                OrientedBrush newMasterBrush = AssetDatabase.LoadAssetAtPath("Assets/Rotorz/Tile System/TileBrushes/Master/" + record.displayName + ".brush.asset", typeof(OrientedBrush)) as OrientedBrush;
                if (newMasterBrush != null)
                {
                    RtsUpgradedBrushMap.BrushMappings.SetMapping(record.brush, newMasterBrush);
                    return;
                }

                // If new version was not found then just proceed to upgrade
                // existing version.
            }
            // Is this one of the original demo brushes?
            else if (record.assetPath == "Assets/Rotorz Tile System/_Demos/TilePrefabs/Diamond.prefab" ||
                     record.assetPath == "Assets/Rotorz Tile System/_Demos/TilePrefabs/Hat Guy.prefab" ||
                     record.assetPath == "Assets/Rotorz Tile System/_Demos/TilePrefabs/Steel Brick.prefab")
            {
                // This is a special case that can be switched to new version
                // if it was imported.
                OrientedBrush newDemoBrush = AssetDatabase.LoadAssetAtPath("Assets/Rotorz/Tile System/Demo/Hat Guy/TileBrushes/" + record.displayName + ".brush.asset", typeof(OrientedBrush)) as OrientedBrush;
                if (newDemoBrush != null)
                {
                    RtsUpgradedBrushMap.BrushMappings.SetMapping(record.brush, newDemoBrush);
                    return;
                }

                // If new version was not found then just proceed to upgrade
                // existing version.
            }
        }

        Transform oldBrushTransform = record.brush.transform;

        OrientedBrush newBrush = BrushUtility.CreateOrientedBrush(record.displayName);

        newBrush.RemoveOrientation(newBrush.DefaultOrientationMask);
        List <Object> variations = new List <Object>();

        RtsUpgradedBrushMap map = RtsUpgradedBrushMap.BrushMappings;

        // Copy orientations from old brush.
        for (int ti = 0; ti < oldBrushTransform.childCount; ++ti)
        {
            MonoBehaviour oldOrientation = oldBrushTransform.GetChild(ti).GetComponent(_tyTileBrushOrientation) as MonoBehaviour;
            if (oldOrientation == null)
            {
                continue;
            }

            Object[] oldVariations = (Object[])_fiTileBrushOrientation_variations.GetValue(oldOrientation);

            BrushOrientation newOrientation = newBrush.AddOrientation(OrientationUtility.MaskFromName(oldOrientation.name));

            variations.Clear();
            for (int i = 0; i < oldVariations.Length; ++i)
            {
                if (oldVariations[i] == null)
                {
                    continue;
                }

                Type       variationType  = oldVariations[i].GetType();
                GameObject variationGO    = oldVariations[i] as GameObject;
                Object     variationBrush = null;

                // If game object is nested, check if it is a tile brush prefab!
                if (variationGO != null)
                {
                    variationBrush = variationGO.GetComponent(_tyTileBrush);
                }
                // If variation is a tile brush then...
                else if (_tyTileBrush.IsAssignableFrom(variationType))
                {
                    variationBrush = oldVariations[i];
                }

                // Need to isolate nested brushes!
                if (variationBrush != null)
                {
                    // Note: This only works because oriented brushes are processed last,
                    //		 and it is not possible to nest oriented brushes.

                    // Use new version of brush!
                    Brush replacementBrush = map.Lookup(variationBrush);
                    if (replacementBrush != null)
                    {
                        variations.Add(replacementBrush);
                    }
                }
                else if (variationGO != null)
                {
                    variations.Add(variationGO);
                }
            }
            newOrientation.variations = variations.ToArray();
        }

        newBrush.DefaultOrientationMask = OrientationUtility.MaskFromName((string)_fiOrientedTileBrush_defaultOrientation.GetValue(record.brush));
        newBrush.FallbackMode           = (FallbackMode)_fiOrientedTileBrush_fallbackMode.GetValue(record.brush);

        if (_fiTileBrush_coalesce != null)
        {
            newBrush.Coalesce = (Coalesce)_fiTileBrush_coalesce.GetValue(record.brush);
        }
        if (_fiTileBrush_coalesceTileGroup != null)
        {
            newBrush.CoalesceBrushGroup = (int)_fiTileBrush_coalesceTileGroup.GetValue(record.brush);
        }

        if (_fiOrientedTileBrush_forceOverrideFlags != null)
        {
            newBrush.forceOverrideFlags = (bool)_fiOrientedTileBrush_forceOverrideFlags.GetValue(record.brush);
        }

        FinalizeStandaloneBrush(record, newBrush);
    }
Esempio n. 5
0
    /// <summary>
    /// Upgrades atlas brush (v1.x) into a tileset brush (v2.x).
    /// </summary>
    /// <remarks>
    /// <para>These are now called tileset brushes because they utilise a central
    /// tileset asset which makes it easier to manage such brushes.</para>
    /// </remarks>
    /// <param name="record">Record for existing v1.x brush.</param>
    private void UpgradeAtlasBrush(RtsBrushAssetRecordWrapper record)
    {
        MonoBehaviour oldBrush     = record.brush;
        Transform     oldTransform = oldBrush.transform;

        // Cannot upgrade atlas tile brush if tileset was not generated
        Tileset tileset = GenerateTilesetFromAtlasBrush(oldBrush);

        if (tileset == null)
        {
            Debug.LogError(string.Format("Could not generate tileset for atlas brush '{0}'.", oldBrush.name));
            return;
        }

        Texture2D atlasTexture   = (Texture2D)_fiAtlasTileBrush_atlasTexture.GetValue(oldBrush);
        int       atlasTileWidth = (int)_fiAtlasTileBrush_atlasTileWidth.GetValue(oldBrush);
        int       atlasRow       = (int)_fiAtlasTileBrush_atlasRow.GetValue(oldBrush);
        int       atlasColumn    = (int)_fiAtlasTileBrush_atlasColumn.GetValue(oldBrush);

        // Create the new tileset brush.
        int          atlasColumns = atlasTexture.width / atlasTileWidth;
        int          tileIndex    = atlasRow * atlasColumns + atlasColumn;
        TilesetBrush newBrush     = BrushUtility.CreateTilesetBrush(record.displayName, tileset, tileIndex, InheritYesNo.Inherit);

        // Was unit collider added to original atlas brush?
        BoxCollider automaticCollider = oldBrush.collider as BoxCollider;

        if (automaticCollider != null && automaticCollider.size == Vector3.one && automaticCollider.center == Vector3.zero)
        {
            newBrush.addCollider = true;
        }

        int componentCount = oldTransform.GetComponents <Component>().Length;

        if (newBrush.addCollider)
        {
            --componentCount;
        }

        // Should prefab be generated and attached?
        //   - Attach prefab if it contains child game objects.
        //   - Attach prefab if collider is non-standard.
        //   - Contains extra components (1=transform, 2=brush, 3=filter, 4=renderer).
        bool attachPrefab = (oldTransform.childCount > 0) ||
                            (!newBrush.addCollider && oldBrush.collider != null) ||
                            (componentCount != 4)
        ;

        if (attachPrefab)
        {
            GameObject attachment = PrefabUtility.InstantiatePrefab(oldBrush.gameObject) as GameObject;

            // Destroy the previous brush component.
            Object.DestroyImmediate(attachment.GetComponent(_tyTileBrush));
            // Destroy collider as it's not needed.
            if (newBrush.addCollider)
            {
                Object.DestroyImmediate(attachment.collider);
            }

            // Remove mesh filter and renderer components.
            Object.DestroyImmediate(attachment.renderer);
            Object.DestroyImmediate(attachment.GetComponent <MeshFilter>());

            string assetPath = GetUniqueMigratedPath(oldBrush.name + ".prefab");
            newBrush.attachPrefab = PrefabUtility.CreatePrefab(assetPath, attachment);

            Object.DestroyImmediate(attachment);
        }

        CopyCommonBrushProperties(newBrush, record.brush);
        RtsUpgradedBrushMap.BrushMappings.SetMapping(record.brush, newBrush);

        if (newBrush.visibility == BrushVisibility.Shown)
        {
            newBrush.visibility = BrushVisibility.Favourite;
        }
        else
        {
            newBrush.visibility = BrushVisibility.Shown;
        }
    }
Esempio n. 6
0
    /// <summary>
    /// Finalize a newly created standalone brush asset.
    /// </summary>
    /// <remarks>
    /// <para>Also moves asset into "Master" folder if needed.</para>
    /// </remarks>
    /// <param name="record">Record for v1.x brush.</param>
    /// <param name="newBrush">The new brush.</param>
    private void FinalizeStandaloneBrush(RtsBrushAssetRecordWrapper record, Brush newBrush)
    {
        CopyCommonBrushProperties(newBrush, record.brush);
        RtsUpgradedBrushMap.BrushMappings.SetMapping(record.brush, newBrush);

        // Was previous brush a master?
        if (record.master)
        {
            string newAssetPath    = AssetDatabase.GetAssetPath(newBrush);
            string masterAssetPath = newAssetPath.Replace(BrushUtility.GetBrushAssetPath(), BrushUtility.GetMasterBrushAssetPath());
            AssetDatabase.MoveAsset(newAssetPath, masterAssetPath);
        }

        EditorUtility.SetDirty(newBrush);
    }
Esempio n. 7
0
    /// <summary>
    /// Generate tileset using an atlas brush.
    /// </summary>
    /// <remarks>
    /// <para>One tileset asset is generated for each unique atlas material that
    /// exists amongst all defined atlas brushes.</para>
    /// </remarks>
    /// <param name="brush">Existing atlas brush.</param>
    /// <returns>
    /// The tileset.
    /// </returns>
    private Tileset GenerateTilesetFromAtlasBrush(MonoBehaviour brush)
    {
        MeshRenderer renderer = brush.GetComponent <MeshRenderer>();

        if (renderer == null)
        {
            return(null);
        }

        Material mat = renderer.sharedMaterial;

        if (mat == null)
        {
            return(null);
        }

        Texture2D atlasTexture = _fiAtlasTileBrush_atlasTexture.GetValue(brush) as Texture2D;

        if (atlasTexture == null)
        {
            return(null);
        }

        RtsUpgradedBrushMap map = RtsUpgradedBrushMap.BrushMappings;

        Tileset tileset = map.Lookup(mat);

        if (tileset != null)
        {
            return(tileset);
        }

        // Create folder for atlas assets
        string atlasFolder = AssetDatabase.GenerateUniqueAssetPath(BrushUtility.GetBrushAssetPath() + atlasTexture.name);

        Directory.CreateDirectory(Directory.GetCurrentDirectory() + "/" + atlasFolder);

        // Create material for tileset
        Material material = Object.Instantiate(mat) as Material;

        material.mainTexture = atlasTexture;

        AssetDatabase.CreateAsset(material, atlasFolder + "/atlas.mat");
        AssetDatabase.ImportAsset(atlasFolder + "/atlas.mat");

        int atlasTileWidth  = (int)_fiAtlasTileBrush_atlasTileWidth.GetValue(brush);
        int atlasTileHeight = (int)_fiAtlasTileBrush_atlasTileHeight.GetValue(brush);

        // Calculate metrics for tileset
        TilesetMetrics metrics = new TilesetMetrics(atlasTexture, atlasTileWidth, atlasTileHeight, 0, 0.5f);

        // Create new tileset asset.
        tileset = ScriptableObject.CreateInstance <Tileset>();
        tileset.Initialize(material, atlasTexture, metrics);
        tileset.procedural = useProceduralTilesets;

        // Save tileset asset.
        string assetPath = atlasFolder + "/" + atlasTexture.name + ".set.asset";

        AssetDatabase.CreateAsset(tileset, assetPath);
        AssetDatabase.ImportAsset(assetPath);

        map.SetMapping(mat, tileset);
        return(tileset);
    }
        protected virtual void OnApplyChanges()
        {
            // Do not proceed if no atlas texture was selected.
            if (this.inputAtlasTexture == null)
            {
                EditorUtility.DisplayDialog(
                    TileLang.ParticularText("Error", "Atlas texture was not specified"),
                    TileLang.Text("Please select an atlas texture before proceeding."),
                    TileLang.ParticularText("Action", "Close")
                    );
                return;
            }

            // Warn user if modified atlas will contain impossible brushes.
            if (BrushUtility.WouldHaveImpossibleTilesetBrushes(this.tileset, this.inputTileWidth, this.inputTileHeight, this.inputBorderSize))
            {
                if (!EditorUtility.DisplayDialog(
                        TileLang.Text("Warning, brushes will be deleted"),
                        TileLang.Text("Modified atlas contains fewer tiles than previously. Previously created brushes that are out of range will be deleted.\n\nWould you like to proceed?"),
                        TileLang.ParticularText("Action", "Yes"),
                        TileLang.ParticularText("Action", "No")
                        ))
                {
                    return;
                }
            }

            bool refreshNonProceduralMeshes = !this.inputProcedural && this.tileset.procedural;

            string tilesetBasePath = this.tilesetRecord.AssetPath.Substring(0, this.tilesetRecord.AssetPath.LastIndexOf('/') + 1);

            // Update and save material asset.
            if (this.tileset.AtlasMaterial == null)
            {
                this.tileset.AtlasMaterial             = new Material(Shader.Find("Rotorz/Tileset/Opaque Unlit"));
                this.tileset.AtlasMaterial.mainTexture = this.inputAtlasTexture;

                string assetPath = AssetDatabase.GenerateUniqueAssetPath(tilesetBasePath + "atlas.mat");
                AssetDatabase.CreateAsset(this.tileset.AtlasMaterial, assetPath);
                AssetDatabase.ImportAsset(assetPath);
            }
            else
            {
                this.tileset.AtlasMaterial.mainTexture = this.inputAtlasTexture;
                EditorUtility.SetDirty(this.tileset.AtlasMaterial);
            }

            this.tileset.AtlasTexture = this.inputAtlasTexture;

            // Calculate metrics for tileset.
            this.RecalculateMetrics();

            // Update properties of tileset.
            this.tileset.procedural = this.inputProcedural;
            this.tileset.SetMetricsFrom(this.inputTilesetMetrics);

            EditorUtility.SetDirty(this.tileset);

            // Delete "impossible" tile brushes in tileset.
            // For example, an extra brush for a tile that no longer exists.
            BrushUtility.DeleteImpossibleTilesetBrushes(this.tileset);

            // Ensure that non-procedural meshes are pre-generated if missing.
            if (refreshNonProceduralMeshes)
            {
                BrushUtility.RefreshNonProceduralMeshes(this.tileset);
            }

            ToolUtility.RepaintBrushPalette();

            // Update procedural meshes for tile systems in scene if necessary.
            // Note: Only update if procedural mode of tileset was not modified.
            if (this.inputProcedural && this.tileset.procedural)
            {
                foreach (TileSystem system in Object.FindObjectsOfType(typeof(TileSystem)))
                {
                    system.UpdateProceduralTiles(true);
                }
            }
        }
Esempio n. 9
0
    public override void Pick(GridLayout grid, GameObject layer, BoundsInt position, Vector3Int pivot)
    {
        GridInformation info = BrushUtility.GetRootGridInformation(true);

        m_Difficulty = info.GetPositionProperty(position.min, k_SwarmDifficultyProperty, 0f);
    }
Esempio n. 10
0
    public override void Erase(GridLayout grid, GameObject layer, Vector3Int position)
    {
        GridInformation info = BrushUtility.GetRootGridInformation(true);

        info.ErasePositionProperty(position, k_SwarmDifficultyProperty);
    }
Esempio n. 11
0
    public override void Pick(GridLayout grid, GameObject layer, BoundsInt position, Vector3Int pivot)
    {
        GridInformation info = BrushUtility.GetRootGridInformation(true);

        m_Color = info.GetPositionProperty(position.min, k_TintColorPropertyName, FindObjectOfType <TintTextureGenerator>().defaultColor);
    }
Esempio n. 12
0
 public override bool StartUp(Vector3Int location, ITilemap tilemap, GameObject go)
 {
     _gridInformation = BrushUtility.GetRootGridInformation();
     return(base.StartUp(location, tilemap, go));
 }