F/make net core 3 compatible (#11)

* This is backword incompatible!

1: making overlay compatible with .NET Core 2.
2: Removing the dep on lib GlobalHook.
3: Adding coroutines for better foreground thread management.
4: FPS now defaults to vsync
master
Zaafar Ahmed 5 years ago committed by GitHub
parent ccf1065ff9
commit 0094db9cb3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 30
      ClickableTransparentOverlay.sln
  2. 0
      ClickableTransparentOverlay/Assets/HLSL/imgui-frag.hlsl.bytes
  3. 0
      ClickableTransparentOverlay/Assets/HLSL/imgui-vertex.hlsl.bytes
  4. 155
      ClickableTransparentOverlay/ClickableTransparentOverlay.csproj
  5. 470
      ClickableTransparentOverlay/HookController.cs
  6. 655
      ClickableTransparentOverlay/ImGuiController.cs
  7. 126
      ClickableTransparentOverlay/NativeMethods.cs
  8. 297
      ClickableTransparentOverlay/Overlay.cs
  9. 39
      ClickableTransparentOverlay/Properties/AssemblyInfo.cs
  10. 15
      ClickableTransparentOverlay/Shaders/HLSL/imgui-frag.hlsl
  11. 27
      ClickableTransparentOverlay/Shaders/HLSL/imgui-vertex.hlsl
  12. 35
      ClickableTransparentOverlay/app.config
  13. 20
      ClickableTransparentOverlay/packages.config
  14. 14
      ClickableTransparentOverlay/stylecop.json
  15. 38
      DriverProgram/App.config
  16. 102
      DriverProgram/DriverProgram.csproj
  17. 214
      DriverProgram/Program.cs
  18. 35
      DriverProgram/Properties/AssemblyInfo.cs
  19. 5
      DriverProgram/packages.config

@ -1,31 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.168
# Visual Studio Version 16
VisualStudioVersion = 16.0.30128.36
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClickableTransparentOverlay", "ClickableTransparentOverlay\ClickableTransparentOverlay.csproj", "{F5CF8972-D0DA-4FC0-8796-E7C60101C8EA}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClickableTransparentOverlay", "ClickableTransparentOverlay\ClickableTransparentOverlay.csproj", "{210EB536-2C1F-48C0-BE59-6C945FC3E1F2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DriverProgram", "DriverProgram\DriverProgram.csproj", "{370E1945-EF74-4618-A2DE-B5796AC3093E}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DriverProgram", "DriverProgram\DriverProgram.csproj", "{8F05BC9C-06E7-49F8-8417-E2E24F07726A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F5CF8972-D0DA-4FC0-8796-E7C60101C8EA}.Debug|x64.ActiveCfg = Debug|x64
{F5CF8972-D0DA-4FC0-8796-E7C60101C8EA}.Debug|x64.Build.0 = Debug|x64
{F5CF8972-D0DA-4FC0-8796-E7C60101C8EA}.Release|x64.ActiveCfg = Release|x64
{F5CF8972-D0DA-4FC0-8796-E7C60101C8EA}.Release|x64.Build.0 = Release|x64
{370E1945-EF74-4618-A2DE-B5796AC3093E}.Debug|x64.ActiveCfg = Debug|x64
{370E1945-EF74-4618-A2DE-B5796AC3093E}.Debug|x64.Build.0 = Debug|x64
{370E1945-EF74-4618-A2DE-B5796AC3093E}.Release|x64.ActiveCfg = Release|x64
{370E1945-EF74-4618-A2DE-B5796AC3093E}.Release|x64.Build.0 = Release|x64
{210EB536-2C1F-48C0-BE59-6C945FC3E1F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{210EB536-2C1F-48C0-BE59-6C945FC3E1F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{210EB536-2C1F-48C0-BE59-6C945FC3E1F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{210EB536-2C1F-48C0-BE59-6C945FC3E1F2}.Release|Any CPU.Build.0 = Release|Any CPU
{8F05BC9C-06E7-49F8-8417-E2E24F07726A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8F05BC9C-06E7-49F8-8417-E2E24F07726A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8F05BC9C-06E7-49F8-8417-E2E24F07726A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8F05BC9C-06E7-49F8-8417-E2E24F07726A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {CC9A7790-CFC1-4D4F-AE2C-177A80D122C8}
SolutionGuid = {0CA675A0-B7AC-4B41-9E79-BFD0DD4F8285}
EndGlobalSection
EndGlobal

@ -1,147 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{F5CF8972-D0DA-4FC0-8796-E7C60101C8EA}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ClickableTransparentOverlay</RootNamespace>
<AssemblyName>ClickableTransparentOverlay</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>false</Optimize>
<RunCodeAnalysis>false</RunCodeAnalysis>
<DocumentationFile>bin\x64\Debug\ClickableTransparentOverlay.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>
</DefineConstants>
<Optimize>true</Optimize>
<DebugType>none</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<NoWarn>
</NoWarn>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<DocumentationFile>bin\x64\Release\ClickableTransparentOverlay.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="Gma.System.MouseKeyHook, Version=5.6.130.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\MouseKeyHook.5.6.0\lib\net40\Gma.System.MouseKeyHook.dll</HintPath>
</Reference>
<Reference Include="ImGui.NET, Version=1.75.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ImGui.NET.1.75.0\lib\netstandard2.0\ImGui.NET.dll</HintPath>
</Reference>
<Reference Include="NativeLibraryLoader, Version=1.0.12.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\NativeLibraryLoader.1.0.12\lib\netstandard2.0\NativeLibraryLoader.dll</HintPath>
</Reference>
<Reference Include="SharpDX, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<HintPath>..\packages\SharpDX.4.2.0\lib\net45\SharpDX.dll</HintPath>
</Reference>
<Reference Include="SharpDX.Direct3D11, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<HintPath>..\packages\SharpDX.Direct3D11.4.2.0\lib\net45\SharpDX.Direct3D11.dll</HintPath>
</Reference>
<Reference Include="SharpDX.DXGI, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<HintPath>..\packages\SharpDX.DXGI.4.2.0\lib\net45\SharpDX.DXGI.dll</HintPath>
</Reference>
<Reference Include="SixLabors.Core, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\SixLabors.Core.1.0.0-beta0007\lib\netstandard2.0\SixLabors.Core.dll</HintPath>
</Reference>
<Reference Include="SixLabors.ImageSharp, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\SixLabors.ImageSharp.1.0.0-beta0006\lib\net472\SixLabors.ImageSharp.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.5.0\lib\netstandard2.0\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.6.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.7.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Windows.Forms" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="Veldrid, Version=4.7.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Veldrid.4.7.0\lib\netstandard2.0\Veldrid.dll</HintPath>
</Reference>
<Reference Include="Veldrid.ImageSharp, Version=4.7.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Veldrid.ImageSharp.4.7.0\lib\netstandard2.0\Veldrid.ImageSharp.dll</HintPath>
</Reference>
<Reference Include="Veldrid.SDL2, Version=4.7.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Veldrid.SDL2.4.7.0\lib\netstandard2.0\Veldrid.SDL2.dll</HintPath>
</Reference>
<Reference Include="Veldrid.StartupUtilities, Version=4.7.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Veldrid.StartupUtilities.4.7.0\lib\netstandard2.0\Veldrid.StartupUtilities.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="HookController.cs" />
<Compile Include="ImGuiController.cs" />
<Compile Include="Overlay.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="NativeMethods.cs" />
<None Remove="Assets\HLSL\imgui-frag.hlsl.bytes" />
<None Remove="Assets\HLSL\imgui-vertex.hlsl.bytes" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
<EmbeddedResource Include="Shaders\HLSL\imgui-vertex.hlsl.bytes" LogicalName="imgui-vertex.hlsl.bytes" />
<EmbeddedResource Include="Shaders\HLSL\imgui-frag.hlsl.bytes" LogicalName="imgui-frag.hlsl.bytes" />
<AdditionalFiles Include="stylecop.json" />
<EmbeddedResource Include="Assets\HLSL\imgui-frag.hlsl.bytes" LogicalName="imgui-frag.hlsl.bytes" />
<EmbeddedResource Include="Assets\HLSL\imgui-vertex.hlsl.bytes" LogicalName="imgui-vertex.hlsl.bytes" />
</ItemGroup>
<ItemGroup>
<Analyzer Include="..\packages\StyleCop.Analyzers.1.1.118\analyzers\dotnet\cs\StyleCop.Analyzers.CodeFixes.dll" />
<Analyzer Include="..\packages\StyleCop.Analyzers.1.1.118\analyzers\dotnet\cs\StyleCop.Analyzers.dll" />
<PackageReference Include="Coroutine" Version="1.0.4" />
<PackageReference Include="ImGui.NET" Version="1.75.0" />
<PackageReference Include="Veldrid" Version="4.7.0" />
<PackageReference Include="Veldrid.ImageSharp" Version="4.7.0" />
<PackageReference Include="Veldrid.Sdl2" Version="4.7.0" />
<PackageReference Include="Veldrid.StartupUtilities" Version="4.7.0" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\ImGui.NET.1.75.0\build\net40\ImGui.NET.targets" Condition="Exists('..\packages\ImGui.NET.1.75.0\build\net40\ImGui.NET.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\ImGui.NET.1.75.0\build\net40\ImGui.NET.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\ImGui.NET.1.75.0\build\net40\ImGui.NET.targets'))" />
<Error Condition="!Exists('..\packages\Veldrid.SDL2.4.7.0\build\net40\Veldrid.SDL2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Veldrid.SDL2.4.7.0\build\net40\Veldrid.SDL2.targets'))" />
</Target>
<Import Project="..\packages\Veldrid.SDL2.4.7.0\build\net40\Veldrid.SDL2.targets" Condition="Exists('..\packages\Veldrid.SDL2.4.7.0\build\net40\Veldrid.SDL2.targets')" />
</Project>

@ -1,470 +0,0 @@
// <copyright file="HookController.cs" company="Zaafar Ahmed">
// Copyright (c) Zaafar Ahmed. All rights reserved.
// </copyright>
namespace ClickableTransparentOverlay
{
using System;
using System.Collections.Generic;
using System.Numerics;
using System.Windows.Forms;
using Gma.System.MouseKeyHook;
using ImGuiNET;
/// <summary>
/// This class Hooks the Global Window Keyboard/Mouse events
/// and pass them into the ImGui Overlay.
///
/// NOTE: This class might miss/skip a Keyboard/Mouse event
/// if ImGui render function takes a lot of time. Report on GitHub
/// if that happens.
/// </summary>
public class HookController
{
private readonly Queue<HookControllerMessage> messages;
private IKeyboardMouseEvents myHook;
private bool enable;
private int windowX;
private int windowY;
/// <summary>
/// Initializes a new instance of the <see cref="HookController"/> class.
/// </summary>
/// <param name="x">
/// Transparent SDL2Window top left corner X axis.
/// </param>
/// <param name="y">
/// Transparent SDL2Window top left corner Y axis.
/// </param>
public HookController(int x, int y)
{
this.messages = new Queue<HookControllerMessage>();
this.windowX = x;
this.windowY = y;
this.enable = true;
this.myHook = Hook.GlobalEvents();
}
private enum HookControllerMessageType
{
MouseUpDown,
MouseMove,
MouseWheel,
KeyUp,
KeyDown,
KeyPress,
}
/// <summary>
/// Enable this class functionality ( only call it once ).
/// </summary>
public void EnableHooks()
{
this.myHook.KeyDown += this.HookKeyDown;
this.myHook.KeyUp += this.HookKeyUp;
this.myHook.KeyPress += this.HookKeyPress;
this.myHook.MouseDownExt += this.HookMouseDownExt;
this.myHook.MouseMove += this.HookMouseMove;
this.myHook.MouseUpExt += this.HookMouseUpExt;
this.myHook.MouseWheelExt += this.HookMouseWheelExt;
}
/// <summary>
/// Update transparent SDL2Window top left position.
/// </summary>
/// <param name="x">
/// X axis of the SDL2Window top left corner.
/// </param>
/// <param name="y">
/// Y axis of the SDL2Window top left corner.
/// </param>
public void UpdateWindowPosition(int x, int y)
{
this.windowX = x;
this.windowY = y;
}
/// <summary>
/// Pause the hooks.
/// </summary>
public void PauseHooks()
{
this.enable = false;
}
/// <summary>
/// Resume the hooks.
/// </summary>
public void ResumeHooks()
{
this.enable = true;
}
/// <summary>
/// Dispose the resources acquired by this class.
/// </summary>
public void Dispose()
{
this.myHook.KeyDown -= this.HookKeyDown;
this.myHook.KeyUp -= this.HookKeyUp;
this.myHook.KeyPress -= this.HookKeyPress;
this.myHook.MouseDownExt -= this.HookMouseDownExt;
this.myHook.MouseMove -= this.HookMouseMove;
this.myHook.MouseUpExt -= this.HookMouseUpExt;
this.myHook.MouseWheelExt -= this.HookMouseWheelExt;
this.myHook.Dispose();
this.messages.Clear();
}
/// <summary>
/// Consumes all (max limit 10 to avoid infinite loop) the
/// keyboard/mouse messages from the message queue.
/// </summary>
public void PopMessages()
{
int counter = 0;
int maxCounter = 20;
while (counter < maxCounter && this.messages.Count > 0)
{
var message = this.messages.Dequeue();
try
{
switch (message.Type)
{
case HookControllerMessageType.MouseUpDown:
this.ProcessMouseUpDown((MouseEventExtArgs)message.E, message.MiscArg, true);
break;
case HookControllerMessageType.MouseMove:
this.ProcessMouseMove((MouseEventArgs)message.E, true);
break;
case HookControllerMessageType.MouseWheel:
this.ProcessMouseWheel((MouseEventExtArgs)message.E, true);
break;
case HookControllerMessageType.KeyUp:
this.ProcessKeyUp((KeyEventArgs)message.E, true);
break;
case HookControllerMessageType.KeyDown:
this.ProcessKeyDown((KeyEventArgs)message.E, true);
break;
case HookControllerMessageType.KeyPress:
this.ProcessKeyPress((KeyPressEventArgs)message.E, true);
break;
default:
break;
}
}
catch (Exception e)
{
Console.WriteLine("Warning: Caught an exception while handling keyboard/mouse inputs." +
"Report to the GitHub repository if this effects your work & it's reproduceable.");
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
counter++;
}
}
/// <summary>
/// Push the keyboard/mouse message to the message queue.
/// </summary>
/// <param name="type">
/// Message Type.
/// </param>
/// <param name="e">
/// Message details.
/// </param>
/// <param name="miscArg">
/// Only Mouse Up/Down hook uses this param to pass isDownEvent param.
/// </param>
private void PushMessage(HookControllerMessageType type, EventArgs e, bool miscArg = false)
{
var message = new HookControllerMessage()
{
Type = type,
E = e,
MiscArg = miscArg,
};
this.messages.Enqueue(message);
}
private void ProcessMouseUpDown(MouseEventExtArgs e, bool isDownEvent, bool shouldSendToImGui)
{
ImGuiIOPtr io = ImGui.GetIO();
if (shouldSendToImGui)
{
switch (e.Button)
{
case MouseButtons.Left:
io.MouseDown[0] = isDownEvent;
break;
case MouseButtons.Right:
io.MouseDown[1] = isDownEvent;
break;
case MouseButtons.Middle:
io.MouseDown[2] = isDownEvent;
break;
case MouseButtons.XButton1:
io.MouseDown[3] = isDownEvent;
break;
case MouseButtons.XButton2:
io.MouseDown[4] = isDownEvent;
break;
case MouseButtons.None:
// TODO: Find out what does this None mean
break;
default:
// TODO: Make a Logger for the whole Overlay
break;
}
}
else
{
this.PushMessage(HookControllerMessageType.MouseUpDown, e, isDownEvent);
}
if (io.WantCaptureMouse)
{
e.Handled = true;
}
}
private void ProcessMouseMove(MouseEventArgs e, bool shouldSendToImGui)
{
if (shouldSendToImGui)
{
ImGuiIOPtr io = ImGui.GetIO();
io.MousePos = new Vector2(e.X - this.windowX, e.Y - this.windowY);
// TODO: Show ImGUI Cursor/Hide ImGui Cursor
// ImGui.GetIO().MouseDrawCursor = true;
// Window32 API ShowCursor(false)
}
else
{
this.PushMessage(HookControllerMessageType.MouseMove, e);
}
}
private void ProcessMouseWheel(MouseEventExtArgs e, bool shouldSendToImGui)
{
ImGuiIOPtr io = ImGui.GetIO();
if (io.WantCaptureMouse)
{
if (shouldSendToImGui)
{
io.MouseWheel = e.Delta / SystemInformation.MouseWheelScrollDelta;
}
else
{
this.PushMessage(HookControllerMessageType.MouseWheel, e);
}
e.Handled = true;
}
}
private void ProcessKeyUp(KeyEventArgs e, bool shouldSendToImGui)
{
if (shouldSendToImGui)
{
var io = ImGui.GetIO();
io.KeysDown[e.KeyValue] = false;
switch (e.KeyCode)
{
case Keys.LWin:
case Keys.RWin:
io.KeySuper = false;
break;
case Keys.LControlKey:
case Keys.RControlKey:
io.KeyCtrl = false;
break;
case Keys.LMenu:
case Keys.RMenu:
io.KeyAlt = false;
break;
case Keys.LShiftKey:
case Keys.RShiftKey:
io.KeyShift = false;
break;
default:
break;
}
}
else
{
this.PushMessage(HookControllerMessageType.KeyUp, e);
}
}
private void ProcessKeyDown(KeyEventArgs e, bool shouldSendToImGui)
{
var io = ImGui.GetIO();
if (io.WantCaptureKeyboard)
{
if (shouldSendToImGui)
{
io.KeysDown[e.KeyValue] = true;
}
else
{
this.PushMessage(HookControllerMessageType.KeyDown, e);
}
switch (e.KeyCode)
{
case Keys.LWin:
case Keys.RWin:
if (shouldSendToImGui)
{
io.KeySuper = true;
}
break;
case Keys.LControlKey:
case Keys.RControlKey:
if (shouldSendToImGui)
{
io.KeyCtrl = true;
}
e.Handled = true;
break;
case Keys.LMenu: // LAlt is LMenu
case Keys.RMenu: // RAlt is RMenu
if (shouldSendToImGui)
{
io.KeyAlt = true;
}
break;
case Keys.LShiftKey:
case Keys.RShiftKey:
if (shouldSendToImGui)
{
io.KeyShift = true;
}
break;
default:
// Ignoring ALT key so we can do ALT+TAB or ALT+F4 etc.
// Not sure if ImGUI needs to use ALT+XXX key for anything.
// Ignoring Capital/NumLock key so Windows can use it.
// Ignoring Win/Super key so we can do Win+D or other stuff.
// Create a new issue on the repo if I miss any important key.
if (!io.KeyAlt && e.KeyCode != Keys.Capital && e.KeyCode != Keys.NumLock && !io.KeySuper &&
e.KeyCode != Keys.PrintScreen && e.KeyCode != Keys.Print)
{
e.Handled = true;
}
break;
}
}
}
private void ProcessKeyPress(KeyPressEventArgs e, bool shouldSendToImGui)
{
var io = ImGui.GetIO();
// Ignoring Win/Super key so we can do Win+D or other stuff
// Ignoring ALT key so we can do ALT+TAB or ALT+F4 etc.
// Not sure if ImGUI needs to use ALT+XXX or Super+XXX key for anything.
if (io.KeySuper || io.KeyAlt)
{
return;
}
if (io.WantTextInput || io.WantCaptureKeyboard)
{
if (shouldSendToImGui)
{
io.AddInputCharacter(e.KeyChar);
}
else
{
this.PushMessage(HookControllerMessageType.KeyPress, e);
}
e.Handled = true;
}
}
private void HookMouseUpExt(object sender, MouseEventExtArgs e)
{
if (this.enable)
{
this.ProcessMouseUpDown(e, false, false);
}
}
private void HookMouseDownExt(object sender, MouseEventExtArgs e)
{
if (this.enable)
{
this.ProcessMouseUpDown(e, true, false);
}
}
private void HookMouseMove(object sender, MouseEventArgs e)
{
if (!this.enable)
{
return;
}
this.ProcessMouseMove(e, false);
}
private void HookMouseWheelExt(object sender, MouseEventExtArgs e)
{
if (!this.enable)
{
return;
}
this.ProcessMouseWheel(e, false);
}
private void HookKeyUp(object sender, KeyEventArgs e)
{
this.ProcessKeyUp(e, true);
}
private void HookKeyDown(object sender, KeyEventArgs e)
{
if (!this.enable)
{
return;
}
this.ProcessKeyDown(e, true);
}
private void HookKeyPress(object sender, KeyPressEventArgs e)
{
if (!this.enable)
{
return;
}
this.ProcessKeyPress(e, false);
}
private struct HookControllerMessage
{
public HookControllerMessageType Type { get; set; }
public EventArgs E { get; set; }
public bool MiscArg { get; set; }
}
}
}

@ -1,151 +1,108 @@
// <auto-generated />
using System;
using System.Collections.Generic;
using System.Numerics;
using System.Reflection;
using System.IO;
using Veldrid;
using System.Runtime.CompilerServices;
using ImGuiNET;
namespace ClickableTransparentOverlay
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using ImGuiNET;
using NativeLibraryLoader;
using Veldrid;
/// <summary>
/// A modified version of ImGui.NET.SampleProgram's ImGuiController.
/// A modified version of Veldrid.ImGui's ImGuiRenderer.
/// Manages input for ImGui and handles rendering ImGui's DrawLists with Veldrid.
/// </summary>
public sealed class ImGuiController : IDisposable
public class ImGuiController : IDisposable
{
#pragma warning disable CS0169 // Force Copy this DLL
private readonly DefaultPathResolver useless;
#pragma warning restore CS0169
private GraphicsDevice _gd;
private bool _frameBegun;
private readonly IntPtr fontAtlasID = (IntPtr)1;
// Veldrid objects
private DeviceBuffer _vertexBuffer;
private DeviceBuffer _indexBuffer;
private DeviceBuffer _projMatrixBuffer;
private Texture _fontTexture;
private TextureView _fontTextureView;
private Shader _vertexShader;
private Shader _fragmentShader;
private ResourceLayout _layout;
private ResourceLayout _textureLayout;
private Pipeline _pipeline;
private ResourceSet _mainResourceSet;
private ResourceSet _fontTextureResourceSet;
private readonly IntPtr _fontAtlasID = (IntPtr)1;
private bool _controlDown;
private bool _shiftDown;
private bool _altDown;
private bool _winKeyDown;
private int _windowWidth;
private int _windowHeight;
private Vector2 _scaleFactor = Vector2.One;
// Image trackers
private readonly Dictionary<TextureView, ResourceSetInfo> setsByView
private readonly Dictionary<TextureView, ResourceSetInfo> _setsByView
= new Dictionary<TextureView, ResourceSetInfo>();
private readonly Dictionary<Texture, TextureView> autoViewsByTexture
private readonly Dictionary<Texture, TextureView> _autoViewsByTexture
= new Dictionary<Texture, TextureView>();
private readonly Dictionary<IntPtr, ResourceSetInfo> viewsById
= new Dictionary<IntPtr, ResourceSetInfo>();
private readonly List<IDisposable> ownedResources
= new List<IDisposable>();
private int lastAssignedID = 100;
private GraphicsDevice gd;
private bool frameBegun;
// Veldrid objects
private DeviceBuffer vertexBuffer;
private DeviceBuffer indexBuffer;
private DeviceBuffer projMatrixBuffer;
private Texture fontTexture;
private TextureView fontTextureView;
private Shader vertexShader;
private Shader fragmentShader;
private ResourceLayout layout;
private ResourceLayout textureLayout;
private Pipeline pipeline;
private ResourceSet mainResourceSet;
private ResourceSet fontTextureResourceSet;
private int windowWidth;
private int windowHeight;
private Vector2 scaleFactor = Vector2.One;
private readonly Dictionary<IntPtr, ResourceSetInfo> _viewsById = new Dictionary<IntPtr, ResourceSetInfo>();
private readonly List<IDisposable> _ownedResources = new List<IDisposable>();
private int _lastAssignedID = 100;
/// <summary>
/// Initializes a new instance of the <see cref="ImGuiController"/> class.
/// Constructs a new ImGuiController.
/// </summary>
/// <param name="gd">
/// Graphic Device
/// </param>
/// <param name="outputDescription">
/// Output Description
/// </param>
/// <param name="width">
/// SDL2Window Window width
/// </param>
/// <param name="height">
/// SDL2Window Window height
/// </param>
/// <param name="fps">
/// desired FPS of the ImGui Overlay
/// </param>
public ImGuiController(GraphicsDevice gd, OutputDescription outputDescription, int width, int height, int fps)
public ImGuiController(GraphicsDevice gd, OutputDescription outputDescription, int width, int height)
{
this.gd = gd;
this.windowWidth = width;
this.windowHeight = height;
_gd = gd;
_windowWidth = width;
_windowHeight = height;
IntPtr context = ImGui.CreateContext();
ImGui.SetCurrentContext(context);
ImGui.GetIO().Fonts.AddFontDefault();
this.CreateDeviceResources(gd, outputDescription);
CreateDeviceResources(gd, outputDescription);
SetKeyMappings();
this.SetPerFrameImGuiData(1f / fps);
SetPerFrameImGuiData(1f / 60f);
ImGui.NewFrame();
this.frameBegun = true;
_frameBegun = true;
}
/// <summary>
/// Updates the ImGui about the SDL2Window Size
/// </summary>
/// <param name="width">
/// Width of the SDL2Window
/// </param>
/// <param name="height">
/// Height of the SDL2Window
/// </param>
public void WindowResized(int width, int height)
{
this.windowWidth = width;
this.windowHeight = height;
_windowWidth = width;
_windowHeight = height;
}
/// <summary>
/// Disposes the resources acquired by the ImGuiController class.
/// </summary>
public void DestroyDeviceObjects()
{
this.Dispose();
Dispose();
}
/// <summary>
/// Initializes different resources for ImGui Controller class.
/// </summary>
/// <param name="gd">
/// Graphic Device
/// </param>
/// <param name="outputDescription">
/// Output Description
/// </param>
public void CreateDeviceResources(GraphicsDevice gd, OutputDescription outputDescription)
{
this.gd = gd;
_gd = gd;
ResourceFactory factory = gd.ResourceFactory;
this.vertexBuffer = factory.CreateBuffer(new BufferDescription(10000, BufferUsage.VertexBuffer | BufferUsage.Dynamic));
this.vertexBuffer.Name = "ImGui.NET Vertex Buffer";
this.indexBuffer = factory.CreateBuffer(new BufferDescription(2000, BufferUsage.IndexBuffer | BufferUsage.Dynamic));
this.indexBuffer.Name = "ImGui.NET Index Buffer";
this.RecreateFontDeviceTexture(gd);
this.projMatrixBuffer = factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic));
this.projMatrixBuffer.Name = "ImGui.NET Projection Buffer";
byte[] vertexShaderBytes = this.LoadEmbeddedShaderCode(gd.ResourceFactory, "imgui-vertex", ShaderStages.Vertex);
byte[] fragmentShaderBytes = this.LoadEmbeddedShaderCode(gd.ResourceFactory, "imgui-frag", ShaderStages.Fragment);
this.vertexShader = factory.CreateShader(new ShaderDescription(ShaderStages.Vertex, vertexShaderBytes, "VS"));
this.fragmentShader = factory.CreateShader(new ShaderDescription(ShaderStages.Fragment, fragmentShaderBytes, "FS"));
_vertexBuffer = factory.CreateBuffer(new BufferDescription(10000, BufferUsage.VertexBuffer | BufferUsage.Dynamic));
_vertexBuffer.Name = "ImGui.NET Vertex Buffer";
_indexBuffer = factory.CreateBuffer(new BufferDescription(2000, BufferUsage.IndexBuffer | BufferUsage.Dynamic));
_indexBuffer.Name = "ImGui.NET Index Buffer";
RecreateFontDeviceTexture(gd);
_projMatrixBuffer = factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic));
_projMatrixBuffer.Name = "ImGui.NET Projection Buffer";
byte[] vertexShaderBytes = LoadEmbeddedShaderCode(gd.ResourceFactory, "imgui-vertex", ShaderStages.Vertex);
byte[] fragmentShaderBytes = LoadEmbeddedShaderCode(gd.ResourceFactory, "imgui-frag", ShaderStages.Fragment);
_vertexShader = factory.CreateShader(new ShaderDescription(
ShaderStages.Vertex, vertexShaderBytes, _gd.BackendType == GraphicsBackend.Vulkan ? "main" : "VS"));
_fragmentShader = factory.CreateShader(new ShaderDescription(
ShaderStages.Fragment, fragmentShaderBytes, _gd.BackendType == GraphicsBackend.Vulkan ? "main" : "FS"));
VertexLayoutDescription[] vertexLayouts = new VertexLayoutDescription[]
{
@ -155,10 +112,10 @@ namespace ClickableTransparentOverlay
new VertexElementDescription("in_color", VertexElementSemantic.Color, VertexElementFormat.Byte4_Norm))
};
this.layout = factory.CreateResourceLayout(new ResourceLayoutDescription(
_layout = factory.CreateResourceLayout(new ResourceLayoutDescription(
new ResourceLayoutElementDescription("ProjectionMatrixBuffer", ResourceKind.UniformBuffer, ShaderStages.Vertex),
new ResourceLayoutElementDescription("MainSampler", ResourceKind.Sampler, ShaderStages.Fragment)));
this.textureLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
_textureLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
new ResourceLayoutElementDescription("MainTexture", ResourceKind.TextureReadOnly, ShaderStages.Fragment)));
GraphicsPipelineDescription pd = new GraphicsPipelineDescription(
@ -166,85 +123,96 @@ namespace ClickableTransparentOverlay
new DepthStencilStateDescription(false, false, ComparisonKind.Always),
new RasterizerStateDescription(FaceCullMode.None, PolygonFillMode.Solid, FrontFace.Clockwise, false, true),
PrimitiveTopology.TriangleList,
new ShaderSetDescription(vertexLayouts, new[] { this.vertexShader, this.fragmentShader }),
new ResourceLayout[] { this.layout, this.textureLayout },
outputDescription);
this.pipeline = factory.CreateGraphicsPipeline(ref pd);
new ShaderSetDescription(vertexLayouts, new[] { _vertexShader, _fragmentShader }),
new ResourceLayout[] { _layout, _textureLayout },
outputDescription,
ResourceBindingModel.Default);
_pipeline = factory.CreateGraphicsPipeline(ref pd);
this.mainResourceSet = factory.CreateResourceSet(new ResourceSetDescription(
this.layout, this.projMatrixBuffer, gd.PointSampler));
_mainResourceSet = factory.CreateResourceSet(new ResourceSetDescription(_layout,
_projMatrixBuffer,
gd.PointSampler));
this.fontTextureResourceSet = factory.CreateResourceSet(
new ResourceSetDescription(this.textureLayout, this.fontTextureView));
_fontTextureResourceSet = factory.CreateResourceSet(new ResourceSetDescription(_textureLayout, _fontTextureView));
}
/// <summary>
/// Gets or creates a handle for a texture to be drawn with ImGui.
/// Pass the returned handle to Image() or ImageButton().
/// E.G. Pass the returned handle to Image() or ImageButton().
/// </summary>
/// <param name="factory">
/// Resource Factory
/// </param>
/// <param name="textureView">
/// Texture View
/// </param>
/// <returns>
/// Creates ImGui Binding
/// </returns>
public IntPtr GetOrCreateImGuiBinding(ResourceFactory factory, TextureView textureView)
{
if (!this.setsByView.TryGetValue(textureView, out ResourceSetInfo rsi))
if (!_setsByView.TryGetValue(textureView, out ResourceSetInfo rsi))
{
ResourceSet resourceSet = factory.CreateResourceSet(
new ResourceSetDescription(this.textureLayout, textureView));
rsi = new ResourceSetInfo(this.GetNextImGuiBindingID(), resourceSet);
ResourceSet resourceSet = factory.CreateResourceSet(new ResourceSetDescription(_textureLayout, textureView));
rsi = new ResourceSetInfo(GetNextImGuiBindingID(), resourceSet);
this.setsByView.Add(textureView, rsi);
this.viewsById.Add(rsi.ImGuiBinding, rsi);
this.ownedResources.Add(resourceSet);
_setsByView.Add(textureView, rsi);
_viewsById.Add(rsi.ImGuiBinding, rsi);
_ownedResources.Add(resourceSet);
}
return rsi.ImGuiBinding;
}
/// <summary>
/// Removes the texture from the resources.
/// </summary>
/// <param name="textureView">texture to remove</param>
public void RemoveImGuiBinding(TextureView textureView)
{
if (_setsByView.TryGetValue(textureView, out ResourceSetInfo rsi))
{
_setsByView.Remove(textureView);
_viewsById.Remove(rsi.ImGuiBinding);
_ownedResources.Remove(rsi.ResourceSet);
rsi.ResourceSet.Dispose();
}
}
/// <summary>
/// Removes the texture from the resources.
/// </summary>
/// <param name="texture">texture to remove</param>
public void RemoveImGuiBinding(Texture texture)
{
if (_autoViewsByTexture.TryGetValue(texture, out TextureView textureView))
{
_autoViewsByTexture.Remove(texture);
_ownedResources.Remove(textureView);
textureView.Dispose();
RemoveImGuiBinding(textureView);
}
}
private IntPtr GetNextImGuiBindingID()
{
int newID = _lastAssignedID++;
return (IntPtr)newID;
}
/// <summary>
/// Gets or creates a handle for a texture to be drawn with ImGui.
/// Pass the returned handle to Image() or ImageButton().
/// </summary>
/// <param name="factory">
/// Resource Factory
/// </param>
/// <param name="texture">
/// Texture information
/// </param>
/// <returns>
/// Pointer to the resource
/// </returns>
public IntPtr GetOrCreateImGuiBinding(ResourceFactory factory, Texture texture)
{
if (!this.autoViewsByTexture.TryGetValue(texture, out TextureView textureView))
if (!_autoViewsByTexture.TryGetValue(texture, out TextureView textureView))
{
textureView = factory.CreateTextureView(texture);
this.autoViewsByTexture.Add(texture, textureView);
this.ownedResources.Add(textureView);
_autoViewsByTexture.Add(texture, textureView);
_ownedResources.Add(textureView);
}
return this.GetOrCreateImGuiBinding(factory, textureView);
return GetOrCreateImGuiBinding(factory, textureView);
}
/// <summary>
/// Retrieves the shader texture binding for the given helper handle.
/// </summary>
/// <param name="imGuiBinding">
/// ImGui Binding resource pointer.
/// </param>
/// <returns>
/// Resource
/// </returns>
public ResourceSet GetImageResourceSet(IntPtr imGuiBinding)
{
if (!this.viewsById.TryGetValue(imGuiBinding, out ResourceSetInfo tvi))
if (!_viewsById.TryGetValue(imGuiBinding, out ResourceSetInfo tvi))
{
throw new InvalidOperationException("No registered ImGui binding with id " + imGuiBinding.ToString());
}
@ -252,52 +220,71 @@ namespace ClickableTransparentOverlay
return tvi.ResourceSet;
}
/// <summary>
/// Clears the cache images.
/// </summary>
public void ClearCachedImageResources()
{
foreach (IDisposable resource in this.ownedResources)
foreach (IDisposable resource in _ownedResources)
{
resource.Dispose();
}
this.ownedResources.Clear();
this.setsByView.Clear();
this.viewsById.Clear();
this.autoViewsByTexture.Clear();
this.lastAssignedID = 100;
_ownedResources.Clear();
_setsByView.Clear();
_viewsById.Clear();
_autoViewsByTexture.Clear();
_lastAssignedID = 100;
}
private byte[] LoadEmbeddedShaderCode(ResourceFactory factory, string name, ShaderStages _)
{
switch (factory.BackendType)
{
case GraphicsBackend.Direct3D11:
{
string resourceName = name + ".hlsl.bytes";
return GetEmbeddedResourceBytes(resourceName);
}
default:
throw new NotImplementedException();
}
}
private byte[] GetEmbeddedResourceBytes(string resourceName)
{
Assembly assembly = typeof(ImGuiController).Assembly;
using (Stream s = assembly.GetManifestResourceStream(resourceName))
{
byte[] ret = new byte[s.Length];
s.Read(ret, 0, (int)s.Length);
return ret;
}
}
/// <summary>
/// Recreates the device texture used to render text.
/// </summary>
/// <param name="gd">
/// Graphic Device
/// </param>
public unsafe void RecreateFontDeviceTexture(GraphicsDevice gd)
public void RecreateFontDeviceTexture(GraphicsDevice gd)
{
ImGuiIOPtr io = ImGui.GetIO();
// Build
byte* pixels;
int width, height, bytesPerPixel;
io.Fonts.GetTexDataAsRGBA32(out pixels, out width, out height, out bytesPerPixel);
io.Fonts.GetTexDataAsRGBA32(
out IntPtr pixels,
out int width,
out int height,
out int bytesPerPixel);
// Store our identifier
io.Fonts.SetTexID(this.fontAtlasID);
io.Fonts.SetTexID(_fontAtlasID);
this.fontTexture = gd.ResourceFactory.CreateTexture(TextureDescription.Texture2D(
_fontTexture = gd.ResourceFactory.CreateTexture(TextureDescription.Texture2D(
(uint)width,
(uint)height,
1,
1,
PixelFormat.R8_G8_B8_A8_UNorm,
TextureUsage.Sampled));
this.fontTexture.Name = "ImGui.NET Font Texture";
_fontTexture.Name = "ImGui.NET Font Texture";
gd.UpdateTexture(
this.fontTexture,
(IntPtr)pixels,
_fontTexture,
pixels,
(uint)(bytesPerPixel * width * height),
0,
0,
@ -307,7 +294,7 @@ namespace ClickableTransparentOverlay
1,
0,
0);
this.fontTextureView = gd.ResourceFactory.CreateTextureView(this.fontTexture);
_fontTextureView = gd.ResourceFactory.CreateTextureView(_fontTexture);
io.Fonts.ClearTexData();
}
@ -318,180 +305,150 @@ namespace ClickableTransparentOverlay
/// or index data has increased beyond the capacity of the existing buffers.
/// A <see cref="CommandList"/> is needed to submit drawing and resource update commands.
/// </summary>
/// <param name="gd">
/// Graphic Device
/// </param>
/// <param name="cl">
/// Command List
/// </param>
public void Render(GraphicsDevice gd, CommandList cl)
{
if (this.frameBegun)
if (_frameBegun)
{
this.frameBegun = false;
_frameBegun = false;
ImGui.Render();
this.RenderImDrawData(ImGui.GetDrawData(), gd, cl);
RenderImDrawData(ImGui.GetDrawData(), gd, cl);
}
}
/// <summary>
/// Initilizes a new frame
/// Updates ImGui input and IO configuration state.
/// </summary>
/// <param name="deltaSeconds">
/// FPS delay
/// </param>
public void InitlizeFrame(float deltaSeconds)
public void Update(float deltaSeconds, InputSnapshot snapshot, IntPtr handle)
{
if (this.frameBegun)
if (_frameBegun)
{
ImGui.Render();
}
this.SetPerFrameImGuiData(deltaSeconds);
SetPerFrameImGuiData(deltaSeconds);
UpdateImGuiInput(snapshot, handle);
this.frameBegun = true;
_frameBegun = true;
ImGui.NewFrame();
}
/// <summary>
/// Frees all graphics resources used by the renderer.
/// Sets per-frame data based on the associated window.
/// This is called by Update(float).
/// </summary>
public void Dispose()
private void SetPerFrameImGuiData(float deltaSeconds)
{
this.vertexBuffer.Dispose();
this.indexBuffer.Dispose();
this.projMatrixBuffer.Dispose();
this.fontTexture.Dispose();
this.fontTextureView.Dispose();
this.vertexShader.Dispose();
this.fragmentShader.Dispose();
this.layout.Dispose();
this.textureLayout.Dispose();
this.pipeline.Dispose();
this.mainResourceSet.Dispose();
this.fontTextureResourceSet.Dispose();
this.ClearCachedImageResources();
ImGuiIOPtr io = ImGui.GetIO();
io.DisplaySize = new Vector2(
_windowWidth / _scaleFactor.X,
_windowHeight / _scaleFactor.Y);
io.DisplayFramebufferScale = _scaleFactor;
io.DeltaTime = deltaSeconds; // DeltaTime is in seconds.
}
/// <summary>
/// Allows ImGui to identify the Keys
/// </summary>
private static void SetKeyMappings()
private void UpdateImGuiInput(InputSnapshot snapshot, IntPtr handle)
{
ImGuiIOPtr io = ImGui.GetIO();
io.KeyMap[(int)ImGuiKey.Tab] = (int)System.Windows.Forms.Keys.Tab;
io.KeyMap[(int)ImGuiKey.LeftArrow] = (int)System.Windows.Forms.Keys.Left;
io.KeyMap[(int)ImGuiKey.RightArrow] = (int)System.Windows.Forms.Keys.Right;
io.KeyMap[(int)ImGuiKey.UpArrow] = (int)System.Windows.Forms.Keys.Up;
io.KeyMap[(int)ImGuiKey.DownArrow] = (int)System.Windows.Forms.Keys.Down;
io.KeyMap[(int)ImGuiKey.PageUp] = (int)System.Windows.Forms.Keys.PageUp;
io.KeyMap[(int)ImGuiKey.PageDown] = (int)System.Windows.Forms.Keys.PageDown;
io.KeyMap[(int)ImGuiKey.Home] = (int)System.Windows.Forms.Keys.Home;
io.KeyMap[(int)ImGuiKey.End] = (int)System.Windows.Forms.Keys.End;
io.KeyMap[(int)ImGuiKey.Delete] = (int)System.Windows.Forms.Keys.Delete;
io.KeyMap[(int)ImGuiKey.Backspace] = (int)System.Windows.Forms.Keys.Back;
io.KeyMap[(int)ImGuiKey.Enter] = (int)System.Windows.Forms.Keys.Enter;
io.KeyMap[(int)ImGuiKey.Escape] = (int)System.Windows.Forms.Keys.Escape;
// io.KeyMap[(int)ImGuiKey.COUNT] = (int)System.Windows.Forms.Keys.un;
io.KeyMap[(int)ImGuiKey.Insert] = (int)System.Windows.Forms.Keys.Insert;
io.KeyMap[(int)ImGuiKey.Space] = (int)System.Windows.Forms.Keys.Space;
io.KeyMap[(int)ImGuiKey.A] = (int)System.Windows.Forms.Keys.A;
io.KeyMap[(int)ImGuiKey.C] = (int)System.Windows.Forms.Keys.C;
io.KeyMap[(int)ImGuiKey.V] = (int)System.Windows.Forms.Keys.V;
io.KeyMap[(int)ImGuiKey.X] = (int)System.Windows.Forms.Keys.X;
io.KeyMap[(int)ImGuiKey.Y] = (int)System.Windows.Forms.Keys.Y;
io.KeyMap[(int)ImGuiKey.Z] = (int)System.Windows.Forms.Keys.Z;
}
/// <summary>
/// Get the Next ImGui Binding ID.
/// </summary>
/// <returns>
/// ImGui next binding ID.
/// </returns>
private IntPtr GetNextImGuiBindingID()
{
int newID = this.lastAssignedID++;
return (IntPtr)newID;
}
// Determine if any of the mouse buttons were pressed during this snapshot period, even if they are no longer held.
bool leftPressed = false;
bool middlePressed = false;
bool rightPressed = false;
for (int i = 0; i < snapshot.MouseEvents.Count; i++)
{
MouseEvent me = snapshot.MouseEvents[i];
if (me.Down)
{
switch (me.MouseButton)
{
case MouseButton.Left:
leftPressed = true;
break;
case MouseButton.Middle:
middlePressed = true;
break;
case MouseButton.Right:
rightPressed = true;
break;
}
}
}
/// <summary>
/// Loading Shader Code
/// </summary>
/// <param name="factory">
/// Resource Factory
/// </param>
/// <param name="name">
/// Shader file name
/// </param>
/// <param name="stage">
/// Shader stage
/// </param>
/// <returns>
/// Returns shader byte code
/// </returns>
private byte[] LoadEmbeddedShaderCode(ResourceFactory factory, string name, ShaderStages stage)
{
switch (factory.BackendType)
io.MouseDown[0] = leftPressed || snapshot.IsMouseDown(MouseButton.Left);
io.MouseDown[1] = rightPressed || snapshot.IsMouseDown(MouseButton.Right);
io.MouseDown[2] = middlePressed || snapshot.IsMouseDown(MouseButton.Middle);
io.MousePos = NativeMethods.GetCursorPosition(handle);
io.MouseWheel = snapshot.WheelDelta;
IReadOnlyList<char> keyCharPresses = snapshot.KeyCharPresses;
for (int i = 0; i < keyCharPresses.Count; i++)
{
case GraphicsBackend.Direct3D11:
string resourceName = name + ".hlsl.bytes";
return this.GetEmbeddedResourceBytes(resourceName);
default:
throw new NotImplementedException();
char c = keyCharPresses[i];
io.AddInputCharacter(c);
}
}
/// <summary>
/// Get embedded resource file in bytes
/// </summary>
/// <param name="resourceName">
/// Name of the resource file
/// </param>
/// <returns>
/// Byte code of the resource file
/// </returns>
private byte[] GetEmbeddedResourceBytes(string resourceName)
{
Assembly assembly = typeof(ImGuiController).Assembly;
using (Stream s = assembly.GetManifestResourceStream(resourceName))
IReadOnlyList<KeyEvent> keyEvents = snapshot.KeyEvents;
for (int i = 0; i < keyEvents.Count; i++)
{
byte[] ret = new byte[s.Length];
s.Read(ret, 0, (int)s.Length);
return ret;
KeyEvent keyEvent = keyEvents[i];
io.KeysDown[(int)keyEvent.Key] = keyEvent.Down;
if (keyEvent.Key == Key.ControlLeft)
{
_controlDown = keyEvent.Down;
}
if (keyEvent.Key == Key.ShiftLeft)
{
_shiftDown = keyEvent.Down;
}
if (keyEvent.Key == Key.AltLeft)
{
_altDown = keyEvent.Down;
}
if (keyEvent.Key == Key.WinLeft)
{
_winKeyDown = keyEvent.Down;
}
}
io.KeyCtrl = _controlDown;
io.KeyAlt = _altDown;
io.KeyShift = _shiftDown;
io.KeySuper = _winKeyDown;
if (io.WantCaptureKeyboard || io.WantCaptureMouse)
{
NativeMethods.SetOverlayClickable(handle, true);
}
else
{
NativeMethods.SetOverlayClickable(handle, false);
}
}
/// <summary>
/// Sets per-frame data based on the associated window.
/// This is called by Update(float).
/// </summary>
/// <param name="deltaSeconds">
/// FPS delay
/// </param>
private void SetPerFrameImGuiData(float deltaSeconds)
private static void SetKeyMappings()
{
ImGuiIOPtr io = ImGui.GetIO();
io.DisplaySize = new Vector2(
this.windowWidth / this.scaleFactor.X,
this.windowHeight / this.scaleFactor.Y);
io.DisplayFramebufferScale = this.scaleFactor;
io.DeltaTime = deltaSeconds; // DeltaTime is in seconds.
io.KeyMap[(int)ImGuiKey.Tab] = (int)Key.Tab;
io.KeyMap[(int)ImGuiKey.LeftArrow] = (int)Key.Left;
io.KeyMap[(int)ImGuiKey.RightArrow] = (int)Key.Right;
io.KeyMap[(int)ImGuiKey.UpArrow] = (int)Key.Up;
io.KeyMap[(int)ImGuiKey.DownArrow] = (int)Key.Down;
io.KeyMap[(int)ImGuiKey.PageUp] = (int)Key.PageUp;
io.KeyMap[(int)ImGuiKey.PageDown] = (int)Key.PageDown;
io.KeyMap[(int)ImGuiKey.Home] = (int)Key.Home;
io.KeyMap[(int)ImGuiKey.End] = (int)Key.End;
io.KeyMap[(int)ImGuiKey.Delete] = (int)Key.Delete;
io.KeyMap[(int)ImGuiKey.Backspace] = (int)Key.BackSpace;
io.KeyMap[(int)ImGuiKey.Enter] = (int)Key.Enter;
io.KeyMap[(int)ImGuiKey.Escape] = (int)Key.Escape;
io.KeyMap[(int)ImGuiKey.A] = (int)Key.A;
io.KeyMap[(int)ImGuiKey.C] = (int)Key.C;
io.KeyMap[(int)ImGuiKey.V] = (int)Key.V;
io.KeyMap[(int)ImGuiKey.X] = (int)Key.X;
io.KeyMap[(int)ImGuiKey.Y] = (int)Key.Y;
io.KeyMap[(int)ImGuiKey.Z] = (int)Key.Z;
}
/// <summary>
/// Draw the ImGui graphic data
/// </summary>
/// <param name="draw_data">
/// ImGui data to draw
/// </param>
/// <param name="gd">
/// Graphic Device
/// </param>
/// <param name="cl">
/// Command List
/// </param>
private void RenderImDrawData(ImDrawDataPtr draw_data, GraphicsDevice gd, CommandList cl)
{
uint vertexOffsetInVertices = 0;
@ -503,19 +460,17 @@ namespace ClickableTransparentOverlay
}
uint totalVBSize = (uint)(draw_data.TotalVtxCount * Unsafe.SizeOf<ImDrawVert>());
if (totalVBSize > this.vertexBuffer.SizeInBytes)
if (totalVBSize > _vertexBuffer.SizeInBytes)
{
gd.DisposeWhenIdle(this.vertexBuffer);
this.vertexBuffer = gd.ResourceFactory.CreateBuffer(new BufferDescription(
(uint)(totalVBSize * 1.5f), BufferUsage.VertexBuffer | BufferUsage.Dynamic));
_vertexBuffer.Dispose();
_vertexBuffer = gd.ResourceFactory.CreateBuffer(new BufferDescription((uint)(totalVBSize * 1.5f), BufferUsage.VertexBuffer | BufferUsage.Dynamic));
}
uint totalIBSize = (uint)(draw_data.TotalIdxCount * sizeof(ushort));
if (totalIBSize > this.indexBuffer.SizeInBytes)
if (totalIBSize > _indexBuffer.SizeInBytes)
{
gd.DisposeWhenIdle(this.indexBuffer);
this.indexBuffer = gd.ResourceFactory.CreateBuffer(new BufferDescription(
(uint)(totalIBSize * 1.5f), BufferUsage.IndexBuffer | BufferUsage.Dynamic));
_indexBuffer.Dispose();
_indexBuffer = gd.ResourceFactory.CreateBuffer(new BufferDescription((uint)(totalIBSize * 1.5f), BufferUsage.IndexBuffer | BufferUsage.Dynamic));
}
for (int i = 0; i < draw_data.CmdListsCount; i++)
@ -523,13 +478,13 @@ namespace ClickableTransparentOverlay
ImDrawListPtr cmd_list = draw_data.CmdListsRange[i];
cl.UpdateBuffer(
this.vertexBuffer,
_vertexBuffer,
vertexOffsetInVertices * (uint)Unsafe.SizeOf<ImDrawVert>(),
cmd_list.VtxBuffer.Data,
(uint)(cmd_list.VtxBuffer.Size * Unsafe.SizeOf<ImDrawVert>()));
cl.UpdateBuffer(
this.indexBuffer,
_indexBuffer,
indexOffsetInElements * sizeof(ushort),
cmd_list.IdxBuffer.Data,
(uint)(cmd_list.IdxBuffer.Size * sizeof(ushort)));
@ -548,12 +503,12 @@ namespace ClickableTransparentOverlay
-1.0f,
1.0f);
this.gd.UpdateBuffer(this.projMatrixBuffer, 0, ref mvp);
_gd.UpdateBuffer(_projMatrixBuffer, 0, ref mvp);
cl.SetVertexBuffer(0, this.vertexBuffer);
cl.SetIndexBuffer(this.indexBuffer, IndexFormat.UInt16);
cl.SetPipeline(this.pipeline);
cl.SetGraphicsResourceSet(0, this.mainResourceSet);
cl.SetVertexBuffer(0, _vertexBuffer);
cl.SetIndexBuffer(_indexBuffer, IndexFormat.UInt16);
cl.SetPipeline(_pipeline);
cl.SetGraphicsResourceSet(0, _mainResourceSet);
draw_data.ScaleClipRects(io.DisplayFramebufferScale);
@ -574,15 +529,13 @@ namespace ClickableTransparentOverlay
{
if (pcmd.TextureId != IntPtr.Zero)
{
if (pcmd.TextureId == this.fontAtlasID)
if (pcmd.TextureId == _fontAtlasID)
{
cl.SetGraphicsResourceSet(
1, this.fontTextureResourceSet);
cl.SetGraphicsResourceSet(1, _fontTextureResourceSet);
}
else
{
cl.SetGraphicsResourceSet(
1, this.GetImageResourceSet(pcmd.TextureId));
cl.SetGraphicsResourceSet(1, GetImageResourceSet(pcmd.TextureId));
}
}
@ -598,14 +551,30 @@ namespace ClickableTransparentOverlay
idx_offset += (int)pcmd.ElemCount;
}
vtx_offset += cmd_list.VtxBuffer.Size;
}
}
/// <summary>
/// ResourceSetInfo
/// Frees all graphics resources used by the renderer.
/// </summary>
public void Dispose()
{
_vertexBuffer.Dispose();
_indexBuffer.Dispose();
_projMatrixBuffer.Dispose();
_fontTexture.Dispose();
_fontTextureView.Dispose();
_vertexShader.Dispose();
_fragmentShader.Dispose();
_layout.Dispose();
_textureLayout.Dispose();
_pipeline.Dispose();
_mainResourceSet.Dispose();
ClearCachedImageResources();
_fontTextureResourceSet.Dispose();
}
private struct ResourceSetInfo
{
public readonly IntPtr ImGuiBinding;
@ -613,8 +582,8 @@ namespace ClickableTransparentOverlay
public ResourceSetInfo(IntPtr imGuiBinding, ResourceSet resourceSet)
{
this.ImGuiBinding = imGuiBinding;
this.ResourceSet = resourceSet;
ImGuiBinding = imGuiBinding;
ResourceSet = resourceSet;
}
}
}

@ -1,13 +1,10 @@
// <copyright file="NativeMethods.cs" company="Zaafar Ahmed">
// Copyright (c) Zaafar Ahmed. All rights reserved.
// </copyright>
using System;
using System.Drawing;
using System.Numerics;
using System.Runtime.InteropServices;
namespace ClickableTransparentOverlay
{
using System;
using System.Drawing;
using System.Runtime.InteropServices;
/// <summary>
/// This class allow user to access Win32 API functions.
/// </summary>
@ -20,39 +17,107 @@ namespace ClickableTransparentOverlay
private const int SW_HIDE = 0x00;
private const int SW_SHOW = 0x05;
public static bool IsClickable = true;
private static IntPtr GWL_EXSTYLE_CLICKABLE = IntPtr.Zero;
private static IntPtr GWL_EXSTYLE_NOT_CLICKABLE = IntPtr.Zero;
private const int KEY_PRESSED = 0x8000;
/// <summary>
/// Allows the SDL2Window to become transparent.
/// </summary>
/// <param name="handle">
/// Veldrid window handle in IntPtr format.
/// </param>
public static void EnableTransparent(IntPtr handle)
public static void InitTransparency(IntPtr handle)
{
IntPtr windowLong = GetWindowLongPtr(handle, GWL_EXSTYLE);
windowLong = new IntPtr(windowLong.ToInt64() | WS_EX_LAYERED | WS_EX_TRANSPARENT);
SetWindowLongPtr(handle, GWL_EXSTYLE, windowLong);
GWL_EXSTYLE_CLICKABLE = GetWindowLongPtr(handle, GWL_EXSTYLE);
GWL_EXSTYLE_NOT_CLICKABLE = new IntPtr(
GWL_EXSTYLE_CLICKABLE.ToInt64() | WS_EX_LAYERED | WS_EX_TRANSPARENT);
Margins margins = Margins.FromRectangle(new Rectangle(-1, -1, -1, -1));
DwmExtendFrameIntoClientArea(handle, ref margins);
}
/// <summary>
/// Allows hiding the console window.
/// Enables (clickable) / Disables (not clickable) the SDL2Window keyboard/mouse inputs.
/// NOTE: This function depends on InitTransparency being called when the SDL2Winhdow was created.
/// </summary>
/// <param name="handle">Veldrid window handle in IntPtr format.</param>
/// <param name="WantClickable">Set to true if you want to make the window clickable otherwise false.</param>
public static void SetOverlayClickable(IntPtr handle, bool WantClickable)
{
if (!IsClickable && WantClickable)
{
SetWindowLongPtr(handle, GWL_EXSTYLE, GWL_EXSTYLE_CLICKABLE);
SetFocus(handle);
IsClickable = true;
}
else if(IsClickable && !WantClickable)
{
SetWindowLongPtr(handle, GWL_EXSTYLE, GWL_EXSTYLE_NOT_CLICKABLE);
IsClickable = false;
}
}
/// <summary>
/// Allows showing/hiding the console window.
/// </summary>
public static void SetConsoleWindow(bool visiable)
{
if (visiable)
{
var handle = GetConsoleWindow();
ShowWindow(handle, SW_SHOW);
}
else
{
var handle = GetConsoleWindow();
ShowWindow(handle, SW_HIDE);
}
}
/// <summary>
/// Returns the current mouse position w.r.t the window in Vector2 format.
/// Also, returns Zero in case of any errors.
/// </summary>
public static void HideConsoleWindow()
/// <param name="hWnd"></param>
/// <returns></returns>
public static Vector2 GetCursorPosition(IntPtr hWnd)
{
var handle = GetConsoleWindow();
ShowWindow(handle, SW_HIDE);
if (GetCursorPos(out var lpPoint))
{
ScreenToClient(hWnd, ref lpPoint);
return lpPoint;
}
return Vector2.Zero;
}
/// <summary>
/// Allows displaying the console window.
/// Returns true if the key is pressed.
/// For keycode information visit: https://www.pinvoke.net/default.aspx/user32.getkeystate
/// </summary>
public static void ShowConsoleWindow()
/// <param name="nVirtKey">key to look for.</param>
/// <returns>weather the key is pressed or not.</returns>
public static bool isKeyPressed(int nVirtKey)
{
var handle = GetConsoleWindow();
ShowWindow(handle, SW_SHOW);
return Convert.ToBoolean(GetKeyState(nVirtKey) & KEY_PRESSED);
}
[DllImport("USER32.dll")]
static extern short GetKeyState(int nVirtKey);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetCursorPos(out POINT lpPoint);
[DllImport("user32.dll")]
static extern bool ScreenToClient(IntPtr hWnd, ref POINT lpPoint);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetFocus(IntPtr hWnd);
[DllImport("dwmapi.dll")]
private static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref Margins pMarInset);
@ -88,5 +153,28 @@ namespace ClickableTransparentOverlay
return margins;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
}
public static implicit operator Point(POINT p)
{
return new Point(p.X, p.Y);
}
public static implicit operator Vector2(POINT p)
{
return new Vector2(p.X, p.Y);
}
}
}
}

@ -1,42 +1,28 @@
// <copyright file="Overlay.cs" company="Zaafar Ahmed">
// Copyright (c) Zaafar Ahmed. All rights reserved.
// </copyright>
using System;
using System.Collections.Generic;
using System.Numerics;
using System.Threading;
using Coroutine;
using Veldrid;
using Veldrid.ImageSharp;
using Veldrid.Sdl2;
using Veldrid.StartupUtilities;
namespace ClickableTransparentOverlay
{
using System;
using System.Collections.Generic;
using System.Numerics;
using System.Threading;
using System.Windows.Forms;
using Veldrid;
using Veldrid.ImageSharp;
using Veldrid.Sdl2;
using Veldrid.StartupUtilities;
// TODO: Implement overlay info, warn, error logger.
/// <summary>
/// A class to create clickable transparent overlay.
/// </summary>
public class Overlay
public static class Overlay
{
private static Sdl2Window window;
private static GraphicsDevice graphicsDevice;
private static CommandList commandList;
private static ImGuiController imController;
private static HookController hookController;
private static Thread uiThread;
// UI State
private static Vector4 clearColor;
private static int myFps;
private static bool isClosed;
private static Dictionary<string, Texture> loadedImages;
// For Resizing SDL2Window
private static Vector2 futurePos;
private static Vector2 futureSize;
private static bool requireResize;
private static bool debugMode;
private readonly static Sdl2Window window;
private readonly static GraphicsDevice graphicsDevice;
private readonly static CommandList commandList;
private readonly static ImGuiController imController;
private readonly static Vector4 clearColor;
private readonly static Dictionary<string, Texture> loadedImages;
private static bool terminal = true;
/// <summary>
/// Initializes a new instance of the <see cref="Overlay"/> class.
@ -59,149 +45,139 @@ namespace ClickableTransparentOverlay
/// <param name="debug">
/// In this mode, overlay will not hide the Console.
/// </param>
public Overlay(int x, int y, int width, int height, int fps, bool debug)
static Overlay()
{
loadedImages = new Dictionary<string, Texture>();
clearColor = new Vector4(0.00f, 0.00f, 0.00f, 0.00f);
myFps = fps;
isClosed = false;
debugMode = debug;
// Stuff related to (thread safe) resizing of SDL2Window
requireResize = false;
futureSize = Vector2.Zero;
futurePos = Vector2.Zero;
window = new Sdl2Window("Overlay", x, y, width, height, SDL_WindowFlags.Borderless | SDL_WindowFlags.AlwaysOnTop | SDL_WindowFlags.SkipTaskbar, false);
graphicsDevice = VeldridStartup.CreateGraphicsDevice(window, new GraphicsDeviceOptions(true, null, true), GraphicsBackend.Direct3D11);
// graphicsDevice = VeldridStartup.CreateDefaultD3D11GraphicsDevice(new GraphicsDeviceOptions(true, null, true), window);
NativeMethods.EnableTransparent(window.Handle);
loadedImages = new Dictionary<string, Texture>();
window = new Sdl2Window(
"Overlay",
0,
0,
2560,
1440,
SDL_WindowFlags.Borderless |
SDL_WindowFlags.AlwaysOnTop |
SDL_WindowFlags.SkipTaskbar,
false);
graphicsDevice = VeldridStartup.CreateDefaultD3D11GraphicsDevice(
new GraphicsDeviceOptions(false, null, true),
window);
commandList = graphicsDevice.ResourceFactory.CreateCommandList();
imController = new ImGuiController(
graphicsDevice,
graphicsDevice.MainSwapchain.Framebuffer.OutputDescription,
window.Width,
window.Height);
window.Resized += () =>
{
graphicsDevice.MainSwapchain.Resize((uint)window.Width, (uint)window.Height);
imController.WindowResized(window.Width, window.Height);
futureSize = Vector2.Zero;
futurePos = Vector2.Zero;
requireResize = false;
};
window.Closed += () =>
{
isClosed = true;
};
commandList = graphicsDevice.ResourceFactory.CreateCommandList();
imController = new ImGuiController(graphicsDevice, graphicsDevice.MainSwapchain.Framebuffer.OutputDescription, window.Width, window.Height, myFps);
uiThread = new Thread(this.WhileLoop);
hookController = new HookController(window.X, window.Y);
NativeMethods.InitTransparency(window.Handle);
NativeMethods.SetOverlayClickable(window.Handle, false);
}
/// <summary>
/// To submit ImGui code for generating the UI.
/// </summary>
public event EventHandler SubmitUI;
/// <summary>
/// Starts the overlay.
/// </summary>
public void Run()
public static void RunInfiniteLoop()
{
uiThread.Start();
hookController.EnableHooks();
if (!debugMode)
DateTime previous = DateTime.Now;
DateTime current;
TimeSpan interval;
float sec;
while (window.Exists && !Close)
{
NativeMethods.HideConsoleWindow();
InputSnapshot snapshot = window.PumpEvents();
if (!window.Exists) { break; }
current = DateTime.Now;
interval = current - previous;
sec = (float)interval.TotalSeconds;
previous = current;
imController.Update(sec > 0 ? sec : 0.001f, snapshot, window.Handle);
CoroutineHandler.Tick(interval.TotalSeconds);
if (Visible)
{
CoroutineHandler.RaiseEvent(OnRender);
}
commandList.Begin();
commandList.SetFramebuffer(graphicsDevice.MainSwapchain.Framebuffer);
commandList.ClearColorTarget(0, new RgbaFloat(clearColor.X, clearColor.Y, clearColor.Z, clearColor.W));
imController.Render(graphicsDevice, commandList);
commandList.End();
graphicsDevice.SubmitCommands(commandList);
graphicsDevice.SwapBuffers(graphicsDevice.MainSwapchain);
}
Application.Run(new ApplicationContext());
Dispose();
}
/// <summary>
/// Set the overlay FPS.
/// To submit ImGui code for generating the UI.
/// </summary>
/// <param name="fps">
/// FPS to set.
/// </param>
public void SetFps(int fps)
{
myFps = fps;
}
public static Event OnRender = new Event();
/// <summary>
/// Resizes the overlay.
/// Safely Closes the Overlay.
/// Doesn't matter if you set it to true multiple times.
/// </summary>
/// <param name="x">
/// x axis of the overlay.
/// </param>
/// <param name="y">
/// y axis of the overlay.
/// </param>
/// <param name="width">
/// width of the overlay.
/// </param>
/// <param name="height">
/// height of the overlay.
/// </param>
public void Resize(int x, int y, int width, int height)
{
futurePos.X = x;
futurePos.Y = y;
futureSize.X = width;
futureSize.Y = height;
// TODO: move following two lines to _window.Moved
hookController.UpdateWindowPosition(x, y);
NativeMethods.EnableTransparent(window.Handle);
requireResize = true;
}
public static bool Close { get; set; } = false;
/// <summary>
/// Shows the overlay.
/// Makes the overlay visible or invisible. Invisible Overlay
/// will not call OnRender coroutines, however time based
/// coroutines are still called.
/// </summary>
public void Show()
public static bool Visible { get; set; } = true;
public static bool TerminalWindow
{
hookController.ResumeHooks();
window.Visible = true;
get => terminal;
set
{
if (value != terminal)
{
NativeMethods.SetConsoleWindow(value);
}
terminal = value;
}
}
/// <summary>
/// hides the overlay.
/// Gets or sets the position of the overlay window.
/// </summary>
public void Hide()
public static Point Position
{
hookController.PauseHooks();
window.Visible = false;
get
{
return new Point(window.X, window.Y);
}
set
{
Sdl2Native.SDL_SetWindowPosition(window.SdlWindowHandle, value.X, value.Y);
}
}
/// <summary>
/// Free all resources acquired by the overlay.
/// Gets or sets the size of the overlay window.
/// </summary>
public void Dispose()
public static Point Size
{
window.Close();
while (!isClosed)
get
{
Thread.Sleep(10);
return new Point(window.Width, window.Height);
}
set
{
Sdl2Native.SDL_SetWindowSize(window.SdlWindowHandle, value.X, value.Y);
}
uiThread.Join();
graphicsDevice.WaitForIdle();
imController.Dispose();
commandList.Dispose();
graphicsDevice.Dispose();
hookController.Dispose();
NativeMethods.ShowConsoleWindow();
this.SubmitUI = null;
loadedImages.Clear();
Console.WriteLine("All Overlay resources are cleared.");
Application.Exit();
}
/// <summary>
/// Adds the image to the Graphic Device as a texture.
/// Then returns the pointer of the added texture. It also
/// cache the image internally rather than creating a new texture on every call,
/// so this function can be called multiple times per image (per FPS).
/// so this function can be called multiple times per frame.
/// </summary>
/// <param name="filePath">
/// Path to the image on disk. If the image is loaded in the memory
@ -211,7 +187,7 @@ namespace ClickableTransparentOverlay
/// <returns>
/// A pointer to the Texture in the Graphic Device.
/// </returns>
public IntPtr AddOrGetImagePointer(string filePath)
public static IntPtr AddOrGetImagePointer(string filePath)
{
if (!loadedImages.TryGetValue(filePath, out Texture texture))
{
@ -224,43 +200,34 @@ namespace ClickableTransparentOverlay
}
/// <summary>
/// Infinite While Loop to render the ImGui.
/// Gets or sets the overlay clickable feature.
/// </summary>
private void WhileLoop()
public static bool Clickable
{
while (window.Exists)
get => NativeMethods.IsClickable;
set
{
if (requireResize)
{
Sdl2Native.SDL_SetWindowPosition(window.SdlWindowHandle, (int)futurePos.X, (int)futurePos.Y);
Sdl2Native.SDL_SetWindowSize(window.SdlWindowHandle, (int)futureSize.X, (int)futureSize.Y);
window.PumpEvents();
continue;
}
if (!window.Visible)
{
window.PumpEvents();
Thread.Sleep(10);
continue;
}
hookController.PopMessages();
if (!window.Exists)
{
break;
}
NativeMethods.SetOverlayClickable(window.Handle, value);
}
}
imController.InitlizeFrame(1f / myFps);
this.SubmitUI?.Invoke(this, new EventArgs());
commandList.Begin();
commandList.SetFramebuffer(graphicsDevice.MainSwapchain.Framebuffer);
commandList.ClearColorTarget(0, new RgbaFloat(clearColor.X, clearColor.Y, clearColor.Z, clearColor.W));
imController.Render(graphicsDevice, commandList);
commandList.End();
graphicsDevice.SubmitCommands(commandList);
graphicsDevice.SwapBuffers(graphicsDevice.MainSwapchain);
/// <summary>
/// Free all resources acquired by the overlay.
/// </summary>
private static void Dispose()
{
window.Close();
while (window.Exists)
{
Thread.Sleep(1);
}
graphicsDevice.WaitForIdle();
imController.Dispose();
commandList.Dispose();
graphicsDevice.Dispose();
loadedImages.Clear();
NativeMethods.SetConsoleWindow(true);
}
}
}

@ -1,39 +0,0 @@
// <copyright file="AssemblyInfo.cs" company="Zaafar Ahmed">
// Copyright (c) Zaafar Ahmed. All rights reserved.
// </copyright>
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("ClickableTransparentOverlay")]
[assembly: AssemblyDescription("A library for creating clickable transparent overlay")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ClickableTransparentOverlay")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(true)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("f5cf8972-d0da-4fc0-8796-e7c60101c8ea")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

@ -1,15 +0,0 @@
struct PS_INPUT
{
float4 pos : SV_POSITION;
float4 col : COLOR0;
float2 uv : TEXCOORD0;
};
Texture2D FontTexture : register(t0);
sampler FontSampler : register(s0);
float4 FS(PS_INPUT input) : SV_Target
{
float4 out_col = input.col * FontTexture.Sample(FontSampler, input.uv);
return out_col;
}

@ -1,27 +0,0 @@
cbuffer ProjectionMatrixBuffer : register(b0)
{
float4x4 ProjectionMatrix;
};
struct VS_INPUT
{
float2 pos : POSITION;
float2 uv : TEXCOORD0;
float4 col : COLOR0;
};
struct PS_INPUT
{
float4 pos : SV_POSITION;
float4 col : COLOR0;
float2 uv : TEXCOORD0;
};
PS_INPUT VS(VS_INPUT input)
{
PS_INPUT output;
output.pos = mul(ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));
output.col = input.col;
output.uv = input.uv;
return output;
}

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SharpDX.Direct3D11" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SharpDX" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SharpDX.DXGI" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ImGui.NET" version="1.75.0" targetFramework="net472" />
<package id="MouseKeyHook" version="5.6.0" targetFramework="net472" />
<package id="NativeLibraryLoader" version="1.0.12" targetFramework="net472" />
<package id="SharpDX" version="4.2.0" targetFramework="net472" />
<package id="SharpDX.Direct3D11" version="4.2.0" targetFramework="net472" />
<package id="SharpDX.DXGI" version="4.2.0" targetFramework="net472" />
<package id="SixLabors.Core" version="1.0.0-beta0007" targetFramework="net472" />
<package id="SixLabors.ImageSharp" version="1.0.0-beta0006" targetFramework="net472" />
<package id="StyleCop.Analyzers" version="1.1.118" targetFramework="net472" developmentDependency="true" />
<package id="System.Buffers" version="4.5.0" targetFramework="net472" />
<package id="System.Memory" version="4.5.3" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net472" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.7.0" targetFramework="net472" />
<package id="Veldrid" version="4.7.0" targetFramework="net472" />
<package id="Veldrid.ImageSharp" version="4.7.0" targetFramework="net472" />
<package id="Veldrid.SDL2" version="4.7.0" targetFramework="net472" />
<package id="Veldrid.StartupUtilities" version="4.7.0" targetFramework="net472" />
</packages>

@ -1,14 +0,0 @@
{
// ACTION REQUIRED: This file was automatically added to your project, but it
// will not take effect until additional steps are taken to enable it. See the
// following page for additional information:
//
// https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md
"$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
"settings": {
"documentationRules": {
"companyName": "Zaafar Ahmed"
}
}
}

@ -1,38 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SharpDX.Direct3D11" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SharpDX" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SharpDX.DXGI" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

@ -1,104 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{370E1945-EF74-4618-A2DE-B5796AC3093E}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>DriverProgram</RootNamespace>
<AssemblyName>OverlayDemo</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>
</DefineConstants>
<Optimize>true</Optimize>
<DebugType>none</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<NoWarn>
</NoWarn>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
</PropertyGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
<ProjectReference Include="..\ClickableTransparentOverlay\ClickableTransparentOverlay.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ClickableTransparentOverlay\ClickableTransparentOverlay.csproj">
<Project>{f5cf8972-d0da-4fc0-8796-e7c60101c8ea}</Project>
<Name>ClickableTransparentOverlay</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Reference Include="ImGui.NET, Version=1.75.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ImGui.NET.1.75.0\lib\netstandard2.0\ImGui.NET.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<None Include="image.png">
<None Update="image.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
<Import Project="..\packages\ImGui.NET.1.75.0\build\net40\ImGui.NET.targets" Condition="Exists('..\packages\ImGui.NET.1.75.0\build\net40\ImGui.NET.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\ImGui.NET.1.75.0\build\net40\ImGui.NET.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\ImGui.NET.1.75.0\build\net40\ImGui.NET.targets'))" />
</Target>
</Project>

@ -1,122 +1,166 @@
namespace DriverProgram
using System;
using System.Collections.Generic;
using System.IO;
using System.Numerics;
using ClickableTransparentOverlay;
using Coroutine;
using ImGuiNET;
namespace DriverProgram
{
using ClickableTransparentOverlay;
using ImGuiNET;
using System;
using System.IO;
using System.Numerics;
using System.Threading;
class Program
{
private static bool isRunning = true;
private static bool showImGuiDemo = false;
private static bool drawOnScreen = false;
private static Random randomGen = new Random();
private static int totalCircles = 10;
private static Vector2[] circleCenters = new Vector2[totalCircles];
public static bool showClickableMenu = true;
public static bool showOverlaySample1 = true;
public static bool showOverlaySample2 = false;
public static bool showImGuiDemo = false;
private static int Fps = 144;
private static int[] resizeHelper = new int[4] { 0, 0, 2560, 1440 };
private static int seconds = 5;
private static Overlay overlay = new Overlay(0, 0, 2560, 1440, Fps, true);
private static void MainApplicationLogic()
{
while (isRunning)
{
for (int i = 0; i < circleCenters.Length; i++)
{
circleCenters[i].X = randomGen.Next(0, 2560);
circleCenters[i].Y = randomGen.Next(0, 1440);
}
Thread.Sleep(600);
}
private static int seconds = 5;
overlay.Dispose();
}
private static Random randomGen = new Random();
private static Vector2[] circleCenters = new Vector2[200];
static void Main(string[] args)
static void Main()
{
overlay.SubmitUI += RenderUi;
Thread p = new Thread(MainApplicationLogic);
p.Start();
overlay.Run();
p.Join();
CoroutineHandler.Start(UpdateOverlaySample2());
CoroutineHandler.Start(SubmitRenderLogic());
Overlay.RunInfiniteLoop();
}
private static void RenderUi(object sender, System.EventArgs e)
private static IEnumerator<IWait> SubmitRenderLogic()
{
if(isRunning)
while (true)
{
ImGui.Begin("Overlay Config", ref isRunning, ImGuiWindowFlags.NoResize | ImGuiWindowFlags.AlwaysAutoResize);
if (ImGui.SliderInt("Set FPS", ref Fps, 30, 144))
{
overlay.SetFps(Fps);
}
yield return new WaitEvent(Overlay.OnRender);
ImGui.NewLine();
ImGui.SliderInt2("Set Position", ref resizeHelper[0], 0, 3840);
ImGui.SliderInt2("Set Size", ref resizeHelper[2], 0, 3840);
if (ImGui.Button("Resize"))
if (NativeMethods.isKeyPressed(0x7B)) //F12.
{
overlay.Resize(resizeHelper[0], resizeHelper[1], resizeHelper[2], resizeHelper[3]);
showClickableMenu = !showClickableMenu;
}
ImGui.NewLine();
ImGui.SliderInt("###time(sec)", ref seconds, 1, 30);
if (ImGui.Button($"Hide for {seconds} seconds"))
if (showImGuiDemo)
{
new Thread(() => { Thread.Sleep(seconds * 1000); overlay.Show(); }).Start();
overlay.Hide();
ImGui.ShowDemoWindow(ref showImGuiDemo);
}
ImGui.NewLine();
if(ImGui.Button("Show ImGui Demo"))
if (showOverlaySample1)
{
showImGuiDemo = true;
ImGui.SetNextWindowPos(new Vector2(0f, 0f));
ImGui.SetNextWindowBgAlpha(0.9f);
ImGui.Begin(
"Sample Overlay",
ImGuiWindowFlags.NoInputs |
ImGuiWindowFlags.NoCollapse |
ImGuiWindowFlags.NoTitleBar |
ImGuiWindowFlags.AlwaysAutoResize |
ImGuiWindowFlags.NoResize);
ImGui.Text("I am sample Overlay");
ImGui.Text("You can not click me");
ImGui.Text("I am here just to display stuff");
ImGui.Text($"Current Date: {DateTime.Now.Date}");
ImGui.Text($"Current Time: {DateTime.Now.TimeOfDay}");
ImGui.End();
}
ImGui.NewLine();
if(ImGui.Button("Draw on Screen"))
if (showOverlaySample2)
{
drawOnScreen = true;
ImGui.SetNextWindowContentSize(ImGui.GetIO().DisplaySize);
ImGui.SetNextWindowPos(new Vector2(0, 0));
ImGui.Begin(
"Background Screen",
ref showOverlaySample2,
ImGuiWindowFlags.NoInputs |
ImGuiWindowFlags.NoBackground |
ImGuiWindowFlags.NoBringToFrontOnFocus |
ImGuiWindowFlags.NoCollapse |
ImGuiWindowFlags.NoMove |
ImGuiWindowFlags.NoScrollbar |
ImGuiWindowFlags.NoSavedSettings |
ImGuiWindowFlags.NoResize |
ImGuiWindowFlags.NoTitleBar);
var windowPtr = ImGui.GetWindowDrawList();
for (int i = 0; i < circleCenters.Length; i++)
{
windowPtr.AddCircleFilled(circleCenters[i], 10.0f, (uint)(((255 << 24) | (00 << 16) | (00 << 8) | 255) & 0xffffffffL));
}
ImGui.End();
}
ImGui.NewLine();
if (File.Exists("image.png"))
if (showClickableMenu)
{
ImGui.Image(overlay.AddOrGetImagePointer("image.png"), new Vector2(256, 256));
bool isRunning = true;
if (!ImGui.Begin("Overlay Main Menu", ref isRunning, ImGuiWindowFlags.NoResize | ImGuiWindowFlags.AlwaysAutoResize))
{
Overlay.Close = !isRunning;
ImGui.End();
continue;
}
Overlay.Close = !isRunning;
ImGui.Text("Try pressing F12 button to show/hide this menu.");
ImGui.Text("Click X on top right of this menu to close the overlay.");
ImGui.Checkbox("Show non-clickable transparent overlay Sample 1.", ref showOverlaySample1);
ImGui.Checkbox("Show full-screen non-clickable transparent overlay sample 2.", ref showOverlaySample2);
ImGui.NewLine();
ImGui.SliderInt2("Set Position", ref resizeHelper[0], 0, 3840);
ImGui.SliderInt2("Set Size", ref resizeHelper[2], 0, 3840);
if (ImGui.Button("Resize"))
{
Overlay.Position = new Veldrid.Point(resizeHelper[0], resizeHelper[1]);
Overlay.Size = new Veldrid.Point(resizeHelper[2], resizeHelper[3]);
}
ImGui.NewLine();
ImGui.SliderInt("###time(sec)", ref seconds, 1, 30);
if (ImGui.Button($"Hide for {seconds} seconds"))
{
Overlay.Visible = false;
// Time Based Coroutines are executed even when the Overlay is invisible.
// So in case there is a reason you want to hide the overlay, u can use timebased
// coroutines to bring it back.
CoroutineHandler.InvokeLater(new WaitSeconds(seconds), () => { Overlay.Visible = true; });
}
ImGui.NewLine();
if (ImGui.Button("Toggle ImGui Demo"))
{
showImGuiDemo = !showImGuiDemo;
}
if (ImGui.Button("Toggle Terminal"))
{
Overlay.TerminalWindow = !Overlay.TerminalWindow;
}
ImGui.NewLine();
if (File.Exists("image.png"))
{
ImGui.Image(Overlay.AddOrGetImagePointer("image.png"), new Vector2(256, 256));
}
else
{
ImGui.Text("Put any image where the exe is, name is 'image.png'");
}
ImGui.End();
}
else
{
ImGui.Text("Put any image where the exe is, name is 'image.png'");
}
ImGui.End();
}
if (showImGuiDemo)
{
ImGui.ShowDemoWindow(ref showImGuiDemo);
}
}
if(drawOnScreen)
private static IEnumerator<IWait> UpdateOverlaySample2()
{
while (true)
{
ImGui.SetNextWindowContentSize(ImGui.GetIO().DisplaySize);
ImGui.SetNextWindowPos(new Vector2(0, 0));
ImGui.Begin("Background Screen", ref drawOnScreen, ImGuiWindowFlags.NoInputs |
ImGuiWindowFlags.NoBackground | ImGuiWindowFlags.NoBringToFrontOnFocus |
ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoScrollbar |
ImGuiWindowFlags.NoSavedSettings | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoTitleBar);
var windowPtr = ImGui.GetWindowDrawList();
yield return new WaitSeconds(1);
for (int i = 0; i < circleCenters.Length; i++)
{
windowPtr.AddCircleFilled(circleCenters[i], 10.0f, (uint)(((255 << 24) | (00 << 16) | (00 << 8) | 255) & 0xffffffffL));
circleCenters[i].X = randomGen.Next(0, 2560);
circleCenters[i].Y = randomGen.Next(0, 1440);
}
ImGui.End();
}
}
}

@ -1,35 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("OverlayDemo")]
[assembly: AssemblyDescription("Overlay Demo with ImGui")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DriverProgram")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("370e1945-ef74-4618-a2de-b5796ac3093e")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ImGui.NET" version="1.75.0" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net472" />
</packages>
Loading…
Cancel
Save