SetupVarTable(editor, "editor.") if FirstLoad then XEditorHideTexts = false XEditorOriginalHandleRand = HandleRand end XEditorHRSettings = { ResolutionPercent = 100, EnablePreciseSelection = 1, ObjectCounter = 1, VerticesCounter = 1, TR_MaxChunksPerFrame=100000, } -- function for generating random handles (used by undo / map patches / map modding) local handle_seed = AsyncRand() function XEditorNewHandleRand(rand) rand, handle_seed = BraidRandom(handle_seed, rand) return rand end function XEditorGetHandleSeed(seed) return handle_seed end function XEditorSetHandleSeed(seed) handle_seed = seed end function IsEditorActive() return editor.Active end function EditorActivate() if Platform.editor and not editor.Active and GetMap() ~= "" then editor.Active = true NetPauseUpdateHash("Editor") local executeBeforeEnter = {} Msg("GameEnteringEditor", executeBeforeEnter) for _, fn in ipairs(executeBeforeEnter) do fn() end OpenDialog("XEditor") HandleRand = XEditorNewHandleRand Msg("GameEnterEditor") SuspendDesyncErrors("Editor") end end function EditorDeactivate() if editor.Active then editor.Active = false local executeBeforeExit = {} Msg("GameExitEditor", executeBeforeExit) for _, fn in ipairs(executeBeforeExit) do fn() end HandleRand = XEditorOriginalHandleRand CloseDialog("XEditor") NetResumeUpdateHash("Editor") ResumeDesyncErrors("Editor") end end function OnMsg.ChangeMap(map) if map == "" then EditorDeactivate() end end if FirstLoad then CameraMaxZoomSpeed = tonumber(hr.CameraMaxZoomSpeed) CameraMaxZoomSpeedSlow = tonumber(hr.CameraMaxZoomSpeedSlow) CameraMaxZoomSpeedFast = tonumber(hr.CameraMaxZoomSpeedFast) end function OnMsg.ChangeMapDone(map) if map == "" then return end local small_map_size = 1024 * guim local map_size = Max(terrain.GetMapSize()) local coef = Max(map_size * 1.0 / small_map_size, 1.0) hr.CameraMaxZoomSpeed = tostring(CameraMaxZoomSpeed * coef) hr.CameraMaxZoomSpeedSlow = tostring(CameraMaxZoomSpeedSlow * coef) hr.CameraMaxZoomSpeedFast = tostring(CameraMaxZoomSpeedFast * coef) end ----- XEditor (the main fullscreen transparent dialog for the map editor) -- -- This dialog's mode is the name of the XEditorTool currently active and created as a child dialog DefineClass.XEditor = { __parents = { "XDialog" }, Dock = "box", InitialMode = "XEditorTool", ZOrder = -1, mode = false, mode_dialog = false, play_box = false, toolbar_context = false, help_popup = false, } function XEditor:Open(...) local size = terrain.GetMapSize() XChangeCameraTypeLayer:new({ CameraType = "cameraMax", CameraClampXY = size, CameraClampZ = 2 * size }, self) XPauseLayer:new({ togglePauseDialog = false, keep_sounds = true }, self) -- editor mode init XShortcutsSetMode("Editor", function() EditorDeactivate() end) XEditorHRSettings.EnableCloudsShadow = EditorSettings:GetCloudShadows() and 1 or 0 table.change(hr, "Editor", XEditorHRSettings) SetSplitScreenEnabled(false, "Editor") ShowMouseCursor("Editor") self.toolbar_context = { filter_buttons = LocalStorage.FilteredCategories, roof_visuals_enabled = LocalStorage.FilteredCategories["Roofs"], } OpenDialog("XEditorToolbar", XShortcutsTarget, self.toolbar_context):SetVisible(EditorSettings:GetEditorToolbar()) OpenDialog("XEditorStatusbar", XShortcutsTarget, self.toolbar_context) if EditorSettings:GetShowPlayArea() then self.play_box = PlaceTerrainBox(GetPlayBox(), nil, nil, nil, nil, "depth test") end -- open editor XDialog.Open(self, ...) CreateRealTimeThread(XEditorUpdateHiddenTexts) self:NotifyEditorObjects("EditorEnter") ShowConsole(false) if IsKindOf(XShortcutsTarget, "XDarkModeAwareDialog") then XShortcutsTarget:SetDarkMode(GetDarkModeSetting()) end -- set up default tool self:SetMode("XSelectObjectsTool") editor.SetSel(SelectedObj and { SelectedObj } or Selection) -- open help the first time if not LocalStorage.editor_help_shown then self:ShowHelpText() LocalStorage.editor_help_shown = true SaveLocalStorage() end end function XEditor:Close(...) -- editor mode deinit XShortcutsSetMode("Game") table.restore(hr, "Editor") SetSplitScreenEnabled(true, "Editor") HideMouseCursor("Editor") CloseDialog("XEditorToolbar") CloseDialog("XEditorStatusbar") CloseDialog("XEditorRoomTools") editor.ClearSel() XShortcutsTarget:SetStatusTextLeft("") XShortcutsTarget:SetStatusTextRight("") XEditorDeleteMapButtons() if self.help_popup and self.help_popup.window_state == "open" then self.help_popup:Close() end if IsValid(self.play_box) then DoneObject(self.play_box) end -- close editor self:NotifyEditorObjects("EditorExit") XDialog.Close(self, ...) end function XEditor:NotifyEditorObjects(method) SuspendPassEdits("Editor") MapForEach(true, "EditorObject", function(obj) if not EditorCursorObjs[obj] then obj[method](obj) end end) ResumePassEdits("Editor") end function XEditor:SetMode(mode, context) if mode == self.Mode and (context or false) == self.mode_param then return end if self.mode_dialog then self.mode_dialog:Close() XPopupMenu.ClosePopupMenus() end self:UpdateStatusText() assert(IsKindOf(g_Classes[mode], "XEditorTool")) self.mode_dialog = OpenDialog(mode, self, context) self.mode_param = context self.Mode = mode self:ActionsUpdated() GetDialog("XEditorToolbar"):ActionsUpdated() GetDialog("XEditorStatusbar"):ActionsUpdated() XEditorUpdateToolbars() if not self.mode_dialog.ToolKeepSelection then editor.ClearSel() end self.mode_dialog:SetFocus() Msg("EditorToolChanged", mode, IsKindOf(self.mode_dialog, "XEditorPlacementHelperHost") and self.mode_dialog.helper_class) end function XEditor:UpdateStatusText() local left_status = mapdata.ModMapPath and _InternalTranslate(mapdata.DisplayName, nil, false) or mapdata.id if config.ModdingToolsInUserMode then local extra_row = (not mapdata.ModMapPath and not editor.ModItem) and "Original map - saving disabled!" or not editor.IsModdingEditor() and "Editor not opened from a mod item - saving disabled!" or editor.ModItem:IsPacked() and "The map's mod is not unpacked for editing - saving disabled!" or string.format("%s%s", editor.ModItem:GetEditorMessage(), Literal(editor.ModItem.mod.title)) -- a saveable mod map left_status = string.format("%s\n%s", left_status, extra_row) else left_status = left_status .. (mapdata.group ~= "Default" and " (" .. mapdata.group .. ")" or "") if EditedMapVariation then left_status = string.format("%s\n