Compare commits

..

26 Commits

Author SHA1 Message Date
hecomi
9f8a026c24 add offset angle xyz. 2016-11-13 23:25:53 +09:00
hecomi
dc702c6e1d support option to choise real / fixed scale. 2016-11-13 23:18:00 +09:00
hecomi
5a3af11d08 add thickness control. 2016-11-13 22:58:14 +09:00
hecomi
0646621f73 modify utility icon. 2016-11-13 22:22:57 +09:00
hecomi
c9d6d3ad6a check texture sizes. 2016-11-13 22:22:33 +09:00
hecomi
78ee75a875 improve detection for monitor state change. 2016-11-13 22:15:22 +09:00
hecomi
c83ce50468 improve log. 2016-11-13 21:59:22 +09:00
hecomi
3567182a4d add dpi warning. 2016-11-13 11:12:45 +09:00
hecomi
e466aa65db add offset angle of roundly layouter. 2016-11-13 11:09:39 +09:00
hecomi
a0edc1a439 use system cursor position for zoom when cursor is invisible (e.g. dragging). 2016-11-12 16:28:33 +09:00
hecomi
1eb821b34d add unknown error. 2016-11-12 16:04:37 +09:00
hecomi
212d8ccb9b check zoom values. 2016-11-12 15:22:53 +09:00
hecomi
fac8fe1ea7 fix dpi zero bug. 2016-11-12 15:22:39 +09:00
hecomi
f90178f1db use inline. 2016-11-12 14:46:22 +09:00
hecomi
74e25f2bd7 add scene manager. 2016-11-12 14:38:13 +09:00
hecomi
70c126be6c fix monitor reinitialization bug. 2016-11-12 13:16:00 +09:00
hecomi
f74221bf75 update board. 2016-11-12 04:27:28 +09:00
hecomi
3a705732d1 improve bending. 2016-11-12 04:25:12 +09:00
hecomi
804bfb96bd add board-style screen. 2016-11-12 03:56:46 +09:00
hecomi
63d8f6936d use ComPtr for resources instead of standard smart pointers. 2016-11-12 02:44:20 +09:00
hecomi
e4e4917bcb fix manager non-initialization bug. 2016-11-12 02:05:09 +09:00
hecomi
0e205ecef7 fix zoom bug. 2016-11-12 02:00:04 +09:00
hecomi
cda8024b17 fix break in error image. 2016-11-12 00:40:11 +09:00
hecomi
05085f7d24 fix bug caused when releasing duplication output. 2016-11-10 23:33:19 +09:00
hecomi
52eafbe919 change unsupported texture. 2016-11-10 23:21:04 +09:00
hecomi
be1e0c25bb expand aabb to avoid culling. 2016-11-10 23:06:24 +09:00
45 changed files with 690 additions and 225 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 42d6b6dbae38a384e882c2c907915139
timeCreated: 1478889784
licenseType: Pro
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9ce9467b01f36d647ace156faef9cb9f
timeCreated: 1478927635
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -14,22 +14,35 @@ public class Loupe : MonoBehaviour
void Update()
{
CheckVariables();
if (uDesktopDuplication.Manager.cursorMonitorId < 0) return;
uddTexture_.monitorId = uDesktopDuplication.Manager.cursorMonitorId;
// To get other monitor textures, set dirty flag.
foreach (var monitor in uDesktopDuplication.Manager.monitors) {
monitor.CreateTexture();
monitor.shouldBeUpdated = true;
foreach (var target in uDesktopDuplication.Manager.monitors) {
target.CreateTexture();
target.shouldBeUpdated = true;
}
var x = (float)uddTexture_.monitor.cursorX / uddTexture_.monitor.width;
var y = (float)uddTexture_.monitor.cursorY / uddTexture_.monitor.height;
var monitor = uddTexture_.monitor;
var cursorX = monitor.isCursorVisible ? monitor.cursorX : monitor.systemCursorX;
var cursorY = monitor.isCursorVisible ? monitor.cursorY : monitor.systemCursorY;
var x = (float)cursorX / monitor.width;
var y = (float)cursorY / monitor.height;
var w = 1f / zoom;
var h = w / aspect * uddTexture_.monitor.aspect;
var h = w / aspect * monitor.aspect;
x = Mathf.Clamp(x - w / 2, 0f, 1f - w);
y = Mathf.Clamp(y - h / 2, 0f, 1f - h);
uddTexture_.clipPos = new Vector2(x, y);
uddTexture_.clipScale = new Vector2(w, h);
}
void CheckVariables()
{
if (zoom < 1f) zoom = 1f;
if (aspect < 0.01f) aspect = 0.01f;
}
}

View File

@@ -1,20 +1,41 @@
using UnityEngine;
using System.Collections.Generic;
using MeshForwardDirection = uDesktopDuplication.Texture.MeshForwardDirection;
public class MultipleMonitorCreator : MonoBehaviour
{
[SerializeField] GameObject monitorPrefab;
[SerializeField] bool removeIfUnsupported = true;
[SerializeField] float removeWaitDuration = 5f;
[Tooltip("Create monitors using this prefab.")]
[SerializeField]
GameObject monitorPrefab;
[Tooltip("Use same scale as real using DPI.")]
[SerializeField]
bool useRealScale = true;
[Tooltip("Use this sacle as width if useRealScale is false.")]
[SerializeField]
float scale = 0.5f;
[Tooltip("Remove unsupported monitors automatically after removeWaitDuration.")]
[SerializeField]
bool removeIfUnsupported = true;
[Tooltip("Remove unsupported monitors automatically after removeWaitDuration.")]
[SerializeField]
float removeWaitDuration = 5f;
bool hasMonitorUnsupportStateChecked = false;
float removeWaitTimer_ = 0f;
[Tooltip("Please specify the surface direction of the mesh (e.g. Plane => Y.)")]
public MeshForwardDirection meshForwardDirection = MeshForwardDirection.Z;
public class MonitorInfo
{
public GameObject gameObject { get; set; }
public Quaternion originalRotation { get; set; }
public uDesktopDuplication.Texture uddTexture { get; set; }
public Vector3 meshBounds;
public Mesh mesh { get; set; }
}
private List<MonitorInfo> monitors_ = new List<MonitorInfo>();
@@ -22,6 +43,7 @@ public class MultipleMonitorCreator : MonoBehaviour
void Start()
{
uDesktopDuplication.Manager.CreateInstance();
Create();
}
@@ -30,6 +52,10 @@ public class MultipleMonitorCreator : MonoBehaviour
if (removeIfUnsupported) {
RemoveUnsupportedDisplayAfterRemoveTimer();
}
if (uDesktopDuplication.Manager.monitorCount != monitors.Count) {
Recreate();
}
}
void OnEnable()
@@ -68,38 +94,53 @@ public class MultipleMonitorCreator : MonoBehaviour
{
ResetRemoveTimer();
// Sort monitors in coordinate order
var monitors = uDesktopDuplication.Manager.monitors;
monitors.Sort((a, b) => a.left - b.left);
// Create monitors
for (int i = 0; i < uDesktopDuplication.Manager.monitorCount; ++i) {
// Create monitor obeject
var go = Instantiate(monitorPrefab);
go.name = "Monitor " + i;
// Expand AABB
var mesh = go.GetComponent<MeshFilter>().mesh; // clone
var aabbScale = mesh.bounds.size;
aabbScale.y = Mathf.Max(aabbScale.y, aabbScale.x);
aabbScale.z = Mathf.Max(aabbScale.z, aabbScale.x);
mesh.bounds = new Bounds(mesh.bounds.center, aabbScale);
// Assign monitor
var texture = go.GetComponent<uDesktopDuplication.Texture>();
texture.monitorId = i;
var monitor = texture.monitor;
// Set width / height
go.transform.localScale = new Vector3(monitor.widthMeter, go.transform.localScale.y, monitor.heightMeter);
float width, height;
if (useRealScale) {
width = monitor.widthMeter;
height = monitor.heightMeter;
} else {
width = scale * (monitor.isHorizontal ? 1f : monitor.aspect);
height = scale * (monitor.isHorizontal ? 1f / monitor.aspect : 1f);
}
if (meshForwardDirection == MeshForwardDirection.Y) {
go.transform.localScale = new Vector3(width, go.transform.localScale.y, height);
} else {
go.transform.localScale = new Vector3(width, height, go.transform.localScale.z);
}
// Set parent as this object
go.transform.SetParent(transform);
// Calc actual size considering mesh size
var bounds = go.GetComponent<MeshFilter>().sharedMesh.bounds.extents * 2f;
// Save
var info = new MonitorInfo();
info.gameObject = go;
info.originalRotation = go.transform.rotation;
info.uddTexture = texture;
info.meshBounds = bounds;
info.mesh = mesh;
monitors_.Add(info);
}
// Sort monitors in coordinate order
monitors_.Sort((a, b) => a.uddTexture.monitor.left - b.uddTexture.monitor.left);
}
void Clear()
@@ -110,7 +151,8 @@ public class MultipleMonitorCreator : MonoBehaviour
monitors_.Clear();
}
void Recreate()
[ContextMenu("Recreate")]
public void Recreate()
{
Clear();
Create();

View File

@@ -6,6 +6,7 @@ public class MultipleMonitorLayouter : MonoBehaviour
protected MultipleMonitorCreator creator_;
[SerializeField] bool updateEveryFrame = true;
[SerializeField] protected float margin = 0.1f;
[SerializeField][Range(0f, 10f)] protected float thickness = 1f;
void Start()
{
@@ -15,14 +16,11 @@ public class MultipleMonitorLayouter : MonoBehaviour
protected virtual void Update()
{
if (updateEveryFrame) {
Layout();
}
}
void LateUpdate()
{
margin = Mathf.Max(margin, 0f);
if (updateEveryFrame) {
Layout();
}
}
protected virtual void Layout()
@@ -32,19 +30,23 @@ public class MultipleMonitorLayouter : MonoBehaviour
var totalWidth = 0f;
foreach (var info in monitors) {
var width = info.uddTexture.monitor.widthMeter * info.meshBounds.x;
var width = info.gameObject.transform.localEulerAngles.x * (info.mesh.bounds.extents.x * 2f);
totalWidth += width;
}
totalWidth += margin * (n - 1);
var x = -totalWidth / 2;
foreach (var info in creator_.monitors) {
var monitor = info.uddTexture.monitor;
x += (monitor.widthMeter * info.meshBounds.x) / 2;
foreach (var info in monitors) {
var width = info.gameObject.transform.localEulerAngles.x;
x += (width * info.mesh.bounds.extents.x);
info.gameObject.transform.localPosition = new Vector3(x, 0f, 0f);
info.gameObject.transform.localRotation = info.originalRotation;
x += (monitor.widthMeter * info.meshBounds.x) / 2 + margin;
x += (width * info.mesh.bounds.extents.x) + margin;
}
foreach (var info in monitors) {
info.uddTexture.thickness = thickness;
}
}

View File

@@ -3,11 +3,12 @@
public class MultipleMonitorRoundLayouter : MultipleMonitorLayouter
{
[SerializeField] float radius = 10f;
[SerializeField] Vector3 offsetAngle = Vector3.zero;
void OnDisable()
{
foreach (var info in creator_.monitors) {
info.uddTexture.bend = uDesktopDuplication.Texture.Bend.Off;
info.uddTexture.bend = false;
}
}
@@ -18,7 +19,7 @@ public class MultipleMonitorRoundLayouter : MultipleMonitorLayouter
var totalWidth = 0f;
foreach (var info in monitors) {
var width = info.uddTexture.monitor.widthMeter * info.meshBounds.x;
var width = info.gameObject.transform.localScale.x * (info.mesh.bounds.extents.x * 2f);
totalWidth += width;
}
totalWidth += margin * (n - 1);
@@ -27,18 +28,25 @@ public class MultipleMonitorRoundLayouter : MultipleMonitorLayouter
var totalAngle = totalWidth / radius;
float angle = -totalAngle / 2;
var offsetRot = Quaternion.Euler(offsetAngle);
foreach (var info in monitors) {
var uddTex = info.uddTexture;
var width = uddTex.monitor.widthMeter * info.meshBounds.x;
var width = info.gameObject.transform.localScale.x * (info.mesh.bounds.extents.x * 2f);
angle += (width / radius) * 0.5f;
uddTex.transform.localPosition = radius * new Vector3(Mathf.Sin(angle), 0f, Mathf.Cos(angle) - 1f);
uddTex.transform.localRotation = Quaternion.AngleAxis(angle * Mathf.Rad2Deg, Vector3.up) * info.originalRotation;
var pos = radius * new Vector3(Mathf.Sin(angle), 0f, Mathf.Cos(angle) - 1f);
pos += radius * Vector3.forward;
pos = offsetRot * pos;
pos -= radius * Vector3.forward;
uddTex.transform.localPosition = pos;
uddTex.transform.localRotation = offsetRot * Quaternion.AngleAxis(angle * Mathf.Rad2Deg, Vector3.up) * info.originalRotation;
angle += (width * 0.5f + margin) / radius;
uddTex.bend = uDesktopDuplication.Texture.Bend.Y;
uddTex.bend = true;
uddTex.meshForwardDirection = creator_.meshForwardDirection;
uddTex.radius = radius;
uddTex.width = uddTex.monitor.widthMeter;
uddTex.thickness = thickness;
uddTex.width = uddTex.transform.localScale.x;
}
}

View File

@@ -0,0 +1,50 @@
using UnityEngine;
using UnityEngine.SceneManagement;
public class UddSceneManager : MonoBehaviour
{
public static UddSceneManager instance { get; set; }
[SerializeField] string[] scenes;
[SerializeField] int sceneNo = 0;
void Awake()
{
if (!instance) {
instance = this;
} else {
Destroy(gameObject);
}
}
void Start()
{
DontDestroyOnLoad(gameObject);
Load();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.RightArrow)) {
Next();
} else if (Input.GetKeyDown(KeyCode.LeftArrow)) {
Prev();
}
}
void Next()
{
sceneNo = (sceneNo + 1) % scenes.Length;
Load();
}
void Prev()
{
sceneNo = (sceneNo - 1) % scenes.Length;
Load();
}
void Load()
{
SceneManager.LoadScene(scenes[sceneNo]);
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 426ff762e9c02b0499e1453018ecdc94
timeCreated: 1478927673
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 75494e992a22ea44d9b614d7fd3dc235
folderAsset: yes
timeCreated: 1478887431
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,78 @@
fileFormatVersion: 2
guid: d6b30b913257fee4d8246bf7a2620fcd
timeCreated: 1478887431
licenseType: Pro
ModelImporter:
serializedVersion: 19
fileIDToRecycleName:
100000: //RootNode
400000: //RootNode
2300000: //RootNode
3300000: //RootNode
4300000: pCube1
4300002: uDD_Board
9500000: //RootNode
materials:
importMaterials: 0
materialName: 0
materialSearch: 1
animations:
legacyGenerateAnimations: 4
bakeSimulation: 0
resampleCurves: 1
optimizeGameObjects: 0
motionNodeName:
animationImportErrors:
animationImportWarnings:
animationRetargetingWarnings:
animationDoRetargetingWarnings: 0
animationCompression: 1
animationRotationError: 0.5
animationPositionError: 0.5
animationScaleError: 0.5
animationWrapMode: 0
extraExposedTransformPaths: []
clipAnimations: []
isReadable: 0
meshes:
lODScreenPercentages: []
globalScale: 0.1
meshCompression: 0
addColliders: 0
importBlendShapes: 1
swapUVChannels: 0
generateSecondaryUV: 0
useFileUnits: 1
optimizeMeshForGPU: 1
keepQuads: 0
weldVertices: 1
secondaryUVAngleDistortion: 8
secondaryUVAreaDistortion: 15.000001
secondaryUVHardAngle: 88
secondaryUVPackMargin: 4
useFileScale: 1
tangentSpace:
normalSmoothAngle: 60
normalImportMode: 0
tangentImportMode: 2
importAnimation: 0
copyAvatar: 0
humanDescription:
human: []
skeleton: []
armTwist: 0.5
foreArmTwist: 0.5
upperLegTwist: 0.5
legTwist: 0.5
armStretch: 0.05
legStretch: 0.05
feetSpacing: 0
rootMotionBoneName:
hasTranslationDoF: 0
lastHumanDescriptionAvatarSource: {instanceID: 0}
animationType: 0
humanoidOversampling: 1
additionalBone: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

@@ -37,6 +37,7 @@ public enum MonitorState
CurrentlyNotAvailable = 4,
SessionDisconnected = 5,
AccessLost = 6,
Unknown = 999,
}
public enum DebugMode
@@ -85,6 +86,8 @@ public static class Lib
[DllImport("uDesktopDuplication")]
public static extern IntPtr GetRenderEventFunc();
[DllImport("uDesktopDuplication")]
public static extern int GetId(int id);
[DllImport("uDesktopDuplication")]
public static extern MonitorState GetState(int id);
[DllImport("uDesktopDuplication")]
public static extern void GetName(int id, StringBuilder buf, int len);

View File

@@ -11,21 +11,7 @@ public class Manager : MonoBehaviour
private static Manager instance_;
public static Manager instance
{
get
{
if (instance_) {
return instance_;
}
var manager = FindObjectOfType<Manager>();
if (manager) {
manager.Awake();
return manager;
}
var go = new GameObject("uDesktopDuplicationManager");
return go.AddComponent<Manager>();
}
get { return CreateInstance(); }
}
private List<Monitor> monitors_ = new List<Monitor>();
@@ -63,6 +49,31 @@ public class Manager : MonoBehaviour
public delegate void ReinitializeHandler();
public static event ReinitializeHandler onReinitialized;
public static Manager CreateInstance()
{
if (instance_) {
return instance_;
}
var manager = FindObjectOfType<Manager>();
if (manager) {
manager.Awake();
return manager;
}
var go = new GameObject("uDesktopDuplicationManager");
return go.AddComponent<Manager>();
}
public static Monitor GetMonitor(int id)
{
if (id < 0 || id >= Manager.monitors.Count) {
Debug.LogErrorFormat("[uDD::Error] there is no monitor whose id is {0}.", id);
return Manager.primary;
}
return monitors[Mathf.Clamp(id, 0, Manager.monitorCount - 1)];
}
void Awake()
{
Lib.SetDebugMode(debugMode);
@@ -104,9 +115,12 @@ public class Manager : MonoBehaviour
[ContextMenu("Reinitialize")]
void Reinitialize()
{
Debug.Log("[uDesktopDuplication] Reinitialize");
Debug.Log("[uDD] Reinitialize");
Lib.Reinitialize();
if (onReinitialized != null) onReinitialized();
CreateMonitors();
if (onReinitialized != null) {
onReinitialized();
}
}
void ReinitializeIfNeeded()
@@ -180,6 +194,17 @@ public class Manager : MonoBehaviour
monitors[i].Reinitialize();
}
}
void WaitThenDo(System.Action func, float sec)
{
StartCoroutine(_WaitThenDo(func, sec));
}
IEnumerator _WaitThenDo(System.Action func, float sec)
{
yield return new WaitForSeconds(sec);
func();
}
}
}

View File

@@ -1,4 +1,5 @@
using UnityEngine;
using System.Runtime.InteropServices;
namespace uDesktopDuplication
{
@@ -11,24 +12,31 @@ public class Monitor
switch (state)
{
case MonitorState.Available:
break;
case MonitorState.InvalidArg:
Debug.LogErrorFormat("[{0}:{1}] Invalid.", id, name);
Debug.LogErrorFormat("[uDD] {0}:{1} => Invalid.", id, name);
break;
case MonitorState.AccessDenied:
Debug.LogErrorFormat("[{0}:{1}] Access Denied.", id, name);
Debug.LogWarningFormat("[uDD] {0}:{1} => Access Denied.", id, name);
break;
case MonitorState.Unsupported:
Debug.LogErrorFormat("[{0}:{1}] Unsupported.", id, name);
Debug.LogWarningFormat("[uDD] {0}:{1} => Unsupported.", id, name);
break;
case MonitorState.SessionDisconnected:
Debug.LogErrorFormat("[{0}:{1}] Disconnected.", id, name);
Debug.LogWarningFormat("[uDD] {0}:{1} => Disconnected.", id, name);
break;
case MonitorState.NotSet:
Debug.LogErrorFormat("[{0}:{1}] Something wrong.", id, name);
Debug.LogErrorFormat("[uDD] {0}:{1} => Something wrong.", id, name);
break;
default:
Debug.LogErrorFormat("[uDD] {0}:{1} => Unknown error.", id, name);
break;
}
if (dpiX == 0 || dpiY == 0) {
Debug.LogWarningFormat("[uDD] {0}:{1} => Could not get DPI", id, name);
}
}
public int id
@@ -94,12 +102,22 @@ public class Monitor
public int dpiX
{
get { return Lib.GetDpiX(id); }
get
{
var dpi = Lib.GetDpiX(id);
if (dpi == 0) dpi = 100; // when monitors are duplicated
return dpi;
}
}
public int dpiY
{
get { return Lib.GetDpiY(id); }
get
{
var dpi = Lib.GetDpiY(id);
if (dpi == 0) dpi = 100; // when monitors are duplicated
return dpi;
}
}
public float widthMeter
@@ -147,6 +165,24 @@ public class Monitor
get { return Lib.GetCursorY(id); }
}
public int systemCursorX
{
get
{
var p = Utility.GetCursorPos();
return p.x - left;
}
}
public int systemCursorY
{
get
{
var p = Utility.GetCursorPos();
return p.y - top;
}
}
public int cursorShapeWidth
{
get { return Lib.GetCursorShapeWidth(id); }

View File

@@ -13,15 +13,16 @@ public class Texture : MonoBehaviour
set
{
monitor_ = value;
material = GetComponent<Renderer>().material;
material = GetComponent<Renderer>().material; // clone
material.mainTexture = monitor_.texture;
material.SetFloat("_Width", transform.localScale.x);
}
}
public int monitorId
{
get { return monitor.id; }
set { monitor = Manager.monitors[Mathf.Clamp(value, 0, Manager.monitorCount - 1)]; }
set { monitor = Manager.GetMonitor(value); }
}
[Header("Invert UVs")]
@@ -33,37 +34,44 @@ public class Texture : MonoBehaviour
public Vector2 clipPos = Vector2.zero;
public Vector2 clipScale = new Vector2(0.2f, 0.2f);
public enum Bend
public enum MeshForwardDirection
{
Off = 0,
Y = 1,
Z = 2,
Y = 0,
Z = 1,
}
public Bend bend
public bool bend
{
get
{
return (Bend)material.GetInt("_Bend");
return material.GetInt("_Bend") != 0;
}
set
{
if (value) {
material.EnableKeyword("BEND_ON");
} else {
material.DisableKeyword("BEND_ON");
}
}
}
public MeshForwardDirection meshForwardDirection
{
get
{
return (MeshForwardDirection)material.GetInt("_Forward");
}
set
{
switch (value) {
case Bend.Off:
material.SetInt("_Bend", 0);
material.DisableKeyword("_BEND_OFF");
material.DisableKeyword("_BEND_Y");
material.DisableKeyword("_BEND_Z");
break;
case Bend.Y:
material.SetInt("_Bend", 1);
material.DisableKeyword("_BEND_OFF");
case MeshForwardDirection.Y:
material.SetInt("_Forward", 0);
material.EnableKeyword("_BEND_Y");
material.DisableKeyword("_BEND_Z");
break;
case Bend.Z:
material.SetInt("_Bend", 2);
material.DisableKeyword("_BEND_OFF");
case MeshForwardDirection.Z:
material.SetInt("_Forward", 1);
material.DisableKeyword("_BEND_Y");
material.EnableKeyword("_BEND_Z");
break;
@@ -83,6 +91,12 @@ public class Texture : MonoBehaviour
set { material.SetFloat("_Width", value); }
}
public float thickness
{
get { return material.GetFloat("_Thickness"); }
set { material.SetFloat("_Thickness", value); }
}
public Material material
{
get;

View File

@@ -0,0 +1,30 @@
using UnityEngine;
using System.Runtime.InteropServices;
namespace uDesktopDuplication
{
public struct MousePoint
{
public int x;
public int y;
}
public static class Utility
{
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetCursorPos(out MousePoint point);
public static MousePoint GetCursorPos()
{
MousePoint p;
if (!GetCursorPos(out p)) {
p.x = -1;
p.y = -1;
}
return p;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 6c7e8da181b03ce4fb343ffa33cbb929
timeCreated: 1479043365
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 89616e59e1cccb346bd4e959257990ca, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -21,7 +21,7 @@ struct Input
float2 uv_MainTex;
};
float2 uddInvertUV(float2 uv)
inline float2 uddInvertUV(float2 uv)
{
#ifdef INVERT_X
uv.x = 1.0 - uv.x;
@@ -32,7 +32,7 @@ float2 uddInvertUV(float2 uv)
return uv;
}
float2 uddRotateUV(float2 uv)
inline float2 uddRotateUV(float2 uv)
{
#ifdef ROTATE90
float2 tmp = uv;
@@ -49,7 +49,7 @@ float2 uddRotateUV(float2 uv)
return uv;
}
float2 uddClipUV(float2 uv)
inline float2 uddClipUV(float2 uv)
{
uv.x = _ClipX + uv.x * _ClipWidth;
uv.y = _ClipY + uv.y * _ClipHeight;
@@ -92,4 +92,27 @@ inline fixed4 uddGetScreenTextureWithCursor(float2 uv)
return color;
}
inline void uddBendVertex(inout float4 v, half radius, half width, half thickness)
{
#ifdef BEND_ON
half angle = width * v.x / radius;
#ifdef _FORWARD_Z
v.y *= thickness;
radius -= v.y;
v.y += radius * (1 - cos(angle));
#elif _FORWARD_Y
v.z *= thickness;
radius -= v.z;
v.z += radius * (1 - cos(angle));
#endif
v.x = radius * sin(angle) / width;
#else
#ifdef _FORWARD_Z
v.y *= thickness;
#elif _FORWARD_Y
v.z *= thickness;
#endif
#endif
}
#endif

View File

@@ -6,8 +6,10 @@ Properties
_Color ("Color", Color) = (1, 1, 1, 1)
_MainTex ("Texture", 2D) = "white" {}
_CursorTex ("Cursor Texture", 2D) = "white" {}
[KeywordEnum(Off, Y, Z)] _Bend("Bending", Int) = 0
[PowerSlider(10.0)]_Radius ("Radius", Range(1, 100)) = 30
[KeywordEnum(Y, Z)] _Forward("Mesh Forward Direction", Int) = 0
[Toggle(BEND_ON)] _Bend("Use Bend", Int) = 0
[PowerSlider(10.0)] _Radius("Bend Radius", Range(1, 100)) = 30
[PowerSlider(10.0)] _Thickness("Thickness", Range(0.01, 10)) = 1
[KeywordEnum(Off, Front, Back)] _Cull("Culling", Int) = 2
}
@@ -24,19 +26,12 @@ CGINCLUDE
half _Radius;
half _Width;
half _Thickness;
v2f vert(appdata v)
{
v2f o;
#if defined(_BEND_Z) || defined(_BEND_Y)
half a = _Width * v.vertex.x / _Radius;
v.vertex.x = _Radius * sin(a) / _Width;
#ifdef _BEND_Y
v.vertex.y += _Radius * (1 - cos(a));
#elif _BEND_Z
v.vertex.z += _Radius * (1 - cos(a));
#endif
#endif
uddBendVertex(v.vertex, _Radius, _Width, _Thickness);
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
@@ -58,7 +53,8 @@ Pass
#pragma multi_compile ___ INVERT_Y
#pragma multi_compile ___ ROTATE90 ROTATE180 ROTATE270
#pragma multi_compile ___ USE_CLIP
#pragma multi_compile _BEND_OFF _BEND_Y _BEND_Z
#pragma multi_compile ___ BEND_ON
#pragma multi_compile _FORWARD_Y _FORWARD_Z
ENDCG
}

View File

@@ -6,6 +6,11 @@ Properties
_Color ("Color", Color) = (1, 1, 1, 1)
_MainTex ("Texture", 2D) = "white" {}
_Mask ("Mask", Range(0, 1)) = 0.1
_CursorTex ("Cursor Texture", 2D) = "white" {}
[KeywordEnum(Y, Z)] _Forward("Mesh Forward Direction", Int) = 0
[Toggle(BEND_ON)] _Bend("Use Bend", Int) = 0
[PowerSlider(10.0)] _Radius("Bend Radius", Range(1, 100)) = 30
[PowerSlider(10.0)] _Thickness("Thickness", Range(0.01, 10)) = 1
[KeywordEnum(Off, Front, Back)] _Cull("Culling", Int) = 2
}
@@ -23,10 +28,14 @@ CGINCLUDE
#include "./uDD_Common.cginc"
fixed _Mask;
half _Radius;
half _Width;
half _Thickness;
v2f vert(appdata v)
{
v2f o;
uddBendVertex(v.vertex, _Radius, _Width, _Thickness);
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
@@ -51,6 +60,7 @@ Pass
#pragma multi_compile ___ ROTATE90 ROTATE180 ROTATE270
#pragma multi_compile ___ USE_BEND
#pragma multi_compile ___ USE_CLIP
#pragma multi_compile _BEND_OFF _BEND_Y _BEND_Z
ENDCG
}

View File

@@ -5,6 +5,11 @@ Properties
{
_Color ("Color", Color) = (1, 1, 1, 1)
_MainTex ("Texture", 2D) = "white" {}
_CursorTex ("Cursor Texture", 2D) = "white" {}
[KeywordEnum(Y, Z)] _Forward("Mesh Forward Direction", Int) = 0
[Toggle(BEND_ON)] _Bend("Use Bend", Int) = 0
[PowerSlider(10.0)] _Radius("Bend Radius", Range(1, 100)) = 30
[PowerSlider(10.0)] _Thickness("Thickness", Range(0.01, 10)) = 1
[KeywordEnum(Off, Front, Back)] _Cull("Culling", Int) = 2
}
@@ -21,9 +26,14 @@ CGINCLUDE
#include "./uDD_Common.cginc"
half _Radius;
half _Width;
half _Thickness;
v2f vert(appdata v)
{
v2f o;
uddBendVertex(v.vertex, _Radius, _Width, _Thickness);
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
@@ -46,6 +56,7 @@ Pass
#pragma multi_compile ___ ROTATE90 ROTATE180 ROTATE270
#pragma multi_compile ___ USE_BEND
#pragma multi_compile ___ USE_CLIP
#pragma multi_compile _BEND_OFF _BEND_Y _BEND_Z
ENDCG
}

View File

@@ -13,18 +13,6 @@ struct ID3D11Device;
ID3D11Device* GetDevice();
// Utility
template <class T>
auto MakeUniqueWithReleaser(T* ptr)
{
const auto deleter = [](T* ptr)
{
if (ptr != nullptr) ptr->Release();
};
return std::unique_ptr<T, decltype(deleter)>(ptr, deleter);
}
// Manager getter
class MonitorManager;
const std::unique_ptr<MonitorManager>& GetMonitorManager();

View File

@@ -1,10 +1,13 @@
#include <d3d11.h>
#include <wrl/client.h>
#include "Common.h"
#include "Debug.h"
#include "MonitorManager.h"
#include "Monitor.h"
#include "Cursor.h"
using namespace Microsoft::WRL;
Cursor::Cursor(Monitor* monitor)
: monitor_(monitor)
@@ -24,16 +27,16 @@ void Cursor::UpdateBuffer(const DXGI_OUTDUPL_FRAME_INFO& frameInfo)
return;
}
x_ = frameInfo.PointerPosition.Position.x;
y_ = frameInfo.PointerPosition.Position.y;
isVisible_ = frameInfo.PointerPosition.Visible != 0;
timestamp_ = frameInfo.LastMouseUpdateTime;
if (isVisible_)
{
GetMonitorManager()->SetCursorMonitorId(monitor_->GetId());
}
x_ = frameInfo.PointerPosition.Position.x;
y_ = frameInfo.PointerPosition.Position.y;
timestamp_ = frameInfo.LastMouseUpdateTime;
if (!IsCursorOnParentMonitor())
{
return;
@@ -149,9 +152,8 @@ void Cursor::UpdateTexture()
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
desc.MiscFlags = 0;
ID3D11Texture2D* texture = nullptr;
ComPtr<ID3D11Texture2D> texture;
hr = GetDevice()->CreateTexture2D(&desc, nullptr, &texture);
const auto textureReleaser = MakeUniqueWithReleaser(texture);
if (FAILED(hr))
{
Debug::Error("Cursor::UpdateTexture() => GetDevice()->CreateTexture2D() failed.");
@@ -172,14 +174,14 @@ void Cursor::UpdateTexture()
return;
}
ID3D11DeviceContext* context;
GetDevice()->GetImmediateContext(&context);
context->CopySubresourceRegion(texture, 0, 0, 0, 0, monitor_->GetUnityTexture(), 0, &box);
context->Release();
{
ComPtr<ID3D11DeviceContext> context;
GetDevice()->GetImmediateContext(&context);
context->CopySubresourceRegion(texture.Get(), 0, 0, 0, 0, monitor_->GetUnityTexture(), 0, &box);
}
IDXGISurface* surface = nullptr;
hr = texture->QueryInterface(__uuidof(IDXGISurface), (void**)&surface);
const auto surfaceReleaser = MakeUniqueWithReleaser(surface);
ComPtr<IDXGISurface> surface;
hr = texture.As<IDXGISurface>(&surface);
if (FAILED(hr))
{
Debug::Error("Cursor::UpdateTexture() => texture->QueryInterface() failed.");
@@ -286,10 +288,9 @@ void Cursor::GetTexture(ID3D11Texture2D* texture)
return;
}
ID3D11DeviceContext* context;
ComPtr<ID3D11DeviceContext> context;
GetDevice()->GetImmediateContext(&context);
context->UpdateSubresource(texture, 0, nullptr, bgra32Buffer_.get(), GetWidth() * 4, 0);
context->Release();
}

View File

@@ -4,81 +4,28 @@
#include "Debug.h"
decltype(Debug::mode_) Debug::mode_ = Debug::Mode::kFile;
decltype(Debug::mode_) Debug::mode_ = Debug::Mode::File;
decltype(Debug::logFunc_) Debug::logFunc_ = nullptr;
decltype(Debug::errFunc_) Debug::errFunc_ = nullptr;
decltype(Debug::fs_) Debug::fs_;
decltype(Debug::ss_) Debug::ss_;
void Debug::Initialize()
{
if (mode_ == Mode::kFile)
if (mode_ == Mode::File)
{
fs_.open("uDesktopDuplication.log");
Debug::Log("Start");
}
}
void Debug::Finalize()
{
fs_.close();
}
void Debug::Log(const char* msg)
{
switch (mode_)
if (mode_ == Mode::File)
{
case Mode::kNone:
{
break;
}
case Mode::kFile:
{
if (fs_.good())
{
fs_ << "[uDD::Log] " << msg << std::endl;
}
break;
}
case Mode::kUnityLog:
{
if (logFunc_ == nullptr)
{
char buf[256];
sprintf_s(buf, 256, "[uDD::Log] %s", msg);
logFunc_(buf);
break;
}
}
}
}
void Debug::Error(const char* msg)
{
switch (mode_)
{
case Mode::kNone:
{
break;
}
case Mode::kFile:
{
if (fs_.good())
{
fs_ << "[uDD::Err] " << msg << std::endl;
}
break;
}
case Mode::kUnityLog:
{
if (logFunc_ == nullptr)
{
char buf[256];
sprintf_s(buf, 256, "[uDD::Err] %s", msg);
errFunc_(buf);
}
}
Debug::Log("Stop");
fs_.close();
}
}

View File

@@ -1,5 +1,6 @@
#pragma once
#include <fstream>
#include <sstream>
#include "IUnityInterface.h"
// Logging
@@ -8,9 +9,9 @@ class Debug
public:
enum class Mode
{
kNone = 0,
kFile = 1,
kUnityLog = 2,
None = 0,
File = 1,
UnityLog = 2,
};
using DebugLogFuncPtr = void(UNITY_INTERFACE_API *)(const char*);
@@ -21,13 +22,89 @@ public:
static void SetLogFunc(DebugLogFuncPtr func) { logFunc_ = func; }
static void SetErrorFunc(DebugLogFuncPtr func) { errFunc_ = func; }
private:
enum class Level
{
Log,
Error
};
template <class T>
static void Output(T&& arg)
{
if (mode_ == Mode::None) return;
if (ss_.good())
{
ss_ << std::forward<T>(arg);
}
}
static void Flush(Level level)
{
switch (mode_)
{
case Mode::None:
{
return;
}
case Mode::File:
{
if (fs_.good() && ss_.good())
{
const auto str = ss_.str();
fs_ << str << std::endl;
fs_.flush();
}
break;
}
case Mode::UnityLog:
{
if (ss_.good())
{
switch (level)
{
case Level::Log : logFunc_(ss_.str().c_str()); break;
case Level::Error : errFunc_(ss_.str().c_str()); break;
}
}
break;
}
}
ss_.str("");
ss_.clear(std::stringstream::goodbit);
}
template <class Arg, class... RestArgs>
static void _Log(Level level, Arg&& arg, RestArgs&&... restArgs)
{
Output(std::forward<Arg>(arg));
_Log(level, std::forward<RestArgs>(restArgs)...);
}
static void _Log(Level level)
{
Flush(level);
}
public:
static void Log(const char* msg);
static void Error(const char* msg);
template <class Arg, class... RestArgs>
static void Log(Arg&& arg, RestArgs&&... restArgs)
{
Output("[uDD::Log] ");
_Log(Level::Log, std::forward<Arg>(arg), std::forward<RestArgs>(restArgs)...);
}
template <class Arg, class... RestArgs>
static void Error(Arg&& arg, RestArgs&&... restArgs)
{
Output("[uDD::Err] ");
_Log(Level::Error, std::forward<Arg>(arg), std::forward<RestArgs>(restArgs)...);
}
private:
static Mode mode_;
static std::ofstream fs_;
static std::ostringstream ss_;
static DebugLogFuncPtr logFunc_;
static DebugLogFuncPtr errFunc_;
};

View File

@@ -6,6 +6,8 @@
#include "MonitorManager.h"
#include "Monitor.h"
using namespace Microsoft::WRL;
Monitor::Monitor(int id)
: id_(id)
@@ -28,17 +30,17 @@ void Monitor::Initialize(IDXGIOutput* output)
GetDpiForMonitor(outputDesc_.Monitor, MDT_RAW_DPI, &dpiX_, &dpiY_);
auto output1 = reinterpret_cast<IDXGIOutput1*>(output);
IDXGIOutputDuplication* deskDupl;
const auto hr = output1->DuplicateOutput(GetDevice(), &deskDupl);
deskDupl_ = std::shared_ptr<IDXGIOutputDuplication>(
deskDupl,
[](IDXGIOutputDuplication* ptr) { ptr->Release(); });
const auto hr = output1->DuplicateOutput(GetDevice(), &deskDupl_);
// TODO: error check
switch (hr)
{
case S_OK:
state_ = State::Available;
Debug::Log("Monitor::Initialize() => OK.");
Debug::Log(" ID : ", GetId());
Debug::Log(" Size : (", GetWidth(), ", ", GetHeight(), ")");
Debug::Log(" DPI : (", GetDpiX(), ", ", GetDpiY(), ")");
break;
case E_INVALIDARG:
state_ = State::InvalidArg;
@@ -65,6 +67,10 @@ void Monitor::Initialize(IDXGIOutput* output)
state_ = State::SessionDisconnected;
Debug::Error("Monitor::Initialize() => Session disconnected.");
break;
default:
state_ = State::Unknown;
Debug::Error("Monitor::Render() => Unknown Error.");
break;
}
}
@@ -73,12 +79,11 @@ void Monitor::Render(UINT timeout)
{
if (!deskDupl_) return;
IDXGIResource* resource = nullptr;
ComPtr<IDXGIResource> resource;
DXGI_OUTDUPL_FRAME_INFO frameInfo;
HRESULT hr;
hr = deskDupl_->AcquireNextFrame(timeout, &frameInfo, &resource);
const auto resourceReleaser = MakeUniqueWithReleaser(resource);
if (FAILED(hr))
{
switch (hr)
@@ -100,6 +105,8 @@ void Monitor::Render(UINT timeout)
Debug::Error("Monitor::Render() => E_INVALIDARG.");
break;
default:
state_ = State::Unknown;
Debug::Error("Monitor::Render() => Unknown Error.");
break;
}
return;
@@ -107,13 +114,25 @@ void Monitor::Render(UINT timeout)
if (unityTexture_)
{
ID3D11Texture2D* texture;
resource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&texture));
ComPtr<ID3D11Texture2D> texture;
resource.As<ID3D11Texture2D>(&texture);
ID3D11DeviceContext* context;
GetDevice()->GetImmediateContext(&context);
context->CopyResource(unityTexture_, texture);
context->Release();
D3D11_TEXTURE2D_DESC srcDesc, dstDesc;
texture->GetDesc(&srcDesc);
texture->GetDesc(&dstDesc);
if (srcDesc.Width != dstDesc.Width ||
srcDesc.Height != dstDesc.Height)
{
Debug::Error("Monitor::Render() => Texture sizes are defferent.");
Debug::Error(" Source : (", srcDesc.Width, ", ", srcDesc.Height, ")");
Debug::Error(" Dest : (", dstDesc.Width, ", ", dstDesc.Height, ")");
}
else
{
ComPtr<ID3D11DeviceContext> context;
GetDevice()->GetImmediateContext(&context);
context->CopyResource(unityTexture_, texture.Get());
}
}
cursor_->UpdateBuffer(frameInfo);
@@ -151,7 +170,7 @@ ID3D11Texture2D* Monitor::GetUnityTexture() const
}
const std::shared_ptr<IDXGIOutputDuplication>& Monitor::GetDeskDupl()
const ComPtr<IDXGIOutputDuplication>& Monitor::GetDeskDupl()
{
return deskDupl_;
}
@@ -183,25 +202,25 @@ bool Monitor::IsPrimary() const
int Monitor::GetLeft() const
{
return outputDesc_.DesktopCoordinates.left;
return static_cast<int>(outputDesc_.DesktopCoordinates.left);
}
int Monitor::GetRight() const
{
return outputDesc_.DesktopCoordinates.right;
return static_cast<int>(outputDesc_.DesktopCoordinates.right);
}
int Monitor::GetTop() const
{
return outputDesc_.DesktopCoordinates.top;
return static_cast<int>(outputDesc_.DesktopCoordinates.top);
}
int Monitor::GetBottom() const
{
return outputDesc_.DesktopCoordinates.bottom;
return static_cast<int>(outputDesc_.DesktopCoordinates.bottom);
}

View File

@@ -2,6 +2,7 @@
#include <d3d11.h>
#include <dxgi1_2.h>
#include <wrl/client.h>
#include <memory>
class Cursor;
@@ -16,6 +17,7 @@ enum class MonitorState
CurrentlyNotAvailable = 4,
SessionDisconnected = 5,
AccessLost = 6,
Unknown = 999,
};
class Monitor
@@ -45,7 +47,7 @@ public:
int GetRotation() const;
int GetDpiX() const;
int GetDpiY() const;
const std::shared_ptr<IDXGIOutputDuplication>& GetDeskDupl();
const Microsoft::WRL::ComPtr<IDXGIOutputDuplication>& GetDeskDupl();
const std::unique_ptr<Cursor>& GetCursor();
private:
@@ -53,7 +55,7 @@ private:
UINT dpiX_ = -1, dpiY_ = -1;
State state_ = State::NotSet;
std::unique_ptr<Cursor> cursor_;
std::shared_ptr<IDXGIOutputDuplication> deskDupl_;
Microsoft::WRL::ComPtr<IDXGIOutputDuplication> deskDupl_;
ID3D11Texture2D* unityTexture_ = nullptr;
DXGI_OUTPUT_DESC outputDesc_;
MONITORINFOEX monitorInfo_;

View File

@@ -1,5 +1,6 @@
#include <d3d11.h>
#include <dxgi1_2.h>
#include <wrl/client.h>
#include <vector>
#include <string>
#include <algorithm>
@@ -8,10 +9,13 @@
#include "IUnityGraphicsD3D11.h"
#include "Common.h"
#include "Debug.h"
#include "Monitor.h"
#include "Cursor.h"
#include "MonitorManager.h"
using namespace Microsoft::WRL;
MonitorManager::MonitorManager()
{
@@ -30,23 +34,20 @@ void MonitorManager::Initialize()
Finalize();
// Get factory
IDXGIFactory1* factory;
CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&factory));
const auto factoryReleaser = MakeUniqueWithReleaser(factory);
ComPtr<IDXGIFactory1> factory;
CreateDXGIFactory1(IID_PPV_ARGS(&factory));
// Check all display adapters
int id = 0;
IDXGIAdapter1* adapter;
ComPtr<IDXGIAdapter1> adapter;
for (int i = 0; (factory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND); ++i)
{
const auto adapterReleaser = MakeUniqueWithReleaser(adapter);
// Search the main monitor from all outputs
IDXGIOutput* output;
ComPtr<IDXGIOutput> output;
for (int j = 0; (adapter->EnumOutputs(j, &output) != DXGI_ERROR_NOT_FOUND); ++j)
{
const auto outputReleaser = MakeUniqueWithReleaser(output);
auto monitor = std::make_shared<Monitor>(id++);
monitor->Initialize(output);
monitor->Initialize(output.Get());
monitors_.push_back(monitor);
}
}
@@ -67,11 +68,36 @@ void MonitorManager::RequireReinitilization()
void MonitorManager::Reinitialize()
{
Debug::Log("MonitorManager::Reinitialize()");
Initialize();
SendMessageToUnity(Message::Reinitialized);
}
void MonitorManager::CheckMonitorNumbers()
{
ComPtr<IDXGIFactory1> factory;
CreateDXGIFactory1(IID_PPV_ARGS(&factory));
int id = 0;
ComPtr<IDXGIAdapter1> adapter;
for (int i = 0; (factory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND); ++i)
{
ComPtr<IDXGIOutput> output;
for (int j = 0; (adapter->EnumOutputs(j, &output) != DXGI_ERROR_NOT_FOUND); ++j)
{
id++;
}
}
if (GetMonitorCount() != id)
{
Debug::Log("Monitor number changed: ", GetMonitorCount(), " => ", id);
RequireReinitilization();
}
}
std::shared_ptr<Monitor> MonitorManager::GetMonitor(int id) const
{
if (id >= 0 && id < monitors_.size())
@@ -84,6 +110,8 @@ std::shared_ptr<Monitor> MonitorManager::GetMonitor(int id) const
void MonitorManager::Update()
{
CheckMonitorNumbers();
if (isReinitializationRequired_)
{
Reinitialize();

View File

@@ -16,6 +16,7 @@ public:
explicit MonitorManager();
~MonitorManager();
void Reinitialize();
void CheckMonitorNumbers();
void RequireReinitilization();
void SetCursorMonitorId(int id) { cursorMonitorId_ = id; }
int GetCursorMonitorId() const { return cursorMonitorId_; }

View File

@@ -29,21 +29,24 @@ extern "C"
{
if (g_unity && !g_manager)
{
g_manager = std::make_unique<MonitorManager>();
Debug::Initialize();
g_manager = std::make_unique<MonitorManager>();
}
}
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API FinalizeUDD()
{
g_manager.reset();
if (g_manager)
{
g_manager.reset();
std::queue<Message> empty;
g_messages.swap(empty);
std::queue<Message> empty;
g_messages.swap(empty);
Debug::SetLogFunc(nullptr);
Debug::SetErrorFunc(nullptr);
Debug::Finalize();
Debug::SetLogFunc(nullptr);
Debug::SetErrorFunc(nullptr);
Debug::Finalize();
}
}
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces)
@@ -138,6 +141,15 @@ extern "C"
g_manager->SetTimeout(timeout);
}
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API GetId(int id)
{
if (!g_manager) return;
if (auto monitor = g_manager->GetMonitor(id))
{
monitor->GetId();
}
}
UNITY_INTERFACE_EXPORT MonitorState UNITY_INTERFACE_API GetState(int id)
{
if (!g_manager) return MonitorState::NotSet;