Compare commits

..

7 Commits

Author SHA1 Message Date
hecomi
f8146c15bd update readme. 2016-10-28 19:33:45 +09:00
hecomi
d5a9827b4d add toggle example. 2016-10-28 19:33:37 +09:00
hecomi
4b499a96de update readme. 2016-10-28 19:23:10 +09:00
hecomi
583326c333 add license. 2016-10-28 19:09:42 +09:00
hecomi
c3ec17dd7b add shader example. 2016-10-28 19:08:08 +09:00
hecomi
6f375e2e5b change class names. / add multiple screen example. / performance tuning. 2016-10-28 18:48:53 +09:00
hecomi
d9f83cf89e implement multiple screen. 2016-10-28 17:28:22 +09:00
46 changed files with 625 additions and 213 deletions

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 678e1de5e6de7914baed516a78940503
folderAsset: yes
timeCreated: 1477643728
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: de6f36e446e5e8a48bf61fe198985bb4
timeCreated: 1477643732
licenseType: Pro
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 445860b05342be845967392bfd70224e
timeCreated: 1477643648
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 281e2991d4d33984fa180845e56cd3f3
timeCreated: 1477648643
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f66b67cb0e751dc4ca0251b38bc8638d
timeCreated: 1477648784
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 78e54899a518eb749a589b921a1b263f
timeCreated: 1477650252
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 71921882396f0f345aa8a66e2fcb0b6c
folderAsset: yes
timeCreated: 1477643608
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,20 @@
using UnityEngine;
public class MultipleMonitorCreator : MonoBehaviour
{
[SerializeField] GameObject monitorPrefab;
[SerializeField] Vector3 margin = new Vector3(20f, 0f, 0f);
void Start()
{
var monitors = uDesktopDuplication.Manager.monitors;
var n = monitors.Count;
for (int i = 0 ; i < n; ++i) {
var go = Instantiate(monitorPrefab);
go.transform.position = transform.position + margin * (i - n / 2f + 0.5f);
var texture = go.GetComponent<uDesktopDuplication.Texture>();
texture.monitorId = i;
}
}
}

View File

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

View File

@@ -0,0 +1,17 @@
using UnityEngine;
public class ToggleMonitors : MonoBehaviour
{
void Update()
{
if (Input.GetKeyDown(KeyCode.Tab)) {
var texture = GetComponent<uDesktopDuplication.Texture>();
if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) {
texture.monitorId--;
} else {
texture.monitorId++;
}
}
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 06ef13d14bbcf9242a8eba19a94803f3
timeCreated: 1477648806
licenseType: Pro
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3abaadab838fb3c4ba342eda7431d4f7
timeCreated: 1477648806
licenseType: Pro
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 647550562f402264fb69871ec732b74c
timeCreated: 1477648806
licenseType: Pro
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,41 @@
using UnityEngine;
namespace uDesktopDuplication
{
[AddComponentMenu("uDesktopDuplication/Cursor"),
RequireComponent(typeof(Texture))]
public class Cursor : MonoBehaviour
{
[SerializeField]
Transform cursor;
[SerializeField]
Vector2 modelScale = Vector2.one;
[SerializeField]
Vector2 offset = new Vector2(0.5f, 0.5f);
private Texture texture_;
void OnEnable()
{
texture_ = GetComponent<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;
worldPos += -cursor.forward * 0.001f;
cursor.position = worldPos;
}
}
}
}

View File

@@ -1,6 +1,6 @@
fileFormatVersion: 2
guid: d2d9e4ca459ecb44da8815bafe9655c5
timeCreated: 1477559806
timeCreated: 1477635630
licenseType: Pro
MonoImporter:
serializedVersion: 2

View File

@@ -0,0 +1,41 @@
using System;
using System.Text;
using System.Runtime.InteropServices;
namespace uDesktopDuplication
{
public static class Lib
{
[DllImport("uDesktopDuplication")]
public static extern int GetMonitorCount();
[DllImport("uDesktopDuplication")]
public static extern void SetTimeout(int timeout);
[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();
}
}
}

View File

@@ -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:

View File

@@ -0,0 +1,85 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace uDesktopDuplication
{
public class Manager : MonoBehaviour
{
private static Manager instance_;
public static Manager instance
{
get
{
if (instance_) return instance_;
var go = new GameObject("uDesktopDuplicationManager");
return go.AddComponent<Manager>();
}
}
private List<Monitor> monitors_ = new List<Monitor>();
static public List<Monitor> monitors
{
get { return instance.monitors_; }
}
static public int monitorCount
{
get { return instance.monitors_.Count; }
}
static public Monitor primary
{
get
{
return instance.monitors_.Find(monitor => monitor.isPrimary);
}
}
[SerializeField, Tooltip("Set Desktop Duplication API timeout (milliseconds).")]
int timeout = 0;
private Coroutine renderCoroutine_ = null;
void Awake()
{
if (instance_ != null) return;
instance_ = this;
for (int i = 0; i < Lib.GetMonitorCount(); ++i) {
monitors.Add(new Monitor(i));
}
Lib.SetTimeout(timeout);
}
void OnEnable()
{
renderCoroutine_ = StartCoroutine(OnRender());
}
void OnDisable()
{
if (renderCoroutine_ != null) {
StopCoroutine(renderCoroutine_);
renderCoroutine_ = null;
}
}
IEnumerator OnRender()
{
for (;;) {
yield return new WaitForEndOfFrame();
for (int i = 0; i < monitors.Count; ++i) {
var monitor = monitors[i];
if (monitor.shouldBeUpdated) {
monitor.Render();
}
monitor.shouldBeUpdated = false;
}
}
}
}
}

View File

@@ -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:

View File

@@ -0,0 +1,79 @@
using UnityEngine;
namespace uDesktopDuplication
{
public class Monitor
{
public Monitor(int id)
{
this.id = id;
}
public int id
{
get;
private set;
}
public string name
{
get { return Lib.GetName(id); }
}
public bool isPrimary
{
get { return Lib.IsPrimary(id); }
}
public int width
{
get { return Lib.GetWidth(id); }
}
public int height
{
get { return Lib.GetHeight(id); }
}
public bool isPointerVisible
{
get { return Lib.IsPointerVisible(id); }
}
public int pointerX
{
get { return Lib.GetPointerX(id); }
}
public int pointerY
{
get { return 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);
Lib.SetTexturePtr(id, texture_.GetNativeTexturePtr());
}
return texture_;
}
}
public void Render()
{
GL.IssuePluginEvent(Lib.GetRenderEventFunc(), id);
}
}
}

View File

@@ -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:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,61 @@
using UnityEngine;
namespace uDesktopDuplication
{
[AddComponentMenu("uDesktopDuplication/Texture")]
public class Texture : MonoBehaviour
{
private Monitor monitor_;
public Monitor monitor
{
get { return monitor_; }
set
{
monitor_ = value;
material_ = GetComponent<Renderer>().material;
material_.mainTexture = monitor_.texture;
}
}
public int monitorId
{
get { return monitor.id; }
set { monitor = Manager.monitors[Mathf.Clamp(value, 0, Manager.monitorCount - 1)]; }
}
public bool invertX = false;
public bool invertY = false;
private Material material_;
void OnEnable()
{
if (monitor == null) {
monitor = Manager.primary;
}
}
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");
}
}
}
}

View File

@@ -1,6 +1,6 @@
fileFormatVersion: 2
guid: bb54a34570e4747429b1c5b66c69d356
timeCreated: 1477559813
timeCreated: 1477635636
licenseType: Pro
MonoImporter:
serializedVersion: 2

View File

@@ -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);
}
}
}
}

View File

@@ -1,5 +1,7 @@
#include <d3d11.h>
#include <dxgi1_2.h>
#include <vector>
#include <string>
#include "IUnityInterface.h"
#include "IUnityGraphics.h"
@@ -10,21 +12,40 @@
namespace
{
IUnityInterfaces* g_unity = nullptr;
IDXGIOutputDuplication* g_deskDupl = nullptr;
ID3D11Texture2D* g_texture = nullptr;
bool g_isPointerVisible = -1;
int g_pointerX = -1;
int g_pointerY = -1;
int g_width = -1;
int g_height = -1;
struct Monitor
{
IDXGIOutputDuplication* output = nullptr;
ID3D11Texture2D* texture = nullptr;
std::string name = "";
bool isPrimary = false;
bool isPointerVisible = false;
int pointerX = -1;
int pointerY = -1;
int width = -1;
int height = -1;
};
IUnityInterfaces* g_unity = nullptr;
int g_timeout = 10;
std::vector<Monitor> g_monitors;
}
extern "C"
{
void FinalizeDuplication()
{
for (auto& monitor : g_monitors)
{
monitor.output->Release();
}
g_monitors.clear();
}
void InitializeDuplication()
{
FinalizeDuplication();
IDXGIFactory1* factory;
CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&factory));
@@ -43,22 +64,18 @@ extern "C"
monitorInfo.cbSize = sizeof(MONITORINFOEX);
GetMonitorInfo(outputDesc.Monitor, &monitorInfo);
if (monitorInfo.dwFlags == MONITORINFOF_PRIMARY)
{
g_width = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left;
g_height = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top;
Monitor monitor;
monitor.name = monitorInfo.szDevice;
monitor.isPrimary = (monitorInfo.dwFlags == MONITORINFOF_PRIMARY);
monitor.width = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left;
monitor.height = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top;
auto device = g_unity->Get<IUnityGraphicsD3D11>()->GetDevice();
IDXGIOutput1* output1;
output1 = reinterpret_cast<IDXGIOutput1*>(output);
output1->DuplicateOutput(device, &g_deskDupl);
auto device = g_unity->Get<IUnityGraphicsD3D11>()->GetDevice();
IDXGIOutput1* output1;
output1 = reinterpret_cast<IDXGIOutput1*>(output);
output1->DuplicateOutput(device, &monitor.output);
output->Release();
adapter->Release();
factory->Release();
return;
}
g_monitors.push_back(monitor);
output->Release();
}
@@ -69,12 +86,6 @@ extern "C"
factory->Release();
}
void FinalizeDuplication()
{
g_deskDupl->Release();
g_deskDupl = nullptr;
}
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces)
{
g_unity = unityInterfaces;
@@ -84,24 +95,26 @@ extern "C"
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API UnityPluginUnload()
{
g_unity = nullptr;
g_texture = nullptr;
g_width = -1;
g_height = -1;
g_pointerX = -1;
g_pointerY = -1;
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;
IDXGIResource* resource = nullptr;
DXGI_OUTDUPL_FRAME_INFO frameInfo;
const UINT timeout = 100; // ms
hr = g_deskDupl->AcquireNextFrame(timeout, &frameInfo, &resource);
hr = monitor.output->AcquireNextFrame(g_timeout, &frameInfo, &resource);
switch (hr)
{
case S_OK:
@@ -110,7 +123,7 @@ extern "C"
}
case DXGI_ERROR_ACCESS_LOST:
{
FinalizeDuplication();
resource->Release();
InitializeDuplication();
return;
}
@@ -120,26 +133,27 @@ extern "C"
}
}
g_isPointerVisible = frameInfo.PointerPosition.Visible;
g_pointerX = frameInfo.PointerPosition.Position.x;
g_pointerY = frameInfo.PointerPosition.Position.y;
monitor.isPointerVisible = frameInfo.PointerPosition.Visible == TRUE;
monitor.pointerX = frameInfo.PointerPosition.Position.x;
monitor.pointerY = frameInfo.PointerPosition.Position.y;
ID3D11Texture2D* texture;
hr = resource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&texture));
if (hr != S_OK)
{
resource->Release();
monitor.output->ReleaseFrame();
return;
}
resource->Release();
ID3D11DeviceContext* context;
auto device = g_unity->Get<IUnityGraphicsD3D11>()->GetDevice();
device->GetImmediateContext(&context);
context->CopyResource(g_texture, texture);
context->CopyResource(monitor.texture, texture);
g_deskDupl->ReleaseFrame();
resource->Release();
texture->Release();
monitor.output->ReleaseFrame();
}
UNITY_INTERFACE_EXPORT UnityRenderingEvent UNITY_INTERFACE_API GetRenderEventFunc()
@@ -147,33 +161,61 @@ extern "C"
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 SetTimeout(int timeout)
{
return g_height;
g_timeout = timeout;
}
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API IsPointerVisible()
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API GetName(int id, char* buf, int len)
{
return g_isPointerVisible;
if (!DoesMonitorExist(id)) return;
strcpy_s(buf, len, g_monitors[id].name.c_str());
}
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetPointerX()
UNITY_INTERFACE_EXPORT bool UNITY_INTERFACE_API IsPrimary(int id)
{
return g_pointerX;
if (!DoesMonitorExist(id)) return false;
return g_monitors[id].isPrimary;
}
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetPointerY()
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetWidth(int id)
{
return g_pointerY;
if (!DoesMonitorExist(id)) return -1;
return g_monitors[id].width;
}
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API SetTexturePtr(void* texture)
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetHeight(int id)
{
g_texture = reinterpret_cast<ID3D11Texture2D*>(texture);
if (!DoesMonitorExist(id)) return -1;
return g_monitors[id].height;
}
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API IsPointerVisible(int id)
{
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);
}
}

View File

@@ -1,12 +1,12 @@
uDesktopDuplication
===================
**uDesktopDuplication** is a simple Desktop Duplication API implementation for Unity.
**uDesktopDuplication** is a Unity asset to use the realtime screen capture as `Texture2D` using Desktop Duplication API.
ScreenShot
----------
![uDesktopDuplication](https://raw.githubusercontent.com/wiki/hecomi/uDesktopDuplication/screenshot.png)
![uDesktopDuplication](https://raw.githubusercontent.com/wiki/hecomi/uDesktopDuplication/animation.gif)
Environment
@@ -22,22 +22,38 @@ Please download the latest *uDesktopDuplication.unitypackage* from the [release
Usage
-----
Attach `uDesktopDuplication.cs` component to the target object, then its main texture will be replaced with the captured screen.
TODOs
-----
- [x] Mouse cursor
- [ ] Monitor selector
- [x] Support linear color
Please request new features you want to issues.
Attach `uDesktopDuplication/Texture` component to the target object, then its main texture will be replaced with the captured screen. Please see example scenes for more details.
Version
-------
| Data | Version | Description |
| ---------- | ------- | --------------------------------- |
| 2016/10/28 | 1.0.0 | Support multiple screens. |
| 2016/10/27 | 0.0.3 | Support lienar color. |
| 2016/10/27 | 0.0.2 | Add mouse cursor / shader family. |
| 2016/10/27 | 0.0.2 | Add mouse cursor / shaders. |
| 2016/10/27 | 0.0.1 | Initial commit. |
Lisence
-------
The MIT License (MIT)
Copyright (c) 2016 hecomi
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.