mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-13 20:44:08 +00:00
GuiScriptInterface is now pannable! Core functionality added to GuiNPCInterface, which means technically any child of that can be pannable
This commit is contained in:
1 parent
45cda3cc90
commit
18c15b13bc
2 files changed
+189
-29
No files matched your search
@@ -102,6 +102,7 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb
|
||||
this.drawDefaultBackground = true;
|
||||
this.closeOnEsc = true;
|
||||
this.xSize = 420;
|
||||
this.isPannableGUI = true;
|
||||
this.setBackground("menubg.png");
|
||||
}
|
||||
|
||||
@@ -142,6 +143,7 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb
|
||||
|
||||
public void initGui() {
|
||||
// ==================== BASE LAYOUT CALCULATION ====================
|
||||
isPanning = false;
|
||||
this.ySize = (int) ((double) this.xSize * 0.56D);
|
||||
if ((double) this.ySize > (double) this.height * 0.95D) {
|
||||
this.ySize = (int) ((double) this.height * 0.95D);
|
||||
@@ -334,6 +336,8 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb
|
||||
}
|
||||
this.addScroll(scroll);
|
||||
}
|
||||
|
||||
computePanBounds(editorX, editorY, editorWidth, editorHeight);
|
||||
}
|
||||
/**
|
||||
* Initialize the settings tab layout (console view).
|
||||
@@ -376,6 +380,12 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb
|
||||
// Language button requires options to be available
|
||||
this.getButton(103).enabled = languageOptions.size() > 0;
|
||||
}
|
||||
|
||||
int consoleX = this.guiLeft + 4 + yoffset;
|
||||
int consoleY = this.guiTop + 6 + yoffset;
|
||||
int consoleW = this.xSize - 160 - yoffset;
|
||||
int consoleH = (int) ((float) this.ySize * 0.92F) - yoffset * 2;
|
||||
computePanBounds(consoleX, consoleY, consoleW, consoleH);
|
||||
}
|
||||
|
||||
public GuiScriptInterface setDimensions(int x, int y) {
|
||||
@@ -393,21 +403,35 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb
|
||||
protected ScriptContext getScriptContext() {
|
||||
return handler.getContext();
|
||||
}
|
||||
|
||||
// ==================== MOUSE HANDLING ====================
|
||||
|
||||
@Override
|
||||
public void mouseClicked(int mouseX, int mouseY, int mouseButton) {
|
||||
// Check if click is within autocomplete menu bounds and consume it if so
|
||||
protected boolean isPannableArea(int mx, int my) {
|
||||
if (activeTab > 0 && fullscreenButton.isMouseOver(mx, my)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GuiScriptTextArea activeArea = getActiveScriptArea();
|
||||
if (activeArea != null && activeArea.isPointOnAutocompleteMenu(mx, my)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return super.isPannableArea(mx, my);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(int i, int j, int k) {
|
||||
int adjX = panAdjustedX(i);
|
||||
int adjY = panAdjustedY(j);
|
||||
|
||||
GuiScriptTextArea activeArea = getActiveScriptArea();
|
||||
boolean isOverAutocomplete = activeArea != null
|
||||
&& activeArea.isPointOnAutocompleteMenu(mouseX, mouseY);
|
||||
&& activeArea.isPointOnAutocompleteMenu(adjX, adjY);
|
||||
if (isOverAutocomplete) {
|
||||
activeArea.mouseClicked(mouseX, mouseY, mouseButton);
|
||||
activeArea.mouseClicked(adjX, adjY, k);
|
||||
return;
|
||||
}
|
||||
|
||||
super.mouseClicked(mouseX, mouseY, mouseButton);
|
||||
super.mouseClicked(i, j, k);
|
||||
}
|
||||
|
||||
public String previousHookClicked = "";
|
||||
|
||||
@@ -61,6 +61,29 @@ public abstract class GuiNPCInterface extends GuiScreen {
|
||||
public float bgScaleZ = 1;
|
||||
public int bgTextureHeight = 256; // Actual content height in texture (for bottom border stitching)
|
||||
|
||||
// ==================== VIEWPORT PANNING ====================
|
||||
/**
|
||||
* If true, this GUI supports viewport panning via click-drag on empty areas.
|
||||
* Subclasses set this to true and call computePanBounds() to enable.
|
||||
*/
|
||||
protected boolean isPannableGUI = false;
|
||||
protected boolean isPanning = false;
|
||||
protected double panStartX, panStartY;
|
||||
|
||||
/**
|
||||
* Cumulative pan offset in scaled GUI pixels.
|
||||
* Positive values = viewport shifted right/down (content appears to move left/up).
|
||||
*/
|
||||
public double currentPanX, currentPanY;
|
||||
|
||||
public static double activePanX, activePanY;
|
||||
|
||||
protected double minPanX, maxPanX, minPanY, maxPanY;
|
||||
protected int panViewportX, panViewportY, panViewportWidth, panViewportHeight;
|
||||
|
||||
/** Pan-adjusted mouse coordinates, updated every frame in drawScreen for hit-testing panned components. */
|
||||
protected int panAdjMouseX, panAdjMouseY;
|
||||
|
||||
public GuiNPCInterface(EntityNPCInterface npc) {
|
||||
this.player = Minecraft.getMinecraft().thePlayer;
|
||||
this.npc = npc;
|
||||
@@ -161,29 +184,38 @@ public abstract class GuiNPCInterface extends GuiScreen {
|
||||
if (subgui != null)
|
||||
subgui.mouseClicked(i, j, k);
|
||||
else {
|
||||
mouseEvent(i, j, k);
|
||||
vanillaMouseClicked(i, j, k);
|
||||
int adjX = isPannableGUI ? panAdjustedX(i) : i;
|
||||
int adjY = isPannableGUI ? panAdjustedY(j) : j;
|
||||
|
||||
if (isPannableGUI && k == 0 && isPannableArea(adjX, adjY)) {
|
||||
isPanning = true;
|
||||
panStartX = i;
|
||||
panStartY = j;
|
||||
return;
|
||||
}
|
||||
|
||||
mouseEvent(adjX, adjY, k);
|
||||
vanillaMouseClicked(adjX, adjY, k);
|
||||
|
||||
for (GuiScrollWindow guiScrollableComponent : scrollWindows.values()) {
|
||||
guiScrollableComponent.mouseClicked(i, j, k);
|
||||
guiScrollableComponent.mouseClicked(adjX, adjY, k);
|
||||
}
|
||||
|
||||
if (k == 0) {
|
||||
for (GuiCustomScroll scroll : new ArrayList<GuiCustomScroll>(scrolls.values())) {
|
||||
scroll.mouseClicked(i, j, k);
|
||||
scroll.mouseClicked(adjX, adjY, k);
|
||||
}
|
||||
}
|
||||
// Process diagram mouse clicks
|
||||
for (GuiDiagram diagram : diagrams.values()) {
|
||||
if (diagram.isWithin(i, j)) {
|
||||
if (diagram.mouseClicked(i, j, k))
|
||||
if (diagram.isWithin(adjX, adjY)) {
|
||||
if (diagram.mouseClicked(adjX, adjY, k))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (GuiNpcTextField tf : new ArrayList<GuiNpcTextField>(textfields.values()))
|
||||
if (tf.enabled)
|
||||
tf.mouseClicked(i, j, k);
|
||||
tf.mouseClicked(adjX, adjY, k);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -225,7 +257,12 @@ public abstract class GuiNPCInterface extends GuiScreen {
|
||||
subgui.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick);
|
||||
return;
|
||||
}
|
||||
super.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick);
|
||||
if (isPannableGUI && isPanning) {
|
||||
return;
|
||||
}
|
||||
int adjX = isPannableGUI ? panAdjustedX(mouseX) : mouseX;
|
||||
int adjY = isPannableGUI ? panAdjustedY(mouseY) : mouseY;
|
||||
super.mouseClickMove(adjX, adjY, clickedMouseButton, timeSinceLastClick);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -234,12 +271,72 @@ public abstract class GuiNPCInterface extends GuiScreen {
|
||||
subgui.mouseMovedOrUp(mouseX, mouseY, state);
|
||||
return;
|
||||
}
|
||||
super.mouseMovedOrUp(mouseX, mouseY, state);
|
||||
if (isPannableGUI && state == 0 && isPanning) {
|
||||
isPanning = false;
|
||||
panStartX = 0;
|
||||
panStartY = 0;
|
||||
return;
|
||||
}
|
||||
int adjX = isPannableGUI ? panAdjustedX(mouseX) : mouseX;
|
||||
int adjY = isPannableGUI ? panAdjustedY(mouseY) : mouseY;
|
||||
super.mouseMovedOrUp(adjX, adjY, state);
|
||||
}
|
||||
|
||||
public void mouseEvent(int i, int j, int k) {
|
||||
}
|
||||
|
||||
// ==================== VIEWPORT PANNING METHODS ====================
|
||||
|
||||
protected boolean isPannableArea(int mx, int my) {
|
||||
for (Object obj : this.buttonList) {
|
||||
GuiButton btn = (GuiButton) obj;
|
||||
if (btn.visible && mx >= btn.xPosition && mx < btn.xPosition + btn.width
|
||||
&& my >= btn.yPosition && my < btn.yPosition + btn.height) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (GuiCustomScroll scroll : scrolls.values()) {
|
||||
if (scroll.visible && scroll.isMouseOver(mx, my)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (GuiNpcTextField tf : textfields.values()) {
|
||||
if (tf.enabled && mx >= tf.xPosition && mx < tf.xPosition + tf.width
|
||||
&& my >= tf.yPosition && my < tf.yPosition + tf.height) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void computePanBounds(int vpX, int vpY, int vpW, int vpH) {
|
||||
this.panViewportX = vpX;
|
||||
this.panViewportY = vpY;
|
||||
this.panViewportWidth = vpW;
|
||||
this.panViewportHeight = vpH;
|
||||
|
||||
int panRange = Math.max(this.width, this.height) / 2;
|
||||
this.minPanX = -panRange;
|
||||
this.maxPanX = panRange;
|
||||
this.minPanY = -panRange;
|
||||
this.maxPanY = panRange;
|
||||
}
|
||||
|
||||
protected int panAdjustedX(int rawMouseX) {
|
||||
return rawMouseX + (int) currentPanX;
|
||||
}
|
||||
|
||||
protected int panAdjustedY(int rawMouseY) {
|
||||
return rawMouseY + (int) currentPanY;
|
||||
}
|
||||
|
||||
public boolean hasPanOffset() {
|
||||
return isPannableGUI && (currentPanX != 0 || currentPanY != 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void actionPerformed(GuiButton guibutton) {
|
||||
if (subgui != null)
|
||||
@@ -377,9 +474,43 @@ public abstract class GuiNPCInterface extends GuiScreen {
|
||||
public void drawScreen(int i, int j, float f) {
|
||||
mouseX = i;
|
||||
mouseY = j;
|
||||
|
||||
boolean panning = hasPanOffset();
|
||||
int drawX = panning ? panAdjustedX(i) : i;
|
||||
int drawY = panning ? panAdjustedY(j) : j;
|
||||
panAdjMouseX = drawX;
|
||||
panAdjMouseY = drawY;
|
||||
|
||||
// Smooth pan: update pan offset every frame using raw mouse delta
|
||||
if (isPannableGUI && isPanning && Mouse.isButtonDown(0)) {
|
||||
double deltaX = i - panStartX;
|
||||
double deltaY = j - panStartY;
|
||||
|
||||
currentPanX = Math.max(minPanX, Math.min(maxPanX, currentPanX - deltaX));
|
||||
currentPanY = Math.max(minPanY, Math.min(maxPanY, currentPanY - deltaY));
|
||||
|
||||
panStartX = i;
|
||||
panStartY = j;
|
||||
|
||||
panning = hasPanOffset();
|
||||
drawX = panning ? panAdjustedX(i) : i;
|
||||
drawY = panning ? panAdjustedY(j) : j;
|
||||
panAdjMouseX = drawX;
|
||||
panAdjMouseY = drawY;
|
||||
} else if (isPanning && !Mouse.isButtonDown(0)) {
|
||||
isPanning = false;
|
||||
}
|
||||
|
||||
if (drawDefaultBackground && subgui == null)
|
||||
drawDefaultBackground();
|
||||
|
||||
if (panning) {
|
||||
GL11.glPushMatrix();
|
||||
GL11.glTranslated(-currentPanX, -currentPanY, 0);
|
||||
activePanX = currentPanX;
|
||||
activePanY = currentPanY;
|
||||
}
|
||||
|
||||
if (background != null && mc.renderEngine != null) {
|
||||
drawBackground();
|
||||
}
|
||||
@@ -390,40 +521,45 @@ public abstract class GuiNPCInterface extends GuiScreen {
|
||||
label.drawLabel(this, fontRendererObj);
|
||||
for (GuiCustomScroll scroll : scrolls.values()) {
|
||||
scroll.updateSubGUI(subGui);
|
||||
scroll.drawScreen(i, j, f, !subGui && scroll.isMouseOver(i, j) ? Mouse.getDWheel() : 0);
|
||||
scroll.drawScreen(drawX, drawY, f, !subGui && scroll.isMouseOver(drawX, drawY) ? Mouse.getDWheel() : 0);
|
||||
}
|
||||
// Draw scrollable windows.
|
||||
for (GuiScrollWindow guiScrollableComponent : scrollWindows.values()) {
|
||||
guiScrollableComponent.drawScreen(i, j, f, !subGui && guiScrollableComponent.isMouseOver(i, j) ? Mouse.getDWheel() : 0);
|
||||
guiScrollableComponent.drawScreen(drawX, drawY, f, !subGui && guiScrollableComponent.isMouseOver(drawX, drawY) ? Mouse.getDWheel() : 0);
|
||||
}
|
||||
for (GuiDiagram diagram : diagrams.values()) {
|
||||
diagram.drawDiagram(i, j, subGui);
|
||||
diagram.drawDiagram(drawX, drawY, subGui);
|
||||
}
|
||||
super.drawScreen(i, j, f);
|
||||
super.drawScreen(drawX, drawY, f);
|
||||
for (GuiCustomScroll scroll : scrolls.values())
|
||||
if (scroll.hoverableText) {
|
||||
scroll.drawHover(i, j);
|
||||
scroll.drawHover(drawX, drawY);
|
||||
}
|
||||
for (GuiNpcButton button : buttons.values()) {
|
||||
button.updateSubGUI(subGui);
|
||||
if (!button.hoverableText.isEmpty()) {
|
||||
button.drawHover(i, j, subGui);
|
||||
button.drawHover(drawX, drawY, subGui);
|
||||
}
|
||||
}
|
||||
for (GuiNpcTextField tf : textfields.values()) {
|
||||
tf.drawTextBox(i, j);
|
||||
tf.drawTextBox(drawX, drawY);
|
||||
if (tf.hasHoverText())
|
||||
tf.drawHover(i, j, subGui);
|
||||
tf.drawHover(drawX, drawY, subGui);
|
||||
}
|
||||
|
||||
for(GuiScrollWindow guiScrollableComponent : scrollWindows.values()) {
|
||||
if (guiScrollableComponent.isMouseOver(mouseX, mouseY)) {
|
||||
guiScrollableComponent.drawHoverTexts(mouseX, mouseY);
|
||||
if (guiScrollableComponent.isMouseOver(drawX, drawY)) {
|
||||
guiScrollableComponent.drawHoverTexts(drawX, drawY);
|
||||
}
|
||||
}
|
||||
|
||||
for (GuiScreen gui : extra.values())
|
||||
gui.drawScreen(i, j, f);
|
||||
gui.drawScreen(drawX, drawY, f);
|
||||
|
||||
if (panning) {
|
||||
GL11.glPopMatrix();
|
||||
activePanX = 0;
|
||||
activePanY = 0;
|
||||
}
|
||||
|
||||
if (subgui != null) {
|
||||
subgui.drawScreen(i, j, f);
|
||||
|
||||
Reference in new issue
Block a user