init uniWindowController 0.9.8
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
# Changelog
|
||||
All notable changes to this package will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.1.0] - 2026-06-14
|
||||
|
||||
### This is the first release of *XUniWindowController*.
|
||||
|
||||
*Initial port of UniWindowController as a UPM package.*
|
||||
|
||||
#### Added
|
||||
- Window transparency (Alpha / ColorKey modes)
|
||||
- Click-through support (Opacity / Raycast / Manual hit-test)
|
||||
- Topmost / Bottommost z-order control
|
||||
- Maximize / Restore window state
|
||||
- Borderless window mode
|
||||
- Window position and size get/set
|
||||
- Multi-monitor window fitting
|
||||
- File drag-and-drop support
|
||||
- Native file open / save dialogs
|
||||
- UI drag-move handle
|
||||
- Inspector editor integration with PlayerSettings validation
|
||||
- All 5 sample scenes ported as UPM samples
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 816edf7e62e07ff48b6595a4f95d1903
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 21a499598678f954687f9bb157795380
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,91 @@
|
||||
# XUniWindowController
|
||||
|
||||
**XUniWindowController** is a Unity native plugin that provides comprehensive standalone application window control for Windows and macOS builds.
|
||||
|
||||
It is a UPM package port of [UniWindowController](https://github.com/kirurobo/UniWindowController) by Kirurobo.
|
||||
|
||||
## Usage
|
||||
|
||||
Add the `UniWindowController` component to any GameObject in your scene. Access it via:
|
||||
|
||||
```csharp
|
||||
var winc = UniWindowController.current;
|
||||
winc.isTransparent = true;
|
||||
winc.isTopmost = true;
|
||||
winc.windowSize = new Vector2(1280, 720);
|
||||
```
|
||||
|
||||
### Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `isTransparent` | `bool` | Enable/disable window transparency |
|
||||
| `alphaValue` | `float` | Window opacity (0.0 ~ 1.0) |
|
||||
| `isTopmost` | `bool` | Keep window always on top |
|
||||
| `isBottommost` | `bool` | Keep window always on bottom |
|
||||
| `isZoomed` | `bool` | Maximize/restore window |
|
||||
| `isClickThrough` | `bool` | Enable/disable mouse click-through |
|
||||
| `windowPosition` | `Vector2Int` | Get/set window position (screen coordinates) |
|
||||
| `windowSize` | `Vector2Int` | Get/set window size (pixels) |
|
||||
| `clientSize` | `Vector2Int` | Get client area size (read-only) |
|
||||
| `allowDropFiles` | `bool` | Enable/disable file drag-and-drop |
|
||||
| `hitTestType` | `HitTestType` | Click-through detection mode |
|
||||
| `transparentType` | `TransparentType` | Transparency algorithm |
|
||||
| `shouldFitMonitor` | `bool` | Fit window to a specific monitor |
|
||||
| `monitorToFit` | `int` | Target monitor index |
|
||||
|
||||
### Events
|
||||
|
||||
| Event | Description |
|
||||
|-------|-------------|
|
||||
| `OnStateChanged` | Fired when window style, z-order, or size changes |
|
||||
| `OnMonitorChanged` | Fired when display configuration changes (resolution, monitor count) |
|
||||
| `OnDropFiles` | Fired when files are dragged and dropped onto the window |
|
||||
|
||||
## Samples
|
||||
|
||||
Import samples via **Package Manager > XUniWindowController > Samples**.
|
||||
|
||||
The following samples are included:
|
||||
|
||||
- **Menu** — Navigation menu for browsing all sample scenes
|
||||
- **SimpleSample** — Minimal setup demonstrating basic window control
|
||||
- **UiSample** — Complete UI with toggles, sliders, dropdowns for all window properties
|
||||
- **Fullscreen** — Fullscreen mode with right-click context menu and a 3D snowman scene
|
||||
- **FileDialog** — Native file open/save dialog integration
|
||||
|
||||
## Technical Details
|
||||
|
||||
### Windows Architecture
|
||||
|
||||
The plugin uses `LibUniWinC.dll` (C++ Win32 DLL) to control window behavior through native Win32 API calls:
|
||||
|
||||
- `SetWindowLong` / `GetWindowLong` — Window style modification (borderless, layered, click-through)
|
||||
- `SetWindowPos` — Position, size, and Z-order (topmost/bottommost)
|
||||
- `DwmExtendFrameIntoClientArea` — DWM alpha transparency
|
||||
- `SetLayeredWindowAttributes` — ColorKey transparency mode
|
||||
- `SetWindowsHookEx` / custom `WNDPROC` — Window message interception (file drop, display change, resize)
|
||||
- `DragAcceptFiles` — File drag-and-drop
|
||||
- `GetOpenFileNameW` / `GetSaveFileNameW` — Native file dialogs
|
||||
|
||||
### macOS Architecture
|
||||
|
||||
The plugin uses `LibUniWinC.bundle` (Swift / Cocoa) to control window behavior through Cocoa APIs:
|
||||
|
||||
- `NSWindow.styleMask` — Borderless mode
|
||||
- `NSWindow.level` — Z-order (topmost/bottommost)
|
||||
- `NSWindow.isOpaque` / `backgroundColor` — Transparency
|
||||
- `NSWindow.ignoresMouseEvents` — Click-through
|
||||
- `NSDraggingDestination` protocol — File drag-and-drop
|
||||
- `NSOpenPanel` / `NSSavePanel` — Native file dialogs
|
||||
- `constrainFrameRect` method swizzling — Free window positioning
|
||||
- `NotificationCenter` — Window state change observation
|
||||
|
||||
### Package Contents
|
||||
|
||||
| Location | Description |
|
||||
|----------|-------------|
|
||||
| `Runtime/Scripts/` | Core C# scripts (UniWindowController, UniWinCore, FilePanel, etc.) |
|
||||
| `Runtime/Plugins/` | Native plugin binaries (.dll for Windows, .bundle for macOS) |
|
||||
| `Editor/Scripts/` | Editor extensions (Inspector UI, batch build, PlayerSettings validation) |
|
||||
| `Samples~/` | Sample scenes and scripts |
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c67695e4c6a6d24f9fcdc3374c61073
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f7d50d96d22abb249aa89d22ffeceb31
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 51 KiB |
@@ -0,0 +1,114 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 77aeb9a6b2955d14cbc743feb1a80851
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 0
|
||||
wrapV: 0
|
||||
wrapW: 0
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e98c5a3fed598e34c9be86e1c42c95a6
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "Lrss3.Xuniwindowcontroller.Editor",
|
||||
"references": [
|
||||
"Lrss3.Xuniwindowcontroller"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": []
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f2ccb850d779ff749a565c6e5d95eaff
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 136bc4b3fb1edb04a814503bea6b7ed5
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,67 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Build;
|
||||
using UnityEditor.Build.Reporting;
|
||||
// ReSharper disable UnusedMember.Local
|
||||
|
||||
namespace Kirurobo
|
||||
{
|
||||
class UniWindowControllerBatch
|
||||
{
|
||||
//[MenuItem("Build/Build OSX")]
|
||||
static void PerformBuild()
|
||||
{
|
||||
// コマンドライン引数の最後が出力パスだとする
|
||||
//string outputPath = System.Environment.GetCommandLineArgs().Last();
|
||||
|
||||
// var buildPlayerOptions = new BuildPlayerOptions();
|
||||
// buildPlayerOptions.scenes = sceneList.ToArray();
|
||||
// buildPlayerOptions.locationPathName = outputPath;
|
||||
// buildPlayerOptions.target = BuildTarget.StandaloneOSX;
|
||||
// buildPlayerOptions.options = BuildOptions.None;
|
||||
|
||||
// 事前にエディタから設定したビルド設定を利用
|
||||
var scenes = EditorBuildSettings.scenes;
|
||||
var buildTarget = EditorUserBuildSettings.activeBuildTarget;
|
||||
var locationPath = EditorUserBuildSettings.GetBuildLocation(buildTarget);
|
||||
|
||||
// ビルド対象は環境に合わせて上書き
|
||||
#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
|
||||
buildTarget = BuildTarget.StandaloneOSX;
|
||||
locationPath = "Builds/macOS/" + Application.productName;
|
||||
#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
|
||||
buildTarget = BuildTarget.StandaloneWindows64;
|
||||
locationPath = "Builds/Win64/" + Application.productName;
|
||||
#endif
|
||||
|
||||
var buildPlayerOptions = new BuildPlayerOptions
|
||||
{
|
||||
scenes = EditorBuildSettingsScene.GetActiveSceneList(scenes),
|
||||
locationPathName = locationPath,
|
||||
target = buildTarget,
|
||||
options = BuildOptions.None
|
||||
};
|
||||
|
||||
// // 内容チェック用
|
||||
// foreach (var scene in buildPlayerOptions.scenes)
|
||||
// {
|
||||
// Debug.Log(scene);
|
||||
// }
|
||||
// Debug.Log(buildPlayerOptions.locationPathName);
|
||||
// return;
|
||||
|
||||
var report = BuildPipeline.BuildPlayer(buildPlayerOptions);
|
||||
var summary = report.summary;
|
||||
|
||||
if (summary.result == BuildResult.Succeeded)
|
||||
{
|
||||
Debug.Log("构建成功");
|
||||
} else if (summary.result == BuildResult.Failed)
|
||||
{
|
||||
Debug.Log("构建失败");
|
||||
//EditorApplication.Exit(1);
|
||||
throw new BuildFailedException(report.summary.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9aa8110448ede05409f3ce652b3ad2d1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,591 @@
|
||||
/*
|
||||
* UniWindowControllerEditor.cs
|
||||
*
|
||||
* Author: Kirurobo http://x.com/kirurobo
|
||||
* License: MIT
|
||||
*/
|
||||
|
||||
// Assembry Definition を有効にしてから、ビルド時に Editor クラスがないとエラーが出る。
|
||||
// そこで丸ごと UNITY_EDITOR が無い場合は無視するものとした
|
||||
#if UNITY_EDITOR
|
||||
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Reflection;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace Kirurobo
|
||||
{
|
||||
/// <summary>
|
||||
/// UniWindowControllerのためのエディタカスタマイズ部分
|
||||
/// </summary>
|
||||
[CustomEditor(typeof(UniWindowController))]
|
||||
public class UniWindowControllerEditor : Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// カーソル下の色を表示するためのプロパティ
|
||||
/// </summary>
|
||||
SerializedProperty pickedColor;
|
||||
|
||||
/// <summary>
|
||||
/// ゲームビューのウィンドウ
|
||||
/// </summary>
|
||||
private EditorWindow gameViewWindow;
|
||||
|
||||
/// <summary>
|
||||
/// プロジェクト設定に関する警告を閉じておくか
|
||||
private bool isWarningDismissed = false;
|
||||
|
||||
/// <summary>
|
||||
/// URP に関する警告を閉じておくか
|
||||
/// </summary>
|
||||
private bool isUrpWarningDismissed = true;
|
||||
|
||||
/// <summary>
|
||||
/// URP が有効かどうか
|
||||
/// </summary>
|
||||
private bool hasUrp = false;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
LoadSettings();
|
||||
|
||||
pickedColor = serializedObject.FindProperty("pickedColor");
|
||||
|
||||
// URP が有効か否かを判定
|
||||
hasUrp = GetUrpSettings();
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
SaveSettings();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// URPが有効か否かを検出
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private bool GetUrpSettings()
|
||||
{
|
||||
var renderPipelineAsset = GraphicsSettings.defaultRenderPipeline;
|
||||
if (renderPipelineAsset == null || renderPipelineAsset.GetType().Name != "UniversalRenderPipelineAsset")
|
||||
{
|
||||
// URP が設定されていない
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void LoadSettings()
|
||||
{
|
||||
isWarningDismissed = EditorUserSettings.GetConfigValue("WindowController_IS_WARNING DISMISSED") == "1";
|
||||
}
|
||||
|
||||
private void SaveSettings()
|
||||
{
|
||||
EditorUserSettings.SetConfigValue("WindowController_IS_WARNING DISMISSED", isWarningDismissed ? "1" : "0");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// インスペクタでの表示をカスタマイズ
|
||||
/// </summary>
|
||||
/// <description>
|
||||
/// 参考情報および、推奨設定の変更欄を表示します。
|
||||
/// </description>
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
|
||||
// カーソル下の色が得られていれば、その透明度を参考として表示
|
||||
if (pickedColor != null)
|
||||
{
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
EditorGUILayout.LabelField("选取的Alpha值", pickedColor.colorValue.a.ToString("P0"));
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
|
||||
// Project Settings の推奨設定を表示
|
||||
isWarningDismissed = ShowPlayerSettingsValidation(isWarningDismissed);
|
||||
|
||||
// URP 関連の推奨設定を表示
|
||||
isUrpWarningDismissed = ShowUrpSettingsValidation(isUrpWarningDismissed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Project Settings に関する推奨設定の自動設定欄を表示
|
||||
/// </summary>
|
||||
private bool ShowPlayerSettingsValidation(bool dismissed) {
|
||||
// 以下は Project Settings 関連
|
||||
EditorGUILayout.Space();
|
||||
|
||||
bool enableValidation = EditorGUILayout.Foldout(!dismissed, "播放器设置验证");
|
||||
|
||||
// チェックするかどうかを記憶
|
||||
if (enableValidation == dismissed)
|
||||
{
|
||||
dismissed = !enableValidation;
|
||||
}
|
||||
|
||||
// 推奨設定のチェック
|
||||
//if (!isWarningDismissed)
|
||||
if (enableValidation)
|
||||
{
|
||||
if (ValidateSettings(false))
|
||||
{
|
||||
// 应用所有推荐设置
|
||||
GUI.backgroundColor = Color.green;
|
||||
if (GUILayout.Button(
|
||||
"✔ 将所有设置修复为推荐值",
|
||||
GUILayout.MinHeight(25f)
|
||||
))
|
||||
{
|
||||
ValidateSettings(true);
|
||||
}
|
||||
|
||||
// 关闭验证
|
||||
GUI.backgroundColor = Color.yellow;
|
||||
if (GUILayout.Button(
|
||||
"✘ 关闭此验证",
|
||||
GUILayout.MinHeight(25f)
|
||||
))
|
||||
{
|
||||
dismissed = true;
|
||||
|
||||
//SaveSettings(); // 如果需要立即保存,取消注释
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.color = Color.green;
|
||||
GUILayout.Label("OK!");
|
||||
}
|
||||
|
||||
// 打开播放器设置页面
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.FlexibleSpace();
|
||||
GUI.color = Color.white;
|
||||
GUI.backgroundColor = Color.white;
|
||||
if (GUILayout.Button(
|
||||
"打开播放器设置",
|
||||
GUILayout.MinHeight(25f), GUILayout.Width(200f)
|
||||
))
|
||||
{
|
||||
SettingsService.OpenProjectSettings("Project/Player");
|
||||
}
|
||||
GUILayout.FlexibleSpace();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
return dismissed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// URP に関する推奨設定の自動設定欄を表示
|
||||
/// </summary>
|
||||
private bool ShowUrpSettingsValidation(bool dismissed) {
|
||||
// URP が無効ならば何もしない
|
||||
if (!hasUrp) return dismissed;
|
||||
|
||||
// 以下は URP 関連の自動設定
|
||||
EditorGUILayout.Space();
|
||||
|
||||
bool enableValidation = EditorGUILayout.Foldout(!dismissed, "URP 设置验证");
|
||||
// チェックするかどうかを記憶
|
||||
if (enableValidation == dismissed)
|
||||
{
|
||||
dismissed = !enableValidation;
|
||||
}
|
||||
// 推奨設定のチェック
|
||||
//if (!isWarningDismissed)
|
||||
if (enableValidation)
|
||||
{
|
||||
if (ValidateUrpSettings(false))
|
||||
{
|
||||
// 应用所有推荐设置
|
||||
GUI.backgroundColor = Color.green;
|
||||
if (GUILayout.Button(
|
||||
"✔ 将所有设置修复为推荐值",
|
||||
GUILayout.MinHeight(25f)
|
||||
))
|
||||
{
|
||||
ValidateUrpSettings(true);
|
||||
}
|
||||
|
||||
// 关闭验证
|
||||
GUI.backgroundColor = Color.yellow;
|
||||
if (GUILayout.Button(
|
||||
"✘ 关闭此验证",
|
||||
GUILayout.MinHeight(25f)
|
||||
))
|
||||
{
|
||||
dismissed = true;
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.color = Color.green;
|
||||
GUILayout.Label("OK!");
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
return dismissed;
|
||||
}
|
||||
|
||||
private delegate void FixMethod();
|
||||
|
||||
/// <summary>
|
||||
/// 显示或修复设置
|
||||
/// </summary>
|
||||
/// <param name="message">警告消息</param>
|
||||
/// <param name="fixAction">修复操作</param>
|
||||
/// <param name="silentFix">false: 显示警告和修复按钮, true: 静默修复</param>
|
||||
private void FixSetting(string message, FixMethod fixAction, bool silentFix = false)
|
||||
|
||||
{
|
||||
if (silentFix)
|
||||
{
|
||||
// 修复
|
||||
fixAction.Invoke();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 显示消息和修复按钮
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.HelpBox(message, MessageType.Warning, true);
|
||||
GUILayout.FlexibleSpace();
|
||||
|
||||
EditorGUILayout.BeginVertical();
|
||||
EditorGUILayout.Space();
|
||||
if (GUILayout.Button("修复", GUILayout.Width(60f))) { fixAction.Invoke(); }
|
||||
//GUILayout.FlexibleSpace();
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 仅显示建议
|
||||
/// </summary>
|
||||
/// <param name="message">警告消息</param>
|
||||
private void ShowInfo(string message, Object target = null)
|
||||
|
||||
{
|
||||
// 显示消息和定位按钮
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.HelpBox(message, MessageType.Info, true);
|
||||
GUILayout.FlexibleSpace();
|
||||
|
||||
// 自動設定できない対象は、プロジェクトウィンドウで示すのみ
|
||||
if (target != null)
|
||||
{
|
||||
EditorGUILayout.BeginVertical();
|
||||
EditorGUILayout.Space();
|
||||
if (GUILayout.Button("定位", GUILayout.Width(60f))) { EditorGUIUtility.PingObject(target); }
|
||||
//GUILayout.FlexibleSpace();
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证播放器设置
|
||||
/// </summary>
|
||||
/// <param name="silentFix">false: 显示警告和修复按钮, true: 静默修复</param>
|
||||
/// <returns>如果有无效项则返回 true</returns>
|
||||
private bool ValidateSettings(bool silentFix = false)
|
||||
{
|
||||
bool invalid = false;
|
||||
|
||||
// バックグラウンドでも実行する。クリックスルー切替などで必要
|
||||
if (!PlayerSettings.runInBackground)
|
||||
{
|
||||
invalid = true;
|
||||
FixSetting(
|
||||
"强烈建议启用'后台运行'。",
|
||||
() => PlayerSettings.runInBackground = true,
|
||||
silentFix
|
||||
);
|
||||
}
|
||||
|
||||
// サイズ変更可能なウィンドウとする。必須ではないがウィンドウ枠無効時にサイズも変わるので変更可能である方が自然
|
||||
if (!PlayerSettings.resizableWindow)
|
||||
{
|
||||
invalid = true;
|
||||
FixSetting(
|
||||
"建议启用'可调整窗口大小'。",
|
||||
() => PlayerSettings.resizableWindow = true,
|
||||
silentFix
|
||||
);
|
||||
}
|
||||
|
||||
// フルスクリーンでなくウィンドウとする
|
||||
#if UNITY_2018_1_OR_NEWER
|
||||
// Unity 2018 からはフルスクリーン指定の仕様が変わった
|
||||
if (PlayerSettings.fullScreenMode != FullScreenMode.Windowed)
|
||||
{
|
||||
invalid = true;
|
||||
FixSetting(
|
||||
"在'全屏模式'中选择'窗口化'。",
|
||||
() => PlayerSettings.fullScreenMode = FullScreenMode.Windowed,
|
||||
silentFix
|
||||
);
|
||||
|
||||
}
|
||||
#else
|
||||
if (PlayerSettings.defaultIsFullScreen)
|
||||
{
|
||||
invalid = true;
|
||||
FixSetting(
|
||||
"不建议启用'默认全屏'。",
|
||||
() => PlayerSettings.defaultIsFullScreen = false,
|
||||
silentFix
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
// フルスクリーンとウィンドウの切替を無効とする
|
||||
if (PlayerSettings.allowFullscreenSwitch)
|
||||
{
|
||||
invalid = true;
|
||||
FixSetting(
|
||||
"禁止全屏切换。",
|
||||
() => PlayerSettings.allowFullscreenSwitch = false,
|
||||
silentFix
|
||||
);
|
||||
}
|
||||
|
||||
// Windowsでは Use DXGI Flip Mode Swapchain を無効にしないと透過できない
|
||||
// ↓Unity 2019.1.6未満だと useFlipModelSwapchain は無いはず
|
||||
// なので除外のため書き連ねてあるが、ここまでサポートしなくて良い気もする。
|
||||
#if UNITY_2019_1_6
|
||||
#elif UNITY_2019_1_5
|
||||
#elif UNITY_2019_1_4
|
||||
#elif UNITY_2019_1_3
|
||||
#elif UNITY_2019_1_2
|
||||
#elif UNITY_2019_1_1
|
||||
#elif UNITY_2019_1_0
|
||||
#elif UNITY_2019_1_OR_NEWER
|
||||
// Unity 2019.1.7 以降であれば、Player 設定 の Use DXGI Flip... 無効化を推奨
|
||||
if (PlayerSettings.useFlipModelSwapchain)
|
||||
{
|
||||
invalid = true;
|
||||
FixSetting(
|
||||
"禁用'使用 DXGI 翻转模式交换链'以使窗口透明。",
|
||||
() => PlayerSettings.useFlipModelSwapchain = false,
|
||||
silentFix
|
||||
);
|
||||
}
|
||||
|
||||
// Direct3D12 は透過ウィンドウに対応していないので、Graphics APIs for Windows から除外することを推奨
|
||||
if (PlayerSettings.GetUseDefaultGraphicsAPIs(BuildTarget.StandaloneWindows))
|
||||
{
|
||||
// 自動の場合も警告を出す
|
||||
ShowInfo(
|
||||
"Direct3D12 不支持透明窗口。" +
|
||||
"请考虑在播放器设置中使用 Direct3D11 替代'自动图形 API for Windows'设置。",
|
||||
null
|
||||
);
|
||||
}
|
||||
else if (PlayerSettings.GetGraphicsAPIs(BuildTarget.StandaloneWindows).Contains(GraphicsDeviceType.Direct3D12))
|
||||
{
|
||||
// Graphhics APIs for Windows に Direct3D12 が含まれている場合は警告を出す
|
||||
ShowInfo(
|
||||
"Direct3D12 不支持透明窗口。" +
|
||||
"请从播放器设置的'图形 API for Windows'中移除 Direct3D12。",
|
||||
null
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
return invalid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证播放器设置
|
||||
/// </summary>
|
||||
/// <param name="silentFix">false: 显示警告和修复按钮, true: 静默修复</param>
|
||||
/// <returns>如果有无效项则返回 true</returns>
|
||||
private bool ValidateUrpSettings(bool silentFix = false)
|
||||
{
|
||||
bool invalid = false;
|
||||
|
||||
// Universal Render Pipelineが有効ならば、HDRの無効化を推奨
|
||||
foreach (var cam in Camera.allCameras)
|
||||
{
|
||||
if (cam.allowHDR) {
|
||||
string name = cam.name;
|
||||
invalid = true;
|
||||
FixSetting(
|
||||
$"{name}:禁用摄像机中的'HDR'以使窗口透明。",
|
||||
() => cam.allowHDR = false,
|
||||
silentFix
|
||||
);
|
||||
}
|
||||
if (cam.allowMSAA) {
|
||||
string name = cam.name;
|
||||
invalid = true;
|
||||
FixSetting(
|
||||
$"{name}:禁用摄像机中的'MSAA'以使窗口透明。",
|
||||
() => cam.allowMSAA = false,
|
||||
silentFix
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
var urpAsset = GraphicsSettings.defaultRenderPipeline;
|
||||
if (hasUrp && urpAsset != null)
|
||||
{
|
||||
// hasUrp == true の時点で urpAsset は UniversalRenderPipelineAsset であるはず。そのため allowPostProcessAlphaOutput があるはず
|
||||
var alphaProcessingProperty = urpAsset.GetType().GetProperty("allowPostProcessAlphaOutput", BindingFlags.Public | BindingFlags.Instance);
|
||||
if (alphaProcessingProperty != null)
|
||||
{
|
||||
var alphaProcessing = alphaProcessingProperty.GetValue(urpAsset);
|
||||
if (!(bool)alphaProcessing)
|
||||
{
|
||||
invalid = true;
|
||||
ShowInfo(
|
||||
"在 URP 资源中启用'Alpha 处理'",
|
||||
urpAsset
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return invalid;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[CustomPropertyDrawer(typeof(ReadOnlyAttribute))]
|
||||
public class UniWindowControllerReadOnlyDrawer : PropertyDrawer
|
||||
{
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
GUI.enabled = false;
|
||||
EditorGUI.PropertyField(position, property, label, true);
|
||||
GUI.enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置布尔属性为可编辑
|
||||
/// 参考: http://ponkotsu-hiyorin.hateblo.jp/entry/2015/10/20/003042
|
||||
/// 参考: https://forum.unity.com/threads/c-class-property-with-reflection-in-propertydrawer-not-saving-to-prefab.473942/
|
||||
/// </summary>
|
||||
[CustomPropertyDrawer(typeof(EditablePropertyAttribute))]
|
||||
public class UniWindowControllerDrawer : PropertyDrawer
|
||||
{
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
//base.OnGUI(position, property, label);
|
||||
|
||||
Object obj = property.serializedObject.targetObject;
|
||||
|
||||
// Range(min, max) が設定されていれば取得
|
||||
FieldInfo fieldInfo = obj.GetType().GetField(
|
||||
property.name,
|
||||
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static
|
||||
);
|
||||
var rangeAttrs = fieldInfo?.GetCustomAttributes(typeof(RangeAttribute), true) as RangeAttribute[];
|
||||
RangeAttribute range = (rangeAttrs?.Length > 0 ? rangeAttrs.First() : null);
|
||||
|
||||
if (EditorApplication.isPlayingOrWillChangePlaymode)
|
||||
{
|
||||
// 変数の先頭が '_' であることが動作の条件
|
||||
if (property.name[0] == '_')
|
||||
{
|
||||
string propertyName = property.name.Substring(1); // '_' なしをプロパティ名として取得
|
||||
PropertyInfo info = obj.GetType().GetProperty(propertyName);
|
||||
MethodInfo getMethod = default(MethodInfo);
|
||||
MethodInfo setMethod = default(MethodInfo);
|
||||
if (info.CanRead) { getMethod = info.GetGetMethod(); }
|
||||
if (info.CanWrite) { setMethod = info.GetSetMethod(); }
|
||||
|
||||
if (property.type == "bool")
|
||||
{ var oldValue = property.boolValue;
|
||||
if (getMethod != null)
|
||||
{
|
||||
oldValue = (bool)getMethod.Invoke(obj, null);
|
||||
}
|
||||
GUI.enabled = (setMethod != null);
|
||||
EditorGUI.PropertyField(position, property, label, true);
|
||||
GUI.enabled = true;
|
||||
var newValue = property.boolValue;
|
||||
if ((setMethod != null) && (oldValue != newValue))
|
||||
{
|
||||
setMethod.Invoke(obj, new[] { (object)newValue });
|
||||
}
|
||||
}
|
||||
else if (property.type == "float")
|
||||
{
|
||||
|
||||
var oldValue = property.floatValue;
|
||||
if (getMethod != null)
|
||||
{
|
||||
oldValue = (float) getMethod.Invoke(obj, null);
|
||||
}
|
||||
|
||||
GUI.enabled = (setMethod != null);
|
||||
if (range != null)
|
||||
{
|
||||
EditorGUI.Slider(position, property, range.min, range.max, label);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUI.PropertyField(position, property, label, true);
|
||||
}
|
||||
GUI.enabled = true;
|
||||
|
||||
var newValue = property.floatValue;
|
||||
if ((setMethod != null) && (oldValue != newValue))
|
||||
{
|
||||
setMethod.Invoke(obj, new[] {(object) newValue});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// bool, float 以外は今のところ非対応で Readonly とする
|
||||
GUI.enabled = false;
|
||||
EditorGUI.PropertyField(position, property, label, true);
|
||||
GUI.enabled = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 只读
|
||||
GUI.enabled = false;
|
||||
EditorGUI.PropertyField(position, property, label, true);
|
||||
GUI.enabled = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Range 指定があればスライダー
|
||||
if (range != null)
|
||||
{
|
||||
EditorGUI.Slider(position, property, range.min, range.max, label);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUI.PropertyField(position, property, label, true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
return EditorGUI.GetPropertyHeight(property, label, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4132cf6e84b9d6e4488bce4df8f1bb67
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,86 @@
|
||||
# XUniWindowController
|
||||
|
||||
**XUniWindowController** is a Unity native plugin that provides comprehensive **standalone application window control** for Windows and macOS builds.
|
||||
|
||||
It allows you to control window transparency, click-through, topmost/bottommost z-order, maximize, file drop, native file dialogs, and multi-monitor window fitting — all from C# scripts through a simple Unity component.
|
||||
|
||||
## Features
|
||||
|
||||
- **Window Transparency** — Alpha blending or ColorKey-based transparency
|
||||
- **Click-Through** — Make the window ignore mouse events
|
||||
- **Z-Order Control** — Set window topmost, bottommost, or normal
|
||||
- **Maximize / Restore** — Themed maximize and restore
|
||||
- **Borderless Mode** — Hide the title bar and border
|
||||
- **Window Position & Size** — Get/set window position and size
|
||||
- **Multi-Monitor Support** — Fit window to any connected display
|
||||
- **File Drop** — Receive file paths from drag-and-drop
|
||||
- **Native File Dialogs** — Open and save file dialogs (Windows/macOS native)
|
||||
- **Drag Move** — Drag the window by any UI element
|
||||
|
||||
## Requirements
|
||||
|
||||
- Unity 2022.3 or later
|
||||
- Windows or macOS standalone build target
|
||||
|
||||
## Installation
|
||||
|
||||
### Via Package Manager
|
||||
|
||||
1. Open **Window > Package Manager**
|
||||
2. Click the **+** button > **Add package from git URL**
|
||||
3. Enter the repository URL
|
||||
|
||||
### Via disk (local package)
|
||||
|
||||
1. Copy the `com.lrss3.xuniwindowcontroller` folder to your project's `Packages/` directory
|
||||
2. Package Manager will automatically pick it up
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. Add a **UniWindowController** component to any GameObject in your scene (or use the prefab from samples)
|
||||
2. Configure the Inspector properties:
|
||||
- **Is Transparent** — Enable window transparency
|
||||
- **Is Topmost** — Keep window on top
|
||||
- **Hit Test Type** — Choose opacity-based or raycast-based click-through detection
|
||||
3. Call methods or toggle properties at runtime:
|
||||
|
||||
```csharp
|
||||
var winc = UniWindowController.current;
|
||||
winc.isTransparent = true; // Enable transparency
|
||||
winc.isTopmost = true; // Keep on top
|
||||
winc.isClickThrough = false; // Disable click-through
|
||||
```
|
||||
|
||||
## Samples
|
||||
|
||||
The package includes 5 sample scenes:
|
||||
|
||||
| Sample | Description |
|
||||
|--------|-------------|
|
||||
| **Menu** | Navigation menu for browsing all samples |
|
||||
| **SimpleSample** | Minimal window control setup |
|
||||
| **UiSample** | Full UI with toggles, sliders, dropdowns for all features |
|
||||
| **Fullscreen** | Fullscreen mode + right-click context menu + 3D scene |
|
||||
| **FileDialog** | Native open/save file dialog demonstration |
|
||||
|
||||
Import samples via **Package Manager > XUniWindowController > Samples**.
|
||||
|
||||
## How It Works
|
||||
|
||||
On **Windows**, the plugin uses `LibUniWinC.dll` (C++ Win32 API) to call:
|
||||
- `SetWindowLong` — modify window styles
|
||||
- `SetWindowPos` — control z-order and position
|
||||
- `DwmExtendFrameIntoClientArea` — DWM transparency
|
||||
- `SetLayeredWindowAttributes` — layered window transparency
|
||||
- `DragAcceptFiles` / window subclassing — file drop handling
|
||||
|
||||
On **macOS**, the plugin uses `LibUniWinC.bundle` (Swift / Cocoa) to call:
|
||||
- `NSWindow.styleMask` — borderless mode
|
||||
- `NSWindow.level` — z-order control
|
||||
- `NSWindow.isOpaque` / `backgroundColor` — transparency
|
||||
- `NSDraggingDestination` protocol — file drop
|
||||
- `NSOpenPanel` / `NSSavePanel` — native dialogs
|
||||
|
||||
## License
|
||||
|
||||
This package is based on [UniWindowController](https://github.com/kirurobo/UniWindowController) by Kirurobo, licensed under the MIT License.
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 288347fd9d4e9a2488d0b8cc74fb4da2
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f24a9f4fa29049144bf79a526b2bb586
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "Lrss3.Xuniwindowcontroller",
|
||||
"references": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": []
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4df3d67771614d24192762dbffd67d98
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9161ad40887a5746afa1d4eb780f60a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 186ab6f8e4a960342b3bac311f6b2eb5
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,33 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 04ad9f4fa34d2ed43a2c2a2b15c9959e
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 1
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Standalone: OSXUniversal
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BuildMachineOSBuild</key>
|
||||
<string>25C56</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>LibUniWinC</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.kirurobo.LibUniWinC</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>LibUniWinC</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.9.8</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>MacOSX</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>DTCompiler</key>
|
||||
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||
<key>DTPlatformBuild</key>
|
||||
<string>25B74</string>
|
||||
<key>DTPlatformName</key>
|
||||
<string>macosx</string>
|
||||
<key>DTPlatformVersion</key>
|
||||
<string>26.1</string>
|
||||
<key>DTSDKBuild</key>
|
||||
<string>25B74</string>
|
||||
<key>DTSDKName</key>
|
||||
<string>macosx26.1</string>
|
||||
<key>DTXcode</key>
|
||||
<string>2610</string>
|
||||
<key>DTXcodeBuild</key>
|
||||
<string>17B55</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>11.0</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2019-2025 kirurobo. All rights reserved.</string>
|
||||
</dict>
|
||||
</plist>
|
||||
Binary file not shown.
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5d40a6da1308b51499d69d09998a1672
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 52438bdad5ba3524daae6d7c7050491e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@@ -0,0 +1,27 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2587e857c903c7648bb243f26d8388c5
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 1
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1afe0de787d9c9b419c0083741340611
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@@ -0,0 +1,27 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 94d4ed4ccee04184c93f70e00c6f442c
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 1
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5807c8581d7c4be4ca838592a3a5ce8e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4ecd974a2286b994b8432ec73c8e5bd2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,209 @@
|
||||
using AOT;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Kirurobo
|
||||
{
|
||||
/// <summary>
|
||||
/// 提供打开原生文件对话框的静态方法
|
||||
/// </summary>
|
||||
public class FilePanel
|
||||
{
|
||||
protected class LibUniWinC
|
||||
{
|
||||
[DllImport("LibUniWinC", CharSet = CharSet.Unicode)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool OpenFilePanel(in PanelSettings settings, [MarshalAs(UnmanagedType.LPWStr), Out] StringBuilder buffer, UInt32 bufferSize);
|
||||
|
||||
[DllImport("LibUniWinC", CharSet = CharSet.Unicode)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool OpenSavePanel(in PanelSettings settings, [MarshalAs(UnmanagedType.LPWStr), Out] StringBuilder buffer, UInt32 bufferSize);
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct PanelSettings : IDisposable {
|
||||
public Int32 structSize;
|
||||
public Int32 flags;
|
||||
public IntPtr lpszTitle;
|
||||
public IntPtr lpszFilter;
|
||||
public IntPtr lpszInitialFile;
|
||||
public IntPtr lpszInitialDir;
|
||||
public IntPtr lpszDefaultExt;
|
||||
|
||||
public PanelSettings(Settings settings)
|
||||
{
|
||||
this.structSize = 0;
|
||||
//this.structSize = 4 * 2 + Marshal.SizeOf<IntPtr>() * 3;
|
||||
this.flags = (Int32)settings.flags;
|
||||
|
||||
//this.lpTitleText = IntPtr.Zero;
|
||||
//this.lpFilterText = IntPtr.Zero;
|
||||
//this.lpDefaultPath = IntPtr.Zero;
|
||||
this.lpszTitle = Marshal.StringToHGlobalUni(settings.title);
|
||||
this.lpszFilter = Marshal.StringToHGlobalUni(Filter.Join(settings.filters));
|
||||
this.lpszInitialFile = Marshal.StringToHGlobalUni(settings.initialFile);
|
||||
this.lpszInitialDir = Marshal.StringToHGlobalUni(settings.initialDirectory);
|
||||
//this.lpszDefaultExt = Marshal.StringToHGlobalUni(settings.defaultExtension);
|
||||
this.lpszDefaultExt = IntPtr.Zero;
|
||||
|
||||
//this.structSize = Marshal.SizeOf(this);
|
||||
this.structSize = Marshal.SizeOf(this);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (this.lpszTitle != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(lpszTitle);
|
||||
this.lpszTitle = IntPtr.Zero;
|
||||
}
|
||||
|
||||
if (this.lpszFilter!= IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(lpszFilter);
|
||||
this.lpszFilter= IntPtr.Zero;
|
||||
}
|
||||
|
||||
if (this.lpszInitialFile!= IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(lpszInitialFile);
|
||||
this.lpszInitialFile= IntPtr.Zero;
|
||||
}
|
||||
|
||||
if (this.lpszInitialDir != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(lpszInitialDir);
|
||||
this.lpszInitialDir = IntPtr.Zero;
|
||||
}
|
||||
|
||||
if (this.lpszDefaultExt != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(lpszDefaultExt);
|
||||
this.lpszDefaultExt = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对话框的设置标志
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum Flag
|
||||
{
|
||||
None = 0,
|
||||
FileMustExist = 1, // 仅 Windows
|
||||
FolderMustExist = 2, // 仅 Windows
|
||||
AllowMultipleSelection = 4,
|
||||
CanCreateDirectories = 16,
|
||||
OverwritePrompt = 256, // macOS 上始终启用
|
||||
CreatePrompt = 512, // macOS 上始终启用
|
||||
ShowHiddenFiles = 4096,
|
||||
RetrieveLink = 8192,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件对话框的参数
|
||||
/// </summary>
|
||||
public struct Settings
|
||||
{
|
||||
public string title;
|
||||
public Filter[] filters;
|
||||
public string initialDirectory;
|
||||
public string initialFile;
|
||||
public string defaultExtension; // 未实现
|
||||
public Flag flags;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件过滤器
|
||||
/// </summary>
|
||||
public class Filter
|
||||
{
|
||||
protected string title;
|
||||
protected string[] extensions;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="title">过滤器标题(macOS 上暂不可用)</param>
|
||||
/// <param name="extensions">扩展名数组,如 ["png", "jpg", "txt"]</param>
|
||||
public Filter(string title, params string[] extensions)
|
||||
{
|
||||
this.title = title;
|
||||
this.extensions = extensions;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return title + "\t" + String.Join("\t", extensions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回由 Filter 数组转换后的字符串
|
||||
/// </summary>
|
||||
/// <param name="filters"></param>
|
||||
/// <returns></returns>
|
||||
public static string Join(Filter[] filters)
|
||||
{
|
||||
if (filters == null) return "";
|
||||
|
||||
string result = "";
|
||||
bool isFirstItem = true;
|
||||
foreach (var filter in filters) {
|
||||
if (!isFirstItem) result += "\n";
|
||||
result += filter.ToString();
|
||||
isFirstItem = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用于传递文件或文件夹路径的 UTF-16 缓冲区字符数
|
||||
/// 因为多个路径以换行符分隔,260 字符不够用。
|
||||
/// </summary>
|
||||
private const int pathBufferSize = 2560;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 打开文件选择对话框
|
||||
/// </summary>
|
||||
/// <param name="settings"></param>
|
||||
/// <param name="action"></param>
|
||||
public static void OpenFilePanel(Settings settings, Action<string[]> action)
|
||||
{
|
||||
LibUniWinC.PanelSettings ps = new LibUniWinC.PanelSettings(settings);
|
||||
StringBuilder sb = new StringBuilder(pathBufferSize);
|
||||
|
||||
if (LibUniWinC.OpenFilePanel(in ps, sb, (uint)sb.Capacity))
|
||||
{
|
||||
string[] files = UniWinCore.parsePaths(sb.ToString());
|
||||
action.Invoke(files);
|
||||
}
|
||||
|
||||
ps.Dispose(); // 通过传入 Settings 的构造函数分配了内存,因此需要释放
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 打开保存文件选择对话框
|
||||
/// </summary>
|
||||
/// <param name="settings"></param>
|
||||
/// <param name="action"></param>
|
||||
public static void SaveFilePanel(Settings settings, Action<string[]> action)
|
||||
{
|
||||
LibUniWinC.PanelSettings ps = new LibUniWinC.PanelSettings(settings);
|
||||
StringBuilder sb = new StringBuilder(pathBufferSize);
|
||||
|
||||
if (LibUniWinC.OpenSavePanel(in ps, sb, (uint)sb.Capacity))
|
||||
{
|
||||
string[] files = UniWinCore.parsePaths(sb.ToString());
|
||||
action.Invoke(files);
|
||||
}
|
||||
|
||||
ps.Dispose(); // 通过传入 Settings 的构造函数分配了内存,因此需要释放
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ade63dbb28ba23c40bfc1795ae2b605c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,926 @@
|
||||
/*
|
||||
* UniWinCore.cs
|
||||
*
|
||||
* Author: Kirurobo http://twitter.com/kirurobo
|
||||
* License: MIT 许可证
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using AOT;
|
||||
using UnityEngine;
|
||||
using System.Text;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
namespace Kirurobo
|
||||
{
|
||||
/// <summary>
|
||||
/// LibUniWinC 的原生插件包装
|
||||
/// </summary>
|
||||
internal class UniWinCore : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// 仅 Windows 下的透明方法类型
|
||||
/// </summary>
|
||||
public enum TransparentType : int
|
||||
{
|
||||
None = 0,
|
||||
Alpha = 1,
|
||||
ColorKey = 2,
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 状态变更事件类型(实验性)
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum WindowStateEventType : int
|
||||
{
|
||||
None = 0,
|
||||
StyleChanged = 1,
|
||||
Resized = 2,
|
||||
|
||||
// 后续规格可能会有变更
|
||||
TopMostEnabled = 16 + 1 + 8,
|
||||
TopMostDisabled = 16 + 1,
|
||||
BottomMostEnabled = 32 + 1 + 8,
|
||||
BottomMostDisabled = 32 + 1,
|
||||
WallpaperModeEnabled = 64 + 1 + 8,
|
||||
WallpaperModeDisabled = 64 + 1,
|
||||
};
|
||||
|
||||
#region Native functions
|
||||
protected class LibUniWinC
|
||||
{
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||
public delegate void StringCallback([MarshalAs(UnmanagedType.LPWStr)] string returnString);
|
||||
|
||||
[UnmanagedFunctionPointer((CallingConvention.Winapi))]
|
||||
public delegate void IntCallback([MarshalAs(UnmanagedType.I4)] int value);
|
||||
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool IsActive();
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool IsTransparent();
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool IsBorderless();
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool IsTopmost();
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool IsBottommost();
|
||||
|
||||
[DllImport("LibUniWinC", CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool IsMaximized();
|
||||
|
||||
[DllImport("LibUniWinC", CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool IsFreePositioningEnabled();
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool AttachMyWindow();
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool AttachMyOwnerWindow();
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool AttachMyActiveWindow();
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool DetachWindow();
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
public static extern void Update();
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
public static extern void SetTransparent([MarshalAs(UnmanagedType.U1)] bool bEnabled);
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
public static extern void SetBorderless([MarshalAs(UnmanagedType.U1)] bool bEnabled);
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
public static extern void SetAlphaValue(float alpha);
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
public static extern void SetClickThrough([MarshalAs(UnmanagedType.U1)] bool bEnabled);
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
public static extern void SetTopmost([MarshalAs(UnmanagedType.U1)] bool bEnabled);
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
public static extern void SetBottommost([MarshalAs(UnmanagedType.U1)] bool bEnabled);
|
||||
|
||||
[DllImport("LibUniWinC", CallingConvention = CallingConvention.Winapi)]
|
||||
public static extern void SetMaximized([MarshalAs(UnmanagedType.U1)] bool bZoomed);
|
||||
|
||||
[DllImport("LibUniWinC", CallingConvention = CallingConvention.Winapi)]
|
||||
public static extern void EnableFreePositioning([MarshalAs(UnmanagedType.U1)] bool bEnabled);
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
public static extern void SetPosition(float x, float y);
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool GetPosition(out float x, out float y);
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
public static extern void SetSize(float x, float y);
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool GetSize(out float x, out float y);
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool GetClientSize(out float width, out float height);
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool GetClientRectangle(out float x, out float y, out float width, out float height);
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool RegisterDropFilesCallback([MarshalAs(UnmanagedType.FunctionPtr)] StringCallback callback);
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool UnregisterDropFilesCallback();
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool RegisterMonitorChangedCallback([MarshalAs(UnmanagedType.FunctionPtr)] IntCallback callback);
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool UnregisterMonitorChangedCallback();
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool RegisterWindowStyleChangedCallback([MarshalAs(UnmanagedType.FunctionPtr)] IntCallback callback);
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool UnregisterWindowStyleChangedCallback();
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool SetAllowDrop([MarshalAs(UnmanagedType.U1)] bool enabled);
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
public static extern int GetCurrentMonitor();
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
public static extern int GetMonitorCount();
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool GetMonitorRectangle(int index, out float x, out float y, out float width, out float height);
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
public static extern void SetCursorPosition(float x, float y);
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool GetCursorPosition(out float x, out float y);
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
public static extern int GetMouseButtons();
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
public static extern int GetModifierKeys();
|
||||
|
||||
|
||||
#region 仅适用于 Windows
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
public static extern void SetTransparentType(int type);
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
public static extern void SetKeyColor(uint colorref);
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
public static extern int GetDebugInfo();
|
||||
|
||||
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool AttachWindowHandle(IntPtr hWnd);
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
|
||||
static string[] lastDroppedFiles;
|
||||
static bool wasDropped = false;
|
||||
static bool wasMonitorChanged = false;
|
||||
static bool wasWindowStyleChanged = false;
|
||||
static WindowStateEventType windowStateEventType = WindowStateEventType.None;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
/// <summary>
|
||||
/// 获取 Unity 编辑器窗口
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <seealso href="http://baba-s.hatenablog.com/entry/2017/09/17/135018"/>
|
||||
public static EditorWindow GetGameView()
|
||||
{
|
||||
var assembly = typeof(EditorWindow).Assembly;
|
||||
var type = assembly.GetType("UnityEditor.GameView");
|
||||
var gameView = EditorWindow.GetWindow(type);
|
||||
return gameView;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// 判断窗口是否已附加且可用
|
||||
/// </summary>
|
||||
/// <value><c>true</c> 如果此实例处于活动状态;否则为 <c>false</c>。</value>
|
||||
public bool IsActive { get; private set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 判断附加窗口是否始终置顶
|
||||
/// </summary>
|
||||
public bool IsTopmost { get { return (IsActive && _isTopmost); } }
|
||||
private bool _isTopmost = false;
|
||||
|
||||
/// <summary>
|
||||
/// 判断附加窗口是否始终置底
|
||||
/// </summary>
|
||||
public bool IsBottommost { get { return (IsActive && _isBottommost); } }
|
||||
private bool _isBottommost = false;
|
||||
|
||||
/// <summary>
|
||||
/// 判断附加窗口是否透明
|
||||
/// </summary>
|
||||
public bool IsTransparent { get { return (IsActive && _isTransparent); } }
|
||||
private bool _isTransparent = false;
|
||||
|
||||
/// <summary>
|
||||
/// 判断附加窗口是否点击穿透(即不接收任何鼠标操作)
|
||||
/// </summary>
|
||||
public bool IsClickThrough { get { return (IsActive && _isClickThrough); } }
|
||||
private bool _isClickThrough = false;
|
||||
|
||||
/// <summary>
|
||||
/// 判断附加窗口是否无边框(无标题栏和边框)
|
||||
/// </summary>
|
||||
public bool IsBorderless { get { return (IsActive && _isBorderless); } }
|
||||
private bool _isBorderless = false;
|
||||
|
||||
/// <summary>
|
||||
/// 判断附加窗口是否可以自由定位(仅 macOS)
|
||||
/// </summary>
|
||||
public bool IsFreePositioningEnabled { get { return (IsActive && _isFreePositioningEnabled); } }
|
||||
private bool _isFreePositioningEnabled = false;
|
||||
|
||||
/// <summary>
|
||||
/// Windows 下的透明方法类型
|
||||
/// </summary>
|
||||
private TransparentType transparentType = TransparentType.Alpha;
|
||||
|
||||
/// <summary>
|
||||
/// 当 transparentType 为 ColorKey 时用于透明的颜色
|
||||
/// </summary>
|
||||
private Color32 keyColor = new Color32(1, 0, 1, 0);
|
||||
|
||||
|
||||
#region Constructor or destructor
|
||||
/// <summary>
|
||||
/// 窗口控制构造函数
|
||||
/// </summary>
|
||||
public UniWinCore()
|
||||
{
|
||||
IsActive = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 析构函数
|
||||
/// </summary>
|
||||
~UniWinCore()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 结束时的处理
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
// 由于最后恢复窗口状态会引起注意,所以特意不恢复,因此注释掉
|
||||
//DetachWindow();
|
||||
|
||||
// 替代 DetachWindow()
|
||||
LibUniWinC.UnregisterDropFilesCallback();
|
||||
LibUniWinC.UnregisterMonitorChangedCallback();
|
||||
LibUniWinC.UnregisterWindowStyleChangedCallback();
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Callbacks
|
||||
|
||||
/// <summary>
|
||||
/// 显示器或分辨率变化时的回调
|
||||
/// 此处的处理保持最低限度,仅设置标志
|
||||
/// </summary>
|
||||
/// <param name="monitorCount"></param>
|
||||
[MonoPInvokeCallback(typeof(LibUniWinC.IntCallback))]
|
||||
private static void _monitorChangedCallback([MarshalAs(UnmanagedType.I4)] int monitorCount)
|
||||
{
|
||||
wasMonitorChanged = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 窗口样式、最大化、最小化等调用的回调
|
||||
/// 此处的处理保持最低限度,仅设置标志
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
[MonoPInvokeCallback(typeof(LibUniWinC.IntCallback))]
|
||||
private static void _windowStyleChangedCallback([MarshalAs(UnmanagedType.I4)] int e)
|
||||
{
|
||||
wasWindowStyleChanged = true;
|
||||
windowStateEventType = (WindowStateEventType)e;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ファイル、フォルダがドロップされた時に呼ばれるコールバック
|
||||
/// 文字列を配列に直すことと、フラグを立てるまで行う
|
||||
/// </summary>
|
||||
/// <param name="paths"></param>
|
||||
[MonoPInvokeCallback(typeof(LibUniWinC.StringCallback))]
|
||||
private static void _dropFilesCallback([MarshalAs(UnmanagedType.LPWStr)] string paths)
|
||||
{
|
||||
// 将以 LF 分隔的字符串分割为路径数组
|
||||
//char[] delimiters = { '\n', '\0' };
|
||||
//string[] files = paths.Split(delimiters).Where(s => s != "").ToArray();
|
||||
string[] files = parsePaths(paths);
|
||||
|
||||
if (files.Length > 0)
|
||||
{
|
||||
lastDroppedFiles = new string[files.Length];
|
||||
files.CopyTo(lastDroppedFiles, 0);
|
||||
|
||||
wasDropped = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将双引号包围、LF(或null)分隔的字符串转换为数组并返回
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
/// <returns></returns>
|
||||
internal static string[] parsePaths(string text)
|
||||
{
|
||||
System.Collections.Generic.List<string> list = new System.Collections.Generic.List<string>();
|
||||
bool inEscaped = false;
|
||||
int len = text.Length;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
char c = text[i];
|
||||
if (c == '"')
|
||||
{
|
||||
if (inEscaped)
|
||||
{
|
||||
if (((i + 1) < len) && text[i + 1] == '"')
|
||||
{
|
||||
i++;
|
||||
sb.Append(c); // 连续双引号视为一个双引号
|
||||
continue;
|
||||
}
|
||||
}
|
||||
inEscaped = !inEscaped; // 非连续则切换是否在引号内
|
||||
}
|
||||
else if (c == '\n')
|
||||
{
|
||||
if (inEscaped)
|
||||
{
|
||||
// 如果在引号内,则作为路径的一部分
|
||||
sb.Append(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果不在引号内,则作为分隔符,移到下一个路径
|
||||
if (sb.Length > 0)
|
||||
{
|
||||
list.Add(sb.ToString());
|
||||
//sb.Clear(); // for .NET 4 or later
|
||||
sb.Length = 0; // for .NET 2
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (c == '\0')
|
||||
{
|
||||
// 空字符始终作为分隔符,移到下一个路径
|
||||
if (sb.Length > 0)
|
||||
{
|
||||
list.Add(sb.ToString());
|
||||
//sb.Clear(); // for .NET 4 or later
|
||||
sb.Length = 0; // for .NET 2
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(c);
|
||||
}
|
||||
}
|
||||
if (sb.Length > 0)
|
||||
{
|
||||
list.Add(sb.ToString());
|
||||
}
|
||||
|
||||
// 移除空字符串元素
|
||||
list.RemoveAll(v => v.Length == 0);
|
||||
return list.ToArray();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Find, attach or detach
|
||||
|
||||
/// <summary>
|
||||
/// 将窗口状态恢复至最初并从操作对象中解除
|
||||
/// </summary>
|
||||
public void DetachWindow()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
// エディタの場合、ウィンドウスタイルでは常に最前面と得られていない可能性があるため、
|
||||
// 最前面ではないのが本来と決め打ちで、デタッチ時無効化する
|
||||
EnableTopmost(false);
|
||||
#endif
|
||||
LibUniWinC.DetachWindow();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找自己的窗口(如果游戏视图是独立窗口则查找它)并作为操作对象
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool AttachMyWindow()
|
||||
{
|
||||
#if UNITY_EDITOR_WIN
|
||||
// 似乎没有可靠的方法获取游戏视图,因此给予焦点后立即获取活动窗口
|
||||
var gameView = GetGameView();
|
||||
if (gameView)
|
||||
{
|
||||
gameView.Focus();
|
||||
LibUniWinC.AttachMyActiveWindow();
|
||||
}
|
||||
#else
|
||||
LibUniWinC.AttachMyWindow();
|
||||
#endif
|
||||
// 添加事件处理程序
|
||||
LibUniWinC.RegisterDropFilesCallback(_dropFilesCallback);
|
||||
LibUniWinC.RegisterMonitorChangedCallback(_monitorChangedCallback);
|
||||
LibUniWinC.RegisterWindowStyleChangedCallback(_windowStyleChangedCallback);
|
||||
|
||||
IsActive = LibUniWinC.IsActive();
|
||||
return IsActive;
|
||||
}
|
||||
|
||||
public bool AttachWindowHandle(IntPtr hWnd)
|
||||
{
|
||||
LibUniWinC.AttachWindowHandle(hWnd);
|
||||
IsActive = LibUniWinC.IsActive();
|
||||
return IsActive;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 选择自己进程中当前活动的窗口
|
||||
/// 编辑器情况下,窗口会关闭或停靠,因此在聚焦时调用
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool AttachMyActiveWindow()
|
||||
{
|
||||
LibUniWinC.AttachMyActiveWindow();
|
||||
IsActive = LibUniWinC.IsActive();
|
||||
return IsActive;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region About window status
|
||||
/// <summary>
|
||||
/// 定期调用以维持窗口样式
|
||||
/// </summary>
|
||||
public void Update()
|
||||
{
|
||||
LibUniWinC.Update();
|
||||
}
|
||||
|
||||
string GetDebubgWindowSizeInfo()
|
||||
{
|
||||
float x, y, cx, cy;
|
||||
LibUniWinC.GetSize(out x, out y);
|
||||
LibUniWinC.GetClientSize(out cx, out cy);
|
||||
return $"W:{x},H:{y} CW:{cx},CH:{cy}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置/取消透明
|
||||
/// </summary>
|
||||
/// <param name="isTransparent"></param>
|
||||
public void EnableTransparent(bool isTransparent)
|
||||
{
|
||||
// 编辑器无法透明或边框与正常不同,因此跳过
|
||||
#if !UNITY_EDITOR
|
||||
LibUniWinC.SetTransparent(isTransparent);
|
||||
LibUniWinC.SetBorderless(isTransparent);
|
||||
#endif
|
||||
this._isTransparent = isTransparent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置窗口透明度
|
||||
/// </summary>
|
||||
/// <param name="alpha">0.0 - 1.0</param>
|
||||
public void SetAlphaValue(float alpha)
|
||||
{
|
||||
// Windows 编辑器下,一旦半透明化后显示不会更新,因此禁用。Mac 则没问题
|
||||
#if !UNITY_EDITOR_WIN
|
||||
LibUniWinC.SetAlphaValue(alpha);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置窗口 Z 顺序(是否置顶)。
|
||||
/// </summary>
|
||||
/// <param name="isTopmost">如果设为 <c>true</c> 则置顶。</param>
|
||||
public void EnableTopmost(bool isTopmost)
|
||||
{
|
||||
LibUniWinC.SetTopmost(isTopmost);
|
||||
this._isTopmost = isTopmost;
|
||||
this._isBottommost = false; // 互斥
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置窗口 Z 顺序(是否置底)。
|
||||
/// </summary>
|
||||
/// <param name="isBottommost">如果设为 <c>true</c> 则置底。</param>
|
||||
public void EnableBottommost(bool isBottommost)
|
||||
{
|
||||
LibUniWinC.SetBottommost(isBottommost);
|
||||
this._isBottommost = isBottommost;
|
||||
this._isTopmost = false; // 互斥
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置/取消点击穿透
|
||||
/// </summary>
|
||||
/// <param name="isThrough"></param>
|
||||
public void EnableClickThrough(bool isThrough)
|
||||
{
|
||||
// 编辑器下点击穿透可能导致无法操作,因此跳过
|
||||
#if !UNITY_EDITOR
|
||||
LibUniWinC.SetClickThrough(isThrough);
|
||||
#endif
|
||||
this._isClickThrough = isThrough;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 最大化窗口(Mac 上为缩放)
|
||||
/// 最大化后可能还会调整大小,目前可能无法可靠工作
|
||||
/// </summary>
|
||||
public void SetZoomed(bool isZoomed)
|
||||
{
|
||||
LibUniWinC.SetMaximized(isZoomed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取窗口是否已最大化(Mac 上为缩放)
|
||||
/// 最大化后可能还会调整大小,目前可能无法可靠工作
|
||||
/// </summary>
|
||||
public bool GetZoomed()
|
||||
{
|
||||
return LibUniWinC.IsMaximized();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置窗口位置。
|
||||
/// </summary>
|
||||
/// <param name="position">位置。</param>
|
||||
public void SetWindowPosition(Vector2 position)
|
||||
{
|
||||
LibUniWinC.SetPosition(position.x, position.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取窗口位置。
|
||||
/// </summary>
|
||||
/// <returns>位置。</returns>
|
||||
public Vector2 GetWindowPosition()
|
||||
{
|
||||
Vector2 pos = Vector2.zero;
|
||||
LibUniWinC.GetPosition(out pos.x, out pos.y);
|
||||
return pos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置窗口大小。
|
||||
/// </summary>
|
||||
/// <param name="size">x 为宽度,y 为高度</param>
|
||||
public void SetWindowSize(Vector2 size)
|
||||
{
|
||||
LibUniWinC.SetSize(size.x, size.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取窗口大小。
|
||||
/// </summary>
|
||||
/// <returns>x 为宽度,y 为高度</returns>
|
||||
public Vector2 GetWindowSize()
|
||||
{
|
||||
Vector2 size = Vector2.zero;
|
||||
LibUniWinC.GetSize(out size.x, out size.y);
|
||||
return size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取客户区大小。
|
||||
/// </summary>
|
||||
/// <returns>x 为宽度,y 为高度</returns>
|
||||
public Vector2 GetClientSize()
|
||||
{
|
||||
Vector2 size = Vector2.zero;
|
||||
LibUniWinC.GetClientSize(out size.x, out size.y);
|
||||
return size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取客户区矩形。
|
||||
/// </summary>
|
||||
/// <returns>x 为宽度,y 为高度</returns>
|
||||
public Rect GetClientRectangle()
|
||||
{
|
||||
Vector2 pos = Vector2.zero;
|
||||
Vector2 size = Vector2.zero;
|
||||
LibUniWinC.GetClientRectangle(out pos.x, out pos.y, out size.x, out size.y);
|
||||
return new Rect(pos.x, pos.y, size.x, size.y);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region File opening
|
||||
public void SetAllowDrop(bool enabled)
|
||||
{
|
||||
LibUniWinC.SetAllowDrop(enabled);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event observers
|
||||
|
||||
/// <summary>
|
||||
/// 检查文件拖放并取消拖放标志
|
||||
/// </summary>
|
||||
/// <param name="files"></param>
|
||||
/// <returns>如果文件被拖放则返回 true</returns>
|
||||
public bool ObserveDroppedFiles(out string[] files)
|
||||
{
|
||||
files = lastDroppedFiles;
|
||||
|
||||
if (!wasDropped || files == null) return false;
|
||||
|
||||
wasDropped = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查显示器数量或分辨率变化,并取消标志
|
||||
/// </summary>
|
||||
/// <returns>如果已变化则返回 true</returns>
|
||||
public bool ObserveMonitorChanged()
|
||||
{
|
||||
if (!wasMonitorChanged) return false;
|
||||
|
||||
wasMonitorChanged = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查窗口样式是否已变更,并取消标志
|
||||
/// </summary>
|
||||
/// <returns>如果窗口样式已变更则返回 true</returns>
|
||||
public bool ObserveWindowStyleChanged()
|
||||
{
|
||||
if (!wasWindowStyleChanged) return false;
|
||||
|
||||
windowStateEventType = WindowStateEventType.None;
|
||||
wasWindowStyleChanged = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查窗口样式是否已变更,并取消标志
|
||||
/// </summary>
|
||||
/// <returns>如果窗口样式已变更则返回 true</returns>
|
||||
public bool ObserveWindowStyleChanged(out WindowStateEventType type)
|
||||
{
|
||||
if (!wasWindowStyleChanged)
|
||||
{
|
||||
type = WindowStateEventType.None;
|
||||
return false;
|
||||
}
|
||||
|
||||
type = windowStateEventType;
|
||||
windowStateEventType = WindowStateEventType.None;
|
||||
wasWindowStyleChanged = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region About mouse cursor
|
||||
/// <summary>
|
||||
/// 设置鼠标指针位置。
|
||||
/// </summary>
|
||||
/// <param name="position">位置。</param>
|
||||
public static void SetCursorPosition(Vector2 position)
|
||||
{
|
||||
LibUniWinC.SetCursorPosition(position.x, position.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取鼠标指针位置。
|
||||
/// </summary>
|
||||
/// <returns>位置。</returns>
|
||||
public static Vector2 GetCursorPosition()
|
||||
{
|
||||
Vector2 pos = Vector2.zero;
|
||||
LibUniWinC.GetCursorPosition(out pos.x, out pos.y);
|
||||
return pos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get pressed mouse buttons.
|
||||
/// </summary>
|
||||
/// <returns>Bit flags of pressed buttons</returns>
|
||||
public static int GetMouseButtons()
|
||||
{
|
||||
return LibUniWinC.GetMouseButtons();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取按下的修饰键。
|
||||
/// </summary>
|
||||
/// <returns>按下键的位标志</returns>
|
||||
public static int GetModifierKeys()
|
||||
{
|
||||
return LibUniWinC.GetModifierKeys();
|
||||
}
|
||||
|
||||
// 未实现
|
||||
public static bool GetCursorVisible()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region for Windows only
|
||||
/// <summary>
|
||||
/// 指定透明方法(仅 Windows 支持)
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
public void SetTransparentType(TransparentType type)
|
||||
{
|
||||
LibUniWinC.SetTransparentType((Int32)type);
|
||||
transparentType = type;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 单色透明时指定透明色(仅 Windows 支持)
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
public void SetKeyColor(Color32 color)
|
||||
{
|
||||
LibUniWinC.SetKeyColor((UInt32)(color.b * 0x10000 + color.g * 0x100 + color.r));
|
||||
keyColor = color;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region for macOS only
|
||||
/// <summary>
|
||||
/// 设置/取消窗口的自由配置(仅 macOS 支持)
|
||||
/// </summary>
|
||||
/// <param name="enabled"></param>
|
||||
public void EnableFreePositioning(bool enabled)
|
||||
{
|
||||
LibUniWinC.EnableFreePositioning(enabled);
|
||||
_isFreePositioningEnabled = LibUniWinC.IsFreePositioningEnabled();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region About monitors
|
||||
/// <summary>
|
||||
/// 获取窗口所在显示器的索引
|
||||
/// </summary>
|
||||
/// <returns>显示器索引</returns>
|
||||
public int GetCurrentMonitor()
|
||||
{
|
||||
return LibUniWinC.GetCurrentMonitor();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取已连接显示器的数量
|
||||
/// </summary>
|
||||
/// <returns>数量</returns>
|
||||
public static int GetMonitorCount()
|
||||
{
|
||||
return LibUniWinC.GetMonitorCount();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取显示器的位置和大小
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <param name="position"></param>
|
||||
/// <param name="size"></param>
|
||||
/// <returns></returns>
|
||||
public static bool GetMonitorRectangle(int index, out Vector2 position, out Vector2 size)
|
||||
{
|
||||
return LibUniWinC.GetMonitorRectangle(index, out position.x, out position.y, out size.x, out size.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将窗口适配到指定显示器
|
||||
/// </summary>
|
||||
/// <param name="monitorIndex"></param>
|
||||
/// <returns></returns>
|
||||
public bool FitToMonitor(int monitorIndex)
|
||||
{
|
||||
float dx, dy, dw, dh;
|
||||
if (LibUniWinC.GetMonitorRectangle(monitorIndex, out dx, out dy, out dw, out dh))
|
||||
{
|
||||
// 如果处于最大化状态则先恢复
|
||||
if (LibUniWinC.IsMaximized()) LibUniWinC.SetMaximized(false);
|
||||
|
||||
// 指定显示器的中心坐标
|
||||
float cx = dx + (dw / 2);
|
||||
float cy = dy + (dh / 2);
|
||||
|
||||
// 将窗口中心移动到指定显示器中心
|
||||
float ww, wh;
|
||||
LibUniWinC.GetSize(out ww, out wh);
|
||||
float wx = cx - (ww / 2);
|
||||
float wy = cy - (wh / 2);
|
||||
LibUniWinC.SetPosition(wx, wy);
|
||||
|
||||
// 最大化
|
||||
LibUniWinC.SetMaximized(true);
|
||||
|
||||
//Debug.Log(String.Format("显示器 {4} : {0},{1} - {2},{3}", dx, dy, dw, dh, monitorIndex));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 打印显示器列表
|
||||
/// </summary>
|
||||
[Obsolete]
|
||||
public static void DebugMonitorInfo()
|
||||
{
|
||||
int monitors = LibUniWinC.GetMonitorCount();
|
||||
|
||||
int currentMonitorIndex = LibUniWinC.GetCurrentMonitor();
|
||||
|
||||
string message = "当前显示器: " + currentMonitorIndex + "\r\n";
|
||||
|
||||
for (int i = 0; i < monitors; i++)
|
||||
{
|
||||
float x, y, w, h;
|
||||
bool result = LibUniWinC.GetMonitorRectangle(i, out x, out y, out w, out h);
|
||||
message += String.Format(
|
||||
"显示器 {0}: X:{1}, Y:{2} - W:{3}, H:{4}\r\n",
|
||||
i, x, y, w, h
|
||||
);
|
||||
}
|
||||
Debug.Log(message);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取用于调试的信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Obsolete]
|
||||
public static int GetDebugInfo()
|
||||
{
|
||||
return LibUniWinC.GetDebugInfo();
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4930552cf3596b040954b14d8b7c47e6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d327b245537480646bd85e511002d6ce
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* UniWindowDragMove.cs
|
||||
*
|
||||
* 作者: Kirurobo http://twitter.com/kirurobo
|
||||
* 许可证: MIT
|
||||
*/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
#elif ENABLE_INPUT_SYSTEM
|
||||
using UnityEngine.InputSystem;
|
||||
#endif
|
||||
|
||||
namespace Kirurobo
|
||||
{
|
||||
public class UniWindowMoveHandle : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler, IPointerUpHandler
|
||||
{
|
||||
private UniWindowController _uniwinc;
|
||||
|
||||
/// <summary>
|
||||
/// 窗口最大化时是否禁用移动
|
||||
/// </summary>
|
||||
[Tooltip("窗口已最大化(缩放)时禁用拖拽移动。")]
|
||||
public bool disableOnZoomed = true;
|
||||
|
||||
/// <summary>
|
||||
/// 拖动中则为 true
|
||||
/// </summary>
|
||||
public bool IsDragging
|
||||
{
|
||||
get { return _isDragging; }
|
||||
}
|
||||
private bool _isDragging = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否进行拖动
|
||||
/// </summary>
|
||||
private bool IsEnabled
|
||||
{
|
||||
get { return enabled && (!disableOnZoomed || !IsZoomed); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否适配显示器或最大化
|
||||
/// </summary>
|
||||
private bool IsZoomed
|
||||
{
|
||||
get { return (_uniwinc && (_uniwinc.shouldFitMonitor || _uniwinc.isZoomed)); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 记录拖动前自动命中测试是否启用
|
||||
/// </summary>
|
||||
private bool _isHitTestEnabled;
|
||||
|
||||
/// <summary>
|
||||
/// 拖动开始时窗口内坐标[像素]
|
||||
/// </summary>
|
||||
private Vector2 _dragStartedPosition;
|
||||
|
||||
// 首次帧更新前调用 Start
|
||||
void Start()
|
||||
{
|
||||
// 获取场景中的 UniWindowController
|
||||
_uniwinc = GameObject.FindAnyObjectByType<UniWindowController>();
|
||||
if (_uniwinc) _isHitTestEnabled = _uniwinc.isHitTestEnabled;
|
||||
|
||||
//// 下面的代码似乎不需要,所以注释掉以免擅自更改
|
||||
//Input.simulateMouseWithTouches = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 拖动开始时的处理
|
||||
/// </summary>
|
||||
public void OnBeginDrag(PointerEventData eventData)
|
||||
{
|
||||
if (!IsEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 仅通过鼠标左键拖动
|
||||
if (eventData.button != PointerEventData.InputButton.Left) return;
|
||||
|
||||
// Mac 上行为会有所不同
|
||||
// 实际上仅在 Retina 支持启用时,但 eventData.position 的坐标系与窗口坐标系的缩放会不一致
|
||||
#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
|
||||
_dragStartedPosition = _uniwinc.windowPosition - _uniwinc.cursorPosition;
|
||||
#else
|
||||
_dragStartedPosition = eventData.position;
|
||||
#endif
|
||||
|
||||
// 如果 _isDragging 为 false,则判断即将开始拖动
|
||||
if (!_isDragging)
|
||||
{
|
||||
// 拖动期间禁用命中测试
|
||||
_isHitTestEnabled = _uniwinc.isHitTestEnabled;
|
||||
_uniwinc.isHitTestEnabled = false;
|
||||
_uniwinc.isClickThrough = false;
|
||||
}
|
||||
|
||||
_isDragging = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 拖动结束时的处理
|
||||
/// </summary>
|
||||
public void OnEndDrag(PointerEventData eventData)
|
||||
{
|
||||
EndDragging();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 鼠标抬起时也视为拖动结束
|
||||
/// </summary>
|
||||
/// <param name="eventData"></param>
|
||||
public void OnPointerUp(PointerEventData eventData)
|
||||
{
|
||||
EndDragging();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 结束拖动
|
||||
/// </summary>
|
||||
private void EndDragging()
|
||||
{
|
||||
if (_isDragging)
|
||||
{
|
||||
_uniwinc.isHitTestEnabled = _isHitTestEnabled;
|
||||
}
|
||||
_isDragging = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 非最大化时,通过鼠标拖动移动窗口
|
||||
/// </summary>
|
||||
public void OnDrag(PointerEventData eventData)
|
||||
{
|
||||
if (!_uniwinc || !_isDragging) return;
|
||||
|
||||
// 如果拖动移动已被禁用,则结束拖动
|
||||
if (!IsEnabled)
|
||||
{
|
||||
EndDragging();
|
||||
return;
|
||||
}
|
||||
|
||||
// // 如果鼠标左键未按下,则结束拖动
|
||||
// if (eventData.button != PointerEventData.InputButton.Left) return;
|
||||
|
||||
// [Shift]、[Ctrl]、[Alt]、[Command] 键按下期间不视为拖动
|
||||
var modifiers = UniWindowController.GetModifierKeys();
|
||||
if (modifiers != UniWindowController.ModifierKey.None) return;
|
||||
|
||||
// 如果鼠标按钮已松开,则结束拖动
|
||||
var buttons = UniWindowController.GetMouseButtons();
|
||||
if ((buttons & UniWindowController.MouseButton.Left) == UniWindowController.MouseButton.None) {
|
||||
EndDragging();
|
||||
return;
|
||||
}
|
||||
// #if ENABLE_LEGACY_INPUT_MANAGER
|
||||
// // 在 Mac 上,如果在多显示器之间移动,EventSystem 的 OnEndDrag 可能无法正确调用,因此始终监控鼠标按钮
|
||||
// if (!Input.Mouse.Button(0).IsPressed) {
|
||||
// EndDragging();
|
||||
// return;
|
||||
// }
|
||||
// if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)
|
||||
// || Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl)
|
||||
// || Input.GetKey(KeyCode.LeftAlt) || Input.GetKey(KeyCode.RightAlt)) return;
|
||||
// #elif ENABLE_INPUT_SYSTEM
|
||||
// // 在 Mac 上,如果在多显示器之间移动,EventSystem 的 OnEndDrag 可能无法正确调用,因此始终监控鼠标按钮
|
||||
// if (!Mouse.current.leftButton.isPressed) {
|
||||
// EndDragging();
|
||||
// return;
|
||||
// }
|
||||
// if (Keyboard.current[Key.LeftShift].isPressed || Keyboard.current[Key.RightShift].isPressed
|
||||
// || Keyboard.current[Key.LeftCtrl].isPressed || Keyboard.current[Key.RightCtrl].isPressed
|
||||
// || Keyboard.current[Key.LeftAlt].isPressed || Keyboard.current[Key.RightAlt].isPressed) return;
|
||||
// #endif
|
||||
|
||||
// 如果是全屏则不移动窗口
|
||||
// 在编辑器中可能会变为 true,因此仅在非编辑器环境下确认
|
||||
#if !UNITY_EDITOR
|
||||
if (Screen.fullScreen)
|
||||
{
|
||||
EndDragging();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
|
||||
// 在 Mac 上,通过原生插件获取/设置光标位置
|
||||
_uniwinc.windowPosition = _uniwinc.cursorPosition + _dragStartedPosition;
|
||||
//Debug.Log("Drag start: " + _dragStartedPosition);
|
||||
#else
|
||||
// 在 Windows 上,为支持触控操作而使用 eventData.position
|
||||
// 将窗口移动与起始位置一致的屏幕位置偏移量
|
||||
_uniwinc.windowPosition += eventData.position - _dragStartedPosition;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd641513c2924f7488734c8cac43310f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 326ddcba926f5e849bde9a0e0fb87ee1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,35 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Kirurobo {
|
||||
/// <summary>
|
||||
/// 使附加的对象以恒定速度进行偏航旋转
|
||||
/// </summary>
|
||||
public class AutoRotator : MonoBehaviour {
|
||||
/// <summary>
|
||||
/// 旋转速度 [度/秒]
|
||||
/// </summary>
|
||||
public float angularVelocity = 90f;
|
||||
|
||||
/// <summary>
|
||||
/// 旋转轴(偏航旋转,方向向上)
|
||||
/// </summary>
|
||||
Vector3 rotationAxis = Vector3.up;
|
||||
|
||||
/// <summary>
|
||||
/// 初始姿态
|
||||
/// </summary>
|
||||
Quaternion initialLocalRotation;
|
||||
|
||||
// 用于初始化
|
||||
void Start () {
|
||||
// 记录初始姿态
|
||||
initialLocalRotation = transform.localRotation;
|
||||
}
|
||||
|
||||
// 每帧调用 Update
|
||||
void Update () {
|
||||
var rotation = Quaternion.Euler(0f, Time.time * angularVelocity, 0f);
|
||||
transform.localRotation = initialLocalRotation * rotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f985bf036f5416a45b9dd4e31bc85075
|
||||
timeCreated: 1545989238
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 452 B |
@@ -0,0 +1,88 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2b5d2690e20d6584e909fd2bdfd93579
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
externalObjects: {}
|
||||
serializedVersion: 9
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -100
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: -1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 0
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 8, y: 8, z: 8, w: 8}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 2
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 533df9bf30503d349b91598d325d5fcd
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 451 B |
@@ -0,0 +1,88 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4713fc586389c694f9e384c7f3a02289
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
externalObjects: {}
|
||||
serializedVersion: 9
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -100
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: -1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 0
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 8, y: 8, z: 8, w: 8}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 2
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 47fdf1b4c9bb7764d916b229e9a2d98c
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
#elif ENABLE_INPUT_SYSTEM
|
||||
using UnityEngine.InputSystem;
|
||||
#endif
|
||||
|
||||
namespace Kirurobo {
|
||||
|
||||
/// <summary>
|
||||
/// 为快速兼容 Legacy InputManager 和 InputSystem 而准备的类
|
||||
/// </summary>
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
public class InputModuleProxy : UnityEngine.EventSystems.StandaloneInputModule
|
||||
{
|
||||
}
|
||||
#elif ENABLE_INPUT_SYSTEM
|
||||
public class InputModuleProxy : UnityEngine.InputSystem.UI.InputSystemUIInputModule
|
||||
{
|
||||
}
|
||||
#else
|
||||
public class InputModuleProxy
|
||||
{
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce6b387a66b0e654d9eb8712d70fff48
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* UniWindowController 的示例脚本
|
||||
*
|
||||
* 作者: Kirurobo http://twitter.com/kirurobo
|
||||
* 许可证: MIT
|
||||
*/
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
// Don't use InputSystem in this script to prevent TouchPhase duplication
|
||||
#elif ENABLE_INPUT_SYSTEM
|
||||
using UnityEngine.InputSystem;
|
||||
#endif
|
||||
|
||||
namespace Kirurobo {
|
||||
/// <summary>
|
||||
/// Input System と Input Manager の違いを吸収するためのプロキシ
|
||||
/// </summary>
|
||||
public class InputProxy
|
||||
{
|
||||
public static Vector3 mousePosition {
|
||||
get {
|
||||
return GetMousePosition();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Input System の利用に合わせてキーアップを取得
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static bool GetKeyUp(String key)
|
||||
{
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetKeyUp(key);
|
||||
#elif ENABLE_INPUT_SYSTEM
|
||||
// 簡易的な実装。keyが1文字で、かつアルファベットか数字に対応
|
||||
// 1文字以外は escape, space のみ対応
|
||||
if (key.Length == 1) {
|
||||
Key k = Key.None;
|
||||
char c = key[0];
|
||||
if (c >= '0' && c <= '9') {
|
||||
// 数字の場合はDigit0~Digit9とNumpad0~Numpad9の両方に反応
|
||||
k = (Key)Enum.ToObject(typeof(Key), (int)Key.Numpad0 + (int)(c - '0'));
|
||||
if (Keyboard.current[k].wasReleasedThisFrame) return true;
|
||||
|
||||
// Digitの場合はDigit0の値が最大
|
||||
k = (Key)Enum.ToObject(typeof(Key), (int)Key.Digit1 + (int)((c == '0' ? 9 : c - '1')));
|
||||
if (Keyboard.current[k].wasReleasedThisFrame) return true;
|
||||
}
|
||||
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
|
||||
// アルファベットの場合は大文字・小文字どちらでも可とする
|
||||
k = (Key)Enum.ToObject(typeof(Key), (int)Key.A + (int)(Char.ToUpper(c) - 'A'));
|
||||
if (Keyboard.current[k].wasReleasedThisFrame) return true;
|
||||
}
|
||||
} else if (key == "escape") {
|
||||
return Keyboard.current.escapeKey.wasReleasedThisFrame;
|
||||
} else if (key == "space") {
|
||||
return Keyboard.current.spaceKey.wasReleasedThisFrame;
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Input System の利用に合わせてマウス座標を取得
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static Vector3 GetMousePosition()
|
||||
{
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.mousePosition;
|
||||
#elif ENABLE_INPUT_SYSTEM
|
||||
return Mouse.current.position.ReadValue();
|
||||
#else
|
||||
return Vector3.zero;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断鼠标按钮当前是否被按下
|
||||
/// </summary>
|
||||
/// <param name="button"></param>
|
||||
/// <returns></returns>
|
||||
public static bool GetMouseButton(int button)
|
||||
{
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetMouseButton(button);
|
||||
#elif ENABLE_INPUT_SYSTEM
|
||||
if (button == 0) return Mouse.current.leftButton.isPressed;
|
||||
if (button == 1) return Mouse.current.rightButton.isPressed;
|
||||
if (button == 2) return Mouse.current.middleButton.isPressed;
|
||||
return false;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// このフレームでマウスボタンが押されたか判定
|
||||
/// </summary>
|
||||
/// <param name="button"></param>
|
||||
/// <returns></returns>
|
||||
public static bool GetMouseButtonDown(int button)
|
||||
{
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetMouseButtonDown(button);
|
||||
#elif ENABLE_INPUT_SYSTEM
|
||||
if (button == 0) return Mouse.current.leftButton.wasPressedThisFrame;
|
||||
if (button == 1) return Mouse.current.rightButton.wasPressedThisFrame;
|
||||
if (button == 2) return Mouse.current.middleButton.wasPressedThisFrame;
|
||||
return false;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断本帧是否松开了鼠标按钮
|
||||
/// </summary>
|
||||
/// <param name="button"></param>
|
||||
/// <returns></returns>
|
||||
public static bool GetMouseButtonUp(int button) {
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetMouseButtonUp(button);
|
||||
#elif ENABLE_INPUT_SYSTEM
|
||||
if (button == 0) return Mouse.current.leftButton.wasReleasedThisFrame;
|
||||
if (button == 1) return Mouse.current.rightButton.wasReleasedThisFrame;
|
||||
if (button == 2) return Mouse.current.middleButton.wasReleasedThisFrame;
|
||||
return false;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 93a3055c4733041a1a83f6c90996f3ee
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* ModelController
|
||||
*
|
||||
* 旋转、平移和缩放对象
|
||||
*
|
||||
* 作者: Kirurobo http://twitter.com/kirurobo
|
||||
* 许可证: MIT
|
||||
*/
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Kirurobo
|
||||
{
|
||||
public class ModelController : MonoBehaviour
|
||||
{
|
||||
[Flags]
|
||||
public enum RotationAxes : int
|
||||
{
|
||||
None = 0,
|
||||
Pitch = 1,
|
||||
Yaw = 2,
|
||||
PitchAndYaw = 3
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum DragState
|
||||
{
|
||||
None,
|
||||
Rotating,
|
||||
Translating,
|
||||
}
|
||||
|
||||
public RotationAxes axes = RotationAxes.PitchAndYaw;
|
||||
public float yawSensitivity = 1f;
|
||||
public float pitchSensitvity = 1f;
|
||||
public float scaleSensitivity = 0.5f;
|
||||
|
||||
public Vector2 minimumAngles = new Vector2(-90f, -360f);
|
||||
public Vector2 maximumAngles = new Vector2(90f, 360f);
|
||||
|
||||
[Tooltip("Restrict to move out from screen")]
|
||||
public bool confineTranslation = true; // 並進移動をウィンドウ(Screen)の範囲に制限するか
|
||||
|
||||
[Tooltip("Default is the parent transform")]
|
||||
public Transform centerTransform; // 回転中心
|
||||
|
||||
[Tooltip("Default is the main camera")]
|
||||
public Camera currentCamera;
|
||||
|
||||
internal GameObject centerObject = null; // 当未指定旋转中心Transform时创建的对象
|
||||
|
||||
internal Vector3 rotation;
|
||||
internal Vector3 translation;
|
||||
internal Vector3 lastMousePosition; // 上一帧的鼠标坐标
|
||||
internal DragState dragState; // 拖动时根据开始时的按钮设置对应状态
|
||||
|
||||
internal Vector3 relativePosition;
|
||||
internal Quaternion relativeRotation;
|
||||
internal Vector3 originalLocalScale;
|
||||
internal float zoom;
|
||||
|
||||
|
||||
void Start()
|
||||
{
|
||||
Initialize();
|
||||
SetupTransform();
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
// 回転中心を独自に作成していれば、削除
|
||||
if (centerObject) GameObject.Destroy(centerObject);
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (!currentCamera.isActiveAndEnabled) return;
|
||||
{
|
||||
HandleMouse();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 必要なオブジェクトを取得・準備
|
||||
/// </summary>
|
||||
internal void Initialize()
|
||||
{
|
||||
if (!centerTransform)
|
||||
{
|
||||
centerTransform = this.transform.parent;
|
||||
if (!centerTransform || centerTransform == this.transform)
|
||||
{
|
||||
centerObject = new GameObject();
|
||||
centerTransform = centerObject.transform;
|
||||
centerTransform.position = Vector3.zero;
|
||||
}
|
||||
}
|
||||
|
||||
if (!currentCamera)
|
||||
{
|
||||
currentCamera = Camera.main;
|
||||
}
|
||||
|
||||
lastMousePosition = InputProxy.mousePosition;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初期位置・姿勢の設定
|
||||
/// 対象となるオブジェクトがそろった後で実行する
|
||||
/// </summary>
|
||||
internal void SetupTransform()
|
||||
{
|
||||
relativePosition = transform.position- centerTransform.position; // 从对象到中心坐标的向量
|
||||
relativeRotation = transform.rotation * Quaternion.Inverse(centerTransform.rotation);
|
||||
originalLocalScale = transform.localScale;
|
||||
|
||||
ResetTransform();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset rotation and translation.
|
||||
/// </summary>
|
||||
public void ResetTransform()
|
||||
{
|
||||
rotation = relativeRotation.eulerAngles;
|
||||
translation = relativePosition;
|
||||
zoom = 0f;
|
||||
|
||||
UpdateTransform();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 应用旋转和平移
|
||||
/// </summary>
|
||||
internal void UpdateTransform()
|
||||
{
|
||||
Quaternion rot = Quaternion.Euler(rotation);
|
||||
transform.rotation = rot;
|
||||
transform.position = centerTransform.position + translation;
|
||||
|
||||
transform.localScale = originalLocalScale * Mathf.Pow(10f, zoom);
|
||||
}
|
||||
|
||||
internal virtual void HandleMouse()
|
||||
{
|
||||
Vector3 mousePos = InputProxy.mousePosition;
|
||||
|
||||
if (InputProxy.GetMouseButtonDown(0))
|
||||
{
|
||||
// 左键(0)拖动时进行平移
|
||||
if (dragState == DragState.None && IsHit(mousePos))
|
||||
{
|
||||
dragState = DragState.Translating;
|
||||
|
||||
// 限制在屏幕范围内
|
||||
if (confineTranslation)
|
||||
{
|
||||
Vector3 screenMax = new Vector3(Screen.width, Screen.height);
|
||||
mousePos = Vector3.Max(Vector3.Min(mousePos, screenMax), Vector3.zero);
|
||||
}
|
||||
|
||||
lastMousePosition = mousePos; // ドラッグ開始時にはリセット
|
||||
}
|
||||
}
|
||||
else if (InputProxy.GetMouseButtonDown(1))
|
||||
{
|
||||
// 右ボタン(1)ドラッグでは回転を行う
|
||||
if (dragState == DragState.None && IsHit(mousePos))
|
||||
{
|
||||
dragState = DragState.Rotating;
|
||||
lastMousePosition = mousePos; // ドラッグ開始時にはリセット
|
||||
}
|
||||
}
|
||||
|
||||
// 通过拖动旋转
|
||||
if (dragState == DragState.Rotating)
|
||||
{
|
||||
// 仅在按下按钮时操作
|
||||
if (InputProxy.GetMouseButton(1))
|
||||
{
|
||||
// 通过拖动旋转
|
||||
if ((axes & RotationAxes.Yaw) > RotationAxes.None)
|
||||
{
|
||||
rotation.y -= (mousePos.x - lastMousePosition.x) * 360f / Screen.width * yawSensitivity;
|
||||
rotation.y = ClampAngle(rotation.y, minimumAngles.y, maximumAngles.y);
|
||||
}
|
||||
|
||||
if ((axes & RotationAxes.Pitch) > RotationAxes.None)
|
||||
{
|
||||
rotation.x += (mousePos.y - lastMousePosition.y) * 360f / Screen.height * pitchSensitvity;
|
||||
rotation.x = ClampAngle(rotation.x, minimumAngles.x, maximumAngles.x);
|
||||
}
|
||||
|
||||
UpdateTransform();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果右键已松开则结束旋转
|
||||
dragState = DragState.None;
|
||||
}
|
||||
}
|
||||
|
||||
// 通过拖动平移
|
||||
if (dragState == DragState.Translating)
|
||||
{
|
||||
// 仅在按下按钮时操作
|
||||
if (InputProxy.GetMouseButton(0))
|
||||
{
|
||||
// 限制在屏幕范围内
|
||||
if (confineTranslation)
|
||||
{
|
||||
Vector3 screenMax = new Vector3(Screen.width, Screen.height);
|
||||
mousePos = Vector3.Max(Vector3.Min(mousePos, screenMax), Vector3.zero);
|
||||
}
|
||||
|
||||
Vector3 screenPos = currentCamera.WorldToScreenPoint(transform.position);
|
||||
Vector3 deltaPos = mousePos - lastMousePosition;
|
||||
deltaPos.z = 0f;
|
||||
Vector3 worldPos = currentCamera.ScreenToWorldPoint(screenPos + deltaPos);
|
||||
translation = worldPos - centerTransform.position;
|
||||
|
||||
UpdateTransform();
|
||||
}
|
||||
else
|
||||
{
|
||||
// ボタンが離されていれば並進は終了
|
||||
dragState = DragState.None;
|
||||
}
|
||||
}
|
||||
|
||||
// 暂时仅在使用 Legacy Input Manager 时接受滚轮操作
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
// 如果滚轮转动,则进行缩放
|
||||
if (!Mathf.Approximately(Input.GetAxis("Mouse ScrollWheel"), 0f) && IsHit(mousePos))
|
||||
{
|
||||
// 滚轮操作量
|
||||
float wheelDelta = Input.GetAxis("Mouse ScrollWheel") * scaleSensitivity;
|
||||
|
||||
// 更改缩放倍率
|
||||
zoom -= wheelDelta;
|
||||
zoom = Mathf.Clamp(zoom, -1f, 2f); // 视场角的对数范围 [度]
|
||||
|
||||
UpdateTransform();
|
||||
}
|
||||
#endif
|
||||
|
||||
lastMousePosition = mousePos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断鼠标操作时是否点击到对象
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal bool IsHit(Vector3 screenPosition)
|
||||
{
|
||||
RaycastHit hit;
|
||||
Ray ray = currentCamera.ScreenPointToRay(screenPosition);
|
||||
|
||||
if (Physics.Raycast(ray, out hit))
|
||||
{
|
||||
if (hit.transform.IsChildOf(transform)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 若角度超出指定范围,则进行修正
|
||||
/// </summary>
|
||||
/// <param name="angle"></param>
|
||||
/// <param name="min"></param>
|
||||
/// <param name="max"></param>
|
||||
/// <returns></returns>
|
||||
public static float ClampAngle(float angle, float min, float max)
|
||||
{
|
||||
if (angle < -min) angle = -((-angle) % 360f);
|
||||
if (angle > max) angle = angle % 360f;
|
||||
return Mathf.Clamp(angle, min, max);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 035ad1913e9c28f4492641ca36127790
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,84 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: UiMaterial
|
||||
m_Shader: {fileID: 10760, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _ColorMask: 15
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _GlossMapScale: 1
|
||||
- _Glossiness: 0.5
|
||||
- _GlossyReflections: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _Stencil: 0
|
||||
- _StencilComp: 8
|
||||
- _StencilOp: 0
|
||||
- _StencilReadMask: 255
|
||||
- _StencilWriteMask: 255
|
||||
- _UVSec: 0
|
||||
- _UseUIAlphaClip: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 0.78431374}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 57c048a21c6552643bb464f9bcd0cf1a
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"displayName": "FileDialog",
|
||||
"description": "Demonstrates native file open/save dialog integration.",
|
||||
"createSeparatePackage": false
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Kirurobo
|
||||
{
|
||||
/// <summary>
|
||||
/// 基础文件面板示例
|
||||
/// </summary>
|
||||
public class FileDialogSample : MonoBehaviour
|
||||
{
|
||||
public Button openFileButton;
|
||||
public Button openMultipleFilesButton;
|
||||
public Button saveFileButton;
|
||||
public Text messageText;
|
||||
|
||||
// 首次更新前调用 Start
|
||||
void Start()
|
||||
{
|
||||
openFileButton.onClick.AddListener(OpenSingleFile);
|
||||
openMultipleFilesButton.onClick.AddListener(OpenMultipleFiles);
|
||||
saveFileButton.onClick.AddListener(OpenSaveFile);
|
||||
messageText.text = "点击按钮!";
|
||||
}
|
||||
|
||||
// 每帧调用 Update
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 打开单个文件的对话框。
|
||||
/// </summary>
|
||||
private void OpenSingleFile() {
|
||||
FilePanel.Settings settings = new FilePanel.Settings();
|
||||
settings.filters = new FilePanel.Filter[]
|
||||
{
|
||||
new FilePanel.Filter("所有文件", "*"),
|
||||
new FilePanel.Filter("图片文件 (*.png;*.jpg;*.jpeg;*.tiff;*.gif;*.tga)", "png", "jpg", "jpeg", "tiff", "gif", "tga"),
|
||||
new FilePanel.Filter("文档 (*.txt;*.rtf;*.doc;*.docx)", "txt", "rtf", "doc", "docx"),
|
||||
};
|
||||
settings.title = "打开文件!";
|
||||
settings.initialDirectory = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyPictures);
|
||||
|
||||
messageText.text = "";
|
||||
FilePanel.OpenFilePanel(settings, (files) =>
|
||||
{
|
||||
messageText.text = "打开文件\n" + string.Join("\n", files);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 打开多个文件的对话框。
|
||||
/// </summary>
|
||||
private void OpenMultipleFiles() {
|
||||
FilePanel.Settings settings = new FilePanel.Settings();
|
||||
settings.filters = new FilePanel.Filter[]
|
||||
{
|
||||
new FilePanel.Filter("图片文件 (*.png;*.jpg;*.jpeg;*.tiff;*.gif;*.tga)", "png", "jpg", "jpeg", "tiff", "gif", "tga"),
|
||||
new FilePanel.Filter("文档 (*.txt;*.rtf;*.doc;*.docx)", "txt", "rtf", "doc", "docx"),
|
||||
new FilePanel.Filter("所有文件", "*"),
|
||||
};
|
||||
settings.flags = FilePanel.Flag.AllowMultipleSelection;
|
||||
settings.title = "打开多个文件!";
|
||||
settings.initialDirectory = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);
|
||||
|
||||
messageText.text = "";
|
||||
FilePanel.OpenFilePanel(settings, (files) =>
|
||||
{
|
||||
messageText.text = "打开多个文件\n" + string.Join("\n", files);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 打开保存文件对话框。
|
||||
/// </summary>
|
||||
private void OpenSaveFile() {
|
||||
FilePanel.Settings settings = new FilePanel.Settings();
|
||||
settings.filters = new FilePanel.Filter[]
|
||||
{
|
||||
new FilePanel.Filter("文本文件 (*.txt;*.log)", "txt", "log"),
|
||||
new FilePanel.Filter("图片文件 (*.png;*.jpg;*.jpeg;*.tiff;*.gif;*.tga)", "png", "jpg", "jpeg", "tiff", "gif", "tga"),
|
||||
new FilePanel.Filter("所有文件", "*"),
|
||||
};
|
||||
settings.title = "实际上不会执行保存操作";
|
||||
settings.initialFile = "Test.txt";
|
||||
|
||||
messageText.text = "";
|
||||
FilePanel.SaveFilePanel(settings, (files) =>
|
||||
{
|
||||
messageText.text = "选中的文件\n" + string.Join("\n", files);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,63 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!850595691 &4890085278179872738
|
||||
LightingSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: FileDialogSampleSettings
|
||||
serializedVersion: 3
|
||||
m_GIWorkflowMode: 0
|
||||
m_EnableBakedLightmaps: 1
|
||||
m_EnableRealtimeLightmaps: 1
|
||||
m_RealtimeEnvironmentLighting: 1
|
||||
m_BounceScale: 1
|
||||
m_AlbedoBoost: 1
|
||||
m_IndirectOutputScale: 1
|
||||
m_UsingShadowmask: 1
|
||||
m_BakeBackend: 1
|
||||
m_LightmapMaxSize: 1024
|
||||
m_BakeResolution: 40
|
||||
m_Padding: 2
|
||||
m_TextureCompression: 1
|
||||
m_AO: 0
|
||||
m_AOMaxDistance: 1
|
||||
m_CompAOExponent: 1
|
||||
m_CompAOExponentDirect: 0
|
||||
m_ExtractAO: 0
|
||||
m_MixedBakeMode: 2
|
||||
m_LightmapsBakeMode: 1
|
||||
m_FilterMode: 1
|
||||
m_LightmapParameters: {fileID: 15204, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ExportTrainingData: 0
|
||||
m_TrainingDataDestination: TrainingData
|
||||
m_RealtimeResolution: 2
|
||||
m_ForceWhiteAlbedo: 0
|
||||
m_ForceUpdates: 0
|
||||
m_FinalGather: 0
|
||||
m_FinalGatherRayCount: 256
|
||||
m_FinalGatherFiltering: 1
|
||||
m_PVRCulling: 1
|
||||
m_PVRSampling: 1
|
||||
m_PVRDirectSampleCount: 32
|
||||
m_PVRSampleCount: 500
|
||||
m_PVREnvironmentSampleCount: 500
|
||||
m_PVREnvironmentReferencePointCount: 2048
|
||||
m_LightProbeSampleCountMultiplier: 4
|
||||
m_PVRBounces: 2
|
||||
m_PVRMinBounces: 2
|
||||
m_PVREnvironmentMIS: 0
|
||||
m_PVRFilteringMode: 2
|
||||
m_PVRDenoiserTypeDirect: 0
|
||||
m_PVRDenoiserTypeIndirect: 0
|
||||
m_PVRDenoiserTypeAO: 0
|
||||
m_PVRFilterTypeDirect: 0
|
||||
m_PVRFilterTypeIndirect: 0
|
||||
m_PVRFilterTypeAO: 0
|
||||
m_PVRFilteringGaussRadiusDirect: 1
|
||||
m_PVRFilteringGaussRadiusIndirect: 5
|
||||
m_PVRFilteringGaussRadiusAO: 2
|
||||
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
|
||||
m_PVRFilteringAtrousPositionSigmaIndirect: 2
|
||||
m_PVRFilteringAtrousPositionSigmaAO: 1
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"displayName": "Fullscreen",
|
||||
"description": "Fullscreen mode example with right-click context menu and 3D snowman scene.",
|
||||
"createSeparatePackage": false
|
||||
}
|
||||
@@ -0,0 +1,304 @@
|
||||
/**
|
||||
* 全屏示例的 UI 控制器
|
||||
*
|
||||
* Author: Kirurobo http://twitter.com/kirurobo
|
||||
* License: MIT
|
||||
*/
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Kirurobo
|
||||
{
|
||||
/// <summary>
|
||||
/// 使用 Toggle 开关 WindowController 设置的示例
|
||||
/// </summary>
|
||||
public class FullscreenSample : MonoBehaviour
|
||||
{
|
||||
private UniWindowController uniwinc;
|
||||
private RectTransform canvasRect;
|
||||
|
||||
private float mouseMoveSS = 0f; // 鼠标轨迹平方和。[px^2]
|
||||
private float mouseMoveSSThreshold = 36f; // 点击(非拖拽)阈值。[px^2]
|
||||
private Vector3 lastMousePosition; // 右键点击位置。
|
||||
private float touchDuration = 0f;
|
||||
private float touchDurationThreshold = 0.5f; // 长按时间阈值。[s]
|
||||
|
||||
public Toggle transparentToggle;
|
||||
public Toggle topmostToggle;
|
||||
public Toggle bottommostToggle;
|
||||
public Dropdown fitWindowDropdown;
|
||||
public Button quitButton;
|
||||
public Button menuCloseButton;
|
||||
public RectTransform menuPanel;
|
||||
|
||||
/// <summary>
|
||||
/// 设置
|
||||
/// </summary>
|
||||
void Start()
|
||||
{
|
||||
// 查找 UniWindowController
|
||||
uniwinc = GameObject.FindAnyObjectByType<UniWindowController>();
|
||||
|
||||
// 获取 Canvas 的 RectTransform
|
||||
if (menuPanel) canvasRect = menuPanel.GetComponentInParent<Canvas>().GetComponent<RectTransform>();
|
||||
|
||||
// 根据有效显示器数量创建选项
|
||||
UpdateMonitorDropdown();
|
||||
|
||||
// 将 Toggle 的选中状态与当前状态同步
|
||||
UpdateUI();
|
||||
|
||||
// 初始状态下关闭菜单
|
||||
CloseMenu();
|
||||
|
||||
if (uniwinc)
|
||||
{
|
||||
// 操作 UI 时将其反映到窗口
|
||||
transparentToggle?.onValueChanged.AddListener(val => uniwinc.isTransparent = val);
|
||||
topmostToggle?.onValueChanged.AddListener(val => uniwinc.isTopmost = val);
|
||||
bottommostToggle?.onValueChanged.AddListener(val => uniwinc.isBottommost = val);
|
||||
fitWindowDropdown?.onValueChanged.AddListener(val => SetFitToMonitor(val));
|
||||
quitButton?.onClick.AddListener(Quit);
|
||||
menuCloseButton?.onClick.AddListener(CloseMenu);
|
||||
|
||||
// Add events
|
||||
uniwinc.OnStateChanged += (type) =>
|
||||
{
|
||||
UpdateUI();
|
||||
//ShowEventMessage("Window state changed: " + type);
|
||||
};
|
||||
uniwinc.OnMonitorChanged += () => {
|
||||
UpdateMonitorDropdown();
|
||||
UpdateUI();
|
||||
//ShowEventMessage("Resolution changed!");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 每帧执行
|
||||
/// </summary>
|
||||
private void Update()
|
||||
{
|
||||
// 鼠标右键点击时显示上下文菜单。
|
||||
// 如果鼠标移动距离在阈值以下,则视为点击
|
||||
if (InputProxy.GetMouseButtonDown(1))
|
||||
{
|
||||
lastMousePosition = InputProxy.mousePosition;
|
||||
touchDuration = 0f;
|
||||
}
|
||||
if (InputProxy.GetMouseButton(1))
|
||||
{
|
||||
mouseMoveSS += (InputProxy.mousePosition - lastMousePosition).sqrMagnitude;
|
||||
}
|
||||
if (InputProxy.GetMouseButtonUp(1))
|
||||
{
|
||||
if (mouseMoveSS < mouseMoveSSThreshold)
|
||||
{
|
||||
ShowMenu(lastMousePosition);
|
||||
}
|
||||
mouseMoveSS = 0f;
|
||||
touchDuration = 0f;
|
||||
}
|
||||
|
||||
// 暂时仅在 Legacy Input Manager 中处理触摸
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
// 长按也可显示菜单
|
||||
if (Input.touchSupported && (Input.touchCount > 0))
|
||||
{
|
||||
Touch touch = Input.GetTouch(0);
|
||||
if (touch.phase == TouchPhase.Began)
|
||||
{
|
||||
lastMousePosition = Input.mousePosition;
|
||||
touchDuration = 0f;
|
||||
}
|
||||
if (touch.phase == TouchPhase.Moved || touch.phase == TouchPhase.Stationary)
|
||||
{
|
||||
mouseMoveSS += touch.deltaPosition.sqrMagnitude;
|
||||
touchDuration += touch.deltaTime;
|
||||
}
|
||||
if (touch.phase == TouchPhase.Ended)
|
||||
{
|
||||
if ((mouseMoveSS < mouseMoveSSThreshold) && (touchDuration >= touchDurationThreshold))
|
||||
{
|
||||
ShowMenu(lastMousePosition);
|
||||
}
|
||||
mouseMoveSS = 0f;
|
||||
touchDuration = 0f;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// 按下 [Space] 键也可显示菜单
|
||||
if (InputProxy.GetKeyUp("space"))
|
||||
{
|
||||
if (menuPanel)
|
||||
{
|
||||
if (menuPanel.gameObject.activeSelf) {
|
||||
CloseMenu();
|
||||
} else {
|
||||
Vector2 pos = new Vector2(Screen.width / 2, Screen.height / 2);
|
||||
ShowMenu(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 按下 [ESC] 时退出或停止播放
|
||||
if (InputProxy.GetKeyUp("escape"))
|
||||
{
|
||||
Quit();
|
||||
}
|
||||
}
|
||||
|
||||
void Quit()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.EditorApplication.isPlaying = false;
|
||||
#else
|
||||
Application.Quit();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 适配显示器下拉列表更改时的处理
|
||||
/// </summary>
|
||||
/// <param name="val"></param>
|
||||
void SetFitToMonitor(int val)
|
||||
{
|
||||
if (!uniwinc) return;
|
||||
|
||||
if (val < 1)
|
||||
{
|
||||
// 下拉列表第一项为不适配
|
||||
uniwinc.shouldFitMonitor = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 由于从第二项开始,显示器编号减1
|
||||
uniwinc.monitorToFit = val - 1;
|
||||
uniwinc.shouldFitMonitor = true; // 从false变为true时才会移动窗口,因此先指定显示器编号再更改
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在指定坐标显示上下文菜单
|
||||
/// </summary>
|
||||
/// <param name="position">指定中心坐标</param>
|
||||
private void ShowMenu(Vector2 position)
|
||||
{
|
||||
if (menuPanel)
|
||||
{
|
||||
Vector2 pos = position * (canvasRect.sizeDelta.x / Screen.width);
|
||||
float w = menuPanel.rect.width;
|
||||
float h = menuPanel.rect.height;
|
||||
|
||||
// 以指定坐标为中心进行位置调整
|
||||
pos.y = Mathf.Max(Mathf.Min(pos.y, Screen.height - h / 2f), h / 2f); // 如果超出则向上移动
|
||||
pos.x = Mathf.Max(Mathf.Min(pos.x, Screen.width - w / 2f), w / 2f); // 如果超出右侧则向左移动
|
||||
|
||||
menuPanel.pivot = Vector2.one * 0.5f; // 设置为中心
|
||||
menuPanel.anchorMin = Vector2.zero;
|
||||
menuPanel.anchorMax = Vector2.zero;
|
||||
menuPanel.anchoredPosition = pos;
|
||||
|
||||
menuPanel.gameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 关闭上下文菜单
|
||||
/// </summary>
|
||||
private void CloseMenu()
|
||||
{
|
||||
if (menuPanel)
|
||||
{
|
||||
menuPanel.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将实际状态反映到 UI 显示
|
||||
/// </summary>
|
||||
private void UpdateUI()
|
||||
{
|
||||
if (uniwinc)
|
||||
{
|
||||
if (transparentToggle)
|
||||
{
|
||||
transparentToggle.isOn = uniwinc.isTransparent;
|
||||
}
|
||||
|
||||
if (topmostToggle)
|
||||
{
|
||||
topmostToggle.isOn = uniwinc.isTopmost;
|
||||
}
|
||||
|
||||
if (bottommostToggle)
|
||||
{
|
||||
bottommostToggle.isOn = uniwinc.isBottommost;
|
||||
}
|
||||
|
||||
if (fitWindowDropdown)
|
||||
{
|
||||
if (uniwinc.shouldFitMonitor)
|
||||
{
|
||||
fitWindowDropdown.value = uniwinc.monitorToFit + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
fitWindowDropdown.value = 0;
|
||||
}
|
||||
fitWindowDropdown.RefreshShownValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新显示器选择下拉列表的选项
|
||||
/// 之后需要调用 UpdateUI()
|
||||
/// </summary>
|
||||
void UpdateMonitorDropdown()
|
||||
{
|
||||
if (!fitWindowDropdown) return;
|
||||
|
||||
// 删除除第一项以外的选项
|
||||
fitWindowDropdown.options.RemoveRange(1, fitWindowDropdown.options.Count - 1);
|
||||
|
||||
if (!uniwinc)
|
||||
{
|
||||
fitWindowDropdown.value = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int count = UniWindowController.GetMonitorCount();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
fitWindowDropdown.options.Add(new Dropdown.OptionData("适配显示器 " + i));
|
||||
}
|
||||
if (uniwinc.monitorToFit >= count)
|
||||
{
|
||||
uniwinc.monitorToFit = count - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示带超时功能的消息
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
private void ShowEventMessage(string message)
|
||||
{
|
||||
Debug.Log(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 如果 UI 中有文本框,则显示消息。否则输出到控制台
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
public void OutputMessage(string text)
|
||||
{
|
||||
Debug.Log(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,66 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!850595691 &4890085278179872738
|
||||
LightingSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: FullscreenSampleSettings
|
||||
serializedVersion: 6
|
||||
m_GIWorkflowMode: 1
|
||||
m_EnableBakedLightmaps: 1
|
||||
m_EnableRealtimeLightmaps: 0
|
||||
m_RealtimeEnvironmentLighting: 1
|
||||
m_BounceScale: 1
|
||||
m_AlbedoBoost: 1
|
||||
m_IndirectOutputScale: 1
|
||||
m_UsingShadowmask: 0
|
||||
m_BakeBackend: 0
|
||||
m_LightmapMaxSize: 1024
|
||||
m_BakeResolution: 50
|
||||
m_Padding: 2
|
||||
m_LightmapCompression: 0
|
||||
m_AO: 1
|
||||
m_AOMaxDistance: 1
|
||||
m_CompAOExponent: 1
|
||||
m_CompAOExponentDirect: 0
|
||||
m_ExtractAO: 0
|
||||
m_MixedBakeMode: 1
|
||||
m_LightmapsBakeMode: 1
|
||||
m_FilterMode: 1
|
||||
m_LightmapParameters: {fileID: 15204, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ExportTrainingData: 0
|
||||
m_TrainingDataDestination: TrainingData
|
||||
m_RealtimeResolution: 1
|
||||
m_ForceWhiteAlbedo: 0
|
||||
m_ForceUpdates: 0
|
||||
m_FinalGather: 0
|
||||
m_FinalGatherRayCount: 256
|
||||
m_FinalGatherFiltering: 1
|
||||
m_PVRCulling: 1
|
||||
m_PVRSampling: 1
|
||||
m_PVRDirectSampleCount: 32
|
||||
m_PVRSampleCount: 512
|
||||
m_PVREnvironmentSampleCount: 512
|
||||
m_PVREnvironmentReferencePointCount: 2048
|
||||
m_LightProbeSampleCountMultiplier: 4
|
||||
m_PVRBounces: 2
|
||||
m_PVRMinBounces: 2
|
||||
m_PVREnvironmentImportanceSampling: 0
|
||||
m_PVRFilteringMode: 0
|
||||
m_PVRDenoiserTypeDirect: 0
|
||||
m_PVRDenoiserTypeIndirect: 0
|
||||
m_PVRDenoiserTypeAO: 0
|
||||
m_PVRFilterTypeDirect: 0
|
||||
m_PVRFilterTypeIndirect: 0
|
||||
m_PVRFilterTypeAO: 0
|
||||
m_PVRFilteringGaussRadiusDirect: 1
|
||||
m_PVRFilteringGaussRadiusIndirect: 5
|
||||
m_PVRFilteringGaussRadiusAO: 2
|
||||
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
|
||||
m_PVRFilteringAtrousPositionSigmaIndirect: 2
|
||||
m_PVRFilteringAtrousPositionSigmaAO: 1
|
||||
m_PVRTiledBaking: 0
|
||||
m_NumRaysToShootPerTexel: -1
|
||||
m_RespectSceneVisibilityWhenBakingGI: 0
|
||||
@@ -0,0 +1,108 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: SnowParticle
|
||||
m_Shader: {fileID: 210, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_Parent: {fileID: 0}
|
||||
m_ModifiedSerializedProperties: 0
|
||||
m_ValidKeywords:
|
||||
- _ALPHABLEND_ON
|
||||
- _EMISSION
|
||||
- _FADING_ON
|
||||
m_InvalidKeywords:
|
||||
- _COLORCOLOR_ON
|
||||
m_LightmapFlags: 0
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: 3000
|
||||
stringTagMap:
|
||||
RenderType: Transparent
|
||||
disabledShaderPasses:
|
||||
- GRABPASS
|
||||
m_LockedProperties:
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 10300, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _BlendOp: 0
|
||||
- _BumpScale: 1
|
||||
- _CameraFadingEnabled: 1
|
||||
- _CameraFarFadeDistance: 5
|
||||
- _CameraNearFadeDistance: 0.5
|
||||
- _ColorMode: 4
|
||||
- _Cull: 2
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DistortionBlend: 0.5
|
||||
- _DistortionEnabled: 0
|
||||
- _DistortionStrength: 1
|
||||
- _DistortionStrengthScaled: 0
|
||||
- _DstBlend: 10
|
||||
- _EmissionEnabled: 1
|
||||
- _FlipbookMode: 0
|
||||
- _GlossMapScale: 1
|
||||
- _Glossiness: 0.5
|
||||
- _GlossyReflections: 1
|
||||
- _LightingEnabled: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 2
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SoftParticlesEnabled: 0
|
||||
- _SoftParticlesFarFadeDistance: 1
|
||||
- _SoftParticlesNearFadeDistance: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 5
|
||||
- _UVSec: 0
|
||||
- _ZWrite: 0
|
||||
m_Colors:
|
||||
- _CameraFadeParams: {r: 0.5, g: 0.22222222, b: 0, a: 0}
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _ColorAddSubDiff: {r: 1, g: 0, b: 0, a: 0}
|
||||
- _EmissionColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _SoftParticleFadeParams: {r: 0, g: 0, b: 0, a: 0}
|
||||
m_BuildTextureStacks: []
|
||||
@@ -0,0 +1,77 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: SnowmanArm
|
||||
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _GlossMapScale: 1
|
||||
- _Glossiness: 0.263
|
||||
- _GlossyReflections: 1
|
||||
- _Metallic: 0.683
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _UVSec: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 0.9433962, g: 0.64307785, b: 0.3693485, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
@@ -0,0 +1,78 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: SnowmanBody
|
||||
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords: _EMISSION _GLOSSYREFLECTIONS_OFF _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
|
||||
_SPECULARHIGHLIGHTS_OFF
|
||||
m_LightmapFlags: 2
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _GlossMapScale: 0
|
||||
- _Glossiness: 0
|
||||
- _GlossyReflections: 0
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 1
|
||||
- _SpecularHighlights: 0
|
||||
- _SrcBlend: 1
|
||||
- _UVSec: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0.3490566, g: 0.3490566, b: 0.3490566, a: 1}
|
||||
@@ -0,0 +1,77 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: SnowmanFace
|
||||
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords: _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _GlossMapScale: 0
|
||||
- _Glossiness: 0.5
|
||||
- _GlossyReflections: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 1
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _UVSec: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 0.21698111, g: 0.21698111, b: 0.21698111, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"displayName": "Menu",
|
||||
"description": "Sample menu scene for navigating between different example scenes.",
|
||||
"createSeparatePackage": false
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace Kirurobo
|
||||
{
|
||||
public class SampleManager : MonoBehaviour
|
||||
{
|
||||
private static SampleManager _instance;
|
||||
public static SampleManager Instance => _instance ?? (_instance = GameObject.FindAnyObjectByType<SampleManager>() ?? new SampleManager());
|
||||
|
||||
public Canvas canvas;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// 设为单例。若已有实例则销毁自身
|
||||
if (this != Instance)
|
||||
{
|
||||
Destroy(this.gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
DontDestroyOnLoad(Instance);
|
||||
DontDestroyOnLoad(UniWindowController.current);
|
||||
|
||||
SceneManager.sceneLoaded += SceneManager_sceneLoaded;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 场景加载时记录主相机
|
||||
/// </summary>
|
||||
/// <param name="arg0"></param>
|
||||
/// <param name="arg1"></param>
|
||||
private void SceneManager_sceneLoaded(Scene arg0, LoadSceneMode arg1)
|
||||
{
|
||||
UniWindowController.current.SetCamera(Camera.main);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 打开指定名称的场景
|
||||
/// </summary>
|
||||
/// <param name="name">场景名</param>
|
||||
public void LoadScene(string name)
|
||||
{
|
||||
if (name == "SimpleSample")
|
||||
{
|
||||
// SimpleSample 时无脚本控制,在此处设置透明
|
||||
UniWindowController.current.isTransparent = true;
|
||||
}
|
||||
else if (name == "FullScreenSample")
|
||||
{
|
||||
// FullScreenSample 时强制最大化
|
||||
UniWindowController.current.shouldFitMonitor = true;
|
||||
}
|
||||
|
||||
SceneManager.LoadScene(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出
|
||||
/// </summary>
|
||||
public void Quit()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.EditorApplication.isPlaying = false;
|
||||
#else
|
||||
Application.Quit();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,63 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!850595691 &4890085278179872738
|
||||
LightingSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: SampleMenuSettings
|
||||
serializedVersion: 3
|
||||
m_GIWorkflowMode: 0
|
||||
m_EnableBakedLightmaps: 1
|
||||
m_EnableRealtimeLightmaps: 1
|
||||
m_RealtimeEnvironmentLighting: 1
|
||||
m_BounceScale: 1
|
||||
m_AlbedoBoost: 1
|
||||
m_IndirectOutputScale: 1
|
||||
m_UsingShadowmask: 1
|
||||
m_BakeBackend: 1
|
||||
m_LightmapMaxSize: 1024
|
||||
m_BakeResolution: 40
|
||||
m_Padding: 2
|
||||
m_TextureCompression: 1
|
||||
m_AO: 0
|
||||
m_AOMaxDistance: 1
|
||||
m_CompAOExponent: 1
|
||||
m_CompAOExponentDirect: 0
|
||||
m_ExtractAO: 0
|
||||
m_MixedBakeMode: 2
|
||||
m_LightmapsBakeMode: 1
|
||||
m_FilterMode: 1
|
||||
m_LightmapParameters: {fileID: 15204, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ExportTrainingData: 0
|
||||
m_TrainingDataDestination: TrainingData
|
||||
m_RealtimeResolution: 2
|
||||
m_ForceWhiteAlbedo: 0
|
||||
m_ForceUpdates: 0
|
||||
m_FinalGather: 0
|
||||
m_FinalGatherRayCount: 256
|
||||
m_FinalGatherFiltering: 1
|
||||
m_PVRCulling: 1
|
||||
m_PVRSampling: 1
|
||||
m_PVRDirectSampleCount: 32
|
||||
m_PVRSampleCount: 500
|
||||
m_PVREnvironmentSampleCount: 500
|
||||
m_PVREnvironmentReferencePointCount: 2048
|
||||
m_LightProbeSampleCountMultiplier: 4
|
||||
m_PVRBounces: 2
|
||||
m_PVRMinBounces: 2
|
||||
m_PVREnvironmentMIS: 0
|
||||
m_PVRFilteringMode: 2
|
||||
m_PVRDenoiserTypeDirect: 0
|
||||
m_PVRDenoiserTypeIndirect: 0
|
||||
m_PVRDenoiserTypeAO: 0
|
||||
m_PVRFilterTypeDirect: 0
|
||||
m_PVRFilterTypeIndirect: 0
|
||||
m_PVRFilterTypeAO: 0
|
||||
m_PVRFilteringGaussRadiusDirect: 1
|
||||
m_PVRFilteringGaussRadiusIndirect: 5
|
||||
m_PVRFilteringGaussRadiusAO: 2
|
||||
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
|
||||
m_PVRFilteringAtrousPositionSigmaIndirect: 2
|
||||
m_PVRFilteringAtrousPositionSigmaAO: 1
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"displayName": "SimpleSample",
|
||||
"description": "A minimal example demonstrating basic window control setup.",
|
||||
"createSeparatePackage": false
|
||||
}
|
||||
@@ -0,0 +1,795 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!29 &1
|
||||
OcclusionCullingSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_OcclusionBakeSettings:
|
||||
smallestOccluder: 5
|
||||
smallestHole: 0.25
|
||||
backfaceThreshold: 100
|
||||
m_SceneGUID: 00000000000000000000000000000000
|
||||
m_OcclusionCullingData: {fileID: 0}
|
||||
--- !u!104 &2
|
||||
RenderSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 9
|
||||
m_Fog: 0
|
||||
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
|
||||
m_FogMode: 3
|
||||
m_FogDensity: 0.01
|
||||
m_LinearFogStart: 0
|
||||
m_LinearFogEnd: 300
|
||||
m_AmbientSkyColor: {r: 0.2, g: 0.2, b: 0.2, a: 1}
|
||||
m_AmbientEquatorColor: {r: 0.2, g: 0.2, b: 0.2, a: 1}
|
||||
m_AmbientGroundColor: {r: 0.2, g: 0.2, b: 0.2, a: 1}
|
||||
m_AmbientIntensity: 1
|
||||
m_AmbientMode: 3
|
||||
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
|
||||
m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_HaloStrength: 0.5
|
||||
m_FlareStrength: 1
|
||||
m_FlareFadeSpeed: 3
|
||||
m_HaloTexture: {fileID: 0}
|
||||
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_DefaultReflectionMode: 0
|
||||
m_DefaultReflectionResolution: 128
|
||||
m_ReflectionBounces: 1
|
||||
m_ReflectionIntensity: 1
|
||||
m_CustomReflection: {fileID: 0}
|
||||
m_Sun: {fileID: 0}
|
||||
m_IndirectSpecularColor: {r: 0.44657815, g: 0.49641186, b: 0.57481647, a: 1}
|
||||
m_UseRadianceAmbientProbe: 0
|
||||
--- !u!157 &4
|
||||
LightmapSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 12
|
||||
m_GIWorkflowMode: 1
|
||||
m_GISettings:
|
||||
serializedVersion: 2
|
||||
m_BounceScale: 1
|
||||
m_IndirectOutputScale: 1
|
||||
m_AlbedoBoost: 1
|
||||
m_EnvironmentLightingMode: 0
|
||||
m_EnableBakedLightmaps: 1
|
||||
m_EnableRealtimeLightmaps: 0
|
||||
m_LightmapEditorSettings:
|
||||
serializedVersion: 12
|
||||
m_Resolution: 1
|
||||
m_BakeResolution: 50
|
||||
m_AtlasSize: 1024
|
||||
m_AO: 1
|
||||
m_AOMaxDistance: 1
|
||||
m_CompAOExponent: 1
|
||||
m_CompAOExponentDirect: 0
|
||||
m_ExtractAmbientOcclusion: 0
|
||||
m_Padding: 2
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_LightmapsBakeMode: 1
|
||||
m_TextureCompression: 0
|
||||
m_FinalGather: 0
|
||||
m_FinalGatherFiltering: 1
|
||||
m_FinalGatherRayCount: 256
|
||||
m_ReflectionCompression: 2
|
||||
m_MixedBakeMode: 1
|
||||
m_BakeBackend: 0
|
||||
m_PVRSampling: 1
|
||||
m_PVRDirectSampleCount: 32
|
||||
m_PVRSampleCount: 500
|
||||
m_PVRBounces: 2
|
||||
m_PVREnvironmentSampleCount: 500
|
||||
m_PVREnvironmentReferencePointCount: 2048
|
||||
m_PVRFilteringMode: 0
|
||||
m_PVRDenoiserTypeDirect: 0
|
||||
m_PVRDenoiserTypeIndirect: 0
|
||||
m_PVRDenoiserTypeAO: 0
|
||||
m_PVRFilterTypeDirect: 0
|
||||
m_PVRFilterTypeIndirect: 0
|
||||
m_PVRFilterTypeAO: 0
|
||||
m_PVREnvironmentMIS: 0
|
||||
m_PVRCulling: 1
|
||||
m_PVRFilteringGaussRadiusDirect: 1
|
||||
m_PVRFilteringGaussRadiusIndirect: 5
|
||||
m_PVRFilteringGaussRadiusAO: 2
|
||||
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
|
||||
m_PVRFilteringAtrousPositionSigmaIndirect: 2
|
||||
m_PVRFilteringAtrousPositionSigmaAO: 1
|
||||
m_ExportTrainingData: 0
|
||||
m_TrainingDataDestination: TrainingData
|
||||
m_LightProbeSampleCountMultiplier: 4
|
||||
m_LightingDataAsset: {fileID: 0}
|
||||
m_LightingSettings: {fileID: 2074312002}
|
||||
--- !u!196 &5
|
||||
NavMeshSettings:
|
||||
serializedVersion: 2
|
||||
m_ObjectHideFlags: 0
|
||||
m_BuildSettings:
|
||||
serializedVersion: 3
|
||||
agentTypeID: 0
|
||||
agentRadius: 0.5
|
||||
agentHeight: 2
|
||||
agentSlope: 45
|
||||
agentClimb: 0.4
|
||||
ledgeDropHeight: 0
|
||||
maxJumpAcrossDistance: 0
|
||||
minRegionArea: 2
|
||||
manualCellSize: 0
|
||||
cellSize: 0.16666666
|
||||
manualTileSize: 0
|
||||
tileSize: 256
|
||||
buildHeightMesh: 0
|
||||
maxJobWorkers: 0
|
||||
preserveTilesOutsideBounds: 0
|
||||
debug:
|
||||
m_Flags: 0
|
||||
m_NavMeshData: {fileID: 0}
|
||||
--- !u!1 &144805234
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 144805236}
|
||||
- component: {fileID: 144805235}
|
||||
m_Layer: 0
|
||||
m_Name: Directional light
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!108 &144805235
|
||||
Light:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 144805234}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 10
|
||||
m_Type: 1
|
||||
m_Shape: 0
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_Intensity: 1
|
||||
m_Range: 10
|
||||
m_SpotAngle: 30
|
||||
m_InnerSpotAngle: 21.80208
|
||||
m_CookieSize: 10
|
||||
m_Shadows:
|
||||
m_Type: 0
|
||||
m_Resolution: -1
|
||||
m_CustomResolution: -1
|
||||
m_Strength: 1
|
||||
m_Bias: 0.05
|
||||
m_NormalBias: 0.4
|
||||
m_NearPlane: 0.2
|
||||
m_CullingMatrixOverride:
|
||||
e00: 1
|
||||
e01: 0
|
||||
e02: 0
|
||||
e03: 0
|
||||
e10: 0
|
||||
e11: 1
|
||||
e12: 0
|
||||
e13: 0
|
||||
e20: 0
|
||||
e21: 0
|
||||
e22: 1
|
||||
e23: 0
|
||||
e30: 0
|
||||
e31: 0
|
||||
e32: 0
|
||||
e33: 1
|
||||
m_UseCullingMatrixOverride: 0
|
||||
m_Cookie: {fileID: 0}
|
||||
m_DrawHalo: 0
|
||||
m_Flare: {fileID: 0}
|
||||
m_RenderMode: 0
|
||||
m_CullingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_RenderingLayerMask: 1
|
||||
m_Lightmapping: 4
|
||||
m_LightShadowCasterMode: 0
|
||||
m_AreaSize: {x: 1, y: 1}
|
||||
m_BounceIntensity: 1
|
||||
m_ColorTemperature: 6570
|
||||
m_UseColorTemperature: 0
|
||||
m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_UseBoundingSphereOverride: 0
|
||||
m_UseViewFrustumForShadowCasterCull: 1
|
||||
m_ShadowRadius: 0
|
||||
m_ShadowAngle: 0
|
||||
--- !u!4 &144805236
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 144805234}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0.40821794, y: -0.23456973, z: 0.10938166, w: 0.8754261}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1001 &269992499
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications:
|
||||
- target: {fileID: 9167954367673589911, guid: d7dcf50428b152040847878685fe0746,
|
||||
type: 3}
|
||||
propertyPath: m_Name
|
||||
value: DragMoveCanvas
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9167954367673589915, guid: d7dcf50428b152040847878685fe0746,
|
||||
type: 3}
|
||||
propertyPath: m_Pivot.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9167954367673589915, guid: d7dcf50428b152040847878685fe0746,
|
||||
type: 3}
|
||||
propertyPath: m_Pivot.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9167954367673589915, guid: d7dcf50428b152040847878685fe0746,
|
||||
type: 3}
|
||||
propertyPath: m_RootOrder
|
||||
value: 4
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9167954367673589915, guid: d7dcf50428b152040847878685fe0746,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMax.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9167954367673589915, guid: d7dcf50428b152040847878685fe0746,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9167954367673589915, guid: d7dcf50428b152040847878685fe0746,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMin.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9167954367673589915, guid: d7dcf50428b152040847878685fe0746,
|
||||
type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9167954367673589915, guid: d7dcf50428b152040847878685fe0746,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9167954367673589915, guid: d7dcf50428b152040847878685fe0746,
|
||||
type: 3}
|
||||
propertyPath: m_SizeDelta.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9167954367673589915, guid: d7dcf50428b152040847878685fe0746,
|
||||
type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9167954367673589915, guid: d7dcf50428b152040847878685fe0746,
|
||||
type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9167954367673589915, guid: d7dcf50428b152040847878685fe0746,
|
||||
type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9167954367673589915, guid: d7dcf50428b152040847878685fe0746,
|
||||
type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9167954367673589915, guid: d7dcf50428b152040847878685fe0746,
|
||||
type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9167954367673589915, guid: d7dcf50428b152040847878685fe0746,
|
||||
type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9167954367673589915, guid: d7dcf50428b152040847878685fe0746,
|
||||
type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9167954367673589915, guid: d7dcf50428b152040847878685fe0746,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9167954367673589915, guid: d7dcf50428b152040847878685fe0746,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9167954367673589915, guid: d7dcf50428b152040847878685fe0746,
|
||||
type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9167954367673589915, guid: d7dcf50428b152040847878685fe0746,
|
||||
type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9167954367673589915, guid: d7dcf50428b152040847878685fe0746,
|
||||
type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: d7dcf50428b152040847878685fe0746, type: 3}
|
||||
--- !u!1 &452327621
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 452327624}
|
||||
- component: {fileID: 452327623}
|
||||
- component: {fileID: 452327625}
|
||||
m_Layer: 0
|
||||
m_Name: EventSystem
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &452327623
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 452327621}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_FirstSelected: {fileID: 0}
|
||||
m_sendNavigationEvents: 1
|
||||
m_DragThreshold: 10
|
||||
--- !u!4 &452327624
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 452327621}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &452327625
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 452327621}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: ce6b387a66b0e654d9eb8712d70fff48, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_SendPointerHoverToParent: 1
|
||||
m_MoveRepeatDelay: 0.5
|
||||
m_MoveRepeatRate: 0.1
|
||||
m_XRTrackingOrigin: {fileID: 0}
|
||||
m_ActionsAsset: {fileID: -944628639613478452, guid: ca9f5fa95ffab41fb9a615ab714db018,
|
||||
type: 3}
|
||||
m_PointAction: {fileID: -1654692200621890270, guid: ca9f5fa95ffab41fb9a615ab714db018,
|
||||
type: 3}
|
||||
m_MoveAction: {fileID: -8784545083839296357, guid: ca9f5fa95ffab41fb9a615ab714db018,
|
||||
type: 3}
|
||||
m_SubmitAction: {fileID: 392368643174621059, guid: ca9f5fa95ffab41fb9a615ab714db018,
|
||||
type: 3}
|
||||
m_CancelAction: {fileID: 7727032971491509709, guid: ca9f5fa95ffab41fb9a615ab714db018,
|
||||
type: 3}
|
||||
m_LeftClickAction: {fileID: 3001919216989983466, guid: ca9f5fa95ffab41fb9a615ab714db018,
|
||||
type: 3}
|
||||
m_MiddleClickAction: {fileID: -2185481485913320682, guid: ca9f5fa95ffab41fb9a615ab714db018,
|
||||
type: 3}
|
||||
m_RightClickAction: {fileID: -4090225696740746782, guid: ca9f5fa95ffab41fb9a615ab714db018,
|
||||
type: 3}
|
||||
m_ScrollWheelAction: {fileID: 6240969308177333660, guid: ca9f5fa95ffab41fb9a615ab714db018,
|
||||
type: 3}
|
||||
m_TrackedDevicePositionAction: {fileID: 6564999863303420839, guid: ca9f5fa95ffab41fb9a615ab714db018,
|
||||
type: 3}
|
||||
m_TrackedDeviceOrientationAction: {fileID: 7970375526676320489, guid: ca9f5fa95ffab41fb9a615ab714db018,
|
||||
type: 3}
|
||||
m_DeselectOnBackgroundClick: 1
|
||||
m_PointerBehavior: 0
|
||||
m_CursorLockBehavior: 0
|
||||
--- !u!1001 &1158200202
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications:
|
||||
- target: {fileID: 2416199871598626842, guid: e893aefd93740714b999573b02916984,
|
||||
type: 3}
|
||||
propertyPath: m_RootOrder
|
||||
value: 3
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2416199871598626842, guid: e893aefd93740714b999573b02916984,
|
||||
type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2416199871598626842, guid: e893aefd93740714b999573b02916984,
|
||||
type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2416199871598626842, guid: e893aefd93740714b999573b02916984,
|
||||
type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2416199871598626842, guid: e893aefd93740714b999573b02916984,
|
||||
type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2416199871598626842, guid: e893aefd93740714b999573b02916984,
|
||||
type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2416199871598626842, guid: e893aefd93740714b999573b02916984,
|
||||
type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2416199871598626842, guid: e893aefd93740714b999573b02916984,
|
||||
type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2416199871598626842, guid: e893aefd93740714b999573b02916984,
|
||||
type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2416199871598626842, guid: e893aefd93740714b999573b02916984,
|
||||
type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2416199871598626842, guid: e893aefd93740714b999573b02916984,
|
||||
type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2416199871598626843, guid: e893aefd93740714b999573b02916984,
|
||||
type: 3}
|
||||
propertyPath: _isTopmost
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2416199871598626843, guid: e893aefd93740714b999573b02916984,
|
||||
type: 3}
|
||||
propertyPath: _isTransparent
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2416199871598626844, guid: e893aefd93740714b999573b02916984,
|
||||
type: 3}
|
||||
propertyPath: m_Name
|
||||
value: UniWindowController
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2416199871598626845, guid: e893aefd93740714b999573b02916984,
|
||||
type: 3}
|
||||
propertyPath: _isTopmost
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2416199871598626845, guid: e893aefd93740714b999573b02916984,
|
||||
type: 3}
|
||||
propertyPath: _isTransparent
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: e893aefd93740714b999573b02916984, type: 3}
|
||||
--- !u!850595691 &2074312002
|
||||
LightingSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Settings.lighting
|
||||
serializedVersion: 6
|
||||
m_GIWorkflowMode: 1
|
||||
m_EnableBakedLightmaps: 1
|
||||
m_EnableRealtimeLightmaps: 0
|
||||
m_RealtimeEnvironmentLighting: 1
|
||||
m_BounceScale: 1
|
||||
m_AlbedoBoost: 1
|
||||
m_IndirectOutputScale: 1
|
||||
m_UsingShadowmask: 0
|
||||
m_BakeBackend: 2
|
||||
m_LightmapMaxSize: 1024
|
||||
m_BakeResolution: 50
|
||||
m_Padding: 2
|
||||
m_LightmapCompression: 0
|
||||
m_AO: 1
|
||||
m_AOMaxDistance: 1
|
||||
m_CompAOExponent: 1
|
||||
m_CompAOExponentDirect: 0
|
||||
m_ExtractAO: 0
|
||||
m_MixedBakeMode: 1
|
||||
m_LightmapsBakeMode: 1
|
||||
m_FilterMode: 1
|
||||
m_LightmapParameters: {fileID: 15204, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ExportTrainingData: 0
|
||||
m_TrainingDataDestination: TrainingData
|
||||
m_RealtimeResolution: 1
|
||||
m_ForceWhiteAlbedo: 0
|
||||
m_ForceUpdates: 0
|
||||
m_FinalGather: 0
|
||||
m_FinalGatherRayCount: 256
|
||||
m_FinalGatherFiltering: 1
|
||||
m_PVRCulling: 1
|
||||
m_PVRSampling: 1
|
||||
m_PVRDirectSampleCount: 32
|
||||
m_PVRSampleCount: 512
|
||||
m_PVREnvironmentSampleCount: 512
|
||||
m_PVREnvironmentReferencePointCount: 2048
|
||||
m_LightProbeSampleCountMultiplier: 4
|
||||
m_PVRBounces: 2
|
||||
m_PVRMinBounces: 2
|
||||
m_PVREnvironmentImportanceSampling: 0
|
||||
m_PVRFilteringMode: 0
|
||||
m_PVRDenoiserTypeDirect: 0
|
||||
m_PVRDenoiserTypeIndirect: 0
|
||||
m_PVRDenoiserTypeAO: 0
|
||||
m_PVRFilterTypeDirect: 0
|
||||
m_PVRFilterTypeIndirect: 0
|
||||
m_PVRFilterTypeAO: 0
|
||||
m_PVRFilteringGaussRadiusDirect: 1
|
||||
m_PVRFilteringGaussRadiusIndirect: 5
|
||||
m_PVRFilteringGaussRadiusAO: 2
|
||||
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
|
||||
m_PVRFilteringAtrousPositionSigmaIndirect: 2
|
||||
m_PVRFilteringAtrousPositionSigmaAO: 1
|
||||
m_PVRTiledBaking: 0
|
||||
m_NumRaysToShootPerTexel: -1
|
||||
m_RespectSceneVisibilityWhenBakingGI: 0
|
||||
--- !u!1 &2084589444
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 2084589449}
|
||||
- component: {fileID: 2084589448}
|
||||
- component: {fileID: 2084589445}
|
||||
m_Layer: 0
|
||||
m_Name: Main Camera
|
||||
m_TagString: MainCamera
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!81 &2084589445
|
||||
AudioListener:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2084589444}
|
||||
m_Enabled: 1
|
||||
--- !u!20 &2084589448
|
||||
Camera:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2084589444}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 2
|
||||
m_ClearFlags: 1
|
||||
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
|
||||
m_projectionMatrixMode: 1
|
||||
m_GateFitMode: 2
|
||||
m_FOVAxisMode: 0
|
||||
m_Iso: 200
|
||||
m_ShutterSpeed: 0.005
|
||||
m_Aperture: 16
|
||||
m_FocusDistance: 10
|
||||
m_FocalLength: 50
|
||||
m_BladeCount: 5
|
||||
m_Curvature: {x: 2, y: 11}
|
||||
m_BarrelClipping: 0.25
|
||||
m_Anamorphism: 0
|
||||
m_SensorSize: {x: 36, y: 24}
|
||||
m_LensShift: {x: 0, y: 0}
|
||||
m_NormalizedViewPortRect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 1
|
||||
height: 1
|
||||
near clip plane: 0.3
|
||||
far clip plane: 1000
|
||||
field of view: 30
|
||||
orthographic: 0
|
||||
orthographic size: 5
|
||||
m_Depth: -1
|
||||
m_CullingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_RenderingPath: -1
|
||||
m_TargetTexture: {fileID: 0}
|
||||
m_TargetDisplay: 0
|
||||
m_TargetEye: 3
|
||||
m_HDR: 1
|
||||
m_AllowMSAA: 1
|
||||
m_AllowDynamicResolution: 0
|
||||
m_ForceIntoRT: 0
|
||||
m_OcclusionCulling: 1
|
||||
m_StereoConvergence: 10
|
||||
m_StereoSeparation: 0.022
|
||||
--- !u!4 &2084589449
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2084589444}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: -5}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &2124152612
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 2124152616}
|
||||
- component: {fileID: 2124152615}
|
||||
- component: {fileID: 2124152614}
|
||||
- component: {fileID: 2124152613}
|
||||
m_Layer: 0
|
||||
m_Name: Cube
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!23 &2124152613
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2124152612}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 0
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 2
|
||||
m_RayTraceProcedural: 0
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 10302, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 0
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
m_AdditionalVertexStreams: {fileID: 0}
|
||||
--- !u!65 &2124152614
|
||||
BoxCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2124152612}
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_IsTrigger: 0
|
||||
m_ProvidesContacts: 0
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Size: {x: 1, y: 1, z: 1}
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
--- !u!33 &2124152615
|
||||
MeshFilter:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2124152612}
|
||||
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
|
||||
--- !u!4 &2124152616
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2124152612}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0.35355338, y: 0.35355338, z: -0.1464466, w: 0.8535535}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 45, y: 45.000004, z: 0}
|
||||
--- !u!1660057539 &9223372036854775807
|
||||
SceneRoots:
|
||||
m_ObjectHideFlags: 0
|
||||
m_Roots:
|
||||
- {fileID: 144805236}
|
||||
- {fileID: 2084589449}
|
||||
- {fileID: 2124152616}
|
||||
- {fileID: 1158200202}
|
||||
- {fileID: 269992499}
|
||||
- {fileID: 452327624}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"displayName": "UiSample",
|
||||
"description": "Complete UI demonstration with toggles and sliders for controlling window properties (transparency, topmost, click-through, etc.).",
|
||||
"createSeparatePackage": false
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,603 @@
|
||||
/**
|
||||
* UniWindowController 的示例脚本
|
||||
*
|
||||
* Author: Kirurobo http://twitter.com/kirurobo
|
||||
* License: MIT
|
||||
*/
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Kirurobo
|
||||
{
|
||||
/// <summary>
|
||||
/// 使用 Toggle 开关 WindowController 设置的示例
|
||||
/// </summary>
|
||||
public class UiSampleController : MonoBehaviour
|
||||
{
|
||||
private UniWindowController uniwinc;
|
||||
private UniWindowMoveHandle uniWinMoveHandle;
|
||||
private RectTransform canvasRect;
|
||||
|
||||
private float mouseMoveSS = 0f; // 鼠标轨迹平方和。[px^2]
|
||||
private float mouseMoveSSThreshold = 36f; // 点击(非拖拽)阈值。[px^2]
|
||||
private Vector3 lastMousePosition; // 右键点击位置。
|
||||
private float lastEventOccurredTime = -5f; // 上次事件发生的时间戳 [s]
|
||||
private float eventMessageTimeout = 1f; // 在此时间段内显示事件消息 [s]
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
private float touchDuration = 0f;
|
||||
private float touchDurationThreshold = 0.5f; // 长按时间阈值。[s]
|
||||
#endif
|
||||
public Toggle transparentToggle;
|
||||
public Slider alphaSlider;
|
||||
public Toggle topmostToggle;
|
||||
public Toggle bottommostToggle;
|
||||
[FormerlySerializedAs("maximizedToggle")] public Toggle zoomedToggle;
|
||||
public Toggle dragMoveToggle;
|
||||
public Toggle allowDropToggle;
|
||||
public Dropdown fitWindowDropdown;
|
||||
public Toggle showBorderlineToggle;
|
||||
public Button widthDownButton;
|
||||
public Button widthUpButton;
|
||||
public Button heightDownButton;
|
||||
public Button heightUpButton;
|
||||
public Dropdown transparentTypeDropdown;
|
||||
public Dropdown hitTestTypeDropdown;
|
||||
public Toggle clickThroughToggle;
|
||||
public Image pickedColorImage;
|
||||
public Text pickedColorText;
|
||||
public Text messageText;
|
||||
public Text clientSizeText;
|
||||
public Button menuCloseButton;
|
||||
public RectTransform menuPanel;
|
||||
public RectTransform borderlinePanel;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化
|
||||
/// </summary>
|
||||
void Start()
|
||||
{
|
||||
// 查找 UniWindowController
|
||||
uniwinc = UniWindowController.current;
|
||||
|
||||
// 查找 UniWindowDragMove
|
||||
uniWinMoveHandle = GameObject.FindAnyObjectByType<UniWindowMoveHandle>();
|
||||
|
||||
// 获取 Canvas 的 RectTransform
|
||||
if (menuPanel) canvasRect = menuPanel.GetComponentInParent<Canvas>().GetComponent<RectTransform>();
|
||||
|
||||
// 根据有效显示器数量创建选项
|
||||
UpdateMonitorDropdown();
|
||||
|
||||
// 将 Toggle 的选中状态与当前状态同步
|
||||
UpdateUI();
|
||||
|
||||
if (uniwinc)
|
||||
{
|
||||
// 操作 UI 时将其反映到窗口
|
||||
transparentToggle?.onValueChanged.AddListener(val => uniwinc.isTransparent = val);
|
||||
alphaSlider?.onValueChanged.AddListener(val => uniwinc.alphaValue = val);
|
||||
topmostToggle?.onValueChanged.AddListener(val => uniwinc.isTopmost = val);
|
||||
bottommostToggle?.onValueChanged.AddListener(val => uniwinc.isBottommost = val);
|
||||
zoomedToggle?.onValueChanged.AddListener(val => uniwinc.isZoomed = val);
|
||||
allowDropToggle?.onValueChanged.AddListener(val => uniwinc.allowDropFiles = val);
|
||||
|
||||
fitWindowDropdown?.onValueChanged.AddListener(val => SetFitToMonitor(val));
|
||||
|
||||
widthDownButton?.onClick.AddListener(() => uniwinc.windowSize += new Vector2(-100, 0));
|
||||
widthUpButton?.onClick.AddListener(() => uniwinc.windowSize += new Vector2(+100, 0));
|
||||
heightDownButton?.onClick.AddListener(() => uniwinc.windowSize += new Vector2(0, -100));
|
||||
heightUpButton?.onClick.AddListener(() => uniwinc.windowSize += new Vector2(0, +100));
|
||||
|
||||
clickThroughToggle?.onValueChanged.AddListener(val => uniwinc.isClickThrough = val);
|
||||
|
||||
transparentTypeDropdown?.onValueChanged.AddListener(val => uniwinc.SetTransparentType((UniWindowController.TransparentType)val));
|
||||
hitTestTypeDropdown?.onValueChanged.AddListener(val => uniwinc.hitTestType = (UniWindowController.HitTestType)val);
|
||||
menuCloseButton?.onClick.AddListener(CloseMenu);
|
||||
|
||||
if (uniWinMoveHandle) dragMoveToggle?.onValueChanged.AddListener(val => uniWinMoveHandle.enabled = val);
|
||||
|
||||
#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
|
||||
// 如果不是 Windows,则禁用透明方式选择
|
||||
//if (transparentTypeDropdown) transparentTypeDropdown.interactable = false;
|
||||
//if (transparentTypeDropdown) transparentTypeDropdown.enabled = false;
|
||||
if (transparentTypeDropdown) transparentTypeDropdown.gameObject.SetActive(false);
|
||||
#endif
|
||||
|
||||
// 添加事件
|
||||
uniwinc.OnStateChanged += (type) =>
|
||||
{
|
||||
UpdateUI();
|
||||
//Debug.Log("Window state changed: " + type);
|
||||
ShowEventMessage("状态改变: " + type);
|
||||
//ShowEventMessage("State changed: " + type + "4:isKey 2:canBecomeKey, 1:canBecomeMain : " + uniwinc.GetDebugInfo().ToString());
|
||||
ShowClientSize();
|
||||
};
|
||||
uniwinc.OnMonitorChanged += () => {
|
||||
UpdateMonitorDropdown();
|
||||
UpdateUI();
|
||||
ShowEventMessage("分辨率已改变!");
|
||||
ShowClientSize();
|
||||
};
|
||||
uniwinc.OnDropFiles += files =>
|
||||
{
|
||||
ShowEventMessage(string.Join(Environment.NewLine, files));
|
||||
};
|
||||
}
|
||||
|
||||
// 即使 UinWinC 未就绪也能运行的 Listener
|
||||
showBorderlineToggle?.onValueChanged.AddListener(val => borderlinePanel.gameObject.SetActive(val));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示带超时功能的消息
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
private void ShowEventMessage(string message)
|
||||
{
|
||||
lastEventOccurredTime = Time.time;
|
||||
if (messageText) messageText.text = message;
|
||||
|
||||
Debug.Log(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 每帧执行的处理
|
||||
/// </summary>
|
||||
private void Update()
|
||||
{
|
||||
// 更新点击测试相关的显示
|
||||
UpdateHitTestUI();
|
||||
|
||||
// 显示窗口位置和大小以确认运行状态
|
||||
if ((lastEventOccurredTime + eventMessageTimeout) < Time.time)
|
||||
{
|
||||
ShowWindowMetrics();
|
||||
}
|
||||
|
||||
// 鼠标右键点击显示菜单。移动距离在阈值以下视为点击。
|
||||
if (InputProxy.GetMouseButtonDown(1))
|
||||
{
|
||||
lastMousePosition = InputProxy.mousePosition;
|
||||
ResetTouchDuration();
|
||||
}
|
||||
if (InputProxy.GetMouseButton(1))
|
||||
{
|
||||
mouseMoveSS += (InputProxy.mousePosition - lastMousePosition).sqrMagnitude;
|
||||
}
|
||||
if (InputProxy.GetMouseButtonUp(1))
|
||||
{
|
||||
if (mouseMoveSS < mouseMoveSSThreshold)
|
||||
{
|
||||
ShowMenu(lastMousePosition);
|
||||
}
|
||||
mouseMoveSS = 0f;
|
||||
ResetTouchDuration();
|
||||
}
|
||||
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
// 长按也可显示菜单
|
||||
if (Input.touchSupported && (Input.touchCount > 0))
|
||||
{
|
||||
Touch touch = Input.GetTouch(0);
|
||||
if (touch.phase == TouchPhase.Began)
|
||||
{
|
||||
lastMousePosition = Input.mousePosition;
|
||||
ResetTouchDuration();
|
||||
}
|
||||
if (touch.phase == TouchPhase.Moved || touch.phase == TouchPhase.Stationary)
|
||||
{
|
||||
mouseMoveSS += touch.deltaPosition.sqrMagnitude;
|
||||
touchDuration += touch.deltaTime;
|
||||
}
|
||||
if (touch.phase == TouchPhase.Ended)
|
||||
{
|
||||
if ((mouseMoveSS < mouseMoveSSThreshold) && (touchDuration >= touchDurationThreshold))
|
||||
{
|
||||
ShowMenu(lastMousePosition);
|
||||
}
|
||||
mouseMoveSS = 0f;
|
||||
ResetTouchDuration();
|
||||
}
|
||||
}
|
||||
#elif ENABLE_INPUT_SYSTEM
|
||||
// 目前 New Input System 不支持触摸
|
||||
// EnhancedTouch 不能与 InputAction 同时使用?
|
||||
#endif
|
||||
|
||||
// 按键也可更改设置
|
||||
if (uniwinc)
|
||||
{
|
||||
// 切换透明模式
|
||||
if (InputProxy.GetKeyUp("t"))
|
||||
{
|
||||
uniwinc.isTransparent = !uniwinc.isTransparent;
|
||||
}
|
||||
|
||||
// 切换始终置顶
|
||||
if (InputProxy.GetKeyUp("f"))
|
||||
{
|
||||
uniwinc.isTopmost = !uniwinc.isTopmost;
|
||||
}
|
||||
|
||||
// 切换始终置底
|
||||
if (InputProxy.GetKeyUp("b"))
|
||||
{
|
||||
uniwinc.isBottommost = !uniwinc.isBottommost;
|
||||
}
|
||||
|
||||
// 切换最大化
|
||||
if (InputProxy.GetKeyUp("z"))
|
||||
{
|
||||
uniwinc.isZoomed = !uniwinc.isZoomed;
|
||||
}
|
||||
|
||||
// 切换自由定位
|
||||
if (InputProxy.GetKeyUp("p"))
|
||||
{
|
||||
uniwinc.isFreePositioningEnabled = !uniwinc.isFreePositioningEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 测试打开文件面板
|
||||
if (InputProxy.GetKeyUp("o"))
|
||||
{
|
||||
FilePanel.Settings ds = new FilePanel.Settings
|
||||
{
|
||||
flags = FilePanel.Flag.AllowMultipleSelection,
|
||||
title = "打开!",
|
||||
filters = new FilePanel.Filter[]{
|
||||
new FilePanel.Filter("Image files", "png", "jpg", "jpeg"),
|
||||
new FilePanel.Filter("All files", "*"),
|
||||
},
|
||||
initialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures),
|
||||
initialFile = "test.png",
|
||||
};
|
||||
FilePanel.OpenFilePanel(ds, (files) => ShowEventMessage(string.Join(Environment.NewLine, files)));
|
||||
}
|
||||
|
||||
// 测试保存文件面板
|
||||
if (InputProxy.GetKeyUp("s"))
|
||||
{
|
||||
FilePanel.Settings ds = new FilePanel.Settings
|
||||
{
|
||||
flags = FilePanel.Flag.AllowMultipleSelection,
|
||||
title = "保存!",
|
||||
filters = new FilePanel.Filter[]{
|
||||
//// TODO: 指定文件类型时,macOS 保存对话框打开会失败
|
||||
//// 给 NSSavePanel.accessoryView 指定内容时会发生此问题。
|
||||
//// NSOpenPanel 继承自它,但不会发生此问题。
|
||||
// new FilePanel.Filter("Shell script", "sh"),
|
||||
// new FilePanel.Filter("Log", "log"),
|
||||
// new FilePanel.Filter("Plain text", "txt"),
|
||||
// new FilePanel.Filter("All files", "*"),
|
||||
},
|
||||
initialFile = "Test.txt",
|
||||
initialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
|
||||
};
|
||||
FilePanel.SaveFilePanel(ds, (files) => ShowEventMessage(string.Join(Environment.NewLine, files)));
|
||||
}
|
||||
|
||||
// 按下 [ESC] 时退出或停止播放
|
||||
if (InputProxy.GetKeyUp("escape"))
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.EditorApplication.isPlaying = false;
|
||||
#else
|
||||
Application.Quit();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重置持续触摸时间的记录
|
||||
/// 仅在 Legacy Input Manager 中处理以避免警告
|
||||
/// </summary>
|
||||
void ResetTouchDuration() {
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
touchDuration = 0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 适配显示器下拉列表更改时的处理
|
||||
/// </summary>
|
||||
/// <param name="val"></param>
|
||||
void SetFitToMonitor(int val)
|
||||
{
|
||||
if (!uniwinc) return;
|
||||
|
||||
if (val < 1)
|
||||
{
|
||||
// 下拉列表第一项为不适配
|
||||
uniwinc.shouldFitMonitor = false;
|
||||
|
||||
// 允许更改最大化状态
|
||||
if (zoomedToggle) zoomedToggle.interactable = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 由于从第二项开始,显示器编号减1
|
||||
uniwinc.monitorToFit = val - 1;
|
||||
uniwinc.shouldFitMonitor = true; // 从false变为true时才会移动窗口,因此先指定显示器编号再更改
|
||||
|
||||
// 禁止更改最大化状态
|
||||
if (zoomedToggle) zoomedToggle.interactable = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示窗口位置和坐标
|
||||
/// </summary>
|
||||
void ShowWindowMetrics()
|
||||
{
|
||||
if (uniwinc)
|
||||
{
|
||||
var winPos = uniwinc.windowPosition;
|
||||
//var curPos = uniwinc.GetClientCursorPosition();
|
||||
OutputMessage(
|
||||
"位置: " + winPos
|
||||
+ "\n大小: " + uniwinc.windowSize
|
||||
+ "\n相对鼠标:" + (uniwinc.cursorPosition - winPos)
|
||||
//+ "\nScr. Cur.:" + curPos
|
||||
+ "\nUnity鼠标:" + (Vector2)InputProxy.mousePosition
|
||||
);
|
||||
ShowClientSize();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 聚焦时刷新 UI
|
||||
/// </summary>
|
||||
/// <param name="hasFocus"></param>
|
||||
private void OnApplicationFocus(bool hasFocus)
|
||||
{
|
||||
if (hasFocus)
|
||||
{
|
||||
UpdateUI();
|
||||
|
||||
if (uniwinc)
|
||||
{
|
||||
OutputMessage("已聚焦");
|
||||
}
|
||||
else
|
||||
{
|
||||
OutputMessage("未找到 UniWindowController");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在指定坐标显示上下文菜单
|
||||
/// </summary>
|
||||
/// <param name="position">指定中心坐标</param>
|
||||
private void ShowMenu(Vector2 position)
|
||||
{
|
||||
if (menuPanel)
|
||||
{
|
||||
Vector2 pos = position * (canvasRect.sizeDelta.x / Screen.width);
|
||||
float w = menuPanel.rect.width;
|
||||
float h = menuPanel.rect.height;
|
||||
|
||||
// 以指定坐标为中心进行位置调整
|
||||
pos.y = Mathf.Max(Mathf.Min(pos.y, Screen.height - h / 2f), h / 2f); // 如果超出则向上移动
|
||||
pos.x = Mathf.Max(Mathf.Min(pos.x, Screen.width - w / 2f), w / 2f); // 如果超出右侧则向左移动
|
||||
|
||||
menuPanel.pivot = Vector2.one * 0.5f; // 设置为中心
|
||||
menuPanel.anchorMin = Vector2.zero;
|
||||
menuPanel.anchorMax = Vector2.zero;
|
||||
menuPanel.anchoredPosition = pos;
|
||||
menuPanel.gameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 关闭上下文菜单
|
||||
/// </summary>
|
||||
private void CloseMenu()
|
||||
{
|
||||
if (menuPanel)
|
||||
{
|
||||
menuPanel.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将实际状态反映到 UI 显示
|
||||
/// </summary>
|
||||
private void UpdateUI()
|
||||
{
|
||||
if (uniwinc)
|
||||
{
|
||||
if (transparentToggle)
|
||||
{
|
||||
transparentToggle.SetIsOnWithoutNotify(uniwinc.isTransparent);
|
||||
}
|
||||
|
||||
if (alphaSlider)
|
||||
{
|
||||
alphaSlider.SetValueWithoutNotify(uniwinc.alphaValue);
|
||||
}
|
||||
|
||||
if (topmostToggle)
|
||||
{
|
||||
topmostToggle.SetIsOnWithoutNotify(uniwinc.isTopmost);
|
||||
}
|
||||
|
||||
if (bottommostToggle)
|
||||
{
|
||||
bottommostToggle.SetIsOnWithoutNotify(uniwinc.isBottommost);
|
||||
}
|
||||
|
||||
if (zoomedToggle)
|
||||
{
|
||||
zoomedToggle.SetIsOnWithoutNotify(uniwinc.isZoomed);
|
||||
}
|
||||
|
||||
if (allowDropToggle)
|
||||
{
|
||||
allowDropToggle.SetIsOnWithoutNotify(uniwinc.allowDropFiles);
|
||||
}
|
||||
|
||||
if (dragMoveToggle)
|
||||
{
|
||||
dragMoveToggle.isOn = (uniWinMoveHandle && uniWinMoveHandle.isActiveAndEnabled);
|
||||
}
|
||||
|
||||
if (fitWindowDropdown)
|
||||
{
|
||||
if (uniwinc.shouldFitMonitor)
|
||||
{
|
||||
fitWindowDropdown.value = uniwinc.monitorToFit + 1;
|
||||
if (zoomedToggle) zoomedToggle.interactable = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
fitWindowDropdown.value = 0;
|
||||
if (zoomedToggle) zoomedToggle.interactable = true;
|
||||
}
|
||||
fitWindowDropdown.RefreshShownValue();
|
||||
}
|
||||
|
||||
if (transparentTypeDropdown)
|
||||
{
|
||||
transparentTypeDropdown.value = (int)uniwinc.transparentType;
|
||||
transparentTypeDropdown.RefreshShownValue();
|
||||
}
|
||||
|
||||
|
||||
if (hitTestTypeDropdown)
|
||||
{
|
||||
hitTestTypeDropdown.value = (int)uniwinc.hitTestType;
|
||||
hitTestTypeDropdown.RefreshShownValue();
|
||||
}
|
||||
|
||||
// 同时更新点击测试部分的显示
|
||||
UpdateHitTestUI();
|
||||
}
|
||||
|
||||
// 即使没有 UniWinC 也能运行的部分
|
||||
if (showBorderlineToggle && borderlinePanel)
|
||||
{
|
||||
borderlinePanel.gameObject.SetActive(showBorderlineToggle.isOn);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新点击测试相关的 UI
|
||||
/// 由于会自动变化,需要比 UpdateUI() 更频繁地更新
|
||||
/// </summary>
|
||||
public void UpdateHitTestUI()
|
||||
{
|
||||
if (uniwinc)
|
||||
{
|
||||
if (clickThroughToggle)
|
||||
{
|
||||
clickThroughToggle.SetIsOnWithoutNotify(uniwinc.isClickThrough);
|
||||
if (uniwinc.hitTestType == UniWindowController.HitTestType.None)
|
||||
{
|
||||
clickThroughToggle.interactable = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
clickThroughToggle.interactable = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (uniwinc.hitTestType == UniWindowController.HitTestType.Opacity && uniwinc.isTransparent)
|
||||
{
|
||||
if (pickedColorImage)
|
||||
{
|
||||
pickedColorImage.color = uniwinc.pickedColor;
|
||||
}
|
||||
|
||||
if (pickedColorText)
|
||||
{
|
||||
pickedColorText.text = $"Alpha:{uniwinc.pickedColor.a:P0}";
|
||||
pickedColorText.color = Color.black;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pickedColorImage)
|
||||
{
|
||||
pickedColorImage.color = Color.gray;
|
||||
}
|
||||
|
||||
if (pickedColorText)
|
||||
{
|
||||
pickedColorText.text = $"颜色拾取器已禁用";
|
||||
pickedColorText.color = Color.gray;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新显示器选择下拉列表的选项
|
||||
/// 之后需要调用 UpdateUI()
|
||||
/// </summary>
|
||||
void UpdateMonitorDropdown()
|
||||
{
|
||||
if (!fitWindowDropdown) return;
|
||||
|
||||
// 删除除第一项以外的选项
|
||||
fitWindowDropdown.options.RemoveRange(1, fitWindowDropdown.options.Count - 1);
|
||||
|
||||
if (!uniwinc)
|
||||
{
|
||||
fitWindowDropdown.value = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int count = UniWindowController.GetMonitorCount();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
fitWindowDropdown.options.Add(new Dropdown.OptionData("适配显示器 " + i));
|
||||
}
|
||||
if (uniwinc.monitorToFit >= count)
|
||||
{
|
||||
uniwinc.monitorToFit = count - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 如果 UI 中有文本框,则显示消息。否则输出到控制台
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
public void OutputMessage(string text)
|
||||
{
|
||||
if (messageText)
|
||||
{
|
||||
messageText.text = text;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log(text);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 如果 UI 中有客户端大小文本框,则显示消息。否则输出到控制台
|
||||
/// </summary>
|
||||
public void ShowClientSize()
|
||||
{
|
||||
if (!uniwinc) return;
|
||||
|
||||
string text = "Client " + uniwinc.clientSize;
|
||||
if (clientSizeText)
|
||||
{
|
||||
clientSizeText.text = text;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4f4b26af82054284b89cba410c27b75d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8878429ebc524544d849c1bc8884262a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,29 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEngine.TestTools;
|
||||
using NUnit.Framework;
|
||||
using System.Collections;
|
||||
|
||||
namespace Lrss3.Xuniwindowcontroller.Editor.Tests
|
||||
{
|
||||
|
||||
class EditorExampleTest
|
||||
{
|
||||
|
||||
[Test]
|
||||
public void EditorSampleTestSimplePasses()
|
||||
{
|
||||
// Use the Assert class to test conditions.
|
||||
}
|
||||
|
||||
// A UnityTest behaves like a coroutine in PlayMode
|
||||
// and allows you to yield null to skip a frame in EditMode
|
||||
[UnityTest]
|
||||
public IEnumerator EditorSampleTestWithEnumeratorPasses()
|
||||
{
|
||||
// Use the Assert class to test conditions.
|
||||
// yield to skip a frame
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7b16c3acbffcdc7478199eacc7ec8497
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "Lrss3.Xuniwindowcontroller.Editor.Tests",
|
||||
"references": [
|
||||
"Lrss3.Xuniwindowcontroller.Editor",
|
||||
"Lrss3.Xuniwindowcontroller"
|
||||
],
|
||||
"optionalUnityReferences": [
|
||||
"TestAssemblies"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": []
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9cdd0222c2019eb4f984a69d349fa385
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e6602e0b6b65ef7438c1a83bcf07d1b2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "Lrss3.Xuniwindowcontroller.Tests",
|
||||
"references": [
|
||||
"Lrss3.Xuniwindowcontroller"
|
||||
],
|
||||
"optionalUnityReferences": [
|
||||
"TestAssemblies"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": []
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 536bc02f6b95d694cbf83ddcac597970
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,28 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using NUnit.Framework;
|
||||
using System.Collections;
|
||||
|
||||
namespace Lrss3.Xuniwindowcontroller.Tests
|
||||
{
|
||||
|
||||
class RuntimeExampleTest
|
||||
{
|
||||
|
||||
[Test]
|
||||
public void PlayModeSampleTestSimplePasses()
|
||||
{
|
||||
// Use the Assert class to test conditions.
|
||||
}
|
||||
|
||||
// A UnityTest behaves like a coroutine in PlayMode
|
||||
// and allows you to yield null to skip a frame in EditMode
|
||||
[UnityTest]
|
||||
public IEnumerator PlayModeSampleTestWithEnumeratorPasses()
|
||||
{
|
||||
// Use the Assert class to test conditions.
|
||||
// yield to skip a frame
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f5802e9dd8c9bf4fb15aa0be21a95fc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,23 @@
|
||||
This package is based on [UniWindowController](https://github.com/kirurobo/UniWindowController) by Kirurobo.
|
||||
|
||||
Licensed under the MIT License.
|
||||
|
||||
Copyright (c) 2024 Kirurobo
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6f366de21623c6e428017761c1d29bc5
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "com.lrss3.xuniwindowcontroller",
|
||||
"displayName": "XUniWindowController",
|
||||
"version": "0.1.0",
|
||||
"unity": "2022.3",
|
||||
"description": "A Unity native plugin for controlling standalone application windows on Windows and macOS. \nSupports transparency, click-through, topmost/bottommost, maximize, file drop, native file dialogs, and multi-monitor window fitting.",
|
||||
"author": {
|
||||
"name": "Lrss3",
|
||||
"url": "https://github.com/Lrss3"
|
||||
},
|
||||
"keywords": [
|
||||
"window",
|
||||
"transparent",
|
||||
"click-through",
|
||||
"native",
|
||||
"plugin",
|
||||
"windows",
|
||||
"macos"
|
||||
],
|
||||
"category": "library",
|
||||
"dependencies": {},
|
||||
"samples": [
|
||||
{
|
||||
"displayName": "Menu",
|
||||
"description": "Sample menu scene for navigating between different example scenes.",
|
||||
"path": "Samples~/Menu"
|
||||
},
|
||||
{
|
||||
"displayName": "SimpleSample",
|
||||
"description": "A minimal example demonstrating basic window control setup.",
|
||||
"path": "Samples~/SimpleSample"
|
||||
},
|
||||
{
|
||||
"displayName": "UiSample",
|
||||
"description": "Complete UI demonstration with toggles and sliders for controlling window properties (transparency, topmost, click-through, etc.).",
|
||||
"path": "Samples~/UiSample"
|
||||
},
|
||||
{
|
||||
"displayName": "Fullscreen",
|
||||
"description": "Fullscreen mode example with right-click context menu and 3D snowman scene.",
|
||||
"path": "Samples~/Fullscreen"
|
||||
},
|
||||
{
|
||||
"displayName": "FileDialog",
|
||||
"description": "Demonstrates native file open/save dialog integration.",
|
||||
"path": "Samples~/FileDialog"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7a9376ee4260d5a4a94bfab85cb4351a
|
||||
PackageManifestImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user