add possible tooltips to buttons

This commit is contained in:
Ronja 2020-04-24 18:53:00 +02:00
parent 1e7668e6a1
commit 532352bb01
9 changed files with 167 additions and 58 deletions

View file

@ -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) return Math.min(Math.max(value, min), max)
}; }
export function lerp(from: number, to:number, at:number) { export function invLerp(min: number, max: number, value: number) {
return from + (to - from) * at; 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)
}

View file

@ -1,10 +1,10 @@
import { Container, DisplayObject } from "pixi.js" import { Container, DisplayObject } from "pixi.js"
import { AABB } from "../Datatypes/MathTypes/aabb" import { AABB } from "../../Datatypes/MathTypes/aabb"
import { System, Entity } from "ecsy" import { System, Entity } from "ecsy"
import globals from "../globals" import globals from "../../globals"
import { Adventure } from "../Components/adventure" import { Adventure } from "../../Components/adventure"
import { InfoMenu } from "../UI/InfoMenu" import { InfoMenu } from "../../UI/InfoMenu"
import { PlanningMenu } from "../UI/PlanningMenu" import { PlanningMenu } from "../../UI/PlanningMenu"
enum InfoState { enum InfoState {
None, None,
@ -13,9 +13,9 @@ enum InfoState {
Info, Info,
} }
// MovableSystem // InfoSystem
export class InfoSystem extends System { export class InfoSystem extends System {
priority = 80 priority = 60
root: Container root: Container
elements: { [id: string]: DisplayObject } = {} elements: { [id: string]: DisplayObject } = {}
@ -32,6 +32,7 @@ export class InfoSystem extends System {
this.root = globals.app.stage.addChild(new Container()) this.root = globals.app.stage.addChild(new Container())
this.root.position = bounds.min() this.root.position = bounds.min()
this.root.zIndex = 1000
this.infoMenu = new InfoMenu(this) this.infoMenu = new InfoMenu(this)
this.planningMenu = new PlanningMenu(this) this.planningMenu = new PlanningMenu(this)

View file

@ -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
}

View file

@ -1,44 +1,57 @@
import { System, Entity, Not } from "ecsy" import { System, Entity, Not } from "ecsy"
import { DebugRect } from "../../Components/rendering/debugRect"; import { DebugRect } from "../../Components/rendering/debugRect"
import { PixiRepresentation } from "../../Components/rendering/pixiRepresentation"; import { PixiRepresentation } from "../../Components/rendering/pixiRepresentation"
import { Graphics, DisplayObject } from "pixi.js"; import { Graphics, DisplayObject } from "pixi.js"
import globals from "../../globals"; import globals from "../../globals"
// MovableSystem // MovableSystem
export class DebugRenderSystem extends System { export class DebugRenderSystem extends System {
priority: 90 priority: 70
// This method will get called on every frame by default // This method will get called on every frame by default
execute(delta : number) { execute(delta: number) {
// Iterate through all the entities on the query // Iterate through all the entities on the query
this.queries.newRectangles.results.forEach((entity: Entity) => { this.queries.newRectangles.results.forEach((entity: Entity) => {
let debugRect = entity.getComponent(DebugRect) let debugRect = entity.getComponent(DebugRect)
let graphic = new Graphics() let graphic = new Graphics()
graphic.lineStyle(1, debugRect.color, 0.5) 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) globals.app.stage.addChild(graphic)
entity.addComponent(PixiRepresentation, <PixiRepresentation>{value: <DisplayObject>graphic}) entity.addComponent(PixiRepresentation, <PixiRepresentation>{
value: <DisplayObject>graphic,
})
}) })
this.queries.rectangles.changed.forEach((entity: Entity) => { this.queries.rectangles.changed.forEach((entity: Entity) => {
let debugRect = entity.getComponent(DebugRect) let debugRect = entity.getComponent(DebugRect)
let graphic = entity.getMutableComponent(PixiRepresentation).value as Graphics let graphic = entity.getMutableComponent(PixiRepresentation)
.value as Graphics
graphic.clear graphic.clear
graphic.lineStyle(1, debugRect.color, 0.5) 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 = { static queries = {
newRectangles: { newRectangles: {
components: [ DebugRect, Not(PixiRepresentation) ] components: [DebugRect, Not(PixiRepresentation)],
}, },
rectangles: { rectangles: {
components: [ DebugRect, PixiRepresentation ], components: [DebugRect, PixiRepresentation],
listen: { listen: {
changed: [ DebugRect ] changed: [DebugRect],
} },
}, },
} }
queries: any; queries: any
} }

View file

@ -1,43 +1,45 @@
import { PixiRepresentation } from "../../Components/rendering/pixiRepresentation"; import { PixiRepresentation } from "../../Components/rendering/pixiRepresentation"
import { Entity, System } from "ecsy"; import { Entity, System } from "ecsy"
import { Position } from "../../Components/position"; import { Position } from "../../Components/position"
import { OrderZ } from "../../Components/rendering/orderZ"; import { OrderZ } from "../../Components/rendering/orderZ"
import globals from "../../globals"; import globals from "../../globals"
import { canvasHeight } from "../../constants"
export class ZOrderSystem extends System { export class ZOrderSystem extends System {
priority: 98 priority = 98
minIndex = 0
maxIndex = canvasHeight
// This method will get called on every frame by default // This method will get called on every frame by default
execute() { execute() {
this.queries.objects.added.forEach((entity:Entity) => { this.queries.objects.added.forEach((entity: Entity) => {
let representation = entity.getComponent(PixiRepresentation).value let representation = entity.getComponent(PixiRepresentation).value
let order = entity.getComponent(OrderZ) let order = entity.getComponent(OrderZ)
let pos = entity.getComponent(Position).value let pos = entity.getComponent(Position).value
representation.zIndex = pos.y + order.offset representation.zIndex = pos.y + order.offset
}); })
this.queries.objects.changed.forEach((entity:Entity) => { this.queries.objects.changed.forEach((entity: Entity) => {
if(!(entity as any).alive) if (!(entity as any).alive) return
return
let representation = entity.getComponent(PixiRepresentation).value let representation = entity.getComponent(PixiRepresentation).value
let order = entity.getComponent(OrderZ) let order = entity.getComponent(OrderZ)
let pos = entity.getComponent(Position).value let pos = entity.getComponent(Position).value
representation.zIndex = pos.y + order.offset representation.zIndex = pos.y + order.offset
}); })
if(this.queries.objects.changed.length > 0) if (this.queries.objects.changed.length > 0)
globals.app.stage.sortChildren() globals.app.stage.sortChildren()
} }
static queries = { static queries = {
objects: { objects: {
// add all draw components here as not thingy otherwise your representation will be killed // add all draw components here as not thingy otherwise your representation will be killed
components: [ Position, OrderZ , PixiRepresentation ], components: [Position, OrderZ, PixiRepresentation],
listen: { listen: {
added: true, added: true,
changed: [ Position, OrderZ ], changed: [Position, OrderZ],
} },
}, },
} }
queries: any; queries: any
} }

View file

@ -1,4 +1,6 @@
import { Sprite, Texture, interaction } from "pixi.js" import { Sprite, Texture, interaction } from "pixi.js"
import globals from "../globals"
import { TooltipSystem } from "../Systems/UI/TooltipSystem"
export class Button extends Sprite { export class Button extends Sprite {
//TODO: sound utility //TODO: sound utility
@ -10,6 +12,12 @@ export class Button extends Sprite {
hovered = false hovered = false
clicked = false clicked = false
tooltipText = ""
setTooltip(tooltip: string) {
this.tooltipText = tooltip
}
constructor(texture?: Texture) { constructor(texture?: Texture) {
super() super()
@ -30,11 +38,13 @@ export class Button extends Sprite {
startHover() { startHover() {
this.hovered = true this.hovered = true
this.updateSprite() this.updateSprite()
this.showTooltip()
} }
endHover() { endHover() {
this.hovered = false this.hovered = false
this.updateSprite() this.updateSprite()
this.hideTooltip()
} }
startClick() { startClick() {
@ -47,6 +57,16 @@ export class Button extends Sprite {
this.updateSprite() 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() { updateSprite() {
if (this.clicked && this.clickSprite) { if (this.clicked && this.clickSprite) {
this.texture = this.clickSprite this.texture = this.clickSprite

View file

@ -1,7 +1,7 @@
import { Container, Text, Sprite, Loader, Texture, interaction } from "pixi.js" import { Container, Text, Sprite, Loader, Texture, interaction } from "pixi.js"
import { Point } from "../Datatypes/MathTypes/point" import { Point } from "../Datatypes/MathTypes/point"
import { InfoSystem } from "../Systems/InfoSystem" import { InfoSystem } from "../Systems/UI/InfoSystem"
import { Name } from "../Components/name" import { Name } from "../Components/name"
import { Entity } from "ecsy" import { Entity } from "ecsy"
import { Button } from "./Button" import { Button } from "./Button"
@ -46,11 +46,13 @@ export class InfoMenu extends Container {
let buttons = Loader.shared.resources["AdventureButtons"].textures let buttons = Loader.shared.resources["AdventureButtons"].textures
let buttonDef: { let buttonDef: {
texture: Texture texture: Texture
tooltip?: string
action?: (event: interaction.InteractionEvent) => void action?: (event: interaction.InteractionEvent) => void
context?: any context?: any
}[] = [ }[] = [
{ {
texture: buttons["New"], texture: buttons["New"],
tooltip: "New Adventure",
action: this.system.createAdventure, action: this.system.createAdventure,
context: this.system, context: this.system,
}, },
@ -65,6 +67,7 @@ export class InfoMenu extends Container {
let button = new Button(def.texture) let button = new Button(def.texture)
if (def.action) button.onClick(def.action, def.context) if (def.action) button.onClick(def.action, def.context)
if (def.tooltip) button.setTooltip(def.tooltip)
container.addChild(button) container.addChild(button)
button.position = new Point(i * 18, 0) button.position = new Point(i * 18, 0)

View file

@ -1,7 +1,7 @@
import { Container, Loader, Texture, interaction } from "pixi.js" import { Container, Loader, Texture, interaction } from "pixi.js"
import { Point } from "../Datatypes/MathTypes/point" import { Point } from "../Datatypes/MathTypes/point"
import { InfoSystem } from "../Systems/InfoSystem" import { InfoSystem } from "../Systems/UI/InfoSystem"
import { Button } from "./Button" import { Button } from "./Button"
export class PlanningMenu extends Container { export class PlanningMenu extends Container {
@ -20,18 +20,20 @@ export class PlanningMenu extends Container {
let buttons = Loader.shared.resources["AdventureButtons"].textures let buttons = Loader.shared.resources["AdventureButtons"].textures
let buttonDef: { let buttonDef: {
texture: Texture texture: Texture
tooltip?: string
action?: (event: interaction.InteractionEvent) => void action?: (event: interaction.InteractionEvent) => void
context?: any context?: any
}[] = [ }[] = [
{ {
texture: buttons["Clear"], texture: buttons["Clear"],
tooltip: "Discard Adventure",
action: this.system.abortPlans, action: this.system.abortPlans,
context: this.system, context: this.system,
}, },
{ texture: buttons["People"] }, { texture: buttons["People"], tooltip: "Adventurers" },
{ texture: buttons["Items"] }, { texture: buttons["Items"], tooltip: "Supplies" },
{ texture: buttons["Dir"] }, { texture: buttons["Dir"], tooltip: "Travel Direction" },
{ texture: buttons["Go"] }, { texture: buttons["Go"], tooltip: "Start Adventure!" },
{ texture: null }, { texture: null },
{ texture: null }, { texture: null },
] ]
@ -44,6 +46,7 @@ export class PlanningMenu extends Container {
let def = buttonDef[i] let def = buttonDef[i]
let button = new Button(def.texture) let button = new Button(def.texture)
if (def.action) button.onClick(def.action, def.context) if (def.action) button.onClick(def.action, def.context)
if (def.tooltip) button.setTooltip(def.tooltip)
container.addChild(button) container.addChild(button)
button.position = new Point(i * 18, 0) button.position = new Point(i * 18, 0)

View file

@ -15,29 +15,34 @@ import { PathWalkerSystem } from "./Systems/PathWalkerSystem"
import { VisibleHumanSystem } from "./Systems/VisibleHumanSystem" import { VisibleHumanSystem } from "./Systems/VisibleHumanSystem"
import { SpriteSystem } from "./Systems/rendering/SpriteSystem" import { SpriteSystem } from "./Systems/rendering/SpriteSystem"
import { ClickableSystem } from "./Systems/ClickableSystem" import { ClickableSystem } from "./Systems/ClickableSystem"
import { InfoSystem } from "./Systems/InfoSystem" import { InfoSystem } from "./Systems/UI/InfoSystem"
import { DebugRenderSystem } from "./Systems/rendering/DebugRenderSystem" import { DebugRenderSystem } from "./Systems/rendering/DebugRenderSystem"
import { ZOrderSystem } from "./Systems/rendering/ZOrderSystem" import { ZOrderSystem } from "./Systems/rendering/ZOrderSystem"
import { PixiCleanupSystem } from "./Systems/rendering/PixiCleanupSystem" import { PixiCleanupSystem } from "./Systems/rendering/PixiCleanupSystem"
import { RenderSystem } from "./Systems/rendering/RenderSystem" import { RenderSystem } from "./Systems/rendering/RenderSystem"
import { Vector } from "./Datatypes/MathTypes/vector" import { Vector } from "./Datatypes/MathTypes/vector"
import { TooltipSystem } from "./Systems/UI/TooltipSystem"
export function setup() { export function setup() {
// Create world and register the systems on it // 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 //we could also register components here but they should get automatically registered once used for the first time
globals.world = new World() globals.world = new World()
globals.world globals.world
//before everything -100 to -1
.registerSystem(TestSystem) //prio -100 .registerSystem(TestSystem) //prio -100
.registerSystem(AdventureReturnSystem) //prio -100 .registerSystem(AdventureReturnSystem) //prio -100
//most stuff 0 to 50
.registerSystem(DoorSystem) //prio 0 .registerSystem(DoorSystem) //prio 0
.registerSystem(RandomWalkSystem) //prio 0 .registerSystem(RandomWalkSystem) //prio 0
.registerSystem(PathWalkerSystem) //prio 50 .registerSystem(PathWalkerSystem) //prio 50
.registerSystem(VisibleHumanSystem) //prio 50 .registerSystem(VisibleHumanSystem) //prio 50
//rendering 51 - 100
.registerSystem(InfoSystem) //prio 60
.registerSystem(TooltipSystem)
.registerSystem(SpriteSystem) //prio 70 .registerSystem(SpriteSystem) //prio 70
.registerSystem(DebugRenderSystem) //prio 70
.registerSystem(ClickableSystem) //prio 80 .registerSystem(ClickableSystem) //prio 80
.registerSystem(InfoSystem) //prio 80 .registerSystem(ZOrderSystem) //prio 80
.registerSystem(DebugRenderSystem) //prio 90
.registerSystem(ZOrderSystem) //prio 98
.registerSystem(PixiCleanupSystem) //prio 99 .registerSystem(PixiCleanupSystem) //prio 99
.registerSystem(RenderSystem) //prio 100 .registerSystem(RenderSystem) //prio 100