[SOLVED] Problems with imgui

/*
 * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
 * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
 */
package jmeimgui;

import static com.jme3.renderer.opengl.GL.GL_LINEAR;
import static com.jme3.renderer.opengl.GL.GL_RGBA;
import static com.jme3.renderer.opengl.GL.GL_TEXTURE_2D;
import static com.jme3.renderer.opengl.GL.GL_TEXTURE_MAG_FILTER;
import static com.jme3.renderer.opengl.GL.GL_TEXTURE_MIN_FILTER;
import static com.jme3.renderer.opengl.GL.GL_UNSIGNED_BYTE;
import com.jme3.system.JmeContext;
import com.jme3.system.JmeSystem;
import com.jme3.system.Platform;
import com.jme3.system.lwjgl.LwjglWindow;
import imgui.ImFont;
import imgui.ImFontConfig;
import imgui.ImFontGlyphRangesBuilder;
import imgui.ImGui;
import imgui.ImGuiIO;
import imgui.flag.ImGuiConfigFlags;
import imgui.gl3.ImGuiImplGl3;
import imgui.glfw.ImGuiImplGlfw;
import imgui.type.ImInt;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Objects;
import org.lwjgl.glfw.GLFW;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_BINDING_2D;
import static org.lwjgl.opengl.GL11.glGenTextures;
import static org.lwjgl.opengl.GL11.glTexImage2D;
import static org.lwjgl.opengl.GL11.glTexParameteri;
import static org.lwjgl.opengl.GL11C.glBindTexture;
import static org.lwjgl.opengl.GL11C.glGetInteger;

/**
 *
 * @author Icyboxs
 */
public class JmeImGui {
    
    
    private final ImGuiImplGlfw imGuiGlfw = new ImGuiImplGlfw();
    private final ImGuiImplGl3 imGuiGl3 = new ImGuiImplGl3();
    private long windowHandle;
        /**
     * Method called at the beginning of the main cycle.
     * It starts a new ImGui frame.
     */
    public void startFrame() {
        imGuiGlfw.newFrame();
        ImGui.newFrame();
    }

    /**
     * Method called in the end of the main cycle.
     * It renders ImGui to prepare an updated frame.
     */
    public void endFrame() {
        ImGui.render();
        imGuiGl3.renderDrawData(ImGui.getDrawData());

        if (ImGui.getIO().hasConfigFlags(ImGuiConfigFlags.ViewportsEnable)) {
            final long backupWindowPtr = GLFW.glfwGetCurrentContext();
            ImGui.updatePlatformWindows();
            ImGui.renderPlatformWindowsDefault();
            GLFW.glfwMakeContextCurrent(backupWindowPtr);
        }

    }
    /**
     * Method to dispose all used ImGui resources.
     */
    public void dispose() {
        imGuiGl3.dispose();
        imGuiGlfw.dispose();
        ImGui.destroyContext();
    }
    
    public void init(JmeContext context, Runnable beforeInit) {
        windowHandle = ((LwjglWindow)context).getWindowHandle();
        ImGui.createContext();
        if (beforeInit != null) beforeInit.run();
        imGuiGlfw.init(windowHandle, true);
        imGuiGl3.init(decideGlslVersion());
    }
    
    public void init(JmeContext context) {
        init(context, null);
    }
    

    
      protected String decideGlslVersion() {
        return JmeSystem.getPlatform().getOs() == Platform.Os.MacOS ? "#version 150" : "#version 130";
    }
      
    public void refreshFontTexture() {
        ImInt fontW = new ImInt();
        ImInt fontH = new ImInt();
        ImGuiIO imGuiIO = ImGui.getIO();
        ByteBuffer fontData = imGuiIO.getFonts().getTexDataAsRGBA32(fontW, fontH);
        int originalTexture = glGetInteger(GL_TEXTURE_BINDING_2D);
        int fontTexture = glGenTextures();
        glBindTexture(GL_TEXTURE_2D, fontTexture);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fontW.get(), fontH.get(), 0, GL_RGBA, GL_UNSIGNED_BYTE, fontData);
        imGuiIO.getFonts().setTexID(fontTexture);
        glBindTexture(GL_TEXTURE_2D, originalTexture);
    }
}

I use this code to initialize imgui

I don’t know why I can only initialize in class Main extends SimpleApplication

If I initialize in the class extends BaseAppState then imgui is not visible on the screen and no error is generated.

Writing an imgui window in simpleRender

    @Override
    public void simpleRender(RenderManager rm) {

        jmeimGui.startFrame();
        if (ImGui.begin("你好")) {
            if (ImGui.beginMenuBar()) {
            }
            if (ImGui.sliderFloat("X", imGuidata.getLocationX(), -1000f, 1000f)) {
            }
            if (ImGui.sliderFloat("Y", imGuidata.getLocationY(), -1000f, 1000f)) {
            }
            if (ImGui.sliderFloat("Z", imGuidata.getLocationZ(), -1000, 1000f)) {
            }
        }
        ImGui.end();
        jmeimGui.endFrame();

    }

Writing an imgui window in render

    @Override
    public void render(RenderManager rm) {


    UIjmeimGui.startFrame();

  
    if (ImGui.begin("Test Window")) {
        ImGui.text("Hello, ImGui!");
        if (ImGui.button("Click Me")) {
            System.out.println("Button clicked!");
        }
    }
    ImGui.end();

 
    UIjmeimGui.endFrame();
    }

The imgui written in the render in extends BaseAppState will not be displayed in the screen.

what does the opengl profiler say?
you don’t show where you are actually initializing the imgui.

1 Like

I found the problem.

startFrame();


endFrame();

startFrame(); and endFrame(); can only occur once per frame cycle of jme

/*
 * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
 * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Interface.java to edit this template
 */
package GUI.imgui;

/**
 *
 * @author icyboxs
 */
public interface imguiComponent {
    void execute();
    public String getComponentName();
}

/*
 * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
 * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
 */
package GUI.imgui;

import java.util.HashMap;
import java.util.Map;

/**
 *
 * @author icyboxs
 */
public class ComponentRegistrar {
    private final Map<String, imguiComponent> componentMap = new HashMap<>();
    
    // 私有构造方法实现单例
    private ComponentRegistrar() {}
    
    private static class Holder {
        private static final ComponentRegistrar INSTANCE = new ComponentRegistrar();
    }
    
    public static ComponentRegistrar getInstance() {
        return Holder.INSTANCE;
    }
    
    public void register(imguiComponent component) {
        componentMap.put(component.getComponentName(), component);
    }
    
    public imguiComponent getComponent(String name) {
        return componentMap.get(name);
    }
    
    public void executeAll() {
        componentMap.values().forEach(imguiComponent::execute);
    }
}

Run the contents of the imgui in main using component registration
So, my problem is solved. I hope this helps someone else.

2 Likes