webfx-project / webfx-cli

The Command Line Interface for WebFX. The terminal tool for developing WebFX applications.
https://webfx.dev
Apache License 2.0
10 stars 3 forks source link

I don't quite get how this works #8

Closed armin-reichert closed 7 months ago

armin-reichert commented 1 year ago

Say I want to use webfx to build a GWT executable (and maybe others too) for an existing JavaFX application (in my case: https://github.com/armin-reichert/pacman-javafx)

Do I have to bring my Maven artifacts to some central Maven repository first to get this working, or can webfx also resolve dependencies against my local Maven repository?

armin-reichert commented 1 year ago

Sorry to bother you again. Things don't work as expected :-(

I have all webfx tools available on my machine. Creating a "hello world" sample, building/runnning it with webfx build -fr, webfx build -gr and webfx build -dr all work as expected and the hello world app opens, either in a window or in the browser.

But for the webfx-demos/webfx-demo-pacman, the app only opens in the browser! For the other variants, no window opens.

Could you please verify that this is the same in your local version? It cannot be caused by my 3 changes so far because I only changed the window background to black, added gitignore files and removed the 3D subproject.

salmonb commented 1 year ago

Here are the results on my iMac:

BTW if you want a mobile version of your game, it's possible but I will need to modify the code a little bit so playing sound can be processed by Gluon Attach on Android & iOS (the desktop & web version will still work after that modification). Let me know if you're interested.

I'm surprised that webfx build -fr doesn't work for you. Do you have any error message in the console? Have you tried to run the Windows fat jar and installer exe generated by the GitHub workflow (available here)?

salmonb commented 1 year ago

hi Armin,

How is it going?

I just noticed that the latest online version is not working, but this is probably due to the following WebFX bug that I would like to make you aware of: when changing a node using parent.getChildren().set(x, newNode), the WebFX mapper may get it wrong and put the node at the end instead of position x.

I will try to fix that bug later, but for the time being, is it possible for you to reset the whole list instead? Ex: parent.getChildren().setAll(node1 ,node2, etc...)?

armin-reichert commented 1 year ago

Hello Bruno,

thanks for the hint. I am aware that there is something fishy in this area. My latest commit should clarify the main scene layering a little bit.

Looks better now. Flash messages are working, the context-sensitive help is toggled by pressing 'H', the cheats like "Immunity" (Alt+Shift I) or the autopilot mode (Alt+Shift A) are displayed correctly in the context help.

salmonb commented 1 year ago

Glad that it's working again, you found the workaround!

Don't hesitate to tell me when you are facing a WebFX bug, I will try to fix it, and this helps to make WebFX better πŸ˜‰

armin-reichert commented 1 year ago

Of course I will tell you about any strange effects I find.

Example: I have the impression that mouse clicks on a Text widget do not work properly. I had a Text instance only for the greeting message ("Click to start") but that did not work in the browser, so I had to put the text inside a panel.

I lost some time because I had to install IntelliJ to work with the webfx branch (I had absolutely no idea how to realize the "application configuration" involving ApplicationBooter inside Eclipse). But working with IntelliJ is really fun, Git integration is top.

salmonb commented 1 year ago

Yes, IntelliJ is amazing, I πŸ’Ÿ it too

The text only (without pane) should work... I just pull the latest source, and noticed a call to greetingText.setMouseTransparent(true); which prevents any interaction with the user. Maybe that's the problem?

I'm glad that you have the OpenJFX configuration running in IntelliJ, so you can now see if your issues come from WebFX or the application code. For example, if the text issue is because of setMouseTransparent(), you should see that the issue is also happening with OpenJFX, and therefore it's not a WebFX bug. This OpenJFX configuration should really accelerate your development cycle! πŸ˜ƒ

armin-reichert commented 1 year ago

Well, I added the setMouseTransparent(true) call after putting the text inside a StackPane. First I had the text only, but the mouse click on the text was only handled in the desktop version, but not in the browser version. Then I added the surrounding StackPane and wanted the mouse click over the text also being handled on the stack pane.

salmonb commented 1 year ago

I tried this locally, and it works in the browser:

    private Node createGreetingPane() {
        DropShadow ds = new DropShadow();
        ds.setOffsetY(3.0f);
        ds.setColor(Color.color(0.2f, 0.2f, 0.2f));

        var greetingText = new Text(">Click to start<");
        //greetingText.setMouseTransparent(true);
        greetingText.setEffect(ds);
        greetingText.setCache(true);
        greetingText.setFill(Color.YELLOW);
        greetingText.setFont(AppRes.Fonts.font(AppRes.Fonts.arcade, 24));
        //var pane = new StackPane(greetingText);
        greetingText.setOnMouseClicked(e -> {
            layers.remove(LAYER_GREETING);
            rebuildMainSceneLayers();
            simulation.start();
            Actions.playHelpVoiceMessageAfterSeconds(4);
        });

        //return pane;
        return greetingText;
    }
armin-reichert commented 1 year ago

Definitely didn't work here (Windows10, Google Chrome). I could try it again with the exact code above.

salmonb commented 1 year ago

Maybe it's a Windows thing (as I don't test on Windows...) If you can test for me, that would be helpful.

PS: Good idea the initial click, as it makes a user interaction, and then the sound works in the browser πŸ‘

πŸ’‘ Tips: if you don't want that greeting text to show in the other platforms (because they can play sound straightaway), you can use the condition dev.webfx.platform.useragent.UserAgent.isBrowser() (just run webfx update after inserting this in your code and the WebFX CLI should automatically insert the required WebFX module - and after that IntelliJ should propose you to replace the fully qualified name with a simple UserAgent.isBrowser() + import dev.webfx.platform.useragent.UserAgent;).

armin-reichert commented 1 year ago

Yes, that "no sound without initial gesture" feature was the reason I added this "Click Me" thing. Thanks for the tip, but the webfx branch should just be used inside the browser. You mentioned that webfx can also be used to build executables for different platforms. That's exactly what I am looking for. But will this also only be possible after downporting to Java 11 and all these changes you had made?

BTW: no single error occurs anymore in the Chrome developer console.

salmonb commented 1 year ago

WebFX can compile apps to many platforms (not only the web) all from a single source code (your code in the webfx branch). The current GitHub workflow already generates different installers of your game as you can see in the generated assets here (just expand the Assets).

If you have an Android device, you can try to download and install the .apk file, but it's probably crashing because of JavaFX media not supported by Gluon. However, I can easily solve this problem using the WebFX API (let me know if you're interested).

Once everything works with WebFX, we can try to back port that into your original game.

armin-reichert commented 1 year ago

Issue: TextFlow does not work inside browser. I used a TextFlow node to put two Text nodes with different fonts together (see GameScene2D.addSignature()). In a window this looks find but in the browser, the text is not rendered correctly (stacked vertically).

salmonb commented 1 year ago

Right, WebFX has a very limited support of TextFlow, because it's a complex component, and the main reason for the existence of the TextFlow API in JavaFX is to provide a (poor) equivalent of HTML - but even that is already complex, and it doesn't really make sense to implement that complexity back for the browser while you can do HTML natively straightaway.

For this reason, WebFX provides alternative classes HtmlText, HtmlTextEditor and SvgText in the package dev.webfx.extras.webtext. HtmlText for example will accept any html content that will be rendered as is in the browser, and will try to render that html content using TextFlow in the OpenJFX version (limited but should works for basic html).

Are you happy to try HtmlTextinstead of TextFlow? Or if you prefer, I can have a look at it later today after work.

armin-reichert commented 1 year ago

Hi Bruno,

that was not a call for action, I just collect what I find on my way and let you know.

Another question: Would it be possible to change the GitHub workflow to only build the GWT version and deploy it to the website as long as I am still adding features in the webfx branch? 10 minutes for a build is a little long.

Text positioning is different in browser than in desktop window! In the browser the signature appears lower than in the desktop version. Why?

salmonb commented 1 year ago

Why are you not testing the web version on your local machine before pushing? This should be must faster.

I will have a look at the text positioning this evening.

armin-reichert commented 1 year ago

Sorry I got a little bit confused (happens at age 56). When I installed IntelliJ some days ago I quickly clicked through the installation and overlooked that IntelliJ uses its own local Git root. My console window still referred to the Git root I use with Eclipse so the webfx build -gr obvioulsy had no effect ony the changes I made with IntelliJ. Stupid me.

But now, when I refer to the IntelliJ Git root and call webfx build -gr and the browser opens (via a file: URL) I observe that some things like tihe boot "animation" do not work properly. Maybe I must let the page being served by a local webserver or use the one inside IntelliJ as you proposed.

salmonb commented 1 year ago

webfx build -gr doesn't use git, just mvn. The important thing is to run the command under your project folder (so webfx-demo-pacman here).

I just pulled your changes and the boot animation works fine on my local machine either with webfx build -gr or IntelliJ webserver.

πŸ’‘ Tips: if you right-click on webfx-demo-pacman in IntelliJ project window and select "Open in" > "Terminal", it will open a terminal tab (inside IntelliJ) already set under that folder (and it will remember that tab on next launches). This is usuallly where I type my webfx commands.

armin-reichert commented 1 year ago

I know that the build uses Maven and not git. The problem was that IntelliJ uses a different local folder for the git repository than Eclipse and when I switched to IntelliJ I didn't change the folder in my terminal window.

When I run with webfx -gr the boot screen shows the random hex symbols but not the random spritesheet tiles.

salmonb commented 1 year ago

I hadn't spotted the spritesheet issue, I see now what you mean, but it happens only when opening from file://, so not an issue for the final web version. Have you found how to open the html file with the IntelliJ built-in webserver?

Another πŸ’‘: You can bookmark the generated index.html in IntelliJ so you can access it quicker next times.

armin-reichert commented 1 year ago

In the IntelliJ internal web browser, it looks ok. Of course, the text positioning issue is also there. Thanks for all the tips! I am using IntelliJ only 3 days, but Eclipse 20 years :-)

salmonb commented 1 year ago

Ok, the positioning issue is with the JavaFX textOrigin property. For now WebFX supports VPos.TOP, VPos.CENTER and VPos.BOTTOM, but not VPos.BASELINE, which is unfortunately the default value. I will investigate again if there is a way to support VPos.BASELINE in HTML, but in the meantime, you can just set a different value to textOrigin and adjust your y value accordingly. Let me know if that solves the issue.

salmonb commented 1 year ago

Actually I think I found a solution and fixed the VPos.BASELINE html mapping in WebFX!

So no need to change your code finally, just get the latest webfx version (your Maven will automatically load it tomorrow, but if you don't want to wait, just clean this folder in your Maven local repository (located here from your user home: .m2/repository/dev/webfx/webfx-kit-javafxgraphics-peers-gwt)

armin-reichert commented 1 year ago

Works!

salmonb commented 1 year ago

Great, and I triggered the GitHub workflow manually again (as no change is needed in your source code), so now the online version works as well

armin-reichert commented 1 year ago

Hi Bruno,

I have an issue with a GridPane. For the context-sensitive help/menus (press 'H' to open/close) I use a GridPane together with a surrounding HBox to give a transparent background and some padding. In the desktop version that looks perfect, but in the browser, the vertical aligment is broken. Any idea?

salmonb commented 1 year ago

Looks like a similar issue as yesterday, probably my fix for VPos.BASELINE doesn't work in all scenarios... I will have a look this evening, but for the time being, just try another value for the textOrigin. For example try text.setTextOrigin(VPos.TOP); and you should have a better result.

salmonb commented 1 year ago

hi Armin, how is it going?

FYI I just pushed some fixes in WebFX, this includes the text positioning (so you might need to remove the translation correction now).

Also as you probably noticed, I fixed the background positioning issue. But on my big 27" screen, the picture is so stretched in width that I see only the top of the image (and the yellow "Click to start !" is on top of the yellow image). I think it would be better to put that image in 'contain' mode (instead of 'cover'), and put the wallpaper behind, so something like:

var bgImage = new BackgroundImage(
            AppRes.Graphics.msPacManCabinet,
            BackgroundRepeat.NO_REPEAT,
            BackgroundRepeat.NO_REPEAT,
            BackgroundPosition.CENTER,
            new BackgroundSize(AUTO, AUTO, false, false, true, false));
        root.setBackground(new Background(
                new BackgroundImage(AppRes.Graphics.wallpaper, null, null, null, null),
                bgImage));

What do you think?

armin-reichert commented 1 year ago

Hi Bruno,

I am making progress. Working mode with IntelliJ and β€žwebfx cliβ€œ is fluent, building the GWT version locally takes around 20 seconds, that’s ok for me.

The greeting page is still provisionary, I probably will select another wallpaper, something like https://wallpapercave.com/w/wp4163225

But I am not sure about copyright etc. The assets in my games are also β€žstolenβ€œ from other projects. But how should one clone a classic Arcade game without using the original assets?

Yes, I noticed that you already fixed some of the alignment issues. That’s great!

What I want to add in any case is some black area around the game scene, something like here: https://www.pacman1.net/

But I am open to your ideas of course too. There is not much missing until we can publish it.

Best regards Armin

salmonb commented 1 year ago

For your black area, you can embed the canvas in a black StackPane container and give it a size slightly superior (ex: +10%), so something like this:

    protected GameScene2D(GameController gameController) {
        checkNotNull(gameController);
        context = new GameSceneContext(gameController);

        StackPane canvasPane = new StackPane(canvas);
        canvasPane.setBackground(new Background(new BackgroundFill(Color.BLACK, new CornerRadii(10), null)));
        double marginFactor = 1.1;
        canvasPane.setMaxWidth(WIDTH * marginFactor);
        canvasPane.setMaxHeight(HEIGHT * marginFactor);

        root = new BorderPane();
        root.heightProperty().addListener((py, ov, nv) -> {
            double scaling = nv.doubleValue() / (HEIGHT * marginFactor);
            canvasPane.setScaleX(scaling);
            canvasPane.setScaleY(scaling);
            // don't ask me why this works but setScaleX/Y doesn't
            overlay.getTransforms().setAll(new Scale(scaling,scaling));
        });

        canvas.setWidth(WIDTH);
        canvas.setHeight(HEIGHT);

        // help appears in overlay layer at left scene border, 10% from top
        helpRoot.setTranslateX(8);
        helpRoot.setTranslateY(HEIGHT * 0.1);

        friendlyGhostImage = new ImageView(AppRes.Graphics.friendlyGhostIcon);
        friendlyGhostImage.setPreserveRatio(true);
        friendlyGhostImage.setFitHeight(20);
        friendlyGhostImage.setTranslateX(-20);
        friendlyGhostImage.setTranslateY(helpRoot.getTranslateY());
        friendlyGhostImage.setOnMousePressed (e -> Actions.showHelp());

        overlay.getChildren().addAll(helpRoot, friendlyGhostImage);

        layers.getChildren().addAll(canvasPane, overlay);
        root.setCenter(layers);

        infoVisiblePy.bind(Env.showDebugInfoPy);
    }

You will need to remove the round corners from the canvas as they will be now in that container.

salmonb commented 1 year ago

hi Armin, just to let you know, I created a new webfx-bundle branch that you can merge into the webfx branch if you want (and delete webfx-bundle once done). It does load the bundles from messages.properties (sorry for the dirty hardcoding in the initial version). FYI it's necessary to list messages.properties as an embed resource in webfx.xml to make this work (otherwise loading the resource would be asynchronous) and run webfx update (already done in webfx-bundle).

Just a suggestion for the font used in the help: wouldn't it be better to use a monospace font (ex: Courier) to get the shortcuts aligned in the right part?

armin-reichert commented 1 year ago

Hi Bruno,

thanks for the effort. Message bundles are not so important for this demo but I will do what you suggested.

What about the persistent high scores? Would it be much work to make these work too?

I changed the font in the help menus. When changing the font size I observed that in GWT, GridPane.setHgap() and GridPane.setVgap() seem to have no effect. Is this a known issue?

salmonb commented 1 year ago

GridPane.setHgap() and GridPane.setVgap() do have effect (try with a big value like 100 and you will see). Maybe it's more a difference between the font metrics between JavaFX & HTML? I will have a deeper look later...

For the high scores persistence, yes it's possible. I will create a new branch for this that you will merge to webfx. Will let you know once done.

armin-reichert commented 1 year ago

I just pushed some changes (monospace font, workaround for grid gap issue).

BTW: Yesterday, I observed differences between my local GWT version and the version created by the build on the website. Do I have to update something locally to get them in sync again?

salmonb commented 1 year ago

That's probably because I pushed my fixes on WebFX yesterday (that's why I sent you a message). This is immediately considered on the GitHub workflow because the workflow rebuilds a new VM from scratch and therefore always download the latest Maven snapshots. But on your local machine, Maven does a snapshot refresh only once a day (on first invocation). So your local WebFX snapshots were not the same in the meantime.

πŸ’‘ Tip: you can use webfx update -c to force the snapshot cleaning (as mentioned in webfx update -H)

armin-reichert commented 1 year ago

I just merged webfx-bundle into my local webfx branch. Now I get errors: Package 'dev.webfx.platform.useragent' is declared in module 'webfx.platform.useragent', but module 'pacman.ui.fx' does not read it

What to do?

salmonb commented 1 year ago

webfx update is always a good try

armin-reichert commented 1 year ago

At least it transforms compile errors into runtime errors :-) Exception in thread "Thread-1" java.lang.RuntimeException: Exception in Application init method at javafx.graphics@19/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:896) at javafx.graphics@19/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:196) at java.base/java.lang.Thread.run(Thread.java:833) Caused by: java.nio.file.InvalidPathException: Illegal char <:> at index 4: file:\C:\Users\Armin\IdeaProjects\webfx-demo-pacman\pacman-ui-fx\target\classes\de\amr\games\pacman\ui\fx\assets\texts\messages.properties at java.base/sun.nio.fs.WindowsPathParser.normalize(WindowsPathParser.java:182) at java.base/sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:153) at java.base/sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:77) at java.base/sun.nio.fs.WindowsPath.parse(WindowsPath.java:92) at java.base/sun.nio.fs.WindowsFileSystem.getPath(WindowsFileSystem.java:232) at java.base/jdk.internal.module.Resources.toSafeFilePath(Resources.java:143) at java.base/jdk.internal.module.Resources.toFilePath(Resources.java:97) at java.base/jdk.internal.module.ModuleReferences$ExplodedModuleReader.find(ModuleReferences.java:382) at java.base/jdk.internal.loader.BuiltinClassLoader$2.run(BuiltinClassLoader.java:464) at java.base/jdk.internal.loader.BuiltinClassLoader$2.run(BuiltinClassLoader.java:459) at java.base/java.security.AccessController.doPrivileged(AccessController.java:569) at java.base/jdk.internal.loader.BuiltinClassLoader.findMiscResource(BuiltinClassLoader.java:458) at java.base/jdk.internal.loader.BuiltinClassLoader.findResource(BuiltinClassLoader.java:341) at java.base/java.lang.ClassLoader.getResource(ClassLoader.java:1404) at java.base/java.lang.ClassLoader.getResourceAsStream(ClassLoader.java:1738) at webfx.platform.resource.java@0.1.0-SNAPSHOT/dev.webfx.platform.resource.spi.impl.java.JavaResourceProvider.getResourceInputStream(JavaResourceProvider.java:44) at webfx.platform.resource.java@0.1.0-SNAPSHOT/dev.webfx.platform.resource.spi.impl.java.JavaResourceProvider.getText(JavaResourceProvider.java:38) at webfx.platform.resource@0.1.0-SNAPSHOT/dev.webfx.platform.resource.Resource.getText(Resource.java:31) at pacman.ui.fx/de.amr.games.pacman.ui.fx.util.ResourceManager.loadBundle(ResourceManager.java:135) at pacman.ui.fx/de.amr.games.pacman.ui.fx.app.AppRes$Texts.load(AppRes.java:91) at pacman.ui.fx/de.amr.games.pacman.ui.fx.app.AppRes.lambda$load$3(AppRes.java:56) at pacman.ui.fx/de.amr.games.pacman.ui.fx.app.AppRes.load(AppRes.java:62) at pacman.ui.fx/de.amr.games.pacman.ui.fx.app.AppRes.load(AppRes.java:56) at pacman.ui.fx/de.amr.games.pacman.ui.fx.app.PacManGameAppFX.init(PacManGameAppFX.java:73) at webfx.kit.openjfx@0.1.0-SNAPSHOT/dev.webfx.kit.launcher.spi.impl.openjfx.JavaFxWebFxKitLauncherProvider$FxKitWrapperApplication.init(JavaFxWebFxKitLauncherProvider.java:102) at javafx.graphics@19/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:825) ... 2 more

salmonb commented 1 year ago

webfx update fixed the previous issue. What's happening now is a Windows error when trying to read the file (but your GWT should work). It looks like Windows doesn't like the 'file:' prefix in the path. I will see what I can do...

armin-reichert commented 1 year ago

As mentioned, this has no priority at all. Maybe we should just create a list of all the issues found and give them priorities. I really do not want to steal your time with such things.

salmonb commented 1 year ago

It's actually good that you report these problems, as I don't have a Windows computer (I have an iMac & a Linux laptop).

I think I fixed the problem (it was in the WebFX Platform layer). Now pushed. Can you run webfx update -c and let me know if this solves the issue?

You are my Windows tester πŸ˜„

armin-reichert commented 1 year ago

Strange. After webfx update -c I cannot use the run configuration in IntelliJ anymore. I get java.lang.ClassNotFoundException: dev.webfx.platform.boot.ApplicationBooter.

salmonb commented 1 year ago

Sometimes IntelliJ gets confused with all these modules. Try "Reload all Maven projects" (the recycling icon in the Maven tool windows on the right). Let me know if it helps.

armin-reichert commented 1 year ago

Yes, that helped! Now I can run the (merged) webfx-bundle branch locally without errors, in the VM and in the GWT version. Changes in the messages.properties file also appear in the help menu.

However, what do I have to do to get the German bundle messages_de.properties at runtime? In Eclipse, I add the VM parameters -Duser.language -Duser.country=de to get that but I didn't success to do that with the WebFX PacMan run configuration in IntelliJ. Or is the locale-dependent loading not yet implemented?

salmonb commented 1 year ago

Great, this means that the Windows bug is fixed! Thank you! πŸ˜ƒ

You can't pass VM parameters to the browser, but maybe you can use dev.webfx.platform.windowlocation.WindowLocation.getQueryString(). Then if you add ?lang=de to the browser url, that method will return lang=de and then you can read messages_de.properties instead in ResourceManager.loadBundle(). To make this work, you will need to list messages_de.properties in the embed resources in webfx.xml. Let me know if you need more help with this.

armin-reichert commented 1 year ago

I wanted to add the VM parameters to the IntelliJ run config to test it with the VM. How can I do that? The browser is another question. But as I said the resource bundle support has prio lower than low.

salmonb commented 1 year ago

Right now the WindowLocation methods (such as getQueryString()) returns null in the JVM, but maybe I could add a possibility to initialise the window location from VM parameters, and then you could pass ?lang=de when running in the JVM? In this way the same java code would work for both the browser and the JVM (which is the goal of WebFX). What do you think?

Alternatively, you can add a language menu (EN & DE) in your game, and we persist that setting. But it's more work for you...

Regarding the score persistence, I think I have something ready. Are you ok if I push that in the webfx branch of webfx-demo-pacman-core?

armin-reichert commented 1 year ago

Hi Bruno,

feel free to make any changes without asking me.

I will continue tomorrow, old men must rest and also have a wine cellar to work on. Malescasse 2009 or Capbern-Gasqueton 2012, that's the question for today :-)

salmonb commented 1 year ago

What do you mean old? You said you were 56! I'm not far behind... 🀣

Ok I pushed the changes, which updated the webfx-demo-pacman-core snapshots. You can get them with webfx update -c in webfx-demo-pacman (this will also update your build chain with a new WebFX module added for the persistence -> you will need to include these changes in your next commit & push to GitHub).

A difficult question for the day! But whatever your choice, enjoy! 🍷 And then rest! πŸ›Œ πŸ˜„