ScissorsHandlerImpl.java 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*
  2. * This file is part of Cloth Config.
  3. * Copyright (C) 2020 - 2021 shedaniel
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 3 of the License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public License
  16. * along with this program; if not, write to the Free Software Foundation,
  17. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. */
  19. package me.shedaniel.clothconfig2.impl;
  20. import com.google.common.collect.Lists;
  21. import com.mojang.blaze3d.platform.Window;
  22. import me.shedaniel.clothconfig2.api.ScissorsHandler;
  23. import me.shedaniel.clothconfig2.api.ScissorsScreen;
  24. import me.shedaniel.math.Rectangle;
  25. import net.fabricmc.api.EnvType;
  26. import net.fabricmc.api.Environment;
  27. import net.minecraft.client.Minecraft;
  28. import org.jetbrains.annotations.ApiStatus;
  29. import org.lwjgl.opengl.GL11;
  30. import java.util.Collections;
  31. import java.util.List;
  32. @Environment(EnvType.CLIENT)
  33. @ApiStatus.Internal
  34. public final class ScissorsHandlerImpl implements ScissorsHandler {
  35. @ApiStatus.Internal
  36. public static final ScissorsHandler INSTANCE = new ScissorsHandlerImpl();
  37. // TODO: should this be reimplemented?
  38. /*static {
  39. Executor.runIf(() -> FabricLoader.getInstance().isModLoaded("notenoughcrashes"), () -> () -> {
  40. try {
  41. Class.forName("fudge.notenoughcrashes.api.NotEnoughCrashesApi").getDeclaredMethod("onEveryCrash", Runnable.class).invoke(null, (Runnable) () -> {
  42. try {
  43. ScissorsHandler.INSTANCE.clearScissors();
  44. } catch (Throwable t) {
  45. ClothConfigInitializer.LOGGER.error("[ClothConfig] Failed clear scissors on game crash!", t);
  46. }
  47. });
  48. } catch (Throwable throwable) {
  49. throwable.printStackTrace();
  50. }
  51. });
  52. }*/
  53. private final List<Rectangle> scissorsAreas;
  54. public ScissorsHandlerImpl() {
  55. this.scissorsAreas = Lists.newArrayList();
  56. }
  57. @Override
  58. public void clearScissors() {
  59. scissorsAreas.clear();
  60. applyScissors();
  61. }
  62. @Override
  63. public List<Rectangle> getScissorsAreas() {
  64. return Collections.unmodifiableList(scissorsAreas);
  65. }
  66. @Override
  67. public void scissor(Rectangle rectangle) {
  68. scissorsAreas.add(rectangle);
  69. applyScissors();
  70. }
  71. @Override
  72. public void removeLastScissor() {
  73. if (!scissorsAreas.isEmpty())
  74. scissorsAreas.remove(scissorsAreas.size() - 1);
  75. applyScissors();
  76. }
  77. @Override
  78. public void applyScissors() {
  79. if (!scissorsAreas.isEmpty()) {
  80. Rectangle r = scissorsAreas.get(0).clone();
  81. for (int i = 1; i < scissorsAreas.size(); i++) {
  82. Rectangle r1 = scissorsAreas.get(i);
  83. if (r.intersects(r1)) {
  84. r.setBounds(r.intersection(r1));
  85. } else {
  86. if (Minecraft.getInstance().screen instanceof ScissorsScreen)
  87. _applyScissor(((ScissorsScreen) Minecraft.getInstance().screen).handleScissor(null));
  88. else _applyScissor(null);
  89. return;
  90. }
  91. }
  92. r.setBounds(Math.min(r.x, r.x + r.width), Math.min(r.y, r.y + r.height), Math.abs(r.width), Math.abs(r.height));
  93. if (Minecraft.getInstance().screen instanceof ScissorsScreen)
  94. _applyScissor(((ScissorsScreen) Minecraft.getInstance().screen).handleScissor(r));
  95. else _applyScissor(r);
  96. } else {
  97. if (Minecraft.getInstance().screen instanceof ScissorsScreen)
  98. _applyScissor(((ScissorsScreen) Minecraft.getInstance().screen).handleScissor(null));
  99. else _applyScissor(null);
  100. }
  101. }
  102. public void _applyScissor(Rectangle r) {
  103. if (r != null && !r.isEmpty()) {
  104. Window window = Minecraft.getInstance().getWindow();
  105. double scaleFactor = window.getGuiScale();
  106. GL11.glEnable(GL11.GL_SCISSOR_TEST);
  107. GL11.glScissor((int) (r.x * scaleFactor), (int) ((window.getGuiScaledHeight() - r.height - r.y) * scaleFactor), (int) (r.width * scaleFactor), (int) (r.height * scaleFactor));
  108. } else
  109. GL11.glDisable(GL11.GL_SCISSOR_TEST);
  110. }
  111. }