From 532352bb01f4ff5ecc06b614aa9d2dab030d7e18 Mon Sep 17 00:00:00 2001 From: Ronja Date: Fri, 24 Apr 2020 18:53:00 +0200 Subject: [PATCH] add possible tooltips to buttons --- Program/src/Datatypes/MathTypes/math.ts | 26 +++++++--- Program/src/Systems/{ => UI}/InfoSystem.ts | 15 +++--- Program/src/Systems/UI/TooltipSystem.ts | 48 +++++++++++++++++++ .../Systems/rendering/DebugRenderSystem.ts | 45 ++++++++++------- Program/src/Systems/rendering/ZOrderSystem.ts | 40 ++++++++-------- Program/src/UI/Button.ts | 20 ++++++++ Program/src/UI/InfoMenu.ts | 5 +- Program/src/UI/PlanningMenu.ts | 13 +++-- Program/src/setup.ts | 13 +++-- 9 files changed, 167 insertions(+), 58 deletions(-) rename Program/src/Systems/{ => UI}/InfoSystem.ts (82%) create mode 100644 Program/src/Systems/UI/TooltipSystem.ts diff --git a/Program/src/Datatypes/MathTypes/math.ts b/Program/src/Datatypes/MathTypes/math.ts index c728c55..85a2c3c 100644 --- a/Program/src/Datatypes/MathTypes/math.ts +++ b/Program/src/Datatypes/MathTypes/math.ts @@ -1,8 +1,22 @@ - -export function clamp(value: number, min:number, max:number) { +export function clamp(value: number, min: number, max: number) { return Math.min(Math.max(value, min), max) -}; +} -export function lerp(from: number, to:number, at:number) { - return from + (to - from) * at; -}; \ No newline at end of file +export function invLerp(min: number, max: number, value: number) { + return (value - min) / (max - min) +} + +export function lerp(from: number, to: number, at: number) { + return from + (to - from) * at +} + +export function remap( + fromMin: number, + fromMax: number, + toMin: number, + toMax: number, + value: number +) { + let relValue = invLerp(fromMin, fromMax, value) + return lerp(toMin, toMax, relValue) +} diff --git a/Program/src/Systems/InfoSystem.ts b/Program/src/Systems/UI/InfoSystem.ts similarity index 82% rename from Program/src/Systems/InfoSystem.ts rename to Program/src/Systems/UI/InfoSystem.ts index 3c4de4e..bb9da11 100644 --- a/Program/src/Systems/InfoSystem.ts +++ b/Program/src/Systems/UI/InfoSystem.ts @@ -1,10 +1,10 @@ import { Container, DisplayObject } from "pixi.js" -import { AABB } from "../Datatypes/MathTypes/aabb" +import { AABB } from "../../Datatypes/MathTypes/aabb" import { System, Entity } from "ecsy" -import globals from "../globals" -import { Adventure } from "../Components/adventure" -import { InfoMenu } from "../UI/InfoMenu" -import { PlanningMenu } from "../UI/PlanningMenu" +import globals from "../../globals" +import { Adventure } from "../../Components/adventure" +import { InfoMenu } from "../../UI/InfoMenu" +import { PlanningMenu } from "../../UI/PlanningMenu" enum InfoState { None, @@ -13,9 +13,9 @@ enum InfoState { Info, } -// MovableSystem +// InfoSystem export class InfoSystem extends System { - priority = 80 + priority = 60 root: Container elements: { [id: string]: DisplayObject } = {} @@ -32,6 +32,7 @@ export class InfoSystem extends System { this.root = globals.app.stage.addChild(new Container()) this.root.position = bounds.min() + this.root.zIndex = 1000 this.infoMenu = new InfoMenu(this) this.planningMenu = new PlanningMenu(this) diff --git a/Program/src/Systems/UI/TooltipSystem.ts b/Program/src/Systems/UI/TooltipSystem.ts new file mode 100644 index 0000000..f003aa9 --- /dev/null +++ b/Program/src/Systems/UI/TooltipSystem.ts @@ -0,0 +1,48 @@ +import { Text } from "pixi.js" +import { System } from "ecsy" +import globals from "../../globals" + +// InfoSystem +export class TooltipSystem extends System { + priority = 61 + + tooltip: Text + source: any + active = false + + init() { + this.tooltip = new Text("Lorem Ipsum", { + fontFamily: "babyblocks", + fontSize: 8, + fill: 0x000000, + }) + globals.app.stage.addChild(this.tooltip) + this.tooltip.anchor.set(0, 1) + this.tooltip.zIndex = 1100 + this.tooltip.visible = false + } + + showTooltip(text: string, source: any) { + this.active = true + this.source = source + this.tooltip.text = text + this.tooltip.visible = true + } + + cancelTooltip(source: any) { + if (this.source === source) { + this.active = false + this.tooltip.visible = false + } + } + + execute(delta: number) { + if (this.active) { + let pos = globals.app.renderer.plugins.interaction.mouse.global + this.tooltip.position = pos + } + } + + static queries = {} + queries: any +} diff --git a/Program/src/Systems/rendering/DebugRenderSystem.ts b/Program/src/Systems/rendering/DebugRenderSystem.ts index 1650684..10a4bd0 100644 --- a/Program/src/Systems/rendering/DebugRenderSystem.ts +++ b/Program/src/Systems/rendering/DebugRenderSystem.ts @@ -1,44 +1,57 @@ import { System, Entity, Not } from "ecsy" -import { DebugRect } from "../../Components/rendering/debugRect"; -import { PixiRepresentation } from "../../Components/rendering/pixiRepresentation"; -import { Graphics, DisplayObject } from "pixi.js"; -import globals from "../../globals"; +import { DebugRect } from "../../Components/rendering/debugRect" +import { PixiRepresentation } from "../../Components/rendering/pixiRepresentation" +import { Graphics, DisplayObject } from "pixi.js" +import globals from "../../globals" // MovableSystem export class DebugRenderSystem extends System { - priority: 90 + priority: 70 // This method will get called on every frame by default - execute(delta : number) { + execute(delta: number) { // Iterate through all the entities on the query this.queries.newRectangles.results.forEach((entity: Entity) => { let debugRect = entity.getComponent(DebugRect) let graphic = new Graphics() graphic.lineStyle(1, debugRect.color, 0.5) - graphic.drawRect(debugRect.rect.source.x, debugRect.rect.source.y, debugRect.rect.size.x, debugRect.rect.size.y) + graphic.drawRect( + debugRect.rect.source.x, + debugRect.rect.source.y, + debugRect.rect.size.x, + debugRect.rect.size.y + ) globals.app.stage.addChild(graphic) - entity.addComponent(PixiRepresentation, {value: graphic}) + entity.addComponent(PixiRepresentation, { + value: graphic, + }) }) this.queries.rectangles.changed.forEach((entity: Entity) => { let debugRect = entity.getComponent(DebugRect) - let graphic = entity.getMutableComponent(PixiRepresentation).value as Graphics + let graphic = entity.getMutableComponent(PixiRepresentation) + .value as Graphics graphic.clear graphic.lineStyle(1, debugRect.color, 0.5) - graphic.drawRect(debugRect.rect.source.x, debugRect.rect.source.y, debugRect.rect.size.x, debugRect.rect.size.y) + graphic.drawRect( + debugRect.rect.source.x, + debugRect.rect.source.y, + debugRect.rect.size.x, + debugRect.rect.size.y + ) }) } static queries = { newRectangles: { - components: [ DebugRect, Not(PixiRepresentation) ] + components: [DebugRect, Not(PixiRepresentation)], }, rectangles: { - components: [ DebugRect, PixiRepresentation ], + components: [DebugRect, PixiRepresentation], listen: { - changed: [ DebugRect ] - } + changed: [DebugRect], + }, }, } - queries: any; -} \ No newline at end of file + queries: any +} diff --git a/Program/src/Systems/rendering/ZOrderSystem.ts b/Program/src/Systems/rendering/ZOrderSystem.ts index 29c1cef..0886aec 100644 --- a/Program/src/Systems/rendering/ZOrderSystem.ts +++ b/Program/src/Systems/rendering/ZOrderSystem.ts @@ -1,43 +1,45 @@ -import { PixiRepresentation } from "../../Components/rendering/pixiRepresentation"; -import { Entity, System } from "ecsy"; -import { Position } from "../../Components/position"; -import { OrderZ } from "../../Components/rendering/orderZ"; -import globals from "../../globals"; - +import { PixiRepresentation } from "../../Components/rendering/pixiRepresentation" +import { Entity, System } from "ecsy" +import { Position } from "../../Components/position" +import { OrderZ } from "../../Components/rendering/orderZ" +import globals from "../../globals" +import { canvasHeight } from "../../constants" export class ZOrderSystem extends System { - priority: 98 + priority = 98 + + minIndex = 0 + maxIndex = canvasHeight // This method will get called on every frame by default execute() { - this.queries.objects.added.forEach((entity:Entity) => { + this.queries.objects.added.forEach((entity: Entity) => { let representation = entity.getComponent(PixiRepresentation).value let order = entity.getComponent(OrderZ) let pos = entity.getComponent(Position).value representation.zIndex = pos.y + order.offset - }); + }) - this.queries.objects.changed.forEach((entity:Entity) => { - if(!(entity as any).alive) - return + this.queries.objects.changed.forEach((entity: Entity) => { + if (!(entity as any).alive) return let representation = entity.getComponent(PixiRepresentation).value let order = entity.getComponent(OrderZ) let pos = entity.getComponent(Position).value representation.zIndex = pos.y + order.offset - }); - if(this.queries.objects.changed.length > 0) + }) + if (this.queries.objects.changed.length > 0) globals.app.stage.sortChildren() } static queries = { objects: { // add all draw components here as not thingy otherwise your representation will be killed - components: [ Position, OrderZ , PixiRepresentation ], + components: [Position, OrderZ, PixiRepresentation], listen: { added: true, - changed: [ Position, OrderZ ], - } + changed: [Position, OrderZ], + }, }, } - queries: any; -} \ No newline at end of file + queries: any +} diff --git a/Program/src/UI/Button.ts b/Program/src/UI/Button.ts index 69bb894..6f22b42 100644 --- a/Program/src/UI/Button.ts +++ b/Program/src/UI/Button.ts @@ -1,4 +1,6 @@ import { Sprite, Texture, interaction } from "pixi.js" +import globals from "../globals" +import { TooltipSystem } from "../Systems/UI/TooltipSystem" export class Button extends Sprite { //TODO: sound utility @@ -10,6 +12,12 @@ export class Button extends Sprite { hovered = false clicked = false + tooltipText = "" + + setTooltip(tooltip: string) { + this.tooltipText = tooltip + } + constructor(texture?: Texture) { super() @@ -30,11 +38,13 @@ export class Button extends Sprite { startHover() { this.hovered = true this.updateSprite() + this.showTooltip() } endHover() { this.hovered = false this.updateSprite() + this.hideTooltip() } startClick() { @@ -47,6 +57,16 @@ export class Button extends Sprite { this.updateSprite() } + showTooltip() { + let ttSystem = globals.world.getSystem(TooltipSystem) as TooltipSystem + ttSystem?.showTooltip(this.tooltipText, this) + } + + hideTooltip() { + let ttSystem = globals.world.getSystem(TooltipSystem) as TooltipSystem + ttSystem?.cancelTooltip(this) + } + updateSprite() { if (this.clicked && this.clickSprite) { this.texture = this.clickSprite diff --git a/Program/src/UI/InfoMenu.ts b/Program/src/UI/InfoMenu.ts index 42c7d0e..f139b27 100644 --- a/Program/src/UI/InfoMenu.ts +++ b/Program/src/UI/InfoMenu.ts @@ -1,7 +1,7 @@ import { Container, Text, Sprite, Loader, Texture, interaction } from "pixi.js" import { Point } from "../Datatypes/MathTypes/point" -import { InfoSystem } from "../Systems/InfoSystem" +import { InfoSystem } from "../Systems/UI/InfoSystem" import { Name } from "../Components/name" import { Entity } from "ecsy" import { Button } from "./Button" @@ -46,11 +46,13 @@ export class InfoMenu extends Container { let buttons = Loader.shared.resources["AdventureButtons"].textures let buttonDef: { texture: Texture + tooltip?: string action?: (event: interaction.InteractionEvent) => void context?: any }[] = [ { texture: buttons["New"], + tooltip: "New Adventure", action: this.system.createAdventure, context: this.system, }, @@ -65,6 +67,7 @@ export class InfoMenu extends Container { let button = new Button(def.texture) if (def.action) button.onClick(def.action, def.context) + if (def.tooltip) button.setTooltip(def.tooltip) container.addChild(button) button.position = new Point(i * 18, 0) diff --git a/Program/src/UI/PlanningMenu.ts b/Program/src/UI/PlanningMenu.ts index 6a4d0e5..d27b71f 100644 --- a/Program/src/UI/PlanningMenu.ts +++ b/Program/src/UI/PlanningMenu.ts @@ -1,7 +1,7 @@ import { Container, Loader, Texture, interaction } from "pixi.js" import { Point } from "../Datatypes/MathTypes/point" -import { InfoSystem } from "../Systems/InfoSystem" +import { InfoSystem } from "../Systems/UI/InfoSystem" import { Button } from "./Button" export class PlanningMenu extends Container { @@ -20,18 +20,20 @@ export class PlanningMenu extends Container { let buttons = Loader.shared.resources["AdventureButtons"].textures let buttonDef: { texture: Texture + tooltip?: string action?: (event: interaction.InteractionEvent) => void context?: any }[] = [ { texture: buttons["Clear"], + tooltip: "Discard Adventure", action: this.system.abortPlans, context: this.system, }, - { texture: buttons["People"] }, - { texture: buttons["Items"] }, - { texture: buttons["Dir"] }, - { texture: buttons["Go"] }, + { texture: buttons["People"], tooltip: "Adventurers" }, + { texture: buttons["Items"], tooltip: "Supplies" }, + { texture: buttons["Dir"], tooltip: "Travel Direction" }, + { texture: buttons["Go"], tooltip: "Start Adventure!" }, { texture: null }, { texture: null }, ] @@ -44,6 +46,7 @@ export class PlanningMenu extends Container { let def = buttonDef[i] let button = new Button(def.texture) if (def.action) button.onClick(def.action, def.context) + if (def.tooltip) button.setTooltip(def.tooltip) container.addChild(button) button.position = new Point(i * 18, 0) diff --git a/Program/src/setup.ts b/Program/src/setup.ts index 0fbfd95..7d22c2b 100644 --- a/Program/src/setup.ts +++ b/Program/src/setup.ts @@ -15,29 +15,34 @@ import { PathWalkerSystem } from "./Systems/PathWalkerSystem" import { VisibleHumanSystem } from "./Systems/VisibleHumanSystem" import { SpriteSystem } from "./Systems/rendering/SpriteSystem" import { ClickableSystem } from "./Systems/ClickableSystem" -import { InfoSystem } from "./Systems/InfoSystem" +import { InfoSystem } from "./Systems/UI/InfoSystem" import { DebugRenderSystem } from "./Systems/rendering/DebugRenderSystem" import { ZOrderSystem } from "./Systems/rendering/ZOrderSystem" import { PixiCleanupSystem } from "./Systems/rendering/PixiCleanupSystem" import { RenderSystem } from "./Systems/rendering/RenderSystem" import { Vector } from "./Datatypes/MathTypes/vector" +import { TooltipSystem } from "./Systems/UI/TooltipSystem" export function setup() { // Create world and register the systems on it //we could also register components here but they should get automatically registered once used for the first time globals.world = new World() globals.world + //before everything -100 to -1 .registerSystem(TestSystem) //prio -100 .registerSystem(AdventureReturnSystem) //prio -100 + //most stuff 0 to 50 .registerSystem(DoorSystem) //prio 0 .registerSystem(RandomWalkSystem) //prio 0 .registerSystem(PathWalkerSystem) //prio 50 .registerSystem(VisibleHumanSystem) //prio 50 + //rendering 51 - 100 + .registerSystem(InfoSystem) //prio 60 + .registerSystem(TooltipSystem) .registerSystem(SpriteSystem) //prio 70 + .registerSystem(DebugRenderSystem) //prio 70 .registerSystem(ClickableSystem) //prio 80 - .registerSystem(InfoSystem) //prio 80 - .registerSystem(DebugRenderSystem) //prio 90 - .registerSystem(ZOrderSystem) //prio 98 + .registerSystem(ZOrderSystem) //prio 80 .registerSystem(PixiCleanupSystem) //prio 99 .registerSystem(RenderSystem) //prio 100