2017-09-24 22:23:22 +00:00
|
|
|
module TK.SpaceTac.UI {
|
2017-05-15 23:20:35 +00:00
|
|
|
export type IBounded = {
|
|
|
|
x: number
|
|
|
|
y: number
|
|
|
|
width: number
|
|
|
|
height: number
|
2017-04-19 21:34:11 +00:00
|
|
|
}
|
|
|
|
|
2017-10-01 18:16:41 +00:00
|
|
|
/**
|
|
|
|
* Destroy all children of a Phaser object
|
|
|
|
*
|
|
|
|
* This is a workaround for a removeChildren bug
|
|
|
|
*/
|
2018-05-15 14:57:45 +00:00
|
|
|
export function destroyChildren(obj: UIContainer, start = 0, end = obj.length - 1) {
|
|
|
|
obj.list.slice(start, end + 1).forEach(child => child.destroy());
|
2017-10-01 18:16:41 +00:00
|
|
|
}
|
|
|
|
|
2018-05-15 14:57:45 +00:00
|
|
|
/**
|
|
|
|
* Common UI function to work around some Phaser limitations
|
|
|
|
*/
|
2017-05-04 23:19:28 +00:00
|
|
|
export class UITools {
|
2018-02-08 15:16:03 +00:00
|
|
|
/**
|
2018-05-15 14:57:45 +00:00
|
|
|
* Check that a game object has transform and bounds available
|
2018-02-08 15:16:03 +00:00
|
|
|
*/
|
2018-05-15 14:57:45 +00:00
|
|
|
static isSpatial(obj: any): obj is Phaser.GameObjects.Components.GetBounds & Phaser.GameObjects.Components.Transform {
|
|
|
|
return obj instanceof UIImage || obj instanceof UIText || obj instanceof UIContainer;
|
|
|
|
}
|
2018-02-08 15:16:03 +00:00
|
|
|
|
2018-05-15 14:57:45 +00:00
|
|
|
/**
|
|
|
|
* Get the bounding rectanle of a displayed object, in screen space
|
|
|
|
*/
|
|
|
|
static getBounds(obj: UIContainer | (Phaser.GameObjects.GameObject & Phaser.GameObjects.Components.GetBounds)): IBounded {
|
|
|
|
let result: IBounded;
|
|
|
|
|
|
|
|
if (obj instanceof UIContainer) {
|
|
|
|
result = obj.getBounds();
|
|
|
|
} else {
|
|
|
|
result = obj.getBounds();
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2018-02-08 15:16:03 +00:00
|
|
|
|
2018-05-15 14:57:45 +00:00
|
|
|
/**
|
|
|
|
* Check if a game object is visible
|
|
|
|
*/
|
|
|
|
static isVisible(obj: Phaser.GameObjects.GameObject & Phaser.GameObjects.Components.Visible & Phaser.GameObjects.Components.Alpha): boolean {
|
|
|
|
if (obj.visible && obj.alpha) {
|
|
|
|
if (obj.parentContainer) {
|
|
|
|
return this.isVisible(obj.parentContainer);
|
|
|
|
} else {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
2018-02-08 15:16:03 +00:00
|
|
|
}
|
|
|
|
|
2017-03-15 21:40:19 +00:00
|
|
|
/**
|
2017-04-19 21:34:11 +00:00
|
|
|
* Get the position of an object, adjusted to remain inside a container
|
2017-03-15 21:40:19 +00:00
|
|
|
*/
|
2017-04-19 21:34:11 +00:00
|
|
|
static positionInside(obj: IBounded, container: IBounded): [number, number] {
|
|
|
|
let y = obj.y;
|
|
|
|
if (y + obj.height > container.height) {
|
|
|
|
y = container.height - obj.height;
|
2017-03-15 21:40:19 +00:00
|
|
|
}
|
2017-04-19 21:34:11 +00:00
|
|
|
if (y < container.y) {
|
|
|
|
y = container.y;
|
2017-03-15 21:40:19 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 21:34:11 +00:00
|
|
|
let x = obj.x;
|
|
|
|
if (x + obj.width > container.width) {
|
|
|
|
x = container.width - obj.width;
|
2017-03-15 21:40:19 +00:00
|
|
|
}
|
2017-04-19 21:34:11 +00:00
|
|
|
if (x < container.x) {
|
|
|
|
x = container.x;
|
|
|
|
}
|
|
|
|
|
|
|
|
return [x, y];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reposition an object to remain inside a container
|
|
|
|
*/
|
2018-05-15 14:57:45 +00:00
|
|
|
static keepInside(obj: UIButton | UIImage | UIContainer, rect: IBounded) {
|
|
|
|
let objbounds = UITools.getBounds(obj);
|
2017-05-04 23:19:28 +00:00
|
|
|
let [x, y] = UITools.positionInside({ x: obj.x, y: obj.y, width: objbounds.width, height: objbounds.height }, rect);
|
2017-04-19 21:34:11 +00:00
|
|
|
|
|
|
|
if (x != obj.x || y != obj.y) {
|
2018-05-15 14:57:45 +00:00
|
|
|
obj.setPosition(x, y);
|
2017-03-15 21:40:19 +00:00
|
|
|
}
|
|
|
|
}
|
2015-01-26 00:00:00 +00:00
|
|
|
|
2018-02-08 15:16:03 +00:00
|
|
|
/**
|
|
|
|
* Compare two rectangles
|
|
|
|
*/
|
|
|
|
static compareRects(rct1: IBounded, rct2: IBounded) {
|
|
|
|
return rct1.x == rct2.x && rct1.y == rct2.y && rct1.width == rct2.width && rct1.height == rct2.height;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the bounding rectangle containing two other rectangles
|
|
|
|
*/
|
|
|
|
static unionRects(rct1: IBounded, rct2: IBounded): IBounded {
|
|
|
|
let result: IBounded;
|
|
|
|
if (rct1.width == 0 || rct1.height == 0) {
|
|
|
|
result = rct2;
|
|
|
|
} else if (rct2.width == 0 || rct2.height == 0) {
|
|
|
|
result = rct1;
|
|
|
|
} else {
|
|
|
|
let xmin = Math.min(rct1.x, rct2.x);
|
|
|
|
let xmax = Math.max(rct1.x + rct1.width, rct2.x + rct2.width);
|
|
|
|
let ymin = Math.min(rct1.y, rct2.y);
|
|
|
|
let ymax = Math.max(rct1.y + rct1.height, rct2.y + rct2.height);
|
|
|
|
|
|
|
|
result = { x: xmin, y: ymin, width: xmax - xmin, height: ymax - ymin };
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result.width == 0 || result.height == 0) {
|
|
|
|
return { x: 0, y: 0, width: 0, height: 0 };
|
|
|
|
} else {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constraint an angle in radians the ]-pi;pi] range.
|
|
|
|
*/
|
2015-01-26 00:00:00 +00:00
|
|
|
static normalizeAngle(angle: number): number {
|
|
|
|
angle = angle % (2 * Math.PI);
|
|
|
|
if (angle <= -Math.PI) {
|
|
|
|
return angle + 2 * Math.PI;
|
2017-01-19 00:17:24 +00:00
|
|
|
} else if (angle > Math.PI) {
|
2015-01-26 00:00:00 +00:00
|
|
|
return angle - 2 * Math.PI;
|
|
|
|
} else {
|
|
|
|
return angle;
|
|
|
|
}
|
|
|
|
}
|
2017-05-16 23:12:05 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Evenly space identical items in a parent
|
|
|
|
*
|
|
|
|
* Returns the relative position of item's center inside parent_width
|
|
|
|
*/
|
|
|
|
static evenlySpace(parent_width: number, item_width: number, item_count: number): number[] {
|
|
|
|
if (item_width * item_count <= parent_width) {
|
|
|
|
let spacing = parent_width / item_count;
|
|
|
|
return range(item_count).map(i => (i + 0.5) * spacing);
|
|
|
|
} else {
|
|
|
|
let breadth = parent_width - item_width;
|
|
|
|
let spacing = breadth / (item_count - 1);
|
|
|
|
return range(item_count).map(i => item_width / 2 + i * spacing);
|
|
|
|
}
|
|
|
|
}
|
2017-05-22 20:41:34 +00:00
|
|
|
|
|
|
|
/**
|
2018-02-08 15:16:03 +00:00
|
|
|
* Draw a background around a content
|
2017-05-22 20:41:34 +00:00
|
|
|
*/
|
2018-05-15 14:57:45 +00:00
|
|
|
static drawBackground(content: UIContainer | UIText, background: UIBackground, border = 6): [number, number] {
|
|
|
|
if (content.parentContainer === background.parent) {
|
|
|
|
background.adaptToContent(content);
|
|
|
|
return [background.width, background.height];
|
2018-02-08 15:16:03 +00:00
|
|
|
} else {
|
|
|
|
console.error("Cannot draw background with different parents", content, background);
|
|
|
|
return [0, 0];
|
|
|
|
}
|
2017-05-22 20:41:34 +00:00
|
|
|
}
|
2015-01-26 00:00:00 +00:00
|
|
|
}
|
|
|
|
}
|