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.keyJustPressed = 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.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;
|
||||
text: string;
|
||||
font: string;
|
||||
fontSize: number;
|
||||
hAlign: string;
|
||||
vAlign: string;
|
||||
|
||||
// EventAttributes
|
||||
onClick: Function;
|
||||
onClickEventId: string;
|
||||
onHover: Function;
|
||||
onHoverEventId: string;
|
||||
onRelease: Function;
|
||||
onReleaseEventId: string;
|
||||
onEnter: Function;
|
||||
onEnterEventId: string;
|
||||
onLeave: Function;
|
||||
onLeaveEventId: string;
|
||||
|
||||
protected isClicked: boolean;
|
||||
protected isEntered: boolean;
|
||||
|
||||
constructor(){
|
||||
super();
|
||||
|
@ -22,13 +32,23 @@ export default class UIElement extends CanvasNode{
|
|||
this.backgroundColor = new Color(0, 0, 0, 0);
|
||||
this.borderColor = new Color(0, 0, 0, 0);
|
||||
this.text = "";
|
||||
this.font = "30px Arial";
|
||||
this.font = "Arial";
|
||||
this.fontSize = 30;
|
||||
this.hAlign = "center";
|
||||
this.vAlign = "center";
|
||||
|
||||
this.onClick = null;
|
||||
this.onClickEventId = null;
|
||||
this.onRelease = null;
|
||||
this.onReleaseEventId = null;
|
||||
|
||||
this.onHover = null;
|
||||
this.onHoverEventId = null;
|
||||
this.onEnter = null;
|
||||
this.onEnterEventId = null;
|
||||
this.onLeave = null;
|
||||
this.onLeaveEventId = null;
|
||||
|
||||
this.isClicked = false;
|
||||
this.isEntered = false;
|
||||
}
|
||||
|
||||
setPosition(vecOrX: Vec2 | number, y: number = null): void {
|
||||
|
@ -61,14 +81,9 @@ export default class UIElement extends CanvasNode{
|
|||
|
||||
update(deltaT: number): void {
|
||||
if(this.input.isMouseJustPressed()){
|
||||
let mousePos = this.input.getMousePressPosition();
|
||||
if(mousePos.x >= this.position.x && mousePos.x <= this.position.x + this.size.x){
|
||||
// Inside x bounds
|
||||
if(mousePos.y >= this.position.y && mousePos.y <= this.position.y + this.size.y){
|
||||
// Inside element
|
||||
if(this.onHover !== null){
|
||||
this.onHover();
|
||||
}
|
||||
let clickPos = this.input.getMousePressPosition();
|
||||
if(this.contains(clickPos.x, clickPos.y)){
|
||||
this.isClicked = true;
|
||||
|
||||
if(this.onClick !== null){
|
||||
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){
|
||||
ctx.fillStyle = this.backgroundColor.toStringRGBA();
|
||||
let mousePos = this.input.getMousePosition();
|
||||
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.fillStyle = this.textColor.toStringRGBA();
|
||||
ctx.font = this.font;
|
||||
ctx.fillText(this.text, this.position.x - viewportOrigin.x, this.position.y - viewportOrigin.y + 30);
|
||||
|
||||
ctx.fillStyle = this.calculateTextColor();
|
||||
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;
|
||||
}
|
||||
|
||||
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 {
|
||||
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() + ")";
|
||||
}
|
||||
|
||||
toStringRGBA(){
|
||||
toStringRGBA(): string {
|
||||
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 ColoredCircle from "./Nodes/ColoredCircle";
|
||||
import Color from "./Utils/Color";
|
||||
import Button from "./Nodes/UIElements/Button";
|
||||
|
||||
function main(){
|
||||
// Create the game object
|
||||
|
@ -15,31 +16,27 @@ function main(){
|
|||
// Initialize GameObjects
|
||||
let player = new Player();
|
||||
|
||||
let recordButton = new UIElement();
|
||||
let recordButton = new Button();
|
||||
recordButton.setSize(100, 50);
|
||||
recordButton.setText("Record");
|
||||
recordButton.setBackgroundColor(new Color(200, 100, 0, 0.3));
|
||||
recordButton.setPosition(400, 30);
|
||||
recordButton.onClickEventId = "record_button_press";
|
||||
|
||||
let stopButton = new UIElement();
|
||||
let stopButton = new Button();
|
||||
stopButton.setSize(100, 50);
|
||||
stopButton.setText("Stop");
|
||||
stopButton.setBackgroundColor(new Color(200, 0, 0, 0.3));
|
||||
stopButton.setPosition(550, 30);
|
||||
stopButton.onClickEventId = "stop_button_press";
|
||||
|
||||
let playButton = new UIElement();
|
||||
let playButton = new Button();
|
||||
playButton.setSize(100, 50);
|
||||
playButton.setText("Play");
|
||||
playButton.setBackgroundColor(new Color(0, 200, 0, 0.3));
|
||||
playButton.setPosition(700, 30);
|
||||
playButton.onClickEventId = "play_button_press";
|
||||
|
||||
let cycleFramerateButton = new UIElement();
|
||||
let cycleFramerateButton = new Button();
|
||||
cycleFramerateButton.setSize(150, 50);
|
||||
cycleFramerateButton.setText("Cycle FPS");
|
||||
cycleFramerateButton.setBackgroundColor(new Color(200, 0, 200, 0.3));
|
||||
cycleFramerateButton.setPosition(5, 400);
|
||||
let i = 0;
|
||||
let fps = [15, 30, 60];
|
||||
|
@ -48,10 +45,9 @@ function main(){
|
|||
i = (i + 1) % 3;
|
||||
}
|
||||
|
||||
let pauseButton = new UIElement();
|
||||
let pauseButton = new Button();
|
||||
pauseButton.setSize(100, 50);
|
||||
pauseButton.setText("Pause");
|
||||
pauseButton.setBackgroundColor(new Color(200, 0, 200, 1));
|
||||
pauseButton.setPosition(700, 400);
|
||||
pauseButton.onClick = () => {
|
||||
game.getGameState().addScene(pauseMenu);
|
||||
|
@ -62,10 +58,9 @@ function main(){
|
|||
modalBackground.setBackgroundColor(new Color(0, 0, 0, 0.4));
|
||||
modalBackground.setPosition(200, 100);
|
||||
|
||||
let resumeButton = new UIElement();
|
||||
let resumeButton = new Button();
|
||||
resumeButton.setSize(100, 50);
|
||||
resumeButton.setText("Resume");
|
||||
resumeButton.setBackgroundColor(new Color(200, 0, 200, 1));
|
||||
resumeButton.setPosition(400, 200);
|
||||
resumeButton.onClick = () => {
|
||||
game.getGameState().removeScene();
|
||||
|
|
Loading…
Reference in New Issue
Block a user