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; /// <summary> /// 初始化进程间消息代理 /// </summary> 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; } /// <summary> /// 释放进程间消息代理 /// </summary> 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); } } }