2022-09-04 21:21:24 +02:00
package io.gitlab.jfronny.inceptum.imgui ;
2021-10-30 22:05:24 +02:00
import imgui.ImGui ;
import imgui.ImGuiIO ;
import imgui.flag.ImGuiConfigFlags ;
import imgui.gl3.ImGuiImplGl3 ;
import imgui.glfw.ImGuiImplGlfw ;
2022-09-06 21:20:59 +02:00
import io.gitlab.jfronny.commons.log.* ;
2022-09-06 11:15:21 +02:00
import io.gitlab.jfronny.inceptum.common.model.inceptum.UpdateMetadata ;
2022-09-04 21:21:24 +02:00
import io.gitlab.jfronny.inceptum.imgui.window.MainWindow ;
import io.gitlab.jfronny.inceptum.launcher.LauncherEnv ;
import io.gitlab.jfronny.inceptum.common.* ;
import io.gitlab.jfronny.inceptum.imgui.window.Window ;
import io.gitlab.jfronny.inceptum.launcher.api.account.AccountManager ;
2022-10-27 20:54:55 +02:00
import io.gitlab.jfronny.inceptum.launcher.system.instance.InstanceList ;
2022-09-19 21:26:23 +02:00
import org.jetbrains.annotations.Nullable ;
import org.lwjgl.PointerBuffer ;
2022-09-04 21:21:24 +02:00
import org.lwjgl.glfw.* ;
2021-10-30 22:05:24 +02:00
import org.lwjgl.opengl.GL ;
import org.lwjgl.opengl.GL32 ;
import org.lwjgl.system.MemoryStack ;
import org.lwjgl.system.MemoryUtil ;
2022-09-19 21:26:23 +02:00
import org.lwjgl.util.tinyfd.TinyFileDialogs ;
2021-10-30 22:05:24 +02:00
import java.io.IOException ;
import java.io.InputStream ;
2022-09-04 21:21:24 +02:00
import java.net.URI ;
import java.net.URISyntaxException ;
2021-10-30 22:05:24 +02:00
import java.nio.IntBuffer ;
2022-09-19 21:26:23 +02:00
import java.nio.file.* ;
2022-02-06 16:00:14 +01:00
import java.util.* ;
2021-10-30 22:05:24 +02:00
2022-09-04 21:21:24 +02:00
public class GuiMain {
2022-09-06 21:20:59 +02:00
public static final MemoryLogger MEMLOG = new MemoryLogger ( " Inceptum " ) ;
2021-10-30 22:05:24 +02:00
public static final Set < Window > WINDOWS = new LinkedHashSet < > ( ) ;
private static final ImGuiImplGlfw imGuiGlfw = new ImGuiImplGlfw ( ) ;
private static final ImGuiImplGl3 imGuiGl3 = new ImGuiImplGl3 ( ) ;
/ * *
* Pointer to the native GLFW window .
* /
protected static long handle ;
private static String glslVersion = null ;
2022-09-04 21:21:24 +02:00
public static void main ( String [ ] args ) throws IOException {
2022-09-06 21:20:59 +02:00
LauncherEnv . initialize ( new GuiEnvBackend ( ) ) ;
2022-09-06 11:15:21 +02:00
Utils . LOGGER . info ( " Launching Inceptum v " + BuildMetadata . VERSION ) ;
2022-09-04 21:21:24 +02:00
Utils . LOGGER . info ( " Loading from " + MetaHolder . BASE_PATH ) ;
try {
2022-09-26 19:09:02 +02:00
showGui ( ) ;
2022-09-04 21:21:24 +02:00
} finally {
LauncherEnv . terminate ( ) ;
}
}
2022-09-26 19:09:02 +02:00
public static void showGui ( ) {
2022-09-06 21:20:59 +02:00
Logger . registerFactory ( name - > new CompoundLogger ( name , InceptumEnvironmentInitializer . defaultFactory ( name ) , MEMLOG ) ) ;
2022-09-06 11:15:21 +02:00
UpdateMetadata update = BuildMetadata . IS_PUBLIC ? Updater . getUpdate ( ) : null ;
2021-10-30 22:05:24 +02:00
AccountManager . loadAccounts ( ) ;
2022-01-18 18:43:39 +01:00
Utils . LOGGER . info ( " Initializing UI " ) ;
2022-01-04 23:32:05 +01:00
try {
2022-10-19 21:44:33 +02:00
InstanceList . forEach ( instance - > instance . mds ( ) . start ( ) ) ;
2022-01-04 23:32:05 +01:00
} catch ( IOException e ) {
2022-01-18 18:43:39 +01:00
Utils . LOGGER . error ( " Could not initialize MDS " ) ;
2022-01-04 23:32:05 +01:00
}
2021-11-11 17:59:35 +01:00
init ( ) ;
2022-09-04 21:21:24 +02:00
if ( update = = null ) {
WINDOWS . add ( new MainWindow ( ) ) ;
2022-09-06 14:55:36 +02:00
} else if ( MetaHolder . isWrapper ( ) ) {
2022-09-04 21:21:24 +02:00
LauncherEnv . showOkCancel ( " An update was found. Should it be installed automatically? " , " Update found " , ( ) - > {
try {
Updater . update ( update , true ) ;
exit ( ) ;
} catch ( IOException | URISyntaxException e ) {
LauncherEnv . showError ( " Could not download update " , e ) ;
}
} , ( ) - > WINDOWS . add ( new MainWindow ( ) ) ) ;
} else {
LauncherEnv . showOkCancel ( " An update was found. Automatic installs are not supported without the wrapper but you can download it nonetheless " , " Update found " , ( ) - > {
try {
2022-11-03 17:07:55 +01:00
Utils . openWebBrowser ( new URI ( Updater . getShadowJarUrl ( InceptumConfig . channel ) ) ) ;
2022-09-04 21:21:24 +02:00
exit ( ) ;
} catch ( URISyntaxException e ) {
LauncherEnv . showError ( " Could not download update " , e ) ;
}
} , ( ) - > WINDOWS . add ( new MainWindow ( ) ) ) ;
}
2021-11-11 17:59:35 +01:00
run ( ) ;
dispose ( ) ;
2021-10-30 22:05:24 +02:00
}
public static void open ( Window window ) {
WINDOWS . add ( window ) ;
}
/ * *
* Method to initialize application .
* /
public static void init ( ) {
initWindow ( ) ;
initImGui ( ) ;
imGuiGlfw . init ( handle , true ) ;
imGuiGl3 . init ( glslVersion ) ;
}
/ * *
* Method to dispose all used application resources and destroy its window .
* /
public static void dispose ( ) {
imGuiGl3 . dispose ( ) ;
imGuiGlfw . dispose ( ) ;
Callbacks . glfwFreeCallbacks ( handle ) ;
GLFW . glfwDestroyWindow ( handle ) ;
GLFW . glfwTerminate ( ) ;
Objects . requireNonNull ( GLFW . glfwSetErrorCallback ( null ) ) . free ( ) ;
}
/ * *
* Method to create and initialize GLFW window .
* /
protected static void initWindow ( ) {
GLFWErrorCallback . createPrint ( System . err ) . set ( ) ;
if ( ! GLFW . glfwInit ( ) ) {
throw new IllegalStateException ( " Unable to initialize GLFW " ) ;
}
decideGlGlslVersions ( ) ;
GLFW . glfwWindowHint ( GLFW . GLFW_VISIBLE , GLFW . GLFW_FALSE ) ;
GLFW . glfwWindowHint ( GLFW . GLFW_RESIZABLE , GLFW . GLFW_FALSE ) ;
handle = GLFW . glfwCreateWindow ( 10 , 10 , " Inceptum " , MemoryUtil . NULL , MemoryUtil . NULL ) ;
if ( handle = = MemoryUtil . NULL ) {
throw new RuntimeException ( " Failed to create the GLFW window " ) ;
}
try ( MemoryStack stack = MemoryStack . stackPush ( ) ) {
final IntBuffer pWidth = stack . mallocInt ( 1 ) ; // int*
final IntBuffer pHeight = stack . mallocInt ( 1 ) ; // int*
GLFW . glfwGetWindowSize ( handle , pWidth , pHeight ) ;
final GLFWVidMode vidmode = Objects . requireNonNull ( GLFW . glfwGetVideoMode ( GLFW . glfwGetPrimaryMonitor ( ) ) ) ;
GLFW . glfwSetWindowPos ( handle , ( vidmode . width ( ) - pWidth . get ( 0 ) ) / 2 , ( vidmode . height ( ) - pHeight . get ( 0 ) ) / 2 ) ;
}
GLFW . glfwMakeContextCurrent ( handle ) ;
GL . createCapabilities ( ) ;
GLFW . glfwSwapInterval ( GLFW . GLFW_TRUE ) ;
clearBuffer ( ) ;
renderBuffer ( ) ;
}
private static void decideGlGlslVersions ( ) {
final boolean isMac = System . getProperty ( " os.name " ) . toLowerCase ( ) . contains ( " mac " ) ;
if ( isMac ) {
glslVersion = " #version 150 " ;
GLFW . glfwWindowHint ( GLFW . GLFW_CONTEXT_VERSION_MAJOR , 3 ) ;
GLFW . glfwWindowHint ( GLFW . GLFW_CONTEXT_VERSION_MINOR , 2 ) ;
GLFW . glfwWindowHint ( GLFW . GLFW_OPENGL_PROFILE , GLFW . GLFW_OPENGL_CORE_PROFILE ) ; // 3.2+ only
GLFW . glfwWindowHint ( GLFW . GLFW_OPENGL_FORWARD_COMPAT , GLFW . GLFW_TRUE ) ; // Required on Mac
} else {
glslVersion = " #version 130 " ;
GLFW . glfwWindowHint ( GLFW . GLFW_CONTEXT_VERSION_MAJOR , 3 ) ;
GLFW . glfwWindowHint ( GLFW . GLFW_CONTEXT_VERSION_MINOR , 0 ) ;
}
}
/ * *
* Method to initialize Dear ImGui context . Could be overridden to do custom Dear ImGui setup before application start .
* /
protected static void initImGui ( ) {
ImGui . createContext ( ) ;
ImGuiIO io = ImGui . getIO ( ) ;
io . addConfigFlags ( ImGuiConfigFlags . ViewportsEnable ) ;
io . setConfigViewportsNoAutoMerge ( true ) ;
2022-09-04 21:21:24 +02:00
try ( InputStream is = LauncherEnv . class . getClassLoader ( ) . getResourceAsStream ( " font.ttf " ) ) {
2022-09-18 15:15:30 +02:00
io . setFontDefault ( io . getFonts ( ) . addFontFromMemoryTTF ( Objects . requireNonNull ( is ) . readAllBytes ( ) , 16f ) ) ;
2021-10-30 22:05:24 +02:00
} catch ( IOException e ) {
2022-01-27 17:57:13 +01:00
Utils . LOGGER . error ( " Could not load font " , e ) ;
2021-10-30 22:05:24 +02:00
}
applyTheme ( ) ;
}
/ * *
* Main application loop .
* /
public static void run ( ) {
while ( ! GLFW . glfwWindowShouldClose ( handle ) ) {
//frame
clearBuffer ( ) ;
imGuiGlfw . newFrame ( ) ;
ImGui . newFrame ( ) ;
//render
if ( WINDOWS . isEmpty ( ) ) exit ( ) ;
else {
2022-02-06 16:00:14 +01:00
for ( Window window : WINDOWS . toArray ( new Window [ 0 ] ) ) {
2021-10-30 22:05:24 +02:00
if ( window . isNew ( ) ) window . preFirstDraw ( ) ;
2022-06-05 16:45:22 +02:00
String title = window . getName ( ) + " ## " + System . identityHashCode ( window ) ;
2022-09-18 15:15:30 +02:00
if ( window . isCloseable ( ) ) {
if ( ImGui . begin ( title , window . getOpenState ( ) , window . getFlags ( ) ) ) {
window . draw ( ) ;
}
} else {
if ( ImGui . begin ( title , window . getFlags ( ) ) ) {
window . draw ( ) ;
}
}
2021-10-30 22:05:24 +02:00
ImGui . end ( ) ;
2021-12-01 16:12:47 +01:00
if ( ! window . getOpenState ( ) . get ( ) & & ! window . isClosed ( ) ) window . close ( ) ;
2021-10-30 22:05:24 +02:00
}
}
//end frame
ImGui . render ( ) ;
imGuiGl3 . renderDrawData ( ImGui . getDrawData ( ) ) ;
if ( ImGui . getIO ( ) . hasConfigFlags ( ImGuiConfigFlags . ViewportsEnable ) ) {
final long backupWindowPtr = GLFW . glfwGetCurrentContext ( ) ;
ImGui . updatePlatformWindows ( ) ;
ImGui . renderPlatformWindowsDefault ( ) ;
GLFW . glfwMakeContextCurrent ( backupWindowPtr ) ;
}
renderBuffer ( ) ;
}
}
private static void clearBuffer ( ) {
GL32 . glClear ( GL32 . GL_COLOR_BUFFER_BIT | GL32 . GL_DEPTH_BUFFER_BIT ) ;
}
private static void renderBuffer ( ) {
GLFW . glfwSwapBuffers ( handle ) ;
GLFW . glfwPollEvents ( ) ;
}
public static void exit ( ) {
GLFW . glfwSetWindowShouldClose ( handle , true ) ;
}
public static void applyTheme ( ) {
2022-09-07 18:06:34 +02:00
if ( InceptumConfig . darkTheme ) ImGui . styleColorsDark ( ) ;
2021-10-30 22:05:24 +02:00
else ImGui . styleColorsLight ( ) ;
}
2022-09-19 21:26:23 +02:00
public static @Nullable Path saveFileDialog ( String title , String defaultName , String [ ] filters , String filterDescription ) {
try ( MemoryStack stack = MemoryStack . stackPush ( ) ) {
PointerBuffer filterPatterns = stack . mallocPointer ( filters . length ) ;
for ( String filter : filters ) {
filterPatterns . put ( stack . UTF8 ( filter ) ) ;
}
filterPatterns . flip ( ) ;
String file = TinyFileDialogs . tinyfd_saveFileDialog ( title , defaultName , filterPatterns , filterDescription ) ;
return file = = null ? null : Paths . get ( file ) . toAbsolutePath ( ) . normalize ( ) ;
}
}
public static List < Path > openFileDialog ( String title , String defaultName , String [ ] filters , String filterDescription , boolean selectMultiple ) {
try ( MemoryStack stack = MemoryStack . stackPush ( ) ) {
PointerBuffer filterPatterns = stack . mallocPointer ( filters . length ) ;
for ( String filter : filters ) {
filterPatterns . put ( stack . UTF8 ( filter ) ) ;
}
filterPatterns . flip ( ) ;
String files = TinyFileDialogs . tinyfd_openFileDialog ( title , defaultName , filterPatterns , filterDescription , selectMultiple ) ;
if ( files = = null ) return List . of ( ) ;
return Arrays . stream ( files . split ( " \\ | " ) )
. map ( Paths : : get )
. map ( Path : : toAbsolutePath )
. map ( Path : : normalize )
. toList ( ) ;
}
}
2021-10-30 22:05:24 +02:00
}