2017-09-24 22:23:22 +00:00
|
|
|
module TK.SpaceTac.UI {
|
2018-05-15 14:57:45 +00:00
|
|
|
/**
|
|
|
|
* Union of all UI components types
|
|
|
|
*/
|
|
|
|
export type UIComponentT = UIContainer | UIImage | UIButton | UIGraphics | UIText;
|
2017-06-08 17:32:57 +00:00
|
|
|
|
2018-05-15 14:57:45 +00:00
|
|
|
/**
|
|
|
|
* Interface to add a component to a group
|
|
|
|
*/
|
|
|
|
export interface UIGroupableI {
|
|
|
|
addToGroup(group: UIContainer): void;
|
2017-06-08 17:32:57 +00:00
|
|
|
}
|
|
|
|
|
2017-04-12 23:22:34 +00:00
|
|
|
/**
|
|
|
|
* Base class for UI components
|
2018-05-15 14:57:45 +00:00
|
|
|
*
|
|
|
|
* DEPRECATED - Use UIBuilder instead
|
2017-04-12 23:22:34 +00:00
|
|
|
*/
|
|
|
|
export class UIComponent {
|
2018-05-15 14:57:45 +00:00
|
|
|
private background: UIImage | UIGraphics | null
|
2017-06-29 17:25:38 +00:00
|
|
|
protected readonly view: BaseView
|
|
|
|
protected readonly parent: UIComponent | null
|
2018-05-15 14:57:45 +00:00
|
|
|
readonly container: UIContainer
|
2017-06-29 17:25:38 +00:00
|
|
|
protected readonly width: number
|
|
|
|
protected readonly height: number
|
2017-10-11 20:58:08 +00:00
|
|
|
protected readonly builder: UIBuilder
|
2017-04-12 23:22:34 +00:00
|
|
|
|
2017-05-02 22:49:35 +00:00
|
|
|
constructor(parent: BaseView | UIComponent, width: number, height: number, background_key: string | null = null) {
|
2017-05-03 18:12:13 +00:00
|
|
|
this.width = width;
|
|
|
|
this.height = height;
|
|
|
|
|
2017-04-12 23:22:34 +00:00
|
|
|
if (parent instanceof UIComponent) {
|
|
|
|
this.view = parent.view;
|
|
|
|
this.parent = parent;
|
|
|
|
} else {
|
|
|
|
this.view = parent;
|
|
|
|
this.parent = null;
|
|
|
|
}
|
|
|
|
|
2017-05-03 18:12:13 +00:00
|
|
|
this.container = this.createInternalNode();
|
|
|
|
if (this.parent) {
|
|
|
|
this.parent.addInternalChild(this.container);
|
|
|
|
} else {
|
|
|
|
this.view.add.existing(this.container);
|
|
|
|
}
|
2018-05-15 14:57:45 +00:00
|
|
|
this.container.setSize(width, height);
|
2017-10-11 20:58:08 +00:00
|
|
|
this.builder = new UIBuilder(this.view, this.container);
|
2017-05-02 22:49:35 +00:00
|
|
|
|
|
|
|
if (background_key) {
|
2018-03-08 19:16:05 +00:00
|
|
|
this.background = this.builder.image(background_key, 0, 0, false);
|
2017-06-08 21:00:56 +00:00
|
|
|
} else {
|
2017-06-29 17:25:38 +00:00
|
|
|
this.background = null;
|
2017-05-03 18:12:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
get game(): MainUI {
|
|
|
|
return this.view.gameui;
|
|
|
|
}
|
|
|
|
|
2017-06-08 17:32:57 +00:00
|
|
|
jasmineToString(): string {
|
|
|
|
return this.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
toString(): string {
|
|
|
|
return `<${classname(this)}>`;
|
|
|
|
}
|
|
|
|
|
2017-06-29 17:25:38 +00:00
|
|
|
/**
|
|
|
|
* Draw a background
|
|
|
|
*/
|
|
|
|
drawBackground(fill: number, border?: number, border_width = 0, alpha = 1, mouse_capture?: Function) {
|
|
|
|
if (this.background) {
|
|
|
|
this.background.destroy();
|
|
|
|
}
|
|
|
|
|
2018-05-15 14:57:45 +00:00
|
|
|
let rect = new Phaser.Geom.Rectangle(0, 0, this.width, this.height);
|
|
|
|
this.background = this.addInternalChild(new UIGraphics(this.view, "background"));
|
|
|
|
this.background.addRectangle(rect, fill, border_width, border, alpha);
|
2017-06-29 17:25:38 +00:00
|
|
|
|
|
|
|
if (mouse_capture) {
|
2018-05-15 14:57:45 +00:00
|
|
|
this.background.setInteractive(rect, Phaser.Geom.Rectangle.Contains);
|
|
|
|
this.background.on("pointerup", () => mouse_capture());
|
2017-06-29 17:25:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-25 23:09:29 +00:00
|
|
|
/**
|
|
|
|
* Move the a parent's layer
|
|
|
|
*/
|
2018-05-15 14:57:45 +00:00
|
|
|
moveToLayer(layer: UIContainer) {
|
2017-05-25 23:09:29 +00:00
|
|
|
layer.add(this.container);
|
|
|
|
}
|
|
|
|
|
2017-06-08 17:32:57 +00:00
|
|
|
/**
|
|
|
|
* Destroy the component
|
|
|
|
*/
|
2018-05-15 14:57:45 +00:00
|
|
|
destroy() {
|
|
|
|
this.container.destroy();
|
2017-06-08 17:32:57 +00:00
|
|
|
}
|
|
|
|
|
2017-05-03 18:12:13 +00:00
|
|
|
/**
|
|
|
|
* Create the internal phaser node
|
|
|
|
*/
|
2018-05-15 14:57:45 +00:00
|
|
|
protected createInternalNode(): UIContainer {
|
|
|
|
let result = new UIContainer(this.view);
|
|
|
|
result.setName(classname(this));
|
|
|
|
return result;
|
2017-05-03 18:12:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add an other internal component as child
|
|
|
|
*/
|
2018-05-15 14:57:45 +00:00
|
|
|
protected addInternalChild<T extends UIComponentT>(child: T): T {
|
2017-06-29 17:25:38 +00:00
|
|
|
this.container.add(child);
|
|
|
|
return child;
|
2017-04-12 23:22:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the component's visibility, with optional transition (in milliseconds)
|
|
|
|
*/
|
|
|
|
setVisible(visible: boolean, transition = 0): void {
|
2017-06-29 17:25:38 +00:00
|
|
|
this.view.animations.setVisible(this.container, visible, transition);
|
2017-04-12 23:22:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the component's declared size
|
|
|
|
*/
|
|
|
|
getSize(): [number, number] {
|
|
|
|
return [this.width, this.height];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the width and height of parent
|
|
|
|
*/
|
|
|
|
getParentSize(): [number, number] {
|
|
|
|
if (this.parent) {
|
|
|
|
return this.parent.getSize();
|
|
|
|
} else {
|
|
|
|
return [this.view.getWidth(), this.view.getHeight()];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the component's position (either relative to its parent, or absolute in the view)
|
|
|
|
*/
|
|
|
|
getPosition(relative = false): [number, number] {
|
|
|
|
if (relative || !this.parent) {
|
|
|
|
return [this.container.x, this.container.y];
|
|
|
|
} else {
|
|
|
|
let [px, py] = this.parent.getPosition();
|
|
|
|
return [px + this.container.x, py + this.container.y];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-02 22:49:35 +00:00
|
|
|
/**
|
|
|
|
* Set the position in pixels.
|
|
|
|
*/
|
|
|
|
setPosition(x: number, y: number): void {
|
2018-05-15 14:57:45 +00:00
|
|
|
this.container.setPosition(x, y);
|
2017-05-02 22:49:35 +00:00
|
|
|
}
|
|
|
|
|
2017-04-12 23:22:34 +00:00
|
|
|
/**
|
|
|
|
* Position the component inside the boundaries of its parent.
|
|
|
|
*
|
|
|
|
* (0, 0) is the top-left anchoring, (1, 1) is the bottom-right one.
|
|
|
|
*
|
|
|
|
* If *pixelsnap* is true, position will be rounded to pixel.
|
|
|
|
*/
|
|
|
|
setPositionInsideParent(x: number, y: number, pixelsnap = true): void {
|
|
|
|
let [pwidth, pheight] = this.getParentSize();
|
|
|
|
let [width, height] = this.getSize();
|
|
|
|
let rx = (pwidth - width) * x;
|
|
|
|
let ry = (pheight - height) * y;
|
|
|
|
if (pixelsnap) {
|
2018-05-15 14:57:45 +00:00
|
|
|
this.container.setPosition(Math.round(rx), Math.round(ry));
|
2017-04-12 23:22:34 +00:00
|
|
|
} else {
|
2018-05-15 14:57:45 +00:00
|
|
|
this.container.setPosition(rx, ry);
|
2017-04-12 23:22:34 +00:00
|
|
|
}
|
|
|
|
}
|
2017-05-02 22:49:35 +00:00
|
|
|
|
2017-06-05 22:05:34 +00:00
|
|
|
/**
|
|
|
|
* Clear from all added content.
|
|
|
|
*/
|
|
|
|
clearContent(): void {
|
2017-06-29 17:25:38 +00:00
|
|
|
let offset = this.background ? 1 : 0;
|
2018-05-15 14:57:45 +00:00
|
|
|
while (this.container.list.length > offset) {
|
|
|
|
this.container.remove(this.container.list[offset], true);
|
2017-06-05 22:05:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-02 22:49:35 +00:00
|
|
|
/**
|
|
|
|
* Add a button in the component, positioning its center.
|
2018-03-08 19:16:05 +00:00
|
|
|
*
|
|
|
|
* DEPRECATED - Use UIBuilder directly
|
2017-05-02 22:49:35 +00:00
|
|
|
*/
|
2018-05-15 14:57:45 +00:00
|
|
|
addButton(x: number, y: number, on_click: Function, background: string, tooltip = ""): UIButton {
|
|
|
|
return this.builder.button(background, x, y, on_click, tooltip, undefined, { center: true });
|
2017-05-03 18:12:13 +00:00
|
|
|
}
|
|
|
|
|
2017-05-25 23:09:29 +00:00
|
|
|
/**
|
|
|
|
* Add a static text.
|
2018-03-08 19:16:05 +00:00
|
|
|
*
|
|
|
|
* DEPRECATED - Use UIBuilder directly
|
2017-05-25 23:09:29 +00:00
|
|
|
*/
|
2018-05-15 14:57:45 +00:00
|
|
|
addText(x: number, y: number, content: string, color = "#ffffff", size = 16, bold = false, center = true, width = 0, vcenter = center): UIText {
|
2017-10-11 20:58:08 +00:00
|
|
|
return this.builder.text(content, x, y, { color: color, size: size, bold: bold, center: center, width: width, vcenter: vcenter });
|
2017-05-25 23:09:29 +00:00
|
|
|
}
|
|
|
|
|
2017-07-31 16:13:55 +00:00
|
|
|
/**
|
|
|
|
* Add a static image, from atlases, positioning its center.
|
2018-03-08 19:16:05 +00:00
|
|
|
*
|
|
|
|
* DEPRECATED - Use UIBuilder directly
|
2017-07-31 16:13:55 +00:00
|
|
|
*/
|
2018-05-15 14:57:45 +00:00
|
|
|
addImage(x: number, y: number, name: string, scale = 1): UIImage {
|
|
|
|
let result = this.builder.image(name, x, y, true);
|
|
|
|
result.setScale(scale);
|
2017-10-11 20:58:08 +00:00
|
|
|
return result;
|
2017-07-31 16:13:55 +00:00
|
|
|
}
|
2017-04-12 23:22:34 +00:00
|
|
|
}
|
|
|
|
}
|