- Install required packages for simStubsGen: see simStubsGen's README
- Download and install Qt (same version as CoppeliaSim)
- Checkout, compile and install into CoppeliaSim:
$ git clone https://github.com/CoppeliaRobotics/simQML.git
$ cd simQML
$ git checkout coppeliasim-v4.5.0-rev0
$ mkdir -p build && cd build
$ cmake -DCMAKE_BUILD_TYPE=Release ..
$ cmake --build .
$ cmake --install .NOTE: replace coppeliasim-v4.5.0-rev0 with the actual CoppeliaSim version you have.
NOTE: You may need to set the CMAKE_PREFIX_PATH environment variable to the lib/cmake subdirectory of your Qt installation, i.e. /path/to/Qt/Qt5.9.0/5.9/<platform>/lib/cmake
NOTE: You may need to run the deploy tool to copy additional Qt dependencies to CoppeliaSim, e.g.:
macdeployqt $COPPELIASIM_ROOT_DIR/../.. -qmldir=/path/to/simQML/qml -always-overwrite -verbose=2In order to load QML components, a QML engine must be created:
engine = simQML.createEngine()
simQML.load(engine, '/path/to/Component.qml')When the engine is not needed anymore, it should be destroyed with:
simQML.destroyEngine(engine)Note: destroying the engine would destroy also all components created within that engine, e.g. all the windows.
It is also possible to load QML inline code, using simQML.loadData.
This component can be found in the CoppeliaSimPlugin QML module.
PluginWindow is a subclass of QtQuick.Window which sets some convenience properties and handlers.
It is possible to use any other component, such as QtQuick.Window as the top-level component, but PluginWindow is what makes sense most of the times.
Example:
simQML.loadData(engine, [[
import QtQuick 2.12
import CoppeliaSimPlugin 1.0
PluginWindow {
id: mainWindow
width: 400
height: 300
title: qsTr("QML plugin window")
}
]])It is possible to send events from QML to Lua using the sendEvent (or sendEventRaw) method of the CoppeliaSimBridge component.
For convenience, CoppeliaSimBridge is already instantiated in the PluginWindow component and exposed as the property simBridge.
QML can call simBridge.sendEvent(eventName, eventData) to send an event to Lua.
In order to receive the event in Lua, an event handler must be registered with simQML.setEventHandler:
function myEventHandler(engine, eventName, eventData)
print('received event', eventName, eventData)
end
engine = simQML.createEngine()
simQML.setEventHandler(engine, 'myEventHandler')
simQML.loadData(engine, [[
import QtQuick 2.12
import QtQuick.Controls 2.12
import CoppeliaSimPlugin 1.0
PluginWindow {
id: mainWindow
width: 400
height: 300
title: qsTr("QML plugin window")
Button {
anchors.fill: parent
text: "Click me"
onClicked: mainWindow.simBridge.sendEvent('click', {someData: 42})
}
}
]])It is possible to send events from Lua to QML using the simQML.sendEvent(engine, name, data) Lua function.
In order to receive the event in QML, the handler onEventReceived of the CoppeliaSimBridge object must be implemented.
For convenience, if using the PluginWindow component, that handler is already implemented, and the event will be dispatched as a call to a function defined in the PluginWindow component.
engine = simQML.createEngine()
simQML.loadData(engine, [[
import QtQuick 2.12
import CoppeliaSimPlugin 1.0
PluginWindow {
id: mainWindow
width: 400
height: 300
title: qsTr("QML plugin window")
function myEvent(data) {
console.log("received event 'myEvent', someData=" + data.someData)
}
}
]])
simQML.sendEvent(engine, 'myEvent', {someData = 42})An onInstanceSwitch event with bool argument is sent each time the scene owning the engine becomes active/inactive.
The PluginWindow component already implements the handler for this event, setting the visible property of the Window. Set the sticky property to true to override this behavior.