awayjs-display
Version:
AwayJS displaylist classes
610 lines (506 loc) • 14.8 kB
text/typescript
import Vector3D from "awayjs-core/lib/geom/Vector3D";
import getTimer from "awayjs-core/lib/utils/getTimer";
import IRenderer from "./IRenderer";
import DisplayObject from "./display/DisplayObject";
import TouchPoint from "./base/TouchPoint";
import Scene from "./display/Scene";
import IPicker from "./pick/IPicker";
import PickingCollision from "./pick/PickingCollision";
import RaycastPicker from "./pick/RaycastPicker";
import Camera from "./display/Camera";
import CameraEvent from "./events/CameraEvent";
import DisplayObjectEvent from "./events/DisplayObjectEvent";
import RendererEvent from "./events/RendererEvent";
import MouseManager from "./managers/MouseManager";
class View
{
/*
*************************************************************************************************************************
* Development Notes
*************************************************************************************************************************
*
* ShareContext - this is not being used at the moment integration with other frameworks is not yet implemented or tested
* and ( _localPos / _globalPos ) position of viewport are the same for the moment
*
* Background
* - this is currently not being included in our tests and is currently disabled
*
******************clear********************************************************************************************************
*/
// Protected
public _pScene:Scene;
public _pCamera:Camera;
public _pRenderer:IRenderer;
// Private
private _aspectRatio:number;
private _width:number = 0;
private _height:number = 0;
private _time:number = 0;
private _deltaTime:number = 0;
private _backgroundColor:number = 0x000000;
private _backgroundAlpha:number = 1;
private _viewportDirty:boolean = true;
private _scissorDirty:boolean = true;
private _onPartitionChangedDelegate:(event:DisplayObjectEvent) => void;
private _onProjectionChangedDelegate:(event:CameraEvent) => void;
private _onViewportUpdatedDelegate:(event:RendererEvent) => void;
private _onScissorUpdatedDelegate:(event:RendererEvent) => void;
private _mouseManager:MouseManager;
private _mousePicker:IPicker = new RaycastPicker();
private _htmlElement:HTMLDivElement;
private _shareContext:boolean;
public _pMouseX:number;
public _pMouseY:number;
public _pTouchPoints:Array<TouchPoint> = new Array<TouchPoint>();
/*
***********************************************************************
* Disabled / Not yet implemented
***********************************************************************
*
* private _background:away.textures.Texture2DBase;
*
* public _pTouch3DManager:away.managers.Touch3DManager;
*
*/
constructor(renderer:IRenderer, scene:Scene = null, camera:Camera = null)
{
this._onPartitionChangedDelegate = (event:DisplayObjectEvent) => this._onPartitionChanged(event);
this._onProjectionChangedDelegate = (event:CameraEvent) => this._onProjectionChanged(event);
this._onViewportUpdatedDelegate = (event:RendererEvent) => this._onViewportUpdated(event);
this._onScissorUpdatedDelegate = (event:RendererEvent) => this._onScissorUpdated(event);
this.scene = scene || new Scene();
this.camera = camera || new Camera();
this.renderer = renderer;
//make sure document border is zero
if(document) {
document.body.style.margin = "0px";
this._htmlElement = document.createElement("div");
this._htmlElement.style.position = "absolute";
document.body.appendChild(this._htmlElement);
}
this._mouseManager = MouseManager.getInstance();
this._mouseManager.registerView(this);
// if (this._shareContext)
// this._mouse3DManager.addViewLayer(this);
}
public layeredView:boolean; //TODO: something to enable this correctly
public get mouseX():number
{
return this._pMouseX;
}
public get mouseY():number
{
return this._pMouseY;
}
get touchPoints():Array<TouchPoint>
{
return this._pTouchPoints;
}
public getLocalMouseX(displayObject:DisplayObject):number
{
return displayObject.inverseSceneTransform.transformVector(this.unproject(this._pMouseX, this._pMouseY, 1000)).x;
}
public getLocalMouseY(displayObject:DisplayObject):number
{
return displayObject.inverseSceneTransform.transformVector(this.unproject(this._pMouseX, this._pMouseY, 1000)).y;
}
public getLocalTouchPoints(displayObject:DisplayObject):Array<TouchPoint>
{
var localPosition:Vector3D;
var localTouchPoints:Array<TouchPoint> = new Array<TouchPoint>();
var len:number = this._pTouchPoints.length;
for (var i:number = 0; i < len; i++) {
localPosition = displayObject.inverseSceneTransform.transformVector(this.unproject(this._pTouchPoints[i].x, this._pTouchPoints[i].y, 1000));
localTouchPoints.push(new TouchPoint(localPosition.x, localPosition.y, this._pTouchPoints[i].id));
}
return localTouchPoints;
}
/**
*
*/
public get htmlElement():HTMLDivElement
{
return this._htmlElement;
}
/**
*
*/
public get renderer():IRenderer
{
return this._pRenderer;
}
public set renderer(value:IRenderer)
{
if (this._pRenderer == value)
return;
if (this._pRenderer) {
this._pRenderer.dispose();
this._pRenderer.removeEventListener(RendererEvent.VIEWPORT_UPDATED, this._onViewportUpdatedDelegate);
this._pRenderer.removeEventListener(RendererEvent.SCISSOR_UPDATED, this._onScissorUpdatedDelegate);
}
this._pRenderer = value;
this._pRenderer.addEventListener(RendererEvent.VIEWPORT_UPDATED, this._onViewportUpdatedDelegate);
this._pRenderer.addEventListener(RendererEvent.SCISSOR_UPDATED, this._onScissorUpdatedDelegate);
//reset back buffer
this._pRenderer._iBackgroundR = ((this._backgroundColor >> 16) & 0xff)/0xff;
this._pRenderer._iBackgroundG = ((this._backgroundColor >> 8) & 0xff)/0xff;
this._pRenderer._iBackgroundB = (this._backgroundColor & 0xff)/0xff;
this._pRenderer._iBackgroundAlpha = this._backgroundAlpha;
this._pRenderer.width = this._width;
this._pRenderer.height = this._height;
this._pRenderer.shareContext = this._shareContext;
}
/**
*
*/
public get shareContext():boolean
{
return this._shareContext;
}
public set shareContext(value:boolean)
{
if (this._shareContext == value)
return;
this._shareContext = value;
if (this._pRenderer)
this._pRenderer.shareContext = this._shareContext;
}
/**
*
*/
public get backgroundColor():number
{
return this._backgroundColor;
}
public set backgroundColor(value:number)
{
if (this._backgroundColor == value)
return;
this._backgroundColor = value;
this._pRenderer._iBackgroundR = ((value >> 16) & 0xff)/0xff;
this._pRenderer._iBackgroundG = ((value >> 8) & 0xff)/0xff;
this._pRenderer._iBackgroundB = (value & 0xff)/0xff;
}
/**
*
* @returns {number}
*/
public get backgroundAlpha():number
{
return this._backgroundAlpha;
}
/**
*
* @param value
*/
public set backgroundAlpha(value:number)
{
if (value > 1)
value = 1;
else if (value < 0)
value = 0;
if (this._backgroundAlpha == value)
return;
this._pRenderer._iBackgroundAlpha = this._backgroundAlpha = value;
}
/**
*
* @returns {Camera3D}
*/
public get camera():Camera
{
return this._pCamera;
}
/**
* Set camera that's used to render the scene for this viewport
*/
public set camera(value:Camera)
{
if (this._pCamera == value)
return;
if (this._pCamera)
this._pCamera.removeEventListener(CameraEvent.PROJECTION_CHANGED, this._onProjectionChangedDelegate);
this._pCamera = value;
if (this._pScene)
this._pScene.partition._iRegisterEntity(this._pCamera);
this._pCamera.addEventListener(CameraEvent.PROJECTION_CHANGED, this._onProjectionChangedDelegate);
this._scissorDirty = true;
this._viewportDirty = true;
}
/**
*
* @returns {away.containers.Scene3D}
*/
public get scene():Scene
{
return this._pScene;
}
/**
* Set the scene that's used to render for this viewport
*/
public set scene(value:Scene)
{
if (this._pScene == value)
return;
if (this._pScene)
this._pScene.removeEventListener(DisplayObjectEvent.PARTITION_CHANGED, this._onPartitionChangedDelegate);
this._pScene = value;
this._pScene.addEventListener(DisplayObjectEvent.PARTITION_CHANGED, this._onPartitionChangedDelegate);
if (this._pCamera)
this._pScene.partition._iRegisterEntity(this._pCamera);
}
/**
*
* @returns {number}
*/
public get deltaTime():number
{
return this._deltaTime;
}
/**
*
*/
public get width():number
{
return this._width;
}
public set width(value:number)
{
if (this._width == value)
return;
this._width = value;
this._aspectRatio = this._width/this._height;
this._pCamera.projection._iAspectRatio = this._aspectRatio;
this._pRenderer.width = value;
if(this._htmlElement) {
this._htmlElement.style.width = value + "px";
}
}
/**
*
*/
public get height():number
{
return this._height;
}
public set height(value:number)
{
if (this._height == value)
return;
this._height = value;
this._aspectRatio = this._width/this._height;
this._pCamera.projection._iAspectRatio = this._aspectRatio;
this._pRenderer.height = value;
if(this._htmlElement) {
this._htmlElement.style.height = value + "px";
}
}
/**
*
*/
public get mousePicker():IPicker
{
return this._mousePicker;
}
public set mousePicker(value:IPicker)
{
if (this._mousePicker == value)
return;
if (value == null)
this._mousePicker = new RaycastPicker();
else
this._mousePicker = value;
}
/**
*
*/
public get x():number
{
return this._pRenderer.x;
}
public set x(value:number)
{
if (this._pRenderer.x == value)
return;
this._pRenderer.x == value;
if(this._htmlElement) {
this._htmlElement.style.left = value + "px";
}
}
/**
*
*/
public get y():number
{
return this._pRenderer.y;
}
public set y(value:number)
{
if (this._pRenderer.y == value)
return;
this._pRenderer.y == value;
if(this._htmlElement) {
this._htmlElement.style.top = value + "px";
}
}
/**
*
*/
public get visible():boolean
{
return (this._htmlElement && this._htmlElement.style.visibility == "visible");
}
public set visible(value:boolean)
{
if(this._htmlElement) {
this._htmlElement.style.visibility = value? "visible" : "hidden";
}
//TODO transfer visible property to associated context (if one exists)
}
/**
*
* @returns {number}
*/
public get renderedFacesCount():number
{
return 0; //TODO
//return this._pEntityCollector._pNumTriangles;//numTriangles;
}
/**
* Renders the view.
*/
public render()
{
this.pUpdateTime();
//update view and size data
this._pCamera.projection._iAspectRatio = this._aspectRatio;
if (this._scissorDirty) {
this._scissorDirty = false;
this._pCamera.projection._iUpdateScissorRect(this._pRenderer.scissorRect.x, this._pRenderer.scissorRect.y, this._pRenderer.scissorRect.width, this._pRenderer.scissorRect.height);
}
if (this._viewportDirty) {
this._viewportDirty = false;
this._pCamera.projection._iUpdateViewport(this._pRenderer.viewPort.x, this._pRenderer.viewPort.y, this._pRenderer.viewPort.width, this._pRenderer.viewPort.height);
}
// update picking
if (!this._shareContext) {
if (this.forceMouseMove && this._htmlElement == this._mouseManager._iActiveDiv && !this._mouseManager._iUpdateDirty)
this._mouseManager._iCollision = this.mousePicker.getViewCollision(this._pMouseX, this._pMouseY, this);
this._mouseManager.fireMouseEvents(this.forceMouseMove);
//_touch3DManager.fireTouchEvents();
}
//_touch3DManager.updateCollider();
//render the contents of the scene
this._pRenderer.render(this._pCamera, this._pScene);
}
/**
*
*/
public pUpdateTime():void
{
var time:number = getTimer();
if (this._time == 0)
this._time = time;
this._deltaTime = time - this._time;
this._time = time;
}
/**
*
*/
public dispose()
{
this._pRenderer.dispose();
// TODO: imeplement mouseManager / touch3DManager
this._mouseManager.unregisterView(this);
//this._touch3DManager.disableTouchListeners(this);
//this._touch3DManager.dispose();
this._mouseManager = null;
//this._touch3DManager = null;
this._pRenderer = null;
}
/**
*
* @param e
*/
private _onPartitionChanged(event:DisplayObjectEvent)
{
if (this._pCamera)
this._pScene.partition._iRegisterEntity(this._pCamera);
}
/**
*
*/
private _onProjectionChanged(event:CameraEvent)
{
this._scissorDirty = true;
this._viewportDirty = true;
}
/**
*
*/
private _onViewportUpdated(event:RendererEvent)
{
this._viewportDirty = true;
}
/**
*
*/
private _onScissorUpdated(event:RendererEvent)
{
this._scissorDirty = true;
}
public project(point3d:Vector3D):Vector3D
{
var v:Vector3D = this._pCamera.project(point3d);
v.x = v.x*this._pRenderer.viewPort.width/2 + this._width*this._pCamera.projection.originX;
v.y = v.y*this._pRenderer.viewPort.height/2 + this._height*this._pCamera.projection.originY;
return v;
}
public unproject(sX:number, sY:number, sZ:number):Vector3D
{
return this._pCamera.unproject(2*(sX - this._width*this._pCamera.projection.originX)/this._pRenderer.viewPort.width, 2*(sY - this._height*this._pCamera.projection.originY)/this._pRenderer.viewPort.height, sZ);
}
public getRay(sX:number, sY:number, sZ:number):Vector3D
{
return this._pCamera.getRay((sX*2 - this._width)/this._width, (sY*2 - this._height)/this._height, sZ);
}
/* TODO: implement Touch3DManager
public get touchPicker():IPicker
{
return this._touch3DManager.touchPicker;
}
*/
/* TODO: implement Touch3DManager
public set touchPicker( value:IPicker)
{
this._touch3DManager.touchPicker = value;
}
*/
public forceMouseMove:boolean;
/*TODO: implement Background
public get background():away.textures.Texture2DBase
{
return this._background;
}
*/
/*TODO: implement Background
public set background( value:away.textures.Texture2DBase )
{
this._background = value;
this._renderer.background = _background;
}
*/
// TODO: required dependency stageGL
public updateCollider()
{
if (!this._shareContext) {
if (this._htmlElement == this._mouseManager._iActiveDiv)
this._mouseManager._iCollision = this.mousePicker.getViewCollision(this._pMouseX, this._pMouseY, this);
} else {
var collidingObject:PickingCollision = this.mousePicker.getViewCollision(this._pMouseX, this._pMouseY, this);
if (this.layeredView || this._mouseManager._iCollision == null || collidingObject.rayEntryDistance < this._mouseManager._iCollision.rayEntryDistance)
this._mouseManager._iCollision = collidingObject;
}
}
}
export default View;