Full Code of arduano/Zenith-MIDI for AI

master 36f8ba3c06a6 cached
175 files
1.1 MB
251.6k tokens
652 symbols
1 requests
Download .txt
Showing preview only (1,159K chars total). Download the full file or copy to clipboard to get everything.
Repository: arduano/Zenith-MIDI
Branch: master
Commit: 36f8ba3c06a6
Files: 175
Total size: 1.1 MB

Directory structure:
gitextract_07bla4mi/

├── .angulardoc.json
├── .gitattributes
├── .gitignore
├── BMEngine/
│   ├── BufferByteReader.cs
│   ├── FastList.cs
│   ├── GLTextEngine.cs
│   ├── GLUtils.cs
│   ├── IPluginRender.cs
│   ├── MidiFile.cs
│   ├── MidiInfo.cs
│   ├── MidiTrack.cs
│   ├── NoteColorPalettePick.xaml
│   ├── NoteColorPalettePick.xaml.cs
│   ├── OpenTK.dll.config
│   ├── PluginUtils.cs
│   ├── Properties/
│   │   └── AssemblyInfo.cs
│   ├── RenderSettings.cs
│   ├── ScriptedCompile/
│   │   ├── ExtraUI.cs
│   │   └── IO.cs
│   ├── UI/
│   │   ├── BBinding.cs
│   │   ├── BetterCheckbox.xaml
│   │   ├── BetterCheckbox.xaml.cs
│   │   ├── BetterRadio.xaml
│   │   ├── BetterRadio.xaml.cs
│   │   ├── BetterSlider.xaml
│   │   ├── BetterSlider.xaml.cs
│   │   ├── Colors.xaml
│   │   ├── Converters.cs
│   │   ├── HexColorPicker.xaml
│   │   ├── HexColorPicker.xaml.cs
│   │   ├── InplaceConverter.cs
│   │   ├── ListBox.xaml
│   │   ├── Material.xaml
│   │   ├── NumberSelect.xaml
│   │   ├── NumberSelect.xaml.cs
│   │   ├── RippleEffectDecorator.cs
│   │   ├── Scrollbar.xaml
│   │   ├── ValueSlider.xaml
│   │   └── ValueSlider.xaml.cs
│   ├── ZenithEngine.csproj
│   └── packages.config
├── Black-Midi-Render/
│   ├── App.config
│   ├── GLPostbuffer.cs
│   ├── GLUtils.cs
│   ├── KDMAPI.cs
│   ├── Languages/
│   │   └── en/
│   │       └── window.xaml
│   ├── MainWindow.xaml
│   ├── MainWindow.xaml.cs
│   ├── OpenTK.dll.config
│   ├── Program.cs
│   ├── Properties/
│   │   ├── AssemblyInfo.cs
│   │   ├── Resources.Designer.cs
│   │   └── Resources.resx
│   ├── RenderWindow.cs
│   ├── Settings.cs
│   ├── Zenith.csproj
│   └── packages.config
├── ClassicRender/
│   ├── ClassicRender.csproj
│   ├── Languages/
│   │   └── en/
│   │       └── classic.xaml
│   ├── OpenTK.dll.config
│   ├── Properties/
│   │   ├── AssemblyInfo.cs
│   │   ├── Resources.Designer.cs
│   │   └── Resources.resx
│   ├── README.md
│   ├── Render.cs
│   ├── Settings.cs
│   ├── SettingsCtrl.xaml
│   ├── SettingsCtrl.xaml.cs
│   └── packages.config
├── FlatRender/
│   ├── FlatRender.csproj
│   ├── Languages/
│   │   └── en/
│   │       └── flat.xaml
│   ├── OpenTK.dll.config
│   ├── Properties/
│   │   ├── AssemblyInfo.cs
│   │   ├── Resources.Designer.cs
│   │   └── Resources.resx
│   ├── README.md
│   ├── Render.cs
│   ├── Settings.cs
│   ├── SettingsCtrl.xaml
│   ├── SettingsCtrl.xaml.cs
│   └── packages.config
├── LICENSE
├── MidiTrailRender/
│   ├── AuraSelect.xaml
│   ├── AuraSelect.xaml.cs
│   ├── Languages/
│   │   └── en/
│   │       └── miditrail.xaml
│   ├── MidiTrailRender.csproj
│   ├── OpenTK.dll.config
│   ├── ProfileManager.cs
│   ├── Properties/
│   │   ├── AssemblyInfo.cs
│   │   ├── Resources.Designer.cs
│   │   └── Resources.resx
│   ├── README.md
│   ├── Render.cs
│   ├── Settings.cs
│   ├── SettingsCtrl.xaml
│   ├── SettingsCtrl.xaml.cs
│   ├── Util.cs
│   └── packages.config
├── NoteCountRender/
│   ├── Languages/
│   │   └── en/
│   │       └── notecounter.xaml
│   ├── NoteCountRender.csproj
│   ├── OpenTK.dll.config
│   ├── Properties/
│   │   ├── AssemblyInfo.cs
│   │   ├── Resources.Designer.cs
│   │   └── Resources.resx
│   ├── README.md
│   ├── Render.cs
│   ├── Settings.cs
│   ├── SettingsCtrl.xaml
│   ├── SettingsCtrl.xaml.cs
│   └── packages.config
├── PFARender/
│   ├── .gitignore
│   ├── Languages/
│   │   └── en/
│   │       └── pfa.xaml
│   ├── OpenTK.dll.config
│   ├── PFARender.csproj
│   ├── Properties/
│   │   ├── AssemblyInfo.cs
│   │   ├── Resources.Designer.cs
│   │   └── Resources.resx
│   ├── README.md
│   ├── Render.cs
│   ├── Settings.cs
│   ├── SettingsCtrl.xaml
│   ├── SettingsCtrl.xaml.cs
│   └── packages.config
├── README-plugin.md
├── README.md
├── ScriptedRenderer/
│   ├── Languages/
│   │   └── en/
│   │       └── scripted.xaml
│   ├── OpenTK.dll.config
│   ├── Properties/
│   │   ├── AssemblyInfo.cs
│   │   ├── Resources.Designer.cs
│   │   └── Resources.resx
│   ├── Render.cs
│   ├── Script.cs
│   ├── ScriptedRender.csproj
│   ├── Settings.cs
│   ├── SettingsCtrl.xaml
│   ├── SettingsCtrl.xaml.cs
│   └── packages.config
├── TexturedRender/
│   ├── Languages/
│   │   └── en/
│   │       └── textured.xaml
│   ├── OpenTK.dll.config
│   ├── Pack.cs
│   ├── Properties/
│   │   ├── AssemblyInfo.cs
│   │   ├── Resources.Designer.cs
│   │   └── Resources.resx
│   ├── README.md
│   ├── Render.cs
│   ├── Resources/
│   │   └── pack.json
│   ├── Settings.cs
│   ├── SettingsCtrl.xaml
│   ├── SettingsCtrl.xaml.cs
│   ├── TexturedRender.csproj
│   └── packages.config
├── Zenith.sln
├── ZenithInstaller/
│   ├── App.config
│   ├── App.xaml
│   ├── App.xaml.cs
│   ├── FodyWeavers.xml
│   ├── FodyWeavers.xsd
│   ├── MainWindow.xaml
│   ├── MainWindow.xaml.cs
│   ├── Program.cs
│   ├── Properties/
│   │   ├── AssemblyInfo.cs
│   │   ├── Resources.Designer.cs
│   │   ├── Resources.resx
│   │   ├── Settings.Designer.cs
│   │   └── Settings.settings
│   ├── ZenithInstaller.csproj
│   ├── ZenithInstaller_nf5vy1mn_wpftmp.csproj
│   └── packages.config
├── ZenithShared/
│   ├── InstallFailedException.cs
│   ├── Properties/
│   │   └── AssemblyInfo.cs
│   ├── ZenithLanguages.cs
│   ├── ZenithShared.csproj
│   ├── ZenithUpdates.cs
│   └── packages.config
└── build.bat

================================================
FILE CONTENTS
================================================

================================================
FILE: .angulardoc.json
================================================
{
  "repoId": "132e1921-3d2f-40c3-9aad-ca5bf9141f7d",
  "lastSync": 0
}

================================================
FILE: .gitattributes
================================================
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto

###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs     diff=csharp

###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following 
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln       merge=binary
#*.csproj    merge=binary
#*.vbproj    merge=binary
#*.vcxproj   merge=binary
#*.vcproj    merge=binary
#*.dbproj    merge=binary
#*.fsproj    merge=binary
#*.lsproj    merge=binary
#*.wixproj   merge=binary
#*.modelproj merge=binary
#*.sqlproj   merge=binary
#*.wwaproj   merge=binary

###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg   binary
#*.png   binary
#*.gif   binary

###############################################################################
# diff behavior for common document formats
# 
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the 
# entries below.
###############################################################################
#*.doc   diff=astextplain
#*.DOC   diff=astextplain
#*.docx  diff=astextplain
#*.DOCX  diff=astextplain
#*.dot   diff=astextplain
#*.DOT   diff=astextplain
#*.pdf   diff=astextplain
#*.PDF   diff=astextplain
#*.rtf   diff=astextplain
#*.RTF   diff=astextplain


================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.

# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/

# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

# NUNIT
*.VisualState.xml
TestResult.xml

# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c

# DNX
project.lock.json
project.fragment.lock.json
artifacts/

*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc

# Chutzpah Test files
_Chutzpah*

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb

# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap

# TFS 2012 Local Workspace
$tf/

# Guidance Automation Toolkit
*.gpState

# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user

# JustCode is a .NET coding add-in
.JustCode

# TeamCity is a build add-in
_TeamCity*

# DotCover is a Code Coverage Tool
*.dotCover

# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*

# MightyMoose
*.mm.*
AutoTest.Net/

# Web workbench (sass)
.sass-cache/

# Installshield output folder
[Ee]xpress/

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish/

# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
#*.pubxml
*.publishproj

# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/

# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets

# Microsoft Azure Build Output
csx/
*.build.csdef

# Microsoft Azure Emulator
ecf/
rcf/

# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt

# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/

# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs

# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/

# RIA/Silverlight projects
Generated_Code/

# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm

# SQL Server files
*.mdf
*.ldf

# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings

# Microsoft Fakes
FakesAssemblies/

# GhostDoc plugin setting file
*.GhostDoc.xml

# Node.js Tools for Visual Studio
.ntvs_analysis.dat

# Visual Studio 6 build log
*.plg

# Visual Studio 6 workspace options file
*.opt

# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions

# Paket dependency manager
.paket/paket.exe
paket-files/

# FAKE - F# Make
.fake/

# JetBrains Rider
.idea/
*.sln.iml

# CodeRush
.cr/

# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc

cleanup.bat

bin
*/obj/*

build/

================================================
FILE: BMEngine/BufferByteReader.cs
================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ZenithEngine
{
    public class BufferByteReader
    {
        long pos;
        int buffersize;
        int bufferpos;
        int maxbufferpos;
        long streamstart;
        long streamlen;
        Stream stream;
        byte[] buffer;
        byte[] bufferNext;
        Task nextReader = null;

        public BufferByteReader(Stream stream, int buffersize, long streamstart, long streamlen)
        {
            if (buffersize > streamlen) buffersize = (int)streamlen;
            this.buffersize = buffersize;
            this.streamstart = streamstart;
            this.streamlen = streamlen;
            this.stream = stream;
            buffer = new byte[buffersize];
            bufferNext = new byte[buffersize];
            UpdateBuffer(pos, true);
        }

        void UpdateBuffer(long pos, bool first = false)
        {
            if (first)
            {
                nextReader = Task.Run(() =>
                {
                    lock (stream)
                    {
                        stream.Position = pos + streamstart;
                        stream.Read(bufferNext, 0, buffersize);
                    }
                });
            }
            nextReader.GetAwaiter().GetResult();
            Buffer.BlockCopy(bufferNext, 0, buffer, 0, buffersize);
            nextReader = Task.Run(() =>
            {
                lock (stream)
                {
                    stream.Position = pos + streamstart + buffersize;
                    stream.Read(bufferNext, 0, buffersize);
                }
            });
            nextReader.GetAwaiter().GetResult();
            //lock (stream)
            //{
            //    stream.Position = pos + streamstart;
            //    stream.Read(buffer, 0, buffersize);
            //}
            maxbufferpos = (int)Math.Min(streamlen - pos + 1, buffersize);
        }

        public long Location => pos;

        public int Pushback = -1;

        public byte Read()
        {
            if (Pushback != -1)
            {
                byte _b = (byte)Pushback;
                Pushback = -1;
                return _b;
            }
            byte b = buffer[bufferpos++];
            if (bufferpos < maxbufferpos) return b;
            else if (bufferpos >= buffersize)
            {
                pos += bufferpos;
                bufferpos = 0;
                UpdateBuffer(pos);
                return b;
            }
            else throw new IndexOutOfRangeException();
        }

        public byte ReadFast()
        {
            byte b = buffer[bufferpos++];
            if (bufferpos < maxbufferpos) return b;
            else if (bufferpos >= buffersize)
            {
                pos += bufferpos;
                bufferpos = 0;
                UpdateBuffer(pos);
                return b;
            }
            else throw new IndexOutOfRangeException();
        }

        public void Reset()
        {
            pos = 0;
            bufferpos = 0;
            UpdateBuffer(pos, true);
        }

        public void Skip(int count)
        {
            for (int i = 0; i < count; i++)
            {
                if(Pushback != -1)
                {
                    Pushback = -1;
                    continue;
                }
                bufferpos++;
                if (bufferpos < maxbufferpos) continue;
                if (bufferpos >= buffersize)
                {
                    pos += bufferpos;
                    bufferpos = 0;
                    UpdateBuffer(pos);
                }
                else throw new IndexOutOfRangeException();
            }
        }

        public void Dispose()
        {
            buffer = null;
        }
    }
}


================================================
FILE: BMEngine/FastList.cs
================================================
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ZenithEngine
{
    public class FastList<T> : IEnumerable<T>
    {
        private class ListItem
        {
            public ListItem Next;
            public T item;
        }

        private ListItem root = new ListItem();
        private ListItem last = null;

        public T First
        {
            get
            {
                if (root.Next != null) return root.Next.item;
                else return default(T);
            }
        }
        public class Iterator
        {
            FastList<T> _ilist;

            private ListItem prev;
            private ListItem curr;

            internal Iterator(FastList<T> ll)
            {
                _ilist = ll;
                Reset();
            }

            public bool MoveNext(out T v)
            {
                ListItem ll = curr.Next;

                if (ll == null)
                {
                    v = default(T);
                    _ilist.last = curr;
                    return false;
                }

                v = ll.item;

                prev = curr;
                curr = ll;

                return true;
            }

            public void Remove()
            {
                if (_ilist.last.Equals(curr)) _ilist.last = prev;
                prev.Next = curr.Next;
            }

            public void Insert(T item)
            {
                var i = new ListItem()
                {
                    item = item,
                    Next = curr
                };
                if (prev == null)
                    _ilist.root.Next = i;
                else
                    prev.Next = i;
                //if (curr.Equals(_ilist.last))
                //{
                //    _ilist.last = curr;
                //}
            }

            public void Reset()
            {
                this.prev = null;
                this.curr = _ilist.root;
            }
        }

        public class FastIterator : IEnumerator<T>
        {
            FastList<T> _ilist;

            private ListItem curr;

            internal FastIterator(FastList<T> ll)
            {
                _ilist = ll;
                Reset();
            }

            public object Current => curr.item;

            T IEnumerator<T>.Current => curr.item;

            public void Dispose()
            {

            }

            public bool MoveNext()
            {
                try
                {
                    curr = curr.Next;

                    return curr != null;
                }
                catch { return false; }
            }

            public void Reset()
            {
                this.curr = _ilist.root;
            }
        }

        public void Add(T item)
        {
            ListItem li = new ListItem();
            li.item = item;

            if (root.Next != null && last != null)
            {
                while (last.Next != null) last = last.Next;
                last.Next = li;
            }
            else
                root.Next = li;

            last = li;
        }

        public T Pop()
        {
            ListItem el = root.Next;
            root.Next = el.Next;
            return el.item;
        }

        public Iterator Iterate()
        {
            return new Iterator(this);
        }

        public bool ZeroLen => root.Next == null;

        public IEnumerator<T> FastIterate()
        {
            return new FastIterator(this);
        }

        public void Unlink()
        {
            root.Next = null;
            last = null;
        }

        public int Count()
        {
            int cnt = 0;

            ListItem li = root.Next;
            while (li != null)
            {
                cnt++;
                li = li.Next;
            }

            return cnt;
        }

        public bool Any()
        {
            return root.Next != null;
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return FastIterate();
        }

        public IEnumerator<T> GetEnumerator()
        {
            return FastIterate();
        }
    }
}


================================================
FILE: BMEngine/GLTextEngine.cs
================================================
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using OpenTK.Graphics.OpenGL;
using OpenTK.Graphics;
using OpenTK;
using System.Drawing.Imaging;
using Size = System.Drawing.Size;

namespace ZenithEngine
{
    public class GLTextEngine
    {
        #region Shaders
        string textShaderVert = @"#version 330 compatibility

layout(location = 0) in vec2 position;
layout(location = 1) in vec2 uv;

uniform mat4 viewmat;
uniform vec4 Col;

out vec2 UV;
out vec4 Color;

void main()
{
    gl_Position = viewmat * vec4(position.x, position.y, 0, 1.0f);
    UV = uv;
    Color = Col;
}
";
        string textShaderFrag = @"#version 330 compatibility

in vec2 UV;
in vec4 Color;

out vec4 color;

uniform sampler2D textureSampler;

void main()
{
    float mask = texture2D( textureSampler, UV ).y;
    color = vec4(1, 1, 1, mask) * Color;
}
";
        #endregion

        int charMapTex;
        Size mapCharSize;
        SizeF[] charSizes;

        int textShader;

        int uniformMatrix;
        int uniformColor;

        int vertexBufferID;
        int uvBufferID;

        int quadBufferLength = 2048 * 2;
        double[] quadVertexbuff;
        double[] quaduvbuff;
        int quadBufferPos = 0;

        int indexBufferId;
        uint[] indexes = new uint[2048 * 4 * 6];

        public void Dispose()
        {
            GL.DeleteBuffers(3, new int[] { vertexBufferID });
            GL.DeleteProgram(textShader);
            GL.DeleteTexture(charMapTex);
        }

        public string Font { get; private set; } = "";
        public int FontSize { get; private set; } = -1;

        public GLTextEngine()
        {
            int _vertexObj = GL.CreateShader(ShaderType.VertexShader);
            int _fragObj = GL.CreateShader(ShaderType.FragmentShader);
            int statusCode;
            string info;

            GL.ShaderSource(_vertexObj, textShaderVert);
            GL.CompileShader(_vertexObj);
            info = GL.GetShaderInfoLog(_vertexObj);
            GL.GetShader(_vertexObj, ShaderParameter.CompileStatus, out statusCode);
            if (statusCode != 1) throw new ApplicationException(info);

            GL.ShaderSource(_fragObj, textShaderFrag);
            GL.CompileShader(_fragObj);
            info = GL.GetShaderInfoLog(_fragObj);
            GL.GetShader(_fragObj, ShaderParameter.CompileStatus, out statusCode);
            if (statusCode != 1) throw new ApplicationException(info);

            textShader = GL.CreateProgram();
            GL.AttachShader(textShader, _fragObj);
            GL.AttachShader(textShader, _vertexObj);
            GL.LinkProgram(textShader);

            quadVertexbuff = new double[quadBufferLength * 8];
            quaduvbuff = new double[quadBufferLength * 8];

            GL.GenBuffers(1, out vertexBufferID);
            GL.GenBuffers(1, out uvBufferID);
            for (uint i = 0; i < indexes.Length / 6; i++)
            {
                indexes[i * 6 + 0] = i * 4 + 0;
                indexes[i * 6 + 1] = i * 4 + 1;
                indexes[i * 6 + 2] = i * 4 + 3;
                indexes[i * 6 + 3] = i * 4 + 1;
                indexes[i * 6 + 4] = i * 4 + 3;
                indexes[i * 6 + 5] = i * 4 + 2;
            }

            GL.GenBuffers(1, out indexBufferId);
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, indexBufferId);
            GL.BufferData(
                BufferTarget.ElementArrayBuffer,
                (IntPtr)(indexes.Length * 4),
                indexes,
                BufferUsageHint.StaticDraw);

            uniformMatrix = GL.GetUniformLocation(textShader, "viewmat");
            uniformColor = GL.GetUniformLocation(textShader, "Col");

            charMapTex = GL.GenTexture();
        }

        public void SetFont(string font, int size)
        {
            var bitmap = GenerateCharacters(size, font, out mapCharSize, out charSizes);
            loadImage(bitmap, charMapTex);
            bitmap.Dispose();
            Font = font;
            FontSize = size;
        }

        public void SetFont(string font, int size, string charmap)
        {
            Characters = charmap;
            SetFont(font, size);
        }

        public void SetFont(string font, System.Drawing.FontStyle fontStyle, int size)
        {
            var bitmap = GenerateCharacters(size, font, fontStyle, out mapCharSize, out charSizes);
            loadImage(bitmap, charMapTex);
            bitmap.Dispose();
            Font = font;
            FontSize = size;
        }

        public void SetFont(string font, System.Drawing.FontStyle fontStyle, int size, string charmap)
        {
            Characters = charmap;
            SetFont(font, fontStyle, size);
        }

        void loadImage(Bitmap image, int texID)
        {
            GL.BindTexture(TextureTarget.Texture2D, texID);
            BitmapData data = image.LockBits(new System.Drawing.Rectangle(0, 0, image.Width, image.Height),
                ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,
                OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);

            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);

            image.UnlockBits(data);
        }

        public void Render(string text, Matrix4 transform, Color4 color)
        {
            //GL.Enable(EnableCap.Blend);
            //GL.EnableClientState(ArrayCap.VertexArray);
            //GL.EnableClientState(ArrayCap.ColorArray);
            //GL.EnableClientState(ArrayCap.TextureCoordArray);
            //GL.Enable(EnableCap.Texture2D);

            //GL.EnableVertexAttribArray(0);
            //GL.EnableVertexAttribArray(1);

            //GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);

            GL.UseProgram(textShader);
            GL.ActiveTexture(TextureUnit.Texture0);
            GL.BindTexture(TextureTarget.Texture2D, charMapTex);

            GL.Uniform4(uniformColor, color);
            GL.UniformMatrix4(uniformMatrix, false, ref transform);

            quadBufferPos = 0;
            Vector2 curpos = new Vector2(0, 0);

            int charImHeight = (Characters.Length - (Characters.Length % charImWidth)) / charImWidth + 1;
            double charwidth = 1.0 / charImWidth;
            double charheight = 1.0 / charImHeight;

            foreach (char c in text)
            {
                if (c == '\n')
                {
                    curpos.Y += mapCharSize.Height;
                    curpos.X = 0;
                }
                if (c == ' ')
                {
                    curpos.X += mapCharSize.Width / 4.0f;
                }
                if (!Characters.Contains(c)) continue;
                var chari = Characters.IndexOf(c);
                var sz = charSizes[chari];
                int charix = chari % charImWidth;
                int chariy = (chari - charix) / charImWidth;
                double sx = charwidth * charix;
                double ex = sx + charSizes[chari].Width / mapCharSize.Width * charwidth;
                double sy = charheight * chariy;
                double ey = sy + charSizes[chari].Height / mapCharSize.Height * charheight;

                float padding = mapCharSize.Width / 8f;
                sz.Width -= padding * 2;
                Vector2 endpos = curpos + new Vector2(sz.Width, sz.Height);

                int pos = quadBufferPos * 8;
                quadVertexbuff[pos++] = (curpos.X - padding);
                quadVertexbuff[pos++] = curpos.Y;
                quadVertexbuff[pos++] = (curpos.X - padding);
                quadVertexbuff[pos++] = endpos.Y;
                quadVertexbuff[pos++] = (endpos.X + padding);
                quadVertexbuff[pos++] = endpos.Y;
                quadVertexbuff[pos++] = (endpos.X + padding);
                quadVertexbuff[pos++] = curpos.Y;

                curpos.X += sz.Width;

                pos = quadBufferPos * 8;
                quaduvbuff[pos++] = sx;
                quaduvbuff[pos++] = sy;
                quaduvbuff[pos++] = sx;
                quaduvbuff[pos++] = ey;
                quaduvbuff[pos++] = ex;
                quaduvbuff[pos++] = ey;
                quaduvbuff[pos++] = ex;
                quaduvbuff[pos++] = sy;
                //quaduvbuff[pos++] = 0;
                //quaduvbuff[pos++] = 0;
                //quaduvbuff[pos++] = 1;
                //quaduvbuff[pos++] = 0;
                //quaduvbuff[pos++] = 1;
                //quaduvbuff[pos++] = 1;
                //quaduvbuff[pos++] = 0;
                //quaduvbuff[pos++] = 1;
                quadBufferPos++;
                FlushQuadBuffer();
            }
            FlushQuadBuffer(false);

            //GL.Disable(EnableCap.Blend);
            //GL.Disable(EnableCap.Texture2D);
            //GL.DisableClientState(ArrayCap.VertexArray);
            //GL.DisableClientState(ArrayCap.ColorArray);
            //GL.DisableClientState(ArrayCap.TextureCoordArray);

            //GL.DisableVertexAttribArray(0);
            //GL.DisableVertexAttribArray(1);
        }

        public SizeF GetBoundBox(string text)
        {
            Vector2 curpos = new Vector2(0, 0);
            int rows = 1;
            float maxWidth = 0;
            float padding = mapCharSize.Width / 8f;
            foreach (char c in text)
            {
                if (c == '\n')
                {
                    curpos.X = 0;
                    rows++;
                }
                if (!Characters.Contains(c)) continue;
                var chari = Characters.IndexOf(c);
                var sz = charSizes[chari];
                sz.Width -= padding * 2;
                Vector2 endpos = curpos + new Vector2(sz.Width, sz.Height);
                curpos.X += sz.Width;
                if (curpos.X > maxWidth) maxWidth = curpos.X;
            }
            return new SizeF(maxWidth + padding * 2, mapCharSize.Height * rows);
        }

        void FlushQuadBuffer(bool check = true)
        {
            if (quadBufferPos < quadBufferLength && check) return;
            if (quadBufferPos == 0) return;
            GL.BindBuffer(BufferTarget.ArrayBuffer, vertexBufferID);
            GL.BufferData(
                BufferTarget.ArrayBuffer,
                (IntPtr)(quadVertexbuff.Length * 8),
                quadVertexbuff,
                BufferUsageHint.StaticDraw);
            GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Double, false, 16, 0);
            GL.BindBuffer(BufferTarget.ArrayBuffer, uvBufferID);
            GL.BufferData(
                BufferTarget.ArrayBuffer,
                (IntPtr)(quaduvbuff.Length * 8),
                quaduvbuff,
                BufferUsageHint.StaticDraw);
            GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Double, false, 16, 0);
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, indexBufferId);
            GL.IndexPointer(IndexPointerType.Int, 1, 0);
            GL.DrawElements(PrimitiveType.Triangles, quadBufferPos * 6, DrawElementsType.UnsignedInt, IntPtr.Zero);
            quadBufferPos = 0;
        }

        private string Characters = @" qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789µ§½!""#¤%&/()=?^*@£€${[]}\~¨'-_.:,;<>|°©®±¥";
        private const int charImWidth = 20;

        public Bitmap GenerateCharacters(int fontSize, string fontName, out Size charSize, out SizeF[] charSizes)
        {
            return GenerateCharacters(fontSize, fontName, System.Drawing.FontStyle.Regular, out charSize, out charSizes);
        }

        public Bitmap GenerateCharacters(int fontSize, string fontName, System.Drawing.FontStyle fontStyle, out Size charSize, out SizeF[] charSizes)
        {
            charSizes = new SizeF[Characters.Length];
            var characters = new List<Bitmap>();
            using (var font = new Font(fontName, fontSize, fontStyle))
            {
                for (int i = 0; i < Characters.Length; i++)
                {
                    var charBmp = GenerateCharacter(font, Characters[i]);
                    charSizes[i] = GetSize(font, Characters[i]);
                    characters.Add(charBmp);
                }
                charSize = new Size(characters.Max(x => x.Width), characters.Max(x => x.Height));

                var charMap = new Bitmap(charSize.Width * charImWidth, charSize.Height * ((characters.Count - (characters.Count % charImWidth)) / charImWidth + 1));
                using (var gfx = Graphics.FromImage(charMap))
                {
                    gfx.FillRectangle(Brushes.Black, 0, 0, charMap.Width, charMap.Height);
                    for (int i = 0; i < characters.Count; i++)
                    {
                        var c = characters[i];
                        int x = i % charImWidth;
                        int y = (i - x) / charImWidth;
                        gfx.DrawImageUnscaled(c, x * charSize.Width, y * charSize.Height);

                        c.Dispose();
                    }
                }
                return charMap;
            }
        }

        private Bitmap GenerateCharacter(Font font, char c)
        {
            var size = GetSize(font, c);
            var bmp = new Bitmap((int)size.Width, (int)size.Height);
            using (var gfx = Graphics.FromImage(bmp))
            {
                gfx.FillRectangle(Brushes.Black, 0, 0, bmp.Width, bmp.Height);
                gfx.DrawString(c.ToString(), font, Brushes.White, 0, 0);
            }
            return bmp;
        }
        private SizeF GetSize(Font font, char c)
        {
            using (var bmp = new Bitmap(512, 512))
            {
                using (var gfx = Graphics.FromImage(bmp))
                {
                    return gfx.MeasureString(c.ToString(), font);
                }
            }
        }
    }
}


================================================
FILE: BMEngine/GLUtils.cs
================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenTK.Graphics.OpenGL;

namespace ZenithEngine
{
    public static class GLUtils
    {
        public static int MakeShaderProgram(string name)
        {
            int _vertexObj = GL.CreateShader(ShaderType.VertexShader);
            int _fragObj = GL.CreateShader(ShaderType.FragmentShader);
            int statusCode;
            string info;

            GL.ShaderSource(_vertexObj, File.ReadAllText("Shaders\\" + name + ".vert"));
            GL.CompileShader(_vertexObj);
            info = GL.GetShaderInfoLog(_vertexObj);
            GL.GetShader(_vertexObj, ShaderParameter.CompileStatus, out statusCode);
            if (statusCode != 1) throw new ApplicationException(info);

            GL.ShaderSource(_fragObj, File.ReadAllText("Shaders\\" + name + ".frag"));
            GL.CompileShader(_fragObj);
            info = GL.GetShaderInfoLog(_fragObj);
            GL.GetShader(_fragObj, ShaderParameter.CompileStatus, out statusCode);
            if (statusCode != 1) throw new ApplicationException(info);

            int shader = GL.CreateProgram();
            GL.AttachShader(shader, _fragObj);
            GL.AttachShader(shader, _vertexObj);
            GL.LinkProgram(shader);
            return shader;
        }

        public static int MakePostShaderProgram(string name)
        {
            int _vertexObj = GL.CreateShader(ShaderType.VertexShader);
            int _fragObj = GL.CreateShader(ShaderType.FragmentShader);
            int statusCode;
            string info;

            GL.ShaderSource(_vertexObj, File.ReadAllText("Shaders\\Post\\post.vert"));
            GL.CompileShader(_vertexObj);
            info = GL.GetShaderInfoLog(_vertexObj);
            GL.GetShader(_vertexObj, ShaderParameter.CompileStatus, out statusCode);
            if (statusCode != 1) throw new ApplicationException(info);

            GL.ShaderSource(_fragObj, File.ReadAllText("Shaders\\Post\\" + name + ".frag"));
            GL.CompileShader(_fragObj);
            info = GL.GetShaderInfoLog(_fragObj);
            GL.GetShader(_fragObj, ShaderParameter.CompileStatus, out statusCode);
            if (statusCode != 1) throw new ApplicationException(info);

            int shader = GL.CreateProgram();
            GL.AttachShader(shader, _fragObj);
            GL.AttachShader(shader, _vertexObj);
            GL.LinkProgram(shader);
            return shader;
        }

        public static void GenFrameBufferTexture(int width, int height, out int fbuffer, out int rtexture)
        {
            fbuffer = GL.GenFramebuffer();
            GL.BindFramebuffer(FramebufferTarget.Framebuffer, fbuffer);
            rtexture = GL.GenTexture();
            GL.BindTexture(TextureTarget.Texture2D, rtexture);
            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0, PixelFormat.Rgba, PixelType.Byte, (IntPtr)0);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
            GL.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, rtexture, 0);
            if (GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer) != FramebufferErrorCode.FramebufferComplete) throw new Exception();
        }

        public static void GenFrameBufferTexture3d(int width, int height, out int fbuffer, out int rtexture, out int depthrenderbuffer)
        {
            fbuffer = GL.GenFramebuffer();
            GL.BindFramebuffer(FramebufferTarget.Framebuffer, fbuffer);
            rtexture = GL.GenTexture();
            GL.BindTexture(TextureTarget.Texture2D, rtexture);
            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0, PixelFormat.Rgba, PixelType.Byte, (IntPtr)0);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
                depthrenderbuffer = GL.GenRenderbuffer();
                GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, depthrenderbuffer);
                GL.RenderbufferStorage(RenderbufferTarget.Renderbuffer, RenderbufferStorage.DepthComponent, width, height);
                GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, RenderbufferTarget.Renderbuffer, depthrenderbuffer);

            GL.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, rtexture, 0);
            if (GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer) != FramebufferErrorCode.FramebufferComplete) throw new Exception();
        }
    }
}


================================================
FILE: BMEngine/IPluginRender.cs
================================================
using OpenTK.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Media;

namespace ZenithEngine
{
    public interface IPluginRender : IDisposable
    {
        string Name { get; }
        string Description { get; }
        bool Initialized { get; }
        ImageSource PreviewImage { get; }
        bool ManualNoteDelete { get; }
        double NoteCollectorOffset { get; }

        NoteColor[][] NoteColors { set; }
        double Tempo { set; }
        
        MidiInfo CurrentMidi { set; }

        string LanguageDictName { get; }

        double NoteScreenTime { get; }
        long LastNoteCount { get; }
        Control SettingsControl { get; }

        void Init();
        void RenderFrame(FastList<Note> notes, double midiTime, int finalCompositeBuff);
        void ReloadTrackColors();
    }
}


================================================
FILE: BMEngine/MidiFile.cs
================================================
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ZenithEngine
{
    public class MidiFile : IDisposable
    {
        Stream MidiFileReader;
        public ushort division;
        public int trackcount;
        public ushort format;

        public int zerothTempo = 500000;

        List<long> trackBeginnings = new List<long>();
        List<uint> trackLengths = new List<uint>();

        public MidiTrack[] tracks;

        public MidiInfo info;

        public long maxTrackTime;
        public long noteCount = 0;

        public long currentSyncTime = 0;
        public double currentFlexSyncTime = 0;

        public FastList<Note> globalDisplayNotes = new FastList<Note>();
        public FastList<Tempo> globalTempoEvents = new FastList<Tempo>();
        public FastList<ColorChange> globalColorEvents = new FastList<ColorChange>();
        public FastList<PlaybackEvent> globalPlaybackEvents = new FastList<PlaybackEvent>();

        public double tempoTickMultiplier = 0;

        public int unendedTracks = 0;

        RenderSettings settings;

        public MidiFile(string filename, RenderSettings settings)
        {
            this.settings = settings;
            MidiFileReader = new StreamReader(filename).BaseStream;
            ParseHeaderChunk();
            while (MidiFileReader.Position < MidiFileReader.Length)
            {
                ParseTrackChunk();
            }
            tracks = new MidiTrack[trackcount];

            Console.WriteLine("Loading tracks into memory");
            info = new MidiInfo();
            LoadAndParseAll(true);
            Console.WriteLine("Loaded!");
            Console.WriteLine("Note count: " + noteCount);
            unendedTracks = trackcount;

            info.division = division;
            info.firstTempo = zerothTempo;
            info.noteCount = noteCount;
            info.tickLength = maxTrackTime;
            info.trackCount = trackcount;
            tempoTickMultiplier = (double)division / 500000 * 1000;
        }

        void AssertText(string text)
        {
            foreach (char c in text)
            {
                if (MidiFileReader.ReadByte() != c)
                {
                    throw new Exception("Corrupt chunk headers");
                }
            }
        }

        uint ReadInt32()
        {
            uint length = 0;
            for (int i = 0; i != 4; i++)
                length = (uint)((length << 8) | (byte)MidiFileReader.ReadByte());
            return length;
        }

        ushort ReadInt16()
        {
            ushort length = 0;
            for (int i = 0; i != 2; i++)
                length = (ushort)((length << 8) | (byte)MidiFileReader.ReadByte());
            return length;
        }

        void ParseHeaderChunk()
        {
            AssertText("MThd");
            uint length = ReadInt32();
            if (length != 6) throw new Exception("Header chunk size isn't 6");
            format = ReadInt16();
            ReadInt16();
            division = ReadInt16();
            if (format == 2) throw new Exception("Midi type 2 not supported");
            if (division < 0) throw new Exception("Division < 0 not supported");
        }

        void ParseTrackChunk()
        {
            AssertText("MTrk");
            uint length = ReadInt32();
            trackBeginnings.Add(MidiFileReader.Position);
            trackLengths.Add(length);
            MidiFileReader.Position += length;
            trackcount++;
            Console.WriteLine("Track " + trackcount + ", Size " + length);
        }


        public bool ParseUpTo(double targetTime)
        {
            lock (globalDisplayNotes)
            {
                if (settings.timeBasedNotes)
                    for (; currentFlexSyncTime <= targetTime && settings.running; currentSyncTime++)
                    {
                        currentFlexSyncTime += 1 / tempoTickMultiplier;
                        int ut = 0;
                        for (int trk = 0; trk < trackcount; trk++)
                        {
                            var t = tracks[trk];
                            if (!t.trackEnded)
                            {
                                ut++;
                                t.Step(currentSyncTime);
                            }
                        }
                        unendedTracks = ut;
                    }
                else
                    for (; currentSyncTime <= targetTime && settings.running; currentSyncTime++)
                    {
                        int ut = 0;
                        for (int trk = 0; trk < trackcount; trk++)
                        {
                            var t = tracks[trk];
                            if (!t.trackEnded)
                            {
                                ut++;
                                t.Step(currentSyncTime);
                            }
                        }
                        unendedTracks = ut;
                    }
                foreach (var t in tracks)
                {
                    if (!t.trackEnded) return true;
                }
                return false;
            }
        }

        public void LoadAndParseAll(bool useBufferStream = false)
        {
            long[] tracklens = new long[tracks.Length];
            int p = 0;
            List<FastList<Tempo>> tempos = new List<FastList<Tempo>>();
            Parallel.For(0, tracks.Length, (i) =>
               {
                   var reader = new BufferByteReader(MidiFileReader, settings.maxTrackBufferSize, trackBeginnings[i], trackLengths[i]);
                   tracks[i] = new MidiTrack(i, reader, this, settings);
                   var t = tracks[i];
                   while (!t.trackEnded)
                   {
                       try
                       {
                           t.ParseNextEventFast();
                       }
                       catch
                       {
                           break;
                       }
                   }
                   noteCount += t.noteCount;
                   tracklens[i] = t.trackTime;
                   if (t.foundTimeSig != null)
                       info.timeSig = t.foundTimeSig;
                   if (t.zerothTempo != -1)
                   {
                       zerothTempo = t.zerothTempo;
                   }
                   lock (tempos) tempos.Add(t.TempoEvents);
                   t.Reset();
                   Console.WriteLine("Loaded track " + p++ + "/" + tracks.Length);
                   GC.Collect();
               });
            maxTrackTime = tracklens.Max();
            Console.WriteLine("Processing Tempos");
            LinkedList<Tempo> Tempos = new LinkedList<Tempo>();
            var iters = tempos.Select(t => t.GetEnumerator()).ToArray();
            bool[] unended = new bool[iters.Length];
            for (int i = 0; i < iters.Length; i++) unended[i] = iters[i].MoveNext();
            while (true)
            {
                long smallest = 0;
                bool first = true;
                int id = 0;
                for (int i = 0; i < iters.Length; i++)
                {
                    if (!unended[i]) continue;
                    if (first)
                    {
                        smallest = iters[i].Current.pos;
                        id = i;
                        first = false;
                        continue;
                    }
                    if (iters[i].Current.pos < smallest)
                    {
                        smallest = iters[i].Current.pos;
                        id = i;
                    }
                }
                if (first)
                {
                    break;
                }
                Tempos.AddLast(iters[id].Current);
                unended[id] = iters[id].MoveNext();
            }

            double time = 0;
            long ticks = maxTrackTime;
            double multiplier = ((double)500000 / division) / 1000000;
            long lastt = 0;
            foreach (var t in Tempos)
            {
                var offset = t.pos - lastt;
                time += offset * multiplier;
                ticks -= offset;
                lastt = t.pos;
                multiplier = ((double)t.tempo / division) / 1000000;
            }

            time += ticks * multiplier;

            info.secondsLength = time;

            maxTrackTime = tracklens.Max();
            unendedTracks = trackcount;
        }

        public void SetZeroColors()
        {
            foreach (var t in tracks) t.SetZeroColors();
        }

        public void Reset()
        {
            globalDisplayNotes.Unlink();
            globalTempoEvents.Unlink();
            globalColorEvents.Unlink();
            globalPlaybackEvents.Unlink();
            currentSyncTime = 0;
            currentFlexSyncTime = 0;
            unendedTracks = trackcount;
            tempoTickMultiplier = (double)division / 500000 * 1000;
            foreach (var t in tracks) t.Reset();
        }

        public void Dispose()
        {
            foreach (var t in tracks) t.Dispose();
            MidiFileReader.Dispose();
        }
    }
}


================================================
FILE: BMEngine/MidiInfo.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ZenithEngine
{
    public class MidiInfo
    {
        public int division;
        public int trackCount;
        public long noteCount;
        public int firstTempo;
        public long tickLength;
        public double secondsLength;
        public TimeSignature timeSig = new TimeSignature() { numerator = 4, denominator = 4 };
    }
}


================================================
FILE: BMEngine/MidiTrack.cs
================================================
using OpenTK.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ZenithEngine
{
    public class Note
    {
        public double start;
        public double end;
        public bool hasEnded;
        public byte channel;
        public byte key;
        public byte vel;
        public bool delete = false;
        public object meta = null;
        public int track;
        public NoteColor color;
    }

    public class NoteColor
    {
        public Color4 left;
        public Color4 right;
        public bool isDefault = true;
    }

    public struct PlaybackEvent
    {
        public double pos;
        public int val;
    }

    public class Tempo
    {
        public long pos;
        public int tempo;
    }

    public class ColorChange
    {
        public double pos;
        public Color4 col1;
        public Color4 col2;
        public byte channel;
        public MidiTrack track;
    }

    public class TimeSignature
    {
        public int numerator { get; internal set; }
        public int denominator { get; internal set; }
    }

    public class MidiTrack : IDisposable
    {
        public int trackID;

        public bool trackEnded = false;

        public long trackTime = 0;
        public long lastStepTime = 0;
        public double trackFlexTime = 0;
        public long noteCount = 0;
        public int zerothTempo = -1;

        byte channelPrefix = 0;

        MidiFile midi;

        public FastList<Note>[] UnendedNotes = null;
        public LinkedList<Tempo> Tempos = new LinkedList<Tempo>();

        FastList<Note> globalDisplayNotes;
        FastList<Tempo> globalTempoEvents;
        FastList<ColorChange> globalColorEvents;
        FastList<PlaybackEvent> globalPlaybackEvents;

        public NoteColor[] trkColors;
        public NoteColor[] zeroTickTrkColors;

        public TimeSignature foundTimeSig = null;

        bool readDelta = false;

        BufferByteReader reader;

        public void Reset()
        {
            if (UnendedNotes != null) foreach (var un in UnendedNotes) un.Unlink();
            reader.Reset();
            ResetColors();
            trackTime = 0;
            lastStepTime = 0;
            trackFlexTime = 0;
            trackEnded = false;
            readDelta = false;
            channelPrefix = 0;
            noteCount = 0;
            UnendedNotes = null;
        }

        public void ResetColors()
        {
            trkColors = new NoteColor[16];
            for (int i = 0; i < 16; i++)
            {
                trkColors[i] = new NoteColor() { left = Color4.Gray, right = Color4.Gray, isDefault = true };
            }
        }

        public void SetZeroColors()
        {
            for (int i = 0; i < 16; i++)
            {
                if (zeroTickTrkColors[i] != null)
                {
                    trkColors[i].left = zeroTickTrkColors[i].left;
                    trkColors[i].right = zeroTickTrkColors[i].right;
                }
            }
        }

        RenderSettings settings;
        public MidiTrack(int id, BufferByteReader reader, MidiFile file, RenderSettings settings)
        {
            this.settings = settings;
            globalDisplayNotes = file.globalDisplayNotes;
            globalTempoEvents = file.globalTempoEvents;
            globalColorEvents = file.globalColorEvents;
            globalPlaybackEvents = file.globalPlaybackEvents;
            midi = file;
            this.reader = reader;
            trackID = id;
            ResetColors();

            zeroTickTrkColors = new NoteColor[16];
            for (int i = 0; i < 16; i++) zeroTickTrkColors[i] = null;
        }

        long ReadVariableLen()
        {
            byte c;
            int val = 0;
            for (int i = 0; i < 4; i++)
            {
                c = reader.ReadFast();
                if (c > 0x7F)
                {
                    val = (val << 7) | (c & 0x7F);
                }
                else
                {
                    val = val << 7 | c;
                    return val;
                }
            }
            return val;
        }

        public void Step(long time)
        {
            timebase = settings.timeBasedNotes;
            trackFlexTime += (time - lastStepTime) / midi.tempoTickMultiplier;
            lastStepTime = time;
            try
            {
                if (time >= trackTime)
                {
                    if (readDelta)
                    {
                        long d = trackTime;
                        do
                        {
                            ParseNextEvent();
                            if (trackEnded) return;
                            trackTime += ReadVariableLen();
                            readDelta = true;
                        }
                        while (trackTime == d);
                    }
                    else
                    {
                        if (trackEnded) return;
                        trackTime += ReadVariableLen();
                        readDelta = true;
                    }
                }
            }
            catch (IndexOutOfRangeException)
            {
                EndTrack();
            }
        }

        void EndTrack()
        {
            trackEnded = true;
            if (UnendedNotes != null)
                foreach (var un in UnendedNotes)
                {
                    var iter = un.Iterate();
                    Note n;
                    while (iter.MoveNext(out n))
                    {
                        n.end = trackTime;
                        n.hasEnded = true;
                    }
                    un.Unlink();
                }
            UnendedNotes = null;
        }

        byte prevCommand = 0;
        bool timebase = false;
        public void ParseNextEvent()
        {
            try
            {
                if (!readDelta)
                {
                    trackTime += ReadVariableLen();
                }
                readDelta = false;

                double time = trackTime;
                if (timebase)
                    time = trackFlexTime;

                byte command = reader.ReadFast();
                if (command < 0x80)
                {
                    reader.Pushback = command;
                    command = prevCommand;
                }
                prevCommand = command;
                byte comm = (byte)(command & 0b11110000);
                if (comm == 0b10010000)
                {
                    byte channel = (byte)(command & 0b00001111);
                    byte note = reader.Read();
                    byte vel = reader.ReadFast();

                    if (settings.playbackEnabled && vel > 10)
                    {
                        globalPlaybackEvents.Add(new PlaybackEvent()
                        {
                            pos = time,
                            val = command | (note << 8) | (vel << 16)
                        });
                    }
                    if (vel == 0)
                    {
                        var l = UnendedNotes[note << 4 | channel];
                        if (!l.ZeroLen)
                        {
                            Note n = l.Pop();
                            n.end = time;
                            n.hasEnded = true;
                        }
                    }
                    else
                    {
                        Note n = new Note();
                        n.start = time;
                        n.key = note;
                        n.color = trkColors[channel];
                        n.channel = channel;
                        n.vel = vel;
                        n.track = trackID;
                        if (UnendedNotes == null)
                        {
                            UnendedNotes = new FastList<Note>[256 * 16];
                            for (int i = 0; i < 256 * 16; i++)
                            {
                                UnendedNotes[i] = new FastList<Note>();
                            }
                        }
                        UnendedNotes[note << 4 | channel].Add(n);
                        globalDisplayNotes.Add(n);
                    }
                }
                else if (comm == 0b10000000)
                {
                    int channel = command & 0b00001111;
                    byte note = reader.Read();
                    byte vel = reader.ReadFast();
                    var l = UnendedNotes[note << 4 | channel];
                    if (!l.ZeroLen)
                    {
                        try
                        {
                            Note n = l.Pop();

                            if (settings.playbackEnabled && n.vel > 10)
                            {
                                globalPlaybackEvents.Add(new PlaybackEvent()
                                {
                                    pos = time,
                                    val = command | (note << 8) | (vel << 16)
                                });
                            }
                            n.end = time;
                            n.hasEnded = true;
                        }
                        catch
                        { }
                    }
                }
                else if (comm == 0b10100000)
                {
                    int channel = command & 0b00001111;
                    byte note = reader.Read();
                    byte vel = reader.Read();
                    if (settings.playbackEnabled)
                    {
                        globalPlaybackEvents.Add(new PlaybackEvent()
                        {
                            pos = time,
                            val = command | (note << 8) | (vel << 16)
                        });
                    }
                }
                else if (comm == 0b11000000)
                {
                    int channel = command & 0b00001111;
                    byte program = reader.Read();
                    if (settings.playbackEnabled)
                    {
                        globalPlaybackEvents.Add(new PlaybackEvent()
                        {
                            pos = time,
                            val = command | (program << 8)
                        });
                    }
                }
                else if (comm == 0b11010000)
                {

                    int channel = command & 0b00001111;
                    byte pressure = reader.Read();
                    if (settings.playbackEnabled)
                    {
                        globalPlaybackEvents.Add(new PlaybackEvent()
                        {
                            pos = time,
                            val = command | (pressure << 8)
                        });
                    }
                }
                else if (comm == 0b11100000)
                {
                    int channel = command & 0b00001111;
                    byte l = reader.Read();
                    byte m = reader.Read();
                    if (settings.playbackEnabled)
                    {
                        globalPlaybackEvents.Add(new PlaybackEvent()
                        {
                            pos = time,
                            val = command | (l << 8) | (m << 16)
                        });
                    }
                }
                else if (comm == 0b10110000)
                {
                    int channel = command & 0b00001111;
                    byte cc = reader.Read();
                    byte vv = reader.Read();
                    if (settings.playbackEnabled)
                    {
                        globalPlaybackEvents.Add(new PlaybackEvent()
                        {
                            pos = time,
                            val = command | (cc << 8) | (vv << 16)
                        });
                    }
                }
                else if (command == 0b11110000)
                {
                    while (reader.Read() != 0b11110111) ;
                }
                else if (command == 0b11110100 || command == 0b11110001 || command == 0b11110101 || command == 0b11111001 || command == 0b11111101)
                {
                    //printf("Undefined\n");
                }
                else if (command == 0b11110010)
                {
                    int channel = command & 0b00001111;
                    byte ll = reader.Read();
                    byte mm = reader.Read();

                }
                else if (command == 0b11110011)
                {
                    byte ss = reader.Read();
                }
                else if (command == 0b11110110)
                {
                }
                else if (command == 0b11110111)
                {
                }
                else if (command == 0b11111000)
                {
                }
                else if (command == 0b11111010)
                {
                }
                else if (command == 0b11111100)
                {
                }
                else if (command == 0b11111110)
                {
                }
                else if (command == 0xFF)
                {
                    command = reader.Read();
                    if (command == 0x00)
                    {
                        if (reader.Read() != 2)
                        {
                            throw new Exception("Corrupt Track");
                        }
                        reader.Read(); 
                        reader.Read();
                    }
                    else if (command == 0x01)
                    {
                        int size = (int)ReadVariableLen();
                        char[] text = new char[size];
                        for (int i = 0; i < size; i++)
                        {
                            text[i] = (char)reader.Read();
                        }
                        string str = new string(text);
                    }
                    else if (command == 0x02)
                    {
                        int size = (int)ReadVariableLen();
                        char[] text = new char[size];
                        for (int i = 0; i < size; i++)
                        {
                            text[i] = (char)reader.Read();
                        }
                        string str = new string(text);
                    }
                    else if (command == 0x03)
                    {
                        int size = (int)ReadVariableLen();
                        char[] text = new char[size];
                        for (int i = 0; i < size; i++)
                        {
                            text[i] = (char)reader.Read();
                        }
                        string str = new string(text);
                    }
                    else if (command == 0x04)
                    {
                        int size = (int)ReadVariableLen();
                        char[] text = new char[size];
                        for (int i = 0; i < size; i++)
                        {
                            text[i] = (char)reader.Read();
                        }
                        string str = new string(text);
                    }
                    else if (command == 0x05)
                    {
                        int size = (int)ReadVariableLen();
                        char[] text = new char[size];
                        for (int i = 0; i < size; i++)
                        {
                            text[i] = (char)reader.Read();
                        }
                        string str = new string(text);
                    }
                    else if (command == 0x06)
                    {
                        int size = (int)ReadVariableLen();
                        char[] text = new char[size];
                        for (int i = 0; i < size; i++)
                        {
                            text[i] = (char)reader.Read();
                        }
                        string str = new string(text);
                    }
                    else if (command == 0x07)
                    {
                        int size = (int)ReadVariableLen();
                        char[] text = new char[size];
                        for (int i = 0; i < size; i++)
                        {
                            text[i] = (char)reader.Read();
                        }
                        string str = new string(text);
                    }
                    else if (command == 0x08)
                    {
                        int size = (int)ReadVariableLen();
                        char[] text = new char[size];
                        for (int i = 0; i < size; i++)
                        {
                            text[i] = (char)reader.Read();
                        }
                        string str = new string(text);
                    }
                    else if (command == 0x09)
                    {
                        int size = (int)ReadVariableLen();
                        char[] text = new char[size];
                        for (int i = 0; i < size; i++)
                        {
                            text[i] = (char)reader.Read();
                        }
                        string str = new string(text);
                    }
                    else if (command == 0x0A)
                    {
                        int size = (int)ReadVariableLen();
                        byte[] data = new byte[size];
                        for (int i = 0; i < size; i++)
                        {
                            data[i] = reader.Read();
                        }
                        if (data.Length == 8 || data.Length == 12)
                        {
                            if (data[0] == 0x00 &&
                                data[1] == 0x0F)
                            {
                                Color4 col1 = new Color4(data[4], data[5], data[6], data[7]);
                                Color4 col2;
                                if (data.Length == 12)
                                    col2 = new Color4(data[8], data[9], data[10], data[11]);
                                else col2 = col1;
                                if (data[2] < 0x10 || data[2] == 0x7F)
                                {
                                    var c = new ColorChange() { pos = time, col1 = col1, col2 = col2, channel = data[2], track = this };
                                    globalColorEvents.Add(c);
                                }
                            }
                        }
                    }
                    else if (command == 0x20)
                    {
                        command = reader.Read();
                        if (command != 1)
                        {
                            throw new Exception("Corrupt Track");
                        }
                        channelPrefix = reader.Read();
                    }
                    else if (command == 0x21)
                    {
                        command = reader.Read();
                        if (command != 1)
                        {
                            throw new Exception("Corrupt Track");
                        }
                        reader.Skip(1);
                        //TODO:  MIDI port
                    }
                    else if (command == 0x2F)
                    {
                        command = reader.Read();
                        if (command != 0)
                        {
                            throw new Exception("Corrupt Track");
                        }
                        EndTrack();
                    }
                    else if (command == 0x51)
                    {
                        command = reader.Read();
                        if (command != 3)
                        {
                            throw new Exception("Corrupt Track");
                        }
                        int btempo = 0;
                        for (int i = 0; i != 3; i++)
                            btempo = (int)((btempo << 8) | reader.Read());
                        if (!timebase)
                        {
                            Tempo t = new Tempo();
                            t.pos = trackTime;
                            t.tempo = btempo;

                            lock (globalTempoEvents)
                            {
                                globalTempoEvents.Add(t);
                            }
                        }
                        midi.tempoTickMultiplier = ((double)midi.division / btempo) * 1000;
                    }
                    else if (command == 0x54)
                    {
                        command = reader.Read();
                        if (command != 5)
                        {
                            throw new Exception("Corrupt Track");
                        }
                        reader.Skip(4);
                    }
                    else if (command == 0x58)
                    {
                        command = reader.Read();
                        if (command != 4)
                        {
                            throw new Exception("Corrupt Track");
                        }
                        reader.Skip(4);
                    }
                    else if (command == 0x59)
                    {
                        command = reader.Read();
                        if (command != 2)
                        {
                            throw new Exception("Corrupt Track");
                        }
                        reader.Skip(2);
                        //TODO: Key Signature
                    }
                    else if (command == 0x7F)
                    {
                        int size = (int)ReadVariableLen();
                        byte[] data = new byte[size];
                        for (int i = 0; i < size; i++)
                        {
                            data[i] = reader.Read();
                        }
                    }
                    else
                    {
                        throw new Exception("Corrupt Track");
                    }
                }
                else
                {
                    throw new Exception("Corrupt Track");
                }
            }
            catch (IndexOutOfRangeException)
            {
                EndTrack();
            }
            catch
            { }
        }

        public FastList<Tempo> TempoEvents = new FastList<Tempo>();
        public void ParseNextEventFast()
        {
            try
            {
                trackTime += ReadVariableLen();
                byte command = reader.Read();
                if (command < 0x80)
                {
                    reader.Pushback = command;
                    command = prevCommand;
                }
                prevCommand = command;
                byte comm = (byte)(command & 0b11110000);
                if (comm == 0b10010000)
                {
                    byte channel = (byte)(command & 0b00001111);
                    reader.Skip(1);
                    byte vel = reader.Read();
                    if (vel != 0)
                        noteCount++;
                }
                else if (comm == 0b10000000)
                {
                    int channel = command & 0b00001111;
                    reader.Skip(2);
                }
                else if (comm == 0b10100000)
                {
                    int channel = command & 0b00001111;
                    reader.Skip(2);
                }
                else if (comm == 0b11000000)
                {
                    int channel = command & 0b00001111;
                    reader.Skip(1);
                }
                else if (comm == 0b11010000)
                {
                    int channel = command & 0b00001111;
                    reader.Skip(1);
                }
                else if (comm == 0b11100000)
                {
                    int channel = command & 0b00001111;
                    reader.Skip(2);
                }
                else if (comm == 0b10110000)
                {
                    int channel = command & 0b00001111;
                    reader.Skip(2);
                }
                else if (command == 0b11110000)
                {
                    while (reader.Read() != 0b11110111) ;
                }
                else if (command == 0b11110100 || command == 0b11110001 || command == 0b11110101 || command == 0b11111001 || command == 0b11111101)
                {
                    //printf("Undefined\n");
                }
                else if (command == 0b11110010)
                {
                    int channel = command & 0b00001111;
                    reader.Skip(2);

                }
                else if (command == 0b11110011)
                {
                    byte ss = reader.Read();
                }
                else if (command == 0b11110110)
                {
                }
                else if (command == 0b11110111)
                {
                }
                else if (command == 0b11111000)
                {
                }
                else if (command == 0b11111010)
                {
                }
                else if (command == 0b11111100)
                {
                }
                else if (command == 0b11111110)
                {
                }
                else if (command == 0xFF)
                {
                    command = reader.Read();
                    if (command == 0x00)
                    {
                        if (reader.Read() != 2)
                        {
                            throw new Exception("Corrupt Track");
                        }
                    }
                    else if (command >= 0x01 &&
                            command <= 0x0A)
                    {
                        int size = (int)ReadVariableLen();
                        if (command != 0x0A || trackTime != 0)
                        {
                            reader.Skip(size);
                        }
                        else
                        {
                            byte[] data = new byte[size];
                            for (int i = 0; i < size; i++)
                            {
                                data[i] = reader.Read();
                            }
                            if (data.Length == 8 || data.Length == 12)
                            {
                                if (data[0] == 0x00 &&
                                    data[1] == 0x0F)
                                {
                                    Color4 col1 = new Color4(data[4], data[5], data[6], data[7]);
                                    Color4 col2;
                                    if (data.Length == 12)
                                        col2 = new Color4(data[8], data[9], data[10], data[11]);
                                    else col2 = col1;
                                    if (data[2] < 0x10)
                                    {
                                        zeroTickTrkColors[data[2]] = new NoteColor() { left = col1, right = col2 };
                                    }
                                    else if (data[2] == 0x7F)
                                    {
                                        for (int i = 0; i < 16; i++)
                                            zeroTickTrkColors[i] = new NoteColor() { left = col1, right = col2 };
                                    }
                                }
                            }
                        }
                    }
                    else if (command == 0x20)
                    {
                        command = reader.Read();
                        if (command != 1)
                        {
                            throw new Exception("Corrupt Track");
                        }
                        channelPrefix = reader.Read();
                    }
                    else if (command == 0x21)
                    {
                        command = reader.Read();
                        if (command != 1)
                        {
                            throw new Exception("Corrupt Track");
                        }
                        reader.Skip(1);
                        //TODO:  MIDI port
                    }
                    else if (command == 0x2F)
                    {
                        command = reader.Read();
                        if (command != 0)
                        {
                            throw new Exception("Corrupt Track");
                        }
                        EndTrack();
                    }
                    else if (command == 0x51)
                    {
                        command = reader.Read();
                        if (command != 3)
                        {
                            throw new Exception("Corrupt Track");
                        }
                        int btempo = 0;
                        for (int i = 0; i != 3; i++)
                            btempo = (int)((btempo << 8) | reader.Read());
                        if (trackTime == 0)
                        {
                            zerothTempo = btempo;
                        }

                        Tempo t = new Tempo();
                        t.pos = trackTime;
                        t.tempo = btempo;
                        TempoEvents.Add(t);
                    }
                    else if (command == 0x54)
                    {
                        command = reader.Read();
                        if (command != 5)
                        {
                            throw new Exception("Corrupt Track");
                        }
                        reader.Skip(4);
                    }
                    else if (command == 0x58)
                    {
                        command = reader.Read();
                        if (command != 4)
                        {
                            throw new Exception("Corrupt Track");
                        }
                        int nn = reader.ReadFast();
                        int dd = reader.ReadFast();
                        dd = (int)Math.Pow(2, dd);
                        foundTimeSig = new TimeSignature() { numerator = nn, denominator = dd };
                        reader.Skip(2);
                    }
                    else if (command == 0x59)
                    {
                        command = reader.Read();
                        if (command != 2)
                        {
                            throw new Exception("Corrupt Track");
                        }
                        reader.Skip(2);
                        //TODO: Key Signature
                    }
                    else if (command == 0x7F)
                    {
                        int size = (int)ReadVariableLen();
                        reader.Skip(size);
                    }
                    else
                    {
                        throw new Exception("Corrupt Track");
                    }
                }
                else
                {
                    throw new Exception("Corrupt Track");
                }
            }
            catch (IndexOutOfRangeException)
            {
                EndTrack();
            }
            catch
            { }
        }

        public void Dispose()
        {
            reader.Dispose();
        }
    }
}


================================================
FILE: BMEngine/NoteColorPalettePick.xaml
================================================
<UserControl x:Class="ZenithEngine.NoteColorPalettePick"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:ZenithEngine"
             xmlns:ui="clr-namespace:ZenithEngine.UI"
             mc:Ignorable="d">
    <UserControl.Resources>
        <ResourceDictionary Source="pack://application:,,,/ZenithEngine;component/UI/Material.xaml"/>
    </UserControl.Resources>
        <DockPanel LastChildFill="True">
            <Button DockPanel.Dock="Top" x:Name="reloadButton" Height="26" Content="{DynamicResource palettes_reload}" Margin="0,0,0,6" VerticalAlignment="Top" Click="ReloadButton_Click"/>
            <Button DockPanel.Dock="Bottom" x:Name="openPaletteFolder" Margin="0,10,0,0" Height="26" Content="{DynamicResource palettes_openFolder}" Click="openPaletteFolder_Click"/>
            <ui:BetterCheckbox x:Name="randomiseOrder" DockPanel.Dock="Bottom" Text="{DynamicResource palettes_randomise}" HorizontalAlignment="Left" Margin="0,5,0,0" VerticalAlignment="Top" CheckToggled="randomiseOrder_CheckToggled" IsChecked="True"/>
            <ListBox x:Name="paletteList" Margin="0" SelectionChanged="PaletteList_SelectionChanged"/>
        </DockPanel>
</UserControl>


================================================
FILE: BMEngine/NoteColorPalettePick.xaml.cs
================================================
using OpenTK.Graphics;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml;
using Brushes = System.Windows.Media.Brushes;
using Color = System.Drawing.Color;
using Path = System.IO.Path;

namespace ZenithEngine
{
    /// <summary>
    /// Interaction logic for NoteColorPalettePick.xaml
    /// </summary>
    public partial class NoteColorPalettePick : UserControl
    {
        string searchPath = "";
        public string SelectedImage { get; private set; } = "";
        bool randomise = true;
        int selectedIndex = -1;
        List<Bitmap> images = new List<Bitmap>();

        public event Action PaletteChanged;

        int seed = 0;

        float defS, defV;
        public NoteColorPalettePick()
        {
            InitializeComponent();
        }

        public void SetPath(string path, float defS = 1, float defV = 1)
        {
            this.defS = defS;
            this.defV = defV;
            searchPath = path;
            Reload();
        }

        public void Reload()
        {
            float mult = 0.12345f;
            if (!Directory.Exists(searchPath)) Directory.CreateDirectory(searchPath);
            using (Bitmap palette = new Bitmap(16, 8))
            {
                for (int i = 0; i < 16 * 8; i++)
                {
                    palette.SetPixel(i % 16, (i - i % 16) / 16, (Color)Color4.FromHsv(new OpenTK.Vector4(i * mult % 1, defS, defV, 1)));
                }
                palette.Save(Path.Combine(searchPath, "Random.png"));
            }
            using (Bitmap palette = new Bitmap(32, 8))
            {
                for (int i = 0; i < 32 * 8; i++)
                {
                    palette.SetPixel(i % 32, (i - i % 32) / 32, (Color)Color4.FromHsv(new OpenTK.Vector4(i * mult % 1, defS, defV, 1)));
                    i++;
                    palette.SetPixel(i % 32, (i - i % 32) / 32, (Color)Color4.FromHsv(new OpenTK.Vector4(((i - 1) * mult + 0.166f) % 1, defS, defV, 1)));
                }
                palette.Save(Path.Combine(searchPath, "Random Gradients.png"));
            }
            using (Bitmap palette = new Bitmap(32, 8))
            {
                for (int i = 0; i < 32 * 8; i++)
                {
                    palette.SetPixel(i % 32, (i - i % 32) / 32, (Color)Color4.FromHsv(new OpenTK.Vector4(i * mult % 1, defS, defV, 0.8f)));
                    i++;
                    palette.SetPixel(i % 32, (i - i % 32) / 32, (Color)Color4.FromHsv(new OpenTK.Vector4(((i - 1) * mult + 0.166f) % 1, defS, defV, 0.8f)));
                }
                palette.Save(Path.Combine(searchPath, "Random Alpha Gradients.png"));
            }
            using (Bitmap palette = new Bitmap(16, 8))
            {
                for (int i = 0; i < 16 * 8; i++)
                {
                    palette.SetPixel(i % 16, (i - i % 16) / 16, (Color)Color4.FromHsv(new OpenTK.Vector4(i * mult % 1, defS, defV, 0.8f)));
                }
                palette.Save(Path.Combine(searchPath, "Random with Alpha.png"));
            }
            var imagePaths = Directory.GetFiles(searchPath).Where(s => s.EndsWith(".png")).ToArray();

            paletteList.Items.Clear();
            foreach (var i in images) i.Dispose();
            images.Clear();

            Array.Sort(imagePaths, new Comparison<string>((s1, s2) =>
            {
                if (s1.Contains("Random.png")) return -1;
                if (s2.Contains("Random.png")) return 1;
                else return 0;
            }));

            foreach (var i in imagePaths)
            {
                try
                {
                    using (var fs = new System.IO.FileStream(i, System.IO.FileMode.Open))
                    {
                        Bitmap img = new Bitmap(fs);
                        if (!(img.Width == 16 || img.Width == 32) || img.Width < 1) continue;
                        images.Add(img);
                        var item = new ListBoxItem() { Content = Path.GetFileNameWithoutExtension(i) };
                        if (img.Width == 32) item.Foreground = Brushes.Blue;
                        paletteList.Items.Add(item);
                    }
                }
                catch
                {

                }
            }
            ReadPFAConfig();
            SelectImage(SelectedImage);
        }

        void ReadPFAConfig()
        {
            try
            {
                var appdata = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
                var configPath = Path.Combine(appdata, "Piano From Above/Config.xml");
                if (File.Exists(configPath))
                {
                    var data = File.ReadAllText(configPath);
                    XmlDocument doc = new XmlDocument();
                    doc.LoadXml(data);
                    var colors = doc.GetElementsByTagName("Colors").Item(0);
                    Bitmap img = new Bitmap(16, 1);
                    for (int i = 0; i < 16; i++)
                    {
                        var c = colors.ChildNodes.Item(i);
                        int r = -1;
                        int g = -1;
                        int b = -1;
                        for (int j = 0; j < 3; j++)
                        {
                            var attrib = c.Attributes.Item(j);
                            if (attrib.Name == "R") r = Convert.ToInt32(attrib.InnerText);
                            if (attrib.Name == "G") g = Convert.ToInt32(attrib.InnerText);
                            if (attrib.Name == "B") b = Convert.ToInt32(attrib.InnerText);
                        }
                        img.SetPixel(i, 0, Color.FromArgb(r, g, b));
                    }
                    images.Add(img);
                    var item = new ListBoxItem() { Content = "PFA Config Colors" };
                    paletteList.Items.Add(item);

                }
            }
            catch { }
        }

        public void SelectImage(string img)
        {
            bool set = false;
            foreach (var i in paletteList.Items)
            {
                if ((string)((ListBoxItem)i).Content == img)
                {
                    paletteList.SelectedItem = i;
                    set = true;
                    break;
                }
            }
            if (!set)
            {
                paletteList.SelectedIndex = 0;
            }

            PaletteChanged?.Invoke();
        }

        public Color4[] GetColors(int tracks)
        {
            Random r = new Random(seed);
            double[] order = new double[tracks * 16];
            int[] coords = new int[tracks * 16];
            for (int i = 0; i < order.Length; i++)
            {
                order[i] = r.NextDouble();
                coords[i] = i;
            }
            if (randomise)
            {
                Array.Sort(order, coords);
            }
            List<Color4> cols = new List<Color4>();
            var img = images[selectedIndex];
            for (int i = 0; i < tracks; i++)
            {
                for (int j = 0; j < 16; j++)
                {
                    int y = coords[i * 16 + j];
                    int x = y % 16;
                    y = y - x;
                    y /= 16;
                    if (img.Width == 16)
                    {
                        cols.Add(img.GetPixel(x, y % img.Height));
                        cols.Add(img.GetPixel(x, y % img.Height));
                    }
                    else
                    {
                        cols.Add(img.GetPixel(x * 2, y % img.Height));
                        cols.Add(img.GetPixel(x * 2 + 1, y % img.Height));
                    }
                }
            }
            return cols.ToArray();
        }

        private void ReloadButton_Click(object sender, RoutedEventArgs e)
        {
            Reload();
        }

        private void randomiseOrder_CheckToggled(object sender, RoutedPropertyChangedEventArgs<bool> e)
        {
            randomise = (bool)randomiseOrder.IsChecked;
            if (randomise) seed++;
            PaletteChanged?.Invoke();
        }

        private void openPaletteFolder_Click(object sender, RoutedEventArgs e)
        {
            if (!searchPath.Contains(":\\") && !searchPath.Contains(":/"))
                Process.Start("explorer.exe", System.IO.Path.Combine(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), searchPath));
            else
                Process.Start("explorer.exe", searchPath);
        }

        private void PaletteList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (paletteList.SelectedItem == null) return;
            try
            {
                SelectedImage = (string)((ListBoxItem)paletteList.SelectedItem).Content;
                selectedIndex = paletteList.SelectedIndex;
                PaletteChanged?.Invoke();
            }
            catch
            { }
        }
    }
}


================================================
FILE: BMEngine/OpenTK.dll.config
================================================
<configuration>
  <dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
  <dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
  <dllmap os="linux" dll="openal32.dll" target="libopenal.so.1"/>
  <dllmap os="linux" dll="alut.dll" target="libalut.so.0"/>
  <dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/>
  <dllmap os="linux" dll="libX11" target="libX11.so.6"/>
  <dllmap os="linux" dll="libXi" target="libXi.so.6"/>
  <dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0"/>
  <dllmap os="osx" dll="opengl32.dll" target="/System/Library/Frameworks/OpenGL.framework/OpenGL"/>
  <dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
  <dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
  <dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
  <dllmap os="osx" dll="libGLESv1_CM.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
  <dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
  <dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
  <dllmap os="osx" dll="SDL2.dll" target="libSDL2.dylib"/>
  <!-- XQuartz compatibility (X11 on Mac) -->
  <dllmap os="osx" dll="libGL.so.1" target="/usr/X11/lib/libGL.dylib"/>
  <dllmap os="osx" dll="libX11" target="/usr/X11/lib/libX11.dylib"/>
  <dllmap os="osx" dll="libXcursor.so.1" target="/usr/X11/lib/libXcursor.dylib"/>
  <dllmap os="osx" dll="libXi" target="/usr/X11/lib/libXi.dylib"/>
  <dllmap os="osx" dll="libXinerama" target="/usr/X11/lib/libXinerama.dylib"/>
  <dllmap os="osx" dll="libXrandr.so.2" target="/usr/X11/lib/libXrandr.dylib"/>
</configuration>


================================================
FILE: BMEngine/PluginUtils.cs
================================================
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;

namespace ZenithEngine
{
    public static class PluginUtils
    {
        public static BitmapImage BitmapToImageSource(Bitmap bitmap)
        {
            using (MemoryStream memory = new MemoryStream())
            {
                bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Bmp);
                memory.Position = 0;
                BitmapImage bitmapimage = new BitmapImage();
                bitmapimage.BeginInit();
                bitmapimage.StreamSource = memory;
                bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
                bitmapimage.EndInit();

                return bitmapimage;
            }
        }

    }
}


================================================
FILE: BMEngine/Properties/AssemblyInfo.cs
================================================
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("ZenithEngine")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ZenithEngine")]
[assembly: AssemblyCopyright("Copyright ©  2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components.  If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("60f2212a-d56c-4776-836f-6a49453cdbc4")]

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]


================================================
FILE: BMEngine/RenderSettings.cs
================================================
using OpenTK.Graphics;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ZenithEngine
{
    public enum KeyboardRenderers
    {
        Legacy,
        New,
        Flat
    }

    public enum NoteRenderers
    {
        Shaded,
        Flat
    }

    public class RenderSettings
    {
        public int fps = 60;

        public int width = 1920;
        public int height = 1080;
        public int downscale = 1;

        public bool ffRender = false;
        public string ffPath = "";
        public bool ffRenderMask = false;
        public string ffMaskPath = "";
        public bool vsync = true;
        public double renderSecondsDelay = 0;

        private bool paused = false;
        public bool forceReRender = true;
        public double tempoMultiplier = 1;

        public bool includeAudio = false;
        public string audioPath = "";

        public int maxTrackBufferSize = 10000;

        public bool useBitrate = true;
        public bool CustomFFmpeg = false;
        public int bitrate = 20000;
        public int crf = 17;
        public string crfPreset = "medium";
        public bool ffmpegDebug = false;
        public string ffoption = "";

        public bool showNoteCount = false;
        public bool showNotesRendered = false;
        public int fontSize = 50;
        public string font = "Arial";

        public bool running = false;

        public bool playSound = true;
        public bool playbackEnabled = true;

        public bool realtimePlayback = true;

        public double liveFps = 0;

        public bool timeBasedNotes = false;

        public bool ignoreColorEvents = false;

        public long lastBGChangeTime = -1;
        public string BGImage = null;

        public event Action PauseToggled;
        public bool Paused
        {
            get => paused;
            set
            {
                paused = value;
                PauseToggled();
            }
        }
    }
}


================================================
FILE: BMEngine/ScriptedCompile/ExtraUI.cs
================================================
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ScriptedEngine
{
    public abstract class UISetting
    {
        public double Padding { get; set; } = 10;
    }
    public abstract class UISettingValued<T> : UISetting
    {
        private bool enabled = true;

        public event Action<bool> EnableToggled;

        public T Default { get; protected set; }

        public bool Enabled
        {
            get => enabled;
            set
            {
                if (enabled != value)
                {
                    enabled = value;
                    EnableToggled?.Invoke(Enabled);
                }
            }
        }

    }

    public class UITabs : UISetting
    {
        public Dictionary<string, IEnumerable<UISetting>> Tabs { get; set; } = new Dictionary<string, IEnumerable<UISetting>>();

        public UITabs() { }
        public UITabs(Dictionary<string, IEnumerable<UISetting>> tabs) { Tabs = tabs; }
    }

    public class UILabel : UISetting
    {
        public double FontSize { get; } = 16;
        public string Text { get; } = "";

        public UILabel(string text) { Text = text; }
        public UILabel(string text, double fontSize) { Text = text; FontSize = fontSize; }
        public UILabel(string text, double fontSize, double padding) { Text = text; FontSize = fontSize; Padding = padding; }
    }

    public class UINumber : UISettingValued<double>
    {
        private double value;

        public UINumber(string text, double value, double minimum, double maximum, int decialPoints)
        {
            Default = value;
            Text = text;
            Value = value;
            Minimum = minimum;
            Maximum = maximum;
            DecialPoints = decialPoints;
        }

        public UINumber(string text, double value, double minimum, double maximum, int decialPoints, double step) : this(text, value, minimum, maximum, decialPoints)
        {
            Step = step;
        }

        public event Action<double> ValueChanged;

        public double Value
        {
            get => value;
            set
            {
                if (this.value != value)
                {
                    this.value = value;
                    ValueChanged?.Invoke(this.value);
                }
            }
        }
        public string Text { get; }
        public double Minimum { get; }
        public double Maximum { get; }
        public int DecialPoints { get; }
        public double Step { get; } = 1;
    }

    public class UINumberSlider : UISettingValued<double>
    {
        private double value;

        public UINumberSlider(string text, double value, double minimum, double maximum, double trueMinimum, double trueMaximum, int decialPoints)
        {
            Default = value;
            Text = text;
            Value = value;
            Minimum = minimum;
            Maximum = maximum;
            TrueMinimum = trueMinimum;
            TrueMaximum = trueMaximum;
            DecialPoints = decialPoints;
        }

        public UINumberSlider(string text, double value, double minimum, double maximum, double trueMinimum, double trueMaximum, int decialPoints, bool logarithmic) : this(text, value, minimum, maximum, trueMinimum, trueMaximum, decialPoints)
        {
            Logarithmic = logarithmic;
        }

        public UINumberSlider(string text, double value, double minimum, double maximum, double trueMinimum, double trueMaximum, int decialPoints, double step, bool logarithmic)
        {
            Default = value;
            Value = value;
            Text = text;
            Minimum = minimum;
            Maximum = maximum;
            TrueMinimum = trueMinimum;
            TrueMaximum = trueMaximum;
            DecialPoints = decialPoints;
            Step = step;
            Logarithmic = logarithmic;
        }

        public UINumberSlider(string text, double value, double minimum, double maximum, double trueMinimum, double trueMaximum, int decialPoints, double step)
        {
            Default = value;
            Value = value;
            Text = text;
            Minimum = minimum;
            Maximum = maximum;
            TrueMinimum = trueMinimum;
            TrueMaximum = trueMaximum;
            DecialPoints = decialPoints;
            Step = step;
        }

        public event Action<double> ValueChanged;

        public double Value
        {
            get => value;
            set
            {
                if (this.value != value)
                {
                    this.value = value;
                    ValueChanged?.Invoke(this.value);
                }
            }
        }
        public string Text { get; }
        public double Minimum { get; }
        public double Maximum { get; }
        public double TrueMinimum { get; }
        public double TrueMaximum { get; }
        public int DecialPoints { get; }
        public double Step { get; } = 1;
        public bool Logarithmic { get; } = false;
    }

    public class UIDropdown : UISettingValued<int>
    {
        private string value;
        private int index;

        public UIDropdown(string text, string[] options)
        {
            Text = text;
            Options = options;
            Index = 0;
            Value = options[0];
            Default = 0;
        }

        public UIDropdown(string text, int index, string[] options)
        {
            Text = text;
            Options = options;
            Index = index;
            Value = options[index];
            Default = index;
        }


        public event Action<int> IndexChanged;

        public string Value
        {
            get => value;
            set
            {
                if (this.value != value)
                {
                    this.value = value;
                    if (!Options.Contains(value)) throw new Exception("Dropdown doesn't contain value '" + value + "'");
                    Index = Array.IndexOf(Options, value);
                }
            }
        }
        public string Text { get; }
        public int Index
        {
            get => index;
            set
            {
                if (index != value)
                {
                    index = value;
                    if (index < 0 || index >= Options.Length) throw new Exception("Index value of " + index + " is outside the rage of the dropdown's " + Options.Length + " item count.");
                    this.value = Options[index];
                    IndexChanged?.Invoke(index);
                }
            }
        }
        public string[] Options { get; }
    }

    public class UICheckbox : UISettingValued<bool>
    {
        private bool value;

        public UICheckbox(string text, bool @checked)
        {
            this.Text = text;
            this.Checked = @checked;
            Default = @checked;
        }

        public event Action<bool> ValueChanged;

        public bool Checked
        {
            get => value;
            set
            {
                if (this.value != value)
                {
                    this.value = value;
                    ValueChanged?.Invoke(this.value);
                }
            }
        }
        public string Text { get; }
    }
}


================================================
FILE: BMEngine/ScriptedCompile/IO.cs
================================================
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using OpenTK;
using ZenithEngine;
using OpenTK.Graphics;

namespace ScriptedEngine
{
    public class Texture
    {
        public string path;
        public Bitmap bitmap;
        public int texId = -1;
        public bool linear = false;
        public bool looped = true;

        public int width;
        public int height;
        public double aspectRatio;
    }

    public enum FontStyle
    {
        Regular = 0,
        Bold = 1,
        Italic = 2,
        Underline = 4,
        Strikeout = 8
    }

    public enum TextAlignment
    {
        Regular = 0,
        Bold = 1,
        Italic = 2,
        Underline = 4,
        Strikeout = 8
    }

    public class Font
    {
        public int fontPixelSize;
        public string fontName;
        public FontStyle fontStyle;
        public string charMap;

        public GLTextEngine engine;
    }

    public enum TextureShaders
    {
        Normal,
        Inverted,
        Hybrid
    }

    public enum BlendFunc
    {
        Mix,
        Add
    }

    public class RenderOptions
    {
        public int firstKey;
        public int lastKey;
        public int renderWidth;
        public int renderHeight;
        public double renderAspectRatio;
        public int renderFPS;
        public int renderSSAA;
        public double midiTime;
        public double noteScreenTime;

        public int midiPPQ;
        public bool midiTimeBased;
        public TimeSignature midiTimeSignature;
        public int midiBarLength;
    }

    public class KeyLayout
    {
        public class pos
        {
            public double left;
            public double right;
        }

        public KeyLayout()
        {
            keys = new pos[257];
            notes = new pos[257];

            for (int i = 0; i < blackKey.Length; i++) blackKey[i] = Util.IsBlackKey(i);
            int b = 0;
            int w = 0;
            for (int i = 0; i < keyNumber.Length; i++)
            {
                if (blackKey[i]) keyNumber[i] = b++;
                else keyNumber[i] = w++;
            }
        }

        public pos[] keys;
        public pos[] notes;
        public bool[] blackKey = new bool[257];
        public int[] keyNumber = new int[257];

        public double blackKeyWidth;
        public double whiteKeyWidth;
        public double blackNoteWidth;
        public double whiteNoteWidth;
    }

    public class KeyboardOptions
    {
        public bool sameWidthNotes = false;

        public double blackKey2setOffset = 0.3;
        public double blackKey3setOffset = 0.5;
        public double blackKeyScale = 0.6;

        public double blackNote2setOffset = 0;
        public double blackNote3setOffset = 0;
        public double blackNoteScale = 1;

        public double[] advancedBlackKeyOffsets = new double[] { 0, 0, 0, 0, 0 };
    }

    public static class IO
    {
        public static Func<string, bool, bool, Texture> loadTexture;
        public static Texture LoadTexture(string path)
        {
            if (!IsInFunction("Load") && !IsInFunction(".ctor")) throw new Exception("Can't call LoadTexture outside the load function");
            return loadTexture(path, true, false);
        }

        public static Texture LoadTexture(string path, bool linear)
        {
            if (!IsInFunction("Load") && !IsInFunction(".ctor")) throw new Exception("Can't call LoadTexture outside the load function");
            return loadTexture(path, true, linear);
        }

        public static Texture LoadTexture(string path, bool uvLoop, bool linear)
        {
            if (!IsInFunction("Load") && !IsInFunction(".ctor")) throw new Exception("Can't call LoadTexture outside the load function");
            return loadTexture(path, uvLoop, linear);
        }

        public static Func<int, string, FontStyle, string, Font> loadFont;
        public static Font LoadFont(int size, string name)
        {
            if (!IsInFunction("Load") && !IsInFunction(".ctor")) throw new Exception("Can't call LoadFont outside the load function");
            return loadFont(size, name, FontStyle.Regular, null);
        }
        public static Font LoadFont(int size, string name, FontStyle style)
        {
            if (!IsInFunction("Load") && !IsInFunction(".ctor")) throw new Exception("Can't call LoadFont outside the load function");
            return loadFont(size, name, style, null);
        }
        public static Font LoadFont(int size, string name, string charmap)
        {
            if (!IsInFunction("Load") && !IsInFunction(".ctor")) throw new Exception("Can't call LoadFont outside the load function");
            return loadFont(size, name, FontStyle.Regular, charmap);
        }
        public static Font LoadFont(int size, string name, FontStyle style, string charmap)
        {
            if (!IsInFunction("Load") && !IsInFunction(".ctor")) throw new Exception("Can't call LoadFont outside the load function");
            return loadFont(size, name, style, charmap);
        }

        public static Action<double, double, double, double, Color4, Color4, Color4, Color4, Texture, double, double, double, double> renderQuad;
        public static Action<double, double, double, Color4, Font, string> renderText;
        public static Func<Font, string, double> getTextSize;
        public static Action<TextureShaders> selectTexShader;
        public static Action<BlendFunc> setBlendFunc;
        public static Action forceFlush;
        public static Action<Vector2d, Vector2d, Vector2d, Vector2d, Color4, Color4, Color4, Color4, Texture, Vector2d, Vector2d, Vector2d, Vector2d> renderShape;

        public static void RenderQuad(double left, double top, double right, double bottom, Color4 col) =>
            renderQuad(left, top, right, bottom, col, col, col, col, null, 0, 0, 0, 0);

        public static void RenderQuad(double left, double top, double right, double bottom, Color4 col, Texture tex) =>
            renderQuad(left, top, right, bottom, col, col, col, col, tex, 0, 0, 1, 1);

        public static void RenderQuad(double left, double top, double right, double bottom, Color4 col, Texture tex, double uvLeft, double uvTop, double uvRight, double uvBottom) =>
            renderQuad(left, top, right, bottom, col, col, col, col, tex, uvLeft, uvTop, uvRight, uvBottom);

        public static void RenderQuad(double left, double top, double right, double bottom, Color4 topLeft, Color4 topRight, Color4 bottomRight, Color4 bottomLeft) =>
            renderQuad(left, top, right, bottom, topLeft, topRight, bottomRight, bottomLeft, null, 0, 0, 0, 0);

        public static void RenderQuad(double left, double top, double right, double bottom, Color4 topLeft, Color4 topRight, Color4 bottomRight, Color4 bottomLeft, Texture tex) =>
            renderQuad(left, top, right, bottom, topLeft, topRight, bottomRight, bottomLeft, tex, 0, 0, 1, 1);

        public static void RenderQuad(double left, double top, double right, double bottom, Color4 topLeft, Color4 topRight, Color4 bottomRight, Color4 bottomLeft, Texture tex, double uvLeft, double uvTop, double uvRight, double uvBottom) =>
            renderQuad(left, top, right, bottom, topLeft, topRight, bottomRight, bottomLeft, tex, uvLeft, uvTop, uvRight, uvBottom);

        public static void RenderShape(Vector2d v1, Vector2d v2, Vector2d v3, Vector2d v4, Color4 col) =>
            renderShape(v1, v2, v3, v4, col, col, col, col, null, Vector2d.Zero, Vector2d.Zero, Vector2d.Zero, Vector2d.Zero);

        public static void RenderShape(Vector2d v1, Vector2d v2, Vector2d v3, Vector2d v4, Color4 col, Texture tex) =>
            renderShape(v1, v2, v3, v4, col, col, col, col, tex, new Vector2d(0, 0), new Vector2d(1, 0), new Vector2d(1, 1), new Vector2d(0, 1));

        public static void RenderShape(Vector2d v1, Vector2d v2, Vector2d v3, Vector2d v4, Color4 col, Texture tex, Vector2d uv1, Vector2d uv2, Vector2d uv3, Vector2d uv4) =>
            renderShape(v1, v2, v3, v4, col, col, col, col, tex, uv1, uv2, uv3, uv4);

        public static void RenderShape(Vector2d v1, Vector2d v2, Vector2d v3, Vector2d v4, Color4 topLeft, Color4 topRight, Color4 bottomRight, Color4 bottomLeft) =>
            renderShape(v1, v2, v3, v4, topLeft, topRight, bottomRight, bottomLeft, null, new Vector2d(0, 0), new Vector2d(1, 0), new Vector2d(1, 1), new Vector2d(0, 1));

        public static void RenderShape(Vector2d v1, Vector2d v2, Vector2d v3, Vector2d v4, Color4 topLeft, Color4 topRight, Color4 bottomRight, Color4 bottomLeft, Texture tex) =>
            renderShape(v1, v2, v3, v4, topLeft, topRight, bottomRight, bottomLeft, tex, new Vector2d(0, 0), new Vector2d(1, 0), new Vector2d(1, 1), new Vector2d(0, 1));

        public static void RenderShape(Vector2d v1, Vector2d v2, Vector2d v3, Vector2d v4, Color4 topLeft, Color4 topRight, Color4 bottomRight, Color4 bottomLeft, Texture tex, Vector2d uv1, Vector2d uv2, Vector2d uv3, Vector2d uv4) =>
            renderShape(v1, v2, v3, v4, topLeft, topRight, bottomRight, bottomLeft, tex, uv1, uv2, uv3, uv4);

        public static void SelectTextureShader(TextureShaders shader) => selectTexShader(shader);

        public static void SetBlendFunc(BlendFunc function) => setBlendFunc(function);

        public static void RenderText(double left, double bottom, double height, Color4 color, Font font, string text) => renderText(left, bottom, height, color, font, text);
        public static double GetTextWidth(Font font, string text) => getTextSize(font, text);
        public static double GetTextWidth(Font font, double height, string text) => getTextSize(font, text) * height;

        public static void ForceFlushBuffer() => forceFlush();

        static string[] functions = new string[] { "Load", "Render", "RenderInit", "RenderDispose", ".ctor" };

        static bool IsInFunction(string name)
        {
            var funcs = functions.Where(f => f != name).ToArray();
            StackTrace st = new StackTrace(true);
            bool has = false;
            for (int i = 0; i < st.FrameCount; i++)
            {
                var m = st.GetFrame(i).GetMethod();
                if (m.Name == name &&
                    m.DeclaringType.Name == "Script")
                    has = true;
                if (funcs.Contains(m.Name) &&
                    m.DeclaringType.Name == "Script")
                    has = false;
            }
            return has;
        }

        static public void callLoadFunction(dynamic script)
        {
            script.Load();
        }
    }

    public static class Util
    {
        public static KeyLayout GetKeyboardLayout(int firstNote, int lastNote, KeyboardOptions options)
        {
            double wdth;

            double[] leftArrayKeys = new double[257];
            double[] widthArrayKeys = new double[257];
            double[] leftArrayNotes = new double[257];
            double[] widthArrayNotes = new double[257];

            var layout = new KeyLayout();

            if (options.sameWidthNotes)
            {
                var samewidth = 1.0f / (lastNote - firstNote);

                for (int i = 0; i < 257; i++)
                {
                    leftArrayKeys[i] = (i - firstNote) / (double)(lastNote - firstNote);
                    widthArrayKeys[i] = samewidth;
                    leftArrayNotes[i] = (i - firstNote) / (double)(lastNote - firstNote);
                    widthArrayNotes[i] = samewidth;
                }

                layout.blackKeyWidth = samewidth;
                layout.whiteKeyWidth = samewidth;
                layout.blackNoteWidth = samewidth;
                layout.whiteNoteWidth = samewidth;
            }
            else
            {
                for (int i = 0; i < 257; i++)
                {
                    if (!layout.blackKey[i])
                    {
                        leftArrayKeys[i] = layout.keyNumber[i];
                        leftArrayNotes[i] = layout.keyNumber[i];
                        widthArrayKeys[i] = 1.0f;
                        widthArrayNotes[i] = 1.0f;
                    }
                    else
                    {
                        int _i = i + 1;
                        wdth = options.blackKeyScale;
                        int bknum = layout.keyNumber[i] % 5;
                        double offset = wdth / 2;
                        if (bknum == 0) offset += wdth / 2 * options.blackKey2setOffset;
                        if (bknum == 2) offset += wdth / 2 * options.blackKey3setOffset;
                        if (bknum == 1) offset -= wdth / 2 * options.blackKey2setOffset;
                        if (bknum == 4) offset -= wdth / 2 * options.blackKey3setOffset;

                        offset -= options.advancedBlackKeyOffsets[layout.keyNumber[i] % 5] * wdth / 2;

                        leftArrayKeys[i] = layout.keyNumber[_i] - offset;
                        widthArrayKeys[i] = wdth;

                        offset -= wdth / 2 * (1 - options.blackNoteScale);
                        if (bknum == 0) offset += wdth / 2 * options.blackNote2setOffset;
                        if (bknum == 2) offset += wdth / 2 * options.blackNote3setOffset;
                        if (bknum == 1) offset -= wdth / 2 * options.blackNote2setOffset;
                        if (bknum == 4) offset -= wdth / 2 * options.blackNote3setOffset;
                        wdth *= options.blackNoteScale;

                        leftArrayNotes[i] = layout.keyNumber[_i] - offset;
                        widthArrayNotes[i] = wdth;
                    }
                }
                double knmfn = leftArrayKeys[firstNote];
                double knmln = leftArrayKeys[lastNote - 1] + widthArrayKeys[lastNote - 1];
                double width = knmln - knmfn;

                for (int i = 0; i < 257; i++)
                {
                    leftArrayKeys[i] = (leftArrayKeys[i] - knmfn) / width;
                    leftArrayNotes[i] = (leftArrayNotes[i] - knmfn) / width;
                    widthArrayKeys[i] /= width;
                    widthArrayNotes[i] /= width;
                }

                layout.blackKeyWidth = options.blackKeyScale / width;
                layout.whiteKeyWidth = 1 / width;
                layout.blackNoteWidth = options.blackKeyScale * options.blackNoteScale / width;
                layout.whiteNoteWidth = 1 / width;
            }

            for (int i = 0; i < 257; i++)
            {
                layout.keys[i] = new KeyLayout.pos() { left = leftArrayKeys[i], right = leftArrayKeys[i] + widthArrayKeys[i] };
                layout.notes[i] = new KeyLayout.pos() { left = leftArrayNotes[i], right = leftArrayNotes[i] + widthArrayNotes[i] };
            }

            return layout;
        }

        public static bool IsBlackKey(int n)
        {
            n = n % 12;
            if (n < 0) n += 12;
            return n == 1 || n == 3 || n == 6 || n == 8 || n == 10;
        }

        public static IEnumerable<Note> BlackNotesAbove(IEnumerable<Note> notes)
        {
            foreach (var n in notes)
            {
                if (!IsBlackKey(n.key)) yield return n;
            }

            foreach (var n in notes)
            {
                if (IsBlackKey(n.key)) yield return n;
            }
        }

        public static Color4 BlendColors(Color4 col1, Color4 col2)
        {
            float blendfac = col2.A;
            float revblendfac = 1 - blendfac;
            return new Color4(
                col2.R * blendfac + col1.R * revblendfac,
                col2.G * blendfac + col1.G * revblendfac,
                col2.B * blendfac + col1.B * revblendfac,
                col1.A + (1 - col1.A) * blendfac);
        }
    }
}


================================================
FILE: BMEngine/UI/BBinding.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;

namespace ZenithEngine.UI
{
    public class BBinding : Binding
    {
        public BBinding(DependencyProperty dp, object source) : base()
        {
            Path = new PropertyPath(dp);
            Source = source;
        }
    }
}


================================================
FILE: BMEngine/UI/BetterCheckbox.xaml
================================================
<UserControl x:Class="ZenithEngine.UI.BetterCheckbox"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:ZenithEngine.UI"
             mc:Ignorable="d" Name="root" >
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Material.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>
    <DockPanel MouseDown="DockPanel_MouseDown" Background="Transparent">
        <Grid Margin="4,0,0,0" VerticalAlignment="Center">
            <Border Width="16" Height="16" BorderThickness="2" Background="Transparent" CornerRadius="3">

                <Border.Style>
                    <Style TargetType="Border">
                        <Setter Property="BorderBrush" Value="{StaticResource PrimaryBrush}"/>
                        <Style.Triggers>
                            <Trigger Property="IsEnabled" Value="False">
                                <Setter Property="BorderBrush" Value="#777777"/>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </Border.Style>
                <Border Name="checkedBox" Margin="2" CornerRadius="1">
                    <Border.Style>
                        <Style TargetType="Border">
                            <Setter Property="Background" Value="{StaticResource PrimaryBrush}"/>
                            <Style.Triggers>
                                <Trigger Property="IsEnabled" Value="False">
                                    <Setter Property="Background" Value="#777777"/>
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </Border.Style>
                </Border>
            </Border>
            <Grid Name="rippleBox" Margin="-7">

            </Grid>
        </Grid>
        <TextBlock FontSize="14" Margin="3,-3,0,0" Text="{Binding ElementName=root, Path=Text}" VerticalAlignment="Center"/>
    </DockPanel>
</UserControl>


================================================
FILE: BMEngine/UI/BetterCheckbox.xaml.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ZenithEngine.UI
{
    /// <summary>
    /// Interaction logic for BetterCheckbox.xaml
    /// </summary>
    public partial class BetterCheckbox : UserControl
    {
        public bool IsChecked
        {
            get { return (bool)GetValue(IsCheckedProperty); }
            set { SetValue(IsCheckedProperty, value); }
        }

        public static readonly DependencyProperty IsCheckedProperty =
            DependencyProperty.Register("IsChecked", typeof(bool), typeof(BetterCheckbox), new PropertyMetadata(false, (s, e) => ((BetterCheckbox)s).OnCheckChanged()));


        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(string), typeof(BetterCheckbox), new PropertyMetadata(""));


        public static readonly RoutedEvent CheckToggledEvent = EventManager.RegisterRoutedEvent(
            "RadioChecked", RoutingStrategy.Bubble,
            typeof(RoutedPropertyChangedEventHandler<bool>), typeof(BetterCheckbox));

        public event RoutedPropertyChangedEventHandler<bool> CheckToggled
        {
            add { AddHandler(CheckToggledEvent, value); }
            remove { RemoveHandler(CheckToggledEvent, value); }
        }


        void OnCheckChanged()
        {
            RaiseEvent(new RoutedPropertyChangedEventArgs<bool>(!IsChecked, IsChecked, CheckToggledEvent));
        }


        public BetterCheckbox()
        {
            InitializeComponent();
            new InplaceConverter(new[] {
                new BBinding(IsCheckedProperty, this)
            }, v => (bool)v[0] ? Visibility.Visible : Visibility.Hidden)
                .Set(checkedBox, VisibilityProperty);
        }

        private void DockPanel_MouseDown(object sender, MouseButtonEventArgs e)
        {
            IsChecked = !IsChecked;


            double ExpandTime = 0.1;
            double FadeTime = 0.1;

            double o = 0.7;

            var targetWidth = rippleBox.ActualWidth;

            var ellipse = new Ellipse()
            {
                Fill = (Brush)Resources["PrimaryBrush"],
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
                Opacity = o
            };
            ellipse.SetBinding(HeightProperty, new Binding("Width") { Source = ellipse });

            Storyboard storyboard = new Storyboard();

            var expand = new DoubleAnimation(10, targetWidth, new Duration(TimeSpan.FromSeconds(ExpandTime + FadeTime)));
            storyboard.Children.Add(expand);
            Storyboard.SetTarget(expand, ellipse);
            Storyboard.SetTargetProperty(expand, new PropertyPath(WidthProperty));

            var opacity = new DoubleAnimation(o, 0, new Duration(TimeSpan.FromSeconds(FadeTime)));
            opacity.BeginTime = TimeSpan.FromSeconds(ExpandTime);
            storyboard.Children.Add(opacity);
            Storyboard.SetTarget(opacity, ellipse);
            Storyboard.SetTargetProperty(opacity, new PropertyPath(Ellipse.OpacityProperty));

            rippleBox.Children.Add(ellipse);

            storyboard.Begin();

            var waitTime = ExpandTime + FadeTime;
            Task.Run(() =>
            {
                Thread.Sleep(TimeSpan.FromSeconds(waitTime));
                Dispatcher.Invoke(() =>
                {
                    rippleBox.Children.Remove(ellipse);
                });
            });
        }
    }
}


================================================
FILE: BMEngine/UI/BetterRadio.xaml
================================================
<UserControl x:Class="ZenithEngine.UI.BetterRadio"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:ZenithEngine.UI"
             mc:Ignorable="d" Name="root">
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Material.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>
    <DockPanel MouseDown="DockPanel_MouseDown" Background="Transparent">
        <Grid VerticalAlignment="Center">
            <Border Width="16" Height="16" BorderThickness="2" BorderBrush="{StaticResource PrimaryBrush}" Background="Transparent" CornerRadius="10">
                <Border Name="checkedBox" Margin="2" CornerRadius="10" Background="{StaticResource PrimaryBrush}">
                </Border>
            </Border>
            <Grid Name="rippleBox" Margin="-7">

            </Grid>
        </Grid>
        <TextBlock FontSize="14" Margin="3,0,0,0" Text="{Binding ElementName=root, Path=Text}" VerticalAlignment="Center"/>
    </DockPanel>
</UserControl>


================================================
FILE: BMEngine/UI/BetterRadio.xaml.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ZenithEngine.UI
{
    /// <summary>
    /// Interaction logic for BetterRadio.xaml
    /// </summary>
    public partial class BetterRadio : UserControl
    {
        public bool IsChecked
        {
            get { return (bool)GetValue(IsCheckedProperty); }
            set { SetValue(IsCheckedProperty, value); }
        }

        public static readonly DependencyProperty IsCheckedProperty =
            DependencyProperty.Register("IsChecked", typeof(bool), typeof(BetterRadio), new PropertyMetadata(false, (s, e) => ((BetterRadio)s).OnCheckChanged()));


        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(string), typeof(BetterRadio), new PropertyMetadata(""));


        public int ParentDepth
        {
            get { return (int)GetValue(ParentDepthProperty); }
            set { SetValue(ParentDepthProperty, value); }
        }

        public static readonly DependencyProperty ParentDepthProperty =
            DependencyProperty.Register("ParentDepth", typeof(int), typeof(BetterRadio), new PropertyMetadata(1));


        public static readonly RoutedEvent RadioCheckedEvent = EventManager.RegisterRoutedEvent(
            "RadioChecked", RoutingStrategy.Bubble,
            typeof(RoutedEventHandler), typeof(BetterRadio));

        public event RoutedEventHandler RadioChecked
        {
            add { AddHandler(RadioCheckedEvent, value); }
            remove { RemoveHandler(RadioCheckedEvent, value); }
        }


        void OnCheckChanged()
        {
            if (IsChecked)
            {
                if (ParentDepth != 0)
                {
                    FrameworkElement p = (FrameworkElement)Parent;
                    for (int i = 1; i < ParentDepth; i++)
                    {
                        p = (FrameworkElement)p.Parent;
                    }
                    RecursiveUncheck(p);
                }
                RaiseEvent(new RoutedEventArgs(RadioCheckedEvent));
            }
        }


        public BetterRadio()
        {
            InitializeComponent();
            new InplaceConverter(new[] {
                new BBinding(IsCheckedProperty, this)
            }, v => (bool)v[0] ? Visibility.Visible : Visibility.Hidden)
                .Set(checkedBox, VisibilityProperty);
        }

        void RecursiveUncheck(FrameworkElement p)
        {
            if (p is Panel)
                foreach (var c in ((Panel)p).Children) if(c is FrameworkElement) RecursiveUncheck((FrameworkElement)c);
            if (p is BetterRadio && p != this) ((BetterRadio)p).IsChecked = false;
        }

        private void DockPanel_MouseDown(object sender, MouseButtonEventArgs e)
        {
            IsChecked = true;

            double ExpandTime = 0.1;
            double FadeTime = 0.1;

            double o = 0.7;

            var targetWidth = rippleBox.ActualWidth;

            var ellipse = new Ellipse()
            {
                Fill = (Brush)Resources["PrimaryBrush"],
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
                Opacity = o
            };
            ellipse.SetBinding(HeightProperty, new Binding("Width") { Source = ellipse });

            Storyboard storyboard = new Storyboard();

            var expand = new DoubleAnimation(10, targetWidth, new Duration(TimeSpan.FromSeconds(ExpandTime + FadeTime)));
            storyboard.Children.Add(expand);
            Storyboard.SetTarget(expand, ellipse);
            Storyboard.SetTargetProperty(expand, new PropertyPath(WidthProperty));

            var opacity = new DoubleAnimation(o, 0, new Duration(TimeSpan.FromSeconds(FadeTime)));
            opacity.BeginTime = TimeSpan.FromSeconds(ExpandTime);
            storyboard.Children.Add(opacity);
            Storyboard.SetTarget(opacity, ellipse);
            Storyboard.SetTargetProperty(opacity, new PropertyPath(Ellipse.OpacityProperty));

            rippleBox.Children.Add(ellipse);

            storyboard.Begin();

            var waitTime = ExpandTime + FadeTime;
            Task.Run(() =>
            {
                Thread.Sleep(TimeSpan.FromSeconds(waitTime));
                Dispatcher.Invoke(() =>
                {
                    rippleBox.Children.Remove(ellipse);
                });
            });
        }
    }
}


================================================
FILE: BMEngine/UI/BetterSlider.xaml
================================================
<UserControl x:Class="ZenithEngine.UI.BetterSlider"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:ZenithEngine.UI"
             mc:Ignorable="d" 
             Name="slider"
             d:DesignHeight="30" d:DesignWidth="800" Focusable="True">
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Material.xaml"/>
            </ResourceDictionary.MergedDictionaries>
            <local:DoubleMultiplyConverter x:Key="DoubleMultiplyConverter"/>
            <local:ThicknessConverter x:Key="ThicknessConverter"/>
        </ResourceDictionary>
    </UserControl.Resources>
    <Grid Height="14" Name="clickerGrid" Background="Transparent" MouseEnter="ClickerGrid_MouseEnter" MouseLeave="ClickerGrid_MouseLeave" MouseDown="ClickerGrid_MouseDown" MouseMove="ClickerGrid_MouseMove" MouseUp="ClickerGrid_MouseUp">
        <Grid Margin="5" VerticalAlignment="Center" Name="barGrid" Height="4" Background="#55000000">
            <Rectangle HorizontalAlignment="Left" Fill="{StaticResource PrimaryBrush}" Opacity="0.8">
                <Rectangle.Style>
                    <Style TargetType="Rectangle">
                        <Setter Property="Fill" Value="{StaticResource PrimaryBrush}"/>
                        <Style.Triggers>
                            <Trigger Property="IsEnabled" Value="False">
                                <Setter Property="Fill" Value="#777777"/>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </Rectangle.Style>
                <Rectangle.Width>
                    <Binding ElementName="slider" Path="ScaledValue"/>
                </Rectangle.Width>
            </Rectangle>
        </Grid>
        <Grid Name="headGrid" HorizontalAlignment="Left" VerticalAlignment="Center" Height="10" Width="10">
            <Ellipse Name="trueHead" Width="10" Height="10" HorizontalAlignment="Center" VerticalAlignment="Center">
                <Ellipse.Style>
                    <Style TargetType="Ellipse">
                        <Setter Property="Fill" Value="{StaticResource PrimaryBrush}"/>
                        <Style.Triggers>
                            <Trigger Property="IsEnabled" Value="False">
                                <Setter Property="Fill" Value="#777777"/>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </Ellipse.Style>
            </Ellipse>
            <Grid Margin="-7" Name="auraGrid">
                <Ellipse Name="hoverEllipse" Visibility="Hidden" Fill="#44000000"/>
            </Grid>
        </Grid>
    </Grid>
</UserControl>


================================================
FILE: BMEngine/UI/BetterSlider.xaml.cs
================================================
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ZenithEngine.UI
{
    /// <summary>
    /// Interaction logic for BetterSlider.xaml
    /// </summary>
    public partial class BetterSlider : UserControl
    {
        public double Minimum
        {
            get { return (double)GetValue(MinimumProperty); }
            set { SetValue(MinimumProperty, value); }
        }

        public static readonly DependencyProperty MinimumProperty =
            DependencyProperty.Register("Minimum", typeof(double), typeof(BetterSlider), new PropertyMetadata(0.0));


        public double Maximum
        {
            get { return (double)GetValue(MaximumProperty); }
            set { SetValue(MaximumProperty, value); }
        }

        public static readonly DependencyProperty MaximumProperty =
            DependencyProperty.Register("Maximum", typeof(double), typeof(BetterSlider), new PropertyMetadata(0.0));


        static void ValueChangedCallback(DependencyObject s, DependencyPropertyChangedEventArgs e)
        {
            var slider = (BetterSlider)s;
            //slider.ScaledValue = (slider.Value - slider.Minimum) / slider.Maximum * slider.barGrid.ActualWidth;
        }

        public double Value
        {
            get { return (double)GetValue(ValueProperty); }
            set
            {
                var v = value;
                if (v > Maximum) v = Maximum;
                if (v < Minimum) v = Minimum;
                SetValue(ValueProperty, v);
            }
        }

        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(double), typeof(BetterSlider), new PropertyMetadata(0.0, ValueChangedCallback));


        double ScaledValue
        {
            get { return (double)GetValue(ScaledValueProperty); }
            set { SetValue(ScaledValueProperty, value); }
        }

        static readonly DependencyProperty ScaledValueProperty =
            DependencyProperty.Register("ScaledValue", typeof(double), typeof(BetterSlider), new PropertyMetadata(0.0));


        public event EventHandler<double> UserValueChanged;


        public BetterSlider()
        {
            InitializeComponent();

            new InplaceConverter(new[]
            {
                new BBinding(ValueProperty, this),
                new BBinding(MinimumProperty, this),
                new BBinding(MaximumProperty, this),
                new BBinding(ActualWidthProperty, barGrid),
            },
            (values) =>
            {
                try
                {
                    return ((double)values[0] - (double)values[1]) / ((double)values[2] - (double)values[1]) * (double)values[3];
                }
                catch { return 0; }
            })
                .Set(this, ScaledValueProperty);

            new InplaceConverter(new[] { new BBinding(ScaledValueProperty, this) },
            (values) => new Thickness((double)values[0], 0, 0, 0))
                .Set(headGrid, MarginProperty);
        }

        private void ClickerGrid_MouseEnter(object sender, MouseEventArgs e)
        {
            //hoverEllipse.Visibility = Visibility.Visible;
        }

        private void ClickerGrid_MouseLeave(object sender, MouseEventArgs e)
        {
            //hoverEllipse.Visibility = Visibility.Hidden;
        }

        private void ClickerGrid_MouseDown(object sender, MouseButtonEventArgs e)
        {
            clickerGrid.CaptureMouse();
            Value = e.GetPosition(barGrid).X / barGrid.ActualWidth * (Maximum - Minimum) + Minimum;
            UserValueChanged?.Invoke(this, Value);
            AddRipple();
            this.Focus();
        }

        private void ClickerGrid_MouseMove(object sender, MouseEventArgs e)
        {
            if (clickerGrid.IsMouseCaptureWithin)
            {
                Value = e.GetPosition(barGrid).X / barGrid.ActualWidth * (Maximum - Minimum) + Minimum;
                UserValueChanged?.Invoke(this, Value);
            }
        }

        private void ClickerGrid_MouseUp(object sender, MouseButtonEventArgs e)
        {
            clickerGrid.ReleaseMouseCapture();
        }

        void AddRipple()
        {
            double ExpandTime = 0.1;
            double FadeTime = 0.1;

            double o = 0.7;

            var targetWidth = auraGrid.ActualWidth;

            var ellipse = new Ellipse()
            {
                Fill = (Brush)Resources["PrimaryBrush"],
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
                Opacity = o
            };
            ellipse.SetBinding(HeightProperty, new Binding("Width") { Source = ellipse });

            Storyboard storyboard = new Storyboard();

            var expand = new DoubleAnimation(0, targetWidth, new Duration(TimeSpan.FromSeconds(ExpandTime + FadeTime)));
            storyboard.Children.Add(expand);
            Storyboard.SetTarget(expand, ellipse);
            Storyboard.SetTargetProperty(expand, new PropertyPath(WidthProperty));

            var opacity = new DoubleAnimation(o, 0, new Duration(TimeSpan.FromSeconds(FadeTime)));
            opacity.BeginTime = TimeSpan.FromSeconds(ExpandTime);
            storyboard.Children.Add(opacity);
            Storyboard.SetTarget(opacity, ellipse);
            Storyboard.SetTargetProperty(opacity, new PropertyPath(Ellipse.OpacityProperty));

            auraGrid.Children.Add(ellipse);

            storyboard.Begin();

            var waitTime = ExpandTime + FadeTime;
            Task.Run(() =>
            {
                Thread.Sleep(TimeSpan.FromSeconds(waitTime));
                Dispatcher.Invoke(() =>
                {
                    headGrid.Children.Remove(ellipse);
                });
            });
        }
    }

    public class DoubleMultiplyConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            double r = 1;
            foreach (var v in values) r *= (double)v;
            return r;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    public class ScaledValueConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return ((double)values[0] - (double)values[1]) / ((double)values[2] - (double)values[1]) * (double)values[3];
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    public class ThicknessConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return new Thickness(
                    (double)value,
                    0,
                    0,
                    0
                );
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}


================================================
FILE: BMEngine/UI/Colors.xaml
================================================
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:ZenithEngine.UI"
                    xmlns:sys="clr-namespace:System;assembly=mscorlib"
                    xmlns:theme="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero2"
                    xmlns:media="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
    <media:Color x:Key="PrimaryColor" >#2E7D32</media:Color>
    <SolidColorBrush x:Key="PrimaryBrush" Color="{StaticResource PrimaryColor}"/>
</ResourceDictionary>

================================================
FILE: BMEngine/UI/Converters.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;

namespace ZenithEngine.UI
{

    public class AndValueConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            bool b = true;
            for (int i = 0; i < values.Length; i++) b = b && (bool)values[i];

            return b;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    public class OrValueConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            bool b = false;
            for (int i = 0; i < values.Length; i++) b = b || (bool)values[i];

            return b;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    public class NotValueConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return !(bool)values[0];
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}


================================================
FILE: BMEngine/UI/HexColorPicker.xaml
================================================
<UserControl x:Class="ZenithEngine.UI.HexColorPicker"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:ZenithEngine.UI"
             mc:Ignorable="d" KeyDown="UserControl_KeyDown">
    <Grid>
        <TextBox FontSize="14" Background="Transparent" BorderThickness="0" Name="hexText" Text="FFFFFF" TextChanged="HexText_TextChanged" LostFocus="HexText_LostFocus"/>
        <Rectangle Fill="Black" Height="1" VerticalAlignment="Bottom"/>
    </Grid>
</UserControl>


================================================
FILE: BMEngine/UI/HexColorPicker.xaml.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ZenithEngine.UI
{
    /// <summary>
    /// Interaction logic for HexColorPicker.xaml
    /// </summary>
    public partial class HexColorPicker : UserControl
    {
        public Color Color
        {
            get { return (Color)GetValue(ColorProperty); }
            set { SetValue(ColorProperty, value); }
        }

        public static readonly DependencyProperty ColorProperty =
            DependencyProperty.Register("Color", typeof(Color), typeof(HexColorPicker), new PropertyMetadata(Color.FromArgb(255, 255, 255, 255), (s, e) => ((HexColorPicker)s).OnColorPropertyChanged(e)));


        public bool UseAlpha
        {
            get { return (bool)GetValue(UseAlphaProperty); }
            set { SetValue(UseAlphaProperty, value); }
        }

        public static readonly DependencyProperty UseAlphaProperty =
            DependencyProperty.Register("UseAlpha", typeof(bool), typeof(HexColorPicker), new PropertyMetadata(false));

        public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent(
            "ValueChanged", RoutingStrategy.Bubble,
            typeof(RoutedPropertyChangedEventHandler<Color>), typeof(HexColorPicker));

        public event RoutedPropertyChangedEventHandler<Color> ValueChanged
        {
            add { AddHandler(ValueChangedEvent, value); }
            remove { RemoveHandler(ValueChangedEvent, value); }
        }


        void OnColorPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            SaveString();
            RaiseEvent(new RoutedPropertyChangedEventArgs<Color>((Color)e.OldValue, (Color)e.NewValue, ValueChangedEvent));
        }

        string Hexify(byte val)
        {
            var s = val.ToString("X");
            if (s.Length == 1) return "0" + s;
            return s;
        }

        void SaveString()
        {
            string s = "";
            s += Hexify(Color.R);
            s += Hexify(Color.G);
            s += Hexify(Color.B);
            if (UseAlpha && (hexText.Text.Length != 6 || Color.A != 255))
                s += Hexify(Color.A);
            if (hexText.Text != s)
                hexText.Text = s;
        }


        public HexColorPicker()
        {
            InitializeComponent();

            new InplaceConverter(
                new[] { new BBinding(UseAlphaProperty, this) },
                (e) => (bool)e[0] ? 8 : 6
            ).Set(hexText, TextBox.MaxLengthProperty);
        }

        private void HexText_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (!((hexText.Text.Length == 6) || (UseAlpha && hexText.Text.Length == 8))) return;
            try
            {
                int col = int.Parse(hexText.Text, System.Globalization.NumberStyles.HexNumber);
                Color c;
                if (hexText.Text.Length == 8)
                    c = Color.FromArgb(
                        (byte)((col >> 0) & 0xFF),
                        (byte)((col >> 24) & 0xFF),
                        (byte)((col >> 16) & 0xFF),
                        (byte)((col >> 8) & 0xFF)
                    );
                else
                    c = Color.FromArgb(
                        255,
                        (byte)((col >> 16) & 0xFF),
                        (byte)((col >> 8) & 0xFF),
                        (byte)((col >> 0) & 0xFF)
                    );
                Color = c;
            }
            catch { }
        }

        private void HexText_LostFocus(object sender, RoutedEventArgs e)
        {
            SaveString();
        }

        private void UserControl_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                SaveString();
                e.Handled = true;
                Keyboard.ClearFocus();

                FrameworkElement parent = (FrameworkElement)hexText.Parent;
                while (parent != null && parent is IInputElement && !((IInputElement)parent).Focusable)
                {
                    parent = (FrameworkElement)parent.Parent;
                }

                DependencyObject scope = FocusManager.GetFocusScope(hexText);
                FocusManager.SetFocusedElement(scope, parent as IInputElement);
            }
        }
    }
}


================================================
FILE: BMEngine/UI/InplaceConverter.cs
================================================
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using System.Reflection;

namespace ZenithEngine.UI
{
    public class InplaceConverter : IMultiValueConverter
    {
        Func<object[], object> func;
        Binding[] bindings;

        public InplaceConverter(Binding[] bindings, Func<object[], object> func)
        {
            this.bindings = bindings;
            this.func = func;
        }

        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            return func(values);
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        public void Set(FrameworkElement o, DependencyProperty p)
        {
            var b = new MultiBinding();
            b.Converter = this;
            foreach (var _b in bindings) b.Bindings.Add(_b);
            o.SetBinding(p, b);
        }
    }
}


================================================
FILE: BMEngine/UI/ListBox.xaml
================================================
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:ZenithEngine.UI"
                    xmlns:sys="clr-namespace:System;assembly=mscorlib"
                    xmlns:theme="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero2"
                    xmlns:media="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="Colors.xaml"/>
    </ResourceDictionary.MergedDictionaries>
    <media:Style TargetType="{x:Type media:ListBox}">
        <media:Setter Property="BorderThickness" Value="1"/>
        <media:Setter Property="media:ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
        <media:Setter Property="media:ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
        <media:Setter Property="media:ScrollViewer.CanContentScroll" Value="true"/>
        <media:Setter Property="media:ScrollViewer.PanningMode" Value="Both"/>
        <media:Setter Property="media:Stylus.IsFlicksEnabled" Value="False"/>
        <media:Setter Property="VerticalContentAlignment" Value="Center"/>
        <media:Setter Property="Template">
            <media:Setter.Value>
                <media:ControlTemplate TargetType="{x:Type media:ListBox}">
                    <media:Border x:Name="Bd" BorderBrush="Black" BorderThickness="1" Background="Transparent" Padding="1" SnapsToDevicePixels="true">
                        <media:ScrollViewer Focusable="false" Padding="{media:TemplateBinding Padding}">
                            <media:ItemsPresenter SnapsToDevicePixels="{media:TemplateBinding SnapsToDevicePixels}"/>
                        </media:ScrollViewer>
                    </media:Border>
                </media:ControlTemplate>
            </media:Setter.Value>
        </media:Setter>
    </media:Style>
    <media:Style TargetType="{x:Type media:ListBoxItem}">
        <media:Setter Property="SnapsToDevicePixels" Value="True"/>
        <media:Setter Property="Padding" Value="4,1"/>
        <media:Setter Property="HorizontalContentAlignment" Value="{media:Binding HorizontalContentAlignment, RelativeSource={media:RelativeSource AncestorType={x:Type media:ItemsControl}}}"/>
        <media:Setter Property="VerticalContentAlignment" Value="{media:Binding VerticalContentAlignment, RelativeSource={media:RelativeSource AncestorType={x:Type media:ItemsControl}}}"/>
        <media:Setter Property="Background" Value="Transparent"/>
        <media:Setter Property="BorderBrush" Value="Transparent"/>
        <media:Setter Property="BorderThickness" Value="1"/>
        <media:Setter Property="FontSize" Value="14"/>
        <media:Setter Property="Foreground" Value="White"/>
        <media:Setter Property="Padding" Value="5"/>
        <media:Setter Property="Template">
            <media:Setter.Value>
                <media:ControlTemplate TargetType="{x:Type media:ListBoxItem}">
                    <local:RippleEffectDecorator>
                        <media:Border x:Name="Bd" Background="{media:TemplateBinding Background}" Padding="{media:TemplateBinding Padding}" SnapsToDevicePixels="true">
                            <media:ContentPresenter HorizontalAlignment="{media:TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{media:TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{media:TemplateBinding VerticalContentAlignment}"/>
                        </media:Border>
                    </local:RippleEffectDecorator>
                    <media:ControlTemplate.Triggers>
                        <media:MultiTrigger>
                            <media:MultiTrigger.Conditions>
                                <media:Condition Property="IsMouseOver" Value="True"/>
                            </media:MultiTrigger.Conditions>
                            <media:Setter Property="Background" TargetName="Bd" Value="#11FFFFFF"/>
                        </media:MultiTrigger>
                        <media:MultiTrigger>
                            <media:MultiTrigger.Conditions>
                                <media:Condition Property="IsSelected" Value="True"/>
                            </media:MultiTrigger.Conditions>
                            <media:Setter Property="Background" TargetName="Bd" Value="#33FFFFFF"/>
                        </media:MultiTrigger>
                    </media:ControlTemplate.Triggers>
                </media:ControlTemplate>
            </media:Setter.Value>
        </media:Setter>
    </media:Style>
</ResourceDictionary>

================================================
FILE: BMEngine/UI/Material.xaml
================================================
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:ZenithEngine.UI"
                    xmlns:sys="clr-namespace:System;assembly=mscorlib"
                    xmlns:theme="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero2"
                    xmlns:media="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="Scrollbar.xaml"/>
        <ResourceDictionary Source="Colors.xaml"/>
        <ResourceDictionary Source="ListBox.xaml"/>
    </ResourceDictionary.MergedDictionaries>
    <Style TargetType="{x:Type TextBlock}">
        <Setter Property="Control.Foreground" Value="White"/>
        <Setter Property="Control.FontSize" Value="14"/>
    </Style>
    <Style TargetType="{x:Type Label}">
        <Setter Property="Control.Foreground" Value="White"/>
        <Setter Property="Control.FontSize" Value="14"/>
    </Style>
    <Style x:Key="WindowButton" TargetType="Button">
        <Setter Property="OverridesDefaultStyle" Value="True"/>
        <Setter Property="Focusable" Value="False"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Border Name="border"
                        BorderThickness="1"
                        Padding="4,2"
                        BorderBrush="DarkGray"
                        CornerRadius="3"
                        Background="{TemplateBinding Background}">
                        <Grid >
                            <ContentPresenter HorizontalAlignment="Center"
                           VerticalAlignment="Center" Name="content"/>
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="border" Property="BorderBrush" Value="#FF4788c8" />
                            <Setter Property="Foreground" Value="#FF4788c8" />
                        </Trigger>
                        <Trigger Property="IsPressed" Value="True">
                        </Trigger>
                        <Trigger Property="IsDefaulted" Value="True">
                        </Trigger>
                        <Trigger Property="IsFocused" Value="True">
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="MenuButtonStyle" TargetType="Button">
        <Setter Property="OverridesDefaultStyle" Value="True"/>
        <Setter Property="Focusable" Value="False"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Border Name="border"
                        Padding="4,2"
                        Background="{TemplateBinding Background}">
                        <Grid >
                            <ContentPresenter HorizontalAlignment="Center"
                           VerticalAlignment="Center" Name="content"/>
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Background" Value="#44FFFFFF" />
                        </Trigger>
                        <Trigger Property="IsPressed" Value="True">
                        </Trigger>
                        <Trigger Property="IsDefaulted" Value="True">
                        </Trigger>
                        <Trigger Property="IsFocused" Value="True">
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="MainTabs" TargetType="TabItem">
        <Setter Property="Foreground" Value="White"/>
        <Setter Property="FontSize" Value="14"/>
        <Setter Property="HorizontalAlignment" Value="Left"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="TabItem">
                    <Grid Name="Panel">
                        <local:RippleEffectDecorator ExpandTime="0.2" FadeTime="0.2">
                            <ContentPresenter x:Name="ContentSite"
                                        VerticalAlignment="Center"
                                        HorizontalAlignment="Center"
                                        ContentSource="Header"
                                        Margin="10,2"/>
                        </local:RippleEffectDecorator>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter TargetName="Panel" Property="Background" Value="#33FFFFFF" />
                        </Trigger>
                        <Trigger Property="IsSelected" Value="False">
                            <Setter TargetName="Panel" Property="Background" Value="Transparent" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="SubTabItems" TargetType="TabItem">
        <Setter Property="Foreground" Value="White"/>
        <Setter Property="FontSize" Value="14"/>
        <Setter Property="HorizontalAlignment" Value="Left"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="TabItem">
                    <Grid Name="Panel" Height="30">
                        <local:RippleEffectDecorator ExpandTime="0.2" FadeTime="0.2">
                            <ContentPresenter x:Name="ContentSite"
                                        VerticalAlignment="Center"
                                        HorizontalAlignment="Center"
                                        ContentSource="Header"
                                        Margin="10,2"/>
                        </local:RippleEffectDecorator>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter TargetName="Panel" Property="Background" Value="#33FFFFFF" />
                        </Trigger>
                        <Trigger Property="IsSelected" Value="False">
                            <Setter TargetName="Panel" Property="Background" Value="Transparent" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="SubTabs" TargetType="TabControl">
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TabControl}">
                    <DockPanel LastChildFill="True">
                        <Border Name="titlebar" Grid.Row="0" DockPanel.Dock="Top" Visibility="{Binding ChromeVisibility, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" Background="#11FFFFFF">
                            <DockPanel>
                                <TabPanel
                                    Grid.Row="0"
                                    Panel.ZIndex="1"
                                    Margin="0,0,0,0"
                                    IsItemsHost="True"
                                    Background="Transparent" />
                            </DockPanel>
                        </Border>
                        <Border Grid.Row="1" CornerRadius="0, 12, 12, 12" >
                            <ContentPresenter ContentSource="SelectedContent" />
                        </Border>
                    </DockPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style TargetType="Button">
        <Setter Property="OverridesDefaultStyle" Value="True"/>
        <Setter Property="Focusable" Value="False"/>
        <Setter Property="FontSize" Value="14"/>
        <Setter Property="Foreground" Value="White"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ContentControl">
                    <Grid Background="{TemplateBinding Background}" Width="{TemplateBinding Width}">
                        <Border x:Name="background">
                            <Border.Background>
                                <SolidColorBrush x:Name="bgBrush" Color="{StaticResource PrimaryColor}"/>
                            </Border.Background>
                            <Border.Effect>
                                <DropShadowEffect x:Name="dropShadow" ShadowDepth="0" Direction="0" BlurRadius="5"/>
                            </Border.Effect>
                        </Border>
                        <local:RippleEffectDecorator ExpandTime="0.2" FadeTime="0.2">
                            <Border Padding="{TemplateBinding Padding}">
                                <ContentPresenter HorizontalAlignment="Center"
                           VerticalAlignment="Center" Name="content"/>
                            </Border>
                        </local:RippleEffectDecorator>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Value="True" Property="IsMouseOver">
                            <Trigger.EnterActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <ColorAnimation Storyboard.TargetName="bgBrush" Storyboard.TargetProperty="Color" Duration="0:0:0.1" To="#43A047" />
                                        <DoubleAnimation Storyboard.TargetName="dropShadow" Storyboard.TargetProperty="BlurRadius" Duration="0:0:0.1" To="10" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </Trigger.EnterActions>
                            <Trigger.ExitActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <ColorAnimation Storyboard.TargetName="bgBrush" Storyboard.TargetProperty="Color" Duration="0:0:0.1" To="{StaticResource PrimaryColor}" />
                                        <DoubleAnimation Storyboard.TargetName="dropShadow" Storyboard.TargetProperty="BlurRadius" Duration="0:0:0.1" To="5" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </Trigger.ExitActions>
                        </Trigger>
                        <Trigger Value="False" Property="IsEnabled">
                            <Trigger.EnterActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <ColorAnimation Storyboard.TargetName="bgBrush" Storyboard.TargetProperty="Color" Duration="0:0:0.1" To="#222222" />
                                        <DoubleAnimation Storyboard.TargetName="dropShadow" Storyboard.TargetProperty="BlurRadius" Duration="0:0:0.0" To="3" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </Trigger.EnterActions>
                            <Trigger.ExitActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <ColorAnimation Storyboard.TargetName="bgBrush" Storyboard.TargetProperty="Color" Duration="0:0:0.1" To="{StaticResource PrimaryColor}" />
                                        <DoubleAnimation Storyboard.TargetName="dropShadow" Storyboard.TargetProperty="BlurRadius" Duration="0:0:0.0" To="5" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </Trigger.ExitActions>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    
    <Style x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}">
        <Setter Property="OverridesDefaultStyle" Value="true"/>
        <Setter Property="IsTabStop" Value="false"/>
        <Setter Property="Focusable" Value="false"/>
        <Setter Property="ClickMode" Value="Press"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ToggleButton}">
                    <Grid>
                        <Border Background="Black">
                            <Border.Effect>
                                <DropShadowEffect x:Name="dropShadow" ShadowDepth="0" BlurRadius="5"/>
                            </Border.Effect>
                        </Border>
                        <Border x:Name="templateRoot" SnapsToDevicePixels="true">
                            <Border.Background>
                                <SolidColorBrush x:Name="solidBrush" Color="#222222"/>
                            </Border.Background>
                            <Border x:Name="splitBorder" BorderBrush="Transparent" BorderThickness="1" HorizontalAlignment="Right" Margin="0" SnapsToDevicePixels="true" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}">
                                <Path x:Name="arrow" Data="F1 M -2,0 L 2.667,2.66665 L 7.3334,0 L 7.3334,-1.78168 L 2.6667,0.88501 L-2,-1.78168 L-2,0 Z" Fill="#2E7D32" HorizontalAlignment="Center" Margin="0" VerticalAlignment="Center"/>
                            </Border>
                        </Border>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <DataTrigger Value="True">
                            <DataTrigger.Binding>
                                <MultiBinding>
                                    <MultiBinding.Converter>
                                        <local:OrValueConverter/>
                                    </MultiBinding.Converter>
                                    <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="IsMouseOver" />
                                </MultiBinding>
                            </DataTrigger.Binding>
                            <DataTrigger.EnterActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <ColorAnimation Storyboard.TargetName="solidBrush" Storyboard.TargetProperty="Color" Duration="0:0:0.1" To="#292929" />
                                        <DoubleAnimation Storyboard.TargetName="dropShadow" Storyboard.TargetProperty="BlurRadius" Duration="0:0:0.1" To="10" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </DataTrigger.EnterActions>
                            <DataTrigger.ExitActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <ColorAnimation Storyboard.TargetName="solidBrush" Storyboard.TargetProperty="Color" Duration="0:0:0.1" To="#222222" />
                                        <DoubleAnimation Storyboard.TargetName="dropShadow" Storyboard.TargetProperty="BlurRadius" Duration="0:0:0.1" To="5" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </DataTrigger.ExitActions>
                        </DataTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style TargetType="{x:Type ComboBox}">
        <Setter Property="FontSize" Value="14"/>
        <Setter Property="Foreground" Value="White"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ComboBox}">
                    <Grid x:Name="templateRoot" SnapsToDevicePixels="true">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Width="0"/>
                        </Grid.ColumnDefinitions>
                        <Popup x:Name="PART_Popup" AllowsTransparency="true" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom">
                            <Grid MinWidth="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ActualWidth}">
                                <Border Background="Black">
                                    <Border.Effect>
                                        <DropShadowEffect ShadowDepth="0" BlurRadius="5"/>
                                    </Border.Effect>
                                </Border>
                                <Border x:Name="dropDownBorder">
                                    <ScrollViewer x:Name="DropDownScrollViewer">
                                        <Grid x:Name="grid" RenderOptions.ClearTypeHint="Enabled">
                                            <Canvas x:Name="canvas" HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
                                                <Rectangle x:Name="opaqueRect" Fill="{Binding Background, ElementName=dropDownBorder}" Height="{Binding ActualHeight, ElementName=dropDownBorder}" Width="{Binding ActualWidth, ElementName=dropDownBorder}"/>
                                            </Canvas>
                                            <ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                                        </Grid>
                                    </ScrollViewer>
                                </Border>
                            </Grid>
                        </Popup>
                        <ToggleButton x:Name="toggleButton" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.ColumnSpan="2" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ComboBoxToggleButton}"/>
                        <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" Content="{TemplateBinding SelectionBoxItem}" ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" IsHitTestVisible="false" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="HasItems" Value="false">
                            <Setter Property="Height" TargetName="dropDownBorder" Value="95"/>
                        </Trigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsGrouping" Value="true"/>
                                <Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping" Value="false"/>
                            </MultiTrigger.Conditions>
                            <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
                        </MultiTrigger>
                        <Trigger Property="ScrollViewer.CanContentScroll" SourceName="DropDownScrollViewer" Value="false">
                            <Setter Property="Canvas.Top" TargetName="opaqueRect" Value="{Binding VerticalOffset, ElementName=DropDownScrollViewer}"/>
                            <Setter Property="Canvas.Left" TargetName="opaqueRect" Value="{Binding HorizontalOffset, ElementName=DropDownScrollViewer}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style TargetType="{x:Type ComboBoxItem}">
        <Setter Property="Foreground" Value="White"/>
        <Setter Property="FontSize" Value="14"/>
        <Setter Property="Padding" Value="5"/>
        <Setter Property="Background" Value="#292929"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ComboBoxItem}">
                    <Border Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}">
                        <ContentPresenter/>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Background" Value="#444444"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    
    <Style TargetType="{x:Type TextBox}">
        <Setter Property="Background" Value="#444444"/>
        <Setter Property="Foreground" Value="White"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="Padding" Value="3"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="TextBox">
                    <Grid>
                        <Border Background="Black">
                            <Border.Effect>
                                <DropShadowEffect x:Name="dropShadow" ShadowDepth="0" BlurRadius="5"/>
                            </Border.Effect>
                        </Border>
                        <Border Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" 
                                             Background="{TemplateBinding Background}" 
                                             SnapsToDevicePixels="true">
                            <ScrollViewer Name="PART_ContentHost" Background="{TemplateBinding Background}" 
                                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                        </Border>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="False">
                            <Setter Value="#333333" Property="Background" />
                        </Trigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsEnabled" Value="True"/>
                                <Condition Property="IsMouseOver" Value="True"/>
                            </MultiTrigger.Conditions>
                            <MultiTrigger.EnterActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetName="dropShadow" Storyboard.TargetProperty="BlurRadius" Duration="0:0:0.1" To="10" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </MultiTrigger.EnterActions>
                            <MultiTrigger.ExitActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetName="dropShadow" Storyboard.TargetProperty="BlurRadius" Duration="0:0:0.1" To="5" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </MultiTrigger.ExitActions>
                        </MultiTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <media:Style x:Key="FocusVisual">
        <media:Setter Property="media:Control.Template">
            <media:Setter.Value>
                <media:ControlTemplate>
                    <media:Rectangle Margin="2" SnapsToDevicePixels="true" Stroke="{media:DynamicResource {x:Static media:SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
                </media:ControlTemplate>
            </media:Setter.Value>
        </media:Setter>
    </media:Style>
</ResourceDictionary>

================================================
FILE: BMEngine/UI/NumberSelect.xaml
================================================
<UserControl x:Class="ZenithEngine.UI.NumberSelect"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:ZenithEngine.UI"
             TextOptions.TextRenderingMode="Aliased"
             KeyDown="UserControl_KeyDown"
             mc:Ignorable="d" >
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Material.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>
    <Grid ClipToBounds="True">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="25"/>
        </Grid.ColumnDefinitions>
        <Grid Margin="0,0,3,0">
            <TextBox ClipToBounds="True" x:Name="textBox" Padding="0,1,0,0" TextWrapping="Wrap"
                 Background="Transparent"
                 BorderThickness="0"
                 KeyDown="TextBox_KeyDown"
                     Foreground="White"
                     Text="0"
                     CaretBrush="White"
                     RenderTransformOrigin="0.5,0.5" TextChanged="TextBox_TextChanged" LostFocus="TextBox_LostFocus" TextInput="TextBox_TextInput" FontSize="16" Margin="0,2,0,0">
                <TextBox.Style>
                    <Style TargetType="TextBox">
                        <Setter Property="Background" Value="#666666"/>
                        <Setter Property="Foreground" Value="White"/>
                        <Setter Property="VerticalContentAlignment" Value="Center"/>
                        <Setter Property="Padding" Value="3"/>
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="TextBox">
                                    <Border Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" 
                                             SnapsToDevicePixels="true">
                                        <ScrollViewer Name="PART_ContentHost" 
                                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                                    </Border>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </TextBox.Style>
                <TextBox.RenderTransform>
                    <TransformGroup>
                        <ScaleTransform/>
                        <SkewTransform AngleX="-0.843"/>
                        <RotateTransform/>
                        <TranslateTransform X="-0.235"/>
                    </TransformGroup>
                </TextBox.RenderTransform>
            </TextBox>
            <Rectangle Fill="{StaticResource PrimaryBrush}" Height="1" VerticalAlignment="Bottom"/>
        </Grid>
        <Grid Grid.Column="1" Width="25" Height="25" Grid.ColumnSpan="2" Margin="0,0">
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Button Name="downArrow" FontSize="12" Grid.Row="1" Padding="0,0,0.3,0" Background="#33FFFFFF" Height="Auto" Margin="0" Click="Button_Click_1">
                <Button.Content>
                    <Label Foreground="white" Padding="0,0,0,0" Margin="0,-0,0,0" FontWeight="Bold">﹀</Label>
                </Button.Content>
            </Button>
            <Button Name="upArrow" FontSize="12" Padding="0,0,0.3,0" Background="#33FFFFFF" Height="Auto" Margin="0" Click="Button_Click">
                <Button.Content>
                    <Label Foreground="white" Padding="0,0,0,0" Margin="0,-6,0,0" FontWeight="Bold">︿</Label>
                </Button.Content>
            </Button>
        </Grid>
    </Grid>
</UserControl>


================================================
FILE: BMEngine/UI/NumberSelect.xaml.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ZenithEngine.UI
{
    /// <summary>
    /// Interaction logic for NumberSelect.xaml
    /// </summary>
    public partial class NumberSelect : UserControl
    {
        public decimal Value
        { get => (decimal)GetValue(ValueProperty); set => SetValue(ValueProperty, value); }
        public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(decimal), typeof(NumberSelect), new PropertyMetadata((decimal)0, new PropertyChangedCallback(OnPropertyChange)));
        public int DecimalPoints
        { get => (int)GetValue(DecimalPointsProperty); set => SetValue(DecimalPointsProperty, value); }
        public static readonly DependencyProperty DecimalPointsProperty = DependencyProperty.Register("DecimalPoints", typeof(int), typeof(NumberSelect), new PropertyMetadata((int)0, new PropertyChangedCallback(OnPropertyChange)));
        public decimal Minimum
        { get => (decimal)GetValue(MinimumProperty); set => SetValue(MinimumProperty, value); }
        public static readonly DependencyProperty MinimumProperty = DependencyProperty.Register("Minimum", typeof(decimal), typeof(NumberSelect), new PropertyMetadata((decimal)0, new PropertyChangedCallback(OnPropertyChange)));
        public decimal Maximum
        { get => (decimal)GetValue(MaximumProperty); set => SetValue(MaximumProperty, value); }
        public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register("Maximum", typeof(decimal), typeof(NumberSelect), new PropertyMetadata((decimal)1000, new PropertyChangedCallback(OnPropertyChange)));
        public decimal Step
        { get => (decimal)GetValue(StepProperty); set => SetValue(StepProperty, value); }
        public static readonly DependencyProperty StepProperty = DependencyProperty.Register("Step", typeof(decimal), typeof(NumberSelect), new PropertyMetadata((decimal)1));

        public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent(
            "ValueChanged", RoutingStrategy.Bubble,
            typeof(RoutedPropertyChangedEventHandler<decimal>), typeof(NumberSelect));

        public event RoutedPropertyChangedEventHandler<decimal> ValueChanged
        {
            add { AddHandler(ValueChangedEvent, value); }
            remove { RemoveHandler(ValueChangedEvent, value); }
        }

        private static void OnPropertyChange(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((NumberSelect)sender).UpdateValue();
        }

        public bool TextFocused => textBox.IsFocused;

        string prevText = "";

        public NumberSelect()
        {
            InitializeComponent();

            prevText = Value.ToString();
            textBox.Text = prevText;

            upArrow.SetBinding(IsEnabledProperty, new BBinding(IsEnabledProperty, this));
            downArrow.SetBinding(IsEnabledProperty, new BBinding(IsEnabledProperty, this));
            textBox.SetBinding(IsEnabledProperty, new BBinding(IsEnabledProperty, this));
        }

        bool ignoreChange = false;
        void UpdateValue()
        {
            if (!ignoreChange)
            {
                try
                {
                    decimal old = Value;
                    decimal d = Decimal.Round(old, DecimalPoints);
                    if (d < Minimum) d = Minimum;
                    if (d > Maximum) d = Maximum;
                    if (d != old)
                    {
                        Value = d;
                    }
                    try
                    {
                        RaiseEvent(new RoutedPropertyChangedEventArgs<decimal>(old, d, ValueChangedEvent));
                    }
                    catch { }
                }
                catch { }
                textBox.Text = Value.ToString();
            }
            ignoreChange = false;
        }

        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            try
            {
                decimal _d = Convert.ToDecimal(textBox.Text);
                decimal d = Decimal.Round(_d, DecimalPoints);
                if (d < Minimum) d = Minimum;
                if (d > Maximum) d = Maximum;
                else
                {
                    var old = Value;
                    if (d != old)
                    {
                        ignoreChange = true;
                        Value = d;
                        try
                        {
                            RaiseEvent(new RoutedPropertyChangedEventArgs<decimal>(old, d, ValueChangedEvent));
                        }
                        catch { }
                    }
                }
            }
            catch
            {
                if(textBox.Text != "")
                    textBox.Text = prevText;
            }
            prevText = textBox.Text;
        }

        private void TextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            CheckAndSave();
        }

        void CheckAndSave()
        {
            try
            {
                decimal _d = Convert.ToDecimal(textBox.Text);
                decimal d = Decimal.Round(_d, DecimalPoints);
                if (d < Minimum) d = Minimum;
                if (d > Maximum) d = Maximum;
                var old = Value;
                if (d != old)
                {
                    Value = d;
                    try
                    {
                        RaiseEvent(new RoutedPropertyChangedEventArgs<decimal>(old, d, ValueChangedEvent));
                    }
                    catch { }
                }
            }
            catch { }
            textBox.Text = Value.ToString();
        }

        private void TextBox_TextInput(object sender, TextCompositionEventArgs e)
        {

        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var d = Value + Step;
            if (d < Minimum) d = Minimum;
            if (d > Maximum) d = Maximum;
            var old = Value;
            Value = d;
            textBox.Text = Value.ToString();
            if (old != d)
                RaiseEvent(new RoutedPropertyChangedEventArgs<decimal>(old, d, ValueChangedEvent));
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            var d = Value - Step;
            if (d < Minimum) d = Minimum;
            if (d > Maximum) d = Maximum;
            var old = Value;
            Value = d;
            textBox.Text = Value.ToString();
            if (old != d)
                RaiseEvent(new RoutedPropertyChangedEventArgs<decimal>(old, d, ValueChangedEvent));
        }

        private void UserControl_KeyDown(object sender, KeyEventArgs e)
        {
            if(e.Key == Key.Enter)
            {
                CheckAndSave();
                e.Handled = true;
                Keyboard.ClearFocus();

                FrameworkElement parent = (FrameworkElement)textBox.Parent;
                while (parent != null && parent is IInputElement && !((IInputElement)parent).Focusable)
                {
                    parent = (FrameworkElement)parent.Parent;
                }

                DependencyObject scope = FocusManager.GetFocusScope(textBox);
                FocusManager.SetFocusedElement(scope, parent as IInputElement);
            }
        }

        private void TextBox_KeyDown(object sender, KeyEventArgs e)
        {
        }
    }
}


================================================
FILE: BMEngine/UI/RippleEffectDecorator.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace ZenithEngine.UI
{
    public class RippleEffectDecorator : ContentControl
    {
        new public double Opacity
        {
            get { return (double)GetValue(OpacityProperty); }
            set { SetValue(OpacityProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Opacity.  This enables animation, styling, binding, etc...
        new public static readonly DependencyProperty OpacityProperty =
            DependencyProperty.Register("Opacity", typeof(double), typeof(RippleEffectDecorator), new PropertyMetadata(0.4));

        public double ExpandTime
        {
            get { return (double)GetValue(ExpandTimeProperty); }
            set { SetValue(ExpandTimeProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ExpandTime.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ExpandTimeProperty =
            DependencyProperty.Register("ExpandTime", typeof(double), typeof(RippleEffectDecorator), new PropertyMetadata(0.4));

        public double FadeTime
        {
            get { return (double)GetValue(FadeTimeProperty); }
            set { SetValue(FadeTimeProperty, value); }
        }

        // Using a DependencyProperty as the backing store for FadeTime.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty FadeTimeProperty =
            DependencyProperty.Register("FadeTime", typeof(double), typeof(RippleEffectDecorator), new PropertyMetadata(0.3));

        public RippleEffectDecorator()
        {
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            var parentGrid = new Grid();
            var grid = new Grid();
            var content = new ContentControl();
            grid.Background = Brushes.Transparent;
            grid.ClipToBounds = true;
            parentGrid.Children.Add(grid);
            parentGrid.Children.Add(content);
Download .txt
gitextract_07bla4mi/

├── .angulardoc.json
├── .gitattributes
├── .gitignore
├── BMEngine/
│   ├── BufferByteReader.cs
│   ├── FastList.cs
│   ├── GLTextEngine.cs
│   ├── GLUtils.cs
│   ├── IPluginRender.cs
│   ├── MidiFile.cs
│   ├── MidiInfo.cs
│   ├── MidiTrack.cs
│   ├── NoteColorPalettePick.xaml
│   ├── NoteColorPalettePick.xaml.cs
│   ├── OpenTK.dll.config
│   ├── PluginUtils.cs
│   ├── Properties/
│   │   └── AssemblyInfo.cs
│   ├── RenderSettings.cs
│   ├── ScriptedCompile/
│   │   ├── ExtraUI.cs
│   │   └── IO.cs
│   ├── UI/
│   │   ├── BBinding.cs
│   │   ├── BetterCheckbox.xaml
│   │   ├── BetterCheckbox.xaml.cs
│   │   ├── BetterRadio.xaml
│   │   ├── BetterRadio.xaml.cs
│   │   ├── BetterSlider.xaml
│   │   ├── BetterSlider.xaml.cs
│   │   ├── Colors.xaml
│   │   ├── Converters.cs
│   │   ├── HexColorPicker.xaml
│   │   ├── HexColorPicker.xaml.cs
│   │   ├── InplaceConverter.cs
│   │   ├── ListBox.xaml
│   │   ├── Material.xaml
│   │   ├── NumberSelect.xaml
│   │   ├── NumberSelect.xaml.cs
│   │   ├── RippleEffectDecorator.cs
│   │   ├── Scrollbar.xaml
│   │   ├── ValueSlider.xaml
│   │   └── ValueSlider.xaml.cs
│   ├── ZenithEngine.csproj
│   └── packages.config
├── Black-Midi-Render/
│   ├── App.config
│   ├── GLPostbuffer.cs
│   ├── GLUtils.cs
│   ├── KDMAPI.cs
│   ├── Languages/
│   │   └── en/
│   │       └── window.xaml
│   ├── MainWindow.xaml
│   ├── MainWindow.xaml.cs
│   ├── OpenTK.dll.config
│   ├── Program.cs
│   ├── Properties/
│   │   ├── AssemblyInfo.cs
│   │   ├── Resources.Designer.cs
│   │   └── Resources.resx
│   ├── RenderWindow.cs
│   ├── Settings.cs
│   ├── Zenith.csproj
│   └── packages.config
├── ClassicRender/
│   ├── ClassicRender.csproj
│   ├── Languages/
│   │   └── en/
│   │       └── classic.xaml
│   ├── OpenTK.dll.config
│   ├── Properties/
│   │   ├── AssemblyInfo.cs
│   │   ├── Resources.Designer.cs
│   │   └── Resources.resx
│   ├── README.md
│   ├── Render.cs
│   ├── Settings.cs
│   ├── SettingsCtrl.xaml
│   ├── SettingsCtrl.xaml.cs
│   └── packages.config
├── FlatRender/
│   ├── FlatRender.csproj
│   ├── Languages/
│   │   └── en/
│   │       └── flat.xaml
│   ├── OpenTK.dll.config
│   ├── Properties/
│   │   ├── AssemblyInfo.cs
│   │   ├── Resources.Designer.cs
│   │   └── Resources.resx
│   ├── README.md
│   ├── Render.cs
│   ├── Settings.cs
│   ├── SettingsCtrl.xaml
│   ├── SettingsCtrl.xaml.cs
│   └── packages.config
├── LICENSE
├── MidiTrailRender/
│   ├── AuraSelect.xaml
│   ├── AuraSelect.xaml.cs
│   ├── Languages/
│   │   └── en/
│   │       └── miditrail.xaml
│   ├── MidiTrailRender.csproj
│   ├── OpenTK.dll.config
│   ├── ProfileManager.cs
│   ├── Properties/
│   │   ├── AssemblyInfo.cs
│   │   ├── Resources.Designer.cs
│   │   └── Resources.resx
│   ├── README.md
│   ├── Render.cs
│   ├── Settings.cs
│   ├── SettingsCtrl.xaml
│   ├── SettingsCtrl.xaml.cs
│   ├── Util.cs
│   └── packages.config
├── NoteCountRender/
│   ├── Languages/
│   │   └── en/
│   │       └── notecounter.xaml
│   ├── NoteCountRender.csproj
│   ├── OpenTK.dll.config
│   ├── Properties/
│   │   ├── AssemblyInfo.cs
│   │   ├── Resources.Designer.cs
│   │   └── Resources.resx
│   ├── README.md
│   ├── Render.cs
│   ├── Settings.cs
│   ├── SettingsCtrl.xaml
│   ├── SettingsCtrl.xaml.cs
│   └── packages.config
├── PFARender/
│   ├── .gitignore
│   ├── Languages/
│   │   └── en/
│   │       └── pfa.xaml
│   ├── OpenTK.dll.config
│   ├── PFARender.csproj
│   ├── Properties/
│   │   ├── AssemblyInfo.cs
│   │   ├── Resources.Designer.cs
│   │   └── Resources.resx
│   ├── README.md
│   ├── Render.cs
│   ├── Settings.cs
│   ├── SettingsCtrl.xaml
│   ├── SettingsCtrl.xaml.cs
│   └── packages.config
├── README-plugin.md
├── README.md
├── ScriptedRenderer/
│   ├── Languages/
│   │   └── en/
│   │       └── scripted.xaml
│   ├── OpenTK.dll.config
│   ├── Properties/
│   │   ├── AssemblyInfo.cs
│   │   ├── Resources.Designer.cs
│   │   └── Resources.resx
│   ├── Render.cs
│   ├── Script.cs
│   ├── ScriptedRender.csproj
│   ├── Settings.cs
│   ├── SettingsCtrl.xaml
│   ├── SettingsCtrl.xaml.cs
│   └── packages.config
├── TexturedRender/
│   ├── Languages/
│   │   └── en/
│   │       └── textured.xaml
│   ├── OpenTK.dll.config
│   ├── Pack.cs
│   ├── Properties/
│   │   ├── AssemblyInfo.cs
│   │   ├── Resources.Designer.cs
│   │   └── Resources.resx
│   ├── README.md
│   ├── Render.cs
│   ├── Resources/
│   │   └── pack.json
│   ├── Settings.cs
│   ├── SettingsCtrl.xaml
│   ├── SettingsCtrl.xaml.cs
│   ├── TexturedRender.csproj
│   └── packages.config
├── Zenith.sln
├── ZenithInstaller/
│   ├── App.config
│   ├── App.xaml
│   ├── App.xaml.cs
│   ├── FodyWeavers.xml
│   ├── FodyWeavers.xsd
│   ├── MainWindow.xaml
│   ├── MainWindow.xaml.cs
│   ├── Program.cs
│   ├── Properties/
│   │   ├── AssemblyInfo.cs
│   │   ├── Resources.Designer.cs
│   │   ├── Resources.resx
│   │   ├── Settings.Designer.cs
│   │   └── Settings.settings
│   ├── ZenithInstaller.csproj
│   ├── ZenithInstaller_nf5vy1mn_wpftmp.csproj
│   └── packages.config
├── ZenithShared/
│   ├── InstallFailedException.cs
│   ├── Properties/
│   │   └── AssemblyInfo.cs
│   ├── ZenithLanguages.cs
│   ├── ZenithShared.csproj
│   ├── ZenithUpdates.cs
│   └── packages.config
└── build.bat
Download .txt
SYMBOL INDEX (652 symbols across 72 files)

FILE: BMEngine/BufferByteReader.cs
  class BufferByteReader (line 11) | public class BufferByteReader
    method BufferByteReader (line 24) | public BufferByteReader(Stream stream, int buffersize, long streamstar...
    method UpdateBuffer (line 36) | void UpdateBuffer(long pos, bool first = false)
    method Read (line 72) | public byte Read()
    method ReadFast (line 92) | public byte ReadFast()
    method Reset (line 106) | public void Reset()
    method Skip (line 113) | public void Skip(int count)
    method Dispose (line 134) | public void Dispose()

FILE: BMEngine/FastList.cs
  class FastList (line 10) | public class FastList<T> : IEnumerable<T>
    class ListItem (line 12) | private class ListItem
    class Iterator (line 29) | public class Iterator
      method Iterator (line 36) | internal Iterator(FastList<T> ll)
      method MoveNext (line 42) | public bool MoveNext(out T v)
      method Remove (line 61) | public void Remove()
      method Insert (line 67) | public void Insert(T item)
      method Reset (line 84) | public void Reset()
    class FastIterator (line 91) | public class FastIterator : IEnumerator<T>
      method FastIterator (line 97) | internal FastIterator(FastList<T> ll)
      method Dispose (line 107) | public void Dispose()
      method MoveNext (line 112) | public bool MoveNext()
      method Reset (line 123) | public void Reset()
    method Add (line 129) | public void Add(T item)
    method Pop (line 145) | public T Pop()
    method Iterate (line 152) | public Iterator Iterate()
    method FastIterate (line 159) | public IEnumerator<T> FastIterate()
    method Unlink (line 164) | public void Unlink()
    method Count (line 170) | public int Count()
    method Any (line 184) | public bool Any()
    method GetEnumerator (line 189) | IEnumerator IEnumerable.GetEnumerator()
    method GetEnumerator (line 194) | public IEnumerator<T> GetEnumerator()

FILE: BMEngine/GLTextEngine.cs
  class GLTextEngine (line 18) | public class GLTextEngine
    method Dispose (line 76) | public void Dispose()
    method GLTextEngine (line 86) | public GLTextEngine()
    method SetFont (line 139) | public void SetFont(string font, int size)
    method SetFont (line 148) | public void SetFont(string font, int size, string charmap)
    method SetFont (line 154) | public void SetFont(string font, System.Drawing.FontStyle fontStyle, i...
    method SetFont (line 163) | public void SetFont(string font, System.Drawing.FontStyle fontStyle, i...
    method loadImage (line 169) | void loadImage(Bitmap image, int texID)
    method Render (line 186) | public void Render(string text, Matrix4 transform, Color4 color)
    method GetBoundBox (line 282) | public SizeF GetBoundBox(string text)
    method FlushQuadBuffer (line 306) | void FlushQuadBuffer(bool check = true)
    method GenerateCharacters (line 333) | public Bitmap GenerateCharacters(int fontSize, string fontName, out Si...
    method GenerateCharacters (line 338) | public Bitmap GenerateCharacters(int fontSize, string fontName, System...
    method GenerateCharacter (line 370) | private Bitmap GenerateCharacter(Font font, char c)
    method GetSize (line 381) | private SizeF GetSize(Font font, char c)

FILE: BMEngine/GLUtils.cs
  class GLUtils (line 11) | public static class GLUtils
    method MakeShaderProgram (line 13) | public static int MakeShaderProgram(string name)
    method MakePostShaderProgram (line 39) | public static int MakePostShaderProgram(string name)
    method GenFrameBufferTexture (line 65) | public static void GenFrameBufferTexture(int width, int height, out in...
    method GenFrameBufferTexture3d (line 78) | public static void GenFrameBufferTexture3d(int width, int height, out ...

FILE: BMEngine/IPluginRender.cs
  type IPluginRender (line 12) | public interface IPluginRender : IDisposable
    method Init (line 32) | void Init();
    method RenderFrame (line 33) | void RenderFrame(FastList<Note> notes, double midiTime, int finalCompo...
    method ReloadTrackColors (line 34) | void ReloadTrackColors();

FILE: BMEngine/MidiFile.cs
  class MidiFile (line 11) | public class MidiFile : IDisposable
    method MidiFile (line 44) | public MidiFile(string filename, RenderSettings settings)
    method AssertText (line 70) | void AssertText(string text)
    method ReadInt32 (line 81) | uint ReadInt32()
    method ReadInt16 (line 89) | ushort ReadInt16()
    method ParseHeaderChunk (line 97) | void ParseHeaderChunk()
    method ParseTrackChunk (line 109) | void ParseTrackChunk()
    method ParseUpTo (line 121) | public bool ParseUpTo(double targetTime)
    method LoadAndParseAll (line 164) | public void LoadAndParseAll(bool useBufferStream = false)
    method SetZeroColors (line 254) | public void SetZeroColors()
    method Reset (line 259) | public void Reset()
    method Dispose (line 272) | public void Dispose()

FILE: BMEngine/MidiInfo.cs
  class MidiInfo (line 9) | public class MidiInfo

FILE: BMEngine/MidiTrack.cs
  class Note (line 10) | public class Note
  class NoteColor (line 24) | public class NoteColor
  type PlaybackEvent (line 31) | public struct PlaybackEvent
  class Tempo (line 37) | public class Tempo
  class ColorChange (line 43) | public class ColorChange
  class TimeSignature (line 52) | public class TimeSignature
  class MidiTrack (line 58) | public class MidiTrack : IDisposable
    method Reset (line 91) | public void Reset()
    method ResetColors (line 106) | public void ResetColors()
    method SetZeroColors (line 115) | public void SetZeroColors()
    method MidiTrack (line 128) | public MidiTrack(int id, BufferByteReader reader, MidiFile file, Rende...
    method ReadVariableLen (line 144) | long ReadVariableLen()
    method Step (line 164) | public void Step(long time)
    method EndTrack (line 199) | void EndTrack()
    method ParseNextEvent (line 219) | public void ParseNextEvent()
    method ParseNextEventFast (line 654) | public void ParseNextEventFast()
    method Dispose (line 892) | public void Dispose()

FILE: BMEngine/NoteColorPalettePick.xaml.cs
  class NoteColorPalettePick (line 30) | public partial class NoteColorPalettePick : UserControl
    method NoteColorPalettePick (line 43) | public NoteColorPalettePick()
    method SetPath (line 48) | public void SetPath(string path, float defS = 1, float defV = 1)
    method Reload (line 56) | public void Reload()
    method ReadPFAConfig (line 132) | void ReadPFAConfig()
    method SelectImage (line 169) | public void SelectImage(string img)
    method GetColors (line 189) | public Color4[] GetColors(int tracks)
    method ReloadButton_Click (line 228) | private void ReloadButton_Click(object sender, RoutedEventArgs e)
    method randomiseOrder_CheckToggled (line 233) | private void randomiseOrder_CheckToggled(object sender, RoutedProperty...
    method openPaletteFolder_Click (line 240) | private void openPaletteFolder_Click(object sender, RoutedEventArgs e)
    method PaletteList_SelectionChanged (line 248) | private void PaletteList_SelectionChanged(object sender, SelectionChan...

FILE: BMEngine/PluginUtils.cs
  class PluginUtils (line 12) | public static class PluginUtils
    method BitmapToImageSource (line 14) | public static BitmapImage BitmapToImageSource(Bitmap bitmap)

FILE: BMEngine/RenderSettings.cs
  type KeyboardRenderers (line 11) | public enum KeyboardRenderers
  type NoteRenderers (line 18) | public enum NoteRenderers
  class RenderSettings (line 24) | public class RenderSettings

FILE: BMEngine/ScriptedCompile/ExtraUI.cs
  class UISetting (line 10) | public abstract class UISetting
  class UISettingValued (line 14) | public abstract class UISettingValued<T> : UISetting
  class UITabs (line 37) | public class UITabs : UISetting
    method UITabs (line 41) | public UITabs() { }
    method UITabs (line 42) | public UITabs(Dictionary<string, IEnumerable<UISetting>> tabs) { Tabs ...
  class UILabel (line 45) | public class UILabel : UISetting
    method UILabel (line 50) | public UILabel(string text) { Text = text; }
    method UILabel (line 51) | public UILabel(string text, double fontSize) { Text = text; FontSize =...
    method UILabel (line 52) | public UILabel(string text, double fontSize, double padding) { Text = ...
  class UINumber (line 55) | public class UINumber : UISettingValued<double>
    method UINumber (line 59) | public UINumber(string text, double value, double minimum, double maxi...
    method UINumber (line 69) | public UINumber(string text, double value, double minimum, double maxi...
  class UINumberSlider (line 95) | public class UINumberSlider : UISettingValued<double>
    method UINumberSlider (line 99) | public UINumberSlider(string text, double value, double minimum, doubl...
    method UINumberSlider (line 111) | public UINumberSlider(string text, double value, double minimum, doubl...
    method UINumberSlider (line 116) | public UINumberSlider(string text, double value, double minimum, doubl...
    method UINumberSlider (line 130) | public UINumberSlider(string text, double value, double minimum, doubl...
  class UIDropdown (line 167) | public class UIDropdown : UISettingValued<int>
    method UIDropdown (line 172) | public UIDropdown(string text, string[] options)
    method UIDropdown (line 181) | public UIDropdown(string text, int index, string[] options)
  class UICheckbox (line 224) | public class UICheckbox : UISettingValued<bool>
    method UICheckbox (line 228) | public UICheckbox(string text, bool @checked)

FILE: BMEngine/ScriptedCompile/IO.cs
  class Texture (line 15) | public class Texture
  type FontStyle (line 28) | public enum FontStyle
  type TextAlignment (line 37) | public enum TextAlignment
  class Font (line 46) | public class Font
  type TextureShaders (line 56) | public enum TextureShaders
  type BlendFunc (line 63) | public enum BlendFunc
  class RenderOptions (line 69) | public class RenderOptions
  class KeyLayout (line 87) | public class KeyLayout
    class pos (line 89) | public class pos
    method KeyLayout (line 95) | public KeyLayout()
  class KeyboardOptions (line 121) | public class KeyboardOptions
  class IO (line 136) | public static class IO
    method LoadTexture (line 139) | public static Texture LoadTexture(string path)
    method LoadTexture (line 145) | public static Texture LoadTexture(string path, bool linear)
    method LoadTexture (line 151) | public static Texture LoadTexture(string path, bool uvLoop, bool linear)
    method LoadFont (line 158) | public static Font LoadFont(int size, string name)
    method LoadFont (line 163) | public static Font LoadFont(int size, string name, FontStyle style)
    method LoadFont (line 168) | public static Font LoadFont(int size, string name, string charmap)
    method LoadFont (line 173) | public static Font LoadFont(int size, string name, FontStyle style, st...
    method RenderQuad (line 187) | public static void RenderQuad(double left, double top, double right, d...
    method RenderQuad (line 190) | public static void RenderQuad(double left, double top, double right, d...
    method RenderQuad (line 193) | public static void RenderQuad(double left, double top, double right, d...
    method RenderQuad (line 196) | public static void RenderQuad(double left, double top, double right, d...
    method RenderQuad (line 199) | public static void RenderQuad(double left, double top, double right, d...
    method RenderQuad (line 202) | public static void RenderQuad(double left, double top, double right, d...
    method RenderShape (line 205) | public static void RenderShape(Vector2d v1, Vector2d v2, Vector2d v3, ...
    method RenderShape (line 208) | public static void RenderShape(Vector2d v1, Vector2d v2, Vector2d v3, ...
    method RenderShape (line 211) | public static void RenderShape(Vector2d v1, Vector2d v2, Vector2d v3, ...
    method RenderShape (line 214) | public static void RenderShape(Vector2d v1, Vector2d v2, Vector2d v3, ...
    method RenderShape (line 217) | public static void RenderShape(Vector2d v1, Vector2d v2, Vector2d v3, ...
    method RenderShape (line 220) | public static void RenderShape(Vector2d v1, Vector2d v2, Vector2d v3, ...
    method SelectTextureShader (line 223) | public static void SelectTextureShader(TextureShaders shader) => selec...
    method SetBlendFunc (line 225) | public static void SetBlendFunc(BlendFunc function) => setBlendFunc(fu...
    method RenderText (line 227) | public static void RenderText(double left, double bottom, double heigh...
    method GetTextWidth (line 228) | public static double GetTextWidth(Font font, string text) => getTextSi...
    method GetTextWidth (line 229) | public static double GetTextWidth(Font font, double height, string tex...
    method ForceFlushBuffer (line 231) | public static void ForceFlushBuffer() => forceFlush();
    method IsInFunction (line 235) | static bool IsInFunction(string name)
    method callLoadFunction (line 253) | static public void callLoadFunction(dynamic script)
  class Util (line 259) | public static class Util
    method GetKeyboardLayout (line 261) | public static KeyLayout GetKeyboardLayout(int firstNote, int lastNote,...
    method IsBlackKey (line 354) | public static bool IsBlackKey(int n)
    method BlackNotesAbove (line 361) | public static IEnumerable<Note> BlackNotesAbove(IEnumerable<Note> notes)
    method BlendColors (line 374) | public static Color4 BlendColors(Color4 col1, Color4 col2)

FILE: BMEngine/UI/BBinding.cs
  class BBinding (line 11) | public class BBinding : Binding
    method BBinding (line 13) | public BBinding(DependencyProperty dp, object source) : base()

FILE: BMEngine/UI/BetterCheckbox.xaml.cs
  class BetterCheckbox (line 23) | public partial class BetterCheckbox : UserControl
    method OnCheckChanged (line 56) | void OnCheckChanged()
    method BetterCheckbox (line 62) | public BetterCheckbox()
    method DockPanel_MouseDown (line 71) | private void DockPanel_MouseDown(object sender, MouseButtonEventArgs e)

FILE: BMEngine/UI/BetterRadio.xaml.cs
  class BetterRadio (line 23) | public partial class BetterRadio : UserControl
    method OnCheckChanged (line 66) | void OnCheckChanged()
    method BetterRadio (line 84) | public BetterRadio()
    method RecursiveUncheck (line 93) | void RecursiveUncheck(FrameworkElement p)
    method DockPanel_MouseDown (line 100) | private void DockPanel_MouseDown(object sender, MouseButtonEventArgs e)

FILE: BMEngine/UI/BetterSlider.xaml.cs
  class BetterSlider (line 24) | public partial class BetterSlider : UserControl
    method ValueChangedCallback (line 46) | static void ValueChangedCallback(DependencyObject s, DependencyPropert...
    method BetterSlider (line 81) | public BetterSlider()
    method ClickerGrid_MouseEnter (line 107) | private void ClickerGrid_MouseEnter(object sender, MouseEventArgs e)
    method ClickerGrid_MouseLeave (line 112) | private void ClickerGrid_MouseLeave(object sender, MouseEventArgs e)
    method ClickerGrid_MouseDown (line 117) | private void ClickerGrid_MouseDown(object sender, MouseButtonEventArgs e)
    method ClickerGrid_MouseMove (line 126) | private void ClickerGrid_MouseMove(object sender, MouseEventArgs e)
    method ClickerGrid_MouseUp (line 135) | private void ClickerGrid_MouseUp(object sender, MouseButtonEventArgs e)
    method AddRipple (line 140) | void AddRipple()
  class DoubleMultiplyConverter (line 187) | public class DoubleMultiplyConverter : IMultiValueConverter
    method Convert (line 189) | public object Convert(object[] values, Type targetType, object paramet...
    method ConvertBack (line 196) | public object[] ConvertBack(object value, Type[] targetTypes, object p...
  class ScaledValueConverter (line 202) | public class ScaledValueConverter : IMultiValueConverter
    method Convert (line 204) | public object Convert(object[] values, Type targetType, object paramet...
    method ConvertBack (line 209) | public object[] ConvertBack(object value, Type[] targetTypes, object p...
  class ThicknessConverter (line 215) | public class ThicknessConverter : IValueConverter
    method Convert (line 217) | public object Convert(object value, Type targetType, object parameter,...
    method ConvertBack (line 227) | public object ConvertBack(object value, Type targetType, object parame...

FILE: BMEngine/UI/Converters.cs
  class AndValueConverter (line 11) | public class AndValueConverter : IMultiValueConverter
    method Convert (line 13) | public object Convert(object[] values, Type targetType, object paramet...
    method ConvertBack (line 21) | public object[] ConvertBack(object value, Type[] targetTypes, object p...
  class OrValueConverter (line 27) | public class OrValueConverter : IMultiValueConverter
    method Convert (line 29) | public object Convert(object[] values, Type targetType, object paramet...
    method ConvertBack (line 37) | public object[] ConvertBack(object value, Type[] targetTypes, object p...
  class NotValueConverter (line 43) | public class NotValueConverter : IMultiValueConverter
    method Convert (line 45) | public object Convert(object[] values, Type targetType, object paramet...
    method ConvertBack (line 50) | public object[] ConvertBack(object value, Type[] targetTypes, object p...

FILE: BMEngine/UI/HexColorPicker.xaml.cs
  class HexColorPicker (line 21) | public partial class HexColorPicker : UserControl
    method OnColorPropertyChanged (line 53) | void OnColorPropertyChanged(DependencyPropertyChangedEventArgs e)
    method Hexify (line 59) | string Hexify(byte val)
    method SaveString (line 66) | void SaveString()
    method HexColorPicker (line 79) | public HexColorPicker()
    method HexText_TextChanged (line 89) | private void HexText_TextChanged(object sender, TextChangedEventArgs e)
    method HexText_LostFocus (line 115) | private void HexText_LostFocus(object sender, RoutedEventArgs e)
    method UserControl_KeyDown (line 120) | private void UserControl_KeyDown(object sender, KeyEventArgs e)

FILE: BMEngine/UI/InplaceConverter.cs
  class InplaceConverter (line 13) | public class InplaceConverter : IMultiValueConverter
    method InplaceConverter (line 18) | public InplaceConverter(Binding[] bindings, Func<object[], object> func)
    method Convert (line 24) | public object Convert(object[] values, Type targetType, object paramet...
    method ConvertBack (line 29) | public object[] ConvertBack(object value, Type[] targetTypes, object p...
    method Set (line 34) | public void Set(FrameworkElement o, DependencyProperty p)

FILE: BMEngine/UI/NumberSelect.xaml.cs
  class NumberSelect (line 21) | public partial class NumberSelect : UserControl
    method OnPropertyChange (line 49) | private static void OnPropertyChange(DependencyObject sender, Dependen...
    method NumberSelect (line 58) | public NumberSelect()
    method UpdateValue (line 71) | void UpdateValue()
    method TextBox_TextChanged (line 97) | private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
    method TextBox_LostFocus (line 128) | private void TextBox_LostFocus(object sender, RoutedEventArgs e)
    method CheckAndSave (line 133) | void CheckAndSave()
    method TextBox_TextInput (line 156) | private void TextBox_TextInput(object sender, TextCompositionEventArgs e)
    method Button_Click (line 161) | private void Button_Click(object sender, RoutedEventArgs e)
    method Button_Click_1 (line 173) | private void Button_Click_1(object sender, RoutedEventArgs e)
    method UserControl_KeyDown (line 185) | private void UserControl_KeyDown(object sender, KeyEventArgs e)
    method TextBox_KeyDown (line 204) | private void TextBox_KeyDown(object sender, KeyEventArgs e)

FILE: BMEngine/UI/RippleEffectDecorator.cs
  class RippleEffectDecorator (line 17) | public class RippleEffectDecorator : ContentControl
    method RippleEffectDecorator (line 49) | public RippleEffectDecorator()
    method OnApplyTemplate (line 53) | public override void OnApplyTemplate()

FILE: BMEngine/UI/ValueSlider.xaml.cs
  class ValueSlider (line 21) | public partial class ValueSlider : UserControl
    method OnValueChange (line 96) | void OnValueChange(DependencyPropertyChangedEventArgs e)
    method ValueSlider (line 108) | public ValueSlider()
    method Slider_ValueChanged (line 125) | private void Slider_ValueChanged(object sender, double e)
    method Updown_ValueChanged (line 134) | private void Updown_ValueChanged(object sender, RoutedPropertyChangedE...

FILE: Black-Midi-Render/GLPostbuffer.cs
  class GLPostbuffer (line 11) | class GLPostbuffer: IDisposable
    method GLPostbuffer (line 16) | public GLPostbuffer(int width, int height)
    method BindBuffer (line 24) | public void BindBuffer()
    method BindTexture (line 29) | public void BindTexture()
    method UnbindBuffers (line 34) | public static void UnbindBuffers()
    method UnbindTextures (line 39) | public static void UnbindTextures()
    method Dispose (line 44) | public void Dispose()

FILE: Black-Midi-Render/GLUtils.cs
  class GLUtils (line 11) | static class GLUtils
    method MakeShaderProgram (line 13) | public static int MakeShaderProgram(string name)
    method MakePostShaderProgram (line 39) | public static int MakePostShaderProgram(string name)
    method GenFrameBufferTexture (line 65) | public static void GenFrameBufferTexture(int width, int height, out in...

FILE: Black-Midi-Render/KDMAPI.cs
  class KDMAPI (line 8) | static class  KDMAPI
    type MIDIHDR (line 10) | public struct MIDIHDR
    type OMSettingMode (line 23) | public enum OMSettingMode
    type OMSetting (line 29) | public enum OMSetting
    type DebugInfo (line 68) | public struct DebugInfo
    method ReturnKDMAPIVer (line 77) | [DllImport("OmniMIDI\\OmniMIDI")]
    method IsKDMAPIAvailable (line 80) | [DllImport("OmniMIDI\\OmniMIDI")]
    method InitializeKDMAPIStream (line 83) | [DllImport("OmniMIDI\\OmniMIDI")]
    method TerminateKDMAPIStream (line 86) | [DllImport("OmniMIDI\\OmniMIDI")]
    method ResetKDMAPIStream (line 89) | [DllImport("OmniMIDI\\OmniMIDI")]
    method SendCustomEvent (line 92) | [DllImport("OmniMIDI\\OmniMIDI")]
    method SendDirectData (line 95) | [DllImport("OmniMIDI\\OmniMIDI")]
    method SendDirectDataNoBuf (line 98) | [DllImport("OmniMIDI\\OmniMIDI")]
    method SendDirectLongData (line 101) | [DllImport("OmniMIDI\\OmniMIDI")]
    method SendDirectLongDataNoBuf (line 104) | [DllImport("OmniMIDI\\OmniMIDI")]
    method PrepareLongData (line 107) | [DllImport("OmniMIDI\\OmniMIDI")]
    method UnprepareLongData (line 110) | [DllImport("OmniMIDI\\OmniMIDI")]
    method DriverSettings (line 113) | [DllImport("OmniMIDI\\OmniMIDI")]
    method LoadCustomSoundFontsList (line 116) | [DllImport("OmniMIDI\\OmniMIDI")]
    method GetDriverDebugInfo (line 119) | [DllImport("OmniMIDI\\OmniMIDI")]

FILE: Black-Midi-Render/MainWindow.xaml.cs
  class CurrentRendererPointer (line 34) | class CurrentRendererPointer
  type UpdateProgress (line 40) | public enum UpdateProgress
  class MainWindow (line 47) | public partial class MainWindow : Window
    method WindowProc (line 50) | private static IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, ...
    method WmGetMinMaxInfo (line 62) | private static void WmGetMinMaxInfo(IntPtr hwnd, IntPtr lParam)
    type POINT (line 81) | [StructLayout(LayoutKind.Sequential)]
      method POINT (line 89) | public POINT(int x, int y)
    type MINMAXINFO (line 96) | [StructLayout(LayoutKind.Sequential)]
    class MONITORINFO (line 106) | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    type RECT (line 115) | [StructLayout(LayoutKind.Sequential, Pack = 0)]
      method RECT (line 125) | public RECT(int left, int top, int right, int bottom)
      method RECT (line 132) | public RECT(RECT rcSrc)
      method ToString (line 140) | public override string ToString()
      method Equals (line 145) | public override bool Equals(object obj)
      method GetHashCode (line 151) | public override int GetHashCode() => left.GetHashCode() + top.GetHas...
    method GetMonitorInfo (line 158) | [DllImport("user32")]
    method MonitorFromWindow (line 161) | [DllImport("User32")]
    method RunLanguageCheck (line 184) | void RunLanguageCheck()
    method RunUpdateCheck (line 207) | void RunUpdateCheck()
    method CheckUpdateDownloaded (line 249) | void CheckUpdateDownloaded()
    method MainWindow (line 278) | public MainWindow()
    method ToggledPause (line 393) | void ToggledPause()
    method InitialiseSettingsValues (line 405) | void InitialiseSettingsValues()
    method RunRenderWindow (line 418) | void RunRenderWindow()
    method ReloadPlugins (line 548) | void ReloadPlugins()
    method SelectRenderer (line 613) | void SelectRenderer(int id)
    method LoadButton_Click (line 649) | private void LoadButton_Click(object sender, RoutedEventArgs e)
    method UnloadButton_Click (line 681) | private void UnloadButton_Click(object sender, RoutedEventArgs e)
    method StartButton_Click (line 693) | private void StartButton_Click(object sender, RoutedEventArgs e)
    method StopButton_Click (line 717) | private void StopButton_Click(object sender, RoutedEventArgs e)
    method StartRenderButton_Click (line 728) | private void StartRenderButton_Click(object sender, RoutedEventArgs e)
    method BrowseVideoSaveButton_Click (line 793) | private void BrowseVideoSaveButton_Click(object sender, RoutedEventArg...
    method BrowseAudioButton_Click (line 804) | private void BrowseAudioButton_Click(object sender, RoutedEventArgs e)
    method BrowseAlphaButton_Click (line 814) | private void BrowseAlphaButton_Click(object sender, RoutedEventArgs e)
    method Paused_Checked (line 825) | private void Paused_Checked(object sender, RoutedEventArgs e)
    method VsyncEnabled_Checked (line 830) | private void VsyncEnabled_Checked(object sender, RoutedEventArgs e)
    method Grid_KeyDown (line 836) | private void Grid_KeyDown(object sender, KeyEventArgs e)
    method ReloadButton_Click (line 845) | private void ReloadButton_Click(object sender, RoutedEventArgs e)
    method PluginsList_SelectionChanged (line 850) | private void PluginsList_SelectionChanged(object sender, SelectionChan...
    method ResolutionPreset_SelectionChanged (line 859) | private void ResolutionPreset_SelectionChanged(object sender, Selectio...
    method LanguageSelect_SelectionChanged (line 897) | private void LanguageSelect_SelectionChanged(object sender, SelectionC...
    method Window_Closing (line 911) | private void Window_Closing(object sender, System.ComponentModel.Cance...
    method Checkbox_Checked (line 917) | private void Checkbox_Checked(object sender, RoutedEventArgs e)
    method DisableKDMAPI_Click (line 923) | private void DisableKDMAPI_Click(object sender, RoutedEventArgs e)
    method NoteSizeStyle_SelectionChanged (line 952) | private void NoteSizeStyle_SelectionChanged(object sender, SelectionCh...
    method IgnoreColorEvents_Checked (line 959) | private void IgnoreColorEvents_Checked(object sender, RoutedEventArgs e)
    method UseBGImage_Checked (line 965) | private void UseBGImage_Checked(object sender, RoutedEventArgs e)
    method BrowseBG_Click (line 982) | private void BrowseBG_Click(object sender, RoutedEventArgs e)
    method Grid_PreviewKeyDown (line 1001) | private void Grid_PreviewKeyDown(object sender, KeyEventArgs e)
    method ExitButton_Click (line 1006) | private void ExitButton_Click(object sender, RoutedEventArgs e)
    method MinimiseButton_Click (line 1011) | private void MinimiseButton_Click(object sender, RoutedEventArgs e)
    method tempoMultSlider_ValueChanged (line 1021) | private void tempoMultSlider_ValueChanged(object sender, RoutedPropert...
    method updateDownloaded_MouseDown (line 1026) | private void updateDownloaded_MouseDown(object sender, MouseButtonEven...
    method StackPanel_DragOver (line 1033) | private void StackPanel_DragOver(object sender, DragEventArgs e)
  class CustomTabs (line 1039) | public class CustomTabs : TabControl
  class AndValueConverter (line 1061) | public class AndValueConverter : IMultiValueConverter
    method Convert (line 1063) | public object Convert(object[] values, Type targetType, object paramet...
    method ConvertBack (line 1071) | public object[] ConvertBack(object value, Type[] targetTypes, object p...
  class OrValueConverter (line 1077) | public class OrValueConverter : IMultiValueConverter
    method Convert (line 1079) | public object Convert(object[] values, Type targetType, object paramet...
    method ConvertBack (line 1087) | public object[] ConvertBack(object value, Type[] targetTypes, object p...
  class NotValueConverter (line 1093) | public class NotValueConverter : IMultiValueConverter
    method Convert (line 1095) | public object Convert(object[] values, Type targetType, object paramet...
    method ConvertBack (line 1100) | public object[] ConvertBack(object value, Type[] targetTypes, object p...

FILE: Black-Midi-Render/Program.cs
  class Program (line 14) | class Program
    method Main (line 16) | [STAThread]

FILE: Black-Midi-Render/Properties/Resources.Designer.cs
  class Resources (line 22) | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resource...
    method Resources (line 31) | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Mic...

FILE: Black-Midi-Render/RenderWindow.cs
  type INoteRender (line 28) | interface INoteRender : IDisposable
    method Render (line 30) | long Render(FastList<Note> notes, double midiTime);
  type IKeyboardRender (line 33) | interface IKeyboardRender : IDisposable
    method Render (line 35) | void Render();
  class RenderWindow (line 38) | class RenderWindow : GameWindow
    method MakeShader (line 153) | int MakeShader(string vert, string frag)
    method loadImage (line 180) | void loadImage(Bitmap image, int texID, bool loop, bool linear)
    method startNewFF (line 252) | Process startNewFF(string path)
    method OnResize (line 333) | protected override void OnResize(EventArgs e)
    method RenderWindow (line 340) | public RenderWindow(CurrentRendererPointer renderer, MidiFile midi, Re...
    method PlaybackLoop (line 408) | void PlaybackLoop()
    method OnRenderFrame (line 460) | protected override void OnRenderFrame(FrameEventArgs e)
    method OnKeyDown (line 799) | protected override void OnKeyDown(KeyboardKeyEventArgs e)
    method OnClosing (line 831) | protected override void OnClosing(CancelEventArgs e)
    method OnClosed (line 838) | protected override void OnClosed(EventArgs e)
    method DrawScreenQuad (line 845) | void DrawScreenQuad()

FILE: Black-Midi-Render/Settings.cs
  class Settings (line 13) | class Settings
    method Settings (line 25) | public Settings()
    method SaveConfig (line 48) | public void SaveConfig()

FILE: ClassicRender/Properties/Resources.Designer.cs
  class Resources (line 22) | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resource...
    method Resources (line 31) | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Mic...

FILE: ClassicRender/Render.cs
  class Render (line 21) | public class Render : IPluginRender
    method BitmapToImageSource (line 24) | BitmapImage BitmapToImageSource(Bitmap bitmap)
    method Dispose (line 116) | public void Dispose()
    method Render (line 127) | public Render(RenderSettings settings)
    method Init (line 144) | public void Init()
    method ReloadTrackColors (line 214) | public void ReloadTrackColors()
    method RenderFrame (line 237) | public void RenderFrame(FastList<Note> notes, double midiTime, int fin...
    method FlushQuadBuffer (line 940) | void FlushQuadBuffer(bool check = true)
    method isBlackNote (line 971) | bool isBlackNote(int n)

FILE: ClassicRender/Settings.cs
  class Settings (line 9) | public class Settings

FILE: ClassicRender/SettingsCtrl.xaml.cs
  class SettingsCtrl (line 24) | public partial class SettingsCtrl : UserControl
    method SetValues (line 34) | public void SetValues()
    method SettingsCtrl (line 45) | public SettingsCtrl(Settings settings) : base()
    method Nud_ValueChanged (line 55) | private void Nud_ValueChanged(object sender, RoutedPropertyChangedEven...
    method NoteDeltaScreenTime_ValueChanged (line 64) | private void NoteDeltaScreenTime_ValueChanged(object sender, RoutedPro...
    method BlackNotesAbove_Checked (line 70) | private void BlackNotesAbove_Checked(object sender, RoutedEventArgs e)
    method SameWidth_Checked (line 76) | private void SameWidth_Checked(object sender, RoutedEventArgs e)

FILE: FlatRender/Properties/Resources.Designer.cs
  class Resources (line 22) | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resource...
    method Resources (line 31) | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Mic...

FILE: FlatRender/Render.cs
  class Render (line 20) | public class Render : IPluginRender
    method BitmapToImageSource (line 23) | BitmapImage BitmapToImageSource(Bitmap bitmap)
    method Dispose (line 114) | public void Dispose()
    method Render (line 125) | public Render(RenderSettings settings)
    method Init (line 142) | public void Init()
    method RenderFrame (line 192) | public void RenderFrame(FastList<Note> notes, double midiTime, int fin...
    method FlushQuadBuffer (line 560) | void FlushQuadBuffer(bool check = true)
    method isBlackNote (line 584) | bool isBlackNote(int n)
    method ReloadTrackColors (line 590) | public void ReloadTrackColors()

FILE: FlatRender/Settings.cs
  class Settings (line 9) | public class Settings

FILE: FlatRender/SettingsCtrl.xaml.cs
  class SettingsCtrl (line 23) | public partial class SettingsCtrl : UserControl
    method SetValues (line 33) | public void SetValues()
    method SettingsCtrl (line 43) | public SettingsCtrl(Settings settings) : base()
    method Nud_ValueChanged (line 53) | private void Nud_ValueChanged(object sender, RoutedPropertyChangedEven...
    method NoteDeltaScreenTime_ValueChanged (line 62) | private void NoteDeltaScreenTime_ValueChanged(object sender, RoutedPro...
    method SameWidth_Checked (line 68) | private void SameWidth_Checked(object sender, RoutedEventArgs e)

FILE: MidiTrailRender/AuraSelect.xaml.cs
  class AuraSelect (line 28) | public partial class AuraSelect : UserControl
    method BitmapToImageSource (line 31) | BitmapImage BitmapToImageSource(Bitmap bitmap)
    method LoadSettings (line 64) | public void LoadSettings()
    method ReloadImages (line 84) | void ReloadImages()
    method AuraSelect (line 133) | public AuraSelect(Settings settings) : base()
    method Reload_Click (line 141) | private void Reload_Click(object sender, RoutedEventArgs e)
    method ImagesList_SelectionChanged (line 146) | private void ImagesList_SelectionChanged(object sender, SelectionChang...
    method AuraStrength_ValueChanged (line 164) | private void AuraStrength_ValueChanged(object sender, RoutedPropertyCh...
    method AuraEnabled_Checked (line 173) | private void AuraEnabled_Checked(object sender, RoutedEventArgs e)
    method openFolder_Click (line 182) | private void openFolder_Click(object sender, RoutedEventArgs e)

FILE: MidiTrailRender/ProfileManager.cs
  class ProfileManager (line 12) | class ProfileManager
    method ProfileManager (line 19) | public ProfileManager(string savePath)
    method injectSettings (line 25) | void injectSettings(Settings insett, Settings outsett)
    method Add (line 40) | public void Add(Settings sett, string name)
    method Save (line 53) | public void Save()
    method Load (line 66) | public void Load()
    method LoadProfile (line 87) | public void LoadProfile(string name, Settings dest)
    method DeleteProfile (line 97) | public void DeleteProfile(string name)

FILE: MidiTrailRender/Properties/Resources.Designer.cs
  class Resources (line 22) | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resource...
    method Resources (line 31) | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Mic...

FILE: MidiTrailRender/Render.cs
  class Render (line 19) | public class Render : IPluginRender
    method BitmapToImageSource (line 22) | BitmapImage BitmapToImageSource(Bitmap bitmap)
    method MakeShader (line 165) | int MakeShader(string vert, string frag)
    method loadImage (line 282) | void loadImage(Bitmap image, int texID)
    method Dispose (line 299) | public void Dispose()
    method Render (line 335) | public Render(RenderSettings settings)
    method ReloadAuraTexture (line 352) | void ReloadAuraTexture()
    method Init (line 360) | public void Init()
    method RenderFrame (line 865) | public void RenderFrame(FastList<Note> notes, double midiTime, int fin...
    method RenderAura (line 1403) | void RenderAura()
    method RenderKeyboard (line 1563) | void RenderKeyboard()
    method ReloadTrackColors (line 1771) | public void ReloadTrackColors()
    method FlushNoteBuffer (line 1789) | void FlushNoteBuffer(bool check = true)
    method isBlackNote (line 1820) | bool isBlackNote(int n)

FILE: MidiTrailRender/Settings.cs
  class Settings (line 9) | public class Settings

FILE: MidiTrailRender/SettingsCtrl.xaml.cs
  class SettingsCtrl (line 23) | public partial class SettingsCtrl : UserControl
    method SetValues (line 34) | public void SetValues()
    method SettingsCtrl (line 64) | public SettingsCtrl(Settings settings) : base()
    method Nud_ValueChanged (line 82) | private void Nud_ValueChanged(object sender, RoutedPropertyChangedEven...
    method injectSettings (line 94) | void injectSettings(Settings sett)
    method BoxNotes_Checked (line 110) | private void BoxNotes_Checked(object sender, RoutedEventArgs e)
    method FOVSlider_ValueChanged (line 116) | private void FOVSlider_ValueChanged(object sender, RoutedPropertyChang...
    method ViewAngSlider_ValueChanged (line 122) | private void ViewAngSlider_ValueChanged(object sender, RoutedPropertyC...
    method ViewTurnSlider_ValueChanged (line 128) | private void ViewTurnSlider_ValueChanged(object sender, RoutedProperty...
    method NoteDeltaScreenTime_ValueChanged (line 134) | private void NoteDeltaScreenTime_ValueChanged(object sender, RoutedPro...
    method RenderDistSlider_ValueChanged (line 140) | private void RenderDistSlider_ValueChanged(object sender, RoutedProper...
    method RenderDistBackSlider_ValueChanged (line 146) | private void RenderDistBackSlider_ValueChanged(object sender, RoutedPr...
    method FarPreset_Click (line 152) | private void FarPreset_Click(object sender, RoutedEventArgs e)
    method MediumPreset_Click (line 165) | private void MediumPreset_Click(object sender, RoutedEventArgs e)
    method ClosePreset_Click (line 178) | private void ClosePreset_Click(object sender, RoutedEventArgs e)
    method TopPreset_Click (line 191) | private void TopPreset_Click(object sender, RoutedEventArgs e)
    method PerspectivePreset_Click (line 204) | private void PerspectivePreset_Click(object sender, RoutedEventArgs e)
    method SaveButton_Click (line 217) | private void SaveButton_Click(object sender, RoutedEventArgs e)
    method DefaultsButton_Click (line 232) | private void DefaultsButton_Click(object sender, RoutedEventArgs e)
    method UseVel_Checked (line 237) | private void UseVel_Checked(object sender, RoutedEventArgs e)
    method CheckboxChecked (line 246) | private void CheckboxChecked(object sender, RoutedEventArgs e)
    method NewProfile_Click (line 258) | private void NewProfile_Click(object sender, RoutedEventArgs e)
    method ProfileSelect_SelectionChanged (line 286) | private void ProfileSelect_SelectionChanged(object sender, SelectionCh...
    method DeleteProfile_Click (line 296) | private void DeleteProfile_Click(object sender, RoutedEventArgs e)
    method ReloadProfiles (line 304) | void ReloadProfiles()
    method verticalNotes_CheckToggled (line 318) | private void verticalNotes_CheckToggled(object sender, RoutedPropertyC...
    method viewSpinSlider_ValueChanged (line 327) | private void viewSpinSlider_ValueChanged(object sender, RoutedProperty...
    method profileSelect_DropDownOpened (line 336) | private void profileSelect_DropDownOpened(object sender, EventArgs e)

FILE: MidiTrailRender/Util.cs
  class Util (line 10) | class Util : IDisposable
    method MakeShader (line 39) | int MakeShader(string vert, string frag)
    method Util (line 73) | public Util()
    method DrawScreenQuad (line 95) | public void DrawScreenQuad()
    method Dispose (line 115) | public void Dispose()

FILE: NoteCountRender/Properties/Resources.Designer.cs
  class Resources (line 22) | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resource...
    method Resources (line 31) | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Mic...

FILE: NoteCountRender/Render.cs
  class Render (line 17) | public class Render : IPluginRender
    method BitmapToImageSource (line 20) | BitmapImage BitmapToImageSource(Bitmap bitmap)
    method Dispose (line 67) | public void Dispose()
    method Init (line 81) | public void Init()
    method Render (line 107) | public Render(RenderSettings settings)
    method RenderFrame (line 125) | public void RenderFrame(FastList<Note> notes, double midiTime, int fin...
    method ReloadTrackColors (line 387) | public void ReloadTrackColors()

FILE: NoteCountRender/Settings.cs
  type Alignments (line 11) | public enum Alignments
  type Commas (line 20) | public enum Commas
  class Settings (line 26) | public class Settings
  class Zeroes (line 51) | public class Zeroes

FILE: NoteCountRender/SettingsCtrl.xaml.cs
  class SettingsCtrl (line 27) | public partial class SettingsCtrl : UserControl
    method SettingsCtrl (line 70) | public SettingsCtrl(Settings settings) : base()
    method AlignSelect_SelectionChanged (line 118) | private void AlignSelect_SelectionChanged(object sender, SelectionChan...
    method FontSize_ValueChanged (line 124) | private void FontSize_ValueChanged(object sender, RoutedPropertyChange...
    method FontSelect_SelectionChanged (line 130) | private void FontSelect_SelectionChanged(object sender, SelectionChang...
    method UpdateFontStyles (line 137) | void UpdateFontStyles()
    method FontStyle_SelectionChanged (line 153) | private void FontStyle_SelectionChanged(object sender, SelectionChange...
    method TextTemplate_TextChanged (line 159) | private void TextTemplate_TextChanged(object sender, TextChangedEventA...
    method Reload (line 166) | void Reload()
    method Templates_SelectionChanged (line 206) | private void Templates_SelectionChanged(object sender, SelectionChange...
    method Reload_Click (line 212) | private void Reload_Click(object sender, RoutedEventArgs e)
    method saveCsv_Checked (line 218) | private void saveCsv_Checked(object sender, RoutedEventArgs e)
    method browseOutputSaveButton_Click (line 224) | private void browseOutputSaveButton_Click(object sender, RoutedEventAr...
    method csvFormat_TextChanged (line 236) | private void csvFormat_TextChanged(object sender, TextChangedEventArgs e)
    method openFolder_Click (line 242) | private void openFolder_Click(object sender, RoutedEventArgs e)
    method useCommas_RadioChecked (line 250) | private void useCommas_RadioChecked(object sender, RoutedEventArgs e)
    method ZP (line 258) | private void ZP(object sender, RoutedPropertyChangedEventArgs<bool> e)
    method Paddings_ValueChanged (line 262) | private void Paddings_ValueChanged(object sender, RoutedPropertyChange...
    method SetDefault_Click (line 274) | private void SetDefault_Click(object sender, RoutedEventArgs e)
    method NewProfile_Click (line 286) | private void NewProfile_Click(object sender, RoutedEventArgs e)

FILE: PFARender/Properties/Resources.Designer.cs
  class Resources (line 22) | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resource...
    method Resources (line 31) | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Mic...

FILE: PFARender/Render.cs
  class Render (line 17) | public class Render : IPluginRender
    method BitmapToImageSource (line 20) | BitmapImage BitmapToImageSource(Bitmap bitmap)
    method Dispose (line 116) | public void Dispose()
    method Render (line 127) | public Render(RenderSettings settings)
    method Init (line 144) | public void Init()
    method RenderFrame (line 213) | public void RenderFrame(FastList<Note> notes, double midiTime, int fin...
    method FlushQuadBuffer (line 1796) | void FlushQuadBuffer(bool check = true)
    method ReloadTrackColors (line 1827) | public void ReloadTrackColors()
    method isBlackNote (line 1845) | bool isBlackNote(int n)

FILE: PFARender/Settings.cs
  type TopColor (line 9) | public enum TopColor
  class Settings (line 16) | public class Settings

FILE: PFARender/SettingsCtrl.xaml.cs
  class SettingsCtrl (line 23) | public partial class SettingsCtrl : UserControl
    method SetValues (line 33) | public void SetValues()
    method SettingsCtrl (line 47) | public SettingsCtrl(Settings settings) : base()
    method Nud_ValueChanged (line 57) | private void Nud_ValueChanged(object sender, RoutedPropertyChangedEven...
    method NoteDeltaScreenTime_ValueChanged (line 67) | private void NoteDeltaScreenTime_ValueChanged(object sender, RoutedPro...
    method injectSettings (line 73) | void injectSettings(Settings sett)
    method SameWidth_Checked (line 89) | private void SameWidth_Checked(object sender, RoutedEventArgs e)
    method MiddleCSquare_Checked (line 104) | private void MiddleCSquare_Checked(object sender, RoutedEventArgs e)
    method BlackNotesAbove_Checked (line 110) | private void BlackNotesAbove_Checked(object sender, RoutedEventArgs e)
    method BarColorHex_TextChanged (line 116) | private void BarColorHex_TextChanged(object sender, TextChangedEventAr...

FILE: ScriptedRenderer/Properties/Resources.Designer.cs
  class Resources (line 22) | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resource...
    method Resources (line 31) | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Mic...

FILE: ScriptedRenderer/Render.cs
  class jsIterator (line 17) | class jsIterator<T>
    method jsIterator (line 22) | public jsIterator(IEnumerable<T> iter)
    method next (line 29) | public bool next() => en.MoveNext();
    method reset (line 30) | public void reset() => en = iter.GetEnumerator();
  class Render (line 33) | public class Render : IPluginRender
    method MakeShader (line 211) | int MakeShader(string vert, string frag)
    method Render (line 278) | public Render(RenderSettings settings)
    method GetRenderOptions (line 288) | RenderOptions GetRenderOptions(double midiTime = 0)
    method UnloadScript (line 310) | void UnloadScript(Script s)
    method LoadScript (line 325) | void LoadScript(Script s)
    method CheckScript (line 349) | void CheckScript(IEnumerable<Note> notes = null)
    method Dispose (line 364) | public void Dispose()
    method Init (line 381) | public void Init()
    method CopyScriptValues (line 499) | void CopyScriptValues()
    method RenderFrame (line 512) | public void RenderFrame(FastList<Note> notes, double midiTime, int fin...
    method RenderQuad (line 571) | void RenderQuad(double left, double top, double right, double bottom, ...
    method RenderShape (line 623) | void RenderShape(Vector2d v1, Vector2d v2, Vector2d v3, Vector2d v4, C...
    method FindTexSlot (line 675) | int FindTexSlot(int id)
    method FlushQuadBuffer (line 691) | void FlushQuadBuffer(bool check = true, bool forceShader = true)
    method loadImage (line 746) | void loadImage(Bitmap image, int texID, bool loop, bool linear = false)
    method ReloadTrackColors (line 779) | public void ReloadTrackColors()

FILE: ScriptedRenderer/Script.cs
  type ScriptType (line 13) | public enum ScriptType
  class Script (line 18) | public class Script

FILE: ScriptedRenderer/Settings.cs
  class Settings (line 9) | public class Settings

FILE: ScriptedRenderer/SettingsCtrl.xaml.cs
  class ScriptLocation (line 45) | class ScriptLocation
  class SettingsCtrl (line 51) | public partial class SettingsCtrl : UserControl
    method BitmapToImageSource (line 72) | BitmapImage BitmapToImageSource(Bitmap bitmap)
    method SettingsCtrl (line 89) | public SettingsCtrl(Settings settings)
    method WriteDefaultPack (line 101) | void WriteDefaultPack()
    method ReloadPacks (line 121) | void ReloadPacks()
    method UnloadScript (line 215) | void UnloadScript(Script r)
    method LoadScript (line 220) | Script LoadScript(string p, ScriptType type, Dictionary<string, string...
    method PluginList_SelectionChanged (line 524) | private void PluginList_SelectionChanged(object sender, SelectionChang...
    method ReloadPackButton_Click (line 529) | private void ReloadPackButton_Click(object sender, RoutedEventArgs e)
    method PopulateSettingsDock (line 534) | void PopulateSettingsDock(IEnumerable<UISetting> settings, DockPanel d...
    method LoadSelectedPack (line 725) | void LoadSelectedPack()
    method SetValues (line 814) | public void SetValues()
    method ReloadButton_Click (line 822) | private void ReloadButton_Click(object sender, RoutedEventArgs e)
    method NoteDeltaScreenTime_ValueChanged (line 829) | private void NoteDeltaScreenTime_ValueChanged(object sender, RoutedPro...
    method Nud_ValueChanged (line 845) | private void Nud_ValueChanged(object sender, RoutedPropertyChangedEven...
    method openFolderButton_Click (line 857) | private void openFolderButton_Click(object sender, RoutedEventArgs e)
    method SaveProfilesFile (line 865) | void SaveProfilesFile()
    method saveProfile_Click (line 870) | private void saveProfile_Click(object sender, RoutedEventArgs e)
    method CheckProfileValidity (line 916) | private bool CheckProfileValidity(IEnumerable<object> data)
    method deleteProfile_Click (line 943) | private void deleteProfile_Click(object sender, RoutedEventArgs e)
    method profileDefaults_Click (line 956) | private void profileDefaults_Click(object sender, RoutedEventArgs e)
    method profileSelect_SelectionChanged (line 984) | private void profileSelect_SelectionChanged(object sender, SelectionCh...
    method profileSelect_DropDownOpened (line 1018) | private void profileSelect_DropDownOpened(object sender, EventArgs e)

FILE: TexturedRender/Pack.cs
  type TextureShaderType (line 10) | public enum TextureShaderType
  type KeyType (line 17) | public enum KeyType
  type PackType (line 24) | public enum PackType
  class KeyboardOverlay (line 29) | public class KeyboardOverlay
  class NoteTexture (line 40) | public class NoteTexture
  class Pack (line 66) | public class Pack

FILE: TexturedRender/Properties/Resources.Designer.cs
  class Resources (line 22) | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resource...
    method Resources (line 31) | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Mic...

FILE: TexturedRender/Render.cs
  class Render (line 17) | public class Render : IPluginRender
    method MakeShader (line 182) | int MakeShader(string vert, string frag)
    method loadImage (line 209) | void loadImage(Bitmap image, int texID, bool loop, bool linear = false)
    method UnloadPack (line 289) | public void UnloadPack()
    method LoadPack (line 322) | public void LoadPack()
    method CheckPack (line 376) | public void CheckPack()
    method Dispose (line 387) | public void Dispose()
    method Render (line 402) | public Render(RenderSettings settings)
    method Init (line 420) | public void Init()
    method SwitchShader (line 492) | void SwitchShader(TextureShaderType shader)
    method RenderFrame (line 499) | public void RenderFrame(FastList<Note> notes, double midiTime, int fin...
    method RenderOverlays (line 1319) | void RenderOverlays(bool below)
    method FlushQuadBuffer (line 1397) | void FlushQuadBuffer(bool check = true)
    method isBlackNote (line 1436) | bool isBlackNote(int n)
    method ReloadTrackColors (line 1442) | public void ReloadTrackColors()

FILE: TexturedRender/Settings.cs
  class Settings (line 9) | public class Settings

FILE: TexturedRender/SettingsCtrl.xaml.cs
  class PackLocation (line 39) | class PackLocation
  class SettingsCtrl (line 45) | public partial class SettingsCtrl : UserControl
    method BitmapToImageSource (line 58) | BitmapImage BitmapToImageSource(Bitmap bitmap)
    method SettingsCtrl (line 75) | public SettingsCtrl(Settings settings)
    method WriteDefaultPack (line 87) | void WriteDefaultPack()
    method ReloadPacks (line 102) | void ReloadPacks()
    method UnloadPack (line 196) | void UnloadPack(Pack r)
    method parseType (line 230) | T parseType<T>(Pack pack, dynamic o)
    method LoadPack (line 276) | Pack LoadPack(string p, PackType type, Dictionary<string, string> swit...
    method PluginList_SelectionChanged (line 960) | private void PluginList_SelectionChanged(object sender, SelectionChang...
    method ReloadPackButton_Click (line 965) | private void ReloadPackButton_Click(object sender, RoutedEventArgs e)
    method LoadSelectedPack (line 970) | void LoadSelectedPack()
    method Menu_SelectionChanged (line 1030) | private void Menu_SelectionChanged(object sender, SelectionChangedEven...
    method SetValues (line 1065) | public void SetValues()
    method ReloadButton_Click (line 1074) | private void ReloadButton_Click(object sender, RoutedEventArgs e)
    method BlackNotesAbove_Checked (line 1081) | private void BlackNotesAbove_Checked(object sender, RoutedEventArgs e)
    method NoteDeltaScreenTime_ValueChanged (line 1091) | private void NoteDeltaScreenTime_ValueChanged(object sender, RoutedPro...
    method Nud_ValueChanged (line 1107) | private void Nud_ValueChanged(object sender, RoutedPropertyChangedEven...
    method openFolderButton_Click (line 1119) | private void openFolderButton_Click(object sender, RoutedEventArgs e)

FILE: ZenithInstaller/App.xaml.cs
  class App (line 14) | public partial class App : Application

FILE: ZenithInstaller/MainWindow.xaml.cs
  class MainWindow (line 23) | public partial class MainWindow : Window
    method MainWindow (line 25) | public MainWindow()
    method ProgressCallbac (line 32) | void ProgressCallbac(long dl, long total)
    method Window_Loaded (line 41) | private void Window_Loaded(object sender, RoutedEventArgs e)

FILE: ZenithInstaller/Program.cs
  class Program (line 13) | class Program
    method Main (line 17) | [STAThread]
    method NormalInstall (line 138) | static void NormalInstall()
    method SilentInstall (line 145) | static void SilentInstall()
    method UpdateFromPackage (line 155) | static void UpdateFromPackage(string path)
    method FinalizeInstall (line 169) | public static void FinalizeInstall()

FILE: ZenithInstaller/Properties/Resources.Designer.cs
  class Resources (line 22) | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resource...
    method Resources (line 32) | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Mic...

FILE: ZenithInstaller/Properties/Settings.Designer.cs
  class Settings (line 15) | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]

FILE: ZenithShared/InstallFailedException.cs
  class InstallFailedException (line 9) | class InstallFailedException : Exception
    method InstallFailedException (line 11) | public InstallFailedException(string message) : base(message) { }

FILE: ZenithShared/ZenithLanguages.cs
  class ZenithLanguages (line 11) | public static class ZenithLanguages
    method GetLatestVersion (line 16) | public static string GetLatestVersion() => ZenithUpdates.GetLatestVers...
    method DownloadLatestVersion (line 17) | public static Stream DownloadLatestVersion() => ZenithUpdates.Download...
    method UnpackFromStream (line 19) | public static void UnpackFromStream(Stream s) => UnpackFromStream(s, "...
    method UnpackFromStream (line 21) | public static void UnpackFromStream(Stream s, string dir)

FILE: ZenithShared/ZenithUpdates.cs
  class ZenithUpdates (line 20) | public static class ZenithUpdates
    method GetHTTPJSON (line 36) | public static dynamic GetHTTPJSON(string uri)
    method GetHTTPData (line 54) | public static Stream GetHTTPData(string uri)
    method GetHTTPDataProgressive (line 72) | public static Stream GetHTTPDataProgressive(string uri, Action<long, l...
    method GetLatestVersion (line 100) | public static string GetLatestVersion() => GetLatestVersion(ApiURL);
    method GetLatestVersion (line 101) | public static string GetLatestVersion(string repo)
    method DownloadAssetData (line 107) | public static Stream DownloadAssetData(string filename) => DownloadAss...
    method DownloadAssetData (line 108) | public static Stream DownloadAssetData(string filename, string repo)
    method DownloadAssetDataProgressive (line 117) | public static Stream DownloadAssetDataProgressive(string filename, Act...
    method DownloadAssetDataProgressive (line 118) | public static Stream DownloadAssetDataProgressive(string filename, str...
    method IsAnotherProcessRunning (line 127) | public static bool IsAnotherProcessRunning()
    method KillAllProcesses (line 134) | public static void KillAllProcesses()
    method InstallFromStream (line 151) | public static void InstallFromStream(Stream s)
    method WriteVersionSettings (line 169) | public static void WriteVersionSettings(string version, bool autoUpdat...
    method CopySelfInside (line 201) | public static void CopySelfInside(string path)
    method UpdateInstaller (line 208) | public static void UpdateInstaller()
    method CreateStartShortcut (line 217) | public static void CreateStartShortcut()
    method DeleteStartShortcut (line 230) | public static void DeleteStartShortcut()
    method CreateDesktopShortcut (line 236) | public static void CreateDesktopShortcut()
    method DeleteDesktopShortcut (line 249) | public static void DeleteDesktopShortcut()
    method DeleteProgramFolder (line 255) | public static void DeleteProgramFolder()
    method CreateUninstallScript (line 260) | public static void CreateUninstallScript()
Condensed preview — 175 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,179K chars).
[
  {
    "path": ".angulardoc.json",
    "chars": 71,
    "preview": "{\n  \"repoId\": \"132e1921-3d2f-40c3-9aad-ca5bf9141f7d\",\n  \"lastSync\": 0\n}"
  },
  {
    "path": ".gitattributes",
    "chars": 2518,
    "preview": "###############################################################################\n# Set default behavior to automatically "
  },
  {
    "path": ".gitignore",
    "chars": 4339,
    "preview": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User"
  },
  {
    "path": "BMEngine/BufferByteReader.cs",
    "chars": 3886,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing System.Thr"
  },
  {
    "path": "BMEngine/FastList.cs",
    "chars": 4267,
    "preview": "using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing S"
  },
  {
    "path": "BMEngine/GLTextEngine.cs",
    "chars": 14561,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.Drawing.Drawing2D;\nusing System.Draw"
  },
  {
    "path": "BMEngine/GLUtils.cs",
    "chars": 5002,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing System.Thr"
  },
  {
    "path": "BMEngine/IPluginRender.cs",
    "chars": 936,
    "preview": "using OpenTK.Graphics;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing Syst"
  },
  {
    "path": "BMEngine/MidiFile.cs",
    "chars": 9348,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Linq;\nusing Sys"
  },
  {
    "path": "BMEngine/MidiInfo.cs",
    "chars": 469,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nna"
  },
  {
    "path": "BMEngine/MidiTrack.cs",
    "chars": 31924,
    "preview": "using OpenTK.Graphics;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing Syst"
  },
  {
    "path": "BMEngine/NoteColorPalettePick.xaml",
    "chars": 1468,
    "preview": "<UserControl x:Class=\"ZenithEngine.NoteColorPalettePick\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xa"
  },
  {
    "path": "BMEngine/NoteColorPalettePick.xaml.cs",
    "chars": 9444,
    "preview": "using OpenTK.Graphics;\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Drawing;\n"
  },
  {
    "path": "BMEngine/OpenTK.dll.config",
    "chars": 1788,
    "preview": "<configuration>\n  <dllmap os=\"linux\" dll=\"opengl32.dll\" target=\"libGL.so.1\"/>\n  <dllmap os=\"linux\" dll=\"glu32.dll\" targe"
  },
  {
    "path": "BMEngine/PluginUtils.cs",
    "chars": 858,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.IO;\nusing System.Linq;\nusing System."
  },
  {
    "path": "BMEngine/Properties/AssemblyInfo.cs",
    "chars": 1392,
    "preview": "using System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\n// General Infor"
  },
  {
    "path": "BMEngine/RenderSettings.cs",
    "chars": 2048,
    "preview": "using OpenTK.Graphics;\nusing System;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.Linq;\nusing S"
  },
  {
    "path": "BMEngine/ScriptedCompile/ExtraUI.cs",
    "chars": 7380,
    "preview": "using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing S"
  },
  {
    "path": "BMEngine/ScriptedCompile/IO.cs",
    "chars": 15953,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Drawing;\nusing System.Linq;\nusin"
  },
  {
    "path": "BMEngine/UI/BBinding.cs",
    "chars": 406,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusi"
  },
  {
    "path": "BMEngine/UI/BetterCheckbox.xaml",
    "chars": 2405,
    "preview": "<UserControl x:Class=\"ZenithEngine.UI.BetterCheckbox\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/"
  },
  {
    "path": "BMEngine/UI/BetterCheckbox.xaml.cs",
    "chars": 4068,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading;\nusing Sys"
  },
  {
    "path": "BMEngine/UI/BetterRadio.xaml",
    "chars": 1411,
    "preview": "<UserControl x:Class=\"ZenithEngine.UI.BetterRadio\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/pre"
  },
  {
    "path": "BMEngine/UI/BetterRadio.xaml.cs",
    "chars": 5017,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading;\nusing Sys"
  },
  {
    "path": "BMEngine/UI/BetterSlider.xaml",
    "chars": 3042,
    "preview": "<UserControl x:Class=\"ZenithEngine.UI.BetterSlider\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/pr"
  },
  {
    "path": "BMEngine/UI/BetterSlider.xaml.cs",
    "chars": 7870,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Text;\nusing"
  },
  {
    "path": "BMEngine/UI/Colors.xaml",
    "chars": 664,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "BMEngine/UI/Converters.cs",
    "chars": 1713,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusi"
  },
  {
    "path": "BMEngine/UI/HexColorPicker.xaml",
    "chars": 761,
    "preview": "<UserControl x:Class=\"ZenithEngine.UI.HexColorPicker\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/"
  },
  {
    "path": "BMEngine/UI/HexColorPicker.xaml.cs",
    "chars": 4667,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusi"
  },
  {
    "path": "BMEngine/UI/InplaceConverter.cs",
    "chars": 1142,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Text;\nusing"
  },
  {
    "path": "BMEngine/UI/ListBox.xaml",
    "chars": 4684,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "BMEngine/UI/Material.xaml",
    "chars": 25304,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "BMEngine/UI/NumberSelect.xaml",
    "chars": 4137,
    "preview": "<UserControl x:Class=\"ZenithEngine.UI.NumberSelect\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/pr"
  },
  {
    "path": "BMEngine/UI/NumberSelect.xaml.cs",
    "chars": 7871,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusi"
  },
  {
    "path": "BMEngine/UI/RippleEffectDecorator.cs",
    "chars": 5188,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading;\nusing Sys"
  },
  {
    "path": "BMEngine/UI/Scrollbar.xaml",
    "chars": 7286,
    "preview": "<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http"
  },
  {
    "path": "BMEngine/UI/ValueSlider.xaml",
    "chars": 864,
    "preview": "<UserControl x:Class=\"ZenithEngine.UI.ValueSlider\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/pre"
  },
  {
    "path": "BMEngine/UI/ValueSlider.xaml.cs",
    "chars": 5450,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusi"
  },
  {
    "path": "BMEngine/ZenithEngine.csproj",
    "chars": 7902,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbui"
  },
  {
    "path": "BMEngine/packages.config",
    "chars": 204,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<packages>\n  <package id=\"OpenTK\" version=\"3.1.0\" targetFramework=\"net461\" />\n  "
  },
  {
    "path": "Black-Midi-Render/App.config",
    "chars": 603,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n  <startup>\n    <supportedRuntime version=\"v4.0\" sku=\".NETFramew"
  },
  {
    "path": "Black-Midi-Render/GLPostbuffer.cs",
    "chars": 1195,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusi"
  },
  {
    "path": "Black-Midi-Render/GLUtils.cs",
    "chars": 3777,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing System.Thr"
  },
  {
    "path": "Black-Midi-Render/KDMAPI.cs",
    "chars": 3550,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.T"
  },
  {
    "path": "Black-Midi-Render/Languages/en/window.xaml",
    "chars": 4318,
    "preview": "<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" \n    xmlns:x=\"http://schemas."
  },
  {
    "path": "Black-Midi-Render/MainWindow.xaml",
    "chars": 36656,
    "preview": "<Window x:Class=\"Zenith_MIDI.MainWindow\"\n        xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    "
  },
  {
    "path": "Black-Midi-Render/MainWindow.xaml.cs",
    "chars": 42398,
    "preview": "using ZenithEngine;\nusing Microsoft.CSharp.RuntimeBinder;\nusing Microsoft.Win32;\nusing System;\nusing System.Collections"
  },
  {
    "path": "Black-Midi-Render/OpenTK.dll.config",
    "chars": 1788,
    "preview": "<configuration>\n  <dllmap os=\"linux\" dll=\"opengl32.dll\" target=\"libGL.so.1\"/>\n  <dllmap os=\"linux\" dll=\"glu32.dll\" targe"
  },
  {
    "path": "Black-Midi-Render/Program.cs",
    "chars": 789,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing Syst"
  },
  {
    "path": "Black-Midi-Render/Properties/AssemblyInfo.cs",
    "chars": 1380,
    "preview": "using System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\n// General Infor"
  },
  {
    "path": "Black-Midi-Render/Properties/Resources.Designer.cs",
    "chars": 2786,
    "preview": "//------------------------------------------------------------------------------\n// <auto-generated>\n//     This code w"
  },
  {
    "path": "Black-Midi-Render/Properties/Resources.resx",
    "chars": 5696,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The prim"
  },
  {
    "path": "Black-Midi-Render/RenderWindow.cs",
    "chars": 34460,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Diagnostics;\nusing System.Dra"
  },
  {
    "path": "Black-Midi-Render/Settings.cs",
    "chars": 2351,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.IO.Compression;\nusing System.Linq;\nusing "
  },
  {
    "path": "Black-Midi-Render/Zenith.csproj",
    "chars": 11624,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbui"
  },
  {
    "path": "Black-Midi-Render/packages.config",
    "chars": 351,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<packages>\n  <package id=\"Newtonsoft.Json\" version=\"12.0.1\" targetFramework=\"net"
  },
  {
    "path": "ClassicRender/ClassicRender.csproj",
    "chars": 6223,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbui"
  },
  {
    "path": "ClassicRender/Languages/en/classic.xaml",
    "chars": 927,
    "preview": "<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" \n    xmlns:x=\"http://schemas."
  },
  {
    "path": "ClassicRender/OpenTK.dll.config",
    "chars": 1788,
    "preview": "<configuration>\n  <dllmap os=\"linux\" dll=\"opengl32.dll\" target=\"libGL.so.1\"/>\n  <dllmap os=\"linux\" dll=\"glu32.dll\" targe"
  },
  {
    "path": "ClassicRender/Properties/AssemblyInfo.cs",
    "chars": 1394,
    "preview": "using System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\n// General Infor"
  },
  {
    "path": "ClassicRender/Properties/Resources.Designer.cs",
    "chars": 3156,
    "preview": "//------------------------------------------------------------------------------\n// <auto-generated>\n//     This code w"
  },
  {
    "path": "ClassicRender/Properties/Resources.resx",
    "chars": 6066,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The prim"
  },
  {
    "path": "ClassicRender/README.md",
    "chars": 24,
    "preview": "# Zenith-Classic-Render\n"
  },
  {
    "path": "ClassicRender/Render.cs",
    "chars": 38364,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusi"
  },
  {
    "path": "ClassicRender/Settings.cs",
    "chars": 514,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nna"
  },
  {
    "path": "ClassicRender/SettingsCtrl.xaml",
    "chars": 3748,
    "preview": "<UserControl\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n             xmlns:x=\"http:"
  },
  {
    "path": "ClassicRender/SettingsCtrl.xaml.cs",
    "chars": 2944,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing System.Thr"
  },
  {
    "path": "ClassicRender/packages.config",
    "chars": 206,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<packages>\n  <package id=\"Newtonsoft.Json\" version=\"12.0.1\" targetFramework=\"net"
  },
  {
    "path": "FlatRender/FlatRender.csproj",
    "chars": 6217,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbui"
  },
  {
    "path": "FlatRender/Languages/en/flat.xaml",
    "chars": 821,
    "preview": "<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" \n    xmlns:x=\"http://schemas."
  },
  {
    "path": "FlatRender/OpenTK.dll.config",
    "chars": 1788,
    "preview": "<configuration>\n  <dllmap os=\"linux\" dll=\"opengl32.dll\" target=\"libGL.so.1\"/>\n  <dllmap os=\"linux\" dll=\"glu32.dll\" targe"
  },
  {
    "path": "FlatRender/Properties/AssemblyInfo.cs",
    "chars": 1388,
    "preview": "using System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\n// General Infor"
  },
  {
    "path": "FlatRender/Properties/Resources.Designer.cs",
    "chars": 3150,
    "preview": "//------------------------------------------------------------------------------\n// <auto-generated>\n//     This code w"
  },
  {
    "path": "FlatRender/Properties/Resources.resx",
    "chars": 6066,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The prim"
  },
  {
    "path": "FlatRender/README.md",
    "chars": 21,
    "preview": "# Zenith-Flat-Render\n"
  },
  {
    "path": "FlatRender/Render.cs",
    "chars": 23016,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusi"
  },
  {
    "path": "FlatRender/Settings.cs",
    "chars": 467,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nna"
  },
  {
    "path": "FlatRender/SettingsCtrl.xaml",
    "chars": 3454,
    "preview": "<UserControl\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n             xmlns:x=\"http:"
  },
  {
    "path": "FlatRender/SettingsCtrl.xaml.cs",
    "chars": 2567,
    "preview": "using Newtonsoft.Json;\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System"
  },
  {
    "path": "FlatRender/packages.config",
    "chars": 206,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<packages>\n  <package id=\"Newtonsoft.Json\" version=\"12.0.1\" targetFramework=\"net"
  },
  {
    "path": "LICENSE",
    "chars": 1122,
    "preview": "# DON'T BE A DICK PUBLIC LICENSE\n\n> Version 1.1, December 2016\n\n> Copyright (C) 2020 Arduano\n\nEveryone is permitted to c"
  },
  {
    "path": "MidiTrailRender/AuraSelect.xaml",
    "chars": 2734,
    "preview": "<UserControl\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n             xmlns:x=\"http:"
  },
  {
    "path": "MidiTrailRender/AuraSelect.xaml.cs",
    "chars": 6187,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Drawing;\nusing System."
  },
  {
    "path": "MidiTrailRender/Languages/en/miditrail.xaml",
    "chars": 3692,
    "preview": "<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" \n    xmlns:x=\"http://schemas."
  },
  {
    "path": "MidiTrailRender/MidiTrailRender.csproj",
    "chars": 6494,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbui"
  },
  {
    "path": "MidiTrailRender/OpenTK.dll.config",
    "chars": 1788,
    "preview": "<configuration>\n  <dllmap os=\"linux\" dll=\"opengl32.dll\" target=\"libGL.so.1\"/>\n  <dllmap os=\"linux\" dll=\"glu32.dll\" targe"
  },
  {
    "path": "MidiTrailRender/ProfileManager.cs",
    "chars": 3003,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing System.Thr"
  },
  {
    "path": "MidiTrailRender/Properties/AssemblyInfo.cs",
    "chars": 1398,
    "preview": "using System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\n// General Infor"
  },
  {
    "path": "MidiTrailRender/Properties/Resources.Designer.cs",
    "chars": 3530,
    "preview": "//------------------------------------------------------------------------------\n// <auto-generated>\n//     This code w"
  },
  {
    "path": "MidiTrailRender/Properties/Resources.resx",
    "chars": 6301,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The prim"
  },
  {
    "path": "MidiTrailRender/README.md",
    "chars": 25,
    "preview": "# Zenith-MidiTrail-Render"
  },
  {
    "path": "MidiTrailRender/Render.cs",
    "chars": 68737,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.Drawing.Imaging;\nusing System.IO;\nus"
  },
  {
    "path": "MidiTrailRender/Settings.cs",
    "chars": 1392,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nna"
  },
  {
    "path": "MidiTrailRender/SettingsCtrl.xaml",
    "chars": 14748,
    "preview": "<UserControl\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n             xmlns:x=\"http:"
  },
  {
    "path": "MidiTrailRender/SettingsCtrl.xaml.cs",
    "chars": 12842,
    "preview": "using Newtonsoft.Json;\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System"
  },
  {
    "path": "MidiTrailRender/Util.cs",
    "chars": 3791,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusi"
  },
  {
    "path": "MidiTrailRender/packages.config",
    "chars": 206,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<packages>\n  <package id=\"Newtonsoft.Json\" version=\"12.0.1\" targetFramework=\"net"
  },
  {
    "path": "NoteCountRender/Languages/en/notecounter.xaml",
    "chars": 2376,
    "preview": "<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" \n    xmlns:x=\"http://schemas."
  },
  {
    "path": "NoteCountRender/NoteCountRender.csproj",
    "chars": 6154,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbui"
  },
  {
    "path": "NoteCountRender/OpenTK.dll.config",
    "chars": 1788,
    "preview": "<configuration>\n  <dllmap os=\"linux\" dll=\"opengl32.dll\" target=\"libGL.so.1\"/>\n  <dllmap os=\"linux\" dll=\"glu32.dll\" targe"
  },
  {
    "path": "NoteCountRender/Properties/AssemblyInfo.cs",
    "chars": 1398,
    "preview": "using System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\n// General Infor"
  },
  {
    "path": "NoteCountRender/Properties/Resources.Designer.cs",
    "chars": 3160,
    "preview": "//------------------------------------------------------------------------------\n// <auto-generated>\n//     This code w"
  },
  {
    "path": "NoteCountRender/Properties/Resources.resx",
    "chars": 6066,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The prim"
  },
  {
    "path": "NoteCountRender/README.md",
    "chars": 51,
    "preview": "# Zenith-Note-Count-Render\nNote counter for Zenith\n"
  },
  {
    "path": "NoteCountRender/Render.cs",
    "chars": 18102,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.IO;\nusing System.Linq;\nusing System."
  },
  {
    "path": "NoteCountRender/Settings.cs",
    "chars": 1659,
    "preview": "using OpenTK.Graphics.OpenGL;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusi"
  },
  {
    "path": "NoteCountRender/SettingsCtrl.xaml",
    "chars": 12361,
    "preview": "<UserControl x:Class=\"NoteCountRender.SettingsCtrl\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/pr"
  },
  {
    "path": "NoteCountRender/SettingsCtrl.xaml.cs",
    "chars": 11259,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing System.Thr"
  },
  {
    "path": "NoteCountRender/packages.config",
    "chars": 206,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<packages>\n  <package id=\"Newtonsoft.Json\" version=\"12.0.1\" targetFramework=\"net"
  },
  {
    "path": "PFARender/.gitignore",
    "chars": 6,
    "preview": "\nobj/*"
  },
  {
    "path": "PFARender/Languages/en/pfa.xaml",
    "chars": 1312,
    "preview": "<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" \n    xmlns:x=\"http://schemas."
  },
  {
    "path": "PFARender/OpenTK.dll.config",
    "chars": 1788,
    "preview": "<configuration>\n  <dllmap os=\"linux\" dll=\"opengl32.dll\" target=\"libGL.so.1\"/>\n  <dllmap os=\"linux\" dll=\"glu32.dll\" targe"
  },
  {
    "path": "PFARender/PFARender.csproj",
    "chars": 6214,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbui"
  },
  {
    "path": "PFARender/Properties/AssemblyInfo.cs",
    "chars": 1386,
    "preview": "using System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\n// General Infor"
  },
  {
    "path": "PFARender/Properties/Resources.Designer.cs",
    "chars": 3148,
    "preview": "//------------------------------------------------------------------------------\n// <auto-generated>\n//     This code w"
  },
  {
    "path": "PFARender/Properties/Resources.resx",
    "chars": 6066,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The prim"
  },
  {
    "path": "PFARender/README.md",
    "chars": 19,
    "preview": "# Zenith-PFA-Render"
  },
  {
    "path": "PFARender/Render.cs",
    "chars": 75579,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.IO;\nusing System.Linq;\nusing System."
  },
  {
    "path": "PFARender/Settings.cs",
    "chars": 791,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nna"
  },
  {
    "path": "PFARender/SettingsCtrl.xaml",
    "chars": 5048,
    "preview": "<UserControl\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n             xmlns:x=\"http:"
  },
  {
    "path": "PFARender/SettingsCtrl.xaml.cs",
    "chars": 4752,
    "preview": "using Newtonsoft.Json;\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System"
  },
  {
    "path": "PFARender/packages.config",
    "chars": 206,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<packages>\n  <package id=\"Newtonsoft.Json\" version=\"12.0.1\" targetFramework=\"net"
  },
  {
    "path": "README-plugin.md",
    "chars": 1268,
    "preview": "# Black-Midi-Render\n\n## Creating a plugin project:\n- Create a new class library project\n- Add references to: BMEngine pr"
  },
  {
    "path": "README.md",
    "chars": 6317,
    "preview": "<h1 align=\"center\">Zenith</h1>\n\n<p align=\"center\">\n    <img src=\"https://i.imgur.com/jshhiL3.png\" width=\"256\" />\n    <br"
  },
  {
    "path": "ScriptedRenderer/Languages/en/scripted.xaml",
    "chars": 1335,
    "preview": "<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" \n    xmlns:x=\"http://schemas."
  },
  {
    "path": "ScriptedRenderer/OpenTK.dll.config",
    "chars": 1788,
    "preview": "<configuration>\n  <dllmap os=\"linux\" dll=\"opengl32.dll\" target=\"libGL.so.1\"/>\n  <dllmap os=\"linux\" dll=\"glu32.dll\" targe"
  },
  {
    "path": "ScriptedRenderer/Properties/AssemblyInfo.cs",
    "chars": 1396,
    "preview": "using System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\n// General Infor"
  },
  {
    "path": "ScriptedRenderer/Properties/Resources.Designer.cs",
    "chars": 3488,
    "preview": "//------------------------------------------------------------------------------\n// <auto-generated>\n//     This code w"
  },
  {
    "path": "ScriptedRenderer/Properties/Resources.resx",
    "chars": 6305,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The prim"
  },
  {
    "path": "ScriptedRenderer/Render.cs",
    "chars": 31124,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusi"
  },
  {
    "path": "ScriptedRenderer/Script.cs",
    "chars": 1134,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.Linq;\nusing System.Reflection;\nusing"
  },
  {
    "path": "ScriptedRenderer/ScriptedRender.csproj",
    "chars": 6592,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbui"
  },
  {
    "path": "ScriptedRenderer/Settings.cs",
    "chars": 432,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nna"
  },
  {
    "path": "ScriptedRenderer/SettingsCtrl.xaml",
    "chars": 6068,
    "preview": "<UserControl x:Class=\"ScriptedRender.SettingsCtrl\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/pre"
  },
  {
    "path": "ScriptedRenderer/SettingsCtrl.xaml.cs",
    "chars": 41746,
    "preview": "using Microsoft.CSharp;\nusing Microsoft.CSharp.RuntimeBinder;\nusing Newtonsoft.Json.Linq;\nusing SharpCompress;\nusing Sh"
  },
  {
    "path": "ScriptedRenderer/packages.config",
    "chars": 281,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<packages>\n  <package id=\"Newtonsoft.Json\" version=\"12.0.3\" targetFramework=\"net"
  },
  {
    "path": "TexturedRender/Languages/en/textured.xaml",
    "chars": 1194,
    "preview": "<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" \n    xmlns:x=\"http://schemas."
  },
  {
    "path": "TexturedRender/OpenTK.dll.config",
    "chars": 1788,
    "preview": "<configuration>\n  <dllmap os=\"linux\" dll=\"opengl32.dll\" target=\"libGL.so.1\"/>\n  <dllmap os=\"linux\" dll=\"glu32.dll\" targe"
  },
  {
    "path": "TexturedRender/Pack.cs",
    "chars": 4170,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.Linq;\nusing System.Text;\nusing Syste"
  },
  {
    "path": "TexturedRender/Properties/AssemblyInfo.cs",
    "chars": 1396,
    "preview": "using System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\n// General Infor"
  },
  {
    "path": "TexturedRender/Properties/Resources.Designer.cs",
    "chars": 6768,
    "preview": "//------------------------------------------------------------------------------\n// <auto-generated>\n//     This code w"
  },
  {
    "path": "TexturedRender/Properties/Resources.resx",
    "chars": 8485,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The prim"
  },
  {
    "path": "TexturedRender/README.md",
    "chars": 67,
    "preview": "# Zenith-Texture-Render\nTexture/Resource pack renderer for Zenith.\n"
  },
  {
    "path": "TexturedRender/Render.cs",
    "chars": 61138,
    "preview": "using ZenithEngine;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System."
  },
  {
    "path": "TexturedRender/Resources/pack.json",
    "chars": 1002,
    "preview": "{\n  //Any line that starts with \"//\" is a comment and can be removed\n  \"description\": \"Default resource pack for Zenith"
  },
  {
    "path": "TexturedRender/Settings.cs",
    "chars": 513,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nna"
  },
  {
    "path": "TexturedRender/SettingsCtrl.xaml",
    "chars": 5341,
    "preview": "<UserControl\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n             xmlns:x=\"http:"
  },
  {
    "path": "TexturedRender/SettingsCtrl.xaml.cs",
    "chars": 46144,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Drawing;\nusing System.IO;\nusing "
  },
  {
    "path": "TexturedRender/TexturedRender.csproj",
    "chars": 7195,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbui"
  },
  {
    "path": "TexturedRender/packages.config",
    "chars": 281,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<packages>\n  <package id=\"Newtonsoft.Json\" version=\"12.0.1\" targetFramework=\"net"
  },
  {
    "path": "Zenith.sln",
    "chars": 13415,
    "preview": "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 16\nVisualStudioVersion = 16.0.2900"
  },
  {
    "path": "ZenithInstaller/App.config",
    "chars": 182,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<configuration>\n    <startup> \n        <supportedRuntime version=\"v4.0\" sku=\".N"
  },
  {
    "path": "ZenithInstaller/App.xaml",
    "chars": 373,
    "preview": "<Application x:Class=\"ZenithInstaller.App\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentatio"
  },
  {
    "path": "ZenithInstaller/App.xaml.cs",
    "chars": 329,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Configuration;\nusing System.Data;\nusing System.Linq;\nusing"
  },
  {
    "path": "ZenithInstaller/FodyWeavers.xml",
    "chars": 137,
    "preview": "<Weavers xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"FodyWeavers.xsd\">\n  <Cost"
  },
  {
    "path": "ZenithInstaller/FodyWeavers.xsd",
    "chars": 6616,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n  <!-- This file was gen"
  },
  {
    "path": "ZenithInstaller/MainWindow.xaml",
    "chars": 1170,
    "preview": "<Window x:Class=\"ZenithInstaller.MainWindow\"\n        xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n"
  },
  {
    "path": "ZenithInstaller/MainWindow.xaml.cs",
    "chars": 2213,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing System.Thr"
  },
  {
    "path": "ZenithInstaller/Program.cs",
    "chars": 6412,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Linq;\nusing Sys"
  },
  {
    "path": "ZenithInstaller/Properties/AssemblyInfo.cs",
    "chars": 2378,
    "preview": "using System.Reflection;\nusing System.Resources;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropSer"
  },
  {
    "path": "ZenithInstaller/Properties/Resources.Designer.cs",
    "chars": 2787,
    "preview": "//------------------------------------------------------------------------------\n// <auto-generated>\n//     This code w"
  },
  {
    "path": "ZenithInstaller/Properties/Resources.resx",
    "chars": 5494,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The prim"
  },
  {
    "path": "ZenithInstaller/Properties/Settings.Designer.cs",
    "chars": 1070,
    "preview": "//------------------------------------------------------------------------------\n// <auto-generated>\n//     This code w"
  },
  {
    "path": "ZenithInstaller/Properties/Settings.settings",
    "chars": 193,
    "preview": "<?xml version='1.0' encoding='utf-8'?>\n<SettingsFile xmlns=\"uri:settings\" CurrentProfile=\"(Default)\">\n  <Profiles>\n    "
  },
  {
    "path": "ZenithInstaller/ZenithInstaller.csproj",
    "chars": 5965,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbui"
  },
  {
    "path": "ZenithInstaller/ZenithInstaller_nf5vy1mn_wpftmp.csproj",
    "chars": 7101,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbui"
  },
  {
    "path": "ZenithInstaller/packages.config",
    "chars": 229,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<packages>\n  <package id=\"Costura.Fody\" version=\"4.1.0\" targetFramework=\"net461\""
  },
  {
    "path": "ZenithShared/InstallFailedException.cs",
    "chars": 276,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nna"
  },
  {
    "path": "ZenithShared/Properties/AssemblyInfo.cs",
    "chars": 1392,
    "preview": "using System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\n// General Infor"
  },
  {
    "path": "ZenithShared/ZenithLanguages.cs",
    "chars": 1851,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.IO.Compression;\nusing System.Linq;\nusing "
  },
  {
    "path": "ZenithShared/ZenithShared.csproj",
    "chars": 3090,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbui"
  },
  {
    "path": "ZenithShared/ZenithUpdates.cs",
    "chars": 11505,
    "preview": "using IWshRuntimeLibrary;\nusing Microsoft.Win32;\nusing Newtonsoft.Json;\nusing Newtonsoft.Json.Linq;\nusing System;\nusing"
  },
  {
    "path": "ZenithShared/packages.config",
    "chars": 139,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<packages>\n  <package id=\"Newtonsoft.Json\" version=\"12.0.3\" targetFramework=\"net"
  },
  {
    "path": "build.bat",
    "chars": 1139,
    "preview": "del /S /F /Q build\\*\nrmdir /s /q build\nmkdir build\n\ncall \"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\"
  }
]

About this extraction

This page contains the full source code of the arduano/Zenith-MIDI GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 175 files (1.1 MB), approximately 251.6k tokens, and a symbol index with 652 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!