Beispiel #1
0
 public SerializedScriptableObject(SerializationInfo info, StreamingContext context)
 {
     Path            = info.GetValue(nameof(Path), Path);
     Guid            = info.GetValue(nameof(Guid), "");
     SerializedValue = info.GetValue(nameof(SerializedValue), "");
     Type            = ParseUtilities.ParseType(info.GetValue(nameof(Type), ""));
 }
    private void Open(string path)
    {
        if (!FileUtilities.CheckFile(path))
        {
            FileUtilities.WriteText(path, string.Empty);
            AssetDatabase.Refresh();
        }

        string json = FileUtilities.ReadText(path);

        data = JsonConvert.DeserializeObject <Dictionary <string, string> > (json);
        if (data != null)
        {
            data_Keys = new List <string> (data.Keys);
            string[] values = new string[data.Values.Count];
            data.Values.CopyTo(values, 0);
            data_Values = new List <Color> (ParseUtilities.ToColor(values));
        }
        else
        {
            data_Keys   = new List <string> ();
            data_Values = new List <Color> ();
            data        = new Dictionary <string, string> ();
        }
    }
Beispiel #3
0
        private IEnumerator ScriptingTest()
        {
            InitSprings();
            TimeManager.StartUnscaled(UpdateSprings(1));
            var lines = _testScripting.SplitIntoLines();

            for (int i = 0; i < lines.Length; i++)
            {
                var words = lines[i].SplitIntoWords();
                if (words.Length < 1)
                {
                    continue;
                }
                var param0 = words.Length < 2 ? "" : words[1];
                var param1 = words.Length < 3 ? "" : words[2];
                switch (words[0].ToLower())
                {
                case "wait":
                    if (words.Length == 1)
                    {
                        yield return(null);

                        continue;
                    }
                    if (float.TryParse(param0, out var time))
                    {
                        yield return(time);
                    }
                    if (param0.ToLower() == "springs")
                    {
                        bool allResting = true;
                        while (allResting)
                        {
                            allResting = _moveSpring.Resting && _rotationSpring.Resting && _fovSpring.Resting;
                            yield return(null);
                        }
                    }
                    break;

                case "fov":
                case "zoom":
                    ZoomForce(ParseUtilities.TryParse(param0, 5f), ParseUtilities.TryParse(param1, 4));
                    break;

                case "pitch":
                case "kick":
                    AddForce(ParseUtilities.TryParse(param0, Vector3.up), ParseUtilities.TryParse(param1, 4));
                    break;

                case "shake":
                case "rotate":
                    AddRotationForce(ParseUtilities.TryParse(param0, Vector3.up), ParseUtilities.TryParse(param1, 4));
                    break;
                }
            }
            yield return(null);
        }
Beispiel #4
0
        public static SystemBase GetType(string typeName)
        {
            var type = ParseUtilities.ParseType(typeName);

            if (type != null)
            {
                return(_systems.TryGetValue(type, out var system) ? system : null);
            }
            return(null);
        }
Beispiel #5
0
        public SerializedV3(SerializationInfo info, StreamingContext context)
        {
            var v3String = info.GetValue(nameof(Value), "");

            if (ParseUtilities.TryParse(v3String, out Vector3 v3))
            {
                Value = v3;
            }
            else
            {
                Value = null;
            }
        }
Beispiel #6
0
        public SerializedQuaternion(SerializationInfo info, StreamingContext context)
        {
            var qtString = info.GetValue(nameof(Value), "");

            if (ParseUtilities.TryParse(qtString, out Quaternion v3))
            {
                Value = v3;
            }
            else
            {
                Value = null;
            }
        }
Beispiel #7
0
            public ProjectileTemplate(DataEntry data)
            {
                Data              = data;
                ID                = data.ID;
                Type              = data.TryGetValue("Type", data.ID);
                Movement          = data.TryGetValue("Movement", "Simple");
                Speed             = data.TryGetValue("Speed", 0f);
                Rotation          = data.TryGetValue("Rotation", 0f);
                CollisionDistance = data.TryGetValue("CollisionDistance", 0.25f);
                Size              = data.TryGetValue("Size", 0f);
                Length            = data.TryGetValue("Length", 0f);
                Timeout           = data.TryGetValue(DatabaseFields.Timeout, _defaultTimeout.Value);
                GlowPower         = data.TryGetValue("GlowPower", 0f);
                TrailAmount       = data.TryGetValue("TrailAmount", 0);
                TrailFrequency    = data.TryGetValue("TrailFrequency", 0f);
                TrailColor        = data.TryGetValue("TrailColor", Color.black);
                Radius            = ParseUtilities.TryParseEnum(data.GetValue <string>("Radius"), ImpactRadiusTypes.Single);
                Billboard         = ParseUtilities.TryParseEnum(data.GetValue <string>("Billboard"), BillboardMode.FaceCamYDiff);
                MainColor         = data.TryGetValue("MainColor", Color.white);
                OffsetColor       = data.TryGetValue("OffsetColor", Color.white);
                PoolSize          = data.TryGetValue("PoolSize", _defaultPool);
                var afx = data.GetValue <string>(DatabaseFields.ActionFx);

                if (!string.IsNullOrEmpty(afx))
                {
                    ActionFx = ItemPool.LoadAsset <ActionFx>(UnityDirs.ActionFx, afx);
                }
                var model = data.GetValue <string>(DatabaseFields.Model);

                switch (Type)
                {
                default:
                case "Simple":
                    break;

                case "SpherePhysics":
                    if (!string.IsNullOrEmpty(model))
                    {
                        Animation = ItemPool.LoadAsset <SpriteAnimation>(UnityDirs.ActionSpawn, model);
                    }
                    break;

                case "VolumeLaser":
                    Prefab = model;
                    break;
                }
                Components = data.Get(DatabaseFields.Components) as DataList;
            }
Beispiel #8
0
 /// <summary>
 /// 获取颜色配置
 /// </summary>
 /// <param name="key">颜色配置数据的 Key</param>
 /// <returns></returns>
 public static Color GetColor(string key)
 {
     if (colorConfig == null)
     {
         string json = Resources.Load <TextAsset> ("color").text;
         colorConfig = JsonConvert.DeserializeObject <Dictionary <string, string> > (json);
     }
     if (colorConfig.ContainsKey(key))
     {
         return(ParseUtilities.ToColor(colorConfig[key]));
     }
     else
     {
         throw new System.Exception(string.Format("颜色配置中不存在这个 Key:{0}", key));
     }
 }
Beispiel #9
0
 public void AddComponentList(Entity entity, DataEntry data, DataList componentList)
 {
     if (componentList == null || componentList.Value.Count == 0)
     {
         return;
     }
     for (int i = 0; i < componentList.Value.Count; i++)
     {
         var type = ParseUtilities.ParseType(componentList.Value[i].GetValue <string>(DatabaseFields.Component));
         if (type == null)
         {
             continue;
         }
         AddComponent(entity, data, type);
     }
 }
Beispiel #10
0
        public AbilityConfig(DataEntry data)
        {
            ID = data.ID;
            var itemType = data.Get <DataReference>(DatabaseFields.ItemType);

            Name        = data.GetValue <string>(DatabaseFields.Name);
            Description = data.TryGetValue(DatabaseFields.Description, Name);
            Icon        = "A_" + data.GetValue <string>(DatabaseFields.Icon);
            Source      = ParseUtilities.TryParseEnum(data.TryGetValue("ActionSource", ""), ActionSource.Melee);
            Target      = ParseUtilities.TryParseEnum(data.TryGetValue("TargetType", "Enemy"), TargetType.Enemy);
            var range = data.TryGetValue("Range", "Medium");
            var cost  = data.TryGetValue("Cost", 1f);

            Level          = data.TryGetValue("Level", 1);
            CommandType    = ParseUtilities.TryParseEnum(data.TryGetValue(DatabaseFields.Radius, "Command"), ActionCommandType.Attack);
            Skill          = data.TryGetValue(DatabaseFields.Skill, "");
            TypeComponents = itemType?.Value.Get(DatabaseFields.Components) as DataList;
            Data           = data;
            //CommandsElements.Add(new DetermineHitOrMiss(ActionStateEvents.None));
            //if (!string.IsNullOrEmpty(Animation)) {
            //    CommandsElements.Add(new WaitForAnimation(ActionStateEvents.None, Animation, _defaultAnimationTimeout, true, false));
            //}
            //if (data.Get<DataReference>(DatabaseFields.Projectile) != null) {
            //    CommandsElements.Add(new WaitForSpawnMovement(ActionStateEvents.None));
            //}
            //CommandsElements.Add(new GenerateCollisionEvent(ActionStateEvents.Activate));
            var radius = ParseUtilities.TryParseEnum(data.TryGetValue(DatabaseFields.Radius, "Single"), ImpactRadiusTypes.Single);

            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            sb.Append("<b>Power:</b> ");
            sb.Append(data.TryGetValue(DatabaseFields.PowerMin, 0f));
            sb.Append(data.TryGetValue(DatabaseFields.PowerMax, 1f));
            sb.Append("<b>Cost:</b> ");
            sb.Append(cost.ToString("F0"));
            sb.Append(" ");
            sb.Append(GameData.Vitals.GetNameAt("Vitals.Energy"));
            sb.Append(System.Environment.NewLine);
            sb.Append("<b>Targeting:</b> ");
            sb.NewLineAppend(Target.ToDescription());
            sb.Append("<b>Radius:</b> ");
            sb.NewLineAppend(radius.ToDescription());
            sb.Append("<b>Range:</b> ");
            sb.NewLineAppend(range);
            sb.Append("<b>Recovery:</b> ");
            sb.NewLineAppend(CommandType.ToDescription());
            DataDescription = sb.ToString();
        }
        public static IActionEventHandler ParseMessage(string[] splitWords)
        {
            var param0 = splitWords.Length < 2 ? "" : splitWords[1];
            var param1 = splitWords.Length < 3 ? "" : splitWords[2];

            switch (splitWords[0].ToLower())
            {
            case "fov":
            case "zoom":
                return(new CameraFovShakeEvent(ParseUtilities.TryParse(param0, 5f), ParseUtilities.TryParse(param1, 4)));

            case "pitch":
            case "kick":
                return(new CameraShakeEvent(ParseUtilities.TryParse(param0, Vector3.up), ParseUtilities.TryParse(param1, 4), false));

            case "shake":
            case "rotate":
                return(new CameraShakeEvent(ParseUtilities.TryParse(param0, Vector3.up), ParseUtilities.TryParse(param1, 4), true));
            }
            return(null);
        }
Beispiel #12
0
        public T TryGetValue <T>(string field, T defaultValue)
        {
            var cell = Get(field);

            if (cell == null)
            {
                return(FindChildValue <T>(field, defaultValue));
            }
            if (cell is DataCell <T> typeCell)
            {
                return(typeCell.Value);
            }
            if (typeof(T).IsEnum && cell is DataCell <string> stringCell)
            {
                return(ParseUtilities.TryParseEnum(stringCell.Value, defaultValue));
            }
            if (cell.Get is T variable)
            {
                return(variable);
            }
            return(FindChildValue <T>(field, defaultValue));
        }
Beispiel #13
0
        static Int32 Main(string[] args)
        {
            TunnelOptions optionsParser = new TunnelOptions();
            List <String> nonOptionArgs = optionsParser.Parse(args);

            if (nonOptionArgs.Count <= 0)
            {
                Console.WriteLine("Must give at least one listener");
                optionsParser.PrintUsage();
                return(-1);
            }

            SelectControl selectControl = new SelectControl(false);

            //
            // Parse listeners
            //
            int arg = 0;

            do
            {
                //
                // Get Command Line Arguments
                //
                String connector = nonOptionArgs[arg];
                arg++;
                if (arg >= nonOptionArgs.Count)
                {
                    Console.WriteLine("EndPoint '{0}' is missing a protocol 'tcp|udp' and a listen port set", connector);
                    optionsParser.PrintUsage();
                    return(-1);
                }
                //
                // Parse End Point
                //
                HostWithOptionalProxy forwardHost = ConnectorParser.ParseConnectorWithPortAndOptionalProxy(connector);

                //
                // Parse Protocol and Port Set
                //
                String protocolAndPortSet = nonOptionArgs[arg++];

                Boolean isTcp;
                if (protocolAndPortSet.StartsWith("tcp", StringComparison.CurrentCultureIgnoreCase))
                {
                    isTcp = true;
                }
                else if (protocolAndPortSet.StartsWith("udp", StringComparison.CurrentCultureIgnoreCase))
                {
                    isTcp = false;
                }
                else
                {
                    throw new InvalidOperationException(String.Format("Unknown protocol '{0}', expected 'tcp' or 'udp'",
                                                                      (protocolAndPortSet.Length < 3) ? protocolAndPortSet : protocolAndPortSet.Remove(3)));
                }

                if (protocolAndPortSet.Length < 4)
                {
                    Console.WriteLine("ProtocolAndPortSet '{0}' Protocol '{1}' is missing a listen port set", connector, protocolAndPortSet);
                    optionsParser.PrintUsage();
                    return(-1);
                }

                String portSetString = protocolAndPortSet.Substring(3);
                if (String.IsNullOrEmpty(portSetString))
                {
                    Console.WriteLine("EndPoint '{0}' Protocol '{1}' is missing a listen port set", connector, protocolAndPortSet);
                    optionsParser.PrintUsage();
                    return(-1);
                }

                PortSet portSet = ParseUtilities.ParsePortSet(portSetString);

                if (isTcp)
                {
                    TcpCallback tcpCallback = new TcpCallback(forwardHost);

                    for (int i = 0; i < portSet.Length; i++)
                    {
                        Socket listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                        listenSocket.Bind(new IPEndPoint(IPAddress.Any, portSet[i]));
                        listenSocket.Listen(optionsParser.socketBackLog.ArgValue);
                        selectControl.AddListenSocket(listenSocket, tcpCallback.HandleAccept);
                    }
                }
                else
                {
                    if (forwardHost.proxy == null)
                    {
                        IPEndPoint        serverEndPoint = forwardHost.directEndPoint.GetOrResolveToIPEndPoint();
                        DirectUdpCallback udpCallback    = new DirectUdpCallback(serverEndPoint, 30 * 60); // 30 minutes
                        for (int i = 0; i < portSet.Length; i++)
                        {
                            Socket udpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                            udpSocket.Bind(new IPEndPoint(IPAddress.Any, portSet[i]));
                            selectControl.AddReceiveSocket(udpSocket, udpCallback.ReceiveHandler);
                        }
                    }
                    else
                    {
                        throw new NotImplementedException();

                        /*
                         * UdpThroughProxyCallback udpCallback = new UdpThroughProxyCallback(serverEndPoint, proxyConnector,
                         *  1000 * 60 * 4, 1000 * 60 * 10);
                         * for (int i = 0; i < portSet.Length; i++)
                         * {
                         *  udpListenerList.Add(new UdpSelectListener(new IPEndPoint(IPAddress.Any, portSet[i]), udpCallback));
                         * }
                         */
                    }
                }
            } while (arg < nonOptionArgs.Count);

            SelectServer selectServer = new SelectServer(selectControl, new Buf(8192));

            selectServer.Run();

            return(-1);
        }
Beispiel #14
0
 public void AddComponent(Entity entity, DataEntry data)
 {
     entity.Add(new SkillRequirement(data.GetValue <string>("Skill"), ParseUtilities.TryParseEnum(data.TryGetValue("Required", "None"), 0)));
 }
Beispiel #15
0
 public SerializedGameObjectReference(SerializationInfo info, StreamingContext context)
 {
     _db   = ParseUtilities.ParseType(info.GetValue(nameof(_db), ""));
     _name = info.GetValue(nameof(_name), _name);
 }
Beispiel #16
0
 public void GetObjectData(SerializationInfo info, StreamingContext context)
 {
     info.AddValue(nameof(Value), Value != null ? ParseUtilities.EncodeV3(Value.Value) : "");
 }
Beispiel #17
0
        public void AddComponent(Entity entity, DataEntry data)
        {
            var action = entity.Add(new ActionConfig());

            var type  = data.Get <DataReference>(DatabaseFields.ItemType);
            var skill = data.TryGetValue <string>(DatabaseFields.Skill, "");

            action.Primary     = type?.TargetID == "WeaponUsable";
            action.WeaponModel = data.TryGetValue("WeaponModel", "");
            if (!string.IsNullOrEmpty(action.WeaponModel))
            {
                entity.Add(new WeaponModelComponent(action.WeaponModel));
            }
            else
            {
                action.WeaponModel = data.TryGetValue("SpriteWeaponModel", "");
            }
            var stats = entity.Get <StatsContainer>();
            var power = new RangeStat(entity, Stats.Power, Stats.Power, data.TryGetValue(DatabaseFields.PowerMin, 0f), data.TryGetValue
                                          (DatabaseFields.PowerMax, 1f));

            stats.Add(power);
            bool generateCollision = false;
            var  targeting         = ParseUtilities.TryParseEnum(data.TryGetValue("TargetType", "Enemy"), TargetType.Enemy);

            if (targeting == TargetType.Self || targeting == TargetType.Friendly)
            {
                generateCollision = true;
            }
            bool limitEnemy  = true;
            var  config      = data.Get <DataList>("Config");
            var  abilityType = data.TryGetValue("Type", "Attack");
            var  damageType  = data.TryGetValue(DatabaseFields.DamageType,
                                                GameData.DamageTypes.GetID(0));

            if (type != null && type.TargetID == "Ability")
            {
                action.AnimationTrigger = data.TryGetValue("Animation", GraphTriggers.UseAbility);
                action.EquipVariable    = "";
                var secondaryType = data.TryGetValue("SecondaryType", "");
                switch (abilityType)
                {
                default:
                case "Attack":
                    entity.Add(
                        new DamageImpact(damageType, Stats.Health, 1));
                    break;

                case "Heal":
                    entity.Add(AddHealImpact(config, false));
                    generateCollision = true;
                    limitEnemy        = false;
                    break;

                case "AddModImpact":
                    entity.Add(AddModImpact(entity, config));
                    generateCollision = true;
                    limitEnemy        = false;
                    break;

                case "Teleport":
                case "Shield":
                case "Unlock":
                    break;
                }
                switch (secondaryType)
                {
                case "Heal":
                    entity.Add(AddHealImpact(config, true));
                    break;

                case "AddModImpact":
                    entity.Add(AddModImpact(entity, config));
                    break;

                case "ConvertVital":
                    entity.Add(new ConvertVitalImpact(config.FindFloat("Percent", 1f), config.FindString("SourceVital"), config.FindString("TargetVital")));
                    break;

                case "InstantKill":
                    entity.Add(new InstantKillImpact(config.FindFloat("Chance", 1f)));
                    break;

                case "Confuse":
                    entity.Add(
                        new ApplyTagImpact(EntityTags.IsConfused, data.TryGetValue("SecondaryPower", EffectChance), config
                                           .FindFloat("Length", EffectTime), damageType, "Confusion"));
                    break;

                case "Slow":
                    entity.Add(new ApplyTagImpact(EntityTags.IsSlowed, data.TryGetValue("SecondaryPower", EffectChance), config
                                                  .FindFloat("Length", EffectTime), damageType, "Slow"));
                    break;

                case "Stun":
                    entity.Add(new ApplyTagImpact(EntityTags.IsStunned, data.TryGetValue("SecondaryPower", EffectChance), config
                                                  .FindFloat("Length", EffectTime), damageType, "Stun"));
                    break;
                }
                switch (abilityType)
                {
                default:
                    action.Costs.Add(new CostVital(Stats.Energy, data.TryGetValue("Cost", 1f), skill));
                    break;

                case "Shield":
                case "Unlock":
                    break;
                }
            }
            else
            {
                action.AnimationTrigger = GraphTriggers.Attack;
                action.EquipVariable    = data.TryGetValue("EquipVariable", "");
                entity.Add(
                    new DamageImpact(data.TryGetValue(DatabaseFields.DamageType,
                                                      GameData.DamageTypes.GetID(0)), Stats.Health, 1));
                var           reload      = data.TryGetValue("ReloadType", "Repair");
                var           reloadSpeed = data.TryGetValue("ReloadSpeed", 1f);
                var           ammo        = AmmoFactory.GetTemplate(data.Get <DataReference>("Ammo"));
                AmmoComponent ammoComponent;
                switch (reload)
                {
                case "Repair":
                    ammoComponent = entity.Add(new AmmoComponent(ammo, skill, reloadSpeed, power, _brokenWeaponPercent));
                    var handlers = entity.GetOrAdd <RuleEventListenerComponent>();
                    handlers.Handlers.Add(World.Get <AmmoSystem>());
                    break;

                default:
                case "Reload":
                    ammoComponent = entity.Add(new AmmoComponent(ammo, skill, reloadSpeed, null));
                    action.Costs.Add(new CostAmmo(ammoComponent));
                    break;
                }
                ammoComponent.Amount.SetLimits(0, data.TryGetValue("AmmoAmount", 5));
                ammoComponent.Amount.SetMax();
            }
            switch (abilityType)
            {
            default:
                var radius = ParseUtilities.TryParseEnum(data.TryGetValue(DatabaseFields.Radius, "Single"), ImpactRadiusTypes.Single);
                if (radius != ImpactRadiusTypes.Single)
                {
                    entity.Add(new ImpactRadius(radius, true));
                }
                action.Range = GameData.ActionDistance.GetAssociatedValue(data.TryGetValue("Range", "Medium"));
                var spawn = data.Get <DataReference>(DatabaseFields.ActionSpawn);
                if (spawn != null)
                {
                    action.AddEvent(AnimationEvents.Default, new EventSpawnProjectile(spawn.TargetID));
                }
                else
                {
                    if (generateCollision)
                    {
                        action.AddEvent(AnimationEvents.Default, new EventGenerateCollisionEvent());
                    }
                    else
                    {
                        var collisionType = data.TryGetValue("CollisionType", "Point");
                        var raycastSize   = GameData.CollisionType.GetAssociatedValue(collisionType) * 0.01f;
                        switch (collisionType)
                        {
                        case "Melee":
                        case "MeleeBig":
                            action.AddEvent(AnimationEvents.CollisionOrImpact, new CameraShakeEvent(new Vector3
                                                                                                        (0, 0, 1), 4, false));
                            break;
                        }
                        //melee or hitscan need to make that clearer
                        action.AddEvent(AnimationEvents.Default, new EventCheckRaycastCollision(action.Range, raycastSize, limitEnemy));
                    }
                }
                break;

            case "Shield":
                entity.Add(
                    new BlockDamageAction(
                        config.FindString("Model", "Shield"), "Vitals.Energy",
                        data.TryGetValue("Cost", 1f), skill, PlayerControls.UseSecondary));
                break;
                //case "Teleport":
                //    sequence.Add(new PlayActionAnimation(ActionStateEvents.None, animation, true, false, true));
                //    sequence.Add(new WaitForAnimation(ActionStateEvents.Activate, animation, true, _defaultAnimationTimeout));
                //    sequence.Add(new TeleportSequence(ActionStateEvents.None, config.FindInt("Distance", 5)));
                //    break;
                //case "Unlock":
                //    sequence.Add(new PlayActionAnimation(ActionStateEvents.None, animation, true, false, true));
                //    sequence.Add(new WaitForAnimation(ActionStateEvents.Activate, animation, true, _defaultAnimationTimeout));
                //    sequence.Add(new Unlock(ActionStateEvents.None, power.UpperRange, data.TryGetValue("Cost", 1f)));
                //    break;
            }
            var afx = data.GetValue <string>(DatabaseFields.ActionFx);

            if (!string.IsNullOrEmpty(afx))
            {
                var actionFx = ItemPool.LoadAsset <ActionFx>(UnityDirs.ActionFx, afx);
                if (actionFx != null)
                {
                    if (actionFx.TryGetColor(out var actionColor))
                    {
                        entity.Add(new HitParticlesComponent(actionColor));
                    }
                    entity.Add(new ActionFxComponent(actionFx));
                }
            }
            var customScripting = data.Get <DataList>("ScriptedEvents");

            if (customScripting != null)
            {
                for (int i = 0; i < customScripting.Count; i++)
                {
                    var scriptingData = customScripting[i];
                    var eventType     = scriptingData.TryGetValue("Event", "");
                    //var eventType = ParseUtilities.TryParseEnum(scriptingData.TryGetValue("Event", ""), ActionState.None);
                    var scripting = scriptingData.TryGetValue("Script", "");
                    if (!string.IsNullOrEmpty(eventType) && !string.IsNullOrEmpty(scripting))
                    {
                        var customScript = ScriptingSystem.ParseMessage(scripting.SplitIntoWords());
                        if (customScript != null)
                        {
                            action.AddEvent(eventType, customScript);
                        }
                    }
                }
            }
        }
        public PickerWindowViewModel()
        {
            using (this.autoChangeTracker.TrackAutoChange())
            {
                this.RegisterPickerProperties();

                this.pickersService.WhenAnyValue(x => x.SelectedPicker.Picker)
                .Subscribe(x =>
                {
                    using (this.autoChangeTracker.TrackAutoChange())
                    {
                        this.RaiseAllChanged();

                        // When we are swapping active pickers, update the local properties.
                        if (!this.userModifyingOutputDirectory)
                        {
                            this.OutputDirectoryOverride = this.Picker.OutputDirectoryOverride;
                        }

                        if (!this.userModifyingNameFormat)
                        {
                            this.NameFormatOverride = this.Picker.NameFormatOverride;
                        }

                        if (!this.userModifyingEncodingPreset)
                        {
                            this.PopulateEncodingPreset(this.Picker.UseEncodingPreset);
                        }
                    }
                });

                this.pickersService.WhenAnyValue(x => x.SelectedPicker.Picker.AudioLanguageCodes).Subscribe(audioLanguageCodes =>
                {
                    using (this.autoChangeTracker.TrackAutoChange())
                    {
                        this.audioLanguages.Edit(audioLanguagesInnerList =>
                        {
                            audioLanguagesInnerList.Clear();

                            if (audioLanguageCodes == null)
                            {
                                audioLanguagesInnerList.Add(new LanguageViewModel(this)
                                {
                                    Code = LanguageUtilities.GetDefaultLanguageCode()
                                });
                                return;
                            }

                            audioLanguagesInnerList.AddRange(audioLanguageCodes.Select(l => new LanguageViewModel(this)
                            {
                                Code = l
                            }));
                        });
                    }
                });

                var audioLanguagesObservable = this.audioLanguages.Connect();
                audioLanguagesObservable.Bind(this.AudioLanguagesBindable).Subscribe();
                audioLanguagesObservable.WhenAnyPropertyChanged().Subscribe(_ =>
                {
                    if (!this.autoChangeTracker.OperationInProgress)
                    {
                        this.HandleAudioLanguageUpdate();
                    }
                });

                this.pickersService.WhenAnyValue(x => x.SelectedPicker.Picker.SubtitleLanguageCodes).Subscribe(subtitleLanguageCodes =>
                {
                    using (this.autoChangeTracker.TrackAutoChange())
                    {
                        this.subtitleLanguages.Edit(subtitleLanguagesInnerList =>
                        {
                            subtitleLanguagesInnerList.Clear();

                            if (subtitleLanguageCodes == null)
                            {
                                subtitleLanguagesInnerList.Add(new LanguageViewModel(this)
                                {
                                    Code = LanguageUtilities.GetDefaultLanguageCode()
                                });
                                return;
                            }

                            subtitleLanguagesInnerList.AddRange(subtitleLanguageCodes.Select(l => new LanguageViewModel(this)
                            {
                                Code = l
                            }));
                        });
                    }
                });

                var subtitleLanguagesObservable = this.subtitleLanguages.Connect();
                subtitleLanguagesObservable.Bind(this.SubtitleLanguagesBindable).Subscribe();
                subtitleLanguagesObservable.WhenAnyPropertyChanged().Subscribe(_ =>
                {
                    if (!this.autoChangeTracker.OperationInProgress)
                    {
                        this.HandleSubtitleLanguageUpdate();
                    }
                });

                // HasMultipleAudioLanguages
                IObservable <int> audioLanguageCountObservable = audioLanguagesObservable
                                                                 .Count()
                                                                 .StartWith(this.audioLanguages.Count);
                IObservable <bool> hasMultipleAudioLanguagesObservable = audioLanguageCountObservable
                                                                         .Select(count => count > 1);
                hasMultipleAudioLanguagesObservable.ToProperty(this, x => x.HasMultipleAudioLanguages, out this.hasMultipleAudioLanguages);

                // AudioFirstTrackLabel
                hasMultipleAudioLanguagesObservable
                .Select(hasMultipleAudioLanguages =>
                {
                    return(hasMultipleAudioLanguages ? PickerRes.FirstTrackOfEachLanguageRadioButton : PickerRes.FirstTrackRadioButton);
                })
                .ToProperty(this, x => x.AudioFirstTrackLabel, out this.audioFirstTrackLabel);

                // AudioAllTracksLabel
                hasMultipleAudioLanguagesObservable
                .Select(hasMultipleAudioLanguages =>
                {
                    return(hasMultipleAudioLanguages ? PickerRes.AllTracksForTheseLanguagesRadioButton : PickerRes.AllTracksForThisLanguageRadioButton);
                })
                .ToProperty(this, x => x.AudioAllTracksLabel, out this.audioAllTracksLabel);

                // HasNoAudioLanguages
                audioLanguageCountObservable
                .Select(count => count == 0)
                .ToProperty(this, x => x.HasNoAudioLanguages, out this.hasNoAudioLanguages);

                // HasMultipleSubtitleLanguages
                IObservable <int> subtitleLanguageCountObservable = subtitleLanguagesObservable
                                                                    .Count()
                                                                    .StartWith(this.subtitleLanguages.Count);
                IObservable <bool> hasMultipleSubtitleLanguagesObservable = subtitleLanguageCountObservable
                                                                            .Select(count => count > 1);
                hasMultipleSubtitleLanguagesObservable.ToProperty(this, x => x.HasMultipleSubtitleLanguages, out this.hasMultipleSubtitleLanguages);

                // SubtitleFirstTrackLabel
                hasMultipleSubtitleLanguagesObservable
                .Select(hasMultipleSubtitleLanguages =>
                {
                    return(hasMultipleSubtitleLanguages ? PickerRes.FirstTrackOfEachLanguageRadioButton : PickerRes.FirstTrackRadioButton);
                })
                .ToProperty(this, x => x.SubtitleFirstTrackLabel, out this.subtitleFirstTrackLabel);

                // SubtitleAllTracksLabel
                hasMultipleSubtitleLanguagesObservable
                .Select(hasMultipleSubtitleLanguages =>
                {
                    return(hasMultipleSubtitleLanguages ? PickerRes.AllTracksForTheseLanguagesRadioButton : PickerRes.AllTracksForThisLanguageRadioButton);
                })
                .ToProperty(this, x => x.SubtitleAllTracksLabel, out this.subtitleAllTracksLabel);

                // HasNoSubtitleLanguages
                subtitleLanguageCountObservable
                .Select(count => count == 0)
                .ToProperty(this, x => x.HasNoSubtitleLanguages, out this.hasNoSubtitleLanguages);

                // SubtitleQuantityClass
                this.WhenAnyValue(x => x.SubtitleSelectionMode, x => x.SubtitleIndices, x => x.HasMultipleSubtitleLanguages, x => x.SubtitleLanguageAll, (selectionMode, subtitleIndices, hasMultipleLanguages, subtitleLanguageAll) =>
                {
                    switch (selectionMode)
                    {
                    case SubtitleSelectionMode.Disabled:
                    case SubtitleSelectionMode.None:
                        return(SubtitleQuantityClass.None);

                    case SubtitleSelectionMode.First:
                    case SubtitleSelectionMode.ForeignAudioSearch:
                        return(SubtitleQuantityClass.Single);

                    case SubtitleSelectionMode.ByIndex:
                        return(ParseUtilities.ParseCommaSeparatedListToPositiveIntegers(subtitleIndices).Count > 1 ? SubtitleQuantityClass.Multiple : SubtitleQuantityClass.Single);

                    case SubtitleSelectionMode.Language:
                        if (hasMultipleLanguages)
                        {
                            return(SubtitleQuantityClass.Multiple);
                        }

                        return(subtitleLanguageAll ? SubtitleQuantityClass.Multiple : SubtitleQuantityClass.Single);

                    case SubtitleSelectionMode.All:
                        return(SubtitleQuantityClass.Multiple);

                    default:
                        throw new ArgumentOutOfRangeException(nameof(selectionMode), selectionMode, null);
                    }
                }).ToProperty(this, x => x.SubtitleQuantityClass, out this.subtitleQuantityClass);

                // ShowMarkFirstAsDefaultCheckBox
                this.WhenAnyValue(x => x.SubtitleQuantityClass, x => x.SubtitleSelectionMode, (subtitleQuantityClass, selectionMode) =>
                {
                    return(subtitleQuantityClass == SubtitleQuantityClass.Multiple && selectionMode != SubtitleSelectionMode.ByIndex);
                }).ToProperty(this, x => x.ShowMarkFirstAsDefaultCheckBox, out this.showMarkFirstAsDefaultCheckBox);

                this.pickersService.WhenAnyValue(x => x.SelectedPicker.Picker.IsDefault, x => x.SelectedPicker.Picker.IsModified, (isDefault, isModified) => !isDefault && !isModified).ToProperty(this, x => x.DeleteButtonVisible, out this.deleteButtonVisible);

                this.pickersService.WhenAnyValue(x => x.SelectedPicker.Picker.DisplayName, x => x.SelectedPicker.Picker.IsModified, (displayName, isModified) =>
                {
                    string windowTitle2 = string.Format(PickerRes.WindowTitle, displayName);
                    if (isModified)
                    {
                        windowTitle2 += " *";
                    }

                    return(windowTitle2);
                }).ToProperty(this, x => x.WindowTitle, out this.windowTitle);

                // Whenever the output directory override is disabled, used the config.
                this.WhenAnyValue(x => x.OutputDirectoryOverrideEnabled).Subscribe(directoryOverrideEnabled =>
                {
                    if (!directoryOverrideEnabled)
                    {
                        this.OutputDirectoryOverride = Config.AutoNameOutputFolder;
                    }
                    else
                    {
                        this.OutputDirectoryOverride = this.Picker.OutputDirectoryOverride;
                    }
                });

                // Whenever the name format override is disabled, used the config.
                this.WhenAnyValue(x => x.NameFormatOverrideEnabled).Subscribe(nameFormatOverrideEnabled =>
                {
                    if (!nameFormatOverrideEnabled)
                    {
                        this.NameFormatOverride = AutoNameCustomFormat;
                    }
                    else
                    {
                        this.NameFormatOverride = this.Picker.NameFormatOverride;
                    }
                });

                // Whenever UseEncodingPreset is false, set the selected VM to null.
                this.WhenAnyValue(x => x.UseEncodingPreset).Subscribe(useEncodingPreset => { this.PopulateEncodingPreset(useEncodingPreset); });

                // Update the underlying picker when our local properties change.
                // Don't need to raise another changed event as our local property setter already raises it.
                this.WhenAnyValue(x => x.OutputDirectoryOverride).Skip(1).Subscribe(directoryOverride =>
                {
                    this.userModifyingOutputDirectory = true;
                    this.UpdatePickerProperty(nameof(this.Picker.OutputDirectoryOverride), directoryOverride, raisePropertyChanged: false);
                    this.outputPathService.GenerateOutputFileName();
                    this.userModifyingOutputDirectory = false;
                });

                this.WhenAnyValue(x => x.NameFormatOverride).Skip(1).Subscribe(nameFormatOverride =>
                {
                    this.userModifyingNameFormat = true;
                    this.UpdatePickerProperty(nameof(this.Picker.NameFormatOverride), nameFormatOverride, raisePropertyChanged: false);
                    this.outputPathService.GenerateOutputFileName();
                    this.userModifyingNameFormat = false;
                });

                this.WhenAnyValue(x => x.SelectedPreset).Subscribe(selectedPreset =>
                {
                    this.userModifyingEncodingPreset = true;
                    string presetName = selectedPreset == null ? null : selectedPreset.Preset.Name;
                    this.UpdatePickerProperty(nameof(this.Picker.EncodingPreset), presetName, raisePropertyChanged: false);
                    if (this.UseEncodingPreset && selectedPreset != null)
                    {
                        if (!this.PresetsService.TryUpdateSelectedPreset(selectedPreset))
                        {
                            DispatchUtilities.BeginInvoke(() =>
                            {
                                this.SelectedPreset = this.PresetsService.SelectedPreset;
                            });
                        }
                    }

                    this.userModifyingEncodingPreset = false;
                });
            }
        }