Web Rendering and Interacting
The goal here is to propose a web interface to programme developed on top of TiledLand. Considering that user are not necessary professional of interactive web technologies, we seek for simple but powerful python-based solutions.
Why not classical GUI ? The main advantage of Web rendering is that, game/player server and the human interface can be on different machines. With Web application, we expect that nothing need to be installed on the interactive device other than a web-brother. The main conter part is the cost on computing ressources generated by client/server architecture.
Quick overview:
Python is not directly interpretative by the user web-brother. Several solutions allow developers to abstract web technologies - mainly HTML, JavaScript - by proposing Python-based web-interaction library.
- Streamlit - First tested solution. Very simple to present animated data and add some classical button or other input. It find its limits with huge dashboard or complex interactions.
- Dash by plotly - Similar philosophy than Streamlit, i.e. oriented toward data visualization.
- Remi - For REMote Interface, more oriented as a Web GUI.
Actually we tried Streamlit and Remi and conclude on the dominance of Remi for our usage.
Streamlit :
Regarding tutorial, streamlit allows for interresting data visualization and simple interaction. Test a first interactive program :
pip install streamlit
streamlit run demo/ihm-streamlit/01-basic.py
The solution allows for custom HTML with a empty widget. Test tabletop rendering :
streamlit run demo/ihm-streamlit/02-rendering.py.
However, it is not easy to get control on a program loops, with interaction. For instance, streamlit relies on a session state dictionary to keep variable value from a iteration to another.
The alternative: https://plotly.com/examples/ seems better structures.
Plotly :
We will try this solution some day...
Remi :
A first demo solution is proposed with basic script :
pip install remi
python3 demo/ihm-remi/01-basic.py
Remi is built on object inheritance.
Your application class should inherit from remi.App class and then redefine the main method :
import remi.gui as gui
from remi import start, App
class MyApp(App):
def __init__(self, *args):
super(MyApp, self).__init__(*args)
def main(self):
# Initialize a root GUI Compoenent (a vertical box for instance)
container= gui.VBox( width=400, height=400 )
# define all GUI components initially draw the interface
# connect events trigering (typically button) to an event callback method
# return the root graphical object.
return container
# starts the web server
start(MyApp)
The main method init the graphical user intercafe.
It defines the initial windows components and how there are structured the one with the others.
This method is also used to intialize event handlers associated to the instanciate component.
In fact it is a verry classical GUI programming interface, and Remi inplements it efficiently.
Finally, Remi allows a call periodically to method to generate calculation at a fixed time frequency.
This feature is triggerred with update_interval parrameter at start time, and will call the idle method.
class MyApp(remi.App):
#...
def idle(self):
# step your simulation and redraw for instance
# starts the web server
remi.start(MyApp, address='0.0.0.0', port=20014, update_interval=0.1)
Cf. demo/ihm-remi/02-interact.py script for a complete example of interactive SVG frame.
For tiledLAnd rendering, the main used GUI composnent will be SVG.
With TiledLand Artist and Tabletop, code will looklike :
frame = gui.Svg( width=400, height=300 )
container.append(frame)
tabletop.renderOn( artist )
textsvg= artist.content()
frame.add_child( 'content', textsvg )
artist.clear()
The demo/ihm-remi/03-simulation.py script proposes an entire examples of TiledLand integration with Remi.