Rhino.Testing within active GL context

Hey Developers,

has anyone had any success with Rhino.Testing in headed mode? I need to run my tests within an active GL context but can’t get it to activate even for the simplest task.

@CallumSykes, @sonderskovmathias can you help here?

[Warning] Frame 0: ViewCapture returned null.
[Warning] Frame 1: ViewCapture returned null.
[Sim Thread 27] Sim Running...
[Warning] Frame 2: ViewCapture returned null.
[Warning] Frame 3: ViewCapture returned null.
[Warning] Frame 4: ViewCapture returned null.
[Sim Thread 27] Sim Finished.
Sim and UI interaction completed.
<?xml version="1.0" encoding="utf-8"?>
<Settings>
	<RhinoSystemDirectory>C:\Program Files\Rhino 8\System</RhinoSystemDirectory>

	<LoadEto>true</LoadEto>
	<LoadRDK>true</LoadRDK>

	<CreateRhinoView>true</CreateRhinoView>
</Settings>
 [TestFixture]
 public class PoCTests
 {
     private void RunOnMainThread(System.Action action)
     {
         if (RhinoApp.InvokeRequired)
         {
             RhinoApp.InvokeOnUiThread(action);
         }
         else
         {
             action();
         }
     }

     [Test]
     public void SanityCheck_RhinoIsLoaded()
     {
         Assert.IsNotNull(RhinoDoc.ActiveDoc, "Rhino ActiveDoc should be available.");
         TestContext.WriteLine($"Running inside Rhino Version: {RhinoApp.Version}");
     }

     [Test]
     public void Test_SimAndUI_ThreadingCollision()
     {

         // Start a fake simulation on a background thread
         var simTask = Task.Run(() =>
         {
             Thread.Sleep(100); // Simulate boot up
             TestContext.WriteLine($"[Sim Thread {Thread.CurrentThread.ManagedThreadId}] Sim Running...");

             // Simulate Native Work
             for (int i = 0; i < 5; i++)
             {
                 Thread.Sleep(50);
             }

             TestContext.WriteLine($"[Sim Thread {Thread.CurrentThread.ManagedThreadId}] Sim Finished.");
         });

         // While Sim is running, force UI/OpenGL access on Main Thread
         for (int i = 0; i < 5; i++)
         {
             RunOnMainThread(() =>
             {
                 var view = RhinoDoc.ActiveDoc.Views.ActiveView;
                 if (view == null || !view.Floating)
                 {
                     view = RhinoDoc.ActiveDoc.Views.Add(
                         "TestView",
                         Rhino.Display.DefinedViewportProjection.Top,
                         new System.Drawing.Rectangle(0, 0, 800, 600),
                         true
                     );

                     view.Size = new System.Drawing.Size(800, 600);
                     RhinoDoc.ActiveDoc.Views.ActiveView = view;
                 }

                 view.Redraw();

                 var capture = new Rhino.Display.ViewCapture
                 {
                     Width = 800,
                     Height = 600,
                     DrawAxes = true,
                     DrawGrid = true,
                     TransparentBackground = false
                 };

                 using (var bitmap = capture.CaptureToBitmap(view))
                 {
                     if (bitmap != null)
                     {
                         string path = Path.Combine(TestContext.CurrentContext.WorkDirectory, $"frame_{i}.png");
                         bitmap.Save(path, System.Drawing.Imaging.ImageFormat.Png);
                         TestContext.WriteLine($"Saved frame to: {path}");
                     }
                     else
                     {
                         TestContext.WriteLine($"[Warning] Frame {i}: ViewCapture returned null.");
                     }
                 }
             });

             Thread.Sleep(60); // Wait between UI updates
         }

         // Wait for Sim to finish
         simTask.Wait();

         Assert.Pass("Sim and UI interaction completed.");
     }
 }

Havent tried headed mode :confused:

Ping @fraguada and @eirannejad

1 Like

cc @curtisw @CallumSykes

1 Like

Sorry for replying so late to this. Viewport capture requires headed Rhino.
If you need to test Rhino in a headed context, you’ll want to start it before running the tests, Rhino.Tests doesn’t do this natively afaik. There are 3 possible ways I know that do this

1 Like