1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
#import "BasicVTKView.h"
#import "vtkRenderer.h"
#import "vtkRenderWindow.h"
#import "vtkRenderWindowInteractor.h"
#import "vtkCocoaRenderWindowInteractor.h"
#import "vtkCocoaRenderWindow.h"
// Private Interface
@interface BasicVTKView()
{
@private
vtkRenderer* _renderer;
}
@end
@implementation BasicVTKView
// ----------------------------------------------------------------------------
// Designated initializer
- (instancetype)initWithFrame:(NSRect)frameRect
{
self = [super initWithFrame:frameRect];
if (self)
{
// nothing to do... add something if you need to
}
return self;
}
// ----------------------------------------------------------------------------
// Designated initializer
- (/*nullable*/ instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self)
{
// nothing to do... add something if you need to
}
return self;
}
// ----------------------------------------------------------------------------
// We are going to override the super class here to do some last minute
// setups. We need to do this because if we initialize in the constructor or
// even later, in say an NSDocument's windowControllerDidLoadNib, then
// we will get a warning about "Invalid Drawable" because the OpenGL Context
// is trying to be set and rendered into an NSView that most likely is not
// on screen yet. This is a way to defer that initialization until the NSWindow
// that contains our NSView subclass is actually on screen and ready to be drawn.
- (void)drawRect:(NSRect)theRect
{
// Check for a valid vtkWindowInteractor and then initialize it. Technically we
// do not need to do this, but what happens is that the window that contains
// this object will not immediately render it so you end up with a big empty
// space in your gui where this NSView subclass should be. This may or may
// not be what is wanted. If you allow this code then what you end up with is the
// typical empty black OpenGL view which seems more 'correct' or at least is
// more soothing to the eye.
vtkRenderWindowInteractor* theRenWinInt = [self getInteractor];
if (theRenWinInt && (theRenWinInt->GetInitialized() == NO))
{
theRenWinInt->Initialize();
}
// Let the vtkCocoaGLView do its regular drawing
[super drawRect:theRect];
}
// ----------------------------------------------------------------------------
- (void)initializeVTKSupport
{
// The usual vtk object creation.
vtkRenderer* ren = vtkRenderer::New();
vtkRenderWindow* renWin = vtkRenderWindow::New();
vtkRenderWindowInteractor* renWinInt = vtkRenderWindowInteractor::New();
// The cast should never fail, but we do it anyway, as
// it's more correct to do so.
vtkCocoaRenderWindow* cocoaRenWin = vtkCocoaRenderWindow::SafeDownCast(renWin);
if (ren && cocoaRenWin && renWinInt)
{
// This is special to our usage of vtk. To prevent vtk
// from creating an NSWindow and NSView automatically (its
// default behaviour) we tell vtk that they exist already.
// The APIs names are a bit misleading, due to the cross
// platform nature of vtk, but this usage is correct.
cocoaRenWin->SetRootWindow((__bridge void*)[self window]);
cocoaRenWin->SetWindowId((__bridge void*)self);
// The usual vtk connections
cocoaRenWin->AddRenderer(ren);
renWinInt->SetRenderWindow(cocoaRenWin);
// This is special to our usage of vtk. vtkCocoaGLView
// keeps track of the renderWindow, and has a get
// accessor if you ever need it.
[self setVTKRenderWindow:cocoaRenWin];
// Likewise, BasicVTKView keeps track of the renderer.
[self setRenderer:ren];
}
}
// ----------------------------------------------------------------------------
- (void)cleanUpVTKSupport
{
vtkRenderer* ren = [self getRenderer];
vtkRenderWindow* renWin = [self getVTKRenderWindow];
vtkRenderWindowInteractor* renWinInt = [self getInteractor];
if (ren)
{
ren->Delete();
}
if (renWin)
{
renWin->Delete();
}
if (renWinInt)
{
renWinInt->Delete();
}
[self setRenderer:nil];
[self setVTKRenderWindow:nil];
// There is no setter accessor for the render window
// interactor, that's ok.
}
// ----------------------------------------------------------------------------
- (/*nullable*/ vtkRenderer*)getRenderer
{
return _renderer;
}
// ----------------------------------------------------------------------------
- (void)setRenderer:(/*nullable*/ vtkRenderer*)theRenderer
{
_renderer = theRenderer;
}
@end
|