예제 #1
0
        public MyCueBank(XAudio2 audioEngine, MyObjectBuilder_CueDefinitions cues)
        {
            m_audioEngine = audioEngine;
            if (cues.Cues.Length > 0)
            {
                InitTransitionCues();
                InitMusicCategories();

                m_cues = new Dictionary <int, MyObjectBuilder_CueDefinition>(cues.Cues.Length);
                InitCues(cues);
                InitCategories();

                InitWaveBank();
                InitVoicePools();

#if DEBUG
                ValidateCues();
#endif //DEBUG

                InitNonLoopableCuesLimitRemoveHelper();

                Reverb reverb = new Reverb();
                m_effectDescriptor = new EffectDescriptor(reverb);
            }
        }
예제 #2
0
    /**********************************************************************************/
    // функция получения урона юнитом
    //
    /**********************************************************************************/
    override public void ApplyDamage(DamageData damage)
    {
        if (m_state == UNIT_STATE.ACTIVE)
        {
            // объект получает урон
            m_armor.TakeDamage(damage);

            // накладываем визуальный эффект
            EffectDescriptor dE = new EffectDescriptor();
            if (damage.DamageType == DamageData.DAMAGE_TYPE.ACID)
            {
                dE.Type = UnitEffect.EFFECT_TYPE.DAMAGE_ACID;
            }
            else
            {
                dE.Type = UnitEffect.EFFECT_TYPE.DAMAGE;
            }
            dE.Responsibility = EffectDescriptor.EffectResponsibility.REQUIRED;
            ApplyEffect(dE);

            // если есть возможность нанести ответный урон - делаем это
            if (damage.ExpectResponce == DamageData.RESPONSE.EXPECTED)
            {
                m_weaponMaster.UseCloseWeapon(damage.Damager, true);
            }
        }
    }
예제 #3
0
파일: Form1.cs 프로젝트: BartoszRudnik/UP-L
        private void DirectSound_Start(object sender, EventArgs e)
        {
            soundStream = new SoundStream(File.OpenRead(loadFilePath));
            WaveFormat format = soundStream.Format;

            AudioBuffer buffer = new AudioBuffer
            {
                Stream     = soundStream.ToDataStream(),
                AudioBytes = (int)soundStream.Length,
                Flags      = BufferFlags.EndOfStream
            };

            soundStream.Close();

            sourceVoice = new SourceVoice(xAudio2, format, true);
            sourceVoice.SubmitSourceBuffer(buffer, soundStream.DecodedPacketsInfo);
            sourceVoice.Start();

            if (directSoundEffect == 0)
            {
                SharpDX.XAPO.Fx.Echo effectEcho       = new SharpDX.XAPO.Fx.Echo(xAudio2);
                EffectDescriptor     effectDescriptor = new EffectDescriptor(effectEcho);
                sourceVoice.SetEffectChain(effectDescriptor);
                sourceVoice.EnableEffect(0);
            }
            else if (directSoundEffect == 1)
            {
                SharpDX.XAPO.Fx.Reverb effectReverb     = new SharpDX.XAPO.Fx.Reverb(xAudio2);
                EffectDescriptor       effectDescriptor = new EffectDescriptor(effectReverb);
                sourceVoice.SetEffectChain(effectDescriptor);
                sourceVoice.EnableEffect(0);
            }
        }
예제 #4
0
    /**********************************************************************************/
    // функция применения эффектов
    //
    /**********************************************************************************/
    public void ApplyEffect(EffectDescriptor effect)
    {
        if (!m_isActive)
        {
            return;
        }

        UnitEffect.EFFECT_TYPE eType = effect.Type;
        bool weHaveEffect            = m_effects.ContainsKey(eType);
        bool effectWasApplied        = false;

        if (weHaveEffect)
        {
            if (m_effects[eType] != null)
            {
                m_effects[eType].EffectProducer = effect.EffectProducer;
                m_effects[eType].Activate(effect.Value);
                effectWasApplied = true;
            }
        }

        if (effectWasApplied == false && effect.Responsibility == EffectDescriptor.EffectResponsibility.REQUIRED)
        {
            Debug.LogError("We cann't apply effect: " + eType + " !");
        }
    }
예제 #5
0
        public void TestCanConstructViaDelegate()
        {
            EffectDescriptor td = new EffectDescriptor();
            td.Delegate = new EffectConstructionDelegate(Effect.TestFactory);

            Effect t = td.CreateEffect(3, null);
            Assert.AreEqual(typeof(Effect), t.GetType());
        }
예제 #6
0
        public void TestConstructsGenericEffect()
        {
            EffectDescriptor td = new EffectDescriptor();

            GenericEffect gt = td.CreateEffect(3, new XmlNodeInformation(new CommonNamespaces(OpenXmlFormat.Transitional))) as GenericEffect;
            Assert.IsNotNull(gt);
            
            Assert.IsTrue(td == gt.Descriptor);
            Assert.AreEqual(3, gt.Depth);
        }
예제 #7
0
        public void TestAdditionalLevelsToInclude()
        {
            EffectDescriptor td = new EffectDescriptor();
            td.AdditionalLevels = 2;

            GenericEffect gt = td.CreateEffect(3, new XmlNodeInformation(new CommonNamespaces(OpenXmlFormat.Transitional))) as GenericEffect;
            Assert.IsNotNull(gt);

            Assert.IsTrue(td == gt.Descriptor);
            Assert.AreEqual(1, gt.Depth);
        }
예제 #8
0
    public void AddEffect(EffectDescriptor effect)
    {
        List <EffectDescriptor> effectList = new List <EffectDescriptor>();

        if (effects != null)
        {
            effectList.AddRange(effects);
        }

        effectList.Add(effect);
        SetEffects(effectList);
    }
예제 #9
0
    /**********************************************************************************/
    // функция применения эффектов
    //
    /**********************************************************************************/
    public override void ApplyEffect(EffectDescriptor effect)
    {
        UnitEffect.EFFECT_TYPE eType = effect.Type;
        bool weHaveEffect            = m_effects.ContainsKey(eType);

        if (weHaveEffect)
        {
            m_effects[eType].EffectProducer = effect.EffectProducer;
            m_effects[eType].Activate(effect.Value);
        }
        else if (effect.Responsibility == EffectDescriptor.EffectResponsibility.REQUIRED)
        {
            Debug.LogError("We cann't apply effect: " + eType + " !");
        }
    }
예제 #10
0
    /// <summary>
    /// Adds the effect.
    /// </summary>
    /// <param name="effectName">Effect name.</param>
    /// <param name="modifier">Modifier.</param>
    /// <param name="duration">Duration (if == MaxValue - this is constant effect).</param>
    /// <param name="fxPrefab">Fx prefab.</param>
    public void AddEffect(string effectName, float modifier, float duration, GameObject fxPrefab)
    {
        // Get effect handler from effect name
        MethodInfo methodInfo = GetType().GetMethod(effectName, BindingFlags.Instance | BindingFlags.NonPublic);

        if (methodInfo != null)
        {
            EffectDescriptor hit = null;
            // Serch if same effect already active
            foreach (EffectDescriptor sem in effectList)
            {
                if (effectName == sem.name)
                {
                    hit = sem;
                    break;
                }
            }

            if (hit == null)             // Have no such active effect
            {
                EffectDescriptor newSem = new EffectDescriptor();
                newSem.name = effectName;
                // Create effect
                newSem.effects.Add(modifier, Time.time + duration);
                // Add it to list
                effectList.Add(newSem);
                // Play visual effect
                if (fxPrefab != null)
                {
                    newSem.fx = Instantiate(fxPrefab, transform);
                }
                // Effect added
                methodInfo.Invoke(this, new object[] { EffectTrigger.Added, modifier });
            }
            else             // Already have same effect
            {
                // Add it to current list
                hit.effects.Add(modifier, Time.time + duration);
                // One more modifier added to existing effect
                methodInfo.Invoke(this, new object[] { EffectTrigger.NewModifier, modifier });
            }
        }
        else
        {
            Debug.LogError("Unknown effect - " + effectName);
        }
    }
예제 #11
0
        public PlayForm()
        {
            InitializeComponent();

            // Initalize XAudio2
            xaudio2        = new XAudio2(XAudio2Flags.None, ProcessorSpecifier.DefaultProcessor);
            masteringVoice = new MasteringVoice(xaudio2);

            var waveFormat = new WaveFormat(44100, 32, 2);

            sourceVoice = new SourceVoice(xaudio2, waveFormat);

            int        bufferSize = waveFormat.ConvertLatencyToByteSize(60000);
            DataStream dataStream = new DataStream(bufferSize, true, true);

            // Prepare the initial sound to modulate
            int numberOfSamples = bufferSize / waveFormat.BlockAlign;

            for (int i = 0; i < numberOfSamples; i++)
            {
                float value = (float)(Math.Cos(2 * Math.PI * 220.0 * i / waveFormat.SampleRate) * 0.5);
                dataStream.Write(value);
                dataStream.Write(value);
            }
            dataStream.Position = 0;

            audioBuffer = new AudioBuffer
            {
                Stream     = dataStream,
                Flags      = BufferFlags.EndOfStream,
                AudioBytes = bufferSize,
                LoopBegin  = 0,
                LoopLength = numberOfSamples,
                LoopCount  = AudioBuffer.LoopInfinite
            };

            // Set the effect on the source
            ModulatorEffect     = new ModulatorEffect();
            modulatorDescriptor = new EffectDescriptor(ModulatorEffect);
            reverb           = new Reverb();
            effectDescriptor = new EffectDescriptor(reverb);
            //sourceVoice.SetEffectChain(modulatorDescriptor, effectDescriptor);
            sourceVoice.SetEffectChain(modulatorDescriptor);
            //sourceVoice.EnableEffect(0);

            this.Closed += new EventHandler(PlayForm_Closed);
        }
예제 #12
0
        public MyCueBank(XAudio2 audioEngine, ListReader <MySoundData> cues)
        {
            m_audioEngine = audioEngine;
            if (cues.Count > 0)
            {
                m_cues = new Dictionary <MyCueId, MySoundData>(cues.Count, MyCueId.Comparer);
                InitTransitionCues();
                InitCues(cues);
                InitCategories();

                InitWaveBank();
                InitVoicePools();

                m_reverb           = new Reverb();
                m_effectDescriptor = new EffectDescriptor(m_reverb);
            }
        }
예제 #13
0
파일: Program.cs 프로젝트: nernst/synth
        /// <summary>
        /// SharpDX XAudio2 sample. Plays a generated sound with some reverb.
        /// </summary>
        static void Main(string[] args)
        {
            var xaudio2        = new XAudio2();
            var masteringVoice = new MasteringVoice(xaudio2);

            var waveFormat  = new WaveFormat(44100, 32, 2);
            var sourceVoice = new SourceVoice(xaudio2, waveFormat);

            int bufferSize = waveFormat.ConvertLatencyToByteSize(60000);
            var dataStream = new DataStream(bufferSize, true, true);

            int numberOfSamples = bufferSize / waveFormat.BlockAlign;

            for (int i = 0; i < numberOfSamples; i++)
            {
                // cos(2 * PI * (220 + 4 * cos(2 * PI * 10 * t)) * t) * 0.5
                double vibrato = Math.Cos(2 * Math.PI * 10.0 * i / waveFormat.SampleRate);
                float  value   = (float)(Math.Cos(2 * Math.PI * (220.0 + 4.0 * vibrato) * i / waveFormat.SampleRate) * 0.5);
                dataStream.Write(value);
                dataStream.Write(value);
            }
            dataStream.Position = 0;

            var audioBuffer = new AudioBuffer {
                Stream = dataStream, Flags = BufferFlags.EndOfStream, AudioBytes = bufferSize
            };

            var reverb           = new Reverb(xaudio2);
            var effectDescriptor = new EffectDescriptor(reverb);

            sourceVoice.SetEffectChain(effectDescriptor);
            sourceVoice.EnableEffect(0);

            sourceVoice.SubmitSourceBuffer(audioBuffer, null);

            sourceVoice.Start();

            Console.WriteLine("Play sound");
            for (int i = 0; i < 60; i++)
            {
                Console.Write(".");
                Console.Out.Flush();
                Thread.Sleep(1000);
            }
        }
예제 #14
0
    private bool RenderEffectFieldWithDelete(EffectDescriptor effect)
    {
        Expression expression = new Expression(effect.effectExpression, validVariables);

        expression.Parse();
        string expressionError = string.Empty;

        if (!expression.isValid)
        {
            expressionError = expression.LastError;
        }
        effect.effectExpression = EditorGUI.TextField(new Rect(170, mainControlRectY, 400, 15), effectDisplayNames[effect.effectType], effect.effectExpression);
        bool result = GUI.Button(new Rect(600, mainControlRectY, 20, 15), "X");

        if (!expression.isValid)
        {
            mainControlRectY += 20;
            EditorGUI.LabelField(new Rect(170, mainControlRectY, 700, 15), expressionError);
        }
        mainControlRectY += 20;
        return(result);
    }
예제 #15
0
파일: Playback.cs 프로젝트: XAYRGA/JPlay
            public Track(XAudio2 xAudio2, Z2Sound baa, Dictionary <Tuple <byte, byte>, Instrument> instrumentTable, Dictionary <int, Sample> sampleTable)
            {
                engine               = xAudio2;
                soundData            = baa;
                this.instrumentTable = instrumentTable;
                this.sampleTable     = sampleTable;
                voiceTable           = new Dictionary <byte, NoteData>();
                submix               = new SubmixVoice(engine);
                Echo             effect           = new Echo();
                EffectDescriptor effectDescriptor = new EffectDescriptor(effect)
                {
                    InitialState       = true,
                    OutputChannelCount = 2
                };

                submix.SetEffectChain(effectDescriptor);
                EchoParameters effectParameter = new EchoParameters
                {
                    Delay     = 160f,
                    Feedback  = 0f,
                    WetDryMix = 0f
                };

                submix.SetEffectParameters(0, effectParameter);
                submix.EnableEffect(0);
                outputMatrix    = new float[2];
                Volume          = 127;
                Pitch           = 0;
                Pan             = 63;
                panChanged      = false;
                Bank            = 0;
                Echo            = 0;
                echoChanged     = false;
                Instrument      = 0;
                outputMatrix[0] = (outputMatrix[1] = 0.5f);
            }
예제 #16
0
 private TriggeringNodeDefinition BuildMockTriggerNodeThing()
 {
     EffectDescriptor td = new EffectDescriptor();
     td.AdditionalLevels = 2;
     td.ContentType = ContentType.SmallText;
     TriggeringNodeDefinition result = new TriggeringNodeDefinition(NamespaceId.w, "vanish", null, null, td);
     return result;
 }
예제 #17
0
 /**********************************************************************************/
 // функция применения эффектов
 // эффекты не применяются
 //
 /**********************************************************************************/
 public override void ApplyEffect(EffectDescriptor effect)
 {
 }
예제 #18
0
 /**********************************************************************************/
 // функция применения эффектов
 //
 /**********************************************************************************/
 abstract public void ApplyEffect(EffectDescriptor effect);
예제 #19
0
 /**********************************************************************************/
 // эффекты
 //
 /**********************************************************************************/
 public override void ApplyEffect(EffectDescriptor effect)
 {
     // эффекты не применяются
 }
예제 #20
0
    /**********************************************************************************/
    // применяем эффеккт кислоты
    //
    /**********************************************************************************/
    protected override void ApplyBilletEffect(Collision2D coll)
    {
        EffectDescriptor effectDescr = new EffectDescriptor(UnitEffect.EFFECT_TYPE.ACID, damage, this, EffectDescriptor.EffectResponsibility.TRY_TO_APPLY);

        coll.gameObject.SendMessage("ApplyEffect", effectDescr, SendMessageOptions.DontRequireReceiver);
    }
예제 #21
0
 /**********************************************************************************/
 // функция применения эффектов
 //
 /**********************************************************************************/
 public override void ApplyEffect(EffectDescriptor effect)
 {
     m_effectMaster.ApplyEffect(effect);
 }
예제 #22
0
        public void TestIntegerToStringLookupEffect()
        {
            Dictionary<string, string> lookup = new Dictionary<string, string>();
            lookup.Add("0", "Nobody We Know");
            lookup.Add("1", "Henry McAlpine");
            lookup.Add("2", "Bicycle Repair Man");

            EffectDescriptor td = new EffectDescriptor();
            td.ContentType = ContentType.Comment;
            td.BlockType = Effect.BlockType.Structure;
            AttributeFilter filter = new NullAttributeFilter();
            td.AddAdditionalInfoDescriptor(new AdditionalInfoDescriptor("Author", "authorID", AdditionalInfoDescriptor.MappingType.StringToStringLookup));

            {
                XmlNodeInformation xni = new XmlNodeInformation(new CommonNamespaces(OpenXmlFormat.Transitional));
                List<AttribDetails> lad = xni.GetAttributes() as List<AttribDetails>;
                lad.Add(new AttribDetails("p", "authorId", @"http://schemas.openxmlformats.org/presentationml/2006/main", "7"));

                GenericEffect ge = td.CreateEffect(2, xni) as GenericEffect;
                List<NodeInfo> geai = ge.GetAdditionalInfo();
                NodeInfo ni = geai[0];
                Assert.AreEqual("Author", ni.name);
                Assert.AreEqual("Unknown", ni.value);
            }

            td.DictStringToStringLookup = lookup;

            {
                XmlNodeInformation xni = new XmlNodeInformation(new CommonNamespaces(OpenXmlFormat.Transitional));
                List<AttribDetails> lad = xni.GetAttributes() as List<AttribDetails>;
                lad.Add(new AttribDetails("p", "authorId", @"http://schemas.openxmlformats.org/presentationml/2006/main", "1"));

                GenericEffect ge = td.CreateEffect(2, xni) as GenericEffect;
                List<NodeInfo> geai = ge.GetAdditionalInfo();
                NodeInfo ni = geai[0];
                Assert.AreEqual("Author", ni.name);
                Assert.AreEqual("Henry McAlpine", ni.value);
            }
            {
                XmlNodeInformation xni = new XmlNodeInformation(new CommonNamespaces(OpenXmlFormat.Transitional));
                List<AttribDetails> lad = xni.GetAttributes() as List<AttribDetails>;
                lad.Add(new AttribDetails("p", "authorId", @"http://schemas.openxmlformats.org/presentationml/2006/main", "2"));

                GenericEffect ge = td.CreateEffect(2, xni) as GenericEffect;
                List<NodeInfo> geai = ge.GetAdditionalInfo();
                NodeInfo ni = geai[0];
                Assert.AreEqual("Author", ni.name);
                Assert.AreEqual("Bicycle Repair Man", ni.value);
            }
            {
                XmlNodeInformation xni = new XmlNodeInformation(new CommonNamespaces(OpenXmlFormat.Transitional));
                List<AttribDetails> lad = xni.GetAttributes() as List<AttribDetails>;
                lad.Add(new AttribDetails("p", "authorId", @"http://schemas.openxmlformats.org/presentationml/2006/main", "7"));

                GenericEffect ge = td.CreateEffect(2, xni) as GenericEffect;
                List<NodeInfo> geai = ge.GetAdditionalInfo();
                NodeInfo ni = geai[0];
                Assert.AreEqual("Author", ni.name);
                Assert.AreEqual("Unknown", ni.value);
            }
        }
예제 #23
0
        public async void RenderProject(StorageFileEx saveToFile)
        {
            //second rendering not allowed
            if (IsRendering)
            {
                return;
            }

            RenderProgress = "Initiate rendering ...";

            IsRendering = true;

            StopIsChecked = true;

            var tempWaveFileStream = await saveToFile.OpenStreamForWriteAsync();

            await Task.Run(() =>
            {
                ExecuteStop();

                var waveFileWriter = new WaveFileWriterEffect();
                var descriptor     = new EffectDescriptor(waveFileWriter);

                AudioDefines.MasteringVoice.SetEffectChain(descriptor);

                AudioDefines.MasteringVoice.EnableEffect(0);

                var silenceSamplePlayer = new SilenceSamplePlayer();

                silenceSamplePlayer.WithXAudio(AudioDefines.XAudio)
                .WithWaveFormat(AudioDefines.WaveFormat)
                .WithVoicePool(AudioDefines.VoicePool);

                silenceSamplePlayer.BuildAsync().Wait();
                silenceSamplePlayer.Play();

                RenderProgress = string.Format("rendering");

                Task.Delay(500).Wait();

                var previousVolume = MasterVolume;
                MasterVolume       = 0.0;

                waveFileWriter.Start();

                PlayIsChecked = true;

                MasterVolume = previousVolume;

                Task.Delay(30000).Wait();

                MasterVolume = 0.0;

                waveFileWriter.Stop(tempWaveFileStream);

                StopIsChecked = true;

                silenceSamplePlayer.Dispose();

                AudioDefines.MasteringVoice.DisableEffect(0);

                AudioDefines.MasteringVoice.SetEffectChain(null);

                waveFileWriter.Dispose();

                MasterVolume = previousVolume;
            });

            tempWaveFileStream.Dispose();

            IsRendering = false;
        }
예제 #24
0
        public void TestFilterOutNodesWithContentByName()
        {
            using (Stream from = File.Open(TESTFILE_DIR + "Comments3.xml", FileMode.Open))
            {
                if (File.Exists(TESTFILE_DIR + "Comments3_result.xml"))
                    File.Delete(TESTFILE_DIR + "Comments3_result.xml");
                using (Stream to = File.Open(TESTFILE_DIR + "Comments3_result.xml", FileMode.CreateNew))
                {

                    StateMachineBasedXmlFilter xfb = new StateMachineBasedXmlFilter(new CommonNamespaces(OpenXmlFormat.Transitional));
                    xfb.ConnectToInputStream(from);
                    xfb.ConnectToOutputStream(to);

                    EffectDescriptor td = new EffectDescriptor();
                    td.BlockType = Effect.BlockType.Content;
                    TriggeringNodeDefinition tnd = new TriggeringNodeDefinition(NamespaceId.w, "t", null, null, td);

                    xfb.AddNodeToTriggerList(tnd);

                    xfb.Execute();
                }
            }
            Assert.IsTrue(XmlDocumentComparison.AreEquivalent(TESTFILE_DIR + "Comments3_wanted.xml",
                                                              TESTFILE_DIR + "Comments3_result.xml"));
        }
예제 #25
0
 public static Effect Factory(int iDepth, XmlNodeInformation ni, EffectDescriptor ed)
 {
     return new EndNodeRememberingEffect(iDepth);
 }
예제 #26
0
    private void OnGUI()
    {
        // Display items

        /*
         * "Skills" label at top left
         * Search text box
         * Results box with selectable items, vertical scrolling
         * Right panel
         *  "Name" label and text box
         *  "Display" label and text box
         *  "Delay" label and text box
         *  "Targets" label and enumeration multi-select
         *  "Start Target" label and enumeration single-select
         *  "Retargetable" label and checkbox
         *  "Effects" label
         *      Vertical scrolling area with effect controls
         *      New Effect button
         * Create button, creates a new skill
         * When a change has been made, a Save and Revert button are shown as enabled
         */

        listItemStyle.normal.background = Texture2D.blackTexture;   // Not that it shows up, awesome
        listItemStyle.normal.textColor  = Color.white;

        selectedItemStyle.normal.background = Texture2D.whiteTexture;
        selectedItemStyle.normal.textColor  = Color.blue;


        bool   newSkillClicked = false;
        string newSkillName    = string.Empty;

        if (GUI.Button(new Rect(30, 370, 100, 20), "New Skill"))
        {
            SkillDescriptor newSkill = new SkillDescriptor();
            newSkillName = newSkill.name;
            SkillDatabase.UpdateSkill(newSkill);
            newSkillClicked = true;
        }


        GUI.Box(new Rect(10, 50, 140, 300), string.Empty);
        GUI.Label(new Rect(10, 10, 40, 15), "Skills");
        GUI.SetNextControlName("txtSearch");
        if (newSkillClicked)
        {
            searchText = string.Empty;
        }
        searchText = GUI.TextField(new Rect(10, 30, 90, 15), searchText);
        if (GUI.GetNameOfFocusedControl() != "txtSearch" && searchText.Length == 0)
        {
            GUI.Label(new Rect(10, 30, 90, 15), "(Search)");
        }

        List <string> skillNames = SkillDatabase.FindSkills(searchText);

        skillListScrollPosition = GUI.BeginScrollView(new Rect(10, 50, 140, 300), skillListScrollPosition, new Rect(0, 0, 120, skillNames.Count * 20));

        if (newSkillClicked)
        {
            selectedSkillName = newSkillName;
        }

        string startSelectionName = selectedSkillName;

        int yButton = 10, skillIndex = 0;

        foreach (string skillName in skillNames)
        {
            if (GUI.Button(new Rect(5, yButton, 130, 15), skillName, selectedSkillName == skillName ? selectedItemStyle : listItemStyle))
            {
                selectedSkillName = skillName;
            }
            yButton += 20;
            skillIndex++;
        }

        if (startSelectionName != selectedSkillName)
        {
            EditorGUI.FocusTextInControl(null);
            Repaint();
        }

        selectedSkill = SkillDatabase.GetSkill(selectedSkillName);

        GUI.EndScrollView();


        GUI.Box(new Rect(160, 10, 700, 400), string.Empty);

        if (selectedSkill != null)
        {
            mainControlRectY = 20;
            // TODO: Set up the skill display itself, and wire up components to variables.
            // Then, create the save/load function. Going to be cool!
            string originalName = selectedSkill.name;
            selectedSkill.name = EditorGUI.TextField(MainControlRect(), "Name", selectedSkill.name);
            if (originalName != selectedSkill.name)
            {
                SkillDatabase.RenameSkill(originalName, selectedSkill);
                selectedSkillName = selectedSkill.name;
            }
            selectedSkill.displayText = EditorGUI.TextField(MainControlRect(), "Display Text", selectedSkill.displayText);
            selectedSkill.delay       = EditorGUI.FloatField(MainControlRect(), "Action Delay", selectedSkill.delay);
            //EditorGUI.LabelField(new Rect(130, y, 100, 15), "Targets");



            // The dance of the target options.

            // First, figure out what our default selection is - because it might forcibly change right after this.
            // Get the list of currently available flags, and use the selectedDefaultIndex value to figure out
            // which one is selected in the editor.
            List <CommandBase.Target> flags = new List <CommandBase.Target>();
            foreach (CommandBase.Target target in (CommandBase.Target[])System.Enum.GetValues(typeof(CommandBase.Target)))
            {
                if ((selectedSkill.targets & target) > 0)
                {
                    flags.Add(target);
                }
            }
            CommandBase.Target selectedDefaultTarget = CommandBase.Target.NONE;
            if (selectedDefaultIndex < flags.Count)
            {
                selectedDefaultTarget = flags[selectedDefaultIndex];
            }

            // Now show the targets enum flags field to pick up changes.
            selectedSkill.targets = (CommandBase.Target)(EditorGUI.EnumFlagsField(MainControlRect(), "Targets", selectedSkill.targets));

            // Now, re-fetch the list of available targets.
            flags.Clear();
            foreach (CommandBase.Target target in (CommandBase.Target[])System.Enum.GetValues(typeof(CommandBase.Target)))
            {
                if ((selectedSkill.targets & target) > 0)
                {
                    flags.Add(target);
                }
            }
            if (flags.Count > 0)
            {
                // Is our selected default value still in here? If so, make sure we're still pointing at it; otherwise, point at the first item in the list.
                if (flags.Contains(selectedDefaultTarget))
                {
                    selectedDefaultIndex = flags.IndexOf(selectedDefaultTarget);
                }
                else
                {
                    selectedDefaultIndex = 0;
                }

                // Now convert the flags to strings so we can display them in a popup.
                List <string> flagStrings = new List <string>();
                foreach (CommandBase.Target flag in flags)
                {
                    flagStrings.Add(flag.ToString());
                }
                selectedDefaultIndex = EditorGUI.Popup(MainControlRect(), "Default target", selectedDefaultIndex, flagStrings.ToArray());
                if (selectedDefaultIndex < flags.Count)
                {
                    selectedDefaultTarget = flags[selectedDefaultIndex];
                }
            }

            selectedSkill.isRetargetable = EditorGUI.Toggle(MainControlRect(), "Retargetable", selectedSkill.isRetargetable);

            mainControlRectY += 40;
            EditorGUI.LabelField(MainControlRect(), "Effects");

            EffectDescriptor killed = null;
            if (selectedSkill.effects != null)
            {
                foreach (EffectDescriptor effect in selectedSkill.effects)
                {
                    if (RenderEffectFieldWithDelete(effect))
                    {
                        // Deleted
                        killed = effect;
                    }
                }
                if (killed != null)
                {
                    selectedSkill.RemoveEffect(killed);
                }
            }
            EditorGUI.LabelField(new Rect(170, mainControlRectY, 100, 15), "Add effect type");

            List <string> effectNames = new List <string>();
            foreach (string key in effectsByName.Keys)
            {
                effectNames.Add(key);
            }

            selectedNewEffectType = EditorGUI.Popup(new Rect(280, mainControlRectY, 100, 15), selectedNewEffectType, effectNames.ToArray());
            if (GUI.Button(new Rect(390, mainControlRectY, 70, 15), "Add"))
            {
                EffectDescriptor newDescriptor = new EffectDescriptor();
                newDescriptor.effectType       = effectsByName[effectNames[selectedNewEffectType]];
                newDescriptor.effectExpression = string.Empty;
                selectedSkill.AddEffect(newDescriptor);
            }

            SkillDatabase.SaveSkills();
        }
    }