2014-04-12 18 views
8

Sto cercando di rendere il rendering di un browser a lato del mio progetto monogame, per disegnare alcune cose dell'interfaccia &. L'ho fatto in passato con versioni precedenti di awesomium senza problemi. Ma non riesco a capire come inizializzare correttamente awesomium in questa nuova versione, ottengo un errore, non importa quanto provo a farlo. Come ho capito ho bisogno di chiamare WebCore.Run() una volta, invece di WebCore.Update(), ma ottengo varie eccezioni da quel metodo.Come implementare Awesomium 1.7.4.2 in un progetto Monogame?

qui sono i passi che ho seguito finora:

  1. Installare Awesomium 1.7.4.2
  2. Refrenced \1.7.4.2\wrappers\Awesomium.NET\Assemblies\Packed\Awesomium.Core.dll nel mio progetto

Ecco alcuni dei miei tentativi:

WebCore.Initialize(new WebConfig()); 
    WebCore.Run(); 
    //Error: Starting an update loop on a thread with an existing message loop, is not supported. 

WebCore.Initialized += (sender, e) => 
    { 
     WebCore.Run(); 
    }; 
    WebCore.Initialize(new WebConfig()); 
    WebView WebView = WebCore.CreateWebView(500, 400); 
    //Error: Starting an update loop on a thread with an existing message loop, is not supported. 

WebCore.Initialize(new WebConfig()); 
    WebView WebView = WebCore.CreateWebView(500, 400); 
    WebView.Source = new Uri("http://www.google.com"); 
    WebView.DocumentReady += (sender, e) => 
    { 
     JSObject js = WebView.CreateGlobalJavascriptObject("w"); 
    }; 
    // No errors, but DocumentReady is never fired.. 

Ho anche riusciti a ottenere gli errori NullRefrence, e se aspetto Thread.Sleep (400) prima di chiamare WebCore.Run(), appena entra nella WebCore.Run() e non completa mai quella linea.

Come si imposta? Non riesco a trovare alcun esempio da nessuna parte. Tutti gli esempi online ti dicono ancora di usare Update che è Obsoleto

+0

Sto lottando con la stessa cosa. –

+0

Sì, non l'ho mai risolto ... Ho eseguito il downgrade alla versione 1.7.3.0 Questa versione funziona perfettamente. Se hai qualche trouple con quello, sarò felice di aiutarti. – BjarkeCK

risposta

13

Ho appena funzionato, devi creare un nuovo thread, quindi chiamare Esegui, quindi ascoltare un evento che verrà generato da WebCore che avrà creato un nuovo SynchronizationContext da allora. È quindi desidera mantenere un riferimento a tale contesto sul thread principale ...

Thread awesomiumThread = new System.Threading.Thread(new System.Threading.ThreadStart(() => 
{ 
    WebCore.Started += (s, e) => { 
     awesomiumContext = SynchronizationContext.Current; 
    }; 

    WebCore.Run(); 
})); 

awesomiumThread.Start(); 

WebCore.Initialize(new WebConfig() { }); 

... si può quindi chiamare tutti i tuoi metodi WebView che utilizzano tale SynchronizationContext ...

awesomiumContext.Post(state => 
{ 
    this.WebView.Source = "http://www.google.com"; 
}, null); 

lo farò riordinare questo con una modifica futura, ma per farvi iniziare ragazzi, ecco il mio componente ...

using Awesomium.Core; 
using Microsoft.Xna.Framework; 
using Microsoft.Xna.Framework.Graphics; 
using Microsoft.Xna.Framework.Input; 
using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Linq; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 

namespace AwesomiumComponent 
{ 
    public class BasicAwesomiumComponent : DrawableGameComponent 
    { 
     private Byte[] imageBytes; 
     private Rectangle area; 
     private Rectangle? newArea; 
     private Boolean resizing; 
     private SpriteBatch spriteBatch; 
     private Texture2D WebViewTexture { get; set; } 
     private SynchronizationContext awesomiumContext = null; 
     private WebView WebView { get; set; } 
     private BitmapSurface Surface { get; set; } 
     private MouseState lastMouseState; 
     private MouseState currentMouseState; 
     private Keys[] lastPressedKeys; 
     private Keys[] currentPressedKeys = new Keys[0]; 
     private static ManualResetEvent awesomiumReady = new ManualResetEvent(false); 

     public Rectangle Area 
     { 
      get { return this.area; } 
      set 
      { 
       this.newArea = value; 
      } 
     } 

     public BasicAwesomiumComponent(Game game, Rectangle area) 
      : base(game) 
     { 
      this.area = area; 

      this.spriteBatch = new SpriteBatch(game.GraphicsDevice); 


      Thread awesomiumThread = new System.Threading.Thread(new System.Threading.ThreadStart(() => 
      { 
       WebCore.Started += (s, e) => { 
        awesomiumContext = SynchronizationContext.Current; 
        awesomiumReady.Set(); 
       }; 

       WebCore.Run(); 
      })); 

      awesomiumThread.Start(); 

      WebCore.Initialize(new WebConfig() { }); 

      awesomiumReady.WaitOne(); 

      awesomiumContext.Post(state => 
      { 
       this.WebView = WebCore.CreateWebView(this.area.Width, this.area.Height, WebViewType.Offscreen); 

       this.WebView.IsTransparent = true; 
       this.WebView.CreateSurface += (s, e) => 
       { 
        this.Surface = new BitmapSurface(this.area.Width, this.area.Height); 
        e.Surface = this.Surface; 
       }; 
      }, null); 
     } 

     public void SetResourceInterceptor(IResourceInterceptor interceptor) 
     { 
      awesomiumContext.Post(state => 
      { 
       WebCore.ResourceInterceptor = interceptor; 
      }, null); 
     } 

     public void Execute(string method, params object[] args) 
     { 
      string script = string.Format("viewModel.{0}({1})", method, string.Join(",", args.Select(x => "\"" + x.ToString() + "\""))); 
      this.WebView.ExecuteJavascript(script); 
     } 

     public void RegisterFunction(string methodName, Action<object, CancelEventArgs> handler) 
     { 
      // Create and acquire a Global Javascript object. 
      // These object persist for the lifetime of the web-view. 
      using (JSObject myGlobalObject = this.WebView.CreateGlobalJavascriptObject("game")) 
      { 
       // The handler is of type JavascriptMethodEventHandler. Here we define it 
       // using a lambda expression. 

       myGlobalObject.Bind(methodName, true, (s, e) => 
       { 
        handler(s, e); 
        // Provide a response. 
        e.Result = "My response"; 
       }); 
      } 
     } 

     public void Load() 
     { 
      LoadContent(); 
     } 

     protected override void LoadContent() 
     { 
      if (this.area.IsEmpty) 
      { 
       this.area = this.GraphicsDevice.Viewport.Bounds; 
       this.newArea = this.GraphicsDevice.Viewport.Bounds; 
      } 
      this.WebViewTexture = new Texture2D(this.Game.GraphicsDevice, this.area.Width, this.area.Height, false, SurfaceFormat.Color); 

      this.imageBytes = new Byte[this.area.Width * 4 * this.area.Height]; 
     } 

     public override void Update(GameTime gameTime) 
     { 
      awesomiumContext.Post(state => 
      { 
       if (this.newArea.HasValue && !this.resizing && gameTime.TotalGameTime.TotalSeconds > 0.10f) 
       { 
        this.area = this.newArea.Value; 
        if (this.area.IsEmpty) 
         this.area = this.GraphicsDevice.Viewport.Bounds; 

        this.WebView.Resize(this.area.Width, this.area.Height); 
        this.WebViewTexture = new Texture2D(this.Game.GraphicsDevice, this.area.Width, this.area.Height, false, SurfaceFormat.Color); 
        this.imageBytes = new Byte[this.area.Width * 4 * this.area.Height]; 
        this.resizing = true; 

        this.newArea = null; 
       } 

       lastMouseState = currentMouseState; 
       currentMouseState = Mouse.GetState(); 

       this.WebView.InjectMouseMove(currentMouseState.X - this.area.X, currentMouseState.Y - this.area.Y); 

       if (currentMouseState.LeftButton == ButtonState.Pressed && lastMouseState.LeftButton == ButtonState.Released) 
       { 
        this.WebView.InjectMouseDown(MouseButton.Left); 
       } 
       if (currentMouseState.LeftButton == ButtonState.Released && lastMouseState.LeftButton == ButtonState.Pressed) 
       { 
        this.WebView.InjectMouseUp(MouseButton.Left); 
       } 
       if (currentMouseState.RightButton == ButtonState.Pressed && lastMouseState.RightButton == ButtonState.Released) 
       { 
        this.WebView.InjectMouseDown(MouseButton.Right); 
       } 
       if (currentMouseState.RightButton == ButtonState.Released && lastMouseState.RightButton == ButtonState.Pressed) 
       { 
        this.WebView.InjectMouseUp(MouseButton.Right); 
       } 
       if (currentMouseState.MiddleButton == ButtonState.Pressed && lastMouseState.MiddleButton == ButtonState.Released) 
       { 
        this.WebView.InjectMouseDown(MouseButton.Middle); 
       } 
       if (currentMouseState.MiddleButton == ButtonState.Released && lastMouseState.MiddleButton == ButtonState.Pressed) 
       { 
        this.WebView.InjectMouseUp(MouseButton.Middle); 
       } 

       if (currentMouseState.ScrollWheelValue != lastMouseState.ScrollWheelValue) 
       { 
        this.WebView.InjectMouseWheel((currentMouseState.ScrollWheelValue - lastMouseState.ScrollWheelValue), 0); 
       } 

       lastPressedKeys = currentPressedKeys; 
       currentPressedKeys = Keyboard.GetState().GetPressedKeys(); 

       // Key Down 
       foreach (var key in currentPressedKeys) 
       { 
        if (!lastPressedKeys.Contains(key)) 
        { 
         this.WebView.InjectKeyboardEvent(new WebKeyboardEvent() 
         { 
          Type = WebKeyboardEventType.KeyDown, 
          VirtualKeyCode = (VirtualKey)(int)key, 
          NativeKeyCode = (int)key 
         }); 

         if ((int)key >= 65 && (int)key <= 90) 
         { 
          this.WebView.InjectKeyboardEvent(new WebKeyboardEvent() 
          { 
           Type = WebKeyboardEventType.Char, 
           Text = key.ToString().ToLower() 
          }); 
         } 
         else if (key == Keys.Space) 
         { 
          this.WebView.InjectKeyboardEvent(new WebKeyboardEvent() 
          { 
           Type = WebKeyboardEventType.Char, 
           Text = " " 
          }); 
         } 
        } 
       } 

       // Key Up 
       foreach (var key in lastPressedKeys) 
       { 
        if (!currentPressedKeys.Contains(key)) 
        { 
         this.WebView.InjectKeyboardEvent(new WebKeyboardEvent() 
         { 
          Type = WebKeyboardEventType.KeyUp, 
          VirtualKeyCode = (VirtualKey)(int)key, 
          NativeKeyCode = (int)key 
         }); 
        } 
       } 

      }, null); 

      base.Update(gameTime); 
     } 

     public override void Draw(GameTime gameTime) 
     { 
      awesomiumContext.Post(state => 
      { 
       if (Surface != null && Surface.IsDirty && !resizing) 
       { 
        unsafe 
        { 
         // This part saves us from double copying everything. 
         fixed (Byte* imagePtr = this.imageBytes) 
         { 
          Surface.CopyTo((IntPtr)imagePtr, Surface.Width * 4, 4, true, false); 
         } 
        } 
        this.WebViewTexture.SetData(this.imageBytes); 
       } 
      }, null); 

      Vector2 pos = new Vector2(0, 0); 
      spriteBatch.Begin(); 
      spriteBatch.Draw(this.WebViewTexture, pos, Color.White); 
      spriteBatch.End(); 
      GraphicsDevice.Textures[0] = null; 

      base.Draw(gameTime); 
     } 

     public Uri Source 
     { 
      get 
      { 
       return this.WebView.Source; 
      } 
      set 
      { 
       awesomiumContext.Post(state => 
       { 
        this.WebView.Source = value; 
       }, null); 
      } 
     } 

     public void Resize(int width, int height) 
     { 
      this.newArea = new Rectangle(0, 0, width, height); ; 
     } 
    } 
} 
+0

Fantastico! Non l'avrei mai capito. Posso chiederti dove hai trovato quell'informazione? – BjarkeCK

+0

Ho letto le osservazioni sul metodo Run e l'ho violato fino a farlo funzionare. Per visualizzare le osservazioni, GoToDefinition sul metodo Run, quindi espandere il commento compresso. –

+0

Ottimo lavoro Dean. Vorrei poterti dare 1000 voti per questo. – ZafarYousafi