aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/cc/polyfrost/oneconfig/lwjgl/BlurHandler.java
blob: 7fc725ad255abbd88ba079cb775e4f7a12b50653 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
package cc.polyfrost.oneconfig.lwjgl;

import cc.polyfrost.oneconfig.gui.OneConfigGui;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.renderer.EntityRenderer;
import net.minecraft.client.shader.Shader;
import net.minecraft.client.shader.ShaderGroup;
import net.minecraft.client.shader.ShaderUniform;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.GuiOpenEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.lang.reflect.Field;
import java.util.List;

/**
 * An implementation of the BlurMC mod by tterrag1098.
 * <p>
 * For the original source see https://github.com/tterrag1098/Blur/blob/1.8.9/src/main/java/com/tterrag/blur/Blur.java
 * For the public license, see https://github.com/tterrag1098/Blur/blob/1.8.9/LICENSE
 * <p>
 * License available under https://github.com/boomboompower/ToggleChat/blob/master/src/main/resources/licenses/BlurMC-License.txt
 *
 * @author tterrag1098, boomboompower
 * <p>
 * Taken from ToggleChat
 * https://github.com/boomboompower/ToggleChat/blob/master/LICENSE
 */
public class BlurHandler {
    private final ResourceLocation blurShader = new ResourceLocation("shaders/post/fade_in_blur.json");
    private final Logger logger = LogManager.getLogger("OneConfig - Blur");
    private final Minecraft mc = Minecraft.getMinecraft();
    private Field shaderList = null;

    private long start;
    private float lastProgress = 0;

    public static BlurHandler INSTANCE = new BlurHandler();

    /**
     * Simply initializes the blur mod so events are properly handled by forge.
     */
    public void load() {
        MinecraftForge.EVENT_BUS.register(this);
    }

    @SubscribeEvent
    public void onGuiChange(GuiOpenEvent event) {
        reloadBlur(event.gui);
    }

    @SubscribeEvent
    public void onRenderTick(final TickEvent.RenderTickEvent event) {
        this.mc.mcProfiler.startSection("blur");

        if (event.phase != TickEvent.Phase.END) {
            this.mc.mcProfiler.endSection();
            return;
        }

        // Only blur on our own menus
        if (this.mc.currentScreen == null) {
            this.mc.mcProfiler.endSection();
            return;
        }

        // Only update the shader if one is active
        if (!this.mc.entityRenderer.isShaderActive()) {
            this.mc.mcProfiler.endSection();
            return;
        }

        float progress = getBlurStrengthProgress();

        // If the new progress value matches the old one this
        // will skip the frame update, which (hopefully) resolves the issue
        // with the heavy computations after the "animation" is complete.
        if (progress == this.lastProgress) {
            this.mc.mcProfiler.endSection();
            return;
        }

        // Store it for the next iteration!
        this.lastProgress = progress;

        // This is hilariously bad, and could cause frame issues on low-end computers.
        // Why is this being computed every tick? Surely there is a better way?
        // This needs to be optimized.
        try {
            final List<Shader> listShaders = getShaderList();

            // Should not happen. Something bad happened.
            if (listShaders == null) {
                this.mc.mcProfiler.endSection();
                return;
            }

            // Iterate through the list of shaders.
            for (Shader shader : listShaders) {
                ShaderUniform su = shader.getShaderManager().getShaderUniform("Progress");

                if (su == null) {
                    continue;
                }

                // All this for this.
                su.set(progress);
            }
        } catch (IllegalArgumentException ex) {
            this.logger.error("An error.png occurred while updating OneConfig's blur. Please report this!", ex);
        }

        this.mc.mcProfiler.endSection();
    }

    /**
     * Activates/deactivates the blur in the current world if
     * one of many conditions are met, such as no current other shader
     * is being used, we actually have the blur setting enabled
     */
    public void reloadBlur(GuiScreen gui) {
        // Don't do anything if no world is loaded
        if (this.mc.theWorld == null) {
            return;
        }

        EntityRenderer er = this.mc.entityRenderer;

        // If a shader is not already active and the UI is
        // a one of ours, we should load our own blur!
        if (!er.isShaderActive() && gui instanceof OneConfigGui) {
            this.mc.entityRenderer.loadShader(this.blurShader);
            try {
                shaderList = ShaderGroup.class.getDeclaredField("listShaders");
                shaderList.setAccessible(true);
            } catch (NoSuchFieldException ignored) {
            }

            this.start = System.currentTimeMillis();

            // If a shader is active and the incoming UI is null or we have blur disabled, stop using the shader.
        } else if (er.isShaderActive() && (gui == null)) {
            String name = er.getShaderGroup().getShaderGroupName();

            // Only stop our specific blur ;)
            if (!name.endsWith("fade_in_blur.json")) {
                return;
            }

            er.stopUseShader();
            shaderList = null;
        }
    }

    /**
     * Returns the strength of the blur as determined by the duration the effect of the blur.
     * <p>
     * The strength of the blur does not go below 5.0F.
     */
    private float getBlurStrengthProgress() {
        return Math.min((System.currentTimeMillis() - this.start) / 50F, 5.0F);
    }

    private List<Shader> getShaderList() {
        if (shaderList == null) return null;
        try {
            return (List<Shader>) shaderList.get(this.mc.entityRenderer.getShaderGroup());
        } catch (IllegalAccessException ignored) {
            return null;
        }
    }
}