226
|
1
|
|
2 module Stone {
|
|
3
|
|
4 // export declare type InitializationCallback = () => void;
|
|
5
|
|
6 // export declare var StoneFrameworkModule : any;
|
|
7
|
|
8 //const ASSETS_FOLDER : string = "assets/lib";
|
|
9 //const WASM_FILENAME : string = "orthanc-framework";
|
|
10
|
|
11 export class WasmViewport {
|
|
12
|
|
13 private module_ : any;
|
|
14 private canvasId_ : string;
|
|
15 private htmlCanvas_ : HTMLCanvasElement;
|
|
16 private context_ : CanvasRenderingContext2D;
|
|
17 private imageData_ : any = null;
|
|
18 private renderingBuffer_ : any = null;
|
|
19 private touchZoom_ : any = false;
|
|
20 private touchTranslation_ : any = false;
|
|
21
|
|
22 private ViewportSetSize : Function;
|
|
23 private ViewportRender : Function;
|
|
24 private ViewportMouseDown : Function;
|
|
25 private ViewportMouseMove : Function;
|
|
26 private ViewportMouseUp : Function;
|
|
27 private ViewportMouseEnter : Function;
|
|
28 private ViewportMouseLeave : Function;
|
|
29 private ViewportMouseWheel : Function;
|
|
30 private ViewportKeyPressed : Function;
|
|
31
|
|
32 public constructor(module: any, canvasId: string) {
|
|
33 this.module_ = module;
|
|
34 this.canvasId_ = canvasId;
|
|
35 this.htmlCanvas_ = document.getElementById(this.canvasId_) as HTMLCanvasElement;
|
|
36 this.context_ = this.htmlCanvas_.getContext('2d');
|
|
37
|
|
38 this.ViewportSetSize = this.module_.cwrap('ViewportSetSize', null, [ 'number', 'number' ]);
|
|
39 this.ViewportRender = this.module_.cwrap('ViewportRender', null, [ 'number', 'number', 'number', 'number' ]);
|
|
40 this.ViewportMouseDown = this.module_.cwrap('ViewportMouseDown', null, [ 'number', 'number', 'number', 'number' ]);
|
|
41 this.ViewportMouseMove = this.module_.cwrap('ViewportMouseMove', null, [ 'number', 'number' ]);
|
|
42 this.ViewportMouseUp = this.module_.cwrap('ViewportMouseUp', null, [ ]);
|
|
43 this.ViewportMouseEnter = this.module_.cwrap('ViewportMouseEnter', null, []);
|
|
44 this.ViewportMouseLeave = this.module_.cwrap('ViewportMouseLeave', null, []);
|
|
45 this.ViewportMouseWheel = this.module_.cwrap('ViewportMouseWheel', null, [ 'number', 'number', 'number', 'number' ]);
|
|
46 this.ViewportKeyPressed = this.module_.cwrap('ViewportKeyPressed', null, [ 'string', 'number', 'number' ]);
|
|
47 }
|
|
48
|
|
49 public Redraw() {
|
|
50 if (this.imageData_ === null ||
|
|
51 this.renderingBuffer_ === null ||
|
|
52 this.ViewportRender(this.imageData_.width,
|
|
53 this.imageData_.height,
|
|
54 this.renderingBuffer_) == 0) {
|
|
55 console.log('The rendering has failed');
|
|
56 } else {
|
|
57 // Create an accessor to the rendering buffer (i.e. create a
|
|
58 // "window" above the heap of the WASM module), then copy it to
|
|
59 // the ImageData object
|
|
60 this.imageData_.data.set(new Uint8ClampedArray(
|
|
61 this.module_.buffer,
|
|
62 this.renderingBuffer_,
|
|
63 this.imageData_.width * this.imageData_.height * 4));
|
|
64
|
|
65 this.context_.putImageData(this.imageData_, 0, 0);
|
|
66 }
|
|
67 }
|
|
68
|
|
69 public Resize() {
|
|
70 if (this.imageData_ != null &&
|
|
71 (this.imageData_.width != window.innerWidth ||
|
|
72 this.imageData_.height != window.innerHeight)) {
|
|
73 this.imageData_ = null;
|
|
74 }
|
|
75
|
|
76 this.htmlCanvas_.width = window.innerWidth;
|
|
77 this.htmlCanvas_.height = window.innerHeight;
|
|
78
|
|
79 if (this.imageData_ === null) {
|
|
80 this.imageData_ = this.context_.getImageData(0, 0, this.htmlCanvas_.width, this.htmlCanvas_.height);
|
|
81 this.ViewportSetSize(this.htmlCanvas_.width, this.htmlCanvas_.height);
|
|
82
|
|
83 if (this.renderingBuffer_ != null) {
|
|
84 this.module_._free(this.renderingBuffer_);
|
|
85 }
|
|
86
|
|
87 this.renderingBuffer_ = this.module_._malloc(this.imageData_.width * this.imageData_.height * 4);
|
|
88 }
|
|
89
|
|
90 this.Redraw();
|
|
91 }
|
|
92
|
|
93 public Initialize() {
|
|
94
|
|
95 // Force the rendering of the viewport for the first time
|
|
96 this.Resize();
|
|
97
|
|
98 // Register an event listener to call the Resize() function
|
|
99 // each time the window is resized.
|
|
100 window.addEventListener('resize', this.Resize, false);
|
|
101
|
|
102 var that = this;
|
|
103
|
|
104 this.htmlCanvas_.addEventListener('contextmenu', function(event) {
|
|
105 // Prevent right click on the canvas
|
|
106 event.preventDefault();
|
|
107 }, false);
|
|
108
|
|
109 this.htmlCanvas_.addEventListener('mouseleave', function(event) {
|
|
110 that.ViewportMouseLeave();
|
|
111 });
|
|
112
|
|
113 this.htmlCanvas_.addEventListener('mouseenter', function(event) {
|
|
114 that.ViewportMouseEnter();
|
|
115 });
|
|
116
|
|
117 this.htmlCanvas_.addEventListener('mousedown', function(event) {
|
|
118 var x = event.pageX - this.offsetLeft;
|
|
119 var y = event.pageY - this.offsetTop;
|
|
120 that.ViewportMouseDown(event.button, x, y, 0 /* TODO */);
|
|
121 });
|
|
122
|
|
123 this.htmlCanvas_.addEventListener('mousemove', function(event) {
|
|
124 var x = event.pageX - this.offsetLeft;
|
|
125 var y = event.pageY - this.offsetTop;
|
|
126 that.ViewportMouseMove(x, y);
|
|
127 });
|
|
128
|
|
129 this.htmlCanvas_.addEventListener('mouseup', function(event) {
|
|
130 that.ViewportMouseUp();
|
|
131 });
|
|
132
|
|
133 window.addEventListener('keydown', function(event) {
|
|
134 that.ViewportKeyPressed(event.key, event.shiftKey, event.ctrlKey, event.altKey);
|
|
135 });
|
|
136
|
|
137 this.htmlCanvas_.addEventListener('wheel', function(event) {
|
|
138 var x = event.pageX - this.offsetLeft;
|
|
139 var y = event.pageY - this.offsetTop;
|
|
140 that.ViewportMouseWheel(event.deltaY, x, y, event.ctrlKey);
|
|
141 event.preventDefault();
|
|
142 });
|
|
143
|
|
144 var that = this;
|
|
145 this.htmlCanvas_.addEventListener('touchstart', function(event) {
|
|
146 that.ResetTouch();
|
|
147 });
|
|
148
|
|
149 this.htmlCanvas_.addEventListener('touchend', function(event) {
|
|
150 that.ResetTouch();
|
|
151 });
|
|
152
|
|
153 this.htmlCanvas_.addEventListener('touchmove', function(event) {
|
|
154 if (that.touchTranslation_.length == 2) {
|
|
155 var t = that.GetTouchTranslation(event);
|
|
156 that.ViewportMouseMove(t[0], t[1]);
|
|
157 }
|
|
158 else if (that.touchZoom_.length == 3) {
|
|
159 var z0 = that.touchZoom_;
|
|
160 var z1 = that.GetTouchZoom(event);
|
|
161 that.ViewportMouseMove(z0[0], z0[1] - z0[2] + z1[2]);
|
|
162 }
|
|
163 else {
|
|
164 // Realize the gesture event
|
|
165 if (event.targetTouches.length == 1) {
|
|
166 // Exactly one finger inside the canvas => Setup a translation
|
|
167 that.touchTranslation_ = that.GetTouchTranslation(event);
|
|
168 that.ViewportMouseDown(1 /* middle button */,
|
|
169 that.touchTranslation_[0],
|
|
170 that.touchTranslation_[1], 0);
|
|
171 } else if (event.targetTouches.length == 2) {
|
|
172 // Exactly 2 fingers inside the canvas => Setup a pinch/zoom
|
|
173 that.touchZoom_ = that.GetTouchZoom(event);
|
|
174 var z0 = that.touchZoom_;
|
|
175 that.ViewportMouseDown(2 /* right button */,
|
|
176 z0[0],
|
|
177 z0[1], 0);
|
|
178 }
|
|
179 }
|
|
180 });
|
|
181 }
|
|
182
|
|
183 public ResetTouch() {
|
|
184 if (this.touchTranslation_ ||
|
|
185 this.touchZoom_) {
|
|
186 this.ViewportMouseUp();
|
|
187 }
|
|
188
|
|
189 this.touchTranslation_ = false;
|
|
190 this.touchZoom_ = false;
|
|
191 }
|
|
192
|
|
193 public GetTouchTranslation(event) {
|
|
194 var touch = event.targetTouches[0];
|
|
195 return [
|
|
196 touch.pageX,
|
|
197 touch.pageY
|
|
198 ];
|
|
199 }
|
|
200
|
|
201 public GetTouchZoom(event) {
|
|
202 var touch1 = event.targetTouches[0];
|
|
203 var touch2 = event.targetTouches[1];
|
|
204 var dx = (touch1.pageX - touch2.pageX);
|
|
205 var dy = (touch1.pageY - touch2.pageY);
|
|
206 var d = Math.sqrt(dx * dx + dy * dy);
|
|
207 return [
|
|
208 (touch1.pageX + touch2.pageX) / 2.0,
|
|
209 (touch1.pageY + touch2.pageY) / 2.0,
|
|
210 d
|
|
211 ];
|
|
212 }
|
|
213
|
|
214 }
|
|
215 }
|
|
216 |