FREE: Web UI (HTML/CSS/JS Interface)

Hi SergiuHulpe,

I am looking for the sample project in VUE.JS which you refer to, but I cannot find it. Are you referring to the project which comes with the plugin, available at

https://github.com/tracerinteractive/UnrealEngine/releases/download/4.27.0/WebUI-4.27.zip

in the directory that contains:

WebUI-4.27\Example\Content\HTML\sample.html

Thanks!

Hi! Protocasting,

I haven’t used this in a really long time, but as I remember, yes, the project which comes with the plugin has a webpage built using Vue.JS, but I think spidershift should confirm that.

Why are you interested in that? are you also trying to build the UI using Vue.JS?

Thanks @SergiuHulpe ,

Yes, I couldn’t find it there. Maybe the sample has been updated and no longer uses VUE.JS? @spidershift

I am actually trying to integrate an eCommerce API using VUE.JS to do a demo of real-world commerce from within Unreal Engine. So, linking virtual and physical worlds. e.g. you order a pizza from an in-game delivery man character and a delivery man comes to your actual door with pizza.

I was trying to use BLUI, but it seems like there are some problems with the DLL’s from CEF. So, I figured it’s worth a try with spidershift’s plugin.

It would be great to find an example using VUE.JS if you remember where you found the sample code (which plugin version). I want to use the API functions and also integrate that with a nice transparent overlay widget in Unreal.

Thanks!

I wonder if I can just use the Web Browser plugin, and VaREST to handle the JSON and REST communications? Maybe that’s simpler than taking a wholly forked version of the engine to be able to do this. I’m curious what your recommendation is as the developer, @spidershift ?

@spidershift - I had a question re: Transparency. When Enable Transparency is set to true, is there a way to find out via blueprints if the mouse is being blocked by UI or being passed through to the game?

The documentation states “This directs the underlying slate widget to sample the pixel under the mouse position on each game tick and dynamically toggles the widget between Hit Test Invisible and Visible modes.”

Based on the above, I’ve tried to sample the visibility value of my WebUI widget, however it does not appear to be changing dynamically when I print the visibility Enum to screen. It just stays at whatever the default setting is. Maybe I’ve interpreted the above wrong.

My use case is I’m performing a raycast in an event tick elsewhere in my app. I want to prevent the raycast from occurring when I’m hovering UI. I need to use the transparency feature because I have a complex, Vuetify based UI with multiple cards which runs as a full screen widget (to make full use of responsiveness etc)

I could check via Javascript what I’m hovering and send that back to UE4, but it seems unnecessary if you’re already sampling the transparency values to determine if the mouse input should pass through.

Hi everyone!

First of all I would like to thank you guys for sharing this plugin! It was a lifesaver to say the least! With it i was able to use Mansory js to create a mansory photo gallery in a way i could never replicate using only UMG slate panels.

In fact this is the reason i need some help. I followed the documentation until the and i could ship a “WindowsNoEditor” for my gallery using Shipping Build. It works just fine for windows builds but when i try to package it for my mobile (a Xiaomi Pocophone F1) it shows a black screen and an Android Logo on the top left corner. These are the pictures from the windows build and the android one:

As you guys can see: I have a vertical box with a text block and the plugin’s browser component as children. For some reason the latter can’t render on mobile…

// HTML

</header>
<script src="./js/ue4-interface-script.js"></script>
<script src="https://unpkg.com/masonry-layout@4/dist/masonry.pkgd.min.js"></script>
<script src="https://unpkg.com/imagesloaded@4/imagesloaded.pkgd.min.js"></script>
<head>
    <link rel="stylesheet" type="text/css" href="./style/css.css">
</head>
 <body>
    <div class="grid">
    </div>

</body>

<script>
    
    ue4("start")
    
    ue.interface.drawImages=function(config){
        
        
        console.log("load")
        console.log(config)

        let folder = "./imgs/gallery/"
        let grid = document.querySelector(".grid")
        config.names.forEach(name =>{ 
         let finalPath = folder + name
         ue4("printFileName",finalPath,function(fixedAbsolutePath)
         {
            finalPath = fixedAbsolutePath
         },2)
         let newImg = document.createElement("img");
         newImg.classList.add("grid-item")
         newImg.src=finalPath
         //console.log(finalPath)
         newImg.setAttribute("id",name)
         newImg.style.width= (config.width + "px")
 

         grid.appendChild(newImg)
         newImg.addEventListener("click", e =>{
            ue4("click!",e.path[0].id)
            
         })
         
        })

        ue4("Images created!", {}, function(updateMasonry)
        {
            var options = 
            {
                /*columnWidth:5,*/
                itemSelector: '.grid-item', 
                gutter:10,
                horizontalOrder:true, 
                transitionDuration:'1.0', 
                originTop:true,
                resize: true, 
                fitWidth: true
            }
            
            var elem = document.querySelector('.grid');
            var msnry = new Masonry( elem, options)
         
        },3)
    }
    
    function imgClick(e)
    {
        ue4("click!")
        console.log(e.id)
    }
    
        
    
</script>

//Css


.grid-item{
    margin-bottom: 10px;
    
    
}

.grid {
    margin: 0% auto;
  }

body{
    background-color: aliceblue;
}

//Interface Script

// create the global ue4(...) helper function
        "object"!=typeof ue&&(ue={}),uuidv4=function(){return"10000000-1000-4000-8000-100000000000".replace(/[018]/g,function(t){return(t^crypto.getRandomValues(new Uint8Array(1))[0]&15>>t/4).toString(16)})},ue4=function(r){return"object"!=typeof ue.interface||"function"!=typeof ue.interface.broadcast?(ue.interface={},function(t,e,n,o){var u,i;"string"==typeof t&&("function"==typeof e&&(o=n,n=e,e=null),u=[t,"",r(n,o)],void 0!==e&&(u[1]=e),i=encodeURIComponent(JSON.stringify(u)),"object"==typeof history&&"function"==typeof history.pushState?(history.pushState({},"","#"+i),history.pushState({},"","#"+encodeURIComponent("[]"))):(document.location.hash=i,document.location.hash=encodeURIComponent("[]")))}):(i=ue.interface,ue.interface={},function(t,e,n,o){var u;"string"==typeof t&&("function"==typeof e&&(o=n,n=e,e=null),u=r(n,o),void 0!==e?i.broadcast(t,JSON.stringify(e),u):i.broadcast(t,"",u))});var i}(function(t,e){if("function"!=typeof t)return"";var n=uuidv4();return ue.interface[n]=t,setTimeout(function(){delete ue.interface[n]},1e3*Math.max(1,parseInt(e)||0)),n});

Thank you in advance!

Updates! Now instead a black screen i got this:

Did I miss something in the docs here regarding performance: https://cdn.tracerinteractive.com/webui/documentation.pdf ?

I’ve set up this plugin in a blank TPP project on 4.27, and in a few other projects I have on 4.27. The implementation is the 2-file widget hud barebones detailed in the above pdf. On the blank project best browser fps using the following code I can get is about 35-40 fps at 1080p, and about 15-17fps at 2160p. This is measured using the following js:

var lastCalledTime;
var fps;

const times = [];

function refreshLoop() {
  window.requestAnimationFrame(() => {
    const now = performance.now();
    while (times.length > 0 && times[0] <= now - 1000) {
      times.shift();
    }
    times.push(now);
    fps = times.length;
    $("#fpsMeter").text(fps.toFixed(1) + " FPS");
    refreshLoop();
  });
}

I noticed this at first when css transitioned elements were taking a bit to respond. Maybe I’m just dumb and missed something. Thanks if you read this and thanks for the plugin - threw some food monies at your website.

Other specs if you care: i7-11700k, RTX 3090 - games at 120 cap.

I’ve got the same problem, looks like the WebView can not parse the custom url scheme.

Hi there, sorry if this has been mentioned already, but is it possible to stop people opening the developer tools with CTRL-SHIFT-I?

Yes it has been mentioned already. If you actually take the time to read the documentation, it literally says on page 29, and quote…

“The browser can be debugged by using CTRL+SHIFT+I when focused. This key combination
opens the Chrome DevTools and is only available in development and debug builds.

image

We found that keyboard input on the webpage will also be passed to the underlying UE scene. For example, as the above image shows, I input ‘w’ on the webpage, not only ‘w’ is captured by the webpage, but also my pawn will move forward.

So One question/issue: how to forbid input on the webpage being passed to UE? Thanks a lot!

1 Like

The plugins have been updated for UE5…

JsonLibrary: 5.0
WebUI: 5.0

There are a few known issues after initial testing which are outlined on the releases page:

github.com/tracerinteractive/UnrealEngine/releases/tag/5.0.0

Tried with UE 5.0 and UE 4.24, but still impossible to get acceptable performance.

GTX 1080:
1080p → 45 fps
2k → 10 fps

Fantastic plugin but unusable.

Any tip on how to improve the performance?
image

Thanks

There’s no way to improve the performance, because the UE CEF implementation lacks GPU acceleration. The whole thing runs on CPU. The plugin is completely useless if you aim for dynamic widget like this Examples - Apache ECharts chart for example.

That used to be true, but not anymore. As I already mentioned, there is a new feature that hasn’t been enabled yet called accelerated paint.

In fact I was just running some tests of my own, so that anyone else reading this wouldn’t be basing all their performance stats on only that other guy. I even used the same graphics card and performance website with the flying UFOs…

GTX 1080:
1080p → 60 fps (with and without mouse transparency)
2K → 20 fps (with mouse transparency) 30 fps (without)

ACCELERATED PAINT:
1080p → 60 fps (with and without mouse transparency)
2K → 60 fps (with and without mouse transparency)

If anyone wants to try accelerated paint before it is updated, then all you have to do is change this piece of code and recompile the plugin:

Source\WebBrowserUI\Private\CEF\CEFWebInterfaceBrowserWindow.cpp

Lol the guy asked nicely. If you weren’t hysterical and actually knew a thing about the plugin, you would know that it uses CEF without GPU acceleration for rendering. That’s why the whole thing is utterly slow.

Btw when one needs to render something more complex than a simple online FPS counter, like a dynamic chart with many data points, they would easily fall below 10 FPS even @1080p.

No they didn’t ask nicely. It’s one thing to say “i’m having trouble with this” or “did i do something wrong” or “do you have any performance tips” but it’s another to just come in and say “these are the performance numbers i got, so therefore this thing is useless” which is exactly what they did.

Not only does it make the assumption their performance is the only one that matters, but also dismisses the fact that plenty of developers have been using this plugin for a long time. On top of that did you seriously just say I don’t know anything about the plugin? …because I’m literally the OP. The fact that you think I don’t know this uses the CEF without GPU acceleration is beyond laughable. Why don’t you go back to your little vector graphics library and focus on the 10 people that downloaded that.

But it is useless for them if they need it to run above 45 FPS @1080p. Also, from my own experience, there’s also a noticeable lag between the user input and the plugin’s response. Nobody said that the plugin doesn’t find its use in other projects made by other people. Suggesting to rewrite a line of code and completely ignore the warning just above that saying it may break the whole thing on multi-GPU systems is just beyond ridiculous. A polite answer like “You can’t get better performance right now because of an issue I’ve been unable to solve so far, but you can do this and this to improve the performance for non-production purposes. I’ll let you know once I figure it out.” probably would hurt your ego too much, I don’t know.

Obviously, in its current state, the plugin performs just terribly for some people. It’s very sad If you, the OP, can’t accept that simple fact. Once you solve the multi-GPU issue, I myself will be happy to use the plugin in a side project I’m working on.

Btw it’s more like 272 people actually using my plugin including a carmaker with whom I’m working closely on implementing UE4&DP into their infotainment, but who’s counting…

1 Like

Asking for tips on how to improve performance is exactly what I did. If you read my post entirely, I say at the end:
Any tip on how to improve the performance?

I am trying (just trying and for hobby) to do an entire UI with moving windows and other elements inside of it, entirely in a webpage adapted for UE Gameplay. Obviously, I am not a good UE developer, since I did not expend too much of my developer experience time in the UE ecosystem.

Sorry if I expressed myself wrong but maybe the correct way was to say that for my use case what unusable.
I didn’t just try for 1 hour and come here, I have been waiting for months to see if UE 5.0 with the updated browser makes any changes in performance. I posted in this same post several months ago for the same exact reason, and during that time I spent a lot of time trying to achieve an acceptable performance.

From a gaming-oriented perspective, 60 fps max limit is not acceptable (and I am not achieving even that). For competitive and intensive game players with 120hz screens, they usually want 100-120fps for a UI (at least if they have a good graphic card, like the 1080 is). This makes the plugin unusable for my use case and for any gaming use case that want to display a big interface with moving parts using this plugin, or maybe, I am missing the point, in that case, I am more than open to hearing and explanation for the reason and accept my mistake.

For this reason, I came here and ask for tips on how to improve it because it was unusable for my use case. I also had time to write that it is a fantastic plugin, but you only read my negative words and come to this forum with all your negativity.

I only can suggest you to chill and stop being rude to all the community, and comment with a more open-minded philosophy, because all here are very thankful for the fantastic job you did with the plugin and what you did publishing it completely for FREE, and we post with the best of our intentions.

1 Like