multiLine.ts 7.5 KB

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