Esempio n. 1
0
 void DrawRegionOutline(EBWorldPainterData.Region region, Color outlineColor)
 {
     for (var i = 0; i < region.points.Count; ++i)
     {
         EBWorldPainterData.Point p0 = region.points[i];
         EBWorldPainterData.Point p1 = region.points[(i + 1) % region.points.Count];
         DrawLine(p0, p1, outlineColor);
     }
 }
Esempio n. 2
0
 void SwitchEditMode(EditMode em)
 {
     editMode          = em;
     lastClickedPoint  = null;
     lastClickedRegion = null;
     if (em == EditMode.BoundingBoxes)
     {
         var renderers = (MeshRenderer[])FindObjectsOfType(typeof(MeshRenderer));
         worldPainterData.SetRegionBounds(renderers);
     }
     Repaint();
 }
Esempio n. 3
0
 void DrawRegionBoundingBox(EBWorldPainterData.Region region, Color outlineColor)
 {
     for (var i = 0; i < region.points.Count; ++i)
     {
         EBWorldPainterData.Point p0 = new EBWorldPainterData.Point(region.bounds.min.x, region.bounds.min.z);
         EBWorldPainterData.Point p1 = new EBWorldPainterData.Point(region.bounds.max.x, region.bounds.min.z);
         EBWorldPainterData.Point p2 = new EBWorldPainterData.Point(region.bounds.max.x, region.bounds.max.z);
         EBWorldPainterData.Point p3 = new EBWorldPainterData.Point(region.bounds.min.x, region.bounds.max.z);
         DrawLine(p0, p1, outlineColor);
         DrawLine(p1, p2, outlineColor);
         DrawLine(p2, p3, outlineColor);
         DrawLine(p3, p0, outlineColor);
     }
 }
Esempio n. 4
0
    void DrawDataLayer(EBWorldPainterData.Region region)
    {
        var     point  = new Vector3(region.Center().location.x, 0.0f, region.Center().location.y);
        Vector2 center = cam.WorldToViewportPoint(point) * textureSize;
        Rect    rect   = new Rect(center.x - 25.0f, textureSize - center.y - 5.0f, 50.0f, 10.0f);

        switch (dataLayer)
        {
        case EBWorldPainterData.eDATA_LAYER.LightmapSize:
            region.dataLayers[(int)dataLayer].value = (int)(EBWorldPainterData.eLIGHTMAP_SIZE)EditorGUI.EnumPopup(rect, (EBWorldPainterData.eLIGHTMAP_SIZE)(region.dataLayers[(int)dataLayer].value));
            break;

        case EBWorldPainterData.eDATA_LAYER.RenderSetting:
            region.dataLayers[(int)dataLayer].value = (int)(EBWorldPainterData.eLIGHTMAP_SIZE)EditorGUI.EnumPopup(rect, (EBWorldPainterData.eRENDER_SETTING)(region.dataLayers[(int)dataLayer].value));
            break;
        }
    }
Esempio n. 5
0
    private void MergeLightmaps(Partition partition, EBWorldPainterData.Region region, Dictionary <int, Texture2D> lightmaps)
    {
        int maxLightMapIndex = 0;

        foreach (int key in lightmaps.Keys)
        {
            maxLightMapIndex = Mathf.Max(maxLightMapIndex, key);
        }

        List <Rect>[] lightmapRects = new List <Rect> [maxLightMapIndex + 1];
        for (int i = 0; i <= maxLightMapIndex; ++i)
        {
            lightmapRects[i] = new List <Rect>();
        }

        //crop each meshes lightmaps out of the partition
        foreach (var instance in partition.instances)
        {
            var renderer = instance.renderer;

            if (!RendererHasLightmap(renderer))
            {
                continue;
            }

            if (!lightmaps.ContainsKey(renderer.lightmapIndex))
            {
                Debug.LogWarning("Some lightmaps weren't loaded that geometry references..." + renderer.lightmapIndex);
                continue;
            }

            var filter = renderer.GetComponent <MeshFilter> ();

            var lightmapUVs = filter.sharedMesh.uv2;

            int subMeshCount = filter.sharedMesh.subMeshCount;

            instance.lightmapInfo = new LightMapInfo[subMeshCount];

            for (int i = 0; i < subMeshCount; ++i)
            {
                Vector2 uvMin = new Vector2(float.MaxValue, float.MaxValue);
                Vector2 uvMax = new Vector2(float.MinValue, float.MinValue);

                var indices = filter.sharedMesh.GetIndices(i);
                foreach (var index in indices)
                {
                    Vector2 uv = lightmapUVs [index];
                    uv.x  = uv.x * renderer.lightmapScaleOffset.x + renderer.lightmapScaleOffset.z;
                    uv.y  = uv.y * renderer.lightmapScaleOffset.y + renderer.lightmapScaleOffset.w;
                    uvMin = Vector2.Min(uvMin, uv);
                    uvMax = Vector2.Max(uvMax, uv);
                }

                var rect = new Rect(uvMin.x, uvMin.y, uvMax.x - uvMin.x, uvMax.y - uvMin.y);
                lightmapRects[renderer.lightmapIndex].Add(rect);

                instance.lightmapInfo[i]       = new LightMapInfo();
                instance.lightmapInfo[i].index = lightmapRects[renderer.lightmapIndex].IndexOf(rect);
            }
        }

        List <KeyValuePair <int, Rect> > allRects = new List <KeyValuePair <int, Rect> > ();

        for (int lm = 0; lm < lightmaps.Count; ++lm)
        {
            int[]       remap         = new int[lightmapRects [lm].Count];
            List <Rect> remappedRects = new List <Rect> ();

            for (int i = 0; i < lightmapRects[lm].Count; ++i)
            {
                var  curOrigRect = lightmapRects [lm] [i];
                bool remapped    = false;
                for (int j = 0; j < remappedRects.Count; ++j)
                {
                    var curRemappedRect = remappedRects [j];
                    if (Intersect(curOrigRect, curRemappedRect))
                    {
                        float l = Mathf.Min(curOrigRect.xMin, curRemappedRect.xMin);
                        float r = Mathf.Max(curOrigRect.xMax, curRemappedRect.xMax);
                        float t = Mathf.Min(curOrigRect.yMin, curRemappedRect.yMin);
                        float b = Mathf.Max(curOrigRect.yMax, curRemappedRect.yMax);
                        Rect  encapsulatedRect = new Rect(l, t, r - l, b - t);

                        remappedRects[j] = encapsulatedRect;
                        remap[i]         = j;
                        remapped         = true;
                        break;
                    }
                }

                if (!remapped)
                {
                    remappedRects.Add(curOrigRect);
                    remap[i] = remappedRects.IndexOf(curOrigRect);
                }
            }

            for (int i = 0; i < remappedRects.Count; ++i)
            {
                Rect rect = remappedRects [i];

                Texture2D lightmap       = lightmaps [lm];
                float     lightmapWidth  = (float)lightmap.width;
                float     lightmapHeight = (float)lightmap.height;

                //we need to bring this rect into a whole integer, as we crop on pixel boundaries;
                float left   = Mathf.Clamp01(Mathf.Floor(rect.x * lightmapWidth) / lightmapWidth);
                float top    = Mathf.Clamp01(Mathf.Floor(rect.y * lightmapHeight) / lightmapHeight);
                float width  = Mathf.Clamp01(Mathf.Clamp01(Mathf.Ceil((rect.x + rect.width) * lightmapWidth) / lightmapWidth) - left);
                float height = Mathf.Clamp01(Mathf.Clamp01(Mathf.Ceil((rect.y + rect.height) * lightmapHeight) / lightmapHeight) - top);

                remappedRects[i] = new Rect(left, top, width, height);

                allRects.Add(new KeyValuePair <int, Rect>(lm, remappedRects[i]));
            }

            foreach (var instance in partition.instances)
            {
                var renderer = instance.renderer;

                if (!RendererIsMergeable(renderer) || !RendererHasLightmap(renderer) || (renderer.lightmapIndex != lm))
                {
                    continue;
                }

                if (!lightmaps.ContainsKey(renderer.lightmapIndex))
                {
                    Debug.LogError("Lightmap " + renderer.lightmapIndex + " wasn't loaded but some geometry references it - are the lightmaps in the right place?");
                    continue;
                }

                var filter       = renderer.GetComponent <MeshFilter> ();
                int subMeshCount = filter.sharedMesh.subMeshCount;

                for (int i = 0; i < subMeshCount; ++i)
                {
                    var rect = remappedRects [remap [instance.lightmapInfo [i].index]];
                    instance.lightmapInfo[i].index       = allRects.IndexOf(new KeyValuePair <int, Rect>(renderer.lightmapIndex, rect));
                    instance.lightmapInfo[i].localScale  = new Vector2(1.0f / rect.width, 1.0f / rect.height);
                    instance.lightmapInfo[i].localOffset = new Vector2(-rect.x / rect.width, -rect.y / rect.height);
                }
            }
        }

        List <Texture2D> croppedLightmaps = new List <Texture2D> ();

        foreach (var kv in allRects)
        {
            int       lm      = kv.Key;
            Rect      rect    = kv.Value;
            Texture2D cropped = CropTexture(lightmaps [lm], rect);
            croppedLightmaps.Add(cropped);
        }

        //pack all the cropped lightmaps
        int lightmapSize = 1024;

        if (region.dataLayers != null)
        {
            int regionLightmapSize = region.dataLayers [(int)EBWorldPainterData.eDATA_LAYER.LightmapSize].value;
            if (regionLightmapSize != 0)
            {
                lightmapSize = regionLightmapSize;
            }
        }
        if (croppedLightmaps.Count == 0)
        {
            lightmapSize = 1;
        }
        Texture2D packedTexture = new Texture2D(lightmapSize, lightmapSize, TextureFormat.RGB24, true);

        partition.lightmapRects = packedTexture.PackTextures(croppedLightmaps.ToArray(), 0, lightmapSize, false);
        packedTexture.Apply(true, false);
        if ((BuildSettings.Target != BuildTarget.Android) && (BuildSettings.Target != BuildTarget.iOS))
        {
            //multiply by 4 * alpha
            for (int y = 0; y < packedTexture.height; ++y)
            {
                for (int x = 0; x < packedTexture.width; ++x)
                {
                    var color = packedTexture.GetPixel(x, y);
                    color.r *= 4.0f * color.a;
                    color.g *= 4.0f * color.a;
                    color.b *= 4.0f * color.a;
                    color.a  = 1.0f;
                    packedTexture.SetPixel(x, y, color);
                }
            }
        }
        else
        {
            for (int y = 0; y < packedTexture.height; ++y)
            {
                for (int x = 0; x < packedTexture.width; ++x)
                {
                    var color = packedTexture.GetPixel(x, y);
                    color.a = 1.0f;
                    packedTexture.SetPixel(x, y, color);
                }
            }
        }
        packedTexture.Apply(true, false);

        string filename = GetMergeOutputPath(partition.name);

        if (File.Exists(filename))
        {
            //it may be checked into perforce, remove 'read-only' flag
            File.SetAttributes(filename, FileAttributes.Normal);
        }
        File.WriteAllBytes(filename, packedTexture.EncodeToPNG());
        AssetDatabase.Refresh();
        partition.lightmap = (Texture2D)AssetDatabase.LoadMainAssetAtPath(filename);
    }
Esempio n. 6
0
    void OnGUI()
    {
        if (!inited)
        {
            return;
        }

        const int offset      = 20;
        Rect      textureRect = Rect.MinMaxRect(offset, offset, textureSize + offset, textureSize + offset);
        Rect      texturSize  = Rect.MinMaxRect(0, 0, textureSize, textureSize);

        SetMode();

        //Deal with the mouse
        if ((Event.current != null) && Event.current.isMouse && textureRect.Contains(Event.current.mousePosition))
        {
            Vector3 worldMousePos3 = cam.ViewportToWorldPoint(new Vector3(((float)Event.current.mousePosition.x - textureRect.x) / (float)textureSize, 1.0f - ((float)Event.current.mousePosition.y - textureRect.y) / (float)textureSize, 0.0f));
            EBWorldPainterData.Point worldMousePos = new EBWorldPainterData.Point(worldMousePos3.x, worldMousePos3.z);

            UpdateClosestPoint(worldPainterData.ClosestPoint(worldMousePos));
            UpdateClosestPoints(worldPainterData.ClosestLine(worldMousePos));
            UpdateCurrentRegions(worldPainterData.RegionsPointIsInside(worldMousePos));

            switch (mode)
            {
            case (Mode.None):
                break;

            case (Mode.AddPoints):
            {
                Vector2 point0       = closestPoints[0].location;
                Vector2 point1       = closestPoints[1].location;
                float   distToPoint0 = Vector2.Distance(point0, worldMousePos.location);
                float   distToPoint1 = Vector2.Distance(point1, worldMousePos.location);
                float   t            = distToPoint0 / (distToPoint0 + distToPoint1);
                pointToAdd = new EBWorldPainterData.Point(Vector2.Lerp(point0, point1, t));

                if (Event.current.type == EventType.MouseDown)
                {
                    var result = worldPainterData.InsertPoint(pointToAdd, closestPoints[0], closestPoints[1]);
                    if (!result)
                    {
                    }
                    Repaint();
                }
                break;
            }

            case (Mode.RemovePoints):
            {
                if (Event.current.type == EventType.MouseDown)
                {
                    var result = worldPainterData.RemovePoint(closestPoint);
                    if (!result)
                    {
                    }
                    Repaint();
                }
                break;
            }

            case (Mode.MovePoints):
            {
                if (Event.current.type == EventType.MouseDown)
                {
                    lastClickedPoint = closestPoint;
                    Repaint();
                }
                else if (Event.current.type == EventType.MouseDrag && lastClickedPoint != null)
                {
                    lastClickedPoint.location = worldMousePos.location;
                    Repaint();
                }
                break;
            }

            case (Mode.SplitRegions):
            {
                if (Event.current.type == EventType.MouseDown)
                {
                    if (lastClickedPoint == null)
                    {
                        lastClickedPoint = closestPoint;
                        Repaint();
                    }
                    else
                    {
                        EBWorldPainterData.Point nextClickedPoint = worldPainterData.ClosestPoint(worldMousePos);
                        if (nextClickedPoint != lastClickedPoint)
                        {
                            EBWorldPainterData.Region[] regions = worldPainterData.RegionsContainingPoints(lastClickedPoint, nextClickedPoint);
                            if (regions.Length == 1)
                            {
                                //don't want to split if the points are in more than one region, as they must be on a boundary of some sort, so splitting wouldn't make sense
                                //TODO: don't split things that are sequential
                                worldPainterData.SplitRegionAcrossPoints(regions[0], lastClickedPoint, nextClickedPoint);
                            }
                        }

                        lastClickedPoint = null;
                        Repaint();
                    }
                }
                break;
            }

            case (Mode.CombineRegions):
            {
                if (Event.current.type == EventType.MouseDown)
                {
                    worldPainterData.RemoveLine(closestPoints[0], closestPoints[1]);
                    UpdateCurrentRegions(worldPainterData.RegionsPointIsInside(worldMousePos));
                    Repaint();
                }
                break;
            }

            case (Mode.PickVisibleBase):
            {
                if (Event.current.type == EventType.MouseDown)
                {
                    lastClickedRegion = (currentRegions.Length > 0) ? currentRegions[0] : null;
                    Repaint();
                }
                break;
            }

            case (Mode.PaintVisible):
            {
                if ((lastClickedRegion != null) && (currentRegions.Length > 0) && (Event.current.type == EventType.MouseDown))
                {
                    lastClickedRegion.ToggleSeesRegion(currentRegions[0]);
                    Repaint();
                }
                break;
            }
            }
        }

        GUILayout.BeginHorizontal();
        GUILayout.Label("Zoom", GUILayout.Width(100));
        orthographicSize = GUILayout.HorizontalSlider(orthographicSize, 100.0f, 4000.0f);
        GUILayout.EndHorizontal();

        GUI.skin = guiskin;

        GUILayout.BeginHorizontal();
        float camPosZ = GUILayout.VerticalSlider(cam.transform.position.z, worldPainterData.WorldBounds().max.z, worldPainterData.WorldBounds().min.z);

        GUI.BeginGroup(textureRect);
        GUI.Box(texturSize, rt);
        GUI.EndGroup();

        GUI.BeginGroup(textureRect);

        switch (editMode)
        {
        case EditMode.Tesselate:
            //Draw all the points
            for (int i = 0; i < worldPainterData.points.Count; ++i)
            {
                EBWorldPainterData.Point point = worldPainterData.points[i];

                TextureFills tex = TextureFills.Gray;
                switch (mode)
                {
                case (Mode.AddPoints):
                    if (point == closestPoint)
                    {
                        tex = TextureFills.Blue;
                    }
                    break;

                case (Mode.RemovePoints):
                    if (point == closestPoint)
                    {
                        tex = TextureFills.Red;
                    }
                    break;

                case (Mode.MovePoints):
                    if (point == closestPoint)
                    {
                        tex = TextureFills.Green;
                    }
                    break;

                case (Mode.SplitRegions):
                    if (point == closestPoint)
                    {
                        tex = TextureFills.Green;
                    }
                    if (point == lastClickedPoint)
                    {
                        tex = TextureFills.Blue;
                    }
                    break;
                }
                DrawPoint(point, tex);
            }

            //Draw the line we may add if we are splitting regions
            if (mode == Mode.AddPoints)
            {
                DrawPoint(pointToAdd, TextureFills.Blue);
            }

            //Draw the line we may add if we are splitting regions
            if (mode == Mode.SplitRegions && lastClickedPoint != null)
            {
                DrawLine(lastClickedPoint, closestPoint, Color.blue);
            }

            //Draw all the region outlines
            foreach (EBWorldPainterData.Region region in worldPainterData.regions)
            {
                DrawRegionOutline(region, Color.white);
            }

            //Draw the line we may remove if we are combining regions
            if (mode == Mode.CombineRegions)
            {
                DrawLine(closestPoints[0], closestPoints[1], Color.red);
            }

            break;

        case EditMode.Visibility:

            //Draw all the points
            for (int i = 0; i < worldPainterData.points.Count; ++i)
            {
                DrawPoint(worldPainterData.points[i], TextureFills.Gray);
            }

            //Draw all the region outlines
            foreach (EBWorldPainterData.Region region in worldPainterData.regions)
            {
                DrawRegionOutline(region, Color.red);
            }

            //outline all the regions our current region sees, and our current region
            if (lastClickedRegion != null)
            {
                foreach (EBWorldPainterData.Region region in worldPainterData.regions)
                {
                    if (lastClickedRegion.SeesRegion(region))
                    {
                        DrawRegionOutline(region, Color.green);
                    }
                }
                DrawRegionOutline(lastClickedRegion, new Color(0.5f, 0.5f, 1.0f));
            }

            break;

        case EditMode.Hover:

            //Draw all the region outlines
            foreach (EBWorldPainterData.Region region in worldPainterData.regions)
            {
                DrawRegionOutline(region, Color.white);
            }

            //outline the one we are hovering over
            if (currentRegions.Length > 0)
            {
                DrawRegionOutline(currentRegions[0], new Color(0.0f, 0.5f, 0.0f));
            }

            break;

        case EditMode.BoundingBoxes:

            //Draw all the region bounding boxes
            foreach (EBWorldPainterData.Region region in worldPainterData.regions)
            {
                DrawRegionBoundingBox(region, Color.white);
            }

            break;

        case EditMode.DataLayer:

            //Draw all the region outlines
            foreach (EBWorldPainterData.Region region in worldPainterData.regions)
            {
                DrawRegionOutline(region, Color.white);
                DrawDataLayer(region);
            }

            break;
        }

        GUI.EndGroup();

        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal();
        float camPosX = GUILayout.HorizontalSlider(cam.transform.position.x, worldPainterData.WorldBounds().min.x, worldPainterData.WorldBounds().max.x);

        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal();
        foreach (EditMode m in System.Enum.GetValues(typeof(EditMode)))
        {
            if (GUILayout.Button(m.ToString()))
            {
                SwitchEditMode(m);
            }
        }
        dataLayer = (EBWorldPainterData.eDATA_LAYER)EditorGUILayout.EnumPopup("Data Layer: ", dataLayer);
        GUILayout.EndHorizontal();

        Render(camPosX, camPosZ, orthographicSize);

        GUI.skin = null;
    }