ice1000 / jimgui

:sparkling_heart: Pure Java binding for dear-imgui
Apache License 2.0
186 stars 13 forks source link

Using jimgui for creation of game editor #10

Closed wrymn closed 6 years ago

wrymn commented 6 years ago

May I ask, in what state jimgui currently is?

We are planning to create game editor on top of our existing java game SDK. Since I am the project lead, I was looking into best ways to create architecture for such a system.

I really like your port, its ease of use, texture loading etc.

Do you think this port would be capable of handling full game editor on top of existing framework?

ice1000 commented 6 years ago

Short answer: it's production ready if you just want to use the imgui api only, these includes:

To interact with the low-level API of the rendering framework, you need some hacking: There's a nativeObjectPtr member in JImGui (as well as many other classes), they're pointers to a C struct/class.

wrymn commented 6 years ago

Thank you for the state explanation.

Would you give us support if it was needed? If there would be any feature request (e.g. Text input), is there an active development for such requests?

If there would be any tech questions from my side, would you have time to answer them in the future? Thank you!

ice1000 commented 6 years ago

There's just one problem: it's using DirectX9 on Windows, and if your game framework is using OpenGL on windows and you want jimgui to use OpenGL on Windows too, some extra work is needed.

Take a look at the CMake project under /core/jni, which controls the compilation of the C++ port of jimgui. You can see that it detects the OS and select either dx9_impl.cpp (on win) or glfw_impl.cpp (on *nix) to be included in the native library. I did this separation because I failed to install glfw on AppVeyor. Why didn't I just use a windows computer with glfw+ogl installed to compile the same code (aka glfw_impl.cpp) works on Linux? Because I don't have any windows devices and it's really painful to debug a dx application without a windows device!

After building the dll using glfw_impl.cpp, replace JniLoader.load() with System.load(full path to the dll), and that's it!

ice1000 commented 6 years ago

Would you give us support if it was needed?

Yes! I'd like to! I created this project because I want to make a code editor, and text input is obviously a just need. It will be added soon even without your request. I'd like to listen to opinions of real users and improve my project. BTW isn't this what I'm doing now :smirk:

Is there would be any feature request?

Yes, if it's not tough work (tough work refers to something like implementing new widgets, etc. These should be a feature request to imgui, not jimgui). I'm syncing the newest changes of imgui in its master branch about once a day and when there's new APIs/bug fixes I'll create a new version and upload it onto jcenter.

is there an active development for such requests?

image

If there would be any tech questions from my side, would you have time to answer them in the future?

Yes, but first read the javadoc and the docs of imgui. The javadoc of JIm*Gen is generated, I made a naive imgui.h parser to copy the comments. If you've found any issue, open an issue.

wrymn commented 6 years ago

Yes our framework does run on OpenGL, specifically using GLFW library.

I will try to recompile with ogl as you suggested and see if it works.


I love to hear this is in active development and its your passion :D

The "final" obstacle I have to overcome is, if it is even possible to add imgui on top of our framework.

From what I understand:

  1. We have to start our framework from the new editor code
  2. Let the framework initialize opengl and run
  3. This will create its window and render game into. This is something where I get kinda lost.

Is it even possible to put imgui into existing GLFW window from our framework? In other case, is it possible to render it only to single "window" of imgui? Kinda like you see in Unity or Unreal.

I have tries to find answers to this question, with no luck.

ice1000 commented 6 years ago

I have to go asleep now since it's 3:46 a.m. on my time zone. I'll answer this tomorrow.

I believe it's possible, but this requires me to refactor the design of the API, which I've mentioned in #9 .

These functions shows how an imgui window is initialized on Linux:

#define STR_J2C(value) \
reinterpret_cast<Ptr<const char>> ((value))

#define PTR_C2J(value) \
reinterpret_cast<jlong> ((value))

#define PTR_J2C(type, value) \
reinterpret_cast<Ptr<type>> ((value))

JNIEXPORT auto JNICALL
Java_org_ice1000_jimgui_JImGui_allocateNativeObjects(
        JNIEnv *env, jclass, jint width, jint height, jlong fontAtlas, jbyteArray _title) -> jlong {
    glfwSetErrorCallback(glfw_error_callback);
    if (!glfwInit()) return 0L;
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#if __APPLE__
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
    __JNI__FUNCTION__INIT__
    __get(Byte, title)
    Ptr<GLFWwindow> window = glfwCreateWindow(width, height, STR_J2C(title), nullptr, nullptr);
    __release(Byte, title)
    __JNI__FUNCTION__CLEAN__
    glfwMakeContextCurrent(window);
    // Enable vsync
    glfwSwapInterval(1);
    gl3wInit();

    // Setup Dear ImGui binding
    IMGUI_CHECKVERSION();
    ImGui::CreateContext(PTR_J2C(ImFontAtlas, fontAtlas));
    ImGuiIO &io = ImGui::GetIO();
    (void) io;
    // Enable Keyboard Controls
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
    ImGui_ImplGlfw_InitForOpenGL(window, true);
    ImGui_ImplOpenGL3_Init();
    return PTR_C2J(window);
}

JNIEXPORT void JNICALL
JavaCritical_org_ice1000_jimgui_JImGui_deallocateNativeObjects(jlong nativeObjectPtr) {
    auto *window = PTR_J2C(GLFWwindow, nativeObjectPtr);
    ImGui_ImplOpenGL3_Shutdown();
    ImGui_ImplGlfw_Shutdown();
    ImGui::DestroyContext();

    glfwDestroyWindow(window);
    glfwTerminate();
}

What to do next is to provide an optional initialization with an already created window pointer.

wrymn commented 6 years ago

Thank you, see you tomorrow.

I can get window pointer from GLFW.glfwGetCurrentContext() I hope that is enough to "steal" the window and render it to imgui panel.

So we can create imgui window, let our framework create its window, steal window context and put it into imgui. Is it that simple? :D

Here is an example from imgui github page. There are several editor windows, but one of them renders the game. image

ice1000 commented 6 years ago

BTW, I've just added text input...

ice1000 commented 6 years ago

I hope that is enough to "steal" the window and render it to imgui panel.

I don't know much about OpenGL or GLFW, maybe you should ask a question on this repo.

If you want to get the window pointer, you can also access the nativeObjectPtr member of JImGui with reflection (it's package-private, by design), whose value is the pointer to the GLFWwindow.

wrymn commented 6 years ago

Thank you for the input. I will ask in their forums if technically something like that could be done.

If we manage somehow to render our games inside imgui window, then we can start using it.

Just a side question, can two OS windows interact with each other? Lets say one window will be window from our framework, the second will be from imgui. Could we simulate drag & drop functionality?

ice1000 commented 6 years ago

Of course, at least on Windows. JavaFX supports that.