HTML5 Build no longer finishes loading

Once loaded cards should be laid on the table like so…

But the HTML5 build is stalled somehow. It has loaded the table top and the cursor sprites but no cards…

The browser seems stalled.

What does the console say?

1 Like

I can’t open the console window. The app seems to have hung.

The entire browser hangs?
I would have thought that a webpage wouldn’t hang the browser itself.

Which browser is this?
Have you tried another browser?

2 firefox windows with the same URL. For some reason the window on the left is loading and the window on the right is not. I copy-pasted the URL from left to right…

The right-hand window eventually shows an error dialog…

I’ve now made a mac build and a windows build. The mac build exhibits the same behaviour as theHTML5 build. But thewWindows build works as expected.

Hmm, would it be possible for tou to share a repro case with us, and we can try it out?

The project is pretty small so might be easiest to share the whole thing rather than try to isolate the problem. Will see about permissions.

1 Like

I think I have isolated the problem to a a set material call:

go.set("#sprite", "material", self[message.fan_position .. "_material"])

I am using this as a hack to group cards at different height layers…

Ideally, I would not have to resort to this and there would be a mechanism to define the draw order that does not hack into using material tags and predicates…

Is this something that started happening recently? Did you update to a newer version of Defold?

I wonder what the three ... are ?
Is that valid Lua? :thinking:

Still, I wouldn’t expect setting a material to hang the application, and I think it’s still relevant to share the app for us to test out.

Ideally, I would not have to resort to this and there would be a mechanism to define the draw order that does not hack into using material tags and predicates…

Currently, it’s only our gui that has that level of control with the draw order and layers.

Ohh, nice catch! The three … is valid but it is the varargs of a function:

local function foobar(...)
    local args = { ... }
    for i=1,#args do
        print(args[i])
    end
end

go.set("#sprite", “material”, self[message.fan_position … “_material”])

For a moment there I thought you guys had found a typo but the actual code is this:

Screenshot 2024-04-22 at 08.35.35.png

I pasted it from this code but you can see it has changed some but not all of the double quotes as well! So I guess it turned 2 dots into an ellipsis when I pasted the code. Something to watch for in future.

EDIT: This forum text box does indeed convert dot dot into … unless you put it in a code block. Oops.

Is this something that started happening recently? Did you update to a newer version of Defold?

I update the engine whenever there is a new version. I did not notice this problem until I started making an HTML5 build as it works fine in the editor so I don’t know when it came in.

Could you please create a minimal project where this happens so that we can have a look?

Working on that today.

I have been able to open a console and I can see these:

ERROR: Viewport argument key “minimal-ui” not recognized and ignored.

WARNING: WebGL: non-portable extension enabled: WEBGL_polygon_mode

1 Like

Thanks for the help. I have found the issue… It was a infinite loop (that I did not protect against sufficiently). It only surfaced on web builds due to some subtle timing difference in the initialisation of the camera is what I’m guessing.

rendy.screen_to_world() is being called with a camera.viewport_pixel_width and camera.viewport_pixel_height equal to 0,0 which results in vector4(nan, nan, nan, nan) being used in the subsequent calculations.

I now use a modified version of screen_to_world with additional checks:

	screen_to_world = function(camera, screen_x, screen_y, input_z)
		local function is_within_viewport()
			return camera.viewport_pixel_x <= screen_x
			and screen_x <= camera.viewport_pixel_x + camera.viewport_pixel_width
			and camera.viewport_pixel_y <= screen_y
			and screen_y <= camera.viewport_pixel_y + camera.viewport_pixel_height
		end

		if not is_within_viewport() then
			return
		end

        -- ADDITIONAL CHECKS
		if camera.viewport_pixel_width == 0 then return end
		if camera.viewport_pixel_height == 0 then return end

		local inverse_frustum = vmath.inv(camera.frustum)

		-- convert to clip space
		local clip_x = (screen_x - camera.viewport_pixel_x) / camera.viewport_pixel_width * 2 - 1
		local clip_y = (screen_y - camera.viewport_pixel_y) / camera.viewport_pixel_height * 2 - 1

		-- make both a near and a far position by projecting back to world space with different z's		
		local near_world_position = vmath.vector4(inverse_frustum * vmath.vector4(clip_x, clip_y, -1, 1))
		local far_world_position = vmath.vector4(inverse_frustum * vmath.vector4(clip_x, clip_y, 1, 1))
		
		-- scale it back so w == 1
		near_world_position = near_world_position / near_world_position.w
		far_world_position = far_world_position / far_world_position.w

		-- this is a ratio for lerping
		local frustum_z = (input_z - camera.z_min) / (camera.z_max - camera.z_min)

		local world_position = vmath.lerp(frustum_z, near_world_position, far_world_position)

		return vmath.vector3(world_position.x, world_position.y, world_position.z)
	end
1 Like