implement multiple screen.

This commit is contained in:
hecomi
2016-10-28 17:28:22 +09:00
parent ba5ebe8094
commit d9f83cf89e
18 changed files with 409 additions and 196 deletions
Binary file not shown.
@@ -1,44 +0,0 @@
using UnityEngine;
namespace uDesktopDuplication
{
[RequireComponent(typeof(uDesktopDuplication))]
public class MouseDrawer : MonoBehaviour
{
[SerializeField]
Transform cursor;
[SerializeField]
Vector2 modelScale = Vector2.one;
[SerializeField]
Vector2 offset = new Vector2(0.5f, 0.5f);
uDesktopDuplication udd_;
void OnEnable()
{
udd_ = GetComponent<uDesktopDuplication>();
udd_.onMouseMove += OnMouseMove;
}
void OnDisable()
{
udd_.onMouseMove -= OnMouseMove;
}
void OnMouseMove(Vector2 pos)
{
var x = pos.x * modelScale.x * 0.5f;
var y = pos.y * modelScale.y * 0.5f;
var iy = udd_.invertY ? +1 : -1;
var localPos = transform.right * x + iy * transform.up * y;
var worldPos = transform.TransformPoint(localPos);
worldPos += cursor.right * offset.x * cursor.localScale.x;
worldPos += -cursor.up * offset.y * cursor.localScale.y;
cursor.position = worldPos;
}
}
}
@@ -0,0 +1,39 @@
using UnityEngine;
namespace uDesktopDuplication
{
[RequireComponent(typeof(uDD_Texture))]
public class uDD_Cursor : MonoBehaviour
{
[SerializeField]
Transform cursor;
[SerializeField]
Vector2 modelScale = Vector2.one;
[SerializeField]
Vector2 offset = new Vector2(0.5f, 0.5f);
private uDD_Texture texture_;
void OnEnable()
{
texture_ = GetComponent<uDD_Texture>();
}
void Update()
{
var monitor = texture_.monitor;
if (monitor.isPointerVisible) {
var x = (1f * monitor.pointerX / monitor.width - 0.5f) * modelScale.x;
var y = (0.5f - 1f * monitor.pointerY / monitor.height) * modelScale.y;
var iy = texture_.invertY ? +1 : -1;
var localPos = transform.right * x + iy * transform.up * y;
var worldPos = transform.TransformPoint(localPos);
worldPos += cursor.right * offset.x * cursor.localScale.x;
worldPos += -cursor.up * offset.y * cursor.localScale.y;
cursor.position = worldPos;
}
}
}
}
@@ -1,6 +1,6 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: d2d9e4ca459ecb44da8815bafe9655c5 guid: d2d9e4ca459ecb44da8815bafe9655c5
timeCreated: 1477559806 timeCreated: 1477635630
licenseType: Pro licenseType: Pro
MonoImporter: MonoImporter:
serializedVersion: 2 serializedVersion: 2
@@ -0,0 +1,39 @@
using System;
using System.Text;
using System.Runtime.InteropServices;
namespace uDesktopDuplication
{
public static class uDD_Lib
{
[DllImport("uDesktopDuplication")]
public static extern int GetMonitorCount();
[DllImport("uDesktopDuplication")]
public static extern IntPtr GetRenderEventFunc();
[DllImport("uDesktopDuplication")]
public static extern void GetName(int id, StringBuilder buf, int len);
[DllImport("uDesktopDuplication")]
public static extern int GetWidth(int id);
[DllImport("uDesktopDuplication")]
public static extern int GetHeight(int id);
[DllImport("uDesktopDuplication")]
public static extern bool IsPrimary(int id);
[DllImport("uDesktopDuplication")]
public static extern bool IsPointerVisible(int id);
[DllImport("uDesktopDuplication")]
public static extern int GetPointerX(int id);
[DllImport("uDesktopDuplication")]
public static extern int GetPointerY(int id);
[DllImport("uDesktopDuplication")]
public static extern int SetTexturePtr(int id, IntPtr ptr);
public static string GetName(int id)
{
var buf = new StringBuilder(32);
GetName(id, buf, buf.Capacity);
return buf.ToString();
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: cb02196c3e766c14ba398dc130e443e8
timeCreated: 1477643164
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 89616e59e1cccb346bd4e959257990ca, type: 3}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,74 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace uDesktopDuplication
{
public class uDD_Manager : MonoBehaviour
{
private static uDD_Manager instance_;
public static uDD_Manager instance
{
get
{
if (instance_) return instance_;
var go = new GameObject("uDesktopDuplicationManager");
return go.AddComponent<uDD_Manager>();
}
}
private List<uDD_Monitor> monitors_ = new List<uDD_Monitor>();
static public List<uDD_Monitor> monitors
{
get { return instance.monitors_; }
}
static public uDD_Monitor primary
{
get
{
return instance.monitors_.Find(monitor => monitor.isPrimary);
}
}
private Coroutine renderCoroutine_ = null;
void Awake()
{
if (instance_ != null) return;
instance_ = this;
for (int i = 0; i < uDD_Monitor.count; ++i) {
monitors.Add(new uDD_Monitor(i));
}
}
void OnEnable()
{
renderCoroutine_ = StartCoroutine(OnRender());
}
void OnDisable()
{
if (renderCoroutine_ != null) {
StopCoroutine(renderCoroutine_);
renderCoroutine_ = null;
}
}
IEnumerator OnRender()
{
for (;;) {
yield return new WaitForEndOfFrame();
foreach (var monitor in monitors) {
if (monitor.shouldBeUpdated) {
monitor.Render();
}
monitor.shouldBeUpdated = false;
}
}
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 4dccb434f55ebee4f91bfb9935092bbf
timeCreated: 1477643174
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 89616e59e1cccb346bd4e959257990ca, type: 3}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,84 @@
using UnityEngine;
namespace uDesktopDuplication
{
public class uDD_Monitor
{
public uDD_Monitor(int id)
{
this.id = id;
}
public static int count
{
get { return uDD_Lib.GetMonitorCount(); }
}
public int id
{
get;
private set;
}
public string name
{
get { return uDD_Lib.GetName(id); }
}
public bool isPrimary
{
get { return uDD_Lib.IsPrimary(id); }
}
public int width
{
get { return uDD_Lib.GetWidth(id); }
}
public int height
{
get { return uDD_Lib.GetHeight(id); }
}
public bool isPointerVisible
{
get { return uDD_Lib.IsPointerVisible(id); }
}
public int pointerX
{
get { return uDD_Lib.GetPointerX(id); }
}
public int pointerY
{
get { return uDD_Lib.GetPointerY(id); }
}
public bool shouldBeUpdated
{
get;
set;
}
private Texture2D texture_;
public Texture2D texture
{
get
{
if (texture_ == null) {
texture_ = new Texture2D(width, height, TextureFormat.BGRA32, false);
uDD_Lib.SetTexturePtr(id, texture_.GetNativeTexturePtr());
}
return texture_;
}
}
public void Render()
{
GL.IssuePluginEvent(uDD_Lib.GetRenderEventFunc(), id);
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 310590b113d909b43b4ea19702904ac3
timeCreated: 1477643181
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 89616e59e1cccb346bd4e959257990ca, type: 3}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,46 @@
using UnityEngine;
namespace uDesktopDuplication
{
public class uDD_Texture : MonoBehaviour
{
public uDD_Monitor monitor { get; set; }
public bool invertX = false;
public bool invertY = false;
private Material material_;
void OnEnable()
{
if (monitor == null) {
monitor = uDD_Manager.primary;
}
material_ = GetComponent<Renderer>().material;
material_.mainTexture = monitor.texture;
}
void Update()
{
monitor.shouldBeUpdated = true;
UpdateMaterial();
}
void UpdateMaterial()
{
if (invertX) {
material_.EnableKeyword("INVERT_X");
} else {
material_.DisableKeyword("INVERT_X");
}
if (invertY) {
material_.EnableKeyword("INVERT_Y");
} else {
material_.DisableKeyword("INVERT_Y");
}
}
}
}
@@ -1,6 +1,6 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: bb54a34570e4747429b1c5b66c69d356 guid: bb54a34570e4747429b1c5b66c69d356
timeCreated: 1477559813 timeCreated: 1477635636
licenseType: Pro licenseType: Pro
MonoImporter: MonoImporter:
serializedVersion: 2 serializedVersion: 2
@@ -1,97 +0,0 @@
using UnityEngine;
using System;
using System.Collections;
using System.Runtime.InteropServices;
namespace uDesktopDuplication
{
public class uDesktopDuplication : MonoBehaviour
{
[DllImport("uDesktopDuplication")]
private static extern void Initialize();
[DllImport("uDesktopDuplication")]
private static extern int GetWidth();
[DllImport("uDesktopDuplication")]
private static extern int GetHeight();
[DllImport("uDesktopDuplication")]
private static extern bool IsPointerVisible();
[DllImport("uDesktopDuplication")]
private static extern int GetPointerX();
[DllImport("uDesktopDuplication")]
private static extern int GetPointerY();
[DllImport("uDesktopDuplication")]
private static extern int SetTexturePtr(IntPtr ptr);
[DllImport("uDesktopDuplication")]
private static extern IntPtr GetRenderEventFunc();
private Material material_;
public bool invertX = false;
public bool invertY = false;
public delegate void MouseMoveEventHandler(Vector2 pos);
public MouseMoveEventHandler onMouseMove { get; set; }
private Coroutine renderCoroutine_ = null;
void OnEnable()
{
var tex = new Texture2D(GetWidth(), GetHeight(), TextureFormat.BGRA32, false);
material_ = GetComponent<Renderer>().material;
material_.mainTexture = tex;
SetTexturePtr(tex.GetNativeTexturePtr());
renderCoroutine_ = StartCoroutine(OnRender());
}
void OnDisable()
{
if (renderCoroutine_ != null) {
StopCoroutine(renderCoroutine_);
renderCoroutine_ = null;
}
}
void Update()
{
UpdateMouseEvent();
UpdateMaterial();
}
void UpdateMouseEvent()
{
var isVisible = IsPointerVisible();
if (isVisible && onMouseMove != null) {
var x = GetPointerX();
var y = GetPointerY();
var w = GetWidth();
var h = GetHeight();
onMouseMove(new Vector2(2f * x / w - 1f, 1f - 2f * y / h));
}
}
void UpdateMaterial()
{
if (invertX) {
material_.EnableKeyword("INVERT_X");
} else {
material_.DisableKeyword("INVERT_X");
}
if (invertY) {
material_.EnableKeyword("INVERT_Y");
} else {
material_.DisableKeyword("INVERT_Y");
}
}
IEnumerator OnRender()
{
for (;;) {
yield return new WaitForEndOfFrame();
GL.IssuePluginEvent(GetRenderEventFunc(), 0);
}
}
}
}
@@ -1,5 +1,7 @@
#include <d3d11.h> #include <d3d11.h>
#include <dxgi1_2.h> #include <dxgi1_2.h>
#include <vector>
#include <string>
#include "IUnityInterface.h" #include "IUnityInterface.h"
#include "IUnityGraphics.h" #include "IUnityGraphics.h"
@@ -10,21 +12,39 @@
namespace namespace
{ {
IUnityInterfaces* g_unity = nullptr; struct Monitor
IDXGIOutputDuplication* g_deskDupl = nullptr; {
ID3D11Texture2D* g_texture = nullptr; IDXGIOutputDuplication* output = nullptr;
bool g_isPointerVisible = -1; ID3D11Texture2D* texture = nullptr;
int g_pointerX = -1; std::string name = "";
int g_pointerY = -1; bool isPrimary = false;
int g_width = -1; bool isPointerVisible = false;
int g_height = -1; int pointerX = -1;
int pointerY = -1;
int width = -1;
int height = -1;
};
IUnityInterfaces* g_unity = nullptr;
std::vector<Monitor> g_monitors;
} }
extern "C" extern "C"
{ {
void FinalizeDuplication()
{
for (auto& monitor : g_monitors)
{
monitor.output->Release();
}
g_monitors.clear();
}
void InitializeDuplication() void InitializeDuplication()
{ {
FinalizeDuplication();
IDXGIFactory1* factory; IDXGIFactory1* factory;
CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&factory)); CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&factory));
@@ -43,22 +63,18 @@ extern "C"
monitorInfo.cbSize = sizeof(MONITORINFOEX); monitorInfo.cbSize = sizeof(MONITORINFOEX);
GetMonitorInfo(outputDesc.Monitor, &monitorInfo); GetMonitorInfo(outputDesc.Monitor, &monitorInfo);
if (monitorInfo.dwFlags == MONITORINFOF_PRIMARY) Monitor monitor;
{ monitor.name = monitorInfo.szDevice;
g_width = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left; monitor.isPrimary = (monitorInfo.dwFlags == MONITORINFOF_PRIMARY);
g_height = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top; monitor.width = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left;
monitor.height = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top;
auto device = g_unity->Get<IUnityGraphicsD3D11>()->GetDevice(); auto device = g_unity->Get<IUnityGraphicsD3D11>()->GetDevice();
IDXGIOutput1* output1; IDXGIOutput1* output1;
output1 = reinterpret_cast<IDXGIOutput1*>(output); output1 = reinterpret_cast<IDXGIOutput1*>(output);
output1->DuplicateOutput(device, &g_deskDupl); output1->DuplicateOutput(device, &monitor.output);
output->Release(); g_monitors.push_back(monitor);
adapter->Release();
factory->Release();
return;
}
output->Release(); output->Release();
} }
@@ -69,12 +85,6 @@ extern "C"
factory->Release(); factory->Release();
} }
void FinalizeDuplication()
{
g_deskDupl->Release();
g_deskDupl = nullptr;
}
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces) UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces)
{ {
g_unity = unityInterfaces; g_unity = unityInterfaces;
@@ -84,24 +94,27 @@ extern "C"
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API UnityPluginUnload() UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API UnityPluginUnload()
{ {
g_unity = nullptr; g_unity = nullptr;
g_texture = nullptr;
g_width = -1;
g_height = -1;
g_pointerX = -1;
g_pointerY = -1;
FinalizeDuplication(); FinalizeDuplication();
} }
void UNITY_INTERFACE_API OnRenderEvent(int eventId) bool DoesMonitorExist(int id)
{ {
if (g_deskDupl == nullptr || g_texture == nullptr) return; return id >= 0 && id < g_monitors.size();
}
void UNITY_INTERFACE_API OnRenderEvent(int id)
{
if (!DoesMonitorExist(id)) return;
auto& monitor = g_monitors[id];
if (monitor.output == nullptr || monitor.texture == nullptr) return;
HRESULT hr; HRESULT hr;
IDXGIResource* resource = nullptr; IDXGIResource* resource = nullptr;
DXGI_OUTDUPL_FRAME_INFO frameInfo; DXGI_OUTDUPL_FRAME_INFO frameInfo;
const UINT timeout = 100; // ms const UINT timeout = 100; // ms
hr = g_deskDupl->AcquireNextFrame(timeout, &frameInfo, &resource); hr = monitor.output->AcquireNextFrame(timeout, &frameInfo, &resource);
switch (hr) switch (hr)
{ {
case S_OK: case S_OK:
@@ -120,9 +133,9 @@ extern "C"
} }
} }
g_isPointerVisible = frameInfo.PointerPosition.Visible; monitor.isPointerVisible = frameInfo.PointerPosition.Visible == TRUE;
g_pointerX = frameInfo.PointerPosition.Position.x; monitor.pointerX = frameInfo.PointerPosition.Position.x;
g_pointerY = frameInfo.PointerPosition.Position.y; monitor.pointerY = frameInfo.PointerPosition.Position.y;
ID3D11Texture2D* texture; ID3D11Texture2D* texture;
hr = resource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&texture)); hr = resource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&texture));
@@ -137,9 +150,9 @@ extern "C"
ID3D11DeviceContext* context; ID3D11DeviceContext* context;
auto device = g_unity->Get<IUnityGraphicsD3D11>()->GetDevice(); auto device = g_unity->Get<IUnityGraphicsD3D11>()->GetDevice();
device->GetImmediateContext(&context); device->GetImmediateContext(&context);
context->CopyResource(g_texture, texture); context->CopyResource(monitor.texture, texture);
g_deskDupl->ReleaseFrame(); monitor.output->ReleaseFrame();
} }
UNITY_INTERFACE_EXPORT UnityRenderingEvent UNITY_INTERFACE_API GetRenderEventFunc() UNITY_INTERFACE_EXPORT UnityRenderingEvent UNITY_INTERFACE_API GetRenderEventFunc()
@@ -147,33 +160,56 @@ extern "C"
return OnRenderEvent; return OnRenderEvent;
} }
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetWidth() UNITY_INTERFACE_EXPORT size_t UNITY_INTERFACE_API GetMonitorCount()
{ {
return g_width; return g_monitors.size();
} }
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetHeight() UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API GetName(int id, char* buf, int len)
{ {
return g_height; if (!DoesMonitorExist(id)) return;
strcpy_s(buf, len, g_monitors[id].name.c_str());
} }
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API IsPointerVisible() UNITY_INTERFACE_EXPORT bool UNITY_INTERFACE_API IsPrimary(int id)
{ {
return g_isPointerVisible; if (!DoesMonitorExist(id)) return false;
return g_monitors[id].isPrimary;
} }
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetPointerX() UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetWidth(int id)
{ {
return g_pointerX; if (!DoesMonitorExist(id)) return -1;
return g_monitors[id].width;
} }
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetPointerY() UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetHeight(int id)
{ {
return g_pointerY; if (!DoesMonitorExist(id)) return -1;
return g_monitors[id].height;
} }
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API SetTexturePtr(void* texture) UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API IsPointerVisible(int id)
{ {
g_texture = reinterpret_cast<ID3D11Texture2D*>(texture); if (!DoesMonitorExist(id)) return false;
return g_monitors[id].isPointerVisible;
}
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetPointerX(int id)
{
if (!DoesMonitorExist(id)) return -1;
return g_monitors[id].pointerX;
}
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetPointerY(int id)
{
if (!DoesMonitorExist(id)) return -1;
return g_monitors[id].pointerY;
}
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API SetTexturePtr(int id, void* texture)
{
if (!DoesMonitorExist(id)) return;
g_monitors[id].texture = reinterpret_cast<ID3D11Texture2D*>(texture);
} }
} }
Binary file not shown.