improved ui elements
This commit is contained in:
parent
91fcfd0a0d
commit
b33b7b0a21
|
@ -21,7 +21,8 @@ export default class InputReceiver{
|
||||||
this.receiver = new Receiver();
|
this.receiver = new Receiver();
|
||||||
this.keyJustPressed = new Map<boolean>();
|
this.keyJustPressed = new Map<boolean>();
|
||||||
this.keyPressed = new Map<boolean>();
|
this.keyPressed = new Map<boolean>();
|
||||||
this.mousePressPosition = null;
|
this.mousePosition = new Vec2(0, 0);
|
||||||
|
this.mousePressPosition = new Vec2(0, 0);
|
||||||
|
|
||||||
this.eventQueue = EventQueue.getInstance();
|
this.eventQueue = EventQueue.getInstance();
|
||||||
this.eventQueue.subscribe(this.receiver, ["mouse_down", "mouse_up", "mouse_move", "key_down", "key_up", "canvas_blur"]);
|
this.eventQueue.subscribe(this.receiver, ["mouse_down", "mouse_up", "mouse_move", "key_down", "key_up", "canvas_blur"]);
|
||||||
|
|
|
@ -9,12 +9,22 @@ export default class UIElement extends CanvasNode{
|
||||||
borderColor: Color;
|
borderColor: Color;
|
||||||
text: string;
|
text: string;
|
||||||
font: string;
|
font: string;
|
||||||
|
fontSize: number;
|
||||||
|
hAlign: string;
|
||||||
|
vAlign: string;
|
||||||
|
|
||||||
// EventAttributes
|
// EventAttributes
|
||||||
onClick: Function;
|
onClick: Function;
|
||||||
onClickEventId: string;
|
onClickEventId: string;
|
||||||
onHover: Function;
|
onRelease: Function;
|
||||||
onHoverEventId: string;
|
onReleaseEventId: string;
|
||||||
|
onEnter: Function;
|
||||||
|
onEnterEventId: string;
|
||||||
|
onLeave: Function;
|
||||||
|
onLeaveEventId: string;
|
||||||
|
|
||||||
|
protected isClicked: boolean;
|
||||||
|
protected isEntered: boolean;
|
||||||
|
|
||||||
constructor(){
|
constructor(){
|
||||||
super();
|
super();
|
||||||
|
@ -22,13 +32,23 @@ export default class UIElement extends CanvasNode{
|
||||||
this.backgroundColor = new Color(0, 0, 0, 0);
|
this.backgroundColor = new Color(0, 0, 0, 0);
|
||||||
this.borderColor = new Color(0, 0, 0, 0);
|
this.borderColor = new Color(0, 0, 0, 0);
|
||||||
this.text = "";
|
this.text = "";
|
||||||
this.font = "30px Arial";
|
this.font = "Arial";
|
||||||
|
this.fontSize = 30;
|
||||||
|
this.hAlign = "center";
|
||||||
|
this.vAlign = "center";
|
||||||
|
|
||||||
this.onClick = null;
|
this.onClick = null;
|
||||||
this.onClickEventId = null;
|
this.onClickEventId = null;
|
||||||
|
this.onRelease = null;
|
||||||
|
this.onReleaseEventId = null;
|
||||||
|
|
||||||
this.onHover = null;
|
this.onEnter = null;
|
||||||
this.onHoverEventId = null;
|
this.onEnterEventId = null;
|
||||||
|
this.onLeave = null;
|
||||||
|
this.onLeaveEventId = null;
|
||||||
|
|
||||||
|
this.isClicked = false;
|
||||||
|
this.isEntered = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
setPosition(vecOrX: Vec2 | number, y: number = null): void {
|
setPosition(vecOrX: Vec2 | number, y: number = null): void {
|
||||||
|
@ -61,14 +81,9 @@ export default class UIElement extends CanvasNode{
|
||||||
|
|
||||||
update(deltaT: number): void {
|
update(deltaT: number): void {
|
||||||
if(this.input.isMouseJustPressed()){
|
if(this.input.isMouseJustPressed()){
|
||||||
let mousePos = this.input.getMousePressPosition();
|
let clickPos = this.input.getMousePressPosition();
|
||||||
if(mousePos.x >= this.position.x && mousePos.x <= this.position.x + this.size.x){
|
if(this.contains(clickPos.x, clickPos.y)){
|
||||||
// Inside x bounds
|
this.isClicked = true;
|
||||||
if(mousePos.y >= this.position.y && mousePos.y <= this.position.y + this.size.y){
|
|
||||||
// Inside element
|
|
||||||
if(this.onHover !== null){
|
|
||||||
this.onHover();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.onClick !== null){
|
if(this.onClick !== null){
|
||||||
this.onClick();
|
this.onClick();
|
||||||
|
@ -79,14 +94,83 @@ export default class UIElement extends CanvasNode{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!this.input.isMousePressed()){
|
||||||
|
if(this.isClicked){
|
||||||
|
this.isClicked = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render(ctx: CanvasRenderingContext2D, viewportOrigin: Vec2, viewportSize: Vec2){
|
let mousePos = this.input.getMousePosition();
|
||||||
ctx.fillStyle = this.backgroundColor.toStringRGBA();
|
if(mousePos && this.contains(mousePos.x, mousePos.y)){
|
||||||
|
this.isEntered = true;
|
||||||
|
|
||||||
|
if(this.onEnter !== null){
|
||||||
|
this.onEnter();
|
||||||
|
}
|
||||||
|
if(this.onEnterEventId !== null){
|
||||||
|
let data = {};
|
||||||
|
this.emit(this.onEnterEventId, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if(this.isEntered) {
|
||||||
|
this.isEntered = false;
|
||||||
|
|
||||||
|
if(this.onLeave !== null){
|
||||||
|
this.onLeave();
|
||||||
|
}
|
||||||
|
if(this.onLeaveEventId !== null){
|
||||||
|
let data = {};
|
||||||
|
this.emit(this.onLeaveEventId, data);
|
||||||
|
}
|
||||||
|
} else if(this.isClicked) {
|
||||||
|
// If mouse is dragged off of element while down, it is not clicked anymore
|
||||||
|
this.isClicked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected calculateOffset(ctx: CanvasRenderingContext2D): Vec2 {
|
||||||
|
let textWidth = ctx.measureText(this.text).width;
|
||||||
|
|
||||||
|
let offset = new Vec2(0, 0);
|
||||||
|
|
||||||
|
let hDiff = this.size.x - textWidth;
|
||||||
|
if(this.hAlign === "center"){
|
||||||
|
offset.x = hDiff/2;
|
||||||
|
} else if (this.hAlign === "right"){
|
||||||
|
offset.x = hDiff;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.vAlign === "top"){
|
||||||
|
ctx.textBaseline = "top";
|
||||||
|
offset.y = 0;
|
||||||
|
} else if (this.vAlign === "bottom"){
|
||||||
|
ctx.textBaseline = "bottom";
|
||||||
|
offset.y = this.size.y;
|
||||||
|
} else {
|
||||||
|
ctx.textBaseline = "middle";
|
||||||
|
offset.y = this.size.y/2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected calculateBackgroundColor(): string {
|
||||||
|
return this.backgroundColor.toStringRGBA();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected calculateTextColor(): string {
|
||||||
|
return this.textColor.toStringRGBA();
|
||||||
|
}
|
||||||
|
|
||||||
|
render(ctx: CanvasRenderingContext2D, viewportOrigin: Vec2, viewportSize: Vec2): void {
|
||||||
|
ctx.font = this.fontSize + "px " + this.font;
|
||||||
|
let offset = this.calculateOffset(ctx);
|
||||||
|
|
||||||
|
ctx.fillStyle = this.calculateBackgroundColor();
|
||||||
ctx.fillRect(this.position.x - viewportOrigin.x, this.position.y - viewportOrigin.y, this.size.x, this.size.y);
|
ctx.fillRect(this.position.x - viewportOrigin.x, this.position.y - viewportOrigin.y, this.size.x, this.size.y);
|
||||||
ctx.fillStyle = this.textColor.toStringRGBA();
|
|
||||||
ctx.font = this.font;
|
ctx.fillStyle = this.calculateTextColor();
|
||||||
ctx.fillText(this.text, this.position.x - viewportOrigin.x, this.position.y - viewportOrigin.y + 30);
|
ctx.fillText(this.text, this.position.x + offset.x - viewportOrigin.x, this.position.y + offset.y - viewportOrigin.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
23
src/Nodes/UIElements/Button.ts
Normal file
23
src/Nodes/UIElements/Button.ts
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import UIElement from "../UIElement";
|
||||||
|
import Color from "../../Utils/Color";
|
||||||
|
import Vec2 from "../../DataTypes/Vec2";
|
||||||
|
|
||||||
|
export default class Button extends UIElement{
|
||||||
|
|
||||||
|
constructor(){
|
||||||
|
super();
|
||||||
|
this.backgroundColor = new Color(150, 75, 203);
|
||||||
|
this.borderColor = new Color(41, 46, 30);
|
||||||
|
this.textColor = new Color(255, 255, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected calculateBackgroundColor(): string {
|
||||||
|
if(this.isEntered && !this.isClicked){
|
||||||
|
return this.backgroundColor.lighten().toStringRGBA();
|
||||||
|
} else if(this.isClicked){
|
||||||
|
return this.backgroundColor.darken().toStringRGBA();
|
||||||
|
} else {
|
||||||
|
return this.backgroundColor.toStringRGBA();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
src/Nodes/UIElements/Label.ts
Normal file
8
src/Nodes/UIElements/Label.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import UIElement from "../UIElement";
|
||||||
|
|
||||||
|
export default class Label extends UIElement{
|
||||||
|
constructor(text: string){
|
||||||
|
super();
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,18 +13,26 @@ export default class Color{
|
||||||
this.a = a;
|
this.a = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lighten(): Color {
|
||||||
|
return new Color(MathUtils.clamp(this.r + 40, 0, 255), MathUtils.clamp(this.g + 40, 0, 255), MathUtils.clamp(this.b + 40, 0, 255), this.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
darken(): Color {
|
||||||
|
return new Color(MathUtils.clamp(this.r - 40, 0, 255), MathUtils.clamp(this.g - 40, 0, 255), MathUtils.clamp(this.b - 40, 0, 255), this.a);
|
||||||
|
}
|
||||||
|
|
||||||
toString(): string {
|
toString(): string {
|
||||||
return "#" + MathUtils.toHex(this.r, 2) + MathUtils.toHex(this.g, 2) + MathUtils.toHex(this.b, 2);
|
return "#" + MathUtils.toHex(this.r, 2) + MathUtils.toHex(this.g, 2) + MathUtils.toHex(this.b, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
toStringRGB(){
|
toStringRGB(): string {
|
||||||
return "rgb(" + this.r.toString() + ", " + this.g.toString() + ", " + this.b.toString() + ")";
|
return "rgb(" + this.r.toString() + ", " + this.g.toString() + ", " + this.b.toString() + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
toStringRGBA(){
|
toStringRGBA(): string {
|
||||||
if(this.a === null){
|
if(this.a === null){
|
||||||
throw "No alpha value assigned to color";
|
return this.toStringRGB();
|
||||||
}
|
}
|
||||||
return "rgb(" + this.r.toString() + ", " + this.g.toString() + ", " + this.b.toString() + ", " + this.a.toString() +")"
|
return "rgba(" + this.r.toString() + ", " + this.g.toString() + ", " + this.b.toString() + ", " + this.a.toString() +")"
|
||||||
}
|
}
|
||||||
}
|
}
|
19
src/main.ts
19
src/main.ts
|
@ -4,6 +4,7 @@ import Player from "./Nodes/Player";
|
||||||
import UIElement from "./Nodes/UIElement";
|
import UIElement from "./Nodes/UIElement";
|
||||||
import ColoredCircle from "./Nodes/ColoredCircle";
|
import ColoredCircle from "./Nodes/ColoredCircle";
|
||||||
import Color from "./Utils/Color";
|
import Color from "./Utils/Color";
|
||||||
|
import Button from "./Nodes/UIElements/Button";
|
||||||
|
|
||||||
function main(){
|
function main(){
|
||||||
// Create the game object
|
// Create the game object
|
||||||
|
@ -15,31 +16,27 @@ function main(){
|
||||||
// Initialize GameObjects
|
// Initialize GameObjects
|
||||||
let player = new Player();
|
let player = new Player();
|
||||||
|
|
||||||
let recordButton = new UIElement();
|
let recordButton = new Button();
|
||||||
recordButton.setSize(100, 50);
|
recordButton.setSize(100, 50);
|
||||||
recordButton.setText("Record");
|
recordButton.setText("Record");
|
||||||
recordButton.setBackgroundColor(new Color(200, 100, 0, 0.3));
|
|
||||||
recordButton.setPosition(400, 30);
|
recordButton.setPosition(400, 30);
|
||||||
recordButton.onClickEventId = "record_button_press";
|
recordButton.onClickEventId = "record_button_press";
|
||||||
|
|
||||||
let stopButton = new UIElement();
|
let stopButton = new Button();
|
||||||
stopButton.setSize(100, 50);
|
stopButton.setSize(100, 50);
|
||||||
stopButton.setText("Stop");
|
stopButton.setText("Stop");
|
||||||
stopButton.setBackgroundColor(new Color(200, 0, 0, 0.3));
|
|
||||||
stopButton.setPosition(550, 30);
|
stopButton.setPosition(550, 30);
|
||||||
stopButton.onClickEventId = "stop_button_press";
|
stopButton.onClickEventId = "stop_button_press";
|
||||||
|
|
||||||
let playButton = new UIElement();
|
let playButton = new Button();
|
||||||
playButton.setSize(100, 50);
|
playButton.setSize(100, 50);
|
||||||
playButton.setText("Play");
|
playButton.setText("Play");
|
||||||
playButton.setBackgroundColor(new Color(0, 200, 0, 0.3));
|
|
||||||
playButton.setPosition(700, 30);
|
playButton.setPosition(700, 30);
|
||||||
playButton.onClickEventId = "play_button_press";
|
playButton.onClickEventId = "play_button_press";
|
||||||
|
|
||||||
let cycleFramerateButton = new UIElement();
|
let cycleFramerateButton = new Button();
|
||||||
cycleFramerateButton.setSize(150, 50);
|
cycleFramerateButton.setSize(150, 50);
|
||||||
cycleFramerateButton.setText("Cycle FPS");
|
cycleFramerateButton.setText("Cycle FPS");
|
||||||
cycleFramerateButton.setBackgroundColor(new Color(200, 0, 200, 0.3));
|
|
||||||
cycleFramerateButton.setPosition(5, 400);
|
cycleFramerateButton.setPosition(5, 400);
|
||||||
let i = 0;
|
let i = 0;
|
||||||
let fps = [15, 30, 60];
|
let fps = [15, 30, 60];
|
||||||
|
@ -48,10 +45,9 @@ function main(){
|
||||||
i = (i + 1) % 3;
|
i = (i + 1) % 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
let pauseButton = new UIElement();
|
let pauseButton = new Button();
|
||||||
pauseButton.setSize(100, 50);
|
pauseButton.setSize(100, 50);
|
||||||
pauseButton.setText("Pause");
|
pauseButton.setText("Pause");
|
||||||
pauseButton.setBackgroundColor(new Color(200, 0, 200, 1));
|
|
||||||
pauseButton.setPosition(700, 400);
|
pauseButton.setPosition(700, 400);
|
||||||
pauseButton.onClick = () => {
|
pauseButton.onClick = () => {
|
||||||
game.getGameState().addScene(pauseMenu);
|
game.getGameState().addScene(pauseMenu);
|
||||||
|
@ -62,10 +58,9 @@ function main(){
|
||||||
modalBackground.setBackgroundColor(new Color(0, 0, 0, 0.4));
|
modalBackground.setBackgroundColor(new Color(0, 0, 0, 0.4));
|
||||||
modalBackground.setPosition(200, 100);
|
modalBackground.setPosition(200, 100);
|
||||||
|
|
||||||
let resumeButton = new UIElement();
|
let resumeButton = new Button();
|
||||||
resumeButton.setSize(100, 50);
|
resumeButton.setSize(100, 50);
|
||||||
resumeButton.setText("Resume");
|
resumeButton.setText("Resume");
|
||||||
resumeButton.setBackgroundColor(new Color(200, 0, 200, 1));
|
|
||||||
resumeButton.setPosition(400, 200);
|
resumeButton.setPosition(400, 200);
|
||||||
resumeButton.onClick = () => {
|
resumeButton.onClick = () => {
|
||||||
game.getGameState().removeScene();
|
game.getGameState().removeScene();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user