Browser build in any plans?

I agree. I have removed step 2 from the directions. I put the directions and my freezify on my server here if you want to take and edit them. I have not verified by rebuilding with them yet.

Note 2 differences in my freezify: 1) I moved all the lines that have to be customized to the top, 2) I replaced the listing of panda lib and module files with directory walks. I think these might be a bit helpful.

Asynchronous is preferred for me. The lua networking is asynchronous and I ‘grew up’ writing device drivers decades ago, so I am comfortable with it (as you might guess from my use of messages). Either way you do it, but I think in async.

I like the wrapper idea. That is what the lua folks at Corona Labs (now Solar2d) did for their targets. In theory could be generalized to Android and iOS.

Actually, none of the keyboard actions appear to work. Do I have to do them a different way? I am using

  self.accept("escape",self.showhideMenu)
  self.accept("q",self.showDescription)

I know there are other ways to capture keystrokes, I will look into them.

I struggled a bit with the keyboard input as well with the Roaming Ralph demo. I think fixing it required changing the Module.canvas function defined in the html file as follows:

            canvas: function() {
                var canvas = document.getElementById('canvas');
                canvas.contentEditable = true;
                canvas.setAttribute("tabindex", "0");
                // Focus the canvas when the mouse enters it.
                canvas.addEventListener('mouseenter',function() {canvas.focus();},false);
                return canvas;
            }(),

This is copy-pasted from the source of this file.

Thank you, that did the trick. (Do you have any better formatted html file I can start from? The html file created by emscripten is a heck of a mess to try to edit.)

Still can’t get physics to load. I tried adding --use-pandaphysics --use-pandaparticlesystem but still got the particle unknown error above. I will try a complete rebuild of panda using those flags instead of update, but I have little hope.

I don’t; the roaming-ralph.html above was just the default-generated one fed through an online HTML formatter. However, I suspect that if you compiled with -s ASSERTIONS=2 or without -O3 it might generate a non-minified HTML file.

I will have to try the physics for myself when I find some time again. Are you using the built-in physics engine in your application? You don’t need panda3d.physics if you are just using the collision system, or if you are using Bullet physics.

Yes, I am only using collision. That is good news, then. All I will need is some way to get remote files.

Thanks for everything. The online formatter worked well, much better than I expected. Thanks.

How do we move forward with requests? It would take very little to adapt my program to use async return, I could do it in 5 min or less, if I had routines to call. It is already designed that way – pull from a queue, request from server, on return from request call the listener (instead of return to the listener for async), pop the queue and restart. All I have to do is substitute the async call for the current call.

But I am not sure I am quite up to writing the shim, unless I have an example of a python routine that directly calls JS (and vv). With such an example, I could probably do it.

Is there a way to detect from Python that it is running in a browser?

The way to move forward is to write a C wrapper around the emscripten_wget interface and write a Python binding around that. I don’t think you can directly call JS from Python (without another C wrapper; it might be nice to have such a general purpose wrapper, but it would be yet more work).

I will see if I can find some time towards the end of the week to hack up an interface one way or another.

In my build of Python, sys.platform is set to “emscripten”. You can also ask Panda which graphics back-end it’s using by checking base.pipe.interface_name which will be “WebGL”.

Of course it has to have C between, as Python is compiled to C first, I realized that later. I’ll see what I can learn about it, but I am not hopeful I can figure it out soon.

Thank you, sys.platform does just what I need.

I’ve made a Python wrapper around a subsection of the emscripten API. This will allow you to interact with JavaScript as well as do asynchronous downloads.

See how it works in my updated editor. Under “Load sample”, choose “emscripten_api_test.py” for some examples of how to use this new module, and “texture_download.py” for a minimal example of rendering a downloaded texture in Panda3D.

To use this module, grab the emscriptenmodule.c (19.4 KB) I’ve attached, and compile it in. The easiest way to do that is to just insert this at the top of your frozenMainCode:

#include "emscriptenmodule.c"

You also need to initialize it and add it to sys.modules, like so, at the appropriate location:

    PyDict_SetItemString(sys_modules, "emscripten", PyInit_emscripten());

This provides just the minimum to get you started; you might want to build an easier-to-use interface around this, more akin to the requests module. Long-term, I think we need to have a real URL mounting system in Panda’s VFS (so that it could download the files automatically, in the background, when you load anything).

You are a hero. Thank you, I will try it. I will build a utility to call this, will show it when I get it running.

BTW, in my browsers (tried Firefox, Chrome, Opera, and Safari) the ‘Load sample’ button is hidden, the list pops up on mouse rollover, but not able to select anything.

Uh, odd. You can call loadSample(3) and loadSample(4) in the JS console in the meantime.

1 Like

Not sure what is going on. I made the program stop after the fetch call to see the error (it went into runaway mode on errors). Top level errors were this:’

File “direct.showbase.ShowBase”, line 2082, in __resetPrevTransform
museum.html:445 TypeError: processEvent() takes 2 positional arguments but 3 were given
museum.js:1 :task(error): Exception occurred in PythonTask resetPrevTransform

You can see it for yourself and the long stack traces. You have to tap on one of the topic buttons to fetch the topic data (just a single img file to start).

I print out the “fetching: …” line just before the call to emscripten.async_wget. There should be only one line after that one, the result of the fetch.

I also note that the images on the wall are not correct. Not rotated correctly. I can get to that later.

I’m seeing this as the top-level error:

FileNotFoundError: [Errno 44] No such file or directory: ‘topics/Europe_1340-1519.csv’

I’m going to need to see the code to be able to troubleshoot further.

I have just finished a new browser module that allows you to make any calls to any JavaScript object, giving you full access to the browser environment from Python. (However, passing a Python class or function to JS code is not yet implemented, so you can’t access Python features from JavaScript.) See the browser_interaction.py sample in the editor (loadSample(5)) to try it out.

The attached browsermodule.c (17.1 KB) can be used in the same way; put an #import at the top of your frozenMainCode and add this to your sys.modules initialization:

    PyDict_SetItemString(sys_modules, "browser", PyInit_browser());

You also need to add the --embind flag to the link step.

2 Likes

That is an old version, I forgot to tell you I am using museum.html

  csvurl = "http://www.ideategames.org/museum/topics/"+self.currentTopic+'.csv'
  if utils.isHTML5:
  	csvurl = "/working_museum.png"
  # 	# avoid browser security issue of http vs https from same server
  # 	csvurl = "topics/"+self.currentTopic+'.csv'
  utils.httpFetch(csvurl,self.currentTopic+'.csv',self.extractData)

Then:

def httpFetch(url,fname,callBack,listener=fetchListener):
	if isHTML5:
		print("fetching: "+str(url))
		handle = emscripten.async_wget(url, fname, onload=callBack, onerror=listener, onprogress=onprogress)
	else:
		tmpdat = requests.get(url)
		if tmpdat.status_code != 200:
			fetchListener(fname,tmpdat.reason)
		else:
			print("received: "+str(tmpdat.encoding))
			if tmpdat.encoding:
				callBack(tmpdat)
			else:
				callBack(tmpdat.content)

I will put the two modules involved (Topics – see lines 162-169 and PPLutilities) on my server at http_fetch.zip

You are probably going to the old version, I might have forgotten to mention that the current game is at ./museum/museum.html not editor.

Sorry for the confusion.

Ah, that was it. Now I get the same error.

So, just to be sure, do you actually have a processEvent function in your application, or is this the processEvent from Panda’s EventManager.py?

If the latter, then I think what’s happening is that the Python heap is getting corrupted. I think I messed up the reference counting. In fact, looking over my code, I definitely did. My apologies.

I think this version of emscriptenmodule.c should fix it:
http://rdb.name/panda3d-webgl/emscriptenmodule.c

I do not have any processEvent in my code. A full search finds it only in museum.wasm.

I rebuilt with the new emscriptenmodule.c with the same result. There is a slight pause before the never-ending stack dump, but it looks the same to me.

My latest dmm_freezify.py is on my server to be sure I did what you said to do.

We have to find a way to isolate this problem down. I am not sure where to start, since I can’t see exactly how you’re invoking emscripten.wget, but I see several options:

  • You could comment out all lines in emscriptenmodule.c containing the exact text Py_DECREF(funcs, PY_XDECREF(funcs, and free(arg). That will cause it to leak memory, but if it no longer crashes, then we know for sure it’s a memory management problem in the emscripten module.
  • Or, you could try to construct a simpler program that uses emscripten.async_wget in the same access pattern as you are using in the real application. If it also crashes, it will be easier to debug, and if it doesn’t, you can further isolate to see what it is doing different from the big application.

The dmm_freezify.py looks fine to me.