import * as Pixi from "pixi.js";
import { PixiPointFrom } from "../../lib/pixi/pixify";
import { Vector2 } from "../../lib/util/geometry/vector2";
import { UpdaterGeneratorType2 } from "../../lib/util/updaterGenerator";
import { engageLifecycle, LifecycleHandlerBase } from "./LifecycleHandler";
type Props = {
args: {
markForceUpdate: (childInstance: any) => void,
},
hitArea: Pixi.IHitArea;
text: string;
delaySeconds?: number;
}
type State = {
isActive: boolean;
}
/**
* For a interesting reference implementation, see https://www.iwm-tuebingen.de/iwmbrowser/lib/pixi/button.html
*/
class TooltippableAreaComponent extends LifecycleHandlerBase<Props, State> {
public state: State
public container: Pixi.Container;
private stateUpdaters: UpdaterGeneratorType2<State>
protected fireStateUpdaters: () => void
public hitAreaDrawn?: Pixi.Graphics; // debug
tooltipContainer: Pixi.Container | null;
constructor(props: Props) {
super(props);
this.container = new Pixi.Container();
this.container.interactive = true;
this.container.buttonMode = true;
this.container.hitArea = props.hitArea;
this.container.zIndex = 2;
// this.container.hitArea = new Pixi.Rectangle(
// - RenderedChunkConstants.NODE_HITAREA_PX / 2,
// - RenderedChunkConstants.NODE_HITAREA_PX / 2,
// RenderedChunkConstants.NODE_HITAREA_PX,
// RenderedChunkConstants.NODE_HITAREA_PX,
// );
// this.hitAreaDrawn = new Pixi.Graphics();
// this.hitAreaDrawn.beginFill(0xffffff);
// this.hitAreaDrawn.drawRect(
// - RenderedChunkConstants.NODE_HITAREA_PX / 2,
// - RenderedChunkConstants.NODE_HITAREA_PX / 2,
// RenderedChunkConstants.NODE_HITAREA_PX,
// RenderedChunkConstants.NODE_HITAREA_PX,
// );
// this.container.addChild(this.hitAreaDrawn);
this.tooltipContainer = null;
({ state: this.state, stateUpdaters: this.stateUpdaters, fireStateUpdaters: this.fireStateUpdaters } =
this.useState<State, TooltippableAreaComponent>(this, {
isActive: false
}));
}
protected renderSelf(props: Props) {
// if (this.state.isActive) {
// this.hitAreaDrawn.tint = 0x888888;
// } else {
// this.hitAreaDrawn.tint = 0xffffff;
// }
if (this.state.isActive) {
if (this.tooltipContainer === null) {
// if doesnt exist, construct it
this.tooltipContainer = new Pixi.Container();
this.tooltipContainer.sortableChildren = true;
const text = new Pixi.Text(props.text, {
fontFamily: 'PixelMix',
padding: 4, // https://github.com/pixijs/pixi.js/issues/4500 -- otherwise on first load the text bounding box is calculated to be too small and the tops of the f's get cut off
fontSize: 26, // use 26 then scale down 50% results in sharper letters than 13
// align: 'center'
});
text.scale = PixiPointFrom(new Vector2(0.5, 0.5));
text.x = 10;
text.y = 10;
text.zIndex = 1;
this.tooltipContainer.addChild(text);
const box = new Pixi.Graphics();
box.lineStyle(1, 0x222222, 1);
box.beginFill(0xEEEEEE);
box.drawRoundedRect(0, 0, text.width + 18, text.height + 18, 4);
box.zIndex = 0;
this.tooltipContainer.addChild(box);
this.container.addChild(this.tooltipContainer);
}
} else {
if (this.tooltipContainer) {
// remove it
this.container.removeChild(this.tooltipContainer);
this.tooltipContainer.destroy();
this.tooltipContainer = null;
}
}
}
protected didMount() {
// TODO(bowei): move these listeners to the parent so that hitArea can be unified
// TODO(bowei): move this object to somewhere else in pixi e.g. the parent hud layer to resolve hiding issues
// using worldtransform: https://www.html5gamedevs.com/topic/12774-absolute-position-of-displayobjectsspritesprimitives/
this.container.addListener('pointerover', this.onPointerOver);
this.container.addListener('pointerout', this.onPointerOut);
}
public onPointerOver = (event: Pixi.InteractionEvent) => {
// console.log('got onPointerOver in toolltippable');
this._staleProps.args.markForceUpdate(this);
this.stateUpdaters.isActive.enqueueUpdate(() => {
// console.log('fired onPointerOver in toolltippable');
return true;
});
}
public onPointerOut = (event: Pixi.InteractionEvent) => {
this._staleProps.args.markForceUpdate(this);
// console.log('got onPointerOut in tooltippable')
this.stateUpdaters.isActive.enqueueUpdate(() => {
// console.log('fired onPointerOut in tooltippable')
return false;
});
}
}
const wrapped = engageLifecycle(TooltippableAreaComponent);
// eslint-disable-next-line
type wrapped = TooltippableAreaComponent;
export { wrapped as TooltippableAreaComponent };
export type { Props as TooltippableAreaComponentProps };