Exemple #1
0
        /// <summary>
        /// 更新通道
        /// </summary>
        /// <param name="deviceContext">数据库实例</param>
        /// <param name="updateChannel">更新的通道</param>
        /// <returns>更新成功时返回true,如果未找到通道返回false</returns>
        public static bool UpdateChannel(FlowContext deviceContext, FlowChannel updateChannel)
        {
            FlowChannel channel = deviceContext.Channels
                                  .Include(c => c.Lanes)
                                  .SingleOrDefault(c => c.ChannelId == updateChannel.ChannelId);

            if (channel == null)
            {
                return(false);
            }
            else
            {
                channel.ChannelName  = updateChannel.ChannelName;
                channel.ChannelType  = updateChannel.ChannelType;
                channel.ChannelIndex = updateChannel.ChannelIndex;
                channel.RtspUser     = updateChannel.RtspUser;
                channel.RtspPassword = updateChannel.RtspPassword;
                channel.RtspProtocol = updateChannel.RtspProtocol;
                channel.IsLoop       = updateChannel.IsLoop;
                channel.SectionId    = updateChannel.SectionId;
                channel.RoadSection  = null;
                channel.CrossingId   = updateChannel.CrossingId;
                channel.RoadCrossing = null;
                channel.Lanes        = updateChannel.Lanes;

                deviceContext.Channels.Update(channel);
                return(true);
            }
        }
Exemple #2
0
 /// <summary>
 /// 更新通道
 /// </summary>
 /// <param name="updateChannel">通道</param>
 /// <param name="userName">用户名</param>
 /// <returns>更新结果</returns>
 public IStatusCodeActionResult Update([FromBody] FlowChannel updateChannel, string userName = null)
 {
     try
     {
         if (UpdateChannel(_context, updateChannel))
         {
             _context.SaveChanges();
             _logger.LogInformation(new EventId((int)LogEvent.编辑通道, userName), $"更新通道 {updateChannel}");
             return(new OkResult());
         }
         else
         {
             return(new NotFoundResult());
         }
     }
     catch (Exception)
     {
         ModelStateDictionary modelState = CheckUpdateError(_context, updateChannel);
         if (modelState.IsValid)
         {
             throw;
         }
         else
         {
             return(new BadRequestObjectResult(modelState));
         }
     }
 }
Exemple #3
0
 /// <summary>
 /// 添加通道
 /// </summary>
 /// <param name="deviceContext">数据库上下文</param>
 /// <param name="newChannel">新通道</param>
 public static void AddChannel(FlowContext deviceContext, FlowChannel newChannel)
 {
     newChannel.ChannelStatus = (int)DeviceStatus.异常;
     newChannel.RoadSection   = null;
     newChannel.RoadCrossing  = null;
     deviceContext.Channels.Add(newChannel);
 }
Exemple #4
0
        /// <summary>
        /// 检查通道添加错误原因
        /// </summary>
        /// <param name="deviceContext">数据库实例</param>
        /// <param name="channel">通道</param>
        /// <returns>数据校验结果</returns>
        private ModelStateDictionary CheckInsertError(FlowContext deviceContext, FlowChannel channel)
        {
            ModelStateDictionary modelState = CheckUpdateError(deviceContext, channel);

            if (deviceContext.Channels.Count(c => c.ChannelId == channel.ChannelId) > 0)
            {
                modelState.AddModelError("ChannelId", $"通道编号重复 {channel.ChannelId}");
            }

            return(modelState);
        }
Exemple #5
0
        /// <summary>
        /// 更新通道状态
        /// </summary>
        /// <param name="channelUpdateStatus">通道状态</param>
        /// <returns>更新结果</returns>
        public IStatusCodeActionResult UpdateStatus(FlowChannelUpdateStatus channelUpdateStatus)
        {
            FlowChannel channel = _context.Channels.SingleOrDefault(c => c.ChannelId == channelUpdateStatus.ChannelId);

            if (channel == null)
            {
                return(new NotFoundResult());
            }
            channel.ChannelStatus = channelUpdateStatus.ChannelStatus;
            _context.Channels.Update(channel);
            _context.SaveChanges();
            return(new OkResult());
        }
Exemple #6
0
        /// <summary>
        /// 删除通道
        /// </summary>
        /// <param name="channelId">通道编号</param>
        /// <param name="userName">用户名</param>
        /// <returns>删除结果</returns>
        public IStatusCodeActionResult Remove([FromRoute] string channelId, string userName = null)
        {
            channelId = Uri.UnescapeDataString(channelId);
            FlowChannel channel = _context.Channels.SingleOrDefault(c => c.ChannelId == channelId);

            if (channel == null)
            {
                return(new NotFoundResult());
            }
            _context.Channels.Remove(channel);
            _context.SaveChanges();
            _logger.LogInformation(new EventId((int)LogEvent.编辑通道, userName), $"删除通道 {channel}");
            return(new OkResult());
        }
        /// <summary>
        /// 查询通道分钟流量状态
        /// </summary>
        /// <param name="channelId">通道编号</param>
        /// <returns>通道流量状态</returns>
        public ChannelMinuteFlow QueryChannelMuniteStatus(string channelId)
        {
            channelId = Uri.UnescapeDataString(channelId);
            ChannelMinuteFlow channelMinuteFlow = new ChannelMinuteFlow
            {
                LanesFlow = new List <LaneFlow>()
            };
            FlowChannel channel = _memoryCache.GetChannel(channelId);

            if (channel != null)
            {
                if (channel.SectionId.HasValue)
                {
                    SectionFlow sectionFlow = _memoryCache.GetSectionLastFlow(channel.SectionId.Value);
                    if (sectionFlow == null)
                    {
                        channelMinuteFlow.SectionFlow = new SectionFlow
                        {
                            SectionId   = channel.SectionId.Value,
                            SectionName = channel.RoadSection.SectionName
                        };
                    }
                    else
                    {
                        _memoryCache.FillSectionFlowCache(sectionFlow);
                        channelMinuteFlow.SectionFlow = sectionFlow;
                    }
                }

                foreach (Lane lane in channel.Lanes)
                {
                    LaneFlow f = _memoryCache.GetLaneLastFlow(lane.DataId);
                    if (f == null)
                    {
                        channelMinuteFlow.LanesFlow.Add(new LaneFlow
                        {
                            DataId   = lane.DataId,
                            LaneName = lane.LaneName
                        });
                    }
                    else
                    {
                        _memoryCache.FillLaneFlow(f);
                        channelMinuteFlow.LanesFlow.Add(f);
                    }
                }
            }
            return(channelMinuteFlow);
        }
Exemple #8
0
        /// <summary>
        /// 更新通道标注状态
        /// </summary>
        /// <param name="channelUpdateLocation">通道标注状态</param>
        /// <returns>更新结果</returns>
        public IStatusCodeActionResult UpdateLocation([FromBody] FlowChannelUpdateLocation channelUpdateLocation)
        {
            FlowChannel channel = _context.Channels.SingleOrDefault(d => d.ChannelId == channelUpdateLocation.ChannelId);

            if (channel == null)
            {
                return(new NotFoundResult());
            }

            channel.Location = channelUpdateLocation.Location;
            channel.Marked   = true;
            _context.Channels.Update(channel);
            _context.SaveChanges();
            return(new OkResult());
        }
Exemple #9
0
        /// <summary>
        /// 查询通道
        /// </summary>
        /// <param name="channelId"/>通道编号/param>
        /// <returns>查询结果</returns>
        public IStatusCodeActionResult Get(string channelId)
        {
            FlowChannel channel = Include(_context.Channels)
                                  .SingleOrDefault(c => c.ChannelId == channelId);

            if (channel == null)
            {
                return(new NotFoundObjectResult(null));
            }
            else
            {
                _memoryCache.FillChannel(channel);
                return(new OkObjectResult(channel));
            }
        }
Exemple #10
0
        /// <summary>
        /// 填充通道缓存
        /// </summary>
        /// <param name="memoryCache">缓存</param>
        /// <param name="channel">通道</param>
        /// <returns>通道</returns>
        public static FlowChannel FillChannel(this IMemoryCache memoryCache, FlowChannel channel)
        {
            if (channel != null)
            {
                channel.ChannelStatus_Desc = memoryCache.GetCode(typeof(DeviceStatus), channel.ChannelStatus);
                channel.ChannelType_Desc   = memoryCache.GetCode(typeof(ChannelType), channel.ChannelType);

                if (channel.RtspProtocol.HasValue)
                {
                    channel.RtspProtocol_Desc = memoryCache.GetCode(typeof(RtspProtocol), channel.RtspProtocol.Value);
                }
            }

            return(channel);
        }
        private static FlowChannel GetFlowChannel(string[] keyWords)
        {
            FlowChannel flowChannel = FlowChannel.None;

            if (keyWords.Contains("_FLOW1"))
            {
                flowChannel = FlowChannel.One;
            }
            if (keyWords.Contains("_FLOW2"))
            {
                flowChannel = FlowChannel.Two;
            }
            if (keyWords.Contains("_FLOW3"))
            {
                flowChannel = FlowChannel.Three;
            }
            return(flowChannel);
        }
Exemple #12
0
 /// <summary>
 /// 添加通道
 /// </summary>
 /// <param name="channel">通道</param>
 /// <param name="userName">用户名</param>
 /// <returns>添加结果</returns>
 public ObjectResult Add(FlowChannel channel, string userName = null)
 {
     try
     {
         AddChannel(_context, channel);
         _context.SaveChanges();
         _logger.LogInformation(new EventId((int)LogEvent.编辑通道, userName), $"添加通道 {channel}");
         return(new OkObjectResult(channel));
     }
     catch (Exception)
     {
         ModelStateDictionary modelState = CheckInsertError(_context, channel);
         if (modelState.IsValid)
         {
             throw;
         }
         else
         {
             return(new BadRequestObjectResult(modelState));
         }
     }
 }
Exemple #13
0
    public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
    {
        // get the current keywords from the material
        Material targetMat = materialEditor.target as Material;

        string[] keyWords = targetMat.shaderKeywords;

        int layerCount = (int)FlowChannel.None;

        if (targetMat.shader.name == "G2Studios/VertexPainter/SplatBlendSpecular_1Layer")
        {
            layerCount = (int)FlowChannel.One;
        }
        else if (targetMat.shader.name == "G2Studios/VertexPainter/SplatBlendSpecular_2Layer")
        {
            layerCount = (int)FlowChannel.Two;
        }
        else if (targetMat.shader.name == "G2Studios/VertexPainter/SplatBlendSpecular_3Layer")
        {
            layerCount = (int)FlowChannel.Three;
        }

        FlowChannel fchannel = FlowChannel.None;

        if (keyWords.Contains("_FLOW1"))
        {
            fchannel = FlowChannel.One;
        }
        if (keyWords.Contains("_FLOW2"))
        {
            fchannel = FlowChannel.Two;
        }
        if (keyWords.Contains("_FLOW3"))
        {
            fchannel = FlowChannel.Three;
        }

        bool flowDrift      = keyWords.Contains("_FLOWDRIFT");
        bool flowRefraction = keyWords.Contains("_FLOWREFRACTION");
        bool parallax       = keyWords.Contains("_PARALLAXMAP");
        bool hasGloss       = (HasTexture(layerCount, targetMat, "_GlossinessTex"));
        bool hasSpec        = (HasTexture(layerCount, targetMat, "_SpecGlossMap"));
        bool hasEmis        = (HasTexture(layerCount, targetMat, "_Emissive"));
        bool hasDistBlend   = keyWords.Contains("_DISTBLEND");

        EditorGUI.BeginChangeCheck();

        int oldLayerCount = layerCount;

        layerCount = EditorGUILayout.IntField("Layer Count", layerCount);
        if (oldLayerCount != layerCount)
        {
            if (layerCount < 1)
            {
                layerCount = 1;
            }
            if (layerCount > 3)
            {
                layerCount = 3;
            }

            targetMat.shader = Shader.Find("G2Studios/VertexPainter/SplatBlendSpecular_" + layerCount + "Layer");
            return;
        }

        parallax     = EditorGUILayout.Toggle("Parallax Offset", parallax);
        hasDistBlend = EditorGUILayout.Toggle("UV Scale in distance", hasDistBlend);
        var distBlendMin = FindProperty("_DistBlendMin", props);
        var distBlendMax = FindProperty("_DistBlendMax", props);

        if (hasDistBlend)
        {
            materialEditor.ShaderProperty(distBlendMin, "Distance Blend Min");
            materialEditor.ShaderProperty(distBlendMax, "Distance Blend Max");

            if (distBlendMin.floatValue > distBlendMax.floatValue)
            {
                distBlendMax.floatValue = distBlendMin.floatValue;
            }

            if (distBlendMax.floatValue <= 1)
            {
                distBlendMax.floatValue = 1;
            }
        }

        for (int i = 0; i < layerCount; ++i)
        {
            DrawLayer(materialEditor, i + 1, props, keyWords, hasGloss, hasSpec, parallax, hasEmis, hasDistBlend);
            EditorGUILayout.Space();
        }

        EditorGUILayout.Space();

        fchannel = (FlowChannel)EditorGUILayout.Popup((int)fchannel, flowChannelNames);
        if (fchannel != FlowChannel.None)
        {
            var flowSpeed     = FindProperty("_FlowSpeed", props);
            var flowIntensity = FindProperty("_FlowIntensity", props);
            var flowAlpha     = FindProperty("_FlowAlpha", props);
            var flowRefract   = FindProperty("_FlowRefraction", props);

            materialEditor.ShaderProperty(flowSpeed, "Flow Speed");
            materialEditor.ShaderProperty(flowIntensity, "Flow Intensity");
            materialEditor.ShaderProperty(flowAlpha, "Flow Alpha");
            if (layerCount > 1)
            {
                flowRefraction = EditorGUILayout.Toggle("Flow Refraction", flowRefraction);
                if (flowRefraction)
                {
                    materialEditor.ShaderProperty(flowRefract, "Refraction Amount");
                }
            }
            flowDrift = EditorGUILayout.Toggle("Flow Drift", flowDrift);
        }

        if (EditorGUI.EndChangeCheck())
        {
            var newKeywords = new List <string>();

            newKeywords.Add("_LAYERS" + layerCount.ToString());
            if (hasDistBlend)
            {
                newKeywords.Add("_DISTBLEND");
            }
            if (parallax)
            {
                newKeywords.Add("_PARALLAXMAP");
            }
            if (HasTexture(layerCount, targetMat, "_Normal"))
            {
                newKeywords.Add("_NORMALMAP");
            }
            if (hasSpec)
            {
                newKeywords.Add("_SPECGLOSSMAP");
            }
            if (hasEmis)
            {
                newKeywords.Add("_EMISSION");
            }
            if (fchannel != FlowChannel.None)
            {
                newKeywords.Add("_FLOW" + (int)fchannel);
            }

            if (flowDrift)
            {
                newKeywords.Add("_FLOWDRIFT");
            }
            if (flowRefraction && layerCount > 1)
            {
                newKeywords.Add("_FLOWREFRACTION");
            }
            targetMat.shaderKeywords = newKeywords.ToArray();
            EditorUtility.SetDirty(targetMat);
        }
    }
 public IActionResult Update([FromBody] FlowChannel updateChannel)
 {
     return(_channelsManager.Update(updateChannel));
 }
Exemple #15
0
        public static List <FlowDevice> CreateFlowDevice(IServiceProvider serviceProvider, int deviceCount, int channelCount, int laneCount, bool initDatabase = false, string ip1 = "127.0.0.", int ip2 = 1, int id = 100)
        {
            List <FlowDevice> devices = new List <FlowDevice>();

            using (FlowContext context = serviceProvider.CreateScope().ServiceProvider.GetRequiredService <FlowContext>())
            {
                if (initDatabase)
                {
                    ResetDatabase(serviceProvider);
                }

                for (int i = 0; i < deviceCount; ++i)
                {
                    FlowDevice device = new FlowDevice
                    {
                        DeviceId                = id,
                        DeviceName              = $"流量测试设备_{id}",
                        DeviceModel             = (int)DeviceModel.MO_AF_A11_04_4X,
                        Ip                      = $"{ip1}{ip2++}",
                        Port                    = 17000,
                        FlowDevice_FlowChannels = new List <FlowDevice_FlowChannel>()
                    };
                    for (int j = 0; j < channelCount; ++j)
                    {
                        RoadCrossing roadCrossing = new RoadCrossing
                        {
                            CrossingId   = id,
                            CrossingName = $"流量测试路口_{id}"
                        };
                        RoadSection roadSection = new RoadSection
                        {
                            SectionId   = id,
                            SectionName = $"流量测试通路段_{id}",
                            SectionType = (int)SectionType.主干路,
                            SpeedLimit  = 10,
                            Length      = 10,
                            Direction   = (int)LaneDirection.由东向西
                        };
                        FlowChannel channel = new FlowChannel
                        {
                            ChannelId    = $"channel_{id}",
                            ChannelName  = $"流量测试通道_{id}",
                            ChannelIndex = j + 1,
                            CrossingId   = id,
                            SectionId    = id,
                            ChannelType  = (int)ChannelType.GB28181,
                            Lanes        = new List <Lane>(),
                            RoadCrossing = roadCrossing,
                            RoadSection  = roadSection
                        };

                        FlowDevice_FlowChannel relation = new FlowDevice_FlowChannel
                        {
                            DeviceId  = id,
                            ChannelId = channel.ChannelId,
                            Channel   = channel
                        };
                        id++;
                        device.FlowDevice_FlowChannels.Add(relation);
                        for (int k = 0; k < laneCount; ++k)
                        {
                            LaneDirection direction;
                            if (k >= 0 && k < 3)
                            {
                                direction = LaneDirection.由南向北;
                            }
                            else if (k >= 3 && k < 6)
                            {
                                direction = LaneDirection.由北向南;
                            }
                            else if (k >= 6 && k < 9)
                            {
                                direction = LaneDirection.由东向西;
                            }
                            else
                            {
                                direction = LaneDirection.由西向东;
                            }

                            FlowDirection flowDirection;
                            if (k % 3 == 0)
                            {
                                flowDirection = FlowDirection.直行;
                            }
                            else if (k % 3 == 1)
                            {
                                flowDirection = FlowDirection.左转;
                            }
                            else
                            {
                                flowDirection = FlowDirection.右转;
                            }
                            channel.Lanes.Add(new Lane
                            {
                                ChannelId     = channel.ChannelId,
                                LaneId        = $"{k + 1:D2}",
                                LaneName      = $"流量测试车道_{k + 1:D2}",
                                Channel       = channel,
                                Direction     = (int)direction,
                                FlowDirection = (int)flowDirection,
                                LaneIndex     = k + 1,
                                Region        = "[]",
                                Length        = 10
                            });
                        }
                    }
                    context.Devices.Add(device);
                    devices.Add(device);
                    context.SaveChanges();
                }
            }
            return(devices);
        }
    public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
    {
        // get the current keywords from the material
        Material targetMat = materialEditor.target as Material;

        string[] keyWords = targetMat.shaderKeywords;

        int      layerCount = 1;
        Workflow workflow   = Workflow.Metallic;

        if (targetMat.shader.name == "VertexPainter/SplatBlend_1Layer")
        {
            layerCount = 1;
        }
        else if (targetMat.shader.name == "VertexPainter/SplatBlend_2Layer")
        {
            layerCount = 2;
        }
        else if (targetMat.shader.name == "VertexPainter/SplatBlend_3Layer")
        {
            layerCount = 3;
        }
        else if (targetMat.shader.name == "VertexPainter/SplatBlend_4Layer")
        {
            layerCount = 4;
        }
        else if (targetMat.shader.name == "VertexPainter/SplatBlend_5Layer")
        {
            layerCount = 5;
        }
        else if (targetMat.shader.name == "VertexPainter/SplatBlendSpecular_1Layer")
        {
            workflow   = Workflow.Specular;
            layerCount = 1;
        }
        else if (targetMat.shader.name == "VertexPainter/SplatBlendSpecular_2Layer")
        {
            workflow   = Workflow.Specular;
            layerCount = 2;
        }
        else if (targetMat.shader.name == "VertexPainter/SplatBlendSpecular_3Layer")
        {
            workflow   = Workflow.Specular;
            layerCount = 3;
        }
        else if (targetMat.shader.name == "VertexPainter/SplatBlendSpecular_4Layer")
        {
            workflow   = Workflow.Specular;
            layerCount = 4;
        }
        else if (targetMat.shader.name == "VertexPainter/SplatBlendSpecular_5Layer")
        {
            workflow   = Workflow.Specular;
            layerCount = 5;
        }

        FlowChannel fchannel = FlowChannel.None;

        if (keyWords.Contains("_FLOW1"))
        {
            fchannel = FlowChannel.One;
        }
        if (keyWords.Contains("_FLOW2"))
        {
            fchannel = FlowChannel.Two;
        }
        if (keyWords.Contains("_FLOW3"))
        {
            fchannel = FlowChannel.Three;
        }
        if (keyWords.Contains("_FLOW4"))
        {
            fchannel = FlowChannel.Four;
        }
        if (keyWords.Contains("_FLOW5"))
        {
            fchannel = FlowChannel.Five;
        }

        bool flowDrift = keyWords.Contains("_FLOWDRIFT");
        bool parallax  = keyWords.Contains("_PARALLAXMAP");
        bool hasGloss  = (HasTexture(layerCount, targetMat, "_GlossinessTex"));
        bool hasSpec   = (HasTexture(layerCount, targetMat, "_SpecGlossMap"));
        bool hasEmis   = (HasTexture(layerCount, targetMat, "_Emissive"));


        EditorGUI.BeginChangeCheck();
        Workflow oldWorkflow = workflow;

        workflow = (Workflow)EditorGUILayout.EnumPopup("Workflow", workflow);

        int oldLayerCount = layerCount;

        layerCount = EditorGUILayout.IntField("Layer Count", layerCount);
        if (oldLayerCount != layerCount || workflow != oldWorkflow)
        {
            if (layerCount < 1)
            {
                layerCount = 1;
            }
            if (layerCount > 5)
            {
                layerCount = 5;
            }

            if (workflow == Workflow.Metallic)
            {
                targetMat.shader = Shader.Find("VertexPainter/SplatBlend_" + layerCount + "Layer");
            }
            else
            {
                targetMat.shader = Shader.Find("VertexPainter/SplatBlendSpecular_" + layerCount + "Layer");
            }
            return;
        }


        parallax = EditorGUILayout.Toggle("Parallax Offset", parallax);

        for (int i = 0; i < layerCount; ++i)
        {
            DrawLayer(materialEditor, i + 1, props, keyWords, workflow, hasGloss, hasSpec, parallax, hasEmis);

            EditorGUILayout.Space();
        }

        EditorGUILayout.Space();

        fchannel = (FlowChannel)EditorGUILayout.Popup((int)fchannel, flowChannelNames);
        if (fchannel != FlowChannel.None)
        {
            var flowSpeed     = FindProperty("_FlowSpeed", props);
            var flowIntensity = FindProperty("_FlowIntensity", props);

            materialEditor.ShaderProperty(flowSpeed, "Flow Speed");
            materialEditor.ShaderProperty(flowIntensity, "Flow Intensity");
            flowDrift = EditorGUILayout.Toggle("Flow Drift", flowDrift);
        }

        if (EditorGUI.EndChangeCheck())
        {
            var newKeywords = new List <string>();

            newKeywords.Add("_LAYERS" + layerCount.ToString());
            if (parallax)
            {
                newKeywords.Add("_PARALLAXMAP");
            }
            if (HasTexture(layerCount, targetMat, "_Normal"))
            {
                newKeywords.Add("_NORMALMAP");
            }
            if (hasGloss && workflow == Workflow.Metallic)
            {
                newKeywords.Add("_METALLICGLOSSMAP");
            }
            if (hasSpec && workflow == Workflow.Specular)
            {
                newKeywords.Add("_SPECGLOSSMAP");
            }
            if (hasEmis)
            {
                newKeywords.Add("_EMISSION");
            }
            if (fchannel != FlowChannel.None)
            {
                newKeywords.Add("_FLOW" + (int)fchannel);
            }

            if (flowDrift)
            {
                newKeywords.Add("_FLOWDRIFT");
            }
            targetMat.shaderKeywords = newKeywords.ToArray();
            EditorUtility.SetDirty(targetMat);
        }
    }
 public IActionResult Add([FromBody] FlowChannel channel)
 {
     return(_channelsManager.Add(channel, User?.Identity?.Name));
 }
Exemple #18
0
        /// <summary>
        /// 检查通道更新错误原因
        /// </summary>
        /// <param name="deviceContext">数据库实例</param>
        /// <param name="channel">通道</param>
        /// <returns>数据校验结果</returns>
        public static ModelStateDictionary CheckUpdateError(FlowContext deviceContext, FlowChannel channel)
        {
            ModelStateDictionary modelState = new ModelStateDictionary();

            if (channel.CrossingId.HasValue)
            {
                if (deviceContext.RoadCrossings.Count(d => d.CrossingId == channel.CrossingId) == 0)
                {
                    modelState.AddModelError("CrossingId", $"不存在路口编号 {channel.CrossingId}");
                }
            }

            if (channel.SectionId.HasValue)
            {
                if (deviceContext.RoadSections.Count(d => d.SectionId == channel.SectionId) == 0)
                {
                    modelState.AddModelError("SectionId", $"不存在路段编号 {channel.SectionId}");
                }
            }

            return(modelState);
        }
    public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
    {
        base.OnGUI(materialEditor, props);

        Material targetMat = materialEditor.target as Material;

        string[] keyWords = targetMat.shaderKeywords;

        FlowChannel fchannel = FlowChannel.None;

        if (keyWords.Contains("_FLOW1"))
        {
            fchannel = FlowChannel.One;
        }
        if (keyWords.Contains("_FLOW2"))
        {
            fchannel = FlowChannel.Two;
        }
        if (keyWords.Contains("_FLOW3"))
        {
            fchannel = FlowChannel.Three;
        }
        if (keyWords.Contains("_FLOW4"))
        {
            fchannel = FlowChannel.Four;
        }
        if (keyWords.Contains("_FLOW5"))
        {
            fchannel = FlowChannel.Five;
        }

        bool flowDrift      = keyWords.Contains("_FLOWDRIFT");
        bool flowRefraction = keyWords.Contains("_FLOWREFRACTION");

        EditorGUI.BeginChangeCheck();
        fchannel = (FlowChannel)EditorGUILayout.Popup((int)fchannel, flowChannelNames);
        if (fchannel != FlowChannel.None)
        {
            // var flowSpeed = FindProperty("_FlowSpeed", props);
            // var flowIntensity = FindProperty("_FlowIntensity", props);
            // var flowAlpha = FindProperty("_FlowAlpha", props);
            // var flowRefract = FindProperty("_FlowRefraction", props);

            //materialEditor.ShaderProperty(flowSpeed, "Flow Speed");
            //materialEditor.ShaderProperty(flowIntensity, "Flow Intensity");
            //materialEditor.ShaderProperty(flowAlpha, "Flow Alpha");
            //if (layerCount > 1)
            //{
            //    flowRefraction = EditorGUILayout.Toggle("Flow Refraction", flowRefraction);
            //    if (flowRefraction)
            //    {
            //        materialEditor.ShaderProperty(flowRefract, "Refraction Amount");
            //    }
            //}
            flowDrift = EditorGUILayout.Toggle("Flow Drift", flowDrift);
        }

        if (EditorGUI.EndChangeCheck())
        {
            var newKeywords = new List <string>();
            if (fchannel != FlowChannel.None)
            {
                newKeywords.Add("_FLOW" + (int)fchannel);
            }
            if (flowDrift)
            {
                newKeywords.Add("_FLOWDRIFT");
            }
            targetMat.shaderKeywords = newKeywords.ToArray();
            EditorUtility.SetDirty(targetMat);
        }
    }
        public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
        {
            Material targetMat = materialEditor.target as Material;

            string[] keyWords   = targetMat.shaderKeywords;
            int      layerCount = GetLayerCount(targetMat.shader.name);

            FlowChannel flowChannel    = GetFlowChannel(keyWords);
            bool        flowDrift      = keyWords.Contains("_FLOWDRIFT");
            bool        flowRefraction = keyWords.Contains("_FLOWREFRACTION");
            bool        parallax       = keyWords.Contains("_PARALLAXMAP");
            bool        hasGloss       = (HasTexture(layerCount, targetMat, "_GlossinessTex"));
            bool        hasSpec        = (HasTexture(layerCount, targetMat, "_SpecGlossMap"));
            bool        hasEmis        = (HasTexture(layerCount, targetMat, "_Emissive"));
            bool        hasDistBlend   = keyWords.Contains("_DISTBLEND");

            EditorGUI.BeginChangeCheck();

            int oldLayerCount = layerCount;

            layerCount = EditorGUILayout.IntField("Layer Count", layerCount);
            if (oldLayerCount != layerCount)
            {
                if (layerCount < 1)
                {
                    layerCount = 1;
                }
                if (layerCount > 3)
                {
                    layerCount = 3;
                }

                targetMat.shader = Shader.Find("VertexPainter/Surface_" + layerCount + "Layer");
                return;
            }

            EditorGUILayout.Space();
            GUI_SetCullingMode(targetMat);

            parallax     = EditorGUILayout.Toggle("Parallax Offset", parallax);
            hasDistBlend = EditorGUILayout.Toggle("UV Scale in distance", hasDistBlend);
            var distBlendMin = FindProperty("_DistBlendMin", props);
            var distBlendMax = FindProperty("_DistBlendMax", props);

            if (hasDistBlend)
            {
                materialEditor.ShaderProperty(distBlendMin, "Distance Blend Min");
                materialEditor.ShaderProperty(distBlendMax, "Distance Blend Max");

                if (distBlendMin.floatValue > distBlendMax.floatValue)
                {
                    distBlendMax.floatValue = distBlendMin.floatValue;
                }

                if (distBlendMax.floatValue <= 1)
                {
                    distBlendMax.floatValue = 1;
                }
            }

            // Setting LayerGUI
            EditorGUILayout.Space();
            for (int i = 0; i < layerCount; ++i)
            {
                layerFoldOuts[i] = Foldout(layerFoldOuts[i], "Layer " + (i + 1) + " Setting");
                if (layerFoldOuts[i])
                {
                    EditorGUI.indentLevel++;
                    EditorGUILayout.Space();
                    DrawLayer(materialEditor, i + 1, props, keyWords, hasGloss, hasSpec, parallax, hasEmis, hasDistBlend);
                    EditorGUI.indentLevel--;
                }
            }
            EditorGUILayout.Space();

            flowChannel = (FlowChannel)EditorGUILayout.Popup((int)flowChannel, CHANNEL_NAMES);
            if (flowChannel != FlowChannel.None)
            {
                var flowSpeed     = FindProperty("_FlowSpeed", props);
                var flowIntensity = FindProperty("_FlowIntensity", props);
                var flowAlpha     = FindProperty("_FlowAlpha", props);
                var flowRefract   = FindProperty("_FlowRefraction", props);

                materialEditor.ShaderProperty(flowSpeed, "Flow Speed");
                materialEditor.ShaderProperty(flowIntensity, "Flow Intensity");
                materialEditor.ShaderProperty(flowAlpha, "Flow Alpha");
                if (layerCount > 1)
                {
                    flowRefraction = EditorGUILayout.Toggle("Flow Refraction", flowRefraction);
                    if (flowRefraction)
                    {
                        materialEditor.ShaderProperty(flowRefract, "Refraction Amount");
                    }
                }
                flowDrift = EditorGUILayout.Toggle("Flow Drift", flowDrift);
            }
            if (EditorGUI.EndChangeCheck())
            {
                var newKeywords = new List <string>();
                newKeywords.Add("_LAYERS" + layerCount.ToString());
                if (hasDistBlend)
                {
                    newKeywords.Add("_DISTBLEND");
                }
                if (parallax)
                {
                    newKeywords.Add("_PARALLAXMAP");
                }
                if (HasTexture(layerCount, targetMat, "_Normal"))
                {
                    newKeywords.Add("_NORMALMAP");
                }
                if (hasSpec)
                {
                    newKeywords.Add("_SPECGLOSSMAP");
                }
                if (hasEmis)
                {
                    newKeywords.Add("_EMISSION");
                }
                if (flowChannel != FlowChannel.None)
                {
                    newKeywords.Add("_FLOW" + (int)flowChannel);
                }
                if (flowDrift)
                {
                    newKeywords.Add("_FLOWDRIFT");
                }
                if (flowRefraction && layerCount > 1)
                {
                    newKeywords.Add("_FLOWREFRACTION");
                }
                targetMat.shaderKeywords = newKeywords.ToArray();
                EditorUtility.SetDirty(targetMat);
            }
        }