Skip to content

Commit a1be72f

Browse files
NaejDoreeJean Poree
authored andcommitted
feat(tooltip): adding the tooltipmodule
1 parent 0084ad0 commit a1be72f

File tree

3 files changed

+300
-0
lines changed

3 files changed

+300
-0
lines changed

engine/modules/tooltip/pom.xml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
5+
<parent>
6+
<groupId>com.codingame</groupId>
7+
<artifactId>gameengine</artifactId>
8+
<version>master-SNAPSHOT</version>
9+
<relativePath>../../../pom.xml</relativePath>
10+
</parent>
11+
12+
<groupId>com.codingame.gameengine</groupId>
13+
<artifactId>module-tooltip</artifactId>
14+
<name>CodinGame Game Engine Tooltip Module</name>
15+
<description>A module to display tooltips for the CodinGame engine toolkit.</description>
16+
17+
<dependencies>
18+
<dependency>
19+
<groupId>com.codingame.gameengine</groupId>
20+
<artifactId>core</artifactId>
21+
<version>${project.version}</version>
22+
</dependency>
23+
<dependency>
24+
<groupId>com.codingame.gameengine</groupId>
25+
<artifactId>module-entities</artifactId>
26+
<version>${project.version}</version>
27+
</dependency>
28+
</dependencies>
29+
30+
</project>
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package com.codingame.gameengine.module.tooltip;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
import com.codingame.gameengine.core.AbstractPlayer;
7+
import com.codingame.gameengine.core.GameManager;
8+
import com.codingame.gameengine.core.Module;
9+
import com.codingame.gameengine.module.entities.Entity;
10+
import com.codingame.gameengine.module.entities.GraphicEntityModule;
11+
import com.google.inject.Inject;
12+
import com.google.inject.Singleton;
13+
14+
/**
15+
* The TooltipModule takes care of displaying tooltips under the mouse cursor when an element has a linked tooltip text.
16+
*
17+
*/
18+
@Singleton
19+
public class TooltipModule implements Module {
20+
21+
GameManager<AbstractPlayer> gameManager;
22+
@Inject GraphicEntityModule entityModule;
23+
Map<Integer, String> registered, newRegistration;
24+
25+
@Inject
26+
TooltipModule(GameManager<AbstractPlayer> gameManager) {
27+
this.gameManager = gameManager;
28+
gameManager.registerModule(this);
29+
registered = new HashMap<>();
30+
newRegistration = new HashMap<>();
31+
}
32+
33+
@Override
34+
public void onGameInit() {
35+
sendFrameData();
36+
}
37+
38+
@Override
39+
public void onAfterGameTurn() {
40+
sendFrameData();
41+
}
42+
43+
@Override
44+
public void onAfterOnEnd() {
45+
sendFrameData();
46+
}
47+
48+
private void sendFrameData() {
49+
Object[] data = { newRegistration };
50+
gameManager.setViewData("tooltips", data);
51+
52+
newRegistration.clear();
53+
}
54+
55+
boolean stringEquals(String a, String b) {
56+
if (a == b) {
57+
return true;
58+
} else if (a != null && a.equals(b)) {
59+
return true;
60+
} else {
61+
return false;
62+
}
63+
}
64+
65+
/**
66+
* Sets a tooltip text linked to an entity
67+
*
68+
* @param entity
69+
* @param text is the tooltip text that will be displayed when hovering over the entity
70+
*/
71+
public void setTooltipText(Entity<?> entity, String text) {
72+
int id = entity.getId();
73+
if (!stringEquals(text, registered.get(id))) {
74+
newRegistration.put(id, text);
75+
registered.put(id, text);
76+
}
77+
}
78+
79+
/**
80+
*
81+
* @param entity
82+
* @return the tooltip text liked to the entity
83+
*/
84+
public String getTooltipText(Entity<?> entity) {
85+
return registered.get(entity.getId());
86+
}
87+
88+
/**
89+
* Removes the tooltip text linked to the entity
90+
* @param entity
91+
*/
92+
public void removeTooltipText(Entity<?> entity) {
93+
newRegistration.put(entity.getId(), null);
94+
registered.remove(entity.getId());
95+
}
96+
}
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
import { WIDTH, HEIGHT } from '../core/constants.js'
2+
import { api as entityModule } from '../entity-module/GraphicEntityModule.js'
3+
4+
/* global PIXI */
5+
6+
function getMouseOverFunc (id, tooltip) {
7+
return function () {
8+
tooltip.inside[id] = true
9+
}
10+
}
11+
12+
function getMouseOutFunc (id, tooltip) {
13+
return function () {
14+
delete tooltip.inside[id]
15+
}
16+
}
17+
18+
function getEntityState (entity, frame) {
19+
const subStates = entity.states[frame]
20+
if (subStates && subStates.length) {
21+
return subStates[subStates.length - 1]
22+
}
23+
return null
24+
}
25+
26+
function getMouseMoveFunc (tooltip, container, module) {
27+
return function (ev) {
28+
if (tooltip) {
29+
var pos = ev.data.getLocalPosition(container)
30+
tooltip.x = pos.x
31+
tooltip.y = pos.y
32+
33+
const showing = []
34+
const ids = Object.keys(tooltip.inside).map(n => +n)
35+
36+
for (let id of ids) {
37+
if (tooltip.inside[id]) {
38+
const entity = entityModule.entities.get(id)
39+
const state = entity && getEntityState(entity, module.currentFrame.number)
40+
if (!state) {
41+
delete tooltip.inside[id]
42+
} else {
43+
showing.push(id)
44+
}
45+
}
46+
}
47+
48+
if (showing.length) {
49+
const tooltipBlocks = []
50+
for (let show of showing) {
51+
const entity = entityModule.entities.get(show)
52+
const state = getEntityState(entity, module.currentFrame.number)
53+
if (state !== null) {
54+
tooltip.visible = true
55+
const text = module.currentFrame.registeredText[show]
56+
if (text && text.length && String(text).valueOf() !== '0') {
57+
tooltipBlocks.push(text)
58+
}
59+
}
60+
}
61+
tooltip.label.text = tooltipBlocks.join('\n──────────\n')
62+
} else {
63+
tooltip.visible = false
64+
}
65+
66+
tooltip.background.width = tooltip.label.width + 20
67+
tooltip.background.height = tooltip.label.height + 20
68+
69+
tooltip.pivot.x = -30
70+
tooltip.pivot.y = -50
71+
72+
if (tooltip.y - tooltip.pivot.y + tooltip.height > HEIGHT) {
73+
tooltip.pivot.y = 10 + tooltip.height
74+
tooltip.y -= tooltip.y - tooltip.pivot.y + tooltip.height - HEIGHT
75+
}
76+
77+
if (tooltip.x - tooltip.pivot.x + tooltip.width > WIDTH) {
78+
tooltip.pivot.x = tooltip.width
79+
}
80+
}
81+
}
82+
};
83+
84+
export class TooltipModule {
85+
constructor (assets) {
86+
this.interactive = {}
87+
this.previousFrame = {
88+
registered: {}
89+
}
90+
this.lastProgress = 1
91+
this.lastFrame = 0
92+
}
93+
94+
static get name () {
95+
return 'tooltips'
96+
}
97+
98+
updateScene (previousData, currentData, progress) {
99+
this.currentFrame = currentData
100+
this.currentProgress = progress
101+
}
102+
103+
handleFrameData (frameInfo, data) {
104+
if (!data) {
105+
return
106+
}
107+
const registered = data[0]
108+
const registeredText = { ...this.previousFrame.registeredText, ...registered }
109+
110+
Object.keys(registered).forEach(
111+
k => {
112+
this.interactive[k] = true
113+
}
114+
)
115+
116+
const frame = { registeredText, number: frameInfo.number }
117+
this.previousFrame = frame
118+
return frame
119+
}
120+
121+
reinitScene (container) {
122+
this.tooltip = this.initTooltip()
123+
entityModule.entities.forEach(entity => {
124+
if (this.interactive[entity.id]) {
125+
entity.container.interactive = true
126+
entity.container.mouseover = getMouseOverFunc(entity.id, this.tooltip)
127+
entity.container.mouseout = getMouseOutFunc(entity.id, this.tooltip)
128+
}
129+
})
130+
this.container = container
131+
container.interactive = true
132+
container.mousemove = getMouseMoveFunc(this.tooltip, container, this)
133+
container.addChild(this.tooltip)
134+
}
135+
136+
generateText (text, size, color, align) {
137+
var textEl = new PIXI.Text(text, {
138+
fontSize: Math.round(size / 1.2) + 'px',
139+
fontFamily: 'Lato',
140+
fontWeight: 'bold',
141+
fill: color
142+
})
143+
144+
textEl.lineHeight = Math.round(size / 1.2)
145+
if (align === 'right') {
146+
textEl.anchor.x = 1
147+
} else if (align === 'center') {
148+
textEl.anchor.x = 0.5
149+
}
150+
151+
return textEl
152+
};
153+
154+
initTooltip () {
155+
var tooltip = new PIXI.Container()
156+
var background = tooltip.background = new PIXI.Graphics()
157+
var label = tooltip.label = this.generateText('', 36, 0xFFFFFF, 'left')
158+
159+
background.beginFill(0x0, 0.7)
160+
background.drawRect(0, 0, 200, 185)
161+
background.endFill()
162+
background.x = -10
163+
background.y = -10
164+
165+
tooltip.visible = false
166+
tooltip.inside = {}
167+
168+
tooltip.addChild(background)
169+
tooltip.addChild(label)
170+
171+
tooltip.interactiveChildren = false
172+
return tooltip
173+
};
174+
}

0 commit comments

Comments
 (0)