├── .gitignore ├── .gitmodules ├── README.md ├── build.proj ├── deps ├── OpenTK │ ├── OpenTK.dll │ └── OpenTK.xml ├── System.Reflection.Metadata.Cil │ └── System.Reflection.Metadata.Cil.dll ├── System.Reflection.Metadata │ ├── System.Reflection.Metadata.dll │ └── System.Reflection.Metadata.xml └── cimgui │ └── x64 │ ├── cimgui.dll │ ├── cimgui.pdb │ └── cimgui.so ├── dir.props ├── dir.targets └── src ├── AssemblyBrowser.sln └── AssemblyBrowser ├── AssemblyBrowser.csproj ├── AssemblyBrowserWindow.cs ├── AsyncStringResult.cs ├── CilToStringUtilities.cs ├── Colors.cs ├── ListNodes.cs ├── Program.cs ├── SimpleGLWindow.cs └── project.json /.gitignore: -------------------------------------------------------------------------------- 1 | syntax: glob 2 | 3 | #NuGet things 4 | project.lock.json 5 | 6 | ### VisualStudio ### 7 | 8 | # User-specific files 9 | *.suo 10 | *.user 11 | *.userosscache 12 | *.sln.docstates 13 | 14 | # Build results 15 | [Dd]ebug/ 16 | [Dd]ebugPublic/ 17 | [Rr]elease/ 18 | [Rr]eleases/ 19 | x64/ 20 | x86/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | msbuild.log 25 | 26 | # Visual Studio 2015 27 | .vs/ 28 | 29 | # Visual Studio 2015 Pre-CTP6 30 | *.sln.ide 31 | *.ide/ 32 | 33 | # MSTest test Results 34 | [Tt]est[Rr]esult*/ 35 | [Bb]uild[Ll]og.* 36 | 37 | #NUNIT 38 | *.VisualState.xml 39 | TestResult.xml 40 | 41 | # Build Results of an ATL Project 42 | [Dd]ebugPS/ 43 | [Rr]eleasePS/ 44 | dlldata.c 45 | 46 | *_i.c 47 | *_p.c 48 | *_i.h 49 | *.ilk 50 | *.meta 51 | *.obj 52 | *.pch 53 | *.pdb 54 | *.pgc 55 | *.pgd 56 | *.rsp 57 | *.sbr 58 | *.tlb 59 | *.tli 60 | *.tlh 61 | *.tmp 62 | *.tmp_proj 63 | *.log 64 | *.vspscc 65 | *.vssscc 66 | .builds 67 | *.pidb 68 | *.svclog 69 | *.scc 70 | 71 | # Chutzpah Test files 72 | _Chutzpah* 73 | 74 | # Visual C++ cache files 75 | ipch/ 76 | *.aps 77 | *.ncb 78 | *.opensdf 79 | *.sdf 80 | *.cachefile 81 | 82 | # Visual Studio profiler 83 | *.psess 84 | *.vsp 85 | *.vspx 86 | 87 | # TFS 2012 Local Workspace 88 | $tf/ 89 | 90 | # Guidance Automation Toolkit 91 | *.gpState 92 | 93 | # ReSharper is a .NET coding add-in 94 | _ReSharper*/ 95 | *.[Rr]e[Ss]harper 96 | *.DotSettings.user 97 | 98 | # JustCode is a .NET coding addin-in 99 | .JustCode 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | _NCrunch_* 109 | .*crunch*.local.xml 110 | 111 | # MightyMoose 112 | *.mm.* 113 | AutoTest.Net/ 114 | 115 | # Web workbench (sass) 116 | .sass-cache/ 117 | 118 | # Installshield output folder 119 | [Ee]xpress/ 120 | 121 | # DocProject is a documentation generator add-in 122 | DocProject/buildhelp/ 123 | DocProject/Help/*.HxT 124 | DocProject/Help/*.HxC 125 | DocProject/Help/*.hhc 126 | DocProject/Help/*.hhk 127 | DocProject/Help/*.hhp 128 | DocProject/Help/Html2 129 | DocProject/Help/html 130 | 131 | # Click-Once directory 132 | publish/ 133 | 134 | # Publish Web Output 135 | *.[Pp]ublish.xml 136 | *.azurePubxml 137 | *.pubxml 138 | *.publishproj 139 | 140 | # NuGet Packages 141 | *.nupkg 142 | **/packages/* 143 | 144 | # Windows Azure Build Output 145 | csx/ 146 | *.build.csdef 147 | 148 | # Windows Store app package directory 149 | AppPackages/ 150 | 151 | # Others 152 | sql/ 153 | *.Cache 154 | ClientBin/ 155 | [Ss]tyle[Cc]op.* 156 | ~$* 157 | *.dbmdl 158 | *.dbproj.schemaview 159 | *.pfx 160 | *.publishsettings 161 | node_modules/ 162 | *.metaproj 163 | *.metaproj.tmp 164 | 165 | # RIA/Silverlight projects 166 | Generated_Code/ 167 | 168 | # Backup & report files from converting an old project file 169 | # to a newer Visual Studio version. Backup files are not needed, 170 | # because we have git ;-) 171 | _UpgradeReport_Files/ 172 | Backup*/ 173 | UpgradeLog*.XML 174 | UpgradeLog*.htm 175 | 176 | # SQL Server files 177 | *.mdf 178 | *.ldf 179 | 180 | # Business Intelligence projects 181 | *.rdl.data 182 | *.bim.layout 183 | *.bim_*.settings 184 | 185 | # Microsoft Fakes 186 | FakesAssemblies/ 187 | 188 | ### MonoDevelop ### 189 | 190 | *.pidb 191 | *.userprefs 192 | 193 | ### Windows ### 194 | 195 | # Windows image file caches 196 | Thumbs.db 197 | ehthumbs.db 198 | 199 | # Folder config file 200 | Desktop.ini 201 | 202 | # Recycle Bin used on file shares 203 | $RECYCLE.BIN/ 204 | 205 | # Windows Installer files 206 | *.cab 207 | *.msi 208 | *.msm 209 | *.msp 210 | 211 | # Windows shortcuts 212 | *.lnk 213 | 214 | ### Linux ### 215 | 216 | *~ 217 | 218 | # KDE directory preferences 219 | .directory 220 | 221 | ### OSX ### 222 | 223 | .DS_Store 224 | .AppleDouble 225 | .LSOverride 226 | 227 | # Icon must end with two \r 228 | Icon 229 | 230 | # Thumbnails 231 | ._* 232 | 233 | # Files that might appear on external disk 234 | .Spotlight-V100 235 | .Trashes 236 | 237 | # Directories potentially created on remote AFP share 238 | .AppleDB 239 | .AppleDesktop 240 | Network Trash Folder 241 | Temporary Items 242 | .apdisk 243 | 244 | # vim temporary files 245 | [._]*.s[a-w][a-z] 246 | [._]s[a-w][a-z] 247 | *.un~ 248 | Session.vim 249 | .netrwhist 250 | *~ 251 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "imgui.net"] 2 | path = imgui.net 3 | url = https://github.com/mellinoe/imgui.net 4 | [submodule "corebuild"] 5 | path = corebuild 6 | url = https://github.com/mellinoe/corebuild 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # assemblybrowser 2 | An GUI-based CIL browser for .NET Core 3 | 4 | ![alt tag](http://i.imgur.com/vE5rUWF.png) 5 | 6 | A side project intended to emulate some of the functionality of ILSpy and similar tools, but running on .NET Core. 7 | 8 | Also using this as an exercise to flesh out [ImGui.NET](https://github.com/mellinoe/ImGui.NET) a bit more. 9 | -------------------------------------------------------------------------------- /build.proj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /deps/OpenTK/OpenTK.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mellinoe/assemblybrowser/e7f1cb0a56e3c696f886926a9d91937e433d77ea/deps/OpenTK/OpenTK.dll -------------------------------------------------------------------------------- /deps/System.Reflection.Metadata.Cil/System.Reflection.Metadata.Cil.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mellinoe/assemblybrowser/e7f1cb0a56e3c696f886926a9d91937e433d77ea/deps/System.Reflection.Metadata.Cil/System.Reflection.Metadata.Cil.dll -------------------------------------------------------------------------------- /deps/System.Reflection.Metadata/System.Reflection.Metadata.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mellinoe/assemblybrowser/e7f1cb0a56e3c696f886926a9d91937e433d77ea/deps/System.Reflection.Metadata/System.Reflection.Metadata.dll -------------------------------------------------------------------------------- /deps/cimgui/x64/cimgui.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mellinoe/assemblybrowser/e7f1cb0a56e3c696f886926a9d91937e433d77ea/deps/cimgui/x64/cimgui.dll -------------------------------------------------------------------------------- /deps/cimgui/x64/cimgui.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mellinoe/assemblybrowser/e7f1cb0a56e3c696f886926a9d91937e433d77ea/deps/cimgui/x64/cimgui.pdb -------------------------------------------------------------------------------- /deps/cimgui/x64/cimgui.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mellinoe/assemblybrowser/e7f1cb0a56e3c696f886926a9d91937e433d77ea/deps/cimgui/x64/cimgui.so -------------------------------------------------------------------------------- /dir.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(ProjectDir)\deps 5 | 6 | 7 | -------------------------------------------------------------------------------- /dir.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/AssemblyBrowser.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.23107.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssemblyBrowser", "AssemblyBrowser\AssemblyBrowser.csproj", "{AE9BC745-284F-42F3-8236-C43F12347FDE}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImGui.NET", "..\imgui.net\src\ImGui.NET\ImGui.NET.csproj", "{2665014F-0FEC-4268-8F77-7B029921AB09}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Debug|x64 = Debug|x64 14 | OSX_Debug|Any CPU = OSX_Debug|Any CPU 15 | OSX_Debug|x64 = OSX_Debug|x64 16 | OSX_Release|Any CPU = OSX_Release|Any CPU 17 | OSX_Release|x64 = OSX_Release|x64 18 | Release|Any CPU = Release|Any CPU 19 | Release|x64 = Release|x64 20 | Ubuntu_Debug|Any CPU = Ubuntu_Debug|Any CPU 21 | Ubuntu_Debug|x64 = Ubuntu_Debug|x64 22 | Ubuntu_Release|Any CPU = Ubuntu_Release|Any CPU 23 | Ubuntu_Release|x64 = Ubuntu_Release|x64 24 | Windows_Debug|Any CPU = Windows_Debug|Any CPU 25 | Windows_Debug|x64 = Windows_Debug|x64 26 | Windows_Release|Any CPU = Windows_Release|Any CPU 27 | Windows_Release|x64 = Windows_Release|x64 28 | EndGlobalSection 29 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 30 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.Debug|Any CPU.ActiveCfg = Windows_Release|x64 31 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.Debug|Any CPU.Build.0 = Windows_Release|x64 32 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.Debug|x64.ActiveCfg = Windows_Debug|x64 33 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.Debug|x64.Build.0 = Windows_Debug|x64 34 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.OSX_Debug|Any CPU.ActiveCfg = Windows_Release|x64 35 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.OSX_Debug|Any CPU.Build.0 = Windows_Release|x64 36 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.OSX_Debug|x64.ActiveCfg = Windows_Release|x64 37 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.OSX_Debug|x64.Build.0 = Windows_Release|x64 38 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.OSX_Release|Any CPU.ActiveCfg = Windows_Release|x64 39 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.OSX_Release|Any CPU.Build.0 = Windows_Release|x64 40 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.OSX_Release|x64.ActiveCfg = Windows_Release|x64 41 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.OSX_Release|x64.Build.0 = Windows_Release|x64 42 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.Release|Any CPU.ActiveCfg = Windows_Release|x64 43 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.Release|Any CPU.Build.0 = Windows_Release|x64 44 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.Release|x64.ActiveCfg = Windows_Release|x64 45 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.Release|x64.Build.0 = Windows_Release|x64 46 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.Ubuntu_Debug|Any CPU.ActiveCfg = Ubuntu_Debug|x64 47 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.Ubuntu_Debug|x64.ActiveCfg = Ubuntu_Debug|x64 48 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.Ubuntu_Debug|x64.Build.0 = Ubuntu_Debug|x64 49 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.Ubuntu_Release|Any CPU.ActiveCfg = Ubuntu_Release|x64 50 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.Ubuntu_Release|x64.ActiveCfg = Ubuntu_Release|x64 51 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.Ubuntu_Release|x64.Build.0 = Ubuntu_Release|x64 52 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.Windows_Debug|Any CPU.ActiveCfg = Windows_Debug|x64 53 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.Windows_Debug|Any CPU.Build.0 = Windows_Debug|x64 54 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.Windows_Debug|Any CPU.Deploy.0 = Windows_Debug|x64 55 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.Windows_Debug|x64.ActiveCfg = Windows_Debug|x64 56 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.Windows_Debug|x64.Build.0 = Windows_Debug|x64 57 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.Windows_Release|Any CPU.ActiveCfg = Windows_Release|x64 58 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.Windows_Release|x64.ActiveCfg = Windows_Release|x64 59 | {AE9BC745-284F-42F3-8236-C43F12347FDE}.Windows_Release|x64.Build.0 = Windows_Release|x64 60 | {2665014F-0FEC-4268-8F77-7B029921AB09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 61 | {2665014F-0FEC-4268-8F77-7B029921AB09}.Debug|Any CPU.Build.0 = Debug|Any CPU 62 | {2665014F-0FEC-4268-8F77-7B029921AB09}.Debug|x64.ActiveCfg = Debug|x64 63 | {2665014F-0FEC-4268-8F77-7B029921AB09}.Debug|x64.Build.0 = Debug|x64 64 | {2665014F-0FEC-4268-8F77-7B029921AB09}.OSX_Debug|Any CPU.ActiveCfg = Debug|Any CPU 65 | {2665014F-0FEC-4268-8F77-7B029921AB09}.OSX_Debug|Any CPU.Build.0 = Debug|Any CPU 66 | {2665014F-0FEC-4268-8F77-7B029921AB09}.OSX_Debug|x64.ActiveCfg = Debug|x64 67 | {2665014F-0FEC-4268-8F77-7B029921AB09}.OSX_Debug|x64.Build.0 = Debug|x64 68 | {2665014F-0FEC-4268-8F77-7B029921AB09}.OSX_Release|Any CPU.ActiveCfg = Release|Any CPU 69 | {2665014F-0FEC-4268-8F77-7B029921AB09}.OSX_Release|Any CPU.Build.0 = Release|Any CPU 70 | {2665014F-0FEC-4268-8F77-7B029921AB09}.OSX_Release|x64.ActiveCfg = Release|x64 71 | {2665014F-0FEC-4268-8F77-7B029921AB09}.OSX_Release|x64.Build.0 = Release|x64 72 | {2665014F-0FEC-4268-8F77-7B029921AB09}.Release|Any CPU.ActiveCfg = Release|Any CPU 73 | {2665014F-0FEC-4268-8F77-7B029921AB09}.Release|Any CPU.Build.0 = Release|Any CPU 74 | {2665014F-0FEC-4268-8F77-7B029921AB09}.Release|x64.ActiveCfg = Release|x64 75 | {2665014F-0FEC-4268-8F77-7B029921AB09}.Release|x64.Build.0 = Release|x64 76 | {2665014F-0FEC-4268-8F77-7B029921AB09}.Ubuntu_Debug|Any CPU.ActiveCfg = Debug|Any CPU 77 | {2665014F-0FEC-4268-8F77-7B029921AB09}.Ubuntu_Debug|Any CPU.Build.0 = Debug|Any CPU 78 | {2665014F-0FEC-4268-8F77-7B029921AB09}.Ubuntu_Debug|x64.ActiveCfg = Debug|x64 79 | {2665014F-0FEC-4268-8F77-7B029921AB09}.Ubuntu_Debug|x64.Build.0 = Debug|x64 80 | {2665014F-0FEC-4268-8F77-7B029921AB09}.Ubuntu_Release|Any CPU.ActiveCfg = Release|Any CPU 81 | {2665014F-0FEC-4268-8F77-7B029921AB09}.Ubuntu_Release|Any CPU.Build.0 = Release|Any CPU 82 | {2665014F-0FEC-4268-8F77-7B029921AB09}.Ubuntu_Release|x64.ActiveCfg = Release|x64 83 | {2665014F-0FEC-4268-8F77-7B029921AB09}.Ubuntu_Release|x64.Build.0 = Release|x64 84 | {2665014F-0FEC-4268-8F77-7B029921AB09}.Windows_Debug|Any CPU.ActiveCfg = Debug|Any CPU 85 | {2665014F-0FEC-4268-8F77-7B029921AB09}.Windows_Debug|Any CPU.Build.0 = Debug|Any CPU 86 | {2665014F-0FEC-4268-8F77-7B029921AB09}.Windows_Debug|x64.ActiveCfg = Debug|x64 87 | {2665014F-0FEC-4268-8F77-7B029921AB09}.Windows_Debug|x64.Build.0 = Debug|x64 88 | {2665014F-0FEC-4268-8F77-7B029921AB09}.Windows_Release|Any CPU.ActiveCfg = Release|Any CPU 89 | {2665014F-0FEC-4268-8F77-7B029921AB09}.Windows_Release|Any CPU.Build.0 = Release|Any CPU 90 | {2665014F-0FEC-4268-8F77-7B029921AB09}.Windows_Release|x64.ActiveCfg = Release|x64 91 | {2665014F-0FEC-4268-8F77-7B029921AB09}.Windows_Release|x64.Build.0 = Release|x64 92 | EndGlobalSection 93 | GlobalSection(SolutionProperties) = preSolution 94 | HideSolutionNode = FALSE 95 | EndGlobalSection 96 | EndGlobal 97 | -------------------------------------------------------------------------------- /src/AssemblyBrowser/AssemblyBrowser.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Ubuntu_Debug 5 | Windows_Debug 6 | 7 | 8 | 9 | 14.0 10 | {AE9BC745-284F-42F3-8236-C43F12347FDE} 11 | Exe 12 | AssemblyBrowser 13 | AssemblyBrowser 14 | true 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | cimgui.dll 40 | PreserveNewest 41 | 42 | 43 | cimgui.so 44 | PreserveNewest 45 | 46 | 47 | 48 | 49 | {2665014f-0fec-4268-8f77-7b029921ab09} 50 | ImGui.NET 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /src/AssemblyBrowser/AssemblyBrowserWindow.cs: -------------------------------------------------------------------------------- 1 | using ImGuiNET; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Reflection.Metadata.Cil; 5 | using System.Numerics; 6 | using System.Runtime.InteropServices; 7 | using System.Threading.Tasks; 8 | using System.Threading; 9 | using System.Collections.Immutable; 10 | 11 | namespace AssemblyBrowser 12 | { 13 | public class AssemblyBrowserWindow : SimpleGLWindow 14 | { 15 | private const string ListViewID = "AssemblyListView"; 16 | 17 | private ImmutableArray _loadedAssemblies = ImmutableArray.Empty; 18 | private ImmutableArray _listNodes = ImmutableArray.Empty; 19 | 20 | private readonly uint _leftFrameId = 0; 21 | private uint _rightFrameID = 1; 22 | 23 | private TextInputBuffer _rightFrameTextBuffer = new TextInputBuffer(" "); 24 | private string _rightFrameRawText = " "; 25 | 26 | private IntPtr _filePathInputBuff = Marshal.AllocHGlobal(1024); 27 | private uint _filePathInputLength = 1024; 28 | private IListNode _currentRightFrameNode; 29 | 30 | private Queue _actions = new Queue(); 31 | private Queue _backupQueue = new Queue(); 32 | 33 | private bool _selectableText = false; 34 | private bool _wrapRightFrame = false; 35 | 36 | public AssemblyBrowserWindow() : base(".NET Assembly Browser", 1024, 576) 37 | { 38 | } 39 | 40 | internal void AddAssembly(CilAssembly assm) 41 | { 42 | _loadedAssemblies = _loadedAssemblies.Add(assm); 43 | _listNodes = _listNodes.Add(new AssemblyNode(assm)); 44 | } 45 | 46 | protected override void PreRenderFrame() 47 | { 48 | ExecuteQueuedActionsOnMainThread(); 49 | } 50 | 51 | private void ExecuteQueuedActionsOnMainThread() 52 | { 53 | var queue = Interlocked.Exchange(ref _actions, _backupQueue); 54 | foreach (Action a in queue) 55 | { 56 | a(); 57 | } 58 | 59 | queue.Clear(); 60 | } 61 | 62 | protected unsafe override void UpdateRenderState() 63 | { 64 | ImGuiNative.igGetStyle()->WindowRounding = 0; 65 | ImGuiNative.igGetStyle()->ColumnsMinSpacing = 1; 66 | var leftFrameSize = new Vector2(NativeWindow.Width - 10, NativeWindow.Height); 67 | ImGui.SetNextWindowSize(leftFrameSize, SetCondition.Always); 68 | ImGui.SetNextWindowPosCenter(SetCondition.Always); 69 | ImGui.BeginWindow("Assembly Browser Main Window", 70 | WindowFlags.NoResize | WindowFlags.NoTitleBar | WindowFlags.NoMove | WindowFlags.ShowBorders | WindowFlags.MenuBar | WindowFlags.NoScrollbar); 71 | 72 | DrawTopMenuBar(); 73 | 74 | ImGuiNative.igColumns(2, "MainLayoutColumns", true); 75 | 76 | // Left panel 77 | ImGui.BeginChildFrame 78 | (_leftFrameId, 79 | new Vector2(ImGuiNative.igGetColumnWidth(0), ImGui.GetWindowHeight() - 40), 80 | WindowFlags.ShowBorders | WindowFlags.HorizontalScrollbar); 81 | 82 | DrawAssemblyListView(); 83 | ImGui.EndChildFrame(); 84 | 85 | // Right panel 86 | ImGuiNative.igNextColumn(); 87 | Vector2 rightFrameSize = new Vector2(ImGuiNative.igGetColumnWidth(1), ImGui.GetWindowHeight() - 40); 88 | ImGui.BeginChildFrame(_rightFrameID, rightFrameSize, WindowFlags.ShowBorders | WindowFlags.HorizontalScrollbar); 89 | DrawRightFrame(rightFrameSize); 90 | ImGui.EndChildFrame(); 91 | 92 | ImGui.EndWindow(); 93 | } 94 | 95 | private void DrawTopMenuBar() 96 | { 97 | ImGui.BeginMenuBar(); 98 | 99 | if (ImGui.BeginMenu("File", true)) 100 | { 101 | ShowModalFilePopup(); 102 | 103 | if (ImGui.MenuItem("About", null)) 104 | { 105 | } 106 | 107 | ImGui.Separator(); 108 | 109 | if (ImGui.MenuItem("Exit", "Alt+F4")) 110 | { 111 | NativeWindow.Visible = false; 112 | } 113 | ImGui.EndMenu(); 114 | } 115 | 116 | if (ImGui.BeginMenu("View", true)) 117 | { 118 | ImGui.Checkbox("Selectable right frame text", ref _selectableText); 119 | ImGui.Checkbox("Wrap right frame text", ref _wrapRightFrame); 120 | 121 | ImGui.EndMenu(); 122 | } 123 | 124 | ImGui.EndMenuBar(); 125 | } 126 | 127 | private unsafe void ShowModalFilePopup() 128 | { 129 | ImGui.Text("Enter file path and press Enter"); 130 | if (ImGui.InputText("", _filePathInputBuff, _filePathInputLength, InputTextFlags.EnterReturnsTrue | InputTextFlags.AutoSelectAll, null)) 131 | { 132 | string path = Marshal.PtrToStringAnsi(_filePathInputBuff); 133 | TryOpenAssembly(path); 134 | ImGui.CloseCurrentPopup(); 135 | } 136 | } 137 | 138 | public async void TryOpenAssembly(string path) 139 | { 140 | try 141 | { 142 | CilAssembly newAssm = await Task.Run(() => CilAssembly.Create(path)); 143 | AddAssembly(newAssm); 144 | } 145 | catch 146 | { 147 | Console.WriteLine("Failed to open " + path); 148 | } 149 | } 150 | 151 | private void DrawRightFrame(Vector2 frameSize) 152 | { 153 | var rightFrameNode = ListView.GetSelectedNode(ListViewID); 154 | 155 | if (_currentRightFrameNode != rightFrameNode) 156 | { 157 | _currentRightFrameNode = rightFrameNode; 158 | Task.Run(() => 159 | { 160 | string newText = rightFrameNode.GetNodeSpecialText(); 161 | TextInputBuffer newBuffer = new TextInputBuffer(newText); 162 | InvokeOnMainThread(() => 163 | { 164 | if (_currentRightFrameNode == rightFrameNode) 165 | { 166 | _rightFrameTextBuffer.Dispose(); 167 | _rightFrameTextBuffer = newBuffer; 168 | _rightFrameRawText = newText; 169 | } 170 | else 171 | { 172 | newBuffer.Dispose(); 173 | } 174 | }); 175 | }); 176 | } 177 | 178 | if (_selectableText) 179 | { 180 | ImGui.PushStyleColor(ColorTarget.FrameBg, new Vector4(1, 1, 1, 1)); 181 | ImGui.PushStyleColor(ColorTarget.Text, new Vector4(0, 0, 0, 1)); 182 | 183 | ImGui.InputTextMultiline( 184 | "", 185 | _rightFrameTextBuffer.Buffer, 186 | _rightFrameTextBuffer.Length, 187 | frameSize * new Vector2(2.5f, 1f) - Vector2.UnitY * 35f, 188 | InputTextFlags.ReadOnly, 189 | null, 190 | IntPtr.Zero); 191 | 192 | ImGui.PopStyleColor(2); 193 | } 194 | else 195 | { 196 | unsafe 197 | { 198 | byte* start = (byte*)_rightFrameTextBuffer.Buffer.ToPointer(); 199 | byte* end = start + _rightFrameTextBuffer.Length; 200 | 201 | if (_wrapRightFrame) 202 | { 203 | ImGuiNative.igPushTextWrapPos(ImGuiNative.igGetColumnWidth(ImGuiNative.igGetColumnIndex())); 204 | } 205 | 206 | ImGuiNative.igTextUnformatted(start, end); 207 | 208 | if (_wrapRightFrame) 209 | { 210 | ImGuiNative.igPopTextWrapPos(); 211 | } 212 | } 213 | } 214 | 215 | } 216 | 217 | private unsafe void DrawAssemblyListView() 218 | { 219 | ListView.BeginListView(ListViewID); 220 | foreach (IListNode node in _listNodes) 221 | { 222 | node.Draw(); 223 | } 224 | ListView.EndListView(); 225 | 226 | } 227 | 228 | private void InvokeOnMainThread(Action action) 229 | { 230 | _actions.Enqueue(action); 231 | } 232 | } 233 | } 234 | -------------------------------------------------------------------------------- /src/AssemblyBrowser/AsyncStringResult.cs: -------------------------------------------------------------------------------- 1 | using ImGuiNET; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Runtime.InteropServices; 6 | using System.Text; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | 10 | namespace AssemblyBrowser 11 | { 12 | public class AsyncTextInputBufferResult 13 | { 14 | public TextInputBuffer Buffer { get; private set; } 15 | 16 | public AsyncTextInputBufferResult(Func initializationFunc, CancellationToken cancellationToken, TextInputBuffer defaultBuffer = null) 17 | { 18 | if (defaultBuffer == null) 19 | { 20 | defaultBuffer = new TextInputBuffer("Loading..."); 21 | } 22 | Buffer = defaultBuffer; 23 | Task.Run(() => 24 | { 25 | string result = initializationFunc(); 26 | Buffer.Dispose(); 27 | Buffer = new TextInputBuffer(result); 28 | 29 | }, cancellationToken); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/AssemblyBrowser/CilToStringUtilities.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Reflection.Metadata.Cil.Visitor; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace AssemblyBrowser 10 | { 11 | public static class CilToStringUtilities 12 | { 13 | public static string GetStringFromCilElement(ICilVisitable visitable) 14 | { 15 | StringBuilder sb = new StringBuilder(); 16 | StringWriter writer = new StringWriter(sb); 17 | CilToStringVisitor visitor = new CilToStringVisitor(new CilVisitorOptions(false), writer); 18 | 19 | visitable.Accept(visitor); 20 | return sb.ToString(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/AssemblyBrowser/Colors.cs: -------------------------------------------------------------------------------- 1 | using System.Numerics; 2 | 3 | namespace AssemblyBrowser 4 | { 5 | public static class Colors 6 | { 7 | public static readonly Vector4 Red = new Vector4(1, 0, 0, 1); 8 | public static readonly Vector4 Green = new Vector4(0, 1, 0, 1); 9 | public static readonly Vector4 Blue = new Vector4(0, 0, 1, 1); 10 | public static readonly Vector4 Yellow = new Vector4(.85f, .85f, 0.15f, 1); 11 | public static readonly Vector4 Grey = new Vector4(.25f, .25f, .25f, 1); 12 | public static readonly Vector4 Cyan = new Vector4(0, 1, 1, 1); 13 | public static readonly Vector4 White = new Vector4(1, 1, 1, 1); 14 | 15 | public static readonly Vector4 NamespaceLabel = new Vector4(240f / 255f, 202f / 255f, 147f / 255f, 1f); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/AssemblyBrowser/ListNodes.cs: -------------------------------------------------------------------------------- 1 | using ImGuiNET; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Numerics; 8 | using System.Reflection; 9 | using System.Reflection.Metadata.Cil; 10 | using System.Reflection.Metadata.Cil.Visitor; 11 | using System.Text; 12 | using System.Threading.Tasks; 13 | 14 | namespace AssemblyBrowser 15 | { 16 | public static class ListView 17 | { 18 | private static readonly Dictionary s_selectedNodes = new Dictionary(); 19 | private static string s_currentViewID; 20 | 21 | public static IListNode GetSelectedNode(string id) 22 | { 23 | IListNode node; 24 | s_selectedNodes.TryGetValue(id, out node); 25 | return node; 26 | } 27 | 28 | public static IListNode GetSelectedNodeForCurrentView() 29 | { 30 | Debug.Assert(s_currentViewID != null); 31 | 32 | IListNode node; 33 | s_selectedNodes.TryGetValue(s_currentViewID, out node); 34 | return node; 35 | } 36 | 37 | 38 | public static void BeginListView(string id) 39 | { 40 | s_currentViewID = id; 41 | } 42 | 43 | public static void EndListView() 44 | { 45 | s_currentViewID = null; 46 | } 47 | 48 | public static void SetSelectedNode(IListNode node) 49 | { 50 | Debug.Assert(s_currentViewID != null); 51 | s_selectedNodes[s_currentViewID] = node; 52 | } 53 | } 54 | 55 | public interface IListNode 56 | { 57 | void Draw(); 58 | bool IsCollapsed { get; set; } 59 | bool IsSelected { get; } 60 | string Label { get; } 61 | Guid ID { get; } 62 | IEnumerable Children { get; } 63 | string GetNodeSpecialText(); 64 | } 65 | 66 | public abstract class ListNode : IListNode 67 | { 68 | private string _specialText; 69 | 70 | public Guid ID { get; } = Guid.NewGuid(); 71 | 72 | public unsafe void Draw() 73 | { 74 | ImGui.PushID(ID.ToString()); 75 | if (ImGui.Selectable($"##{ID}", IsSelected)) 76 | { 77 | bool isCtrlPressed = ImGuiNative.igGetIO()->KeyCtrl == 1; 78 | 79 | if (!isCtrlPressed && IsSelected || IsCollapsed) 80 | { 81 | IsCollapsed = !IsCollapsed; 82 | } 83 | 84 | if (IsSelected && isCtrlPressed) 85 | { 86 | ListView.SetSelectedNode(null); 87 | } 88 | else 89 | { 90 | ListView.SetSelectedNode(this); 91 | } 92 | } 93 | ImGui.PopID(); 94 | if (Children.Any()) 95 | { 96 | ImGui.SetNextTreeNodeOpened(!IsCollapsed); 97 | PreDrawNodeLabel(); 98 | ImGui.SameLine(); 99 | if (ImGui.TreeNode(Label)) 100 | { 101 | PostDrawNodeLabel(); 102 | foreach (IListNode node in Children) 103 | { 104 | node.Draw(); 105 | } 106 | 107 | ImGui.TreePop(); 108 | } 109 | 110 | if (IsCollapsed) 111 | { 112 | PostDrawNodeLabel(); 113 | } 114 | } 115 | else 116 | { 117 | PreDrawNodeLabel(); 118 | ImGui.SameLine(); 119 | ImGui.Text(Label); 120 | PostDrawNodeLabel(); 121 | } 122 | 123 | } 124 | 125 | public string GetNodeSpecialText() 126 | { 127 | if (_specialText == null) 128 | { 129 | try 130 | { 131 | _specialText = InternalGetSpecialText(); 132 | } 133 | catch (Exception e) 134 | { 135 | _specialText = e.ToString(); 136 | } 137 | } 138 | 139 | return _specialText; 140 | } 141 | 142 | protected abstract string InternalGetSpecialText(); 143 | 144 | protected virtual void PreDrawNodeLabel() { } 145 | protected virtual void PostDrawNodeLabel() { } 146 | 147 | public bool IsCollapsed { get; set; } = true; 148 | public bool IsSelected => ListView.GetSelectedNodeForCurrentView() == this; 149 | 150 | public abstract string Label { get; } 151 | public abstract IEnumerable Children { get; } 152 | 153 | } 154 | 155 | public class AssemblyNode : ListNode 156 | { 157 | private readonly CilAssembly _assembly; 158 | private readonly List _children = new List(); 159 | 160 | public AssemblyNode(CilAssembly assm) 161 | { 162 | _assembly = assm; 163 | _children.Add(new AssemblyReferencesNode(_assembly.AssemblyReferences)); 164 | var groupings = _assembly.TypeDefinitions.GroupBy((ctd) => ctd.Namespace); 165 | foreach (var ns in groupings) 166 | { 167 | _children.Add(new NamespaceNode(ns.Key, ns)); 168 | } 169 | } 170 | 171 | public override IEnumerable Children => _children; 172 | 173 | public override string Label => $"{_assembly.Name} [{_assembly.Version}]"; 174 | 175 | protected override string InternalGetSpecialText() 176 | { 177 | return CilToStringUtilities.GetStringFromCilElement(_assembly); 178 | } 179 | } 180 | 181 | public class AssemblyReferencesNode : ListNode 182 | { 183 | private readonly List _assemblyRefs; 184 | 185 | public AssemblyReferencesNode(IEnumerable assemblyReferences) 186 | { 187 | _assemblyRefs = assemblyReferences.Select(car => new AssemblyReferenceNode(car)).ToList(); 188 | } 189 | 190 | public override IEnumerable Children => _assemblyRefs; 191 | 192 | public override string Label => "References"; 193 | 194 | protected override string InternalGetSpecialText() 195 | { 196 | return string.Join(Environment.NewLine, _assemblyRefs.Select(arn => arn.GetInternalString())); 197 | } 198 | 199 | private class AssemblyReferenceNode : ListNode 200 | { 201 | private readonly CilAssemblyReference _assemblyRef; 202 | 203 | public AssemblyReferenceNode(CilAssemblyReference car) 204 | { 205 | _assemblyRef = car; 206 | } 207 | 208 | public override IEnumerable Children => Enumerable.Empty(); 209 | 210 | public override string Label => $"{_assemblyRef.Name} [{_assemblyRef.GetFormattedVersion()}]"; 211 | 212 | protected override string InternalGetSpecialText() 213 | { 214 | return CilToStringUtilities.GetStringFromCilElement(_assemblyRef); 215 | } 216 | 217 | internal string GetInternalString() 218 | { 219 | return InternalGetSpecialText(); 220 | } 221 | } 222 | } 223 | 224 | public class NamespaceNode : ListNode 225 | { 226 | private readonly List _children; 227 | private readonly string _name; 228 | 229 | public NamespaceNode(string name, IEnumerable types) 230 | { 231 | _name = name; 232 | _children = types.Select(ctd => new TypeDefinitionNode(ctd)).ToList(); 233 | } 234 | 235 | public override IEnumerable Children => _children; 236 | 237 | public override string Label 238 | { 239 | get 240 | { 241 | return $"{{}} {_name}"; 242 | } 243 | } 244 | 245 | protected override string InternalGetSpecialText() 246 | { 247 | if (string.IsNullOrWhiteSpace(_name)) 248 | { 249 | return "Global Namespace"; 250 | } 251 | else 252 | { 253 | return "Namespace " + _name; 254 | } 255 | } 256 | 257 | protected override void PreDrawNodeLabel() 258 | { 259 | ImGui.PushStyleColor(ColorTarget.Text, Colors.NamespaceLabel); 260 | } 261 | 262 | protected override void PostDrawNodeLabel() 263 | { 264 | ImGui.PopStyleColor(); 265 | } 266 | } 267 | 268 | public class TypeDefinitionNode : ListNode 269 | { 270 | private CilTypeDefinition _typeDefinition; 271 | private List _children = new List(); 272 | 273 | public TypeDefinitionNode(CilTypeDefinition typeDef) 274 | { 275 | _typeDefinition = typeDef; 276 | _children.AddRange(typeDef.FieldDefinitions.Select(cf => new FieldNode(cf))); 277 | _children.AddRange(typeDef.Properties.Select(cp => new PropertyNode(cp))); 278 | _children.AddRange( 279 | typeDef.MethodDefinitions 280 | .Where(cmd => !cmd.Name.StartsWith("get_") && !cmd.Name.StartsWith("set_")) 281 | .Select(cmd => new MethodNode(cmd))); 282 | } 283 | 284 | public override IEnumerable Children => _children; 285 | 286 | public override string Label => _typeDefinition.Name; 287 | 288 | protected override string InternalGetSpecialText() 289 | { 290 | return CilToStringUtilities.GetStringFromCilElement(_typeDefinition); 291 | } 292 | } 293 | 294 | public class FieldNode : ListNode 295 | { 296 | private CilField _field; 297 | 298 | public FieldNode(CilField cf) 299 | { 300 | _field = cf; 301 | } 302 | 303 | public override IEnumerable Children => Enumerable.Empty(); 304 | 305 | public override string Label => _field.Name; 306 | 307 | protected override string InternalGetSpecialText() 308 | { 309 | return CilToStringUtilities.GetStringFromCilElement(_field); 310 | } 311 | } 312 | 313 | public class MethodNode : ListNode 314 | { 315 | private CilMethodDefinition _methodDef; 316 | 317 | public MethodNode(CilMethodDefinition methodDef) 318 | { 319 | _methodDef = methodDef; 320 | } 321 | 322 | public override IEnumerable Children => Enumerable.Empty(); 323 | 324 | public override string Label => $"{_methodDef.Name}({_methodDef.GetDecodedSignature()})"; 325 | 326 | protected override string InternalGetSpecialText() 327 | { 328 | return CilToStringUtilities.GetStringFromCilElement(_methodDef); 329 | } 330 | protected override void PreDrawNodeLabel() 331 | { 332 | Vector4 color = _methodDef.HasImport ? new Vector4(.95f, .35f, .35f, 1.0f) : new Vector4(.75f, .25f, .95f, 1.0f); 333 | ImGui.PushStyleColor(ColorTarget.Text, color); 334 | } 335 | 336 | protected override void PostDrawNodeLabel() 337 | { 338 | ImGui.PopStyleColor(); 339 | } 340 | 341 | } 342 | 343 | public class PropertyNode : ListNode 344 | { 345 | private readonly CilProperty _property; 346 | private readonly List _children = new List(); 347 | 348 | public PropertyNode(CilProperty cp) 349 | { 350 | _property = cp; 351 | if (cp.HasGetter) 352 | { 353 | _children.Add(new MethodNode(cp.Getter)); 354 | } 355 | if (cp.HasSetter) 356 | { 357 | _children.Add(new MethodNode(cp.Setter)); 358 | } 359 | } 360 | 361 | public override IEnumerable Children => _children; 362 | 363 | public override string Label => $"{_property.Name} {{ {(_property.HasGetter ? "get; " : string.Empty)}{(_property.HasSetter ? "set; " : string.Empty)}}}"; 364 | 365 | protected override string InternalGetSpecialText() 366 | { 367 | return CilToStringUtilities.GetStringFromCilElement(_property); 368 | } 369 | } 370 | } 371 | -------------------------------------------------------------------------------- /src/AssemblyBrowser/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection.Metadata.Cil; 3 | 4 | namespace AssemblyBrowser 5 | { 6 | public class Program 7 | { 8 | public static unsafe void Main(string[] args) 9 | { 10 | AssemblyBrowserWindow browser = new AssemblyBrowserWindow(); 11 | for (int i = 0; i < args.Length; i++) 12 | { 13 | string path = args[i]; 14 | browser.TryOpenAssembly(path); 15 | } 16 | 17 | browser.RunWindowLoop(); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/AssemblyBrowser/SimpleGLWindow.cs: -------------------------------------------------------------------------------- 1 | using ImGuiNET; 2 | using OpenTK; 3 | using OpenTK.Graphics; 4 | using OpenTK.Graphics.OpenGL; 5 | using OpenTK.Input; 6 | using System; 7 | using System.ComponentModel; 8 | using System.Runtime.InteropServices; 9 | using System.Threading; 10 | 11 | namespace AssemblyBrowser 12 | { 13 | public abstract class SimpleGLWindow 14 | { 15 | private NativeWindow _nativeWindow; 16 | private GraphicsContext _graphicsContext; 17 | private int s_fontTexture; 18 | private float _wheelPosition; 19 | private float _sliderVal; 20 | private System.Numerics.Vector4 _buttonColor = new System.Numerics.Vector4(55f / 255f, 155f / 255f, 1f, 1f); 21 | private bool _mainWindowOpened; 22 | private static double s_desiredFrameLength = 1f / 60.0f; 23 | private DateTime _previousFrameStartTime; 24 | private float _scaleFactor; 25 | private System.Numerics.Vector3 _positionValue = new System.Numerics.Vector3(500); 26 | 27 | private bool _visible = false; 28 | public bool Visible 29 | { 30 | get { return _visible; } 31 | set 32 | { 33 | _visible = value; 34 | NativeWindow.Visible = value; 35 | } 36 | } 37 | 38 | public NativeWindow NativeWindow => _nativeWindow; 39 | 40 | public unsafe SimpleGLWindow(string title, int desiredWidth, int desiredHeight) 41 | { 42 | _nativeWindow = new NativeWindow(desiredWidth, desiredHeight, title, GameWindowFlags.Default, GraphicsMode.Default, DisplayDevice.Default); 43 | _scaleFactor = NativeWindow.Width / desiredWidth; 44 | 45 | GraphicsContextFlags flags = GraphicsContextFlags.Default; 46 | _graphicsContext = new GraphicsContext(GraphicsMode.Default, NativeWindow.WindowInfo, 3, 0, flags); 47 | _graphicsContext.MakeCurrent(NativeWindow.WindowInfo); 48 | ((IGraphicsContextInternal)_graphicsContext).LoadAll(); // wtf is this? 49 | GL.ClearColor(Color.Black); 50 | 51 | NativeWindow.Closing += OnWindowClosing; 52 | 53 | 54 | NativeWindow.KeyDown += OnKeyDown; 55 | NativeWindow.KeyUp += OnKeyUp; 56 | NativeWindow.KeyPress += OnKeyPress; 57 | 58 | ImGui.LoadDefaultFont(); 59 | 60 | SetOpenTKKeyMappings(); 61 | 62 | CreateDeviceObjects(); 63 | } 64 | 65 | private void OnWindowClosing(object sender, System.ComponentModel.CancelEventArgs e) 66 | { 67 | _graphicsContext.Dispose(); 68 | Visible = false; 69 | } 70 | 71 | private void OnKeyPress(object sender, KeyPressEventArgs e) 72 | { 73 | ImGui.AddInputCharacter(e.KeyChar); 74 | } 75 | 76 | private static unsafe void SetOpenTKKeyMappings() 77 | { 78 | IO io = ImGui.GetIO(); 79 | io.KeyMap[GuiKey.Tab] = (int)Key.Tab; 80 | io.KeyMap[GuiKey.LeftArrow] = (int)Key.Left; 81 | io.KeyMap[GuiKey.RightArrow] = (int)Key.Right; 82 | io.KeyMap[GuiKey.UpArrow] = (int)Key.Up; 83 | io.KeyMap[GuiKey.DownArrow] = (int)Key.Down; 84 | io.KeyMap[GuiKey.PageUp] = (int)Key.PageUp; 85 | io.KeyMap[GuiKey.PageDown] = (int)Key.PageDown; 86 | io.KeyMap[GuiKey.Home] = (int)Key.Home; 87 | io.KeyMap[GuiKey.End] = (int)Key.End; 88 | io.KeyMap[GuiKey.Delete] = (int)Key.Delete; 89 | io.KeyMap[GuiKey.Backspace] = (int)Key.BackSpace; 90 | io.KeyMap[GuiKey.Enter] = (int)Key.Enter; 91 | io.KeyMap[GuiKey.Escape] = (int)Key.Escape; 92 | io.KeyMap[GuiKey.A] = (int)Key.A; 93 | io.KeyMap[GuiKey.C] = (int)Key.C; 94 | io.KeyMap[GuiKey.V] = (int)Key.V; 95 | io.KeyMap[GuiKey.X] = (int)Key.X; 96 | io.KeyMap[GuiKey.Y] = (int)Key.Y; 97 | io.KeyMap[GuiKey.Z] = (int)Key.Z; 98 | } 99 | 100 | private unsafe void OnKeyDown(object sender, KeyboardKeyEventArgs e) 101 | { 102 | ImGui.GetIO().KeysDown[(int)e.Key] = true; 103 | UpdateModifiers(e); 104 | } 105 | 106 | private unsafe void OnKeyUp(object sender, KeyboardKeyEventArgs e) 107 | { 108 | ImGui.GetIO().KeysDown[(int)e.Key] = false; 109 | UpdateModifiers(e); 110 | } 111 | 112 | private static unsafe void UpdateModifiers(KeyboardKeyEventArgs e) 113 | { 114 | IO io = ImGui.GetIO(); 115 | io.AltPressed = e.Alt; 116 | io.CtrlPressed = e.Control; 117 | io.ShiftPressed = e.Shift; 118 | } 119 | 120 | private unsafe void CreateDeviceObjects() 121 | { 122 | IO io = ImGui.GetIO(); 123 | 124 | // Build texture atlas 125 | FontTextureData texData = io.FontAtlas.GetTexDataAsAlpha8(); 126 | 127 | // Create OpenGL texture 128 | s_fontTexture = GL.GenTexture(); 129 | GL.BindTexture(TextureTarget.Texture2D, s_fontTexture); 130 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear); 131 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear); 132 | GL.TexImage2D( 133 | TextureTarget.Texture2D, 134 | 0, 135 | PixelInternalFormat.Alpha, 136 | texData.Width, 137 | texData.Height, 138 | 0, 139 | PixelFormat.Alpha, 140 | PixelType.UnsignedByte, 141 | new IntPtr(texData.Pixels)); 142 | 143 | // Store the texture identifier in the ImFontAtlas substructure. 144 | io.FontAtlas.SetTexID(s_fontTexture); 145 | 146 | // Cleanup (don't clear the input data if you want to append new fonts later) 147 | //io.Fonts->ClearInputData(); 148 | io.FontAtlas.ClearTexData(); 149 | GL.BindTexture(TextureTarget.Texture2D, 0); 150 | } 151 | 152 | public void RunWindowLoop() 153 | { 154 | Visible = true; 155 | while (Visible) 156 | { 157 | _previousFrameStartTime = DateTime.UtcNow; 158 | 159 | RenderFrame(); 160 | 161 | NativeWindow.ProcessEvents(); 162 | 163 | DateTime afterFrameTime = DateTime.UtcNow; 164 | double elapsed = (afterFrameTime - _previousFrameStartTime).TotalSeconds; 165 | double sleepTime = s_desiredFrameLength - elapsed; 166 | if (sleepTime > 0.0) 167 | { 168 | DateTime finishTime = afterFrameTime + TimeSpan.FromSeconds(sleepTime); 169 | while (DateTime.UtcNow < finishTime) 170 | { 171 | Thread.Sleep(0); 172 | } 173 | } 174 | } 175 | } 176 | 177 | private unsafe void RenderFrame() 178 | { 179 | IO io = ImGui.GetIO(); 180 | io.DisplaySize = new System.Numerics.Vector2(NativeWindow.Width, NativeWindow.Height); 181 | io.DisplayFramebufferScale = new System.Numerics.Vector2(_scaleFactor); 182 | io.DeltaTime = (1f / 60f); 183 | 184 | UpdateImGuiInput(io); 185 | 186 | ImGui.NewFrame(); 187 | PreRenderFrame(); 188 | UpdateRenderState(); 189 | 190 | ImGui.Render(); 191 | 192 | DrawData* data = ImGui.GetDrawData(); 193 | RenderImDrawData(data); 194 | } 195 | 196 | protected abstract void PreRenderFrame(); 197 | protected abstract void UpdateRenderState(); 198 | 199 | private unsafe int OnTextEdited(TextEditCallbackData* data) 200 | { 201 | char currentEventChar = (char)data->EventChar; 202 | return 0; 203 | } 204 | 205 | private unsafe void UpdateImGuiInput(IO io) 206 | { 207 | MouseState cursorState = Mouse.GetCursorState(); 208 | MouseState mouseState = Mouse.GetState(); 209 | 210 | if (NativeWindow.Bounds.Contains(cursorState.X, cursorState.Y)) 211 | { 212 | Point windowPoint = NativeWindow.PointToClient(new Point(cursorState.X, cursorState.Y)); 213 | io.MousePosition = new System.Numerics.Vector2(windowPoint.X / io.DisplayFramebufferScale.X, windowPoint.Y / io.DisplayFramebufferScale.Y); 214 | } 215 | else 216 | { 217 | io.MousePosition = new System.Numerics.Vector2(-1f, -1f); 218 | } 219 | 220 | io.MouseDown[0] = mouseState.LeftButton == ButtonState.Pressed; 221 | io.MouseDown[1] = mouseState.RightButton == ButtonState.Pressed; 222 | io.MouseDown[2] = mouseState.MiddleButton == ButtonState.Pressed; 223 | 224 | float newWheelPos = mouseState.WheelPrecise; 225 | float delta = newWheelPos - _wheelPosition; 226 | _wheelPosition = newWheelPos; 227 | io.MouseWheel = delta; 228 | } 229 | 230 | private unsafe void RenderImDrawData(DrawData* draw_data) 231 | { 232 | // Rendering 233 | int display_w, display_h; 234 | display_w = NativeWindow.Width; 235 | display_h = NativeWindow.Height; 236 | 237 | Vector4 clear_color = new Vector4(114f / 255f, 144f / 255f, 154f / 255f, 1.0f); 238 | GL.Viewport(0, 0, display_w, display_h); 239 | GL.ClearColor(clear_color.X, clear_color.Y, clear_color.Z, clear_color.W); 240 | GL.Clear(ClearBufferMask.ColorBufferBit); 241 | 242 | // We are using the OpenGL fixed pipeline to make the example code simpler to read! 243 | // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers. 244 | int last_texture; 245 | GL.GetInteger(GetPName.TextureBinding2D, out last_texture); 246 | GL.PushAttrib(AttribMask.EnableBit | AttribMask.ColorBufferBit | AttribMask.TransformBit); 247 | GL.Enable(EnableCap.Blend); 248 | GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); 249 | GL.Disable(EnableCap.CullFace); 250 | GL.Disable(EnableCap.DepthTest); 251 | GL.Enable(EnableCap.ScissorTest); 252 | GL.EnableClientState(ArrayCap.VertexArray); 253 | GL.EnableClientState(ArrayCap.TextureCoordArray); 254 | GL.EnableClientState(ArrayCap.ColorArray); 255 | GL.Enable(EnableCap.Texture2D); 256 | 257 | GL.UseProgram(0); 258 | 259 | // Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays) 260 | IO io = ImGui.GetIO(); 261 | ImGui.ScaleClipRects(draw_data, io.DisplayFramebufferScale); 262 | 263 | // Setup orthographic projection matrix 264 | GL.MatrixMode(MatrixMode.Projection); 265 | GL.PushMatrix(); 266 | GL.LoadIdentity(); 267 | GL.Ortho( 268 | 0.0f, 269 | io.DisplaySize.X / io.DisplayFramebufferScale.X, 270 | io.DisplaySize.Y / io.DisplayFramebufferScale.Y, 271 | 0.0f, 272 | -1.0f, 273 | 1.0f); 274 | GL.MatrixMode(MatrixMode.Modelview); 275 | GL.PushMatrix(); 276 | GL.LoadIdentity(); 277 | 278 | // Render command lists 279 | 280 | for (int n = 0; n < draw_data->CmdListsCount; n++) 281 | { 282 | DrawList* cmd_list = draw_data->CmdLists[n]; 283 | byte* vtx_buffer = (byte*)cmd_list->VtxBuffer.Data; 284 | ushort* idx_buffer = (ushort*)cmd_list->IdxBuffer.Data; 285 | 286 | DrawVert vert0 = *((DrawVert*)vtx_buffer); 287 | DrawVert vert1 = *(((DrawVert*)vtx_buffer) + 1); 288 | DrawVert vert2 = *(((DrawVert*)vtx_buffer) + 2); 289 | 290 | GL.VertexPointer(2, VertexPointerType.Float, sizeof(DrawVert), new IntPtr(vtx_buffer + DrawVert.PosOffset)); 291 | GL.TexCoordPointer(2, TexCoordPointerType.Float, sizeof(DrawVert), new IntPtr(vtx_buffer + DrawVert.UVOffset)); 292 | GL.ColorPointer(4, ColorPointerType.UnsignedByte, sizeof(DrawVert), new IntPtr(vtx_buffer + DrawVert.ColOffset)); 293 | 294 | for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) 295 | { 296 | DrawCmd* pcmd = &(((DrawCmd*)cmd_list->CmdBuffer.Data)[cmd_i]); 297 | if (pcmd->UserCallback != IntPtr.Zero) 298 | { 299 | throw new NotImplementedException(); 300 | } 301 | else 302 | { 303 | GL.BindTexture(TextureTarget.Texture2D, pcmd->TextureId.ToInt32()); 304 | GL.Scissor( 305 | (int)pcmd->ClipRect.X, 306 | (int)(io.DisplaySize.Y - pcmd->ClipRect.W), 307 | (int)(pcmd->ClipRect.Z - pcmd->ClipRect.X), 308 | (int)(pcmd->ClipRect.W - pcmd->ClipRect.Y)); 309 | ushort[] indices = new ushort[pcmd->ElemCount]; 310 | for (int i = 0; i < indices.Length; i++) { indices[i] = idx_buffer[i]; } 311 | GL.DrawElements(PrimitiveType.Triangles, (int)pcmd->ElemCount, DrawElementsType.UnsignedShort, new IntPtr(idx_buffer)); 312 | } 313 | idx_buffer += pcmd->ElemCount; 314 | } 315 | } 316 | 317 | // Restore modified state 318 | GL.DisableClientState(ArrayCap.ColorArray); 319 | GL.DisableClientState(ArrayCap.TextureCoordArray); 320 | GL.DisableClientState(ArrayCap.VertexArray); 321 | GL.BindTexture(TextureTarget.Texture2D, last_texture); 322 | GL.MatrixMode(MatrixMode.Modelview); 323 | GL.PopMatrix(); 324 | GL.MatrixMode(MatrixMode.Projection); 325 | GL.PopMatrix(); 326 | GL.PopAttrib(); 327 | 328 | _graphicsContext.SwapBuffers(); 329 | } 330 | } 331 | } 332 | -------------------------------------------------------------------------------- /src/AssemblyBrowser/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "NETStandard.Library": "1.0.0-rc2-23727", 4 | "Microsoft.NETCore.Runtime": "1.0.1-rc2-23727", 5 | "Microsoft.NETCore.ConsoleHost": "1.0.0-rc2-23727", 6 | "System.Runtime.InteropServices.RuntimeInformation": "4.0.0-rc2-23727", 7 | "System.Numerics.Vectors": "4.1.1-rc2-23727", 8 | "System.Collections.Immutable": "1.2.0-rc2-23727", 9 | "System.Console": "4.0.0-rc2-23727", 10 | "System.Threading.Thread": "4.0.0-rc2-23727", 11 | "System.ComponentModel": "4.0.0", 12 | "System.Linq.Expressions": "4.0.10", 13 | "System.IO.FileSystem.Watcher": "4.0.0-rc2-23727", 14 | }, 15 | "runtimes": { 16 | "win10-x64": { }, 17 | "ubuntu.14.04-x64": { }, 18 | }, 19 | "frameworks": { 20 | "dnxcore50": { } 21 | } 22 | } --------------------------------------------------------------------------------