Download CommonLua/Editor/XEditor/XEditorPlacementHelper.lua from sirnii/myspace: direct link, hf CLI and curl.
- Browser
- Download file 9.21 kB
-
https://huggingface.co/spaces/sirnii/myspace/resolve/main/CommonLua/Editor/XEditor/XEditorPlacementHelper.lua
- Command line
-
hf download hf://spaces/sirnii/myspace/CommonLua/Editor/XEditor/XEditorPlacementHelper.lua
-
curl -L -o XEditorPlacementHelper.lua https://huggingface.co/spaces/sirnii/myspace/resolve/main/CommonLua/Editor/XEditor/XEditorPlacementHelper.lua
9.21 kB
| ----- XEditorPlacementHelper | |
| -- | |
| -- Each placement helper defines a sub-mode of the default XSelectObjectsTool. | |
| -- Leaf children of XEditorPlacementHelper define shortcust, icons, and rollover | |
| -- descriptions, and are auto-displayed as buttons in the editor statusbar. | |
| -- | |
| -- Placement helpers define the editor's behavior when objects are dragged upon | |
| -- or after initial placement. Editor gizmos are also implemented as placement helpers. | |
| -- | |
| -- The base class is abstract and only defines methods/members that need to be present. | |
| DefineClass.XEditorPlacementHelper = { | |
| __parents = { "InitDone" }, | |
| operation_started = false, | |
| local_cs = false, | |
| snap = false, | |
| HasLocalCSSetting = false, | |
| HasSnapSetting = false, | |
| InXPlaceObjectTool = false, | |
| InXSelectObjectsTool = false, | |
| AllowRotationAfterPlacement = false, | |
| UsesCodeRenderables = false, | |
| Title = "None", | |
| Description = false, | |
| ActionSortKey = "0", | |
| ActionIcon = "CommonAssets/UI/Editor/Tools/VertexNudge.tga", -- proxy icon for testing | |
| ActionShortcut = "", | |
| ActionShortcut2 = "", | |
| } | |
| function XEditorPlacementHelper:GetDescription() | |
| end | |
| function XEditorPlacementHelper:CheckStartOperation(mouse_pos) | |
| -- return true if clicking on this position should start object movement | |
| end | |
| function XEditorPlacementHelper:StartOperation(mouse_pos, objects) | |
| -- initialize and start the movement operation here; you can assume CheckStartOperation was called and returned true | |
| self.operation_started = true | |
| end | |
| function XEditorPlacementHelper:PerformOperation(mouse_pos, objects) | |
| -- perform object movement here | |
| end | |
| function XEditorPlacementHelper:EndOperation(objects) | |
| -- called when the movement operation ends | |
| self.operation_started = false | |
| end | |
| ----- XEditorGizmo, base class for editor gizmos | |
| DefineClass.XEditorGizmo = { | |
| __parents = { "XEditorPlacementHelper", "Mesh" }, | |
| InXSelectObjectsTool = true, | |
| UsesCodeRenderables = true, | |
| thickness = 75, | |
| opacity = 110, | |
| scale = 85, | |
| sensitivity = 100, | |
| update_thread = false, | |
| } | |
| function XEditorGizmo:GetProperties() | |
| return empty_table -- prevent properties of the Mesh class from appearing in the tool settings | |
| end | |
| function XEditorGizmo:Init() | |
| self.update_thread = CreateRealTimeThread(function() | |
| while IsValid(self) do | |
| self.thickness = XEditorSettings:GetGizmoThickness() | |
| self.opacity = XEditorSettings:GetGizmoOpacity() | |
| self.scale = XEditorSettings:GetGizmoScale() | |
| self.sensitivity = XEditorSettings:GetGizmoSensitivity() | |
| self:Render() | |
| WaitNextFrame() | |
| end | |
| end) | |
| end | |
| function XEditorGizmo:Done() | |
| DeleteThread(self.update_thread) | |
| end | |
| function XEditorGizmo:Render() | |
| end | |
| ----- XObjectPlacementHelper - sample implementation / base class, a helper that moves selected/placed objects | |
| DefineClass.XObjectPlacementHelper = { | |
| __parents = { "XEditorPlacementHelper" }, | |
| InXPlaceObjectTool = true, | |
| InXSelectObjectsTool = true, | |
| init_drag_position = false, | |
| init_move_positions = false, | |
| init_orientations = false, | |
| } | |
| function XObjectPlacementHelper:CheckStartOperation(mouse_pos) | |
| local obj = GetObjectAtCursor() | |
| return obj and editor.IsSelected(obj) -- start operation when we drag an already selected object | |
| end | |
| function XObjectPlacementHelper:StartOperation(mouse_pos, objects) | |
| SuspendPassEditsForEditOp(objects) | |
| self:StartMoveObjects(mouse_pos, objects) | |
| self.operation_started = true | |
| end | |
| function XObjectPlacementHelper:PerformOperation(mouse_pos, objects) | |
| self:MoveObjects(mouse_pos, objects) | |
| end | |
| function XObjectPlacementHelper:EndOperation(objects) | |
| self.init_drag_position = false | |
| self.init_move_positions = false | |
| self.init_orientations = false | |
| self.operation_started = false | |
| ResumePassEditsForEditOp() | |
| end | |
| function XObjectPlacementHelper:StartMoveObjects(mouse_pos, objects) | |
| self.init_drag_position = GetTerrainCursor() | |
| self.init_move_positions = {} | |
| self.init_orientations = {} | |
| for i, o in ipairs(objects) do | |
| self.init_move_positions[i] = o:GetPos() | |
| self.init_orientations[i] = { o:GetOrientation() } | |
| end | |
| end | |
| function XObjectPlacementHelper:MoveObjects(mouse_pos, objects) -- override in your child class (this is a sample implementation) | |
| local vMove = (GetTerrainCursor() - self.init_drag_position):SetZ(0) | |
| for i, obj in ipairs(objects) do | |
| obj:SetPos(self.init_move_positions[i] + vMove) | |
| end | |
| Msg("EditorCallback", "EditorCallbackMove", objects) | |
| end | |
| ----- XEditorPlacementHelperHost | |
| local helper_classes | |
| function helpers_button_list(tool_class) | |
| if not helper_classes then | |
| helper_classes = ClassLeafDescendantsList("XEditorPlacementHelper") | |
| table.sort(helper_classes, function(a, b) return g_Classes[a].ActionSortKey < g_Classes[b].ActionSortKey end) | |
| end | |
| local buttons = {} | |
| for _, class_name in ipairs(helper_classes) do | |
| local class = g_Classes[class_name] | |
| if class.Title ~= "None" and class["In" .. tool_class] then | |
| table.insert(buttons, { | |
| toggle = true, | |
| func = function(self, root, prop_id, ged, param) self:SetHelperClass(param) end, | |
| is_toggled = function(self) return self:GetHelperClass() == class_name end, | |
| name = class_name, | |
| param = class_name, | |
| icon = class.ActionIcon, | |
| icon_scale = 100, | |
| rollover = class.Title .. (class.Description and ("\n\n" .. table.concat(class.Description, "\n\n")) or ""), | |
| -- not part of the button definition - used by the tools the helpers are present it | |
| shortcut = class.ActionShortcut, | |
| shortcut2 = class.ActionShortcut2, | |
| }) | |
| end | |
| end | |
| return buttons | |
| end | |
| DefineClass.XEditorPlacementHelperHost = { | |
| __parents = { "InitDone", "XEditorToolSettings" }, | |
| helper_class = false, -- define the default helper in your tool | |
| placement_helper = false, | |
| prop_cache = false, | |
| props_from_helper = false, | |
| } | |
| function XEditorPlacementHelperHost:Init() | |
| self.placement_helper = g_Classes[self.helper_class]:new() | |
| end | |
| function XEditorPlacementHelperHost:Done() | |
| self.placement_helper:delete() | |
| end | |
| function XEditorPlacementHelperHost:GetToolTitle() | |
| return self.placement_helper.Title or self.ToolTitle | |
| end | |
| function XEditorPlacementHelperHost:GetProperties() | |
| if not self.prop_cache then | |
| -- append the placement helper properties after ours | |
| local props = {} | |
| for _, prop_meta in ipairs(InitDone.GetProperties(self)) do | |
| props[#props + 1] = table.copy(prop_meta) | |
| end | |
| self.props_from_helper = {} | |
| for _, prop_meta in ipairs(self.placement_helper and self.placement_helper:GetProperties()) do | |
| self.props_from_helper[prop_meta.id] = true | |
| props[#props + 1] = table.copy(prop_meta) | |
| end | |
| self.prop_cache = props | |
| end | |
| return self.prop_cache | |
| end | |
| function XEditorPlacementHelperHost:GetProperty(prop) | |
| if self.props_from_helper and self.props_from_helper[prop] then | |
| return self.placement_helper:GetProperty(prop) | |
| end | |
| return PropertyObject.GetProperty(self, prop) | |
| end | |
| function XEditorPlacementHelperHost:SetProperty(prop, value) | |
| if self.props_from_helper and self.props_from_helper[prop] then | |
| self.placement_helper:SetProperty(prop, value) | |
| return | |
| end | |
| PropertyObject.SetProperty(self, prop, value) | |
| end | |
| function XEditorPlacementHelperHost:GetHelperClass() | |
| return self.helper_class | |
| end | |
| function XEditorPlacementHelperHost:SetHelperClass(class_name, properties) | |
| self.prop_cache = nil | |
| self.props_from_helper = nil | |
| self.helper_class = class_name | |
| if not IsKindOf(self.placement_helper, class_name) then | |
| self.placement_helper:delete() | |
| self.placement_helper = g_Classes[class_name]:new(properties) | |
| end | |
| local statusbar = GetDialog("XEditorStatusbar") | |
| if statusbar then | |
| statusbar:ActionsUpdated() | |
| end | |
| self:UpdatePlacementHelper() | |
| ObjModified(self) | |
| Msg("EditorToolChanged", GetDialog("XEditor").Mode, self.helper_class) | |
| end | |
| function XEditorPlacementHelperHost:UpdatePlacementHelper() | |
| end | |
| function XEditorPlacementHelperHost:OnShortcut(shortcut, source, ...) | |
| local buttons = helpers_button_list(self.class) | |
| local button = table.find_value(buttons, "shortcut", shortcut) or table.find_value(buttons, "shortcut2", shortcut) | |
| if button then | |
| if self.placement_helper.operation_started then | |
| self.desktop:SetMouseCapture() -- stop current operation if one is in progress | |
| end | |
| self:SetHelperClass(button.name) | |
| return "break" | |
| end | |
| if self.placement_helper:HasMember("OnShortcut") then | |
| return self.placement_helper:OnShortcut(shortcut, source, ...) | |
| end | |
| end | |
| function XEditorPlacementHelperHost:OnMouseButtonDown(pt, button) | |
| if button == "L" then | |
| local ret = self.placement_helper:CheckStartOperation(pt, "btn_pressed") | |
| if ret == "break" then | |
| return "break" | |
| elseif ret then | |
| SuspendPassEditsForEditOp() | |
| self.placement_helper:StartOperation(pt, editor.GetSel()) | |
| self.desktop:SetMouseCapture(self) | |
| return "break" | |
| end | |
| end | |
| end | |
| function XEditorPlacementHelperHost:OnMousePos(pt) | |
| if self.placement_helper.operation_started then | |
| self.placement_helper:PerformOperation(pt, editor.GetSel()) | |
| return "break" | |
| end | |
| end | |
| function XEditorPlacementHelperHost:OnMouseButtonUp(pt, button) | |
| if self.placement_helper.operation_started then | |
| self.desktop:SetMouseCapture() | |
| return "break" | |
| end | |
| end | |
| function XEditorPlacementHelperHost:OnCaptureLost() | |
| if self.placement_helper.operation_started then | |
| self.placement_helper:EndOperation(editor.GetSel()) | |
| ResumePassEditsForEditOp() | |
| end | |
| end | |