Fully undecorated window in Windows OS
This commit is contained in:
@@ -8,6 +8,7 @@ import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Window;
|
||||
import games.rednblack.editor.proxy.SettingsManager;
|
||||
import games.rednblack.editor.splash.SplashScreenAdapter;
|
||||
import games.rednblack.editor.utils.AppConfig;
|
||||
import games.rednblack.editor.utils.HyperLap2DUtils;
|
||||
import games.rednblack.h2d.common.view.ui.StandardWidgetsFactory;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
|
||||
@@ -54,27 +55,26 @@ public class HyperLap2DApp extends ApplicationAdapter {
|
||||
|
||||
splashWindow = app.newWindow(new SplashScreenAdapter(), config2);
|
||||
|
||||
Gdx.app.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
hyperlap2D = new HyperLap2D(settingsManager);
|
||||
Gdx.app.postRunnable(() -> {
|
||||
hyperlap2D = new HyperLap2D(settingsManager);
|
||||
|
||||
Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration();
|
||||
config.setTitle("HyperLap2D - Beta v" + AppConfig.getInstance().versionString);
|
||||
config.setResizable(true);
|
||||
Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration();
|
||||
config.setTitle("HyperLap2D - Beta v" + AppConfig.getInstance().versionString);
|
||||
config.setResizable(true);
|
||||
if (!SystemUtils.IS_OS_WINDOWS)
|
||||
config.setWindowedMode((int) (windowWidth), (int) (windowHeight));
|
||||
config.setIdleFPS(60);
|
||||
config.setForegroundFPS(settingsManager.editorConfigVO.fpsLimit);
|
||||
config.useVsync(false);
|
||||
config.setInitialVisible(false);
|
||||
config.setMaximized(true);
|
||||
config.setWindowIcon("hyperlap_icon_96.png");
|
||||
config.setWindowSizeLimits(920, 800, -1, -1);
|
||||
if (SystemUtils.IS_OS_WINDOWS)
|
||||
config.setWindowPosition(0, (int) (windowHeight * .04));
|
||||
config.setIdleFPS(60);
|
||||
config.setForegroundFPS(settingsManager.editorConfigVO.fpsLimit);
|
||||
config.useVsync(false);
|
||||
config.setInitialVisible(false);
|
||||
config.setMaximized(true);
|
||||
config.setWindowIcon("hyperlap_icon_96.png");
|
||||
config.setWindowSizeLimits(920, 800, -1, -1);
|
||||
|
||||
mainWindow = app.newWindow(hyperlap2D, config);
|
||||
mainWindow.setWindowListener(hyperlap2D);
|
||||
mainWindow = app.newWindow(hyperlap2D, config);
|
||||
mainWindow.setWindowListener(hyperlap2D);
|
||||
if (SystemUtils.IS_OS_WINDOWS) {
|
||||
Gdx.app.postRunnable(() -> HyperLap2DUtils.overwriteWindowProc2(mainWindow.getWindowHandle()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,39 +1,26 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* * Copyright 2015 See AUTHORS file.
|
||||
* *
|
||||
* * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* * you may not use this file except in compliance with the License.
|
||||
* * You may obtain a copy of the License at
|
||||
* *
|
||||
* * http://www.apache.org/licenses/LICENSE-2.0
|
||||
* *
|
||||
* * Unless required by applicable law or agreed to in writing, software
|
||||
* * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* * See the License for the specific language governing permissions and
|
||||
* * limitations under the License.
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
package games.rednblack.editor.utils;
|
||||
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor;
|
||||
import com.badlogic.gdx.scenes.scene2d.InputEvent;
|
||||
import com.badlogic.gdx.scenes.scene2d.InputListener;
|
||||
import com.badlogic.gdx.math.Rectangle;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import games.rednblack.editor.HyperLap2DFacade;
|
||||
import games.rednblack.editor.view.ui.UIWindowAction;
|
||||
import games.rednblack.editor.view.ui.UIWindowActionMediator;
|
||||
import games.rednblack.editor.view.ui.UIWindowTitle;
|
||||
import games.rednblack.editor.view.ui.UIWindowTitleMediator;
|
||||
import org.apache.commons.io.filefilter.SuffixFileFilter;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.lwjgl.glfw.GLFWNativeWin32;
|
||||
import org.lwjgl.system.JNI;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
import org.lwjgl.system.windows.RECT;
|
||||
import org.lwjgl.system.windows.User32;
|
||||
import org.lwjgl.system.windows.WINDOWPLACEMENT;
|
||||
import org.lwjgl.system.windows.WindowProc;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.nio.DoubleBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
/**
|
||||
* Created by sargis on 4/1/15.
|
||||
@@ -64,15 +51,27 @@ public class HyperLap2DUtils {
|
||||
return System.getProperty("user.home") + File.separator + "Documents";
|
||||
}
|
||||
|
||||
public static void setWindowDragListener(Actor actor) {
|
||||
actor.addListener(new InputListener() {
|
||||
private final long context = GLFW.glfwGetCurrentContext();
|
||||
private float startX = 0;
|
||||
private float startY = 0;
|
||||
/**
|
||||
* Function to override Windows behavior to use undecorated style while preserving snap to edge and resize.
|
||||
* Works only on Windows OS
|
||||
* From: https://gist.github.com/SWinxy/d48469ac83834219a0044c2c5df55f56
|
||||
* @author SWinxy
|
||||
*
|
||||
* @param lwjglWindow lwjgl pointer to window object
|
||||
*/
|
||||
public static void overwriteWindowProc2(long lwjglWindow) {
|
||||
if (!SystemUtils.IS_OS_WINDOWS) return;
|
||||
|
||||
long hwnd = GLFWNativeWin32.glfwGetWin32Window(lwjglWindow);
|
||||
long pWindowProc = User32.GetWindowLongPtr(hwnd, User32.GWL_WNDPROC);
|
||||
System.out.println("oldptr: " + pWindowProc);
|
||||
|
||||
WindowProc proc = new WindowProc() {
|
||||
private final Vector2 tmp = new Vector2();
|
||||
private final Rectangle titleBounds = new Rectangle();
|
||||
private final DoubleBuffer cursorX = BufferUtils.createDoubleBuffer(1);
|
||||
private final DoubleBuffer cursorY = BufferUtils.createDoubleBuffer(1);
|
||||
private final IntBuffer windowX = BufferUtils.createIntBuffer(1);
|
||||
private final IntBuffer windowY = BufferUtils.createIntBuffer(1);
|
||||
private RECT rect;
|
||||
|
||||
private int getX() {
|
||||
return MathUtils.floor((float) cursorX.get(0));
|
||||
@@ -82,154 +81,90 @@ public class HyperLap2DUtils {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
|
||||
UIWindowActionMediator uiWindowActionMediator = HyperLap2DFacade.getInstance().retrieveMediator(UIWindowActionMediator.NAME);
|
||||
UIWindowAction uiWindowAction = uiWindowActionMediator.getViewComponent();
|
||||
if (uiWindowAction.isMaximized())
|
||||
return false;
|
||||
GLFW.glfwGetCursorPos(context, cursorX, cursorY);
|
||||
startX = getX();
|
||||
startY = getY();
|
||||
return true;
|
||||
}
|
||||
public long invoke(long hwnd, int uMsg, long wParam, long lParam) {
|
||||
if (uMsg == User32.WM_NCHITTEST) {
|
||||
try (MemoryStack stack = MemoryStack.stackPush()) {
|
||||
short x = (short) (lParam & 0xFFFF);
|
||||
short y = (short) ((lParam & 0xFFFF0000) >> 16);
|
||||
GLFW.glfwGetCursorPos(GLFW.glfwGetCurrentContext(), cursorX, cursorY);
|
||||
|
||||
@Override
|
||||
public void touchDragged(InputEvent event, float x, float y, int pointer) {
|
||||
GLFW.glfwGetCursorPos(context, cursorX, cursorY);
|
||||
float offsetX = getX() - startX;
|
||||
float offsetY = getY() - startY;
|
||||
GLFW.glfwGetWindowPos(context, windowX, windowY);
|
||||
GLFW.glfwSetWindowPos(context, (int)(windowX.get(0) + offsetX), (int)(windowY.get(0) + offsetY));
|
||||
}
|
||||
});
|
||||
}
|
||||
if (rect == null)
|
||||
rect = RECT.calloc(stack);
|
||||
User32.GetWindowRect(hwnd, rect);
|
||||
|
||||
public static void setWindowResizeListener(Actor actor) {
|
||||
actor.addListener(new InputListener() {
|
||||
private static final int TOP_BORDER = 0;
|
||||
private static final int BOTTOM_BORDER = 1;
|
||||
private static final int LEFT_BORDER = 2;
|
||||
private static final int RIGHT_BORDER = 3;
|
||||
private static final int BOTTOM_LEFT_CORNER = 4;
|
||||
private static final int BOTTOM_RIGHT_CORNER = 5;
|
||||
private static final int TOP_LEFT_CORNER = 6;
|
||||
private static final int TOP_RIGHT_CORNER = 7;
|
||||
if (y < rect.top() + 16 && x < rect.left() + 16) {
|
||||
return User32.HTTOPLEFT;
|
||||
}
|
||||
if (y > rect.bottom() - 16 && x > rect.right() - 16) {
|
||||
return User32.HTBOTTOMRIGHT;
|
||||
}
|
||||
if (y < rect.top() + 12 && x > rect.right() - 16) {
|
||||
return User32.HTTOPRIGHT;
|
||||
}
|
||||
if (y > rect.bottom() - 16 && x < rect.left() + 16) {
|
||||
return User32.HTBOTTOMLEFT;
|
||||
}
|
||||
|
||||
private static final int BORDER_SIZE = 10;
|
||||
if (y < rect.top() + 8) {
|
||||
return User32.HTTOP;
|
||||
}
|
||||
if (x < rect.left() + 16) {
|
||||
return User32.HTLEFT;
|
||||
}
|
||||
if (y > rect.bottom() - 16) {
|
||||
return User32.HTBOTTOM;
|
||||
}
|
||||
if (x > rect.right() - 16) {
|
||||
return User32.HTRIGHT;
|
||||
}
|
||||
|
||||
private final long context = GLFW.glfwGetCurrentContext();
|
||||
private float startX = 0;
|
||||
private float startY = 0;
|
||||
private float startW = 0;
|
||||
private float startH = 0;
|
||||
private float startWindowX = 0;
|
||||
private float startWindowY = 0;
|
||||
private int anchorPoint = -1;
|
||||
private final DoubleBuffer cursorX = BufferUtils.createDoubleBuffer(1);
|
||||
private final DoubleBuffer cursorY = BufferUtils.createDoubleBuffer(1);
|
||||
//Test if the pointer is in Title Bar
|
||||
UIWindowTitleMediator uiWindowTitleMediator = HyperLap2DFacade.getInstance().retrieveMediator(UIWindowTitleMediator.NAME);
|
||||
UIWindowTitle uiWindowTitle = uiWindowTitleMediator.getViewComponent();
|
||||
uiWindowTitle.localToScreenCoordinates(tmp.set(0, 0));
|
||||
titleBounds.set(tmp.x, tmp.y, uiWindowTitle.getWidth() + ((11 * uiWindowTitle.getWidth() / 100)), uiWindowTitle.getHeight());
|
||||
|
||||
private final IntBuffer windowX = BufferUtils.createIntBuffer(1);
|
||||
private final IntBuffer windowY = BufferUtils.createIntBuffer(1);
|
||||
private final IntBuffer windowW = BufferUtils.createIntBuffer(1);
|
||||
private final IntBuffer windowH = BufferUtils.createIntBuffer(1);
|
||||
|
||||
private int getX() {
|
||||
return MathUtils.floor((float) cursorX.get(0));
|
||||
}
|
||||
private int getY() {
|
||||
return MathUtils.floor((float) cursorY.get(0));
|
||||
}
|
||||
private int getWidth() {
|
||||
return MathUtils.floor((float) windowW.get(0));
|
||||
}
|
||||
private int getHeight() {
|
||||
return MathUtils.floor((float) windowH.get(0));
|
||||
}
|
||||
private int getWindowX() {
|
||||
return MathUtils.floor((float) windowX.get(0));
|
||||
}
|
||||
private int getWindowY() {
|
||||
return MathUtils.floor((float) windowY.get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
|
||||
UIWindowActionMediator uiWindowActionMediator = HyperLap2DFacade.getInstance().retrieveMediator(UIWindowActionMediator.NAME);
|
||||
UIWindowAction uiWindowAction = uiWindowActionMediator.getViewComponent();
|
||||
if (uiWindowAction.isMaximized())
|
||||
return false;
|
||||
|
||||
GLFW.glfwGetCursorPos(context, cursorX, cursorY);
|
||||
GLFW.glfwGetWindowSize(context, windowW, windowH);
|
||||
GLFW.glfwGetWindowPos(context, windowX, windowY);
|
||||
anchorPoint = getAnchorPoint();
|
||||
|
||||
if (anchorPoint == -1)
|
||||
return false;
|
||||
|
||||
startX = getX();
|
||||
startY = getY();
|
||||
startW = getWidth();
|
||||
startH = getHeight();
|
||||
startWindowX = getWindowX();
|
||||
startWindowY = getWindowY();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void touchDragged(InputEvent event, float x, float y, int pointer) {
|
||||
GLFW.glfwGetWindowPos(context, windowX, windowY);
|
||||
GLFW.glfwGetCursorPos(context, cursorX, cursorY);
|
||||
float offsetX = getX() - startX + (startWindowX - getWindowX());
|
||||
float offsetY = getY() - startY;
|
||||
GLFW.glfwGetWindowSize(context, windowW, windowH);
|
||||
switch (anchorPoint) {
|
||||
case BOTTOM_BORDER:
|
||||
GLFW.glfwSetWindowSize(context, (int) startW, (int)(startH + offsetY));
|
||||
break;
|
||||
case TOP_BORDER:
|
||||
GLFW.glfwSetWindowSize(context, (int) startW, (int)(startH - offsetY));
|
||||
break;
|
||||
case LEFT_BORDER:
|
||||
GLFW.glfwSetWindowSize(context, (int)(startW - offsetX), (int) startH);
|
||||
break;
|
||||
case RIGHT_BORDER:
|
||||
GLFW.glfwSetWindowSize(context, (int)(startW + offsetX), (int) startH);
|
||||
break;
|
||||
case BOTTOM_RIGHT_CORNER:
|
||||
GLFW.glfwSetWindowSize(context, (int)(startW + offsetX), (int)(startH + offsetY));
|
||||
break;
|
||||
case TOP_RIGHT_CORNER:
|
||||
GLFW.glfwSetWindowSize(context, (int)(startW + offsetX), (int)(startH - offsetY));
|
||||
break;
|
||||
case BOTTOM_LEFT_CORNER:
|
||||
GLFW.glfwSetWindowSize(context, (int)(startW - offsetX), (int)(startH + offsetY));
|
||||
break;
|
||||
case TOP_LEFT_CORNER:
|
||||
GLFW.glfwSetWindowSize(context, (int)(startW - offsetX), (int)(startH - offsetY));
|
||||
break;
|
||||
int glfwX = getX();
|
||||
int glfwY = getY();
|
||||
if (titleBounds.x <= glfwX && titleBounds.x + titleBounds.width >= glfwX
|
||||
&& titleBounds.y >= glfwY && titleBounds.y - titleBounds.height <= glfwY) {
|
||||
return User32.HTCAPTION;
|
||||
}
|
||||
return JNI.callPPPP(hwnd, uMsg, wParam, lParam, pWindowProc);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (uMsg == User32.WM_NCCALCSIZE) {
|
||||
if (wParam == 1) {
|
||||
try (MemoryStack stack = MemoryStack.stackPush()) {
|
||||
WINDOWPLACEMENT windowplacement = WINDOWPLACEMENT.calloc(stack);
|
||||
User32.GetWindowPlacement(hwnd, windowplacement);
|
||||
// ...but instead we're gonna just pretend it's just a RECT struct
|
||||
// the NCCALCSIZE_PARAMS struct conveniently has what we need
|
||||
// at the very start, so we can quietly say it's a RECT struct lol
|
||||
// hacky because LWJGL doesn't include the structs to the aforementioned
|
||||
// struct, nor some of the other structs contained
|
||||
RECT rect = RECT.create(lParam);
|
||||
if (windowplacement.showCmd() != User32.SW_MAXIMIZE) {
|
||||
rect.left(rect.left() + 8);
|
||||
// rect.top(rect.top() + 0);
|
||||
rect.right(rect.right() - 8);
|
||||
rect.bottom(rect.bottom() - 8);
|
||||
} else {
|
||||
rect.left(rect.left() + 8);
|
||||
rect.top(rect.top() + 8);
|
||||
rect.right(rect.right() - 8);
|
||||
rect.bottom(rect.bottom() - 8);
|
||||
}
|
||||
|
||||
private int getAnchorPoint() {
|
||||
if (getX() < BORDER_SIZE && getY() > BORDER_SIZE && getY() < getHeight() - BORDER_SIZE)
|
||||
return LEFT_BORDER;
|
||||
if (getX() < BORDER_SIZE && getY() < BORDER_SIZE)
|
||||
return TOP_LEFT_CORNER;
|
||||
if (getX() < BORDER_SIZE && getY() > getHeight() - BORDER_SIZE)
|
||||
return BOTTOM_LEFT_CORNER;
|
||||
if (getX() > BORDER_SIZE && getY() > getHeight() - BORDER_SIZE && getX() < getWidth() - BORDER_SIZE)
|
||||
return BOTTOM_BORDER;
|
||||
if (getX() > getWidth() - BORDER_SIZE && getY() > getHeight() - BORDER_SIZE)
|
||||
return BOTTOM_RIGHT_CORNER;
|
||||
if (getX() > getWidth() - BORDER_SIZE && getY() > BORDER_SIZE && getY() < getHeight() - BORDER_SIZE)
|
||||
return RIGHT_BORDER;
|
||||
if (getX() > getWidth() - BORDER_SIZE && getY() < BORDER_SIZE)
|
||||
return TOP_RIGHT_CORNER;
|
||||
if (getX() > BORDER_SIZE && getY() < BORDER_SIZE && getX() < getWidth() - BORDER_SIZE)
|
||||
return TOP_BORDER;
|
||||
return -1;
|
||||
return rect.address();
|
||||
}
|
||||
}
|
||||
}
|
||||
return JNI.callPPPP(hwnd, uMsg, wParam, lParam, pWindowProc);
|
||||
}
|
||||
});
|
||||
};
|
||||
System.out.println("procaddr: " + proc.address());
|
||||
System.out.println("setptr: " + User32.SetWindowLongPtr(hwnd, User32.GWL_WNDPROC, proc.address()));
|
||||
System.out.println("setwinptr: " + User32.SetWindowPos(hwnd, 0, 0, 0, 0, 0, User32.SWP_NOMOVE | User32.SWP_NOSIZE | User32.SWP_NOZORDER | User32.SWP_FRAMECHANGED));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,11 @@ package games.rednblack.editor.view.ui;
|
||||
|
||||
import com.kotcrab.vis.ui.widget.VisTable;
|
||||
import games.rednblack.editor.HyperLap2DFacade;
|
||||
import games.rednblack.editor.utils.HyperLap2DUtils;
|
||||
import games.rednblack.editor.view.menu.HyperLap2DMenuBar;
|
||||
import games.rednblack.editor.view.menu.HyperLap2DMenuBarMediator;
|
||||
import games.rednblack.editor.view.ui.box.*;
|
||||
import games.rednblack.editor.view.ui.widget.H2DLogo;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
|
||||
public class UIMainTable extends VisTable {
|
||||
private final VisTable topTable, middleTable;
|
||||
@@ -47,8 +47,6 @@ public class UIMainTable extends VisTable {
|
||||
initToolsPanel();
|
||||
initLeftBoxesPanel();
|
||||
initRightBoxesPanel();
|
||||
|
||||
HyperLap2DUtils.setWindowDragListener(topTable);
|
||||
}
|
||||
|
||||
private void initMenuBar() {
|
||||
@@ -56,16 +54,17 @@ public class UIMainTable extends VisTable {
|
||||
|
||||
HyperLap2DMenuBarMediator hyperlap2DMenuBarMediator = facade.retrieveMediator(HyperLap2DMenuBarMediator.NAME);
|
||||
HyperLap2DMenuBar menuBar = hyperlap2DMenuBarMediator.getViewComponent();
|
||||
topTable.add(menuBar.getTable()).height(32).growX();
|
||||
topTable.add(menuBar.getTable()).height(32);
|
||||
|
||||
//TODO Undecorated window is cool but too much glitches
|
||||
/*UIWindowTitleMediator uiWindowTitleMediator = facade.retrieveMediator(UIWindowTitleMediator.NAME);
|
||||
UIWindowTitle uiWindowTitle = uiWindowTitleMediator.getViewComponent();
|
||||
topTable.add(uiWindowTitle).growX().fillY();
|
||||
if (SystemUtils.IS_OS_WINDOWS) {
|
||||
UIWindowTitleMediator uiWindowTitleMediator = facade.retrieveMediator(UIWindowTitleMediator.NAME);
|
||||
UIWindowTitle uiWindowTitle = uiWindowTitleMediator.getViewComponent();
|
||||
topTable.add(uiWindowTitle).growX().fillY();
|
||||
|
||||
UIWindowActionMediator uiWindowActionMediator = facade.retrieveMediator(UIWindowActionMediator.NAME);
|
||||
UIWindowAction uiWindowAction = uiWindowActionMediator.getViewComponent();
|
||||
topTable.add(uiWindowAction).padTop(-1).fillY();*/
|
||||
UIWindowActionMediator uiWindowActionMediator = facade.retrieveMediator(UIWindowActionMediator.NAME);
|
||||
UIWindowAction uiWindowAction = uiWindowActionMediator.getViewComponent();
|
||||
topTable.add(uiWindowAction).padTop(-1).fillY();
|
||||
}
|
||||
}
|
||||
|
||||
private void initSupportMenus() {
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.badlogic.gdx.utils.Align;
|
||||
import com.kotcrab.vis.ui.VisUI;
|
||||
import com.kotcrab.vis.ui.widget.VisLabel;
|
||||
import com.kotcrab.vis.ui.widget.VisTable;
|
||||
import games.rednblack.editor.utils.AppConfig;
|
||||
import games.rednblack.h2d.common.view.ui.StandardWidgetsFactory;
|
||||
|
||||
public class UIWindowTitle extends VisTable {
|
||||
@@ -13,8 +14,10 @@ public class UIWindowTitle extends VisTable {
|
||||
|
||||
public UIWindowTitle() {
|
||||
setBackground(VisUI.getSkin().getDrawable("menu-bg"));
|
||||
title = StandardWidgetsFactory.createLabel("", "default", Align.center);
|
||||
add(title);
|
||||
title = StandardWidgetsFactory.createLabel("HyperLap2D - Beta v" + AppConfig.getInstance().versionString, "default", Align.center);
|
||||
title.setEllipsis(true);
|
||||
title.setWrap(true);
|
||||
add(title).growX();
|
||||
setTouchable(Touchable.enabled);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user