Beispiel #1
0
    ///////////////////////////////////////////////////////////////////////////////
    // Overridable functions
    ///////////////////////////////////////////////////////////////////////////////

    // TODO: check border change if sliced

    // ------------------------------------------------------------------
    // Desc:
    // ------------------------------------------------------------------

    internal override exUpdateFlags UpdateBuffers(exList <Vector3> _vertices, exList <Vector2> _uvs, exList <Color32> _colors32, exList <int> _indices)
    {
        exDebug.Assert(textureInfo_ != null, "textureInfo_ == null");

        switch (spriteType_)
        {
        case exSpriteType.Simple:
            SpriteBuilder.SimpleUpdateBuffers(this, textureInfo_, useTextureOffset_, Space.Self, _vertices, _uvs, _indices, 0, 0);
            break;

        case exSpriteType.Sliced:
            SpriteBuilder.SlicedUpdateBuffers(this, textureInfo_, useTextureOffset_, Space.Self, _vertices, _uvs, _indices, 0, 0);
            break;

        case exSpriteType.Tiled:
            SpriteBuilder.TiledUpdateBuffers(this, textureInfo_, useTextureOffset_, tiledSpacing_, Space.Self, _vertices, _uvs, _indices, 0, 0);
            break;

        case exSpriteType.Diced:
            SpriteBuilder.DicedUpdateBuffers(this, textureInfo_, useTextureOffset_, Space.Self, _vertices, _uvs, _indices, 0, 0);
            break;
        }
        if ((updateFlags & exUpdateFlags.Color) != 0 && _colors32 != null)
        {
            Color32 color32 = new Color(color_.r, color_.g, color_.b, color_.a);
            for (int i = 0; i < vertexCount_; ++i)
            {
                _colors32.buffer [i] = color32;
            }
        }
        exUpdateFlags applyedFlags = updateFlags;

        updateFlags = exUpdateFlags.None;
        return(applyedFlags);
    }
Beispiel #2
0
    // ------------------------------------------------------------------
    /// Get sprite's geometry data
    // ------------------------------------------------------------------

    public void GetBuffers(exList <Vector3> _vertices, exList <Vector2> _uvs, exList <Color32> _colors, exList <int> _indices = null)
    {
        _vertices.Clear();
        _uvs.Clear();
        if (_indices != null)
        {
            _indices.Clear();
        }
        if (visible)
        {
            UpdateTransform();
            exUpdateFlags originalFlags             = updateFlags;
            int           originalVertexBufferIndex = vertexBufferIndex;
            int           originalIndexBufferIndex  = indexBufferIndex;

            FillBuffers(_vertices, _uvs, _colors);

            if (_indices != null)
            {
                _indices.AddRange(indexCount);
            }
            indexBufferIndex = 0;
            updateFlags     |= exUpdateFlags.Index;
            UpdateBuffers(_vertices, _uvs, _colors, _indices);

            vertexBufferIndex = originalVertexBufferIndex;
            indexBufferIndex  = originalIndexBufferIndex;
            updateFlags       = originalFlags;
        }
    }
Beispiel #3
0
    // ------------------------------------------------------------------
    /// Apply all buffer changes
    // ------------------------------------------------------------------

    public void Apply(exUpdateFlags _additionalUpdateFlags = exUpdateFlags.None)
    {
        updateFlags |= _additionalUpdateFlags;
        Mesh mesh;

        if (isDynamic && updateFlags != exUpdateFlags.None)
        {
            mesh = SwapMeshBuffer();
        }
        else
        {
            mesh = GetMeshBuffer();
        }

        FlushBuffers(mesh, updateFlags, vertices, indices, uvs, colors32);
#if EX_DEBUG
        if (mesh.uv.Length != mesh.vertices.Length)
        {
            Debug.LogError("Shader wants texture coordinates... uv.Length != vertex.Length");
            OutputDebugInfo(true);
        }
#endif

        if ((updateFlags & exUpdateFlags.Vertex) != 0)
        {
            // 当fast hide sprite时,判断是否可以隐藏整个mesh,减少draw call
            bool visible = false;
            if (spriteList.Count > 10)
            {
                visible = true; // 如果有大量sprite,不遍历整个列表,强制可见
            }
            else
            {
                for (int i = 0, count = spriteList.Count; i < count; ++i)
                {
                    if (spriteList[i].visible)
                    {
                        visible = true;
                        break;
                    }
                }
            }
            if (gameObject.activeSelf != visible)
            {
                gameObject.SetActive(visible);
            }
        }
        else if ((updateFlags & exUpdateFlags.Index) != 0)
        {
            // 如果index改变了则也有可能改变显隐,这种情况不多只是基本简单检查下索引数量就够
            bool visible = (indices.Count > 0);
            if (gameObject.activeSelf != visible)
            {
                gameObject.SetActive(visible);
            }
        }

        updateFlags = exUpdateFlags.None;
    }
Beispiel #4
0
    // ------------------------------------------------------------------
    /// Compact all reserved buffers
    // ------------------------------------------------------------------

    public void Compact()
    {
        // 其实mscorlib在实现TrimExcess时还是会预留10%的buffer
        spriteList.TrimExcess();
        vertices.TrimExcess();
        indices.TrimExcess();
        uvs.TrimExcess();
        colors32.TrimExcess();
        updateFlags |= (exUpdateFlags.Color | exUpdateFlags.UV | exUpdateFlags.Normal);   //need to flush to mesh if defined exLayer.LAZY_UPDATE_BUFFER_TAIL
    }
Beispiel #5
0
    // ------------------------------------------------------------------
    /// If we are using dynamic layer, the mesh is double buffered so that we can get the best performance on iOS devices.
    /// http://forum.unity3d.com/threads/118723-Huge-performance-loss-in-Mesh.CreateVBO-for-dynamic-meshes-IOS
    // ------------------------------------------------------------------

    private Mesh SwapMeshBuffer()
    {
        exDebug.Assert(isDynamic);
        if (enableDoubleBuffer)
        {
            isEvenMeshBuffer = !isEvenMeshBuffer;
            exUpdateFlags currentBufferUpdate = updateFlags;
            updateFlags    |= lastUpdateFlags;       // combine changes during two frame
            lastUpdateFlags = currentBufferUpdate;   // for next buffer
        }
        return(GetMeshBuffer());
    }
Beispiel #6
0
    // ------------------------------------------------------------------
    /// Actually apply all buffer changes to mesh.
    // ------------------------------------------------------------------

    public static void FlushBuffers(Mesh _mesh, exUpdateFlags _updateFlags, exList <Vector3> _vertices, exList <int> _indices, exList <Vector2> _uvs, exList <Color32> _colors32)
    {
        if ((_updateFlags & exUpdateFlags.VertexAndIndex) == exUpdateFlags.VertexAndIndex)
        {
            // if we need to update vertices, we should also clear triangles first
            _mesh.triangles = null;  // we dont use Mesh.Clear() since sometimes it goes wrong when the uv and color have not been updated
        }
        if ((_updateFlags & exUpdateFlags.Vertex) != 0 ||
            (_updateFlags & exUpdateFlags.Index) != 0)      // if we need to update triangles, we should also update vertices, or mesh will become invisible
        {
            _mesh.vertices = _vertices.FastToArray();
        }
        if ((_updateFlags & exUpdateFlags.UV) != 0)
        {
            _mesh.uv = _uvs.FastToArray();
        }
        if ((_updateFlags & exUpdateFlags.Color) != 0)
        {
            _mesh.colors32 = _colors32.FastToArray();
        }
        if ((_updateFlags & exUpdateFlags.Index) != 0)
        {
            _mesh.triangles = _indices.FastToArray();       // we do update triangles here
            //string bufv = "Vertex Buffer: ";
            //string vertices = "Mesh.vertices[" + _mesh.vertices.Length + "]: ";
            //foreach (var v in _mesh.vertices) {
            //    bufv += v;
            //    bufv += ", ";
            //}
            //Debug.Log(bufv);
            //var buf = _indices.FastToArray();
            //string triangles = "Mesh.indices[" + buf.Length + "]: ";
            //foreach (var index in buf) {
            //    triangles += index;
            //    triangles += ",";
            //}
            //Debug.Log(triangles);
        }
        if ((_updateFlags & exUpdateFlags.Index) != 0 || (_updateFlags & exUpdateFlags.Vertex) != 0)
        {
            _mesh.RecalculateBounds();  // Sometimes Unity will not automatically recalculate the bounding volume.
        }
        if ((_updateFlags & exUpdateFlags.Normal) != 0)
        {
            Vector3[] normals = new Vector3[_vertices.Count];
            for (int i = 0; i < normals.Length; ++i)
            {
                normals[i] = new Vector3(0, 0, -1);
            }
            _mesh.normals = normals;
        }
    }
    // ------------------------------------------------------------------
    /// Update mesh
    // ------------------------------------------------------------------

    protected new void LateUpdate()
    {
        if (updateFlags != exUpdateFlags.None && visible)
        {
            exUpdateFlags meshUpdateFlags = UpdateBuffers(vertices, uvs, colors32, indices);
            exMesh.FlushBuffers(mesh, meshUpdateFlags, vertices, indices, uvs, colors32);
            if ((meshUpdateFlags & exUpdateFlags.Index) != 0)
            {
                bool realVisible = (indices.Count > 0);
                if (cachedRenderer.enabled != realVisible)
                {
                    cachedRenderer.enabled = realVisible;
                }
            }
        }
    }
Beispiel #8
0
    ///////////////////////////////////////////////////////////////////////////////
    // Internal Functions
    ///////////////////////////////////////////////////////////////////////////////

    // ------------------------------------------------------------------
    // Desc:
    // ------------------------------------------------------------------

    public void Clear()
    {
        spriteList.Clear();
        sortedSpriteList.Clear();
        vertices.Clear();
        indices.Clear();
        uvs.Clear();
        colors32.Clear();
        if (mesh0 != null)
        {
            mesh0.Clear();
        }
        if (mesh1 != null)
        {
            mesh1.Clear();
        }
        updateFlags = exUpdateFlags.None;
    }
Beispiel #9
0
    // ------------------------------------------------------------------
    /// \param _dynamic if true, optimize mesh for frequent updates
    // ------------------------------------------------------------------

    public void SetDynamic(bool _dynamic)
    {
        //Debug.Log(string.Format("[SetDynamic|exMesh] _dynamic: {0} isDynamic: " + isDynamic, _dynamic));
        if (isDynamic == _dynamic)
        {
            return;
        }
        if (_dynamic)
        {
            // create all buffer
            exDebug.Assert(mesh0 != null);
            if (mesh0 == null)
            {
                mesh0 = CreateMesh();
            }
            mesh0.MarkDynamic();

            exDebug.Assert(mesh1 == null);
            if (mesh1 == null)
            {
                mesh1 = CreateMesh();
            }
            mesh1.MarkDynamic();

            lastUpdateFlags = exUpdateFlags.All;    // init new created mesh buffer
        }
        else
        {
            if (isEvenMeshBuffer != true)
            {
                isEvenMeshBuffer = true;
                updateFlags     |= lastUpdateFlags;
            }
            // destroy another buffer
            if (mesh1 != null)
            {
                mesh1.Destroy();
            }
            mesh1 = null;
        }
    }
Beispiel #10
0
 // ------------------------------------------------------------------
 /// If we are using dynamic layer, the mesh is double buffered so that we can get the best performance on iOS devices.
 /// http://forum.unity3d.com/threads/118723-Huge-performance-loss-in-Mesh.CreateVBO-for-dynamic-meshes-IOS
 // ------------------------------------------------------------------
 private Mesh SwapMeshBuffer()
 {
     exDebug.Assert(isDynamic);
     if (enableDoubleBuffer) {
         isEvenMeshBuffer = !isEvenMeshBuffer;
         exUpdateFlags currentBufferUpdate = updateFlags;
         updateFlags |= lastUpdateFlags;          // combine changes during two frame
         lastUpdateFlags = currentBufferUpdate;   // for next buffer
     }
     return GetMeshBuffer();
 }
Beispiel #11
0
    // ------------------------------------------------------------------
    /// \param _dynamic if true, optimize mesh for frequent updates
    // ------------------------------------------------------------------
    public void SetDynamic(bool _dynamic)
    {
        //Debug.Log(string.Format("[SetDynamic|exMesh] _dynamic: {0} isDynamic: " + isDynamic, _dynamic));
        if (isDynamic == _dynamic) {
            return;
        }
        if (_dynamic) {
            // create all buffer
            exDebug.Assert(mesh0 != null);
            if (mesh0 == null) {
                mesh0 = CreateMesh();
            }
            mesh0.MarkDynamic();

            exDebug.Assert(mesh1 == null);
            if (mesh1 == null) {
                mesh1 = CreateMesh();
            }
            mesh1.MarkDynamic();

            lastUpdateFlags = exUpdateFlags.All;    // init new created mesh buffer
        }
        else {
            if (isEvenMeshBuffer != true) {
                isEvenMeshBuffer = true;
                updateFlags |= lastUpdateFlags;
            }
            // destroy another buffer
            if (mesh1 != null) {
                mesh1.Destroy();
            }
            mesh1 = null;
        }
    }
Beispiel #12
0
 // ------------------------------------------------------------------
 /// Compact all reserved buffers
 // ------------------------------------------------------------------
 public void Compact()
 {
     // 其实mscorlib在实现TrimExcess时还是会预留10%的buffer
     spriteList.TrimExcess();
     vertices.TrimExcess();
     indices.TrimExcess();
     uvs.TrimExcess();
     colors32.TrimExcess();
     updateFlags |= (exUpdateFlags.Color | exUpdateFlags.UV | exUpdateFlags.Normal);   //need to flush to mesh if defined exLayer.LAZY_UPDATE_BUFFER_TAIL
 }
Beispiel #13
0
 ///////////////////////////////////////////////////////////////////////////////
 // Internal Functions
 ///////////////////////////////////////////////////////////////////////////////
 // ------------------------------------------------------------------
 // Desc:
 // ------------------------------------------------------------------
 public void Clear()
 {
     spriteList.Clear();
     sortedSpriteList.Clear();
     vertices.Clear();
     indices.Clear();
     uvs.Clear();
     colors32.Clear();
     if (mesh0 != null) {
         mesh0.Clear();
     }
     if (mesh1 != null) {
         mesh1.Clear();
     }
     updateFlags = exUpdateFlags.None;
 }
Beispiel #14
0
    // ------------------------------------------------------------------
    /// Apply all buffer changes
    // ------------------------------------------------------------------
    public void Apply(exUpdateFlags _additionalUpdateFlags = exUpdateFlags.None)
    {
        updateFlags |= _additionalUpdateFlags;
        Mesh mesh;
        if (isDynamic && updateFlags != exUpdateFlags.None) {
            mesh = SwapMeshBuffer();
        }
        else {
            mesh = GetMeshBuffer();
        }

        FlushBuffers (mesh, updateFlags, vertices, indices, uvs, colors32);
        #if EX_DEBUG
        if (mesh.uv.Length != mesh.vertices.Length) {
            Debug.LogError("Shader wants texture coordinates... uv.Length != vertex.Length");
            OutputDebugInfo(true);
        }
        #endif

        if ((updateFlags & exUpdateFlags.Vertex) != 0) {
            // 当fast hide sprite时,判断是否可以隐藏整个mesh,减少draw call
            bool visible = false;
            if (spriteList.Count > 10) {
                visible = true; // 如果有大量sprite,不遍历整个列表,强制可见
            }
            else {
                for (int i = 0, count = spriteList.Count; i < count; ++i) {
                    if (spriteList[i].visible) {
                        visible = true;
                        break;
                    }
                }
            }
            if (gameObject.activeSelf != visible) {
                gameObject.SetActive(visible);
            }
        }
        else if ((updateFlags & exUpdateFlags.Index) != 0) {
            // 如果index改变了则也有可能改变显隐,这种情况不多只是基本简单检查下索引数量就够
            bool visible = (indices.Count > 0);
            if (gameObject.activeSelf != visible) {
                gameObject.SetActive(visible);
            }
        }

        updateFlags = exUpdateFlags.None;
    }
Beispiel #15
0
 // ------------------------------------------------------------------
 /// Actually apply all buffer changes to mesh.
 // ------------------------------------------------------------------
 public static void FlushBuffers(Mesh _mesh, exUpdateFlags _updateFlags, exList<Vector3> _vertices, exList<int> _indices, exList<Vector2> _uvs, exList<Color32> _colors32)
 {
     if ((_updateFlags & exUpdateFlags.VertexAndIndex) == exUpdateFlags.VertexAndIndex) {
         // if we need to update vertices, we should also clear triangles first
         _mesh.triangles = null;  // we dont use Mesh.Clear() since sometimes it goes wrong when the uv and color have not been updated
     }
     if ((_updateFlags & exUpdateFlags.Vertex) != 0 ||
         (_updateFlags & exUpdateFlags.Index) != 0) {    // if we need to update triangles, we should also update vertices, or mesh will become invisible
         _mesh.vertices = _vertices.FastToArray();
     }
     if ((_updateFlags & exUpdateFlags.UV) != 0) {
         _mesh.uv = _uvs.FastToArray();
     }
     if ((_updateFlags & exUpdateFlags.Color) != 0) {
         _mesh.colors32 = _colors32.FastToArray();
     }
     if ((_updateFlags & exUpdateFlags.Index) != 0) {
         _mesh.triangles = _indices.FastToArray();       // we do update triangles here
         //string bufv = "Vertex Buffer: ";
         //string vertices = "Mesh.vertices[" + _mesh.vertices.Length + "]: ";
         //foreach (var v in _mesh.vertices) {
         //    bufv += v;
         //    bufv += ", ";
         //}
         //Debug.Log(bufv);
         //var buf = _indices.FastToArray();
         //string triangles = "Mesh.indices[" + buf.Length + "]: ";
         //foreach (var index in buf) {
         //    triangles += index;
         //    triangles += ",";
         //}
         //Debug.Log(triangles);
     }
     if ((_updateFlags & exUpdateFlags.Index) != 0 || (_updateFlags & exUpdateFlags.Vertex) != 0) {
         _mesh.RecalculateBounds();  // Sometimes Unity will not automatically recalculate the bounding volume.
     }
     if ((_updateFlags & exUpdateFlags.Normal) != 0) {
         Vector3[] normals = new Vector3[_vertices.Count];
         for (int i = 0; i < normals.Length; ++i) {
             normals[i] = new Vector3(0, 0, -1);
         }
         _mesh.normals = normals;
     }
 }
Beispiel #16
0
        // ------------------------------------------------------------------
        // Desc:
        // ------------------------------------------------------------------

        public static exUpdateFlags UpdateBuffers(exISpriteFont _sprite, Space _space, float _alpha,
                                                  exList <Vector3> _vertices, exList <Vector2> _uvs, exList <Color32> _colors32, exList <int> _indices, int _vbIndex, int _ibIndex)
        {
#if UNITY_EDITOR
            if (_sprite.text == null || _sprite.vertexCount < _sprite.text.Length * exMesh.QUAD_VERTEX_COUNT)
            {
                Debug.LogError("顶点缓冲长度不够,是否绕开属性直接修改了text_?: " + _sprite.vertexCount, _sprite as Object);
                return(_sprite.updateFlags);
            }
#endif
            bool colorUpdated = false;   // 有渐变色时,每个字符单独计算顶点色,否则全局填充顶点色

            // Debug.Log(string.Format("[UpdateBuffers|SpriteFontBuilder] _vbIndex: {0} _ibIndex: {1}", _vbIndex, _ibIndex));
            if ((_sprite.updateFlags & exUpdateFlags.Text) != 0)
            {
                if (_alpha > 0.0f)
                {
                    // 初始化渐变色要用到的全局参数
                    Color tmp = _sprite.color; tmp.a *= _alpha;
                    topFinalColor = _sprite.topColor * tmp;
                    botFinalColor = _sprite.botColor * tmp;
                    if (_sprite.fontSize != 0)
                    {
                        botFinalColor = exMath.Lerp(topFinalColor, botFinalColor, 1.0f / _sprite.fontSize);   // 预除
                    }
                    else
                    {
                        botFinalColor = topFinalColor;
                        Debug.LogWarning("Failed to use gradient font color due to invalid font size", _sprite as Object);
                    }
                }
                else
                {
                    topFinalColor = new Color();
                    botFinalColor = new Color();
                }
                colorUpdated = topFinalColor != botFinalColor;
                if ((_sprite.updateFlags & exUpdateFlags.Text & ~exUpdateFlags.Color) != 0 || colorUpdated)
                {
                    BuildText(_sprite, _space, _vertices, _vbIndex, _uvs, colorUpdated ? _colors32 : null);
                }
            }
            if ((_sprite.updateFlags & exUpdateFlags.Index) != 0 && _indices != null)
            {
                // update index buffer
                int indexBufferEnd = _ibIndex + _sprite.indexCount - 5;
                for (int i = _ibIndex, v = _vbIndex; i < indexBufferEnd; i += 6, v += 4)
                {
                    _indices.buffer[i]     = v;
                    _indices.buffer[i + 1] = v + 1;
                    _indices.buffer[i + 2] = v + 2;
                    _indices.buffer[i + 3] = v + 2;
                    _indices.buffer[i + 4] = v + 3;
                    _indices.buffer[i + 5] = v;
                }
            }
            if ((_sprite.updateFlags & exUpdateFlags.Color) != 0 && _colors32 != null && colorUpdated == false)
            {
                // if not gradient we just need to fill same color here
                Color   tmp             = _sprite.topColor * _sprite.color;
                Color32 color32         = new Color(tmp.r, tmp.g, tmp.b, tmp.a * _alpha);
                int     vertexBufferEnd = _vbIndex + _sprite.text.Length * 4;
                for (int i = _vbIndex; i < vertexBufferEnd; ++i)
                {
                    _colors32.buffer[i] = color32;
                }
            }
            exUpdateFlags updatedFlags = _sprite.updateFlags;
            _sprite.updateFlags = exUpdateFlags.None;
            return(updatedFlags);
        }