From d4ec643fd6ba373c61a38ec56fe88d12db5e8500 Mon Sep 17 00:00:00 2001
From: Sorata <39014375+q8X@users.noreply.github.com>
Date: Tue, 21 Apr 2026 23:37:07 +0300
Subject: [PATCH] Feature: local move space
---
[editor]/editor_main/client/controls.lua | 1 +
[editor]/editor_main/client/main.lua | 6 ++
[editor]/move_keyboard/meta.xml | 3 +
[editor]/move_keyboard/move_keyboard.lua | 104 +++++++++++++++--------
4 files changed, 79 insertions(+), 35 deletions(-)
diff --git a/[editor]/editor_main/client/controls.lua b/[editor]/editor_main/client/controls.lua
index da6fdf9b3..6ac7126e7 100644
--- a/[editor]/editor_main/client/controls.lua
+++ b/[editor]/editor_main/client/controls.lua
@@ -32,6 +32,7 @@ local defaultControls = {
{ name="mod_rotate", key ="lctrl", friendlyName="Rotate Modifier World Space" },
{ name="mod_rotate_local", key ="rctrl", friendlyName="Rotate Modifier Local Space" },
{ name="high_sensitivity_mode", key ="e", friendlyName="High Sensivity Mode" },
+{ name="local_move_space_mode", key ="v", friendlyName="Local Move Space Mode" },
{ name="element_move_right", key ="arrow_r", friendlyName="Move Element Right / Yaw" },
{ name="element_move_left", key ="arrow_l", friendlyName="Move Element Left / Yaw" },
{ name="element_move_forward", key ="arrow_u", friendlyName="Move Element Forward / Pitch" },
diff --git a/[editor]/editor_main/client/main.lua b/[editor]/editor_main/client/main.lua
index 3f36f99cd..599c8507a 100644
--- a/[editor]/editor_main/client/main.lua
+++ b/[editor]/editor_main/client/main.lua
@@ -1171,6 +1171,7 @@ function bindInput(commandsOnly)
bindControl("redo", "down", keyboardRedo)
bindControl("high_sensitivity_mode", "down", toggleSensitivityMode)
bindControl("lock_selected_element", "down", lockSelectedElement)
+ bindControl("local_move_space_mode", "down", toggleLocalMoveSpaceMode)
end
function unbindInput(commandsOnly)
@@ -1192,6 +1193,7 @@ function unbindInput(commandsOnly)
unbindControl("redo", "down", keyboardRedo)
unbindControl("high_sensitivity_mode", "down", toggleSensitivityMode)
unbindControl("lock_selected_element", "down", lockSelectedElement)
+ unbindControl("local_move_space_mode", "down", toggleLocalMoveSpaceMode)
end
-- get the point and element targeted by the camera
@@ -1329,6 +1331,10 @@ function toggleSensitivityMode ()
end
end
+function toggleLocalMoveSpaceMode()
+ exports.move_keyboard:toggleLocalMoveSpace()
+end
+
function streamInCollessObjects()
if getElementType(source) == "object" then
g_colless[source] = true
diff --git a/[editor]/move_keyboard/meta.xml b/[editor]/move_keyboard/meta.xml
index 177d0ad20..dce871d9d 100644
--- a/[editor]/move_keyboard/meta.xml
+++ b/[editor]/move_keyboard/meta.xml
@@ -16,4 +16,7 @@
+
+
+
diff --git a/[editor]/move_keyboard/move_keyboard.lua b/[editor]/move_keyboard/move_keyboard.lua
index 2a1c14ee1..2ac36a8f2 100644
--- a/[editor]/move_keyboard/move_keyboard.lua
+++ b/[editor]/move_keyboard/move_keyboard.lua
@@ -24,6 +24,8 @@ local MOVEMENT_MOVE = 1
local MOVEMENT_ROTATE_WORLD = 2
local MOVEMENT_ROTATE_LOCAL = 3
+local localMoveSpace = false
+
local hasRotation = {
object = true,
player = true,
@@ -33,6 +35,14 @@ local hasRotation = {
-- PRIVATE
+local function getPositionFromElementOffset(element,offX,offY,offZ)
+ local m = getElementMatrix ( element )
+ local x = offX * m[1][1] + offY * m[2][1] + offZ * m[3][1] + m[4][1]
+ local y = offX * m[1][2] + offY * m[2][2] + offZ * m[3][2] + m[4][2]
+ local z = offX * m[1][3] + offY * m[2][3] + offZ * m[3][3] + m[4][3]
+ return x, y, z
+end
+
local function getCameraRotation ()
local px, py, pz, lx, ly, lz = getCameraMatrix()
local rotz = 6.2831853071796 - math.atan2 ( ( lx - px ), ( ly - py ) ) % 6.2831853071796
@@ -110,38 +120,53 @@ local function onClientRender_keyboard()
speed = moveSpeed.medium
end
- -- convert getCameraRotation output to radians
- camRotZ = math.rad(camRotZ)
- local distanceX = speed * math.cos(camRotZ)
- local distanceY = speed * math.sin(camRotZ)
+ if not localMoveSpace then
+ -- convert getCameraRotation output to radians
+ camRotZ = math.rad(camRotZ)
+ local distanceX = speed * math.cos(camRotZ)
+ local distanceY = speed * math.sin(camRotZ)
- -- right/left
- if (getCommandState("element_move_right")) then
- tempX = tempX + distanceX
- tempY = tempY - distanceY
- end
- if (getCommandState("element_move_left")) then
- tempX = tempX - distanceX
- tempY = tempY + distanceY
- end
+ -- right/left
+ if (getCommandState("element_move_right")) then
+ tempX = tempX + distanceX
+ tempY = tempY - distanceY
+ end
+ if (getCommandState("element_move_left")) then
+ tempX = tempX - distanceX
+ tempY = tempY + distanceY
+ end
- -- forward/back
- if (getCommandState("element_move_forward")) then
- tempX = tempX + distanceY
- tempY = tempY + distanceX
- end
+ -- forward/back
+ if (getCommandState("element_move_forward")) then
+ tempX = tempX + distanceY
+ tempY = tempY + distanceX
+ end
- if (getCommandState("element_move_backward")) then
- tempX = tempX - distanceY
- tempY = tempY - distanceX
- end
+ if (getCommandState("element_move_backward")) then
+ tempX = tempX - distanceY
+ tempY = tempY - distanceX
+ end
- -- up/down
- if (getCommandState("element_move_upwards")) then
- tempZ = tempZ + speed
- end
- if (getCommandState("element_move_downwards")) then
- tempZ = tempZ - speed
+ -- up/down
+ if (getCommandState("element_move_upwards")) then
+ tempZ = tempZ + speed
+ end
+ if (getCommandState("element_move_downwards")) then
+ tempZ = tempZ - speed
+ end
+ else
+ -- local space
+ local x, y, z = 0, 0, 0
+ if getCommandState("element_move_right") then x = x + speed end
+ if getCommandState("element_move_left") then x = x - speed end
+ if getCommandState("element_move_forward") then y = y + speed end
+ if getCommandState("element_move_backward") then y = y - speed end
+ if getCommandState("element_move_upwards") then z = z + speed end
+ if getCommandState("element_move_downwards") then z = z - speed end
+
+ if x ~= 0 or y ~= 0 or z ~= 0 then
+ tempX, tempY, tempZ = getPositionFromElementOffset(selectedElement, x, y, z)
+ end
end
-- check if position changed
@@ -192,9 +217,9 @@ local function onClientRender_keyboard()
else
local tempRotX, tempRotY, tempRotZ = rotX, rotY, rotZ
if (not tempRotX) then return false end
-
+
local yaw, pitch, roll = 0, 0, 0
-
+
-- yaw
if (getCommandTogSTATE("element_move_right")) then
yaw = speed
@@ -208,14 +233,14 @@ local function onClientRender_keyboard()
elseif (getCommandTogSTATE("element_move_downwards")) then
pitch = -speed
end
-
+
-- roll
if (getCommandTogSTATE("element_move_forward")) then
roll = speed
elseif (getCommandTogSTATE("element_move_backward")) then
roll = -speed
end
-
+
-- Perform rotation about one axis at a time
if yaw ~= 0 then
tempRotX, tempRotY, tempRotZ = exports.editor_main:applyIncrementalRotation(selectedElement, "yaw", yaw, world_space)
@@ -289,7 +314,7 @@ local function onClientRender_keyboard()
if (not tempRotX) then return false end
local yaw, pitch, roll = 0, 0, 0
-
+
-- yaw
if (getCommandTogSTATE("element_move_right")) then
yaw = speed
@@ -303,14 +328,14 @@ local function onClientRender_keyboard()
elseif (getCommandTogSTATE("element_move_downwards")) then
pitch = -speed
end
-
+
-- roll
if (getCommandTogSTATE("element_move_forward")) then
roll = speed
elseif (getCommandTogSTATE("element_move_backward")) then
roll = -speed
end
-
+
-- Perform rotation about one axis at a time
if yaw ~= 0 then
tempRotX, tempRotY, tempRotZ = exports.editor_main:applyIncrementalRotation(selectedElement, "yaw", yaw, world_space)
@@ -538,6 +563,15 @@ function toggleAxesLock ( bool )
return true
end
+function toggleLocalMoveSpace()
+ localMoveSpace = not localMoveSpace
+ exports.editor_gui:outputMessage("Local Move Space Mode "..(localMoveSpace and "Enabled" or "Disabled"), 50, 255, 50)
+end
+
+function isLocalMoveSpace()
+ return localMoveSpace
+end
+
function enable()
if isEnabled then
return false