/** * RobloxIDEDoc.h * Copyright (c) 2013 ROBLOX Corp. All Rights Reserved. */ #pragma once //this will make sure that we can use qt with boost (else moc compiler errors) #ifndef QT_NO_KEYWORDS #define QT_NO_KEYWORDS #endif // Qt Headers #include #include #include #include #include #include #include #include #include // Roblox Headers #include "GfxBase/ViewBase.h" #include "v8datamodel/Game.h" #include "tool/DragTypes.h" #include "rbx/signal.h" #include "rbx/BaldPtr.h" #include "util/G3DCore.h" #include "tool/DragTypes.h" // Roblox Studio Headers #include "CloudEditAdornable.h" #include "RobloxBasicDoc.h" #include "SelectionHighlightAdornable.h" // 3rd. party #include "Filewatcher/FileWatcher.h" class XmlElement; class RobloxView; class RobloxTreeWidget; class QStringList; class QOgreWidget; class RobloxMainWindow; class RobloxDiagnosticsView; class RecordToggleVerb; class ScreenshotVerb; class RobloxChatWidget; class PlayersDataManager; class EntityProperties; class WorkspaceAnnouncementTooltip : public QFrame { Q_OBJECT public: WorkspaceAnnouncementTooltip(QWidget* parent); void showText(); void hideText(); private: QPushButton* closeButton; QLabel* toolTipLabel; QString lastClosedMessage; void setLastClosedMessage(const QString& messageID) { lastClosedMessage = messageID; } QString& getLastClosedMessage() { return lastClosedMessage; } private Q_SLOTS: void closeText(); }; namespace RBX { class Verb; class Name; class DataModel; class SelectionChanged; class Heartbeat; class Instance; class ViewBase; class ViewRbxGfx; class LuaSourceContainer; namespace Reflection { class Variant; class PropertyDescriptor; } namespace Scripting { class ScriptDebugger; } } class RecentlySavedFilesHandler; typedef QMap tActionIDVerbMap; struct GameState { shared_ptr m_Game; QVector m_Verbs; tActionIDVerbMap m_VerbMap; RBX::BaldPtr m_View; RBX::BaldPtr m_TreeWidget; shared_ptr m_PlayerDataManager; RBX::BaldPtr m_UndoVerb; RBX::BaldPtr m_RedoVerb; #ifdef _WIN32 RBX::BaldPtr m_RecordToggleVerb; #endif rbx::signals::scoped_connection m_ChangeHistoryConnection; SelectionHighlightAdornable m_SelectionHighlightAdornable; }; class RobloxIDEDoc: public QObject, public RobloxBasicDoc, FW::FileWatchListener { Q_OBJECT public: RobloxIDEDoc(RobloxMainWindow* pMainWindow); virtual ~RobloxIDEDoc(); bool openFile(const QString& fileName, bool asNew); bool openStream(const QString& fileName, std::istream* stream, bool asNew); bool open(RobloxMainWindow *pMainWindow, const QString &fileName); void displayWorkspaceMessage(); void initializeNewPlace(); void initializeRobloxView(); IRobloxDoc::RBXCloseRequest requestClose(); IRobloxDoc::RBXDocType docType() { return IRobloxDoc::IDE; } QString fileName() const { return m_fileName; } QString displayName() const; QString windowTitle() const; QString keyName() const { return "RobloxIDEDoc"; } QString initializationScript() const { return m_initializationScript; } virtual const QIcon& titleIcon() const; virtual const QString& titleTooltip() const; QWidget* getViewer(); RBX::DataModel* getDataModel() const { if (m_CurrentGame && m_CurrentGame->m_Game && m_CurrentGame->m_Game->getDataModel()) return m_CurrentGame->m_Game->getDataModel().get(); return NULL; } shared_ptr getEditDataModel() const { return m_EditGame.m_Game ? m_EditGame.m_Game->getDataModel() : shared_ptr(); } bool isPlaySolo() { return (m_PlayGame.m_Game && m_PlayGame.m_Game->getDataModel()); } bool isModified(); bool isSimulating(); bool isLocalDoc() { return m_bIsLocalDocument; } bool save(); bool saveAs(const QString& filename); bool autoSave(bool force); void setAutoSaveLoad(); void resetDirty(RBX::DataModel* dataModel); static const char* getOpenFileFilters(); static const char* getSaveFileFilters(); QString openFileFilters() { return getOpenFileFilters(); } QString saveFileFilters() { return getSaveFileFilters(); } // Material Properties static bool displayAskConvertPlaceToNewMaterialsIfInsertNewModel(); void onWorkspacePropertyChanged(const RBX::Reflection::PropertyDescriptor* pDescriptor); void activate(); void deActivate(); virtual bool doHandleAction(const QString& actionID, bool isChecked); bool actionState(const QString &actionID, bool &enableState, bool &checkedState); bool handleDrop(const QString &fileName); bool handlePluginAction(void *pNotifier, void *pAction); void handleScriptCommand(const QString &execCommand); void setInitializationScript(const QString& script) { m_initializationScript = script; } void onDMItemChanged(shared_ptr item, const RBX::Reflection::PropertyDescriptor* descriptor); void enableUndo(bool enable); void publish(); void setFullScreen(bool fullScreen); RBX::Reflection::Variant evaluateCommandBarItem(const char* itemToEvaluateshared, shared_ptr script); RBX::Verb* getVerb(const QString& name) const; void initializeDataModeHash(); void teleportToURL(QString url, bool play); void loadPlayDataModel(QString url, bool play, bool cloneDataModel, bool isTeleport = false); void closePlayDataModel(); void notifyScriptEdited(shared_ptr modifiedScript); static bool isEditMode(const RBX::Instance* context); bool isCloudEditSession(); static bool getIsCloudEditSession(); void forceViewSize(QSize viewSize); void setReopenLastSavedPlace(bool reopenLastSavedPlace) { m_ReopenLastSavedPlace = reopenLastSavedPlace; } void updateDisplayName(const QString& newDisplayName); static const char* lastOpenedPlaceFileSetting() { return "LastOpenedPlaceFile"; } static const char* lastOpenedPlaceScriptSetting() { return "LastOpenedPlaceScript"; } static const char* lastOpenedPlaceUserID() { return "LastOpenedPlaceUserID"; } void forceReloadImages(const QStringList& contentIds); void initServerAudioBehavior(); void setMuteAllSounds(bool mute); void promptForExistingAssetId(const std::string& assetType, boost::function resumeFunction, boost::function errorFunction); boost::shared_ptr getEditScriptByPlayInstance(RBX::Instance* instance); QString downloadPlaceCopy(); public Q_SLOTS: void exportSelection(std::string filePath = "", RBX::ExporterSaveType exportType = RBX::ExporterSaveType_Selection); void exportPlace() { exportSelection("", RBX::ExporterSaveType_Everything); } void updateFromPlaceID(int placeId); void refreshDisplayName(); private Q_SLOTS: void onDelayedInitializeDebuggerData(); void showImportAssetDialog(QVariant resumeFunctionVar, QVariant errorFunctionVar); private: virtual bool doClose(); bool loadFromStream(std::istream* stream); void createActionIDVerbMap(GameState& gameState); void mapFilesMenu(GameState& gameState); void mapEditMenu(GameState& gameState); void mapViewMenu(GameState& gameState); void mapFormatMenu(GameState& gameState); void mapToolMenu(GameState& gameState); void mapAdvToolsToolbar(GameState& gameState); void mapRunToolbar(GameState& gameState); void mapCameraToolbar(GameState& gameState); void mapStandardToolbar(GameState& gameState); void mapAdvanceBuildToolbar(GameState& gameState); void mapInsertMenu(GameState& gameState); void preProcessVerb(const QStringList &tokens); void applyScriptChanges(); void onIdeRun(bool play); void onIdePause(); void onIdeReset(); bool isIdeRunEnabled(bool play); bool isIdePauseEnabled(); bool isIdeResetEnabled(); bool isObjectRenameEnabled(); void onObjectRename(); void onWaypointChanged(); Q_INVOKABLE void updateUndoRedo(); void openUrl(const std::string url); void InitializeDefaultsFromSettings(); void setDockViewsEnabled(bool state = true); void preFetchResources(); void toggleStats(const QString& stats); void setStatsEnabled(const QString& stats,bool enabled, QAction* verbAction = NULL); void createOptionalDMServices(); void setGridMode(RBX::DRAG::DraggerGridMode gridMode); void setDraggerGridMode(RBX::DRAG::DraggerGridMode gridMode); void setGridSize(int gridSize); void mapActionIDWithVerb(GameState& gameState,const QString &actionID, const RBX::Name &verbName); void mapActionIDWithVerb(GameState& gameState,const QString &actionID, const RBX::Verb *pVerb); void mapActionIDWithVerb(GameState& gameState,const QString &actionID, const char *verbName); RBX::Verb* getVerb(GameState& gameState,const QString& name) const; void cleanupGameState(GameState& gameState); void onContentDataLoaded(); void onContentDataSaved(); QString getUploadURL(); QString getDebugInfoFile(bool isAutoSaveFile = false, const QString& debuggerFileExt = QString()); bool saveScriptsChangedWhileTesting(); void patchPlayModelScripts(); void restoreEditModelScripts(); void createScriptMapping(shared_ptr instance); // file watcher listener virtual void handleFileAction(FW::WatchID watchid, const FW::String& dir, const FW::String& filename, FW::Action action); class PlayModifiedScriptItem { public: PlayModifiedScriptItem() {} boost::shared_ptr instance; rbx::signals::scoped_connection ancestryChangedConnection; }; typedef std::list tPlayModifiedScriptList; typedef std::map > tScriptMap; void onPlayModifiedAncestryChanged(boost::shared_ptr script, boost::shared_ptr newParent); tPlayModifiedScriptList& getPlayModifiedScriptList() { return m_playModifiedScriptList; } void clearPlayModifiedScriptList(); tScriptMap& getScriptMap() { return m_scriptMap; } void addScriptMapping(shared_ptr script, shared_ptr playDataModel); void clearScriptMap() { m_scriptMap.clear(); } std::string getScriptIndexHierarchy(shared_ptr, std::vector& indexHierarchy); shared_ptr getScriptByIndexHierarchy(shared_ptr dataModel, const std::vector& indexHierarchy, const std::string& serviceName); Q_INVOKABLE void placeNameLoaded(QString json); void initializeVideoRecording(GameState& gameState); void cleanupVideoRecording(GameState& gameState); void resetMouseCommand(const char* mouseCommandToReset); shared_ptr cloudEditDetectionAndPlaceLaunch(); struct DebuggerData { struct BreakpointData { int line; bool enabled; //std::string condition; }; struct BreakpointLineNumberOrder { bool operator()(const BreakpointData& lhs, const BreakpointData& rhs) const { return lhs.line < rhs.line; } }; std::list breakpoints; std::list watches; }; typedef std::map, DebuggerData> tDebuggersMap; void saveEditModelDebuggerData(); void updateEditModelDebuggerData(); void initializeDebuggerData(const QString &fileName, const shared_ptr dm, const tDebuggersMap& debuggersMap = tDebuggersMap()); void updateDebuggerManager(const tDebuggersMap& debuggers); void updateDebuggersMap(shared_ptr instance, tDebuggersMap& debuggersMap); void addToDebuggersMap(shared_ptr script, tDebuggersMap& debuggersMap); DebuggerData getDebuggerData(RBX::Scripting::ScriptDebugger* debugger); QString getRecentSaveFile(); void clearOutputWidget(); void searchToolboxByDefaultSearchString(); void onLocalPlayerAdded(shared_ptr newPlayer); void onLocalPlayerNameChanged(const RBX::Reflection::PropertyDescriptor* pDescriptor); Q_INVOKABLE void syncPlayerName(); void appendTimeStampToDisplayName(); void removeTimeStampFromDisplayName(); void updateOnSimulationStateChange(bool run); void setTeamCreateWidgetEnabled(bool state); void initCloudEditObjects(); void enableDownloadPlaceCopy(bool state); GameState m_EditGame; GameState m_PlayGame; GameState* m_CurrentGame; #ifdef _WIN32 RecordToggleVerb *m_pRecordToggle; #endif rbx::signals::scoped_connection m_ChangeHistoryConnection; rbx::signals::scoped_connection m_openUrlConnection; rbx::signals::scoped_connection m_contentDataLoadedConnection; rbx::signals::scoped_connection m_localPlayerConnection; rbx::signals::scoped_connection m_workspacePropertyChangedConnection; rbx::signals::scoped_connection m_dataModelItemChangedConnection; boost::shared_ptr m_GameView; QWidget *m_WrapperWidget; QOgreWidget *m_pQOgreWidget; RobloxDiagnosticsView *m_pDiagViewWidget; FW::FileWatcher *m_pFileWatcher; WorkspaceAnnouncementTooltip *m_AnnouncementWidget; RobloxMainWindow *m_pMainWindow; boost::scoped_ptr m_pRSFHandler; QString m_fileName; QString m_displayName; QString m_initializationScript; QString m_windowTitlePrefix; bool m_bIsLocalDocument; QString m_AutoSaveName; bool m_IsAutoSaveLoad; bool m_RequiresSave; bool m_TestModeEnabled; bool m_ReopenLastSavedPlace; QMutex m_IOMutex; static int sIDEDocCount; QByteArray m_initialDataModelHash; QByteArray m_autoSaveDataModelHash; tPlayModifiedScriptList m_playModifiedScriptList; tScriptMap m_scriptMap; boost::optional m_IsCloudEditSession; tDebuggersMap m_EditDebuggersMap; CloudEditAdornable m_CloudEditAdornable; shared_ptr m_ChatWidget; }; class RecentlySavedFilesHandler { public: RecentlySavedFilesHandler(); ~RecentlySavedFilesHandler(); void addFile(const QString& fileName); void removeFile(const QString& fileName); private: void updateFileList(); void saveFileList(); void readFileList(); QStringList m_RecentlySavedFiles; };