multiLine.ts 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. import { Nullable } from "babylonjs/types";
  2. import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
  3. import { Control } from "./control";
  4. import { MultiLinePoint } from "../multiLinePoint";
  5. import { Measure } from "../measure";
  6. import { _TypeStore } from 'babylonjs/Misc/typeStore';
  7. /**
  8. * Class used to create multi line control
  9. */
  10. export class MultiLine extends Control {
  11. private _lineWidth: number = 1;
  12. private _dash: number[];
  13. private _points: Nullable<MultiLinePoint>[];
  14. private _minX: Nullable<number>;
  15. private _minY: Nullable<number>;
  16. private _maxX: Nullable<number>;
  17. private _maxY: Nullable<number>;
  18. /**
  19. * Creates a new MultiLine
  20. * @param name defines the control name
  21. */
  22. constructor(public name?: string) {
  23. super(name);
  24. this.isHitTestVisible = false;
  25. this._horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
  26. this._verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
  27. this._dash = [];
  28. this._points = [];
  29. }
  30. /** Gets or sets dash pattern */
  31. public get dash(): Array<number> {
  32. return this._dash;
  33. }
  34. public set dash(value: Array<number>) {
  35. if (this._dash === value) {
  36. return;
  37. }
  38. this._dash = value;
  39. this._markAsDirty();
  40. }
  41. /**
  42. * Gets point stored at specified index
  43. * @param index defines the index to look for
  44. * @returns the requested point if found
  45. */
  46. public getAt(index: number): MultiLinePoint {
  47. if (!this._points[index]) {
  48. this._points[index] = new MultiLinePoint(this);
  49. }
  50. return this._points[index] as MultiLinePoint;
  51. }
  52. /** Function called when a point is updated */
  53. public onPointUpdate = (): void => {
  54. this._markAsDirty();
  55. }
  56. /**
  57. * Adds new points to the point collection
  58. * @param items defines the list of items (mesh, control or 2d coordiantes) to add
  59. * @returns the list of created MultiLinePoint
  60. */
  61. public add(...items: (AbstractMesh | Control | { x: string | number, y: string | number })[]): MultiLinePoint[] {
  62. return items.map((item) => this.push(item));
  63. }
  64. /**
  65. * Adds a new point to the point collection
  66. * @param item defines the item (mesh, control or 2d coordiantes) to add
  67. * @returns the created MultiLinePoint
  68. */
  69. public push(item?: (AbstractMesh | Control | { x: string | number, y: string | number })): MultiLinePoint {
  70. var point: MultiLinePoint = this.getAt(this._points.length);
  71. if (item == null) { return point; }
  72. if (item instanceof AbstractMesh) {
  73. point.mesh = item;
  74. }
  75. else if (item instanceof Control) {
  76. point.control = item;
  77. }
  78. else if (item.x != null && item.y != null) {
  79. point.x = item.x;
  80. point.y = item.y;
  81. }
  82. return point;
  83. }
  84. /**
  85. * Remove a specific value or point from the active point collection
  86. * @param value defines the value or point to remove
  87. */
  88. public remove(value: number | MultiLinePoint): void {
  89. var index: number;
  90. if (value instanceof MultiLinePoint) {
  91. index = this._points.indexOf(value);
  92. if (index === -1) {
  93. return;
  94. }
  95. }
  96. else {
  97. index = value;
  98. }
  99. var point: Nullable<MultiLinePoint> = this._points[index];
  100. if (!point) {
  101. return;
  102. }
  103. point.dispose();
  104. this._points.splice(index, 1);
  105. }
  106. /**
  107. * Resets this object to initial state (no point)
  108. */
  109. public reset(): void {
  110. while (this._points.length > 0) {
  111. this.remove(this._points.length - 1);
  112. }
  113. }
  114. /**
  115. * Resets all links
  116. */
  117. public resetLinks(): void {
  118. this._points.forEach((point) => {
  119. if (point != null) { point.resetLinks(); }
  120. });
  121. }
  122. /** Gets or sets line width */
  123. public get lineWidth(): number {
  124. return this._lineWidth;
  125. }
  126. public set lineWidth(value: number) {
  127. if (this._lineWidth === value) {
  128. return;
  129. }
  130. this._lineWidth = value;
  131. this._markAsDirty();
  132. }
  133. public set horizontalAlignment(value: number) {
  134. return;
  135. }
  136. public set verticalAlignment(value: number) {
  137. return;
  138. }
  139. protected _getTypeName(): string {
  140. return "MultiLine";
  141. }
  142. public _draw(context: CanvasRenderingContext2D): void {
  143. context.save();
  144. if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
  145. context.shadowColor = this.shadowColor;
  146. context.shadowBlur = this.shadowBlur;
  147. context.shadowOffsetX = this.shadowOffsetX;
  148. context.shadowOffsetY = this.shadowOffsetY;
  149. }
  150. this._applyStates(context);
  151. context.strokeStyle = this.color;
  152. context.lineWidth = this._lineWidth;
  153. context.setLineDash(this._dash);
  154. context.beginPath();
  155. var first: boolean = true; //first index is not necessarily 0
  156. this._points.forEach((point) => {
  157. if (!point) {
  158. return;
  159. }
  160. if (first) {
  161. context.moveTo(point._point.x, point._point.y);
  162. first = false;
  163. }
  164. else {
  165. context.lineTo(point._point.x, point._point.y);
  166. }
  167. });
  168. context.stroke();
  169. context.restore();
  170. }
  171. protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
  172. this._minX = null;
  173. this._minY = null;
  174. this._maxX = null;
  175. this._maxY = null;
  176. this._points.forEach((point, index) => {
  177. if (!point) {
  178. return;
  179. }
  180. point.translate();
  181. if (this._minX == null || point._point.x < this._minX) { this._minX = point._point.x; }
  182. if (this._minY == null || point._point.y < this._minY) { this._minY = point._point.y; }
  183. if (this._maxX == null || point._point.x > this._maxX) { this._maxX = point._point.x; }
  184. if (this._maxY == null || point._point.y > this._maxY) { this._maxY = point._point.y; }
  185. });
  186. if (this._minX == null) { this._minX = 0; }
  187. if (this._minY == null) { this._minY = 0; }
  188. if (this._maxX == null) { this._maxX = 0; }
  189. if (this._maxY == null) { this._maxY = 0; }
  190. }
  191. public _measure(): void {
  192. if (this._minX == null || this._maxX == null || this._minY == null || this._maxY == null) {
  193. return;
  194. }
  195. this._currentMeasure.width = Math.abs(this._maxX - this._minX) + this._lineWidth;
  196. this._currentMeasure.height = Math.abs(this._maxY - this._minY) + this._lineWidth;
  197. }
  198. protected _computeAlignment(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
  199. if (this._minX == null || this._minY == null) {
  200. return;
  201. }
  202. this._currentMeasure.left = this._minX - this._lineWidth / 2;
  203. this._currentMeasure.top = this._minY - this._lineWidth / 2;
  204. }
  205. public dispose(): void {
  206. this.reset();
  207. super.dispose();
  208. }
  209. }
  210. _TypeStore.RegisteredTypes["BABYLON.GUI.MultiLine"] = MultiLine;