using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using CommonAIEditor;
using CommonAI.Zone.ZoneEditor.Plugin.EditorToScene;
using CommonAI.Zone.ZoneEditor.Plugin;
using CommonAI.Zone.ZoneEditor.Plugin.SceneToEditor;
using System.IO;
using System.Runtime.InteropServices;
using CommonLang.File;
using GameEditorPlugin.Utils;
using CommonAI.Zone;
using CommonLang.Property;
using System.Configuration;
using System.Text.RegularExpressions;
using System.Threading;
using CommonFroms;
using GameEditorPlugin.Win32.Runtime;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
using System.Runtime.Serialization.Formatters;
using System.Collections;
using System.Runtime.Remoting.Channels.Tcp;
using System.Net.NetworkInformation;
using System.Net;
namespace GameEditorUnity3D
{
public partial class Unity3dControl : UserControl, ISceneEditorPlugin
{
public Unity3dControl()
{
InitializeComponent();
}
#region IEditorPlugin
public event PluginMessageHandler OnGetPluginMessage;
public event CallAddSceneObject CallAddObject;
public event CallResetSceneObject CallResetObject;
public Control AsControl()
{
return this;
}
public bool EnableRight { get { return true; } }
private void Response(object resp)
{
this.Invoke(new System.Action(() =>
{
if (resp is RspOnObjectSelected)
{
RspOnObjectSelected rsp = resp as RspOnObjectSelected;
rsp.Selected = true;
}
if (OnGetPluginMessage != null)
{
OnGetPluginMessage.Invoke(resp);
if (resp is RspEditorState)
{
if ((resp as RspEditorState).State == RspEditorState.STATE_SUCCEED)
{
OnEditorStatusOK();
}
}
}
}));
}
public void SendMessage(object data)
{
string output = EditorMessageDecoder.EncodeMessage(data);
Send(output);
return;
}
public static bool PortInUse(int port)
{
bool inUse = false;
IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
IPEndPoint[] ipEndPoints = ipProperties.GetActiveTcpListeners();
foreach (IPEndPoint endPoint in ipEndPoints)
{
if (endPoint.Port == port)
{
inUse = true;
break;
}
}
return inUse;
}
private void OnEditorStatusOK()
{
var timer = new System.Timers.Timer(1);
timer.Elapsed += (sender, e) =>
{
timer.Close();
timer.Dispose();
this.Invoke(new System.Action(() =>
{
ActivateUnityWindow();
}));
};
timer.Start();
}
//------------------------------------------------------------------------------
#endregion
#region 组件设计器生成的代码
private System.ComponentModel.IContainer components = null;
[DllImport("user32.dll")]
static extern bool MoveWindow(IntPtr handle, int x, int y, int width, int height, bool redraw);
internal delegate int WindowEnumProc(IntPtr hwnd, IntPtr lparam);
[DllImport("user32.dll")]
internal static extern bool EnumChildWindows(IntPtr hwnd, WindowEnumProc func, IntPtr lParam);
[DllImport("user32.dll")]
internal static extern IntPtr SetFocus(IntPtr hWnd);
[DllImport("user32.dll")]
static extern int SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
private Process process;
private IntPtr unityHWND = IntPtr.Zero;
private const int WM_ACTIVATE = 0x0006;
private readonly IntPtr WA_ACTIVE = new IntPtr(1);
private readonly IntPtr WA_INACTIVE = new IntPtr(0);
public IpcRemoteObject RemoteObject { get; set; }
private ObjRef RemoteObjectRef;
private int MessageProxyServerPort = 9900;
private string MessageProxyServerIP = @"127.0.0.1";
private string MessageProxyServerName = @"GameEditorUnity3D.Server";
private string MessageProxyURLName = @"GameEditorUnity3D";
private string MessageProxyURL;
///
/// 初始化进程间消息代理
///
public void InitializeIPCMessageProxy()
{
while (PortInUse(MessageProxyServerPort))
{
MessageProxyServerPort++;
}
MessageProxyURLName += System.Guid.NewGuid();
MessageProxyURL = string.Format(@"tcp://{0}:{1}/{2}", MessageProxyServerIP, MessageProxyServerPort, MessageProxyURLName);
BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
serverProvider.TypeFilterLevel = TypeFilterLevel.Full;
BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();
IDictionary props = new Hashtable();
props["name"] = MessageProxyServerName;
props["port"] = MessageProxyServerPort;
props["bindTo"] = MessageProxyServerIP;
TcpChannel channel = new TcpChannel(props, clientProvider, serverProvider);
ChannelServices.RegisterChannel(channel, false);
RemoteObject = new IpcRemoteObject();
RemoteObjectRef = RemotingServices.Marshal(RemoteObject, MessageProxyURLName);
//RemoteObject = Activator.GetObject(typeof(IpcRemoteObject), MessageProxyURLName) as IpcRemoteObject;
RemoteObject.ServerCallback = Recv;
}
///
/// 释放进程间消息代理
///
public void DisposeIPCMessageProxy()
{
RemotingServices.Unmarshal(RemoteObjectRef, true);
IChannel[] regChannels = ChannelServices.RegisteredChannels;
foreach (IChannel item in regChannels)
{
if (item.ChannelName == MessageProxyServerName)
{
TcpChannel channel = item as TcpChannel;
channel.StopListening(null);
ChannelServices.UnregisterChannel(channel);
break;
}
}
}
private void InitializeComponent()
{
try
{
InitializeIPCMessageProxy();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Unity3dControl));
this.SuspendLayout();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + "\n" + ex.StackTrace);
}
{
//-----------------------------------------
try
{
string unitysrc = Application.StartupPath + "\\U3DScene\\U3DEditor.exe";
string u3d_webplayer = ConfigurationManager.AppSettings["u3d_webplayer"];
if (u3d_webplayer != null)
{
unitysrc = Application.StartupPath + u3d_webplayer;
}
process = new Process();
process.StartInfo.FileName = unitysrc;
process.StartInfo.Arguments = "-parentHWND " + this.Handle.ToInt32() + " -ipcPort " + MessageProxyServerPort + " -serviceName " + MessageProxyURLName + " " + Environment.CommandLine;
process.StartInfo.UseShellExecute = true;
process.StartInfo.CreateNoWindow = true;
Application.ThreadExit += new System.EventHandler(this.App_Exit);
process.Start();
process.WaitForInputIdle();
EnumChildWindows(this.Handle, WindowEnum, IntPtr.Zero);
this.Resize += new System.EventHandler(this.Form_Resize);
this.VisibleChanged += new System.EventHandler(this.Form_Activated);
this.Disposed += new System.EventHandler(this.Form_FormClosed);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + "\n" + ex.StackTrace);
}
//-----------------------------------------
}
//
// Unity3dControl
//
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
//this.Controls.Add(this.axUnityWebPlayer1);
this.Name = "Unity3dControl";
this.Size = new System.Drawing.Size(915, 685);
this.ResumeLayout(false);
}
public void ActivateUnityWindow()
{
SendMessage(unityHWND, WM_ACTIVATE, WA_ACTIVE, IntPtr.Zero);
SetFocus(unityHWND);
}
public void DeactivateUnityWindow()
{
SendMessage(unityHWND, WM_ACTIVATE, WA_INACTIVE, IntPtr.Zero);
}
private int WindowEnum(IntPtr hwnd, IntPtr lparam)
{
unityHWND = hwnd;
ActivateUnityWindow();
return 0;
}
public void Form_Resize(object sender, EventArgs e)
{
MoveWindow(unityHWND, 0, 0, this.Width, this.Height, true);
ActivateUnityWindow();
//OnGetPluginMessage.Invoke(new RspEditorState());
}
// Close Unity application
public void Form_FormClosed(object sender, EventArgs e)
{
try
{
process.CloseMainWindow();
Thread.Sleep(1000);
while (process.HasExited == false)
process.Kill();
}
catch (Exception)
{
}
}
public void App_Exit(object sender, EventArgs e)
{
try
{
process.Kill();
}
catch (Exception)
{
}
}
public void Form_Activated(object sender, EventArgs e)
{
if (this.Visible)
ActivateUnityWindow();
else
DeactivateUnityWindow();
}
public void Form_Deactivate(object sender, EventArgs e)
{
DeactivateUnityWindow();
}
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
if (disposing)
{
DisposeIPCMessageProxy();
}
base.Dispose(disposing);
}
#endregion
#region Unity3dControl
const string Prefix = "OnExternalCall(\"";
const string Endfix = "\");";
string Recv(string s)
{
object data = EditorMessageDecoder.DecodeMessage(s);
Response(data);
return "";
}
void Send(string regionmsg)
{
RemoteObject.SendToClient(regionmsg);
}
#endregion
}
public class U3dGamePlugin : IGameEditorPlugin
{
private static string dataRoot;
private static string pluginDll;
[DllImport("user32.dll", SetLastError = true)]
private static extern void SwitchToThisWindow(IntPtr hWnd, bool turnOn);
private string U3DRuntimeEXE = "/U3DScene/U3DSceneRun.exe";
public string Name { get { return "Unity"; } }
public string DataRoot
{
get { return U3dGamePlugin.dataRoot; }
set { U3dGamePlugin.dataRoot = value.Replace('\\', '/'); }
}
public string PluginDLL
{
get { return U3dGamePlugin.pluginDll; }
set { U3dGamePlugin.pluginDll = value.Replace('\\', '/'); }
}
public U3dGamePlugin()
{
string u3d_runtime = ConfigurationManager.AppSettings["u3d_runtime"];
if (u3d_runtime != null)
{
U3DRuntimeEXE = u3d_runtime;
}
}
public ISceneEditorPlugin CreateScenePlugin(IGameEditorPlugin d)
{
return new Unity3dControl();
}
public void RunTest(IGameEditorPlugin d, string data_dir, int sceneID, int actorTemplateID)
{
Type plugintype = ReflectionUtil.GetType(TemplateManager.Factory.GetType().FullName);
string args = string.Format(
"-CustomArgs:RunPlatform={0};MapID={1};FolderPath={2};ResPath={3};UserID={4};Plugin={5};IsNet=0;NetDriver=0;IP=0;UUID=0;Force=0;RoomID=0",
0,
sceneID,
dataRoot + "/data",
dataRoot,
actorTemplateID,
PluginDLL
);
FileInfo exefile = new FileInfo(Application.StartupPath + U3DRuntimeEXE);
ProcessStartInfo start = new ProcessStartInfo(exefile.FullName, args);
start.WorkingDirectory = exefile.Directory.FullName;
Process p = new Process();
p.StartInfo = start;
p.Start();
new Thread(() =>
{
while (!p.HasExited)
{
Thread.Sleep(1000);
}
Regex regex = new Regex(@"\d{4}-\d{2}-\d{2}_\d*");
foreach (DirectoryInfo dir in exefile.Directory.GetDirectories())
{
if (regex.IsMatch(dir.Name))
{
if (File.Exists(dir.FullName + Path.DirectorySeparatorChar + "crash.dmp"))
{
FileSystem.DeleteToRecycleBin(dir.FullName);
//dir.Delete(true);
}
}
}
}).Start();
}
public void RunModelView(IGameEditorPlugin d, string[] filepath)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < filepath.Length; i++)
{
sb.Append(filepath[i].Replace('\\', '/'));
if (i < filepath.Length - 1)
{
sb.Append(",");
}
}
ProcessStartInfo start = new ProcessStartInfo(
Application.StartupPath + "/U3DScene/U3DSceneRun.exe",
"-CustomArgs:" +
"RunPlatform=" + 1 + ";" +
"ModelPath=" + sb.ToString() +
"");
start.WorkingDirectory = Application.StartupPath + "\\U3DScene";
Process p = new Process();
p.StartInfo = start;
p.Start();
}
public bool AcceptResource(IGameEditorPlugin d, string filename)
{
return filename.ToLower().EndsWith(".assetbundles");
}
public void RunLocalPlay(IGameEditorPlugin d, DirectoryInfo data_dir, int sceneID, bool recorder)
{
d.RunLocalPlay(null, data_dir, sceneID, recorder);
}
public void RunServerPlay(IGameEditorPlugin d, DirectoryInfo data_dir, int sceneID)
{
d.RunServerPlay(null, data_dir, sceneID);
}
}
}