├── .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 | 
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 | }
--------------------------------------------------------------------------------