QScriptEngine * ScriptEngineWorker::createScriptEngine(bool supportThreads)
{
	QScriptEngine *engine = new QScriptEngine();
	QLOG_INFO() << "New script engine" << engine << ", thread:" << QThread::currentThread();

	Scriptable<BatteryInterface>::registerMetatype(engine);
	Scriptable<ColorSensorInterface>::registerMetatype(engine);
	Scriptable<DisplayInterface>::registerMetatype(engine);
	Scriptable<EncoderInterface>::registerMetatype(engine);
	Scriptable<EventCodeInterface>::registerMetatype(engine);
	Scriptable<EventDeviceInterface>::registerMetatype(engine);
	Scriptable<EventInterface>::registerMetatype(engine);
	Scriptable<GamepadInterface>::registerMetatype(engine);
	Scriptable<GyroSensorInterface>::registerMetatype(engine);
	Scriptable<FifoInterface>::registerMetatype(engine);
	Scriptable<KeysInterface>::registerMetatype(engine);
	Scriptable<LedInterface>::registerMetatype(engine);
	Scriptable<LineSensorInterface>::registerMetatype(engine);
	Scriptable<MailboxInterface>::registerMetatype(engine);
	Scriptable<MotorInterface>::registerMetatype(engine);
	Scriptable<ObjectSensorInterface>::registerMetatype(engine);
	Scriptable<SensorInterface>::registerMetatype(engine);
	Scriptable<SoundSensorInterface>::registerMetatype(engine);
	Scriptable<QTimer>::registerMetatype(engine);
	qScriptRegisterMetaType(engine, timeValToScriptValue, timeValFromScriptValue);
	Scriptable<VectorSensorInterface>::registerMetatype(engine);

	qScriptRegisterSequenceMetaType<QVector<int>>(engine);
	qScriptRegisterSequenceMetaType<QStringList>(engine);

	engine->globalObject().setProperty("brick", engine->newQObject(&mBrick));
	engine->globalObject().setProperty("script", engine->newQObject(&mScriptControl));

	if (mMailbox) {
		engine->globalObject().setProperty("mailbox", engine->newQObject(mMailbox));
	}

	// Gamepad can still be accessed from script as brick.gamepad(), 'gamepad' variable is here for backwards
	// compatibility.
	if (mBrick.gamepad()) {
		engine->globalObject().setProperty("gamepad", engine->newQObject(mBrick.gamepad()));
	}

	if (supportThreads) {
		engine->globalObject().setProperty("Threading", engine->newQObject(&mThreading));
	}

	for (const auto &step : mCustomInitSteps) {
		step(engine);
	}

	evalSystemJs(engine);

	engine->setProcessEventsInterval(1);
	return engine;
}