diff --git a/README.md b/README.md index 65f899d..1558649 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,139 @@ -# Window controller for Unity using Windows API -*This is a submodule of https://github.com/kirurobo/UniWinApi* +# UniWinApi -[UniWinApi](https://github.com/kirurobo/UniWinApi/) の中心部分です。 -この中身は CC0 ライセンスです。 +**UniWinApi** is a Windows API utility with a window controller class for Unity. This allows some window controls that Unity originally does not provide as follows. +* Move the window +* Resize the window +* Maximize or Minimize +* **Transparent (non-rectangular) window** +* **Accept file dropping** +* **File open dialog (Experimental)** +* Move the mouse pointer +* Send mouse button up/down + +[![UniWinApi VRM viewer](http://i.ytimg.com/vi/cq2g-hIGlAs/mqdefault.jpg)](https://youtu.be/cq2g-hIGlAs "UniWinApi VRM viewer v0.4.0 beta") + + +## Confirmed environment + +* Unity 5.6.6f2, Unity 2018.2.20f1 +* Windows 10 Pro x64 +* GeForce GTX980, GeForce GTX 1070 + +|Scripting backend|x86_64|x86| +|:----------------|:----:|:-:| +|Mono | x | x | +|IL2CPP | x | | + +## Usage + +1. Download .unitypackage file from the [Releases](https://github.com/kirurobo/UniWinApi/releases) page. +2. Impoart the package to your project. +3. Attach "WindowController.cs" to a suitable object + * Creating an empty object named "WindowController" is recommended. +4. Build the project as PC Standalone application. ## License [![CC0](http://i.creativecommons.org/p/zero/1.0/88x31.png "CC0")](http://creativecommons.org/publicdomain/zero/1.0/deed.ja) + +## Contact & Source + +* [Twitter: @kirurobo](http://twitter.com/kirurobo) +* [GitHub](http://github.com/kirurobo) + + +--- + +# UniWinApi (日本語説明) + +**UniWinApi** は Unityでは本来行えない操作を Windows API 経由で行うものです。 +自ウィンドウに対しての処理を行うためのコントローラーが付属します。 +以下のようなことができます。 + +* ウィンドウの移動 +* ウィンドウサイズ変更 +* ウィンドウの最大化、最小化 +* **ウィンドウの透過** (枠なしで、四角形でないウィンドウにします) +* **ファイルのドロップを受け付ける** +* **Windowsのダイアログでファイルを開く(試験実装で単一ファイルのみ)** +* マウスポインタを移動させる +* マウスのボタン操作を送出する + +主にデスクトップマスコット的な用途で利用しそうな機能を取り込んでいます。 +[![UniWinApi VRM viewer](http://i.ytimg.com/vi/cq2g-hIGlAs/mqdefault.jpg)](https://youtu.be/cq2g-hIGlAs "UniWinApi VRM viewer v0.4.0 beta") + + +## 確認済み動作環境 + +* Unity 5.6.6f2, Unity 2018.2.20f1 +* Windows 10 Pro x64 +* GeForce GTX980, GeForce GTX 1070 + +|Scripting backend|x86_64|x86| +|:----------------|:----:|:-:| +|Mono | ○ | ○ | +|IL2CPP | ○ | | + +## 利用方法 + +1. [Releases](https://github.com/kirurobo/UniWinApi/releases) ページから .unitypackage ファイルをダウンロードします。 +2. それをプロジェクトにインポートします。 +3. "WindowController.cs" スクリプトを適当なオブジェクトにアタッチしてください。 + * "WindowController" といった名前の空オブジェクト作成をお勧めします。 +4. Platform として PC Standalone を選び、ビルドしてください。 + +UniWinApi が本体ですが、自ウィンドウを操作するものとして WindowController を用意しています。 + + +インスペクタで下記を変更するか、スクリプトから変更するとウィンドウの状態を変えられます。 +- IsTransparent … ウィンドウ枠を透明化 +- IsTopmost … 常に最前面 +- IsMaximized … ウィンドウ最大化 +- IsMinimized … ウィンドウ最小化 +- EnableFileDrop … ファイルドロップを受け付ける +- EnableDragMove … マウス左ボタンでウィンドウを移動できる + +![image](https://user-images.githubusercontent.com/1019117/51594588-1dcb4080-1f38-11e9-9a93-910f59632fc2.png) + +ファイルドロップを利用する場合、`OnFilesDropped(string[] files)` というイベントがありますので、そちらに処理を追加してください。 +files にはドロップされたファイルのパスが入ります。 + +ドキュメントは整えられていないため、利用例はサンプルをご覧ください (^-^; + + +## 注意点 +- ウィンドウハンドルを確実に取る方法が分ってないので、別のウィンドウが操作対象になったりするかも知れません。 + - (むしろ別のウィンドウもタイトルやクラス名で指定して操作できます。) +- 閉じるボタンがなくなったり、ウィンドウを見失った場合、タスクマネージャから終了する必要が出るかも知れません。 + +## FAQ +- エディタ上で透明にすると表示がおかしいのですが。 + - すみません。仕様です。透明化はビルドしたものでご確認ください。 + - Game ウィンドウはどうも背景が塗りつぶされてしまっているようで、透明化されません。 + - ゲームビューが操作対象となりますが、他のビューとドッキングしていた場合はそのウィンドウごと対象となります。 + + +## ライセンス + +[![CC0](http://i.creativecommons.org/p/zero/1.0/88x31.png "CC0")](http://creativecommons.org/publicdomain/zero/1.0/deed.ja) + +UniWinApi は、CC0(パブリックドメイン)としています。 +著作権表示なしで修正、複製、再配布も可能です。好きに使っていただけますが無保証です。 + +※他の方のブログなど参考にしている部分が大いにありますが、一通り作成した結果、同様の機能を実装した場合は似た内容になるとして、著作権で保護される範囲においては基本的に独自のものとしてCC0にできると判断しています。 + +## 連絡先・配布元 + +* [Twitter: @kirurobo](http://twitter.com/kirurobo) +* [GitHub](http://github.com/kirurobo) + +## 更新履歴 + +* 2019/01/23 ファイルオープンダイアログ追加。自ウィンドウ取得方法をアクティブウィンドウ基準に戻した。 +* 2018/12/28 namespaceを設定、自ウィンドウ取得をPIDを基準とする方法に修正 +* 2018/12/07 UniWinApiのアセット部分を分離 +* 2018/09/09 おおよそ想定通りに動作しそうなため、パッケージを公開 +* 2018/08/24 UniWinApiとして整理し直した +* 2015/03/03 最小化、最大化時はその直前の状態を保存するようにした +* 2014/04/26 公開用初版 \ No newline at end of file diff --git a/Scripts/Editor/WindowControllerEditor.cs b/Scripts/Editor/WindowControllerEditor.cs index b224637..8237505 100644 --- a/Scripts/Editor/WindowControllerEditor.cs +++ b/Scripts/Editor/WindowControllerEditor.cs @@ -12,6 +12,8 @@ namespace Kirurobo [CustomEditor(typeof(WindowController))] public class WindowControllerEditor : Editor { + private EditorWindow gameViewWindow; + public override void OnInspectorGUI() { base.OnInspectorGUI(); @@ -67,6 +69,19 @@ public override void OnInspectorGUI() } #endif } + + // 参考 http://baba-s.hatenablog.com/entry/2017/09/17/135018 + /// + /// ゲームビューのEditorWindowを取得 + /// + /// + public static EditorWindow GetGameView() + { + var assembly = typeof(EditorWindow).Assembly; + var type = assembly.GetType("UnityEditor.GameView"); + var gameView = EditorWindow.GetWindow(type); + return gameView; + } } [CustomPropertyDrawer(typeof(ReadOnlyAttribute))] diff --git a/Scripts/UniWinApi.cs b/Scripts/UniWinApi.cs index 7020f3a..3d921f3 100644 --- a/Scripts/UniWinApi.cs +++ b/Scripts/UniWinApi.cs @@ -53,7 +53,7 @@ public WindowHandle(IntPtr hwnd) { ClassName = sbClass.ToString(); } - Debug.Log("CLASS:" + ClassName); + //Debug.Log("CLASS:" + ClassName); // ウィンドウタイトルを取得 StringBuilder sbTitle = new StringBuilder(len); @@ -61,17 +61,16 @@ public WindowHandle(IntPtr hwnd) { Title = sbTitle.ToString(); } - Debug.Log("TITLE:" + Title); + //Debug.Log("TITLE:" + Title); + // プロセスIDを取得 - //IntPtr pid; - ulong pid; + IntPtr pid; WinApi.GetWindowThreadProcessId(hWnd, out pid); // IL2CPP かつ x86 だとクラッシュ? - //ProcessId = pid.ToInt32(); - ProcessId = (int)pid; - Debug.Log("PID: " + ProcessId); + ProcessId = pid.ToInt32(); #if ENABLE_IL2CPP + // プロセス名を取得 // Unity 2018.2.8f1 にて IL2CPP の場合、プロセス名取得時にクラッシュする。 // .NET 4 の場合は即クラッシュした。 // .NET 3.5 のときは即ではないがやはりクラッシュした。 @@ -90,7 +89,7 @@ public WindowHandle(IntPtr hwnd) Debug.Log("Getting process name by PID " + ProcessId + " failed"); } #endif - Debug.Log("NAME: " + ProcessName); + //Debug.Log("NAME: " + ProcessName); } /// @@ -354,7 +353,7 @@ static public WindowHandle FindWindow() //return new WindowHandle(process.MainWindowHandle); // ←これではダメだった。MainWindowHandle == 0 となった。 int pid = process.Id; - Debug.Log("PID: " + pid); + //Debug.Log("PID: " + pid); #if UNITY_EDITOR // Gameビューを取得 @@ -373,33 +372,33 @@ static public WindowHandle FindWindow() // 一応PIDをチェックし、自分一致したらそのウィンドウを使うことにして終了 if (gameWindow.ProcessId == pid) return gameWindow; - +#else + IntPtr hwnd; #endif - //// IL2CPP では FindWindows() を利用できないため、アクティブなウィンドウを取得する方法にいったん戻す - //hwnd = WinApi.GetActiveWindow(); - //if (hwnd == IntPtr.Zero) return null; + // アクティブウィンドウを取得する方法 + hwnd = WinApi.GetActiveWindow(); + if (hwnd == IntPtr.Zero) return null; //Debug.Log("Active HWND:" + hwnd); - //WindowHandle window = new WindowHandle(hwnd); - //if (window.ProcessId != pid) return null; - - //return window; + WindowHandle window = new WindowHandle(hwnd); + if (window.ProcessId != pid) return null; + return window; - // 現存するウィンドウ一式を取得 - WindowHandle[] handles = FindWindows(); - foreach (WindowHandle window in handles) - { - Debug.Log(window); + //// 現存するウィンドウ一式を取得してPIDが一致するものを利用する方法 + //WindowHandle[] handles = FindWindows(); + //foreach (WindowHandle window in handles) + //{ + // Debug.Log(window); - // PIDが一致するものを検索 - if (window.ProcessId == pid) - { - return window; - } - } - return null; + // // PIDが一致するものを検索 + // if (window.ProcessId == pid) + // { + // return window; + // } + //} + //return null; } /// diff --git a/Scripts/WindowController.cs b/Scripts/WindowController.cs index bf3f407..31e57d9 100644 --- a/Scripts/WindowController.cs +++ b/Scripts/WindowController.cs @@ -7,6 +7,10 @@ using System.Collections; using UnityEngine; +#if UNITY_EDITOR +using UnityEditor; +using System.Reflection; +#endif namespace Kirurobo { @@ -196,6 +200,14 @@ void Awake() // 自分のウィンドウを取得 FindMyWindow(); + +#if UNITY_EDITOR + // エディタのウィンドウ配置が変化した際の呼び出し + EditorApplicationUtility.windowsReordered += () => { + this.isWindowChecked = false; // ウィンドウが不確かであるとする + Debug.Log("Editor windows reordered"); + }; +#endif } void Start() @@ -212,6 +224,13 @@ void OnDestroy() // Update is called once per frame void Update() { + // 自ウィンドウ取得状態が不確かなら探しなおす + // マウス押下が取れるのはすなわちフォーカスがあるとき + if (Input.GetMouseButtonDown(0)) + { + UpdateWindow(); + } + // キー、マウス操作の下ウィンドウへの透過状態を更新 UpdateClickThrough(); @@ -394,43 +413,53 @@ private void FindMyWindow() } /// - /// ウィンドウへのフォーカスが変化したときに呼ばれる + /// 自分のウィンドウハンドルが不確かならば探しなおす /// - /// - private void OnApplicationFocus(bool focus) + private void UpdateWindow() { - Debug.Log("Focus:" + focus); - if (uniWin == null) return; - if (focus) + // もしウィンドウハンドル取得に失敗していたら再取得 + if (!uniWin.IsActive) { - // もしウィンドウハンドル取得に失敗していたら再取得 - if (!uniWin.IsActive) + //Debug.Log("Window is not active"); + FindMyWindow(); + } + else if (!isWindowChecked) + { + // 自分自身のウィンドウか未確認の場合 + + // 今アクティブなウィンドウが自分自身かをチェック + if (uniWin.CheckActiveWindow()) { - Debug.Log("Window is not active"); - FindMyWindow(); + isWindowChecked = true; // どうやら正しくウィンドウをつかめているよう } - else if (!isWindowChecked) + else { - // 自分自身のウィンドウか確認できていなかった場合 - - if (uniWin.CheckActiveWindow()) - { - isWindowChecked = true; // どうやら正しくウィンドウをつかめているよう - } - else - { - // ウィンドウが違っているようなので、もう一度アクティブウィンドウを取得 - uniWin.Reset(); - uniWin.Dispose(); - uniWin = new UniWinApi(); - FindMyWindow(); - } + // ウィンドウが違っているようなので、もう一度アクティブウィンドウを取得 + uniWin.Reset(); + uniWin.Dispose(); + uniWin = new UniWinApi(); + FindMyWindow(); } } } + /// + /// ウィンドウへのフォーカスが変化したときに呼ばれる + /// + /// + private void OnApplicationFocus(bool focus) + { + //Debug.Log("Focus:" + focus); + + if (focus) + { + UpdateWindow(); + } + + } + /// /// ウィンドウ透過状態になった際、自動的に背景を透明単色に変更する /// @@ -585,4 +614,37 @@ void OnApplicationQuit() } } } + + +#if UNITY_EDITOR + // エディタ実行時専用 + // ゲームビューが閉じたり開いたりされたときの対応 + + // 参考 http://baba-s.hatenablog.com/entry/2017/12/04/090000#Unity-%E3%82%A8%E3%83%87%E3%82%A3%E3%82%BF%E3%81%AE%E5%90%84%E3%82%A6%E3%82%A3%E3%83%B3%E3%83%89%E3%82%A6%E3%81%AE%E4%BD%8D%E7%BD%AE%E3%81%8C%E5%A4%89%E6%9B%B4%E3%81%95%E3%82%8C%E3%81%9F%E6%99%82 + [InitializeOnLoad] + public static class EditorApplicationUtility + { + private const BindingFlags BINDING_ATTR = BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic; + + private static readonly FieldInfo m_info = typeof(EditorApplication).GetField("windowsReordered", BINDING_ATTR); + + /// + /// エディタウィンドウ配置変化時に呼ばれる + /// + public static EditorApplication.CallbackFunction windowsReordered + { + get + { + return m_info.GetValue(null) as EditorApplication.CallbackFunction; + } + set + { + var functions = m_info.GetValue(null) as EditorApplication.CallbackFunction; + functions += value; + m_info.SetValue(null, functions); + } + } + } +#endif + } diff --git a/Scripts/Wrappers b/Scripts/Wrappers index a61b560..e393756 160000 --- a/Scripts/Wrappers +++ b/Scripts/Wrappers @@ -1 +1 @@ -Subproject commit a61b5601e2bd432821badef399cca7700fed1eef +Subproject commit e393756a43d609760ad2d2b116a9a22ab7beb8de diff --git a/readme_jp.txt b/readme_jp.txt deleted file mode 100644 index 1fdc67b..0000000 --- a/readme_jp.txt +++ /dev/null @@ -1,86 +0,0 @@ -UniWinApi - -Copyright (c) 2014-2018 Kirurobo -Released under CC0 - - -■ 概要 -・Windows API の機能を Unity 上から呼び出すためのクラスです。 - - -■ 確認済み動作環境 -・Unity 5.6.6f2, Unity 2018.2.6f1 -・Windows 10 Pro x64 -・GeForce GTX980, GeForce GTX 1070 - - -■ 内容物 -本体は下記フォルダ配下です。 -・UniWinApi - ・Examples - サンプルシーンがあります。 - ・Scripts - ・WindowController.cs … 自ウィンドウを操作する前提で実装したクラス - ・UniWinApi.cs … Windows API をまとめた、本体 - ・Wrapper - ・DwmApi … DWM API のラッパー - ・WinApi … Windows API のラッパー - ・Editor - ・WindowControllerEditor.cs … WindowControllerを利用する上でのエディタ拡張 - - -■ 利用方法 -UniWinApi が本体ですが、自ウィンドウを操作するものとして WindowController を用意しています。 - -WindowController をヒエラルキーの中の適当なゲームオブジェクトにアタッチしてみてください。 -インスペクタで下記を変更するか、スクリプトから変更するとウィンドウの状態を変えられます。 -・IsTransparent … ウィンドウ枠を透明化 -・IsTopmost … 常に最前面 -・IsMaximized … ウィンドウ最大化 -・IsMinimized … ウィンドウ最小化 -・EnableFileDrop … ファイルドロップを受け付ける -・EnableDragMove … マウス左ボタンでウィンドウを移動できる - -ファイルドロップを利用する場合、OnFilesDropped(string[] files) というイベントがありますので、そちらに処理を追加してください。 -files にはドロップされたファイルのパスが入ります。 - -ドキュメントは整えられていないため、利用例はサンプルをご覧ください (^-^; - - -■ 注意点 -・ウィンドウハンドルを確実に取る方法が分ってないので、別のウィンドウが - 操作対象になったりするかも知れません。 - (むしろ別のウィンドウもタイトルやクラス名で指定して操作できます。) -・閉じるボタンがなくなったり、ウィンドウを見失った場合、タスクマネージャから - 終了する必要が出るかも知れません。 - - -■ FAQ -・エディタ上で透明にすると表示がおかしいのですが。 - ・すみません。仕様です。 - ・Game ウィンドウはどうも背景が塗りつぶされてしまっているようで、透明化されません。 - ・透明化はビルドしたものでご確認ください。 - - -■ ライセンス -・Kiruroboが作成したファイルは、CC0(パブリックドメイン)としています。 - 著作権表示なしで修正、複製、再配布も可能です。 - 好きに使っていただけますが無保証です。 - ※他の方のブログなど参考にしている部分が大いにありますが、 -  一通り作成した結果、同様の機能を実装した場合は似た内容になるとして、 -  著作権で保護される範囲においては基本的に独自のものとしてCC0にできると判断しています。 - - -■ 更新履歴 -2018/12/28 namespaceを設定、自ウィンドウ取得方法修正 -2018/12/07 UniWinApiのアセット部分を分離 -2018/09/09 おおよそ想定通りに動作しそうなため、パッケージを公開 -2018/08/24 UniWinApiとして整理し直した -2015/03/03 最小化、最大化時はその直前の状態を保存するようにした -2014/04/26 公開用初版 - - -■ 連絡先・配布元 -@kirurobo -http://twitter.com/kirurobo -http://github.com/kirurobo diff --git a/readme_jp.txt.meta b/readme_jp.txt.meta deleted file mode 100644 index cb68691..0000000 --- a/readme_jp.txt.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: ae49fb3f0408bd743a7756b3af928ada -timeCreated: 1545989242 -licenseType: Pro -TextScriptImporter: - userData: - assetBundleName: - assetBundleVariant: