TargetNode = function()

in seriously.js [3586:3802]


		TargetNode = function (hook, target, options) {
			var opts,
				flip,
				width,
				height,
				that = this,
				matchedType = false,
				i, element, elements, context,
				debugContext,
				frameBuffer,
				targetList,
				triedWebGl = false,
				key;

			function targetPlugin(hook, target, options, force) {
				var plugin = seriousTargets[hook];
				if (plugin.definition) {
					plugin = plugin.definition.call(that, target, options, force);
					if (!plugin) {
						return null;
					}
					plugin = extend(extend({}, seriousTargets[hook]), plugin);
					that.hook = key;
					matchedType = true;
					that.plugin = plugin;
					that.compare = plugin.compare;
					if (plugin.target) {
						target = plugin.target;
					}
					if (plugin.gl && !that.gl) {
						that.gl = plugin.gl;
						if (!gl) {
							attachContext(plugin.gl);
						}
					}
					if (that.gl === gl) {
						that.model = rectangleModel;
						that.shader = baseShader;
					}
				}
				return plugin;
			}

			function compareTarget(target) {
				return that.target === target;
			}

			Node.call(this);

			if (hook && typeof hook !== 'string' || !target && target !== 0) {
				if (!options || typeof options !== 'object') {
					options = target;
				}
				target = hook;
			}

			opts = options || {};
			flip = opts.flip === undefined ? true : opts.flip
			width = parseInt(opts.width, 10);
			height = parseInt(opts.height, 10);
			debugContext = opts.debugContext;

			// forced target type?
			if (typeof hook === 'string' && seriousTargets[hook]) {
				targetPlugin(hook, target, opts, true);
			}

			this.renderToTexture = opts.renderToTexture;

			if (target instanceof WebGLFramebuffer) {
				frameBuffer = target;

				if (opts instanceof HTMLCanvasElement) {
					target = opts;
				} else if (opts instanceof WebGLRenderingContext) {
					target = opts.canvas;
				} else if (opts.canvas instanceof HTMLCanvasElement) {
					target = opts.canvas;
				} else if (opts.context instanceof WebGLRenderingContext) {
					target = opts.context.canvas;
				} else {
					//todo: search all canvases for matching contexts?
					throw new Error('Must provide a canvas with WebGLFramebuffer target');
				}
			}

			if (target instanceof HTMLElement && target.tagName === 'CANVAS') {
				width = target.width;
				height = target.height;

				//try to get a webgl context.
				if (!gl || gl.canvas !== target && opts.allowSecondaryWebGL) {
					triedWebGl = true;
					context = getWebGlContext(target, {
						alpha: true,
						premultipliedAlpha: false,
						preserveDrawingBuffer: true,
						stencil: true,
						debugContext: debugContext
					});
				}

				if (!context) {
					if (!opts.allowSecondaryWebGL && gl && gl.canvas !== target) {
						throw new Error('Only one WebGL target canvas allowed. Set allowSecondaryWebGL option to create secondary context.');
					}

					this.render = nop;
					Seriously.logger.log('Unable to create WebGL context.');
					//throw new Error('Unable to create WebGL context.');
				} else if (!gl || gl === context) {
					//this is our main WebGL canvas
					if (!primaryTarget) {
						primaryTarget = this;
					}
					if (!gl) {
						attachContext(context);
					}
					this.render = this.renderWebGL;

					/*
					Don't remember what this is for. Maybe we should remove it
					*/
					if (opts.renderToTexture) {
						if (gl) {
							this.frameBuffer = new FrameBuffer(gl, width, height, false);
						}
					} else {
						this.frameBuffer = {
							frameBuffer: frameBuffer || null
						};
					}
				} else {
					//set up alternative drawing method using ArrayBufferView
					this.gl = context;

					//this.pixels = new Uint8Array(width * height * 4);
					//todo: probably need another framebuffer for renderToTexture?
					//todo: handle lost context on secondary webgl
					this.frameBuffer = {
						frameBuffer: frameBuffer || null
					};
					this.shader = new ShaderProgram(this.gl, baseVertexShader, baseFragmentShader);
					this.model = buildRectangleModel.call(this, this.gl);
					this.pixels = null;

					this.texture = this.gl.createTexture();
					this.gl.bindTexture(gl.TEXTURE_2D, this.texture);
					this.gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
					this.gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
					this.gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
					this.gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

					this.render = this.renderSecondaryWebGL;
				}

				matchedType = true;
			}

			if (!matchedType) {
				for (key in seriousTargets) {
					if (seriousTargets.hasOwnProperty(key) && seriousTargets[key]) {
						if (targetPlugin(key, target, opts, false)) {
							break;
						}
					}
				}
			}

			if (!matchedType) {
				throw new Error('Unknown target type');
			}

			if (allTargets) {
				targetList = allTargets.get(target);
				if (targetList) {
					Seriously.logger.warn(
						'Target already in use by another instance',
						target,
						Object.keys(targetList).map(function (key) {
							return targetList[key];
						})
					);
				} else {
					targetList = {};
					allTargets.set(target, targetList);
				}
				targetList[seriously.id] = seriously;
			}

			this.target = target;
			this.transform = null;
			this.transformDirty = true;
			this.flip = flip;
			if (width) {
				this.width = width;
			}
			if (height) {
				this.height = height;
			}

			this.uniforms.resolution[0] = this.width;
			this.uniforms.resolution[1] = this.height;

			if (opts.auto !== undefined) {
				this.auto = opts.auto;
			} else {
				this.auto = auto;
			}
			this.frames = 0;

			this.pub = new Target(this);

			nodes.push(this);
			nodesById[this.id] = this;
			targets.push(this);
		};