1135 lines
26 KiB
Java
1135 lines
26 KiB
Java
package speiger.src.coreengine.rendering.gui;
|
|
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.UUID;
|
|
import java.util.function.Consumer;
|
|
|
|
import org.lwjgl.glfw.GLFW;
|
|
|
|
import speiger.src.collections.objects.lists.ObjectArrayList;
|
|
import speiger.src.collections.objects.sets.ObjectLinkedOpenHashSet;
|
|
import speiger.src.coreengine.assets.AssetLocation;
|
|
import speiger.src.coreengine.math.collision2d.Plane;
|
|
import speiger.src.coreengine.math.vector.doubles.Vec2d;
|
|
import speiger.src.coreengine.rendering.gui.base.GuiScreenBase;
|
|
import speiger.src.coreengine.rendering.gui.base.IButtonComponent;
|
|
import speiger.src.coreengine.rendering.gui.base.IKeyComponent;
|
|
import speiger.src.coreengine.rendering.gui.components.TextComponent;
|
|
import speiger.src.coreengine.rendering.gui.helper.Align;
|
|
import speiger.src.coreengine.rendering.gui.helper.animations.Animator;
|
|
import speiger.src.coreengine.rendering.gui.helper.box.GuiBox;
|
|
import speiger.src.coreengine.rendering.gui.helper.box.IGuiBox;
|
|
import speiger.src.coreengine.rendering.gui.helper.constrains.ComponentConstrains;
|
|
import speiger.src.coreengine.rendering.gui.helper.constrains.Constrain;
|
|
import speiger.src.coreengine.rendering.gui.renderer.IComponentRenderer;
|
|
import speiger.src.coreengine.rendering.gui.renderer.UIRenderer;
|
|
import speiger.src.coreengine.rendering.input.Keyboard;
|
|
import speiger.src.coreengine.rendering.input.bindings.utils.BindingType;
|
|
import speiger.src.coreengine.rendering.input.bindings.utils.ModType;
|
|
import speiger.src.coreengine.rendering.input.window.Window;
|
|
import speiger.src.coreengine.rendering.utils.Cursor;
|
|
import speiger.src.coreengine.rendering.utils.GLUtils;
|
|
import speiger.src.coreengine.utils.collections.CollectionUtils;
|
|
import speiger.src.coreengine.utils.collections.FlagHolder;
|
|
|
|
public abstract class GuiComponent extends FlagHolder
|
|
{
|
|
public static final int FLAG_VISIBLE = 1;
|
|
public static final int FLAG_ENABLED = 2;
|
|
public static final int FLAG_IGNORE_PARENT_BOUNDS = 4;
|
|
public static final int FLAG_ALWAYS_CLICKABLE = 8;
|
|
public static final int FLAG_RENDER_ORDER = 16;
|
|
public static final int FLAG_MANUAL_RENDER = 32;
|
|
public static final int FLAG_MASS_CHANGE = 64;
|
|
public static final int FLAG_SUPPORT_BINDING = 128;
|
|
public static final int FLAG_TEST_SCISSORS = 256;
|
|
static final int FLAG_CLOSING = 512;
|
|
|
|
public static final int LAST_FLAG = 1 << 19;// This is the last flag and then
|
|
// anything behind this is custom
|
|
// flags for components
|
|
|
|
public static final int LISTENER_USER_ACTION = 0;
|
|
public static final int LISTENER_ON_CHANGE = 1;
|
|
public static final int LISTENER_CLOSED = 2;
|
|
|
|
final IGuiBox box;
|
|
GuiBase owner;
|
|
GuiComponent parent;
|
|
ComponentConstrains constraints = null;
|
|
Animator animation = null;
|
|
KeyBindAction binding = null;
|
|
IComponentRenderer<GuiComponent> customRenderer;
|
|
Set<Consumer<GuiComponent>>[] listeners = CollectionUtils.createSets(3, true);
|
|
Set<GuiComponent> children = new ObjectLinkedOpenHashSet<>();
|
|
Set<GuiComponent> popupChildren = new ObjectLinkedOpenHashSet<>();
|
|
Tooltips tooltips = new Tooltips();
|
|
UUID tooltipId;
|
|
float zLevel = 0F;
|
|
float totalZ = 0F;
|
|
float visiblity = 1F;
|
|
float totalVisibility = 1F;
|
|
float brightness = 1F;
|
|
boolean changed = false;
|
|
boolean massRepaint = false;
|
|
|
|
public GuiComponent(float x, float y, float width, float height)
|
|
{
|
|
this(new GuiBox(x, y, width, height));
|
|
}
|
|
|
|
public GuiComponent(IGuiBox box)
|
|
{
|
|
super(FLAG_VISIBLE | FLAG_ENABLED);
|
|
this.box = box;
|
|
}
|
|
|
|
public IGuiBox getBox()
|
|
{
|
|
return box;
|
|
}
|
|
|
|
public GuiBase getGui()
|
|
{
|
|
return owner;
|
|
}
|
|
|
|
public void calculateActualBounds(float[] area, boolean start)
|
|
{
|
|
if(start)
|
|
{
|
|
area[0] = Float.MAX_VALUE;
|
|
area[1] = Float.MAX_VALUE;
|
|
area[2] = Float.MIN_VALUE;
|
|
area[3] = Float.MIN_VALUE;
|
|
}
|
|
area[0] = Math.min(area[0], box.getMinX());
|
|
area[1] = Math.min(area[1], box.getMinY());
|
|
area[2] = Math.max(area[2], box.getMaxX());
|
|
area[3] = Math.max(area[3], box.getMaxY());
|
|
for(GuiComponent comp : children)
|
|
{
|
|
if(comp.isVisible()) comp.calculateActualBounds(area, false);
|
|
}
|
|
}
|
|
|
|
public boolean isMouseOver(int mouseX, int mouseY)
|
|
{
|
|
return (parent == null || isFlagSet(FLAG_IGNORE_PARENT_BOUNDS) || parent.isMouseOver(mouseX, mouseY)) && isOverBox(mouseX, mouseY);
|
|
}
|
|
|
|
protected boolean isOverBox(int mouseX, int mouseY)
|
|
{
|
|
return box.isColiding(mouseX, mouseY);
|
|
}
|
|
|
|
public boolean isHovered(int mouseX, int mouseY)
|
|
{
|
|
return isParentVisible() && isAnyFlagSet(FLAG_ALWAYS_CLICKABLE | FLAG_ENABLED) && isMouseOver(mouseX, mouseY);
|
|
}
|
|
|
|
public boolean isTopHovered(int mouseX, int mouseY)
|
|
{
|
|
if(!isHovered(mouseX, mouseY))
|
|
{
|
|
return false;
|
|
}
|
|
GuiComponent top = getTopComponent();
|
|
return !getGui().hasComponentInTheWay(top, mouseX, mouseY) && top.isChildAtTop(this, mouseX, mouseY);
|
|
}
|
|
|
|
public boolean isChildAtTop(GuiComponent component, int mouseX, int mouseY)
|
|
{
|
|
float sourceHeight = component.calculateZLevel();
|
|
if(children.isEmpty())
|
|
{
|
|
return true;
|
|
}
|
|
for(GuiComponent comp : children)
|
|
{
|
|
if(comp != component && comp.isOverChild(mouseX, mouseY) && (comp.calculateZLevel() > sourceHeight || !comp.isChildAtTop(component, mouseX, mouseY)))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public boolean isOverChild(int mouseX, int mouseY)
|
|
{
|
|
if(children.isEmpty())
|
|
{
|
|
return false;
|
|
}
|
|
for(GuiComponent comp : children)
|
|
{
|
|
if(comp.isOverChild(mouseX, mouseY) || (comp instanceof IButtonComponent && ((IButtonComponent)comp).isComponentColliding(mouseX, mouseY)))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public boolean hasFocus()
|
|
{
|
|
return getGui().isComponentFocused(getTopComponent());
|
|
}
|
|
|
|
public final boolean hasPopups()
|
|
{
|
|
return popupChildren.size() > 0;
|
|
}
|
|
|
|
public final void setOwner(GuiBase gui)
|
|
{
|
|
owner = gui;
|
|
for(GuiComponent comp : children)
|
|
{
|
|
comp.setOwner(gui);
|
|
if(comp instanceof IButtonComponent)
|
|
{
|
|
getGui().addButtonListener((IButtonComponent)comp);
|
|
}
|
|
if(comp instanceof IKeyComponent)
|
|
{
|
|
getGui().addKeyListener((IKeyComponent)comp);
|
|
}
|
|
}
|
|
init();
|
|
onComponentChanged(true);
|
|
if(binding != null)
|
|
{
|
|
gui.addKeyListener(binding);
|
|
}
|
|
}
|
|
|
|
public abstract void init();
|
|
|
|
public void onClosed()
|
|
{
|
|
if(!setFlag(FLAG_CLOSING, true))
|
|
{
|
|
return;
|
|
}
|
|
for(GuiComponent comp : children)
|
|
{
|
|
comp.onClosed();
|
|
if(comp instanceof IButtonComponent)
|
|
{
|
|
getGui().removeButtonListener((IButtonComponent)comp);
|
|
}
|
|
if(comp instanceof IKeyComponent)
|
|
{
|
|
getGui().removeKeyListener((IKeyComponent)comp);
|
|
}
|
|
}
|
|
children.clear();
|
|
popupChildren.clear();
|
|
box.clearChildren();
|
|
if(binding != null)
|
|
{
|
|
owner.removeKeyListener(binding);
|
|
}
|
|
notifyListeners(LISTENER_CLOSED);
|
|
clearFlag(FLAG_CLOSING);
|
|
}
|
|
|
|
public final float getZOffset()
|
|
{
|
|
return zLevel;
|
|
}
|
|
|
|
public final float calculateZLevel()
|
|
{
|
|
return totalZ;
|
|
}
|
|
|
|
public final float getVisibility()
|
|
{
|
|
return visiblity;
|
|
}
|
|
|
|
public final float getTotalVisibility()
|
|
{
|
|
return totalVisibility;
|
|
}
|
|
|
|
public final float getBrightness()
|
|
{
|
|
return brightness;
|
|
}
|
|
|
|
public final boolean hasConstraints()
|
|
{
|
|
return constraints != null;
|
|
}
|
|
|
|
public final boolean isEnabled()
|
|
{
|
|
return isFlagSet(FLAG_ENABLED);
|
|
}
|
|
|
|
public final boolean isVisible()
|
|
{
|
|
return isFlagSet(FLAG_VISIBLE);
|
|
}
|
|
|
|
public final boolean usesRenderOrder()
|
|
{
|
|
return isFlagSet(FLAG_RENDER_ORDER);
|
|
}
|
|
|
|
public final boolean isManualRender()
|
|
{
|
|
return isFlagSet(FLAG_MANUAL_RENDER);
|
|
}
|
|
|
|
public boolean isTestingScissors()
|
|
{
|
|
return isFlagSet(FLAG_TEST_SCISSORS);
|
|
}
|
|
|
|
public final boolean isParentVisible()
|
|
{
|
|
return isVisible() && (parent == null || parent.isVisible());
|
|
}
|
|
|
|
public final void setMassChanging()
|
|
{
|
|
setFlag(FLAG_MASS_CHANGE);
|
|
}
|
|
|
|
public final <T extends GuiComponent> T setMassChanging(Class<T> clz)
|
|
{
|
|
setFlag(FLAG_MASS_CHANGE);
|
|
return (T)this;
|
|
}
|
|
|
|
public final GuiComponent finishMassChanging()
|
|
{
|
|
return finishMassChanging(false);
|
|
}
|
|
|
|
public final GuiComponent finishMassChanging(boolean quiet)
|
|
{
|
|
if(isFlagSet(FLAG_MASS_CHANGE))
|
|
{
|
|
clearFlag(FLAG_MASS_CHANGE);
|
|
if(changed && !quiet)
|
|
{
|
|
onComponentChanged(massRepaint);
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
|
|
public final GuiComponent setEnabled(boolean value)
|
|
{
|
|
if(!setFlag(FLAG_ENABLED, value)) return this;
|
|
for(GuiComponent comp : children)
|
|
{
|
|
comp.setEnabled(value);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
public final GuiComponent setVisible(boolean value)
|
|
{
|
|
if(!setFlag(FLAG_VISIBLE, value)) return this;
|
|
for(GuiComponent comp : children)
|
|
{
|
|
comp.setVisible(value);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
public final GuiComponent setManualRenderer(boolean value)
|
|
{
|
|
setFlag(FLAG_MANUAL_RENDER, value);
|
|
return this;
|
|
}
|
|
|
|
public GuiComponent setIgnoreBounds(boolean value)
|
|
{
|
|
setFlag(FLAG_IGNORE_PARENT_BOUNDS, value);
|
|
return this;
|
|
}
|
|
|
|
public GuiComponent setScissorsTest(boolean value)
|
|
{
|
|
setFlag(FLAG_TEST_SCISSORS, value);
|
|
return this;
|
|
}
|
|
|
|
public final GuiComponent setScale(float value)
|
|
{
|
|
if(getBox().getBaseScale() != value)
|
|
{
|
|
getBox().setScale(value);
|
|
onComponentChanged(true);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
public final GuiComponent setZOffset(float value)
|
|
{
|
|
zLevel = value;
|
|
return this;
|
|
}
|
|
|
|
public final GuiComponent setVisibilty(float value)
|
|
{
|
|
if(visiblity == value) return this;
|
|
visiblity = value;
|
|
updateVisibility();
|
|
return this;
|
|
}
|
|
|
|
public final GuiComponent setBrightness(float value)
|
|
{
|
|
brightness = value;
|
|
return this;
|
|
}
|
|
|
|
public final GuiComponent changeVisibility(float value)
|
|
{
|
|
return value == 1F ? this : setVisibilty(visiblity * value);
|
|
}
|
|
|
|
protected void updateVisibility()
|
|
{
|
|
totalVisibility = (parent != null ? parent.totalVisibility : 1F) * visiblity;
|
|
for(GuiComponent comp : children)
|
|
{
|
|
comp.updateVisibility();
|
|
}
|
|
}
|
|
|
|
public GuiComponent setUserKey(int keyBind){return setUserKey(keyBind, ModType.IGNORE, false);}
|
|
public GuiComponent setUserKey(int keyBind, boolean block){return setUserKey(keyBind, ModType.IGNORE, block);}
|
|
public GuiComponent setUserKey(int keyBind, int mod){return setUserKey(keyBind, mod, false);}
|
|
public GuiComponent setUserKey(int keyBind, int mod, boolean block)
|
|
{
|
|
if(isFlagNotSet(FLAG_SUPPORT_BINDING)) return this;
|
|
if(owner != null)
|
|
{
|
|
if(binding != null)
|
|
{
|
|
owner.removeKeyListener(binding);
|
|
tooltips.removeTooltip(binding.getTooltip());
|
|
}
|
|
binding = new KeyBindAction(keyBind, mod, block);
|
|
owner.addKeyListener(binding);
|
|
addBindingTooltip();
|
|
return this;
|
|
}
|
|
binding = new KeyBindAction(keyBind, mod, block);
|
|
addBindingTooltip();
|
|
return this;
|
|
}
|
|
|
|
public <T extends GuiComponent> GuiComponent setCustomRenderer(IComponentRenderer<T> renderer)
|
|
{
|
|
customRenderer = (IComponentRenderer<GuiComponent>)renderer;
|
|
return this;
|
|
}
|
|
|
|
private void addBindingTooltip()
|
|
{
|
|
tooltips.addComponent(binding.getTooltip(), new TextComponent(0F, 0F, 200F, 0F, "Key: "+ModType.getMods(binding.mod)+BindingType.KEYBOARD.getName(binding.key)).setLimitedHeight(false).setAlignment(Align.LEFT_TOP, Align.LEFT_TOP).setScale(0.5F));
|
|
}
|
|
|
|
protected boolean onUserKey()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public <T extends GuiComponent> T setRelativeTo(T component)
|
|
{
|
|
return setRelativeTo(component, Align.CENTER, Align.CENTER);
|
|
}
|
|
|
|
public <T extends GuiComponent> T setRelativeTo(T component, Align horizontal, Align vertical)
|
|
{
|
|
return component.setComponentPosition(box.getMinX() + horizontal.align(box.getWidth(), component.getBox().getWidth()), box.getMinY() + vertical.align(box.getHeight(), component.getBox().getHeight())).cast();
|
|
}
|
|
|
|
public <T extends GuiComponent> T centerComponent(T component)
|
|
{
|
|
return getGui().centerComponent(component);
|
|
}
|
|
|
|
public <T extends GuiComponent> T addChild(T comp)
|
|
{
|
|
return addChild(comp, null);
|
|
}
|
|
|
|
public <T extends GuiComponent> T addChild(T comp, Constrain xPos, Constrain yPos, Constrain width, Constrain height)
|
|
{
|
|
return addChild(comp, new ComponentConstrains(xPos, yPos, width, height));
|
|
}
|
|
|
|
public <T extends GuiComponent> T addChild(T comp, ComponentConstrains constrains)
|
|
{
|
|
comp.constraints = constrains;
|
|
comp.parent = this;
|
|
children.add(comp);
|
|
box.addChild(comp.getBox());
|
|
if(constrains != null)
|
|
{
|
|
constrains.setOwner(comp, this);
|
|
constrains.onComponentChanged();
|
|
}
|
|
if(owner != null)
|
|
{
|
|
comp.setOwner(owner);
|
|
if(comp instanceof IButtonComponent)
|
|
{
|
|
owner.addButtonListener((IButtonComponent)comp);
|
|
}
|
|
if(comp instanceof IKeyComponent)
|
|
{
|
|
owner.addKeyListener((IKeyComponent)comp);
|
|
}
|
|
}
|
|
return comp;
|
|
}
|
|
|
|
public <T extends GuiComponent> T addPopup(T popup)
|
|
{
|
|
popupChildren.add(popup.addCloseListener(popupChildren::remove));
|
|
getGui().addComponent(popup);
|
|
return popup;
|
|
}
|
|
|
|
protected void addConstrains(GuiComponent comp, ComponentConstrains constrains)
|
|
{
|
|
comp.constraints = constrains;
|
|
if(constrains != null)
|
|
{
|
|
constrains.setOwner(comp, this);
|
|
constrains.onComponentChanged();
|
|
}
|
|
}
|
|
|
|
public final UUID getTooltipId()
|
|
{
|
|
return tooltipId;
|
|
}
|
|
|
|
public Tooltips getTooltips()
|
|
{
|
|
return tooltips;
|
|
}
|
|
|
|
public GuiComponent addTooltip(String s, float width)
|
|
{
|
|
return addTooltip(s, width, 0F);
|
|
}
|
|
|
|
public GuiComponent addTooltip(String s, float width, float height)
|
|
{
|
|
return addTooltip(s, width, height, 0.5F);
|
|
}
|
|
|
|
public GuiComponent addTooltip(String s, float width, float height, float scale)
|
|
{
|
|
tooltips.addComponent(new TextComponent(0F, 0F, width, height, s).setLimitedHeight(height != 0F).setAlignment(Align.LEFT_TOP, Align.LEFT_TOP).setScale(scale));
|
|
return this;
|
|
}
|
|
|
|
public GuiComponent addTooltip(GuiComponent comp)
|
|
{
|
|
tooltips.addComponent(comp);
|
|
return this;
|
|
}
|
|
|
|
public GuiComponent addTooltip(UUID id, GuiComponent comp)
|
|
{
|
|
tooltips.addComponent(id, comp);
|
|
return this;
|
|
}
|
|
|
|
public boolean containsTooltip(UUID id)
|
|
{
|
|
return tooltips.contains(id);
|
|
}
|
|
|
|
public boolean isTooltip()
|
|
{
|
|
return tooltipId != null;
|
|
}
|
|
|
|
public GuiComponent removeTooltip(GuiComponent comp)
|
|
{
|
|
return removeTooltip(comp.getTooltipId());
|
|
}
|
|
|
|
public GuiComponent removeTooltip(UUID id)
|
|
{
|
|
return tooltips.removeTooltip(id);
|
|
}
|
|
|
|
public List<GuiComponent> getChildren()
|
|
{
|
|
return new ObjectArrayList<GuiComponent>(children);
|
|
}
|
|
|
|
public GuiComponent getParent()
|
|
{
|
|
return parent;
|
|
}
|
|
|
|
public GuiComponent removeChild(GuiComponent comp)
|
|
{
|
|
comp.onClosed();
|
|
children.remove(comp);
|
|
box.removeChild(comp.getBox());
|
|
if(comp instanceof IButtonComponent)
|
|
{
|
|
owner.removeButtonListener((IButtonComponent)comp);
|
|
}
|
|
if(comp instanceof IKeyComponent)
|
|
{
|
|
owner.removeKeyListener((IKeyComponent)comp);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
public GuiComponent removeChildren()
|
|
{
|
|
for(GuiComponent comp : children)
|
|
{
|
|
comp.onClosed();
|
|
if(comp instanceof IButtonComponent)
|
|
{
|
|
owner.removeButtonListener((IButtonComponent)comp);
|
|
}
|
|
if(comp instanceof IKeyComponent)
|
|
{
|
|
owner.removeKeyListener((IKeyComponent)comp);
|
|
}
|
|
}
|
|
children.clear();
|
|
box.clearChildren();
|
|
return this;
|
|
}
|
|
|
|
public IGuiBox addBox(IGuiBox box)
|
|
{
|
|
this.box.addChild(box);
|
|
return box;
|
|
}
|
|
|
|
public GuiComponent removeBox(IGuiBox box)
|
|
{
|
|
this.box.removeChild(box);
|
|
return this;
|
|
}
|
|
|
|
public final GuiComponent addUserActionListener(Consumer<GuiComponent> listener)
|
|
{
|
|
return addListener(listener, GuiComponent.LISTENER_USER_ACTION);
|
|
}
|
|
|
|
public final GuiComponent addUserActionListener(Runnable listener)
|
|
{
|
|
return addListener(listener, GuiComponent.LISTENER_USER_ACTION);
|
|
}
|
|
|
|
public final GuiComponent addChangeListener(Consumer<GuiComponent> listener)
|
|
{
|
|
return addListener(listener, GuiComponent.LISTENER_ON_CHANGE);
|
|
}
|
|
|
|
public final GuiComponent addChangeListener(Runnable listener)
|
|
{
|
|
return addListener(listener, GuiComponent.LISTENER_ON_CHANGE);
|
|
}
|
|
|
|
public final GuiComponent addCloseListener(Consumer<GuiComponent> listener)
|
|
{
|
|
return addListener(listener, GuiComponent.LISTENER_CLOSED);
|
|
}
|
|
|
|
public final GuiComponent addCloseListener(Runnable listener)
|
|
{
|
|
return addListener(listener, GuiComponent.LISTENER_CLOSED);
|
|
}
|
|
|
|
public final GuiComponent addListener(Runnable runnable, int index)
|
|
{
|
|
listeners[index].add(T -> runnable.run());
|
|
return this;
|
|
}
|
|
|
|
public final GuiComponent addListener(Consumer<GuiComponent> listener, int index)
|
|
{
|
|
listeners[index].add(listener);
|
|
return this;
|
|
}
|
|
|
|
protected final void notifyListeners(int index)
|
|
{
|
|
if(listeners[index].size() > 0)
|
|
{
|
|
for(Consumer<GuiComponent> comp : listeners[index])
|
|
{
|
|
comp.accept(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
public final GuiComponent removeUserActionListener(Consumer<GuiComponent> listener)
|
|
{
|
|
return removeListener(listener, GuiComponent.LISTENER_USER_ACTION);
|
|
}
|
|
|
|
public final GuiComponent removeChangeListener(Consumer<GuiComponent> listener)
|
|
{
|
|
return removeListener(listener, GuiComponent.LISTENER_ON_CHANGE);
|
|
}
|
|
|
|
public final GuiComponent removeCloseListener(Consumer<GuiComponent> listener)
|
|
{
|
|
return removeListener(listener, GuiComponent.LISTENER_CLOSED);
|
|
}
|
|
|
|
public final GuiComponent removeListener(Consumer<GuiComponent> listener, int index)
|
|
{
|
|
listeners[index].remove(listener);
|
|
return this;
|
|
}
|
|
|
|
public GuiComponent moveComponent(float x, float y)
|
|
{
|
|
if(x == 0F && y == 0F || constraints != null) return this;
|
|
box.move(x, y);
|
|
onComponentChanged(false);
|
|
return this;
|
|
}
|
|
|
|
public GuiComponent setComponentPosition(float x, float y)
|
|
{
|
|
if(box.getBaseX() == x && box.getBaseY() == y || constraints != null) return this;
|
|
box.setXY(x, y);
|
|
onComponentChanged(false);
|
|
return this;
|
|
}
|
|
|
|
public GuiComponent resizeComponent(float moveX, float moveY)
|
|
{
|
|
if(moveX == 0F && moveY == 0F || constraints != null) return this;
|
|
box.grow(moveX, moveY);
|
|
onComponentChanged(true);
|
|
return this;
|
|
}
|
|
|
|
public GuiComponent setComponentBounds(float width, float height)
|
|
{
|
|
if(box.getBaseWidth() == width && box.getBaseHeight() == height || constraints != null) return this;
|
|
box.setBounds(width, height);
|
|
onComponentChanged(true);
|
|
return this;
|
|
}
|
|
|
|
public final void onComponentChanged(boolean repaint)
|
|
{
|
|
if(owner == null) return;
|
|
if(isFlagSet(FLAG_MASS_CHANGE))
|
|
{
|
|
changed = true;
|
|
massRepaint |= repaint;
|
|
return;
|
|
}
|
|
massRepaint = false;
|
|
changed = false;
|
|
if(constraints != null)
|
|
{
|
|
constraints.onComponentChanged();
|
|
if(animation != null) animation.applyValues(false);
|
|
}
|
|
box.onChanged();
|
|
totalZ = 0F;
|
|
GuiComponent zComp = this;
|
|
while(zComp != null)
|
|
{
|
|
totalZ += 0.01F + zComp.getZOffset();
|
|
zComp = zComp.parent;
|
|
}
|
|
notifyListeners(LISTENER_ON_CHANGE);
|
|
updateState();
|
|
if(repaint) repaint();
|
|
if(children.isEmpty()) return;
|
|
for(GuiComponent comp : children)
|
|
{
|
|
comp.onComponentChanged(repaint);
|
|
}
|
|
}
|
|
|
|
protected void updateState()
|
|
{
|
|
|
|
}
|
|
|
|
protected void repaint()
|
|
{
|
|
|
|
}
|
|
|
|
public final void onFixedUpdate()
|
|
{
|
|
if(fixedUpdateSelf()) fixedUpdateChildren();
|
|
}
|
|
|
|
public final void onUpdate(int mouseX, int mouseY, float particalTicks)
|
|
{
|
|
if(animation != null) animation.update(particalTicks);
|
|
if(updateSelf(mouseX, mouseY, particalTicks)) updateChildren(mouseX, mouseY, particalTicks);
|
|
}
|
|
|
|
protected void onPreRender()
|
|
{
|
|
|
|
}
|
|
|
|
public final void onRender(int mouseX, int mouseY, float particalTicks)
|
|
{
|
|
if(customRenderer != null)
|
|
{
|
|
customRenderer.onPreRender(this);
|
|
getRenderer().setVisibility(totalVisibility).setBrightness(brightness);
|
|
if(customRenderer.render(this)) renderChildren(mouseX, mouseY, particalTicks);
|
|
customRenderer.onPostRender(this);
|
|
getRenderer().resetEffects();
|
|
}
|
|
else
|
|
{
|
|
onPreRender();
|
|
getRenderer().setVisibility(totalVisibility).setBrightness(brightness);
|
|
if(renderSelf(mouseX, mouseY, particalTicks)) renderChildren(mouseX, mouseY, particalTicks);
|
|
onPostRender();
|
|
getRenderer().resetEffects();
|
|
}
|
|
if(getGui() instanceof GuiScreenBase)
|
|
{
|
|
((GuiScreenBase)getGui()).drawBox(this);
|
|
}
|
|
}
|
|
|
|
protected void onPostRender()
|
|
{
|
|
|
|
}
|
|
|
|
protected boolean fixedUpdateSelf()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
protected boolean updateSelf(int mouseX, int mouseY, float particalTicks)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
protected boolean renderSelf(int mouseX, int mouseY, float particalTicks)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
public void collectTooltips(int mouseX, int mouseY, float particalTicks, Map<UUID, GuiComponent> collector)
|
|
{
|
|
if(isParentVisible())
|
|
{
|
|
if(isHovered(mouseX, mouseY))
|
|
{
|
|
tooltips.merge(collector);
|
|
}
|
|
if(children.size() > 0)
|
|
{
|
|
for(GuiComponent entry : children)
|
|
{
|
|
entry.collectTooltips(mouseX, mouseY, particalTicks, collector);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void fixedUpdateChildren()
|
|
{
|
|
for(GuiComponent entry : children)
|
|
{
|
|
if(entry.isVisible())
|
|
{
|
|
entry.onFixedUpdate();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void updateChildren(int mouseX, int mouseY, float particalTicks)
|
|
{
|
|
for(GuiComponent entry : children)
|
|
{
|
|
if(entry.isVisible())
|
|
{
|
|
entry.onUpdate(mouseX, mouseY, particalTicks);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void renderChildren(int mouseX, int mouseY, float particalTicks)
|
|
{
|
|
for(GuiComponent entry : children)
|
|
{
|
|
if(!entry.isManualRender() && entry.isVisible() && (!isTestingScissors() || isInScissors(entry.getBox())))
|
|
{
|
|
float zOffset = entry.getZOffset() + 0.01F;
|
|
getRenderer().push();
|
|
getRenderer().translate(0F, 0F, zOffset);
|
|
entry.onPreRender();
|
|
entry.onRender(mouseX, mouseY, particalTicks);
|
|
entry.onPostRender();
|
|
getRenderer().translate(0F, 0F, -zOffset);
|
|
getRenderer().pop();
|
|
}
|
|
}
|
|
}
|
|
|
|
public Animator getAnimator()
|
|
{
|
|
if(animation == null)
|
|
{
|
|
animation = new Animator(this);
|
|
}
|
|
return animation;
|
|
}
|
|
|
|
public <T> T cast()
|
|
{
|
|
return (T)this;
|
|
}
|
|
|
|
public <T> T cast(Class<T> clz)
|
|
{
|
|
return (T)this;
|
|
}
|
|
|
|
public <T> T tryCast(Class<T> clz)
|
|
{
|
|
return clz.isInstance(this) ? (T)this : null;
|
|
}
|
|
|
|
public GuiComponent getTopComponent()
|
|
{
|
|
GuiComponent top = this;
|
|
while(top.parent != null)
|
|
{
|
|
top = top.parent;
|
|
}
|
|
return top;
|
|
}
|
|
|
|
protected void requestFocus()
|
|
{
|
|
getGui().requestComponentFocus(this);
|
|
}
|
|
|
|
protected boolean isFocused()
|
|
{
|
|
return getGui().isComponentFocused(this);
|
|
}
|
|
|
|
protected boolean isFocusedOrChilds()
|
|
{
|
|
return isFocused() || isChildFocused();
|
|
}
|
|
|
|
protected boolean isChildFocused()
|
|
{
|
|
for(GuiComponent comp : children)
|
|
{
|
|
if(comp.isFocusedOrChilds())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
protected UIRenderer getRenderer()
|
|
{
|
|
return owner.getRenderer();
|
|
}
|
|
|
|
protected Window getWindow()
|
|
{
|
|
return owner.getWindow();
|
|
}
|
|
|
|
protected boolean isSelect(int keyCode)
|
|
{
|
|
return keyCode == GLFW.GLFW_KEY_A && Keyboard.isCtrlDown() && !Keyboard.isShiftDown() && !Keyboard.isAltDown();
|
|
}
|
|
|
|
protected boolean isCopy(int keyCode)
|
|
{
|
|
return keyCode == GLFW.GLFW_KEY_C && Keyboard.isCtrlDown() && !Keyboard.isShiftDown() && !Keyboard.isAltDown();
|
|
}
|
|
|
|
protected boolean isPaste(int keyCode)
|
|
{
|
|
return keyCode == GLFW.GLFW_KEY_V && Keyboard.isCtrlDown() && !Keyboard.isShiftDown() && !Keyboard.isAltDown();
|
|
}
|
|
|
|
protected boolean isCut(int keyCode)
|
|
{
|
|
return keyCode == GLFW.GLFW_KEY_X && Keyboard.isCtrlDown() && !Keyboard.isShiftDown() && !Keyboard.isAltDown();
|
|
}
|
|
|
|
protected final float getBrightness(int mouseX, int mouseY)
|
|
{
|
|
return isEnabled() ? (isHovered(mouseX, mouseY) ? 0.7F : 1F) : 0.5F;
|
|
}
|
|
|
|
public final float getActiveBrightness()
|
|
{
|
|
return isEnabled() ? 1F : 0.5F;
|
|
}
|
|
|
|
public long getGlobalClock()
|
|
{
|
|
return getGui().getGlobalClock();
|
|
}
|
|
|
|
protected final void bindCursor(AssetLocation location)
|
|
{
|
|
Cursor.INSTANCE.bindCursor(location, getWindow());
|
|
}
|
|
|
|
protected final void clearCursor()
|
|
{
|
|
Cursor.INSTANCE.clearCursor(getWindow());
|
|
}
|
|
|
|
protected final void enableScissors(Plane box)
|
|
{
|
|
enableScissors(box.getMinX(), box.getMinY(), box.getWidth(), box.getHeight());
|
|
}
|
|
|
|
protected final void enableScissors(IGuiBox box)
|
|
{
|
|
enableScissors((int)box.getMinX(), (int)box.getMinY(), (int)box.getWidth(), (int)box.getHeight());
|
|
}
|
|
|
|
protected final void enableScissorsBox(float minX, float minY, float maxX, float maxY)
|
|
{
|
|
enableScissors((int)minX, (int)minY, (int)(maxX - minX), (int)(maxY - minY));
|
|
}
|
|
|
|
protected final void enableScissors(float x, float y, float width, float height)
|
|
{
|
|
enableScissors((int)x, (int)y, (int)width, (int)height);
|
|
}
|
|
|
|
protected final void enableScissors(int x, int y, int width, int height)
|
|
{
|
|
getRenderer().flush();
|
|
int bottom = y + height;
|
|
Window window = owner.getWindow();
|
|
Vec2d vec = owner.getUIManager().res.getScaleVec();
|
|
GLUtils.TESTER.enableScissors((int)(x * vec.getX()), (int)(window.getHeight() - bottom * vec.getY()), (int)(width * vec.getX()), (int)(height * vec.getY()));
|
|
}
|
|
|
|
protected final boolean isInScissors(Plane box)
|
|
{
|
|
return isInScissors(box.getMinX(), box.getMinY(), box.getWidth(), box.getHeight());
|
|
}
|
|
|
|
protected final boolean isInScissors(IGuiBox box)
|
|
{
|
|
return isInScissors((int)box.getMinX(), (int)box.getMinY(), (int)box.getWidth(), (int)box.getHeight());
|
|
}
|
|
|
|
protected final boolean isInScissors(float minX, float minY, float maxX, float maxY)
|
|
{
|
|
return isInScissors((int)minX, (int)minY, (int)(maxX - minX), (int)(maxY - minY));
|
|
}
|
|
|
|
protected final boolean isInScissors(int x, int y, int width, int height)
|
|
{
|
|
int bottom = y + height;
|
|
Window window = owner.getWindow();
|
|
Vec2d vec = owner.getUIManager().res.getScaleVec();
|
|
return GLUtils.TESTER.isInScissors((int)(x * vec.getX()), (int)(window.getHeight() - bottom * vec.getY()), (int)(width * vec.getX()), (int)(height * vec.getY()));
|
|
}
|
|
|
|
public final void disableScissors()
|
|
{
|
|
getRenderer().flush();
|
|
GLUtils.TESTER.disableScissors();
|
|
}
|
|
|
|
class KeyBindAction implements IKeyComponent
|
|
{
|
|
int key;
|
|
int mod;
|
|
boolean block;
|
|
UUID tooltip = UUID.randomUUID();
|
|
|
|
public KeyBindAction(int key, int mod, boolean block)
|
|
{
|
|
this.key = key;
|
|
this.mod = mod;
|
|
this.block = block;
|
|
}
|
|
|
|
public UUID getTooltip()
|
|
{
|
|
return tooltip;
|
|
}
|
|
|
|
@Override
|
|
public boolean isAcceptingInput()
|
|
{
|
|
return isAnyFlagSet(FLAG_ALWAYS_CLICKABLE | FLAG_ENABLED);
|
|
}
|
|
|
|
@Override
|
|
public boolean isBlockingMovement()
|
|
{
|
|
return block;
|
|
}
|
|
|
|
@Override
|
|
public boolean isPopup()
|
|
{
|
|
return isPopupButton(GuiComponent.this) || isPopupButton(getTopComponent());
|
|
}
|
|
|
|
@Override
|
|
public boolean hasChildPopups()
|
|
{
|
|
return hasPopups();
|
|
}
|
|
|
|
private boolean isPopupButton(GuiComponent comp)
|
|
{
|
|
return comp instanceof IButtonComponent ? ((IButtonComponent)comp).isPopup() : false;
|
|
}
|
|
|
|
@Override
|
|
public boolean onKeyPressed(int key)
|
|
{
|
|
if(key == this.key && ModType.isActive(mod))
|
|
{
|
|
return onUserKey();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
}
|
|
}
|