public void OnBegunInterval(UInt64 ctxId, Interval iv)
        {
            StreamingTextureInterval siv = (StreamingTextureInterval)iv;
            TextureCtx ctx = GetRailIdForPath(ctxId, siv.Filename);

            ctx.MinMipAvailable = siv.MinMipAvailable;
            ctx.MinMipWanted    = siv.MinMipWanted;
            ctx.IsVisible       = siv.InUse;

            if (!m_seenInterval)
            {
                m_seenInterval = true;

                lock (m_log)
                {
                    m_log.SetItemMetaData("/StreamingTextures/mipDelta", EItemType.Float);
                    m_log.SetItemMetaData("/StreamingTextures/mipDeltaSD", EItemType.Float);
                    m_log.SetItemMetaData("/StreamingTextures/mipDeltaMean", EItemType.Float);
                }
            }

            lock (m_log.IntervalTree)
            {
                m_log.IntervalTree.AddInterval(ctx.RailId, iv);
            }
        }
        public void OnFinalisedInterval(UInt64 ctxId, Interval iv, bool isModification)
        {
            StreamingTextureInterval siv = (StreamingTextureInterval)iv;
            TextureCtx ctx = GetRailIdForPath(ctxId, siv.Filename);

            lock (m_log.IntervalTree)
            {
                m_log.IntervalTree.AddInterval(ctx.RailId, iv);
            }

            if (!isModification)
            {
                m_rails.Remove(ctxId);
            }
        }
        private TextureCtx GetRailIdForPath(UInt64 ctxId, string path)
        {
            TextureCtx t = null;

            if (m_rails.ContainsKey(ctxId))
            {
                t = m_rails[ctxId];
            }
            else
            {
                lock (m_log.IntervalTree)
                {
                    int railId = m_log.IntervalTree.AddRail(path);
                    t        = new TextureCtx();
                    t.RailId = railId;
                    m_rails.Add(ctxId, t);

                    m_log.IntervalTree.AddRailToGroup(railId, m_groupId);
                }
            }
            return(t);
        }
        public void OnFrameRecord(FrameRecordValues values)
        {
            if (m_rails.Count == 0)
            {
                return;
            }

            int totalDelta = 0, count = 0;

            foreach (var kv in m_rails)
            {
                TextureCtx ctx = kv.Value;
                if (ctx.IsVisible && ctx.MinMipWanted <= ctx.MinMipAvailable)
                {
                    totalDelta += Math.Abs(ctx.MinMipWanted - ctx.MinMipAvailable);
                    ++count;
                }
            }

            double mean = totalDelta / (double)count;
            double v    = 0;

            foreach (var kv in m_rails)
            {
                TextureCtx ctx = kv.Value;
                if (ctx.IsVisible && ctx.MinMipWanted <= ctx.MinMipAvailable)
                {
                    int d = Math.Abs(ctx.MinMipWanted - ctx.MinMipAvailable);
                    v += (d - mean) * (d - mean);
                }
            }

            double vmean = v / count;
            double sd    = Math.Sqrt(vmean);

            values["/StreamingTextures/mipDelta"]     = (float)totalDelta;
            values["/StreamingTextures/mipDeltaSD"]   = (float)sd;
            values["/StreamingTextures/mipDeltaMean"] = (float)mean;
        }