diff --git a/src/main/java/noppes/npcs/client/gui/global/GuiDiagram.java b/src/main/java/noppes/npcs/client/gui/global/GuiDiagram.java
index 2c0ee2fac..404e3628d 100644
--- a/src/main/java/noppes/npcs/client/gui/global/GuiDiagram.java
+++ b/src/main/java/noppes/npcs/client/gui/global/GuiDiagram.java
@@ -14,56 +14,63 @@ import org.lwjgl.opengl.GL11;
/**
* Abstract GUI class for drawing diagrams with icons (nodes) and connections (arrows).
*
- * Features:
- * - Uses a parent GuiNPCInterface to disable mouse interaction when a subgui is active.
- * - Caches icons and connections (subclasses must implement createIcons() and createConnections()).
- * - DiagramIcon now has an index (for ring, row, or level) and a priority (for ordering).
- * - New manual layout types (CIRCULAR_MANUAL, SQUARE_MANUAL, TREE_MANUAL) use index and priority
- * to order nodes.
- * - Arrow-drawing options: curvedArrows (if false, straight lines) and curveAngle (in degrees).
- * - For curved arrows, hit-detection is done by approximating the quadratic Bezier with 20 segments.
+ * Features include:
+ *
+ * - Parent reference to disable mouse interaction when a subGUI is active.
+ * - Caching for icons and connections (subclasses must implement createIcons() and createConnections()).
+ * - Support for different layout types (circular, square, tree, generated, and manual versions)
+ * plus a CHART layout.
+ * - Drawing of connections as either straight or curved arrows (with hit‐detection improved for curves).
+ * - Chart layout: a grid with header icons and inner cells that show connection colors.
+ * When hovering over a header or cell, only the corresponding row/column (or cell and its two icons) are highlighted
+ * while all non‑relevant cells are dimmed. Also, cells with no connection are drawn with a darker gray.
+ *
+ * - Zooming and panning controls apply to both chart and non‑chart layouts.
+ * - Callbacks for icon and connection interactions including click, held, release and hover events.
+ *
*/
public abstract class GuiDiagram extends Gui {
- // Diagram Area & Controls
- protected int x, y, width, height;
- protected float panX = 0, panY = 0;
- protected float zoom = 1.0f;
- protected boolean dragging = false;
- protected int lastDragX, lastDragY;
+ // --- Diagram Area & Controls ---
+ protected int x, y, width, height; // Drawing area for the diagram
+ protected float panX = 0, panY = 0; // Panning offsets
+ protected float zoom = 1.0f; // Zoom factor
+ protected boolean dragging = false; // Flag indicating active panning
+ protected int lastDragX, lastDragY; // Last mouse positions used for panning
- // Node (Icon) Sizing
- protected int iconSize = 16;
- protected int slotPadding = 4;
- protected int slotSize = iconSize + slotPadding;
+ // --- Node (Icon) Sizing ---
+ protected int iconSize = 16; // Icon image size (square)
+ protected int slotPadding = 4; // Padding around icons
+ protected int slotSize = iconSize + slotPadding; // Total size of the icon box
- // Node Box Appearance
- protected int iconBackgroundColor = 0xFF999999;
- protected int iconBorderColor = 0xFF555555;
- protected int iconBorderThickness = 1;
+ // --- Icon Box Appearance ---
+ protected int iconBackgroundColor = 0xFF999999; // Background color for icon boxes
+ protected int iconBorderColor = 0xFF555555; // Border color for icon boxes
+ protected int iconBorderThickness = 1; // Border thickness in pixels
- // Connection Options
- protected boolean showArrowHeads = true;
- protected boolean useColorScaling = true;
+ // --- Connection Options ---
+ protected boolean showArrowHeads = true; // Whether to draw arrow heads
+ protected boolean useColorScaling = true; // Scale connection color based on a percentage
- // Layout Options
+ // --- Layout Options ---
public enum DiagramLayout {
CIRCULAR, SQUARE, TREE, GENERATED,
- CIRCULAR_MANUAL, SQUARE_MANUAL, TREE_MANUAL
+ CIRCULAR_MANUAL, SQUARE_MANUAL, TREE_MANUAL,
+ CHART
}
- protected DiagramLayout layout = DiagramLayout.CIRCULAR;
+ protected DiagramLayout layout = DiagramLayout.CIRCULAR; // Default layout
/**
- * Sets the layout and invalidates caches.
+ * Sets the layout type and invalidates caches.
*/
public void setLayout(DiagramLayout layout) {
this.layout = layout;
invalidateCache();
}
- // Arrow Drawing Options
- protected boolean curvedArrows = true; // if false, straight lines are drawn.
- protected int curveAngle = 15; // in degrees; adjust for "hardness" of curve.
+ // --- Arrow Drawing Options ---
+ protected boolean curvedArrows = true; // If false, draw straight connection lines
+ protected int curveAngle = 15; // Curvature angle in degrees
public void setCurvedArrows(boolean curved) {
this.curvedArrows = curved;
@@ -72,13 +79,13 @@ public abstract class GuiDiagram extends Gui {
this.curveAngle = angle;
}
- // Caching for positions and for icons/connections.
- protected Map cachedPositions = null;
- protected List iconsCache = null;
- protected List connectionsCache = null;
+ // --- Caching for icons and connections ---
+ protected Map cachedPositions = null; // Cached positions for nodes (non-CHART)
+ protected List iconsCache = null; // Cached list of icons
+ protected List connectionsCache = null; // Cached list of connections
/**
- * Clears all caches.
+ * Clears cached layout information.
*/
public void invalidateCache() {
cachedPositions = null;
@@ -86,10 +93,10 @@ public abstract class GuiDiagram extends Gui {
connectionsCache = null;
}
- // Parent Reference
+ // --- Parent reference ---
protected GuiNPCInterface parent;
- // Constructor
+ // --- Constructor ---
public GuiDiagram(GuiNPCInterface parent, int x, int y, int width, int height) {
this.parent = parent;
this.x = x;
@@ -98,7 +105,7 @@ public abstract class GuiDiagram extends Gui {
this.height = height;
}
- // Data Providers – Subclasses must implement these.
+ // --- Data Providers (Subclasses must implement these) ---
protected abstract List createIcons();
protected abstract List createConnections();
@@ -120,7 +127,14 @@ public abstract class GuiDiagram extends Gui {
*/
protected abstract void renderIcon(DiagramIcon icon, int posX, int posY, IconRenderState state);
+ /**
+ * Returns the tooltip text lines for an icon.
+ */
protected List getIconTooltip(DiagramIcon icon) { return null; }
+
+ /**
+ * Returns the tooltip text lines for a connection.
+ */
protected List getConnectionTooltip(DiagramConnection conn) {
List tooltip = new ArrayList<>();
DiagramIcon iconFrom = getIconById(conn.idFrom);
@@ -138,33 +152,41 @@ public abstract class GuiDiagram extends Gui {
}
protected String getIconName(DiagramIcon icon) { return "Icon " + icon.id; }
- // Layout Calculation – Chooses algorithm based on layout type.
+ // --- Layout Calculation ---
+ /**
+ * For non‑CHART layouts, returns the mapping from node ID to (x,y) position.
+ * CHART layout is drawn directly.
+ */
protected Map calculatePositions() {
if (cachedPositions != null) return cachedPositions;
+ if (layout == DiagramLayout.CHART) {
+ return new HashMap<>();
+ }
switch (layout) {
- case CIRCULAR: cachedPositions = calculateCircularPositions(); break;
- case SQUARE: cachedPositions = calculateSquarePositions(); break;
- case TREE: cachedPositions = calculateTreePositions(); break;
- case GENERATED: cachedPositions = calculateGeneratedPositions(); break;
- case CIRCULAR_MANUAL: cachedPositions = calculateCircularManualPositions(); break;
- case SQUARE_MANUAL: cachedPositions = calculateSquareManualPositions(); break;
- case TREE_MANUAL: cachedPositions = calculateTreeManualPositions(); break;
- default: cachedPositions = calculateCircularPositions(); break;
+ case CIRCULAR: cachedPositions = calculateCircularPositions(); break;
+ case SQUARE: cachedPositions = calculateSquarePositions(); break;
+ case TREE: cachedPositions = calculateTreePositions(); break;
+ case GENERATED: cachedPositions = calculateGeneratedPositions(); break;
+ case CIRCULAR_MANUAL: cachedPositions = calculateCircularManualPositions(); break;
+ case SQUARE_MANUAL: cachedPositions = calculateSquareManualPositions(); break;
+ case TREE_MANUAL: cachedPositions = calculateTreeManualPositions(); break;
+ default: cachedPositions = calculateCircularPositions(); break;
}
return cachedPositions;
}
- // Standard Layouts:
+ // --- Standard Layout Methods ---
+
protected Map calculateCircularPositions() {
List icons = getIcons();
Map positions = new HashMap<>();
int count = icons.size();
- int centerX = x + width / 2, centerY = y + height / 2;
- int radius = Math.min(width, height) / 2 - iconSize - 10;
+ int centerX = x + width/2, centerY = y + height/2;
+ int radius = Math.min(width, height)/2 - iconSize - 10;
for (int i = 0; i < count; i++) {
double angle = 2 * Math.PI * i / count;
- int posX = centerX + (int) (radius * Math.cos(angle));
- int posY = centerY + (int) (radius * Math.sin(angle));
+ int posX = centerX + (int)(radius * Math.cos(angle));
+ int posY = centerY + (int)(radius * Math.sin(angle));
positions.put(icons.get(i).id, new Point(posX, posY));
}
return positions;
@@ -174,14 +196,14 @@ public abstract class GuiDiagram extends Gui {
List icons = getIcons();
Map positions = new HashMap<>();
int count = icons.size();
- int n = (int) Math.ceil(Math.sqrt(count));
+ int n = (int)Math.ceil(Math.sqrt(count));
int gridWidth = width - 20, gridHeight = height - 20;
int cellWidth = gridWidth / n, cellHeight = gridHeight / n;
- int startX = x + (width - gridWidth) / 2, startY = y + (height - gridHeight) / 2;
+ int startX = x + (width - gridWidth)/2, startY = y + (height - gridHeight)/2;
for (int i = 0; i < count; i++) {
int row = i / n, col = i % n;
- int posX = startX + col * cellWidth + cellWidth / 2;
- int posY = startY + row * cellHeight + cellHeight / 2;
+ int posX = startX + col * cellWidth + cellWidth/2;
+ int posY = startY + row * cellHeight + cellHeight/2;
positions.put(icons.get(i).id, new Point(posX, posY));
}
return positions;
@@ -191,15 +213,15 @@ public abstract class GuiDiagram extends Gui {
List icons = getIcons();
Map positions = new HashMap<>();
int count = icons.size();
- int levels = (int) Math.ceil(Math.log(count + 1) / Math.log(2));
+ int levels = (int)Math.ceil(Math.log(count + 1) / Math.log(2));
int levelHeight = height / (levels + 1);
int index = 0;
for (int level = 0; level < levels && index < count; level++) {
- int nodesThisLevel = (int) Math.min(Math.pow(2, level), count - index);
+ int nodesThisLevel = (int)Math.min(Math.pow(2, level), count - index);
int levelWidth = width - 20;
int cellWidth = levelWidth / nodesThisLevel;
for (int i = 0; i < nodesThisLevel && index < count; i++, index++) {
- int posX = x + 10 + i * cellWidth + cellWidth / 2;
+ int posX = x + 10 + i * cellWidth + cellWidth/2;
int posY = y + (level + 1) * levelHeight;
positions.put(icons.get(index).id, new Point(posX, posY));
}
@@ -213,8 +235,8 @@ public abstract class GuiDiagram extends Gui {
Map> graph = buildGraph(icons, connections);
List> clusters = getConnectedComponents(graph);
int clusterCount = clusters.size();
- int gridCols = (int) Math.ceil(Math.sqrt(clusterCount));
- int gridRows = (int) Math.ceil((double) clusterCount / gridCols);
+ int gridCols = (int)Math.ceil(Math.sqrt(clusterCount));
+ int gridRows = (int)Math.ceil((double)clusterCount / gridCols);
int clusterMargin = 20;
int compWidth = (width - (gridCols + 1) * clusterMargin) / gridCols;
int compHeight = (height - (gridRows + 1) * clusterMargin) / gridRows;
@@ -240,7 +262,7 @@ public abstract class GuiDiagram extends Gui {
return globalPositions;
}
- // Helpers for generated layout.
+ // --- Helpers for Generated Layout ---
private Map> buildGraph(List icons, List connections) {
Map> graph = new HashMap<>();
for (DiagramIcon icon : icons) {
@@ -270,9 +292,8 @@ public abstract class GuiDiagram extends Gui {
visited.add(current);
comp.add(current);
for (Integer neighbor : graph.get(current)) {
- if (!visited.contains(neighbor)) {
+ if (!visited.contains(neighbor))
dfsComponent(neighbor, graph, visited, comp);
- }
}
}
private boolean isCycle(Set cluster, Map> graph) {
@@ -298,11 +319,11 @@ public abstract class GuiDiagram extends Gui {
}
private boolean isSquare(Set cluster) {
int n = cluster.size();
- int sqrt = (int) Math.round(Math.sqrt(n));
+ int sqrt = (int)Math.round(Math.sqrt(n));
return sqrt * sqrt == n;
}
- // Layout algorithms for clusters:
+ // --- Layout Algorithms for Clusters ---
private Map layoutCycle(Set cluster, int compX, int compY, int compWidth, int compHeight) {
Map positions = new HashMap<>();
int centerX = compX + compWidth / 2, centerY = compY + compHeight / 2;
@@ -310,8 +331,8 @@ public abstract class GuiDiagram extends Gui {
int i = 0;
for (Integer id : cluster) {
double angle = 2 * Math.PI * i / cluster.size();
- int posX = centerX + (int) (radius * Math.cos(angle));
- int posY = centerY + (int) (radius * Math.sin(angle));
+ int posX = centerX + (int)(radius * Math.cos(angle));
+ int posY = centerY + (int)(radius * Math.sin(angle));
positions.put(id, new Point(posX, posY));
i++;
}
@@ -362,8 +383,8 @@ public abstract class GuiDiagram extends Gui {
double spacing = compWidth / (nodesAtLevel.size() + 1.0);
for (int i = 0; i < nodesAtLevel.size(); i++) {
int id = nodesAtLevel.get(i);
- int posX = compX + (int) ((i + 1) * spacing);
- int posY = compY + (int) (lvl * levelHeight + levelHeight / 2);
+ int posX = compX + (int)((i + 1) * spacing);
+ int posY = compY + (int)(lvl * levelHeight + levelHeight / 2);
positions.put(id, new Point(posX, posY));
}
}
@@ -372,7 +393,7 @@ public abstract class GuiDiagram extends Gui {
private Map layoutSquare(Set cluster, int compX, int compY, int compWidth, int compHeight) {
Map positions = new HashMap<>();
- int n = (int) Math.round(Math.sqrt(cluster.size()));
+ int n = (int)Math.round(Math.sqrt(cluster.size()));
int gridCellWidth = compWidth / n, gridCellHeight = compHeight / n;
int index = 0;
List nodes = new ArrayList<>(cluster);
@@ -463,7 +484,8 @@ public abstract class GuiDiagram extends Gui {
return positions;
}
- // Manual Layouts – using index (ring) and priority.
+ // --- Manual Layouts ---
+ // Manual layouts use the icon index (e.g. ring number, row, level) and the priority for ordering.
private Map calculateCircularManualPositions() {
List icons = getIcons();
Map> groups = new TreeMap<>();
@@ -471,22 +493,21 @@ public abstract class GuiDiagram extends Gui {
groups.computeIfAbsent(icon.index, k -> new ArrayList<>()).add(icon);
}
Map positions = new HashMap<>();
- int centerX = x + width / 2, centerY = y + height / 2;
+ int centerX = x + width/2, centerY = y + height/2;
int maxRing = groups.isEmpty() ? 0 : Collections.max(groups.keySet());
- int maxRadius = Math.min(width, height) / 2 - iconSize - 10;
- double ringSpacing = (maxRing + 1) > 0 ? (double) maxRadius / (maxRing + 1) : 0;
- // For each ring, sort by priority. For ring 0, start at -90° (top); for higher rings, start at -135°.
+ int maxRadius = Math.min(width, height)/2 - iconSize - 10;
+ double ringSpacing = (maxRing + 1) > 0 ? (double)maxRadius/(maxRing + 1) : 0;
for (Map.Entry> entry : groups.entrySet()) {
int ring = entry.getKey();
List groupIcons = entry.getValue();
groupIcons.sort(Comparator.comparingInt(icon -> icon.priority));
double radius = ringSpacing * (ring + 1);
int count = groupIcons.size();
- double startAngle = (ring == 0) ? -Math.PI / 2 : -3 * Math.PI / 4;
+ double startAngle = (ring == 0) ? -Math.PI/2 : -3 * Math.PI/4;
for (int i = 0; i < count; i++) {
double angle = startAngle + 2 * Math.PI * i / count;
- int posX = centerX + (int) (radius * Math.cos(angle));
- int posY = centerY + (int) (radius * Math.sin(angle));
+ int posX = centerX + (int)(radius * Math.cos(angle));
+ int posY = centerY + (int)(radius * Math.sin(angle));
positions.put(groupIcons.get(i).id, new Point(posX, posY));
}
}
@@ -500,11 +521,10 @@ public abstract class GuiDiagram extends Gui {
groups.computeIfAbsent(icon.index, k -> new ArrayList<>()).add(icon);
}
Map positions = new HashMap<>();
- int centerX = x + width / 2, centerY = y + height / 2;
+ int centerX = x + width/2, centerY = y + height/2;
int maxRing = groups.isEmpty() ? 0 : Collections.max(groups.keySet());
- int halfSide = Math.min(width, height) / 2 - iconSize - 10;
- double ringSpacing = (maxRing + 1) > 0 ? (double) halfSide / (maxRing + 1) : 0;
- // Distribute each ring's icons along the square perimeter.
+ int halfSide = Math.min(width, height)/2 - iconSize - 10;
+ double ringSpacing = (maxRing + 1) > 0 ? (double)halfSide/(maxRing + 1) : 0;
for (Map.Entry> entry : groups.entrySet()) {
int ring = entry.getKey();
List groupIcons = entry.getValue();
@@ -516,17 +536,17 @@ public abstract class GuiDiagram extends Gui {
double posAlong = (perimeter * i) / count;
int posX, posY;
if (posAlong < 2 * offset) {
- posX = centerX - (int) offset + (int) posAlong;
- posY = centerY - (int) offset;
+ posX = centerX - (int)offset + (int)posAlong;
+ posY = centerY - (int)offset;
} else if (posAlong < 4 * offset) {
- posX = centerX + (int) offset;
- posY = centerY - (int) offset + (int) (posAlong - 2 * offset);
+ posX = centerX + (int)offset;
+ posY = centerY - (int)offset + (int)(posAlong - 2 * offset);
} else if (posAlong < 6 * offset) {
- posX = centerX + (int) offset - (int) (posAlong - 4 * offset);
- posY = centerY + (int) offset;
+ posX = centerX + (int)offset - (int)(posAlong - 4 * offset);
+ posY = centerY + (int)offset;
} else {
- posX = centerX - (int) offset;
- posY = centerY + (int) offset - (int) (posAlong - 6 * offset);
+ posX = centerX - (int)offset;
+ posY = centerY + (int)offset - (int)(posAlong - 6 * offset);
}
positions.put(groupIcons.get(i).id, new Point(posX, posY));
}
@@ -558,11 +578,10 @@ public abstract class GuiDiagram extends Gui {
return positions;
}
- // Arrow Drawing:
+ // --- Arrow Drawing Methods ---
/**
- * Draws a connection line.
- * If curvedArrows is false, draws a straight line.
- * Otherwise draws a quadratic Bezier curve using curveAngle for offset.
+ * Draws a connection line between two points.
+ * If curvedArrows is enabled, draws a quadratic Bezier curve.
*/
protected void drawConnectionLine(int x1, int y1, int x2, int y2, DiagramConnection conn, boolean dim) {
int color = getConnectionColor(conn);
@@ -593,7 +612,7 @@ public abstract class GuiDiagram extends Gui {
double perpX = -dy / len, perpY = dx / len;
Point control = new Point((x1 + x2) / 2 + (int)(perpX * offset),
(y1 + y2) / 2 + (int)(perpY * offset));
- int segments = 300;
+ int segments = 100;
GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glLineWidth(2.0F);
@@ -616,8 +635,7 @@ public abstract class GuiDiagram extends Gui {
}
/**
- * Draws the arrow head.
- * For curved arrows, the head is aligned with the derivative at t=0.95.
+ * Draws the arrow head at the end of a connection.
*/
protected void drawArrowHead(int x1, int y1, int x2, int y2, DiagramConnection conn, boolean dim) {
int color = getConnectionColor(conn);
@@ -643,16 +661,16 @@ public abstract class GuiDiagram extends Gui {
float defenderEdgeX = x2 - (slotSize / 2f) * (float)Math.cos(angle);
float defenderEdgeY = y2 - (slotSize / 2f) * (float)Math.sin(angle);
int arrowSize = 6;
- float leftX = (float)(defenderEdgeX - arrowSize * Math.cos(angle - Math.PI/6));
- float leftY = (float)(defenderEdgeY - arrowSize * Math.sin(angle - Math.PI/6));
- float rightX = (float)(defenderEdgeX - arrowSize * Math.cos(angle + Math.PI/6));
- float rightY = (float)(defenderEdgeY - arrowSize * Math.sin(angle + Math.PI/6));
+ float leftX = defenderEdgeX - arrowSize * (float)Math.cos(angle - Math.PI / 6);
+ float leftY = defenderEdgeY - arrowSize * (float)Math.sin(angle - Math.PI / 6);
+ float rightX = defenderEdgeX - arrowSize * (float)Math.cos(angle + Math.PI / 6);
+ float rightY = defenderEdgeY - arrowSize * (float)Math.sin(angle + Math.PI / 6);
GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
GL11.glDisable(GL11.GL_TEXTURE_2D);
- float rr = ((color >> 16)&0xFF)/255f;
- float gg = ((color >> 8)&0xFF)/255f;
- float bb = (color&0xFF)/255f;
- if(dim){ rr*=0.4f; gg*=0.4f; bb*=0.4f; }
+ float rr = ((color >> 16) & 0xFF) / 255f;
+ float gg = ((color >> 8) & 0xFF) / 255f;
+ float bb = (color & 0xFF) / 255f;
+ if(dim){ rr *= 0.4f; gg *= 0.4f; bb *= 0.4f; }
GL11.glColor4f(rr, gg, bb, 1f);
GL11.glDisable(GL11.GL_CULL_FACE);
GL11.glBegin(GL11.GL_TRIANGLES);
@@ -665,7 +683,7 @@ public abstract class GuiDiagram extends Gui {
GL11.glPopAttrib();
}
- // Standard Icon Box Drawing
+ // --- Standard Icon Box Drawing ---
protected void drawIconBox(int slotX, int slotY, int slotSize, boolean highlighted) {
int bg = highlighted ? mixColors(iconBackgroundColor, 0xFFFFFFFF, 0.2f) : iconBackgroundColor;
drawRect(slotX, slotY, slotX + slotSize, slotY + slotSize, bg);
@@ -686,7 +704,7 @@ public abstract class GuiDiagram extends Gui {
return (a << 24) | (r << 16) | (g << 8) | b;
}
- // Hit-detection helper for curved arrows.
+ // --- Hit-detection helpers ---
private double distanceToBezier(Point start, Point control, Point end, int segments, int px, int py) {
double minDist = Double.MAX_VALUE;
Point prev = null;
@@ -697,7 +715,7 @@ public abstract class GuiDiagram extends Gui {
Point curr = new Point(x, y);
if (prev != null) {
double d = distancePointToSegment(px, py, prev, curr);
- if (d < minDist) minDist = d;
+ if(d < minDist) minDist = d;
}
prev = curr;
}
@@ -710,18 +728,245 @@ public abstract class GuiDiagram extends Gui {
double lenSq = C * C + D * D;
double param = (lenSq != 0) ? (dot / lenSq) : -1;
double xx, yy;
- if (param < 0) { xx = a.x; yy = a.y; }
- else if (param > 1) { xx = b.x; yy = b.y; }
+ if(param < 0){ xx = a.x; yy = a.y; }
+ else if(param > 1){ xx = b.x; yy = b.y; }
else { xx = a.x + param * C; yy = a.y + param * D; }
double dx = px - xx, dy = py - yy;
return Math.sqrt(dx * dx + dy * dy);
}
- // Main Draw Method
+ // --- CHART Layout Drawing ---
+ /**
+ * Draws the CHART layout.
+ *
+ * - The grid has (n+1) columns and rows, where n is the number of icons.
+ * - The top row and left column show header icons.
+ * - Each inner cell is filled with the connection color (if one exists) or a darker gray otherwise.
+ * - Hovering over a header or inner cell highlights the corresponding column/row or cell (and its two header icons),
+ * while dimming non-relevant cells.
+ * - Zoom and pan are applied to the entire chart.
+ *
+ */
+ private void drawChartDiagram(int mouseX, int mouseY, boolean subGui) {
+ Minecraft mc = Minecraft.getMinecraft();
+ ScaledResolution sr = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight);
+ int factor = sr.getScaleFactor();
+
+ // 1. Draw the static background for the entire diagram.
+ drawRect(x, y, x + width, y + height, 0xFF333333);
+
+ // 2. Setup scissor to clip drawing to the diagram area.
+ GL11.glEnable(GL11.GL_SCISSOR_TEST);
+ GL11.glScissor(x * factor, (sr.getScaledHeight() - (y + height)) * factor, width * factor, height * factor);
+
+ // 3. Push a matrix and apply pan/zoom for grid, icons, and overlays.
+ GL11.glPushMatrix();
+ int centerX = x + width / 2;
+ int centerY = y + height / 2;
+ GL11.glTranslatef(centerX + panX, centerY + panY, 0);
+ GL11.glScalef(zoom, zoom, 1.0f);
+ GL11.glTranslatef(-centerX, -centerY, 0);
+
+ // 4. Compute grid parameters.
+ List icons = getIcons();
+ int n = icons.size();
+ int cols = n + 1, rows = n + 1;
+ int cellSize = Math.min(width / cols, height / rows);
+ int gridWidth = cellSize * cols;
+ int gridHeight = cellSize * rows;
+ int startX = x + (width - gridWidth) / 2;
+ int startY = y + (height - gridHeight) / 2;
+
+ // 5. Draw grid cells.
+ for (int row = 0; row < rows; row++) {
+ for (int col = 0; col < cols; col++) {
+ int cellX = startX + col * cellSize;
+ int cellY = startY + row * cellSize;
+ int fillColor = 0xFFCCCCCC; // Default for header cells.
+ if (row > 0 && col > 0) { // inner cell: use connection color (or darker gray)
+ DiagramIcon leftIcon = icons.get(row - 1);
+ DiagramIcon topIcon = icons.get(col - 1);
+ DiagramConnection conn = getConnectionByIds(leftIcon.id, topIcon.id);
+ fillColor = (conn != null) ? getConnectionColor(conn) : 0xFF777777;
+ }
+ drawRect(cellX, cellY, cellX + cellSize, cellY + cellSize, fillColor);
+ }
+ }
+
+ // 6. Draw grid lines.
+ GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
+ GL11.glDisable(GL11.GL_TEXTURE_2D);
+ GL11.glColor4f(0, 0, 0, 1);
+ GL11.glLineWidth(1.0f);
+ GL11.glBegin(GL11.GL_LINES);
+ for (int col = 0; col <= cols; col++) {
+ int xLine = startX + col * cellSize;
+ GL11.glVertex2i(xLine, startY);
+ GL11.glVertex2i(xLine, startY + gridHeight);
+ }
+ for (int row = 0; row <= rows; row++) {
+ int yLine = startY + row * cellSize;
+ GL11.glVertex2i(startX, yLine);
+ GL11.glVertex2i(startX + gridWidth, yLine);
+ }
+ GL11.glEnd();
+ GL11.glEnable(GL11.GL_TEXTURE_2D);
+ GL11.glPopAttrib();
+
+ // 7. Draw header icons (top and left) scaled to fit within each cell.
+ float iconMargin = 1f; // margin in pixels inside the cell.
+ float iconScale = (cellSize - iconMargin) / (float)iconSize;
+ for (int i = 0; i < n; i++) {
+ // Top header icon:
+ int topHeaderCenterX = startX + (i + 1) * cellSize + cellSize / 2;
+ int topHeaderCenterY = startY + cellSize / 2;
+ GL11.glPushMatrix();
+ GL11.glTranslatef(topHeaderCenterX, topHeaderCenterY, 0);
+ GL11.glScalef(iconScale, iconScale, 1);
+ // renderIcon should draw centered at (0,0)
+ renderIcon(icons.get(i), 0, 0, IconRenderState.DEFAULT);
+ GL11.glPopMatrix();
+
+ // Left header icon:
+ int leftHeaderCenterX = startX + cellSize / 2;
+ int leftHeaderCenterY = startY + (i + 1) * cellSize + cellSize / 2;
+ GL11.glPushMatrix();
+ GL11.glTranslatef(leftHeaderCenterX, leftHeaderCenterY, 0);
+ GL11.glScalef(iconScale, iconScale, 1);
+ renderIcon(icons.get(i), 0, 0, IconRenderState.DEFAULT);
+ GL11.glPopMatrix();
+ }
+
+ // 8. Compute effective mouse coordinates (reverse pan/zoom).
+ int effectiveMouseX = (int)(((float)mouseX - (centerX + panX)) / zoom + centerX);
+ int effectiveMouseY = (int)(((float)mouseY - (centerY + panY)) / zoom + centerY);
+
+ // 9. Determine hover state on the grid.
+ boolean hoverInGrid = (effectiveMouseX >= startX && effectiveMouseX < startX + gridWidth &&
+ effectiveMouseY >= startY && effectiveMouseY < startY + gridHeight);
+ int hoveredRow = -1, hoveredCol = -1;
+ Set highlightTop = new HashSet<>();
+ Set highlightLeft = new HashSet<>();
+ List tooltipToShow = null;
+ if (hoverInGrid) {
+ int colIndex = (effectiveMouseX - startX) / cellSize;
+ int rowIndex = (effectiveMouseY - startY) / cellSize;
+ // If hovering over a top header cell.
+ if (rowIndex == 0 && colIndex >= 1) {
+ highlightTop.add(colIndex - 1);
+ tooltipToShow = getIconTooltip(icons.get(colIndex - 1));
+ onIconHover(icons.get(colIndex - 1));
+ }
+ // If hovering over a left header cell.
+ else if (colIndex == 0 && rowIndex >= 1) {
+ highlightLeft.add(rowIndex - 1);
+ tooltipToShow = getIconTooltip(icons.get(rowIndex - 1));
+ onIconHover(icons.get(rowIndex - 1));
+ }
+ // Else, hovering over an inner cell.
+ else if (rowIndex >= 1 && colIndex >= 1) {
+ hoveredRow = rowIndex - 1;
+ hoveredCol = colIndex - 1;
+ highlightTop.add(hoveredCol);
+ highlightLeft.add(hoveredRow);
+ DiagramIcon leftIcon = icons.get(hoveredRow);
+ DiagramIcon topIcon = icons.get(hoveredCol);
+ DiagramConnection conn = getConnectionByIds(leftIcon.id, topIcon.id);
+ if (conn != null) {
+ tooltipToShow = getConnectionTooltip(conn);
+ onConnectionHover(conn);
+ }
+ }
+ }
+
+ // 10. Draw hover overlay:
+ // Dim all inner cells (row>=1 & col>=1) not in highlighted row/column.
+ GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
+ GL11.glDisable(GL11.GL_TEXTURE_2D);
+ GL11.glColor4f(0, 0, 0, 0.5f);
+ GL11.glBegin(GL11.GL_QUADS);
+ for (int r = 1; r < rows; r++) {
+ for (int c = 1; c < cols; c++) {
+ boolean keepBright = false;
+ if (!highlightTop.isEmpty() && highlightTop.contains(c - 1))
+ keepBright = true;
+ if (!highlightLeft.isEmpty() && highlightLeft.contains(r - 1))
+ keepBright = true;
+ // Also, if a specific cell is hovered, its entire row/column is bright.
+ if (hoveredRow != -1 && hoveredCol != -1) {
+ if (r - 1 == hoveredRow || c - 1 == hoveredCol)
+ keepBright = true;
+ }
+ if (!keepBright) {
+ int cellX = startX + c * cellSize;
+ int cellY = startY + r * cellSize;
+ GL11.glVertex2i(cellX, cellY);
+ GL11.glVertex2i(cellX + cellSize, cellY);
+ GL11.glVertex2i(cellX + cellSize, cellY + cellSize);
+ GL11.glVertex2i(cellX, cellY + cellSize);
+ }
+ }
+ }
+ GL11.glEnd();
+ // Then draw a white overlay on the highlighted headers/inner cell.
+ GL11.glColor4f(1, 1, 1, 0.3f);
+ GL11.glBegin(GL11.GL_QUADS);
+ for (int i = 0; i < n; i++) {
+ if (highlightTop.contains(i)) {
+ int hx = startX + (i + 1) * cellSize;
+ int hy = startY;
+ GL11.glVertex2i(hx, hy);
+ GL11.glVertex2i(hx + cellSize, hy);
+ GL11.glVertex2i(hx + cellSize, hy + cellSize);
+ GL11.glVertex2i(hx, hy + cellSize);
+ }
+ if (highlightLeft.contains(i)) {
+ int hx = startX;
+ int hy = startY + (i + 1) * cellSize;
+ GL11.glVertex2i(hx, hy);
+ GL11.glVertex2i(hx + cellSize, hy);
+ GL11.glVertex2i(hx + cellSize, hy + cellSize);
+ GL11.glVertex2i(hx, hy + cellSize);
+ }
+ }
+ if (hoveredRow != -1 && hoveredCol != -1) {
+ int cellX = startX + (hoveredCol + 1) * cellSize;
+ int cellY = startY + (hoveredRow + 1) * cellSize;
+ GL11.glVertex2i(cellX, cellY);
+ GL11.glVertex2i(cellX + cellSize, cellY);
+ GL11.glVertex2i(cellX + cellSize, cellY + cellSize);
+ GL11.glVertex2i(cellX, cellY + cellSize);
+ }
+ GL11.glEnd();
+ GL11.glEnable(GL11.GL_TEXTURE_2D);
+ GL11.glPopAttrib();
+
+ // End pan/zoom block.
+ GL11.glPopMatrix();
+ GL11.glDisable(GL11.GL_SCISSOR_TEST);
+
+ // 11. Draw tooltip (using raw screen coordinates).
+ if (tooltipToShow != null && !tooltipToShow.isEmpty()) {
+ drawHoveringText(tooltipToShow, mouseX, mouseY, mc.fontRenderer);
+ }
+ }
+
+
+
+ /**
+ * Main method for drawing the diagram.
+ * If layout == CHART, delegates to drawChartDiagram().
+ * Otherwise, applies pan/zoom, draws connections (with hit-detection fixed for curves)
+ * and icons, and shows tooltips and hover events.
+ */
public void drawDiagram(int mouseX, int mouseY, boolean subGui) {
boolean allowInput = (parent == null || !parent.hasSubGui());
if (allowInput && isWithin(mouseX, mouseY) && !subGui)
handleMouseScroll(Mouse.getDWheel());
+ if (layout == DiagramLayout.CHART) {
+ drawChartDiagram(mouseX, mouseY, subGui);
+ return;
+ }
Minecraft mc = Minecraft.getMinecraft();
ScaledResolution sr = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight);
int factor = sr.getScaleFactor();
@@ -732,6 +977,7 @@ public abstract class GuiDiagram extends Gui {
Integer hoveredIconId = null;
int hoveredConnFrom = -1, hoveredConnTo = -1;
Set selectedIconIds = new HashSet<>();
+ // Check if mouse is over an icon.
for (DiagramIcon icon : getIcons()) {
if (!icon.enabled) continue;
Point pos = positions.get(icon.id);
@@ -741,21 +987,12 @@ public abstract class GuiDiagram extends Gui {
effectiveMouseY >= slotY && effectiveMouseY < slotY + slotSize) {
hoveredIconId = icon.id;
selectedIconIds.add(icon.id);
+ onIconHover(icon);
break;
}
}
- if (hoveredIconId != null) {
- for (DiagramConnection conn : getConnections()) {
- DiagramIcon iconFrom = getIconById(conn.idFrom);
- DiagramIcon iconTo = getIconById(conn.idTo);
- if (iconFrom == null || iconTo == null || !iconFrom.enabled || !iconTo.enabled)
- continue;
- if (conn.idFrom == hoveredIconId || conn.idTo == hoveredIconId) {
- selectedIconIds.add(conn.idFrom);
- selectedIconIds.add(conn.idTo);
- }
- }
- } else {
+ // If no icon was hovered, check connections.
+ if (hoveredIconId == null) {
final double threshold = 5.0;
outer:
for (DiagramConnection conn : getConnections()) {
@@ -771,12 +1008,11 @@ public abstract class GuiDiagram extends Gui {
double dx = pTo.x - pFrom.x, dy = pTo.y - pFrom.y;
double len = Math.sqrt(dx * dx + dy * dy);
if (len == 0) len = 1;
- double angleRad = Math.toRadians(curveAngle);
- double offset = len * Math.tan(angleRad) / 2;
+ double offset = len * Math.tan(Math.toRadians(curveAngle)) / 2;
double perpX = -dy / len, perpY = dx / len;
- Point control = new Point((pFrom.x+pTo.x)/2 + (int)(perpX*offset),
- (pFrom.y+pTo.y)/2 + (int)(perpY*offset));
- dist = distanceToBezier(pFrom, control, pTo, 20, effectiveMouseX, effectiveMouseY);
+ Point control = new Point((pFrom.x + pTo.x) / 2 + (int)(perpX * offset),
+ (pFrom.y + pTo.y) / 2 + (int)(perpY * offset));
+ dist = distanceToBezier(pFrom, control, pTo, 200, effectiveMouseX, effectiveMouseY);
} else {
dist = pointLineDistance(effectiveMouseX, effectiveMouseY, pFrom.x, pFrom.y, pTo.x, pTo.y);
}
@@ -785,10 +1021,12 @@ public abstract class GuiDiagram extends Gui {
hoveredConnTo = conn.idTo;
selectedIconIds.add(conn.idFrom);
selectedIconIds.add(conn.idTo);
+ onConnectionHover(conn);
break outer;
}
}
}
+ // Setup scissor.
GL11.glEnable(GL11.GL_SCISSOR_TEST);
GL11.glScissor(x * factor, (sr.getScaledHeight() - (y + height)) * factor, width * factor, height * factor);
drawRect(x, y, x + width, y + height, 0xFF333333);
@@ -796,6 +1034,7 @@ public abstract class GuiDiagram extends Gui {
GL11.glTranslatef(centerX + panX, centerY + panY, 0);
GL11.glScalef(zoom, zoom, 1.0f);
GL11.glTranslatef(-centerX, -centerY, 0);
+ // Draw connections.
for (DiagramConnection conn : getConnections()) {
DiagramIcon iconFrom = getIconById(conn.idFrom);
DiagramIcon iconTo = getIconById(conn.idTo);
@@ -805,9 +1044,11 @@ public abstract class GuiDiagram extends Gui {
Point pTo = positions.get(conn.idTo);
if (pFrom == null || pTo == null) continue;
int ax = pFrom.x, ay = pFrom.y, bx = pTo.x, by = pTo.y;
- boolean dim = !selectedIconIds.isEmpty() && !(selectedIconIds.contains(conn.idFrom) && selectedIconIds.contains(conn.idTo));
+ boolean dim = !selectedIconIds.isEmpty() &&
+ !(selectedIconIds.contains(conn.idFrom) && selectedIconIds.contains(conn.idTo));
drawConnectionLine(ax, ay, bx, by, conn, dim);
}
+ // Draw icons.
for (DiagramIcon icon : getIcons()) {
if (!icon.enabled) continue;
Point pos = positions.get(icon.id);
@@ -819,6 +1060,7 @@ public abstract class GuiDiagram extends Gui {
renderIcon(icon, pos.x, pos.y, state);
}
GL11.glPopMatrix();
+ // Draw arrow heads.
if (showArrowHeads) {
GL11.glPushMatrix();
GL11.glTranslatef(centerX + panX, centerY + panY, 0);
@@ -833,12 +1075,14 @@ public abstract class GuiDiagram extends Gui {
Point pTo = positions.get(conn.idTo);
if (pFrom == null || pTo == null) continue;
int ax = pFrom.x, ay = pFrom.y, bx = pTo.x, by = pTo.y;
- boolean dim = !selectedIconIds.isEmpty() && !(selectedIconIds.contains(conn.idFrom) && selectedIconIds.contains(conn.idTo));
+ boolean dim = !selectedIconIds.isEmpty() &&
+ !(selectedIconIds.contains(conn.idFrom) && selectedIconIds.contains(conn.idTo));
drawArrowHead(ax, ay, bx, by, conn, dim);
}
GL11.glPopMatrix();
}
GL11.glDisable(GL11.GL_SCISSOR_TEST);
+ // Show tooltips if an icon or connection was hovered.
if (hoveredIconId != null) {
DiagramIcon icon = getIconById(hoveredIconId);
List tooltip = getIconTooltip(icon);
@@ -852,6 +1096,7 @@ public abstract class GuiDiagram extends Gui {
}
}
+ // --- Utility Methods ---
protected DiagramIcon getIconById(int id) {
for (DiagramIcon icon : getIcons()) {
if (icon.id == id) return icon;
@@ -893,86 +1138,7 @@ public abstract class GuiDiagram extends Gui {
return Math.sqrt(dx * dx + dy * dy);
}
- // Mouse Handling
- public boolean mouseClicked(int mouseX, int mouseY, int mouseButton) {
- if (parent != null && parent.hasSubGui()) return false;
- if (mouseButton == 0) {
- for (DiagramIcon icon : getIcons()) {
- if (!icon.enabled || !icon.pressable) continue;
- Point pos = calculatePositions().get(icon.id);
- if (pos == null) continue;
- int centerX = x + width/2, centerY = y + height/2;
- int effectiveX = (int)(((float)mouseX - (centerX+panX))/zoom+centerX);
- int effectiveY = (int)(((float)mouseY - (centerY+panY))/zoom+centerY);
- int slotX = pos.x - slotSize/2, slotY = pos.y - slotSize/2;
- if (effectiveX >= slotX && effectiveX < slotX+slotSize &&
- effectiveY >= slotY && effectiveY < slotY+slotSize) {
- onIconClick(icon);
- currentlyPressedIcon = icon;
- return true;
- }
- }
- if (isWithin(mouseX, mouseY)) {
- dragging = true;
- lastDragX = mouseX;
- lastDragY = mouseY;
- return true;
- }
- }
- return false;
- }
- protected DiagramIcon currentlyPressedIcon = null;
- public void mouseClickMove(int mouseX, int mouseY, int mouseButton, long timeSinceLastClick) {
- if (parent != null && parent.hasSubGui()) return;
- if (dragging) {
- int dx = mouseX - lastDragX, dy = mouseY - lastDragY;
- panX += dx/zoom*0.7f;
- panY += dy/zoom*0.7f;
- lastDragX = mouseX;
- lastDragY = mouseY;
- }
- if (currentlyPressedIcon != null) onIconHeld(currentlyPressedIcon);
- }
- public void mouseReleased(int mouseX, int mouseY, int state) {
- if (parent != null && parent.hasSubGui()) return;
- if (currentlyPressedIcon != null) {
- onIconRelease(currentlyPressedIcon);
- currentlyPressedIcon = null;
- }
- dragging = false;
- }
- public boolean isWithin(int mouseX, int mouseY) {
- if (parent.hasSubGui())
- return false;
- return mouseX >= x && mouseX <= x+width && mouseY >= y && mouseY <= y+height;
- }
- /**
- * Handles zoom based on mouse wheel scrolling.
- */
- public void handleMouseScroll(int scrollDelta) {
- zoom += scrollDelta * 0.0009f;
- if (zoom < 0.5f) zoom = 0.5f;
- if (zoom > 2.0f) zoom = 2.0f;
- }
- /**
- * Override to render tooltips.
- */
- protected void drawHoveringText(List text, int mouseX, int mouseY, FontRenderer fontRenderer) {
- // Default implementation is empty.
- }
- // Flag Setters
- public void setShowArrowHeads(boolean showArrowHeads) {
- this.showArrowHeads = showArrowHeads;
- }
- public void setUseColorScaling(boolean useColorScaling) {
- this.useColorScaling = useColorScaling;
- }
- public enum IconRenderState {
- DEFAULT,
- HIGHLIGHTED,
- NOT_HIGHLIGHTED;
- }
- // Inner Classes
+ // --- Inner Helper Classes ---
public static class DiagramIcon {
public int id;
public boolean enabled = true;
@@ -997,14 +1163,133 @@ public abstract class GuiDiagram extends Gui {
this.hoverText = hoverText;
}
}
- // Icon Event Callbacks
+ // Used by the CHART layout to represent an inner cell.
+ private static class ConnectionCell {
+ int x, y, size;
+ DiagramConnection conn;
+ ConnectionCell(int x, int y, int size, DiagramConnection conn) {
+ this.x = x; this.y = y; this.size = size; this.conn = conn;
+ }
+ }
+ // Simple helper class for rectangles.
+ private static class Rectangle {
+ int x, y, width, height;
+ Rectangle(int x, int y, int width, int height) {
+ this.x = x; this.y = y; this.width = width; this.height = height;
+ }
+ int centerX() { return x + width / 2; }
+ int centerY() { return y + height / 2; }
+ }
+
+ public enum IconRenderState {
+ DEFAULT,
+ HIGHLIGHTED,
+ NOT_HIGHLIGHTED;
+ }
+
+ // --- Mouse Handling ---
+ public boolean mouseClicked(int mouseX, int mouseY, int mouseButton) {
+ if (parent != null && parent.hasSubGui()) return false;
+ if (mouseButton == 0) {
+ for (DiagramIcon icon : getIcons()) {
+ if (!icon.enabled || !icon.pressable) continue;
+ Point pos = calculatePositions().get(icon.id);
+ if (pos == null) continue;
+ int centerX = x + width / 2, centerY = y + height / 2;
+ int effectiveX = (int)(((float)mouseX - (centerX + panX)) / zoom + centerX);
+ int effectiveY = (int)(((float)mouseY - (centerY + panY)) / zoom + centerY);
+ int slotX = pos.x - slotSize / 2, slotY = pos.y - slotSize / 2;
+ if (effectiveX >= slotX && effectiveX < slotX + slotSize &&
+ effectiveY >= slotY && effectiveY < slotY + slotSize) {
+ onIconClick(icon);
+ currentlyPressedIcon = icon;
+ return true;
+ }
+ }
+ if (isWithin(mouseX, mouseY)) {
+ dragging = true;
+ lastDragX = mouseX;
+ lastDragY = mouseY;
+ return true;
+ }
+ }
+ return false;
+ }
+ protected DiagramIcon currentlyPressedIcon = null;
+ public void mouseClickMove(int mouseX, int mouseY, int mouseButton, long timeSinceLastClick) {
+ if (parent != null && parent.hasSubGui()) return;
+ if (dragging) {
+ int dx = mouseX - lastDragX, dy = mouseY - lastDragY;
+ panX += dx / zoom * 0.7f;
+ panY += dy / zoom * 0.7f;
+ lastDragX = mouseX;
+ lastDragY = mouseY;
+ }
+ if (currentlyPressedIcon != null) onIconHeld(currentlyPressedIcon);
+ }
+ public void mouseReleased(int mouseX, int mouseY, int state) {
+ if (parent != null && parent.hasSubGui()) return;
+ if (currentlyPressedIcon != null) {
+ onIconRelease(currentlyPressedIcon);
+ currentlyPressedIcon = null;
+ }
+ dragging = false;
+ }
+ public boolean isWithin(int mouseX, int mouseY) {
+ if (parent.hasSubGui())
+ return false;
+ return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height;
+ }
+ /**
+ * Handles zooming based on mouse wheel scrolling.
+ */
+ public void handleMouseScroll(int scrollDelta) {
+ zoom += scrollDelta * 0.0009f;
+ if (zoom < 0.5f) zoom = 0.5f;
+ if (zoom > 2.0f) zoom = 2.0f;
+ }
+ /**
+ * Override to render tooltips.
+ */
+ protected void drawHoveringText(List text, int mouseX, int mouseY, FontRenderer fontRenderer) {}
+
+ // --- Flag Setters ---
+ public void setShowArrowHeads(boolean showArrowHeads) {
+ this.showArrowHeads = showArrowHeads;
+ }
+ public void setUseColorScaling(boolean useColorScaling) {
+ this.useColorScaling = useColorScaling;
+ }
+
+ // --- Icon and Connection Event Callbacks ---
+ /**
+ * Called when an icon is clicked.
+ */
protected void onIconClick(DiagramIcon icon) {
System.out.println("Icon " + icon.id + " clicked.");
}
+ /**
+ * Called when an icon is held.
+ */
protected void onIconHeld(DiagramIcon icon) {
System.out.println("Icon " + icon.id + " held.");
}
+ /**
+ * Called when an icon is released.
+ */
protected void onIconRelease(DiagramIcon icon) {
System.out.println("Icon " + icon.id + " released.");
}
+ /**
+ * Called when an icon is hovered over.
+ */
+ protected void onIconHover(DiagramIcon icon) {
+ // Override to handle icon hovering events.
+ }
+ /**
+ * Called when a connection is hovered over.
+ */
+ protected void onConnectionHover(DiagramConnection conn) {
+ // Override to handle connection hovering events.
+ }
}
diff --git a/src/main/java/noppes/npcs/client/gui/global/GuiMagicMap.java b/src/main/java/noppes/npcs/client/gui/global/GuiMagicMap.java
index 7954d5f56..01b9ef562 100644
--- a/src/main/java/noppes/npcs/client/gui/global/GuiMagicMap.java
+++ b/src/main/java/noppes/npcs/client/gui/global/GuiMagicMap.java
@@ -31,9 +31,9 @@ public class GuiMagicMap extends GuiDiagram {
for (Magic magic : MagicController.getInstance().magics.values()) {
magics.add(magic);
}
- setLayout(DiagramLayout.CIRCULAR_MANUAL);
+ setLayout(DiagramLayout.CHART);
this.setCurvedArrows(true);
- this.setCurveAngle(25);
+ this.setCurveAngle(-20);
}
@Override
diff --git a/src/main/java/noppes/npcs/controllers/MagicController.java b/src/main/java/noppes/npcs/controllers/MagicController.java
index b2c6385af..da72e80a2 100644
--- a/src/main/java/noppes/npcs/controllers/MagicController.java
+++ b/src/main/java/noppes/npcs/controllers/MagicController.java
@@ -57,7 +57,7 @@ public class MagicController {
} catch (Exception ee) { }
}
magics.clear();
- if (false) {
+ if (true) {
// Create default Pokémon types
Magic normal = new Magic(0, "Normal", 0xA8A878);
normal.setIconItem(new ItemStack(net.minecraft.init.Items.paper)); // using paper for Normal
@@ -205,30 +205,30 @@ public class MagicController {
magics.put(fairy.id, fairy);
}
- if (true || magics.isEmpty()) {
+ if (false) {
// Create default magics
- Magic earth = new Magic(0, "Earth", 0x00DD00, 0, 0);
+ Magic earth = new Magic(0, "Earth", 0x00DD00, 1, 1);
earth.setIconItem(new ItemStack(CustomItems.earthElement));
- Magic water = new Magic(1, "Water", 0xF2DD00, 0, 1);
+ Magic water = new Magic(1, "Water", 0xF2DD00, 1, 2);
water.setIconItem(new ItemStack(CustomItems.waterElement));
- Magic fire = new Magic(2, "Fire", 0xDD0000, 0, 2);
+ Magic fire = new Magic(2, "Fire", 0xDD0000, 1, 3);
fire.setIconItem(new ItemStack(CustomItems.spellFire));
- Magic air = new Magic(3, "Air", 0xDD0000, 0, 3);
+ Magic air = new Magic(3, "Air", 0xDD0000, 1, 0);
air.setIconItem(new ItemStack(CustomItems.airElement));
- Magic dark = new Magic(4, "Dark", 0xDD0000, 1, 3);
+ Magic dark = new Magic(4, "Dark", 0xDD0000, 0, 3);
dark.setIconItem(new ItemStack(CustomItems.spellDark));
- Magic holy = new Magic(5, "Holy", 0xDD0000, 1, 1);
+ Magic holy = new Magic(5, "Holy", 0xDD0000, 0, 1);
holy.setIconItem(new ItemStack(CustomItems.spellHoly));
- Magic nature = new Magic(6, "Nature", 0xDD0000, 1, 0);
+ Magic nature = new Magic(6, "Nature", 0xDD0000, 0, 0);
nature.setIconItem(new ItemStack(CustomItems.spellNature));
- Magic arcane = new Magic(7, "Arcane", 0xDD0000, 1, 2);
+ Magic arcane = new Magic(7, "Arcane", 0xDD0000, 0, 2);
arcane.setIconItem(new ItemStack(CustomItems.spellArcane));
// Insiders