瀏覽代碼

Merge pull request #4114 from royibernthal/master

Complex Line Tracking
David Catuhe 7 年之前
父節點
當前提交
3e052d6738
共有 3 個文件被更改,包括 352 次插入1 次删除
  1. 3 1
      Tools/Gulp/config.json
  2. 217 0
      gui/src/controls/multiLine.ts
  3. 132 0
      gui/src/multiLinePoint.ts

+ 3 - 1
Tools/Gulp/config.json

@@ -1622,6 +1622,7 @@
                     "../../gui/src/measure.ts",
                     "../../gui/src/math2D.ts",
                     "../../gui/src/valueAndUnit.ts",
+                    "../../gui/src/multiLinePoint.ts",
                     "../../gui/src/controls/control.ts",
                     "../../gui/src/controls/container.ts",
                     "../../gui/src/controls/stackPanel.ts",
@@ -1636,7 +1637,8 @@
                     "../../gui/src/controls/button.ts",
                     "../../gui/src/controls/colorpicker.ts",
                     "../../gui/src/controls/inputText.ts",
-                    "../../gui/src/controls/virtualKeyboard.ts"
+                    "../../gui/src/controls/virtualKeyboard.ts",
+                    "../../gui/src/controls/multiLine.ts"
                 ],
                 "output": "babylon.gui.js",
                 "buildAsModule": true,

+ 217 - 0
gui/src/controls/multiLine.ts

@@ -0,0 +1,217 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GUI {
+
+    export class MultiLine extends Control {
+
+        private _lineWidth: number = 1;
+        private _dash: number[];
+        private _points: Nullable<MultiLinePoint>[];
+
+        private _minX: Nullable<number>;
+        private _minY: Nullable<number>;
+        private _maxX: Nullable<number>;
+        private _maxY: Nullable<number>;
+
+        constructor(public name?: string) {
+            super(name);
+
+            this.isHitTestVisible = false;
+            this._horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
+            this._verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
+
+            this._dash = [];
+            this._points = [];
+        }
+
+        public get dash(): Array<number> {
+            return this._dash;
+        }
+
+        public set dash(value: Array<number>) {
+            if (this._dash === value) {
+                return;
+            }
+
+            this._dash = value;
+            this._markAsDirty();
+        }
+
+        public getAt(index: number): MultiLinePoint {
+            if (!this._points[index]) {
+                this._points[index] = new MultiLinePoint(this);
+            }
+
+            return this._points[index] as MultiLinePoint;
+        }
+
+        public onPointUpdate = (): void => {
+            this._markAsDirty();
+        }
+
+        public add(...items: (AbstractMesh | Control | { x: string | number, y: string | number })[]): void {
+            items.forEach(item => {
+                var point: MultiLinePoint = this.push();
+
+                if (item instanceof AbstractMesh) {
+                    point.mesh = item;
+                }
+                else if (item instanceof Control) {
+                    point.control = item;
+                }
+                else if (item.x != null && item.y != null) {
+                    point.x = item.x;
+                    point.y = item.y;
+                }
+            });
+        }
+
+        public push(): MultiLinePoint {
+            return this.getAt(this._points.length);
+        }
+
+        public remove(value: number | MultiLinePoint): void {
+            var index: number;
+            
+            if (value instanceof MultiLinePoint) {
+                index = this._points.indexOf(value);
+
+                if (index === -1) {
+                    return;
+                }
+            }
+            else {
+                index = value;
+            }
+            
+            var point: Nullable<MultiLinePoint> = this._points[index];
+
+            if (!point) {
+                return;
+            }
+
+            point.dispose();
+
+            this._points.splice(index, 1);
+        }
+        
+        public get lineWidth(): number {
+            return this._lineWidth;
+        }
+
+        public set lineWidth(value: number) {
+            if (this._lineWidth === value) {
+                return;
+            }
+
+            this._lineWidth = value;
+            this._markAsDirty();
+        }   
+
+        public set horizontalAlignment(value: number) {
+            return;
+        } 
+
+        public set verticalAlignment(value: number) {
+            return;
+        }
+
+        protected _getTypeName(): string {
+            return "MultiLine";
+        }              
+
+        public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+            context.save();
+
+            if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY){
+                context.shadowColor = this.shadowColor;
+                context.shadowBlur = this.shadowBlur;
+                context.shadowOffsetX = this.shadowOffsetX;
+                context.shadowOffsetY = this.shadowOffsetY;
+            }
+
+            this._applyStates(context);
+
+            if (this._processMeasures(parentMeasure, context)) {
+                context.strokeStyle = this.color;
+                context.lineWidth = this._lineWidth;
+                context.setLineDash(this._dash);
+
+                context.beginPath();
+
+                var first: boolean = true; //first index is not necessarily 0
+
+                this._points.forEach(point => {
+                    if (!point) {
+                        return;
+                    }
+
+                    if (first) {
+                        context.moveTo(point._point.x, point._point.y);
+
+                        first = false;
+                    }
+                    else {
+                        context.lineTo(point._point.x, point._point.y);
+                    }
+                });
+
+                context.stroke();
+            }
+
+            context.restore();
+        }
+
+        protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+            this._minX = null;
+            this._minY = null;
+            this._maxX = null;
+            this._maxY = null;
+            
+            this._points.forEach((point, index) => {
+                if (!point) {
+                    return;
+                }
+
+                point.translate();
+
+                if (this._minX == null || point._point.x < this._minX) this._minX = point._point.x;
+                if (this._minY == null || point._point.y < this._minY) this._minY = point._point.y;
+                if (this._maxX == null || point._point.x > this._maxX) this._maxX = point._point.x;
+                if (this._maxY == null || point._point.y > this._maxY) this._maxY = point._point.y;
+            });
+
+            if (this._minX == null) this._minX = 0;
+            if (this._minY == null) this._minY = 0;
+            if (this._maxX == null) this._maxX = 0;
+            if (this._maxY == null) this._maxY = 0;
+        }
+
+        public _measure(): void {
+            if (this._minX == null || this._maxX == null || this._minY == null || this._maxY == null) {
+                return;
+            }
+
+            this._currentMeasure.width = Math.abs(this._maxX - this._minX) + this._lineWidth;
+            this._currentMeasure.height = Math.abs(this._maxY - this._minY) + this._lineWidth;
+        }
+
+        protected _computeAlignment(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+            if (this._minX == null || this._minY == null) {
+                return;
+            }
+
+            this._currentMeasure.left = this._minX - this._lineWidth / 2;
+            this._currentMeasure.top = this._minY - this._lineWidth / 2;  
+        }
+
+        public dispose(): void {
+            while (this._points.length > 0) {
+                this.remove(this._points.length - 1);
+            }
+
+            super.dispose();
+        }
+
+    }    
+}

+ 132 - 0
gui/src/multiLinePoint.ts

@@ -0,0 +1,132 @@
+/// <reference path="../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GUI {
+
+    export class MultiLinePoint {
+
+        private _multiLine: MultiLine;
+
+        private _x: ValueAndUnit;
+        private _y: ValueAndUnit;
+        private _control: Nullable<Control>;
+        private _mesh: Nullable<AbstractMesh>;
+
+        private _controlObserver: Nullable< Observer<Control> >;
+        private _meshObserver: Nullable< Observer<Camera> >;
+
+        public _point: Vector2;
+
+        constructor(multiLine: MultiLine) {
+            this._multiLine = multiLine;
+
+            this._x = new ValueAndUnit(0);
+            this._y = new ValueAndUnit(0);
+
+            this._point = new Vector2(0, 0);
+        }
+
+        public get x(): string | number {
+            return this._x.toString(this._multiLine._host);
+        }
+
+        public set x(value: string | number) {
+            if (this._x.toString(this._multiLine._host) === value) {
+                return;
+            }
+
+            if (this._x.fromString(value)) {
+                this._multiLine._markAsDirty();
+            }
+        }
+
+        public get y(): string | number {
+            return this._y.toString(this._multiLine._host);
+        }
+
+        public set y(value: string | number) {
+            if (this._y.toString(this._multiLine._host) === value) {
+                return;
+            }
+
+            if (this._y.fromString(value)) {
+                this._multiLine._markAsDirty();
+            }
+        }
+
+        public get control(): Nullable<Control> {
+            return this._control;
+        }
+
+        public set control(value: Nullable<Control>) {
+            if (this._control === value) {
+                return;
+            }
+
+            if (this._control && this._controlObserver) {
+                this._control.onDirtyObservable.remove(this._controlObserver);
+
+                this._controlObserver = null;
+            }
+
+            this._control = value;
+
+            if (this._control) {
+                this._controlObserver = this._control.onDirtyObservable.add(this._multiLine.onPointUpdate);
+            }
+
+            this._multiLine._markAsDirty();
+        }
+
+        public get mesh(): Nullable<AbstractMesh> {
+            return this._mesh;
+        }
+
+        public set mesh(value: Nullable<AbstractMesh>) {
+            if (this._mesh === value) {
+                return;
+            }
+
+            if (this._mesh && this._meshObserver) {
+                this._mesh.getScene().onAfterCameraRenderObservable.remove(this._meshObserver);
+            }
+
+            this._mesh = value;
+
+            if (this._mesh) {
+                this._meshObserver = this._mesh.getScene().onAfterCameraRenderObservable.add(this._multiLine.onPointUpdate);
+            }
+
+            this._multiLine._markAsDirty();
+        }
+
+        public translate(): Vector2 {
+            this._point = this._translatePoint();
+
+            return this._point;
+        }
+
+        private _translatePoint(): Vector2 {
+            if (this._mesh != null) {
+                return this._multiLine._host.getProjectedPosition(this._mesh.getBoundingInfo().boundingSphere.center, this._mesh.getWorldMatrix());
+            }
+            else if (this._control != null) {
+                return new Vector2(this._control.centerX, this._control.centerY);
+            }
+            else {
+                var host: any = this._multiLine._host as any;
+
+                var xValue: number = this._x.getValueInPixel(host, Number(host._canvas.width));
+                var yValue: number = this._y.getValueInPixel(host, Number(host._canvas.height));
+                
+                return new Vector2(xValue, yValue);
+            }
+        }
+
+        public dispose(): void {
+            this.control = null;
+            this.mesh = null;
+        }
+
+    }
+
+}