Skip to content

editor: fixes, random rotation func, getCurrentMapName func, updated scale func #633

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 26 commits into from
Jul 15, 2025
Merged
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
0dc9b6e
Added function getCurrentMapName()
PrimelPrime Mar 21, 2025
56a69a8
Merge branch 'master' of https://github.com/PrimelPrime/mtasa-resources
PrimelPrime May 9, 2025
6a4b1d8
Fix: Issue #603
PrimelPrime May 9, 2025
68f9ce5
Fix: Issue #589
PrimelPrime May 10, 2025
655d983
Update scale functionality; remove deprecated functions setPedRotatio…
PrimelPrime May 10, 2025
94ae228
Only one value should be returned for scale
PrimelPrime May 10, 2025
e4b6c06
Remove unnecessary special handling of scale
PrimelPrime May 10, 2025
adf0b3e
Add advanced options for element scaling and random rotation function…
PrimelPrime May 10, 2025
b08ce6c
Add check for loadedMap in passNewMapSettings function
PrimelPrime May 10, 2025
8c0a266
Implement stripHexCode function and update output messages to remove …
PrimelPrime May 10, 2025
521787a
Fix: linter
PrimelPrime May 10, 2025
640c939
Revert "Remove unnecessary special handling of scale"
PrimelPrime May 10, 2025
4c0e8e6
Fix search being case sensitive
PrimelPrime May 12, 2025
1859c07
Fix search to handle special characters in resource names
PrimelPrime May 12, 2025
28c7ac7
Fix refreshGamemodeSettings to correctly handle new and existing sett…
PrimelPrime May 12, 2025
b5efa95
Quicktest F5 -> get last added gamemode
PrimelPrime May 17, 2025
7de8fad
Fix: create missing entries; validate entries -> remove if invalid
PrimelPrime May 17, 2025
10b89b3
Fix: #637 initalize currentMapSettings.addedGamemodes = {} outside se…
PrimelPrime May 17, 2025
669d1da
Fix: Update quickTest() to only update lastTestGamemode when GridList…
PrimelPrime May 17, 2025
cfb2e30
Add support for scaling markers up/down via keybind as well
PrimelPrime May 19, 2025
7cc935e
Fix: g_minZ = minZ -> g_minZ = minZ or 0 to fix vehicle element creation
PrimelPrime May 19, 2025
5759ca6
Remove redundant code
PrimelPrime May 19, 2025
6b57f8c
Fix: Cloning -> Only set rotation when random rot is enabled
PrimelPrime May 21, 2025
07ce4d7
Revert check for creationParameters.position
PrimelPrime May 28, 2025
9ca4abd
Reintroduce if check for creationParameters.position
PrimelPrime May 28, 2025
90dd3d1
Merge branch 'master' into master
Dutchman101 Jul 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions [admin]/admin/conf/messages.xml
Original file line number Diff line number Diff line change
@@ -249,6 +249,10 @@
<all>Chatbox cleared$by_admin_4all.</all>
<log>ADMIN: $admin has cleared the chatbox.</log>
</group>
<group action="setfpslimit" r="225" g="170" b="90">
<all>FPS limit set to '$data'$by_admin_4all.</all>
<log>ADMIN: $admin has set FPS limit to '$data'</log>
</group>
</server>
<bans>

6 changes: 3 additions & 3 deletions [admin]/admin/server/admin_server.lua
Original file line number Diff line number Diff line change
@@ -608,9 +608,9 @@ function aAction ( type, action, admin, player, data, more )

if ( node ) then
local r, g, b = node["r"], node["g"], node["b"]
if ( node["all"] ) then outputChatBox ( aStripString ( node["all"] ), root, r, g, b ) end
if ( node["admin"] ) and ( admin ~= player ) then outputChatBox ( aStripString ( node["admin"] ), admin, r, g, b ) end
if ( node["player"] ) then outputChatBox ( aStripString ( node["player"] ), player, r, g, b ) end
if ( node["all"] ) then outputChatBox ( aStripString ( node["all"] ), root, r, g, b, true ) end
if ( node["admin"] ) and ( admin ~= player ) then outputChatBox ( aStripString ( node["admin"] ), admin, r, g, b, true ) end
if ( node["player"] ) then outputChatBox ( aStripString ( node["player"] ), player, r, g, b, true ) end
if ( node["log"] ) then outputServerLog ( aStripString ( node["log"] ) ) end
end
end
87 changes: 48 additions & 39 deletions [editor]/edf/edf.lua
Original file line number Diff line number Diff line change
@@ -884,23 +884,29 @@ end

--Returns an element's scale, or its scale element data, or false
function edfGetElementScale(element)
local etype = getElementType(element)
if etype == "object" then
scale = getObjectScale(element)
else
local handle = edfGetHandle(element)
if handle then
scale = getObjectScale(handle)
else
scale = tonumber(getElementData(element,"scale"))
end
end

if scale then
return scale
else
return false
end
local etype = getElementType(element)
if etype == "object" then
scale = getObjectScale(element)
if type(scale) ~= "table" then
scale = select(1, scale) or 1
end
else
local handle = edfGetHandle(element)
if handle then
scale = getObjectScale(handle)
if type(scale) == "table" then
scale = select(1, scale) or 1
end
else
scale = tonumber(getElementData(element,"scale"))
end
end

if scale then
return scale
else
return false
end
end

--Sets an element's position, or its posX/Y/Z element data
@@ -965,28 +971,31 @@ end

--Sets an element's scale, or its scale element data
function edfSetElementScale(element, scale)
local ancestor = edfGetAncestor(element) or element
setElementData(ancestor, "scale", scale)
local etype = getElementType(element)
if etype == "object" then
if setObjectScale(element, scale) then
triggerEvent ( "onElementPropertyChanged", ancestor, "scale" )
return true
end
else
local handle = edfGetHandle(element)
if handle then
if setObjectScale(handle, scale) then
triggerEvent ( "onElementPropertyChanged", ancestor, "scale" )
return true
end
else
setElementData(element, "scale", scale or 1)
triggerEvent ( "onElementPropertyChanged", ancestor, "scale" )
return true
end
end
return false
local ancestor = edfGetAncestor(element) or element
setElementData(ancestor, "scale", scale)
local etype = getElementType(element)
if type(scale) == "table" then
scale = scale[1]
end
if etype == "object" then
if setObjectScale(element, scale) then
triggerEvent ( "onElementPropertyChanged", ancestor, "scale" )
return true
end
else
local handle = edfGetHandle(element)
if handle then
if setObjectScale(handle, scale) then
triggerEvent ( "onElementPropertyChanged", ancestor, "scale" )
return true
end
else
setElementData(element, "scale", scale or 1)
triggerEvent ( "onElementPropertyChanged", ancestor, "scale" )
return true
end
end
return false
end

function edfGetElementInterior(element)
3 changes: 3 additions & 0 deletions [editor]/edf/edf_client.lua
Original file line number Diff line number Diff line change
@@ -189,6 +189,9 @@ end
--Sets an element's scale, or its scale element data
function edfSetElementScale(element, scale)
if scale then
if type(scale) == "table" then
scale = scale[1]
end
if isBasic[getElementType(element)] then
return setElementData(element, "scale", scale)
else
2 changes: 1 addition & 1 deletion [editor]/editor_gui/client/elementproperties.lua
Original file line number Diff line number Diff line change
@@ -448,7 +448,7 @@ local function addPropertyControl( controlType, controlLabelName, controlDescrip
if selectedElement then
if newControl:getLabel() == "model" and (elementType == "object" or elementType == "vehicle") then
local minX, minY, minZ = getElementBoundingBox(selectedElement)
g_minZ = minZ
g_minZ = minZ or 0
local handlerFunction = function ()
local minX2, minY2, minZ2 = getElementBoundingBox(selectedElement)
if minX2 and minY2 and minZ2 then
3 changes: 2 additions & 1 deletion [editor]/editor_gui/client/load.lua
Original file line number Diff line number Diff line change
@@ -75,8 +75,9 @@ function openSearch()
guiGridListSetItemText ( loadDialog.mapsList, row, 3, res["version"], false, false )
end
else
local escapedText = string.gsub(string.lower(text), "([%-%.%+%*%?%[%]%^%$%(%)%%])", "%%%1")
for i,res in ipairs(openResources) do
if string.find(res["friendlyName"],text) then
if string.find(res["friendlyName"], escapedText) then
local row = guiGridListAddRow ( loadDialog.mapsList )
guiGridListSetItemText ( loadDialog.mapsList, row, 1, res["friendlyName"], false, false )
guiGridListSetItemText ( loadDialog.mapsList, row, 2, res["gamemodes"], false, false )
7 changes: 5 additions & 2 deletions [editor]/editor_gui/client/mapsettings_gamemodesettings.lua
Original file line number Diff line number Diff line change
@@ -45,7 +45,10 @@ function refreshGamemodeSettings()
mapsettings.rowValues[subRow] = dataInfo.default
if currentMapSettings.newSettings and currentMapSettings.newSettings[dataName] then
mapsettings.rowValues[subRow] = currentMapSettings.newSettings[dataName]
mapsettings.gamemodeSettings = copyTable ( mapsettings.rowValues )
end

if currentMapSettings.gamemodeSettings and currentMapSettings.gamemodeSettings[subRow] then
mapsettings.rowValues[subRow] = currentMapSettings.gamemodeSettings[subRow]
end
end
if count == 0 then
@@ -58,7 +61,7 @@ function refreshGamemodeSettings()
local row = guiGridListAddRow ( mapsettings.settingsList )
guiGridListSetItemText ( mapsettings.settingsList, row, 1, "No Settings definitions", true, false )
end
currentMapSettings.newSettings = nil
mapsettings.gamemodeSettings = copyTable ( mapsettings.rowValues )
end

local requiredText = { [true]="REQUIRED" }
10 changes: 9 additions & 1 deletion [editor]/editor_gui/client/options_action.lua
Original file line number Diff line number Diff line change
@@ -35,6 +35,14 @@ function optionsActions.elemScalingSnap(value)
optionsData.elemScalingSnap = tonumber(value)
end

function optionsActions.randomizeRotation(value)
optionsData.randomizeRotation = value
end

function optionsActions.randomizeRotationAxis(value)
optionsData.randomizeRotationAxis = value
end

function optionsActions.enableColPatch(value)
local success, isLoaded = editor_main.toggleColPatch(value)
if success then
@@ -170,7 +178,7 @@ function setEditorMoveSpeeds()
move_cursor.setRotateSpeeds ( dialog.slowElemRotate:getValue(), dialog.normalElemRotate:getValue(), dialog.fastElemRotate:getValue() )
move_freecam.setRotateSpeeds ( dialog.slowElemRotate:getValue(), dialog.normalElemRotate:getValue(), dialog.fastElemRotate:getValue() )

move_keyboard.setScaleIncrement ( dialog.elemScaling:getValue() )
move_keyboard.setScalingSpeeds ( dialog.slowElemScale:getValue(), dialog.normalElemScale:getValue(), dialog.fastElemScale:getValue() )

move_keyboard.toggleAxesLock ( dialog.lockToAxes:getValue() )
end
124 changes: 92 additions & 32 deletions [editor]/editor_gui/client/options_backend.lua
Original file line number Diff line number Diff line change
@@ -17,19 +17,23 @@ local xmlVariants = {
["normalElemRotate"]="rotate_normal_speed",
["fastElemRotate"]="rotate_fast_speed",
["slowElemRotate"]="rotate_slow_speed",
["elemScaling"]="scaling_increment",
["normalElemScale"]="scaling_normal_speed",
["fastElemScale"]="scaling_fast_speed",
["slowElemScale"]="scaling_slow_speed",
["lockToAxes"]="movement_lock_to_axes",
["autosnap"]="currentbrowser_autosnap",
["tutorialOnStart"]="tutorial_on_start",
["enableBox"]="enablebox",
["enableXYZlines"]="enablexyzlines",
["precisionLevel"]="precisionlevel",
["precisionRotLevel"]="precisionrotlevel",
["elemScalingSnap"]="scalingSnap",
["elemScalingSnap"]="elemscalingsnap",
["enablePrecisionSnap"]="enableprecisionsnap",
["enablePrecisionRotation"]="enableprecisionrotation",
["enableColPatch"]="enablecolpatch",
["enableRotPatch"]="enablerotpatch",
["randomizeRotation"]="enablerandomrot",
["randomizeRotationAxis"]="randomizerotaxis",
["fov"]="fov",
}
local nodeTypes = {
@@ -49,7 +53,9 @@ local nodeTypes = {
["normalElemRotate"]="progress",
["fastElemRotate"]="progress",
["slowElemRotate"]="progress",
["elemScaling"]="progress",
["normalElemScale"]="progress",
["fastElemScale"]="progress",
["slowElemScale"]="progress",
["lockToAxes"]="bool",
["autosnap"]="bool",
["tutorialOnStart"]="bool",
@@ -63,6 +69,8 @@ local nodeTypes = {
["enableXYZlines"]="bool",
["enableColPatch"]="bool",
["enableRotPatch"]="bool",
["randomizeRotation"]="bool",
["randomizeRotationAxis"]={"X","Y","Z","XY","XZ","YZ","XYZ"},
["fov"]="progress",
}
local defaults = {
@@ -81,20 +89,24 @@ local defaults = {
["slowElemMove"]=.025,
["normalElemRotate"]=2,
["fastElemRotate"]=10,
["slowElemRotate"]=.25,
["elemScaling"]=.1,
["slowElemRotate"]=0.25,
["normalElemScale"]=0.1,
["fastElemScale"]=1,
["slowElemScale"]=0.01,
["lockToAxes"]=false,
["autosnap"]=true,
["tutorialOnStart"]=true,
["enableBox"]=true,
["precisionLevel"]="0.1",
["precisionRotLevel"]="30",
["elemScalingSnap"]="0.1",
["elemScalingSnap"]="0.0001",
["enablePrecisionSnap"]=true,
["enablePrecisionRotation"]=false,
["enableXYZlines"]=true,
["enableColPatch"]=false,
["enableRotPatch"]=true,
["randomizeRotation"]=false,
["randomizeRotationAxis"]="XYZ",
["fov"]=dxGetStatus()["SettingFOV"],
}

@@ -118,36 +130,74 @@ function loadXMLSettings()
outputMessage ( "Map editor settings could not be created!.", 255,0,0 )
return
end
--
local settingsNodes = {}
for gui,nodeName in pairs(xmlVariants) do
local node = xmlFindChild ( settingsXML, nodeName, 0 )
if node then
settingsNodes[gui] = node
else
settingsNodes[gui] = xmlCreateChild ( settingsXML, nodeName )
end
-- check if the entries in the XML are valid, and remove invalid ones
local validNodes = {}
for _, nodeName in pairs(xmlVariants) do
validNodes[nodeName] = true
end

local children = xmlNodeGetChildren(settingsXML)
for i = #children, 1, -1 do
local node = children[i]
local nodeName = xmlNodeGetName(node)
if not validNodes[nodeName] then
xmlDestroyNode(node)
end
end
xmlSaveFile(settingsXML)
--
local settingsTable = {}
for gui,node in pairs(settingsNodes) do
local value
if nodeTypes[gui] == "bool" then
nodeValue = getNodeValue ( node, defaults[gui] )
value = bools[xmlNodeGetValue ( node )]
elseif nodeTypes[gui] == "progress" then
value = tonumber(getNodeValue ( node, defaults[gui] ))
elseif type(nodeTypes[gui]) == "table" then
value = tostring(getNodeValue ( node, defaults[gui] ))
local valid = false
for key,valuePossibility in pairs(nodeTypes[gui]) do
if value == valuePossibility then
valid = true
for gui, nodeName in pairs(xmlVariants) do
local node = xmlFindChild(settingsXML, nodeName, 0)
-- Node should exist after validation, but check anyway
if node then
local value
if nodeTypes[gui] == "bool" then
local nodeValue = xmlNodeGetValue(node)
value = bools[nodeValue]
-- If value is nil (invalid boolean), use default
if value == nil then
value = defaults[gui]
xmlNodeSetValue(node, tostring(value))
outputDebugString("Fixed invalid boolean value for " .. nodeName)
end
elseif nodeTypes[gui] == "progress" then
local nodeValue = xmlNodeGetValue(node)
value = tonumber(nodeValue)
-- If value is nil or out of range, use default
if value == nil then
value = defaults[gui]
xmlNodeSetValue(node, tostring(value))
outputDebugString("Fixed invalid numeric value for " .. nodeName)
end
elseif type(nodeTypes[gui]) == "table" then
local nodeValue = xmlNodeGetValue(node)
value = tostring(nodeValue)
-- Validate enum values
local valid = false
for _, valuePossibility in pairs(nodeTypes[gui]) do
if value == valuePossibility then
valid = true
break
end
end
-- If invalid value, use default
if not valid then
value = defaults[gui]
xmlNodeSetValue(node, tostring(value))
outputDebugString("Fixed invalid enum value for " .. nodeName)
end
end
settingsTable[gui] = value
else
-- This should never happen after validation, but as a fallback
settingsTable[gui] = defaults[gui]
node = xmlCreateChild(settingsXML, nodeName)
xmlNodeSetValue(node, tostring(settingsTable[gui]))
if node then
xmlSaveFile(settingsXML)
end
if not valid then value = defaults[gui] end
end
settingsTable[gui] = value
end
inputSettings ( settingsTable )
doActions()
@@ -167,7 +217,10 @@ function createSettingsXML()
local xml = xmlCreateFile ( "settings.xml", "settings" )
for gui,nodeName in pairs(xmlVariants) do
local node = xmlCreateChild ( xml, nodeName )
xmlNodeSetValue ( node, tostring(defaults[gui]) )
if not node then
node = xmlCreateChild ( xml, nodeName )
xmlNodeSetValue ( node, tostring(defaults[gui]) )
end
end
xmlSaveFile ( xml )
xmlUnloadFile ( xml )
@@ -179,7 +232,14 @@ end

function inputSettings ( settingsTable )
for gui,value in pairs(settingsTable) do
dialog[gui]:setValue(value)
if dialog[gui] then
dialog[gui]:setValue(value)
if nodeTypes[gui] == "progress" then
if optionsActions[gui] then
optionsActions[gui](value)
end
end
end
end
optionsSettings = settingsTable
end
27 changes: 21 additions & 6 deletions [editor]/editor_gui/client/options_gui.lua
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@ function createOptionsDialog()
dialog.generalTab = guiCreateTab("General",tabpanel)
dialog.cameraTab = guiCreateTab("Camera",tabpanel)
dialog.movementTab = guiCreateTab("Movement",tabpanel)
dialog.advancedTab = guiCreateTab("Advanced",tabpanel)

dialog.ok = guiCreateButton ( 0.5, 0.919444, 0.22857142, 0.05555555, "OK", true, dialog.window )
dialog.cancel = guiCreateButton ( 0.780357142, 0.919444, 0.22857142, 0.05555555, "Cancel", true, dialog.window )
@@ -83,8 +84,6 @@ function createOptionsDialog()
guiCreateLabel ( 0.5, 0.12, 1, 0.1, "Normal element rotation speed:", true, dialog.movementTab )
guiCreateLabel ( 0.5, 0.32, 1, 0.1, "Fast element rotation speed:", true, dialog.movementTab )
guiCreateLabel ( 0.5, 0.52, 1, 0.1, "Slow element rotation speed:", true, dialog.movementTab )
guiCreateLabel ( 0.5, 0.72, 1, 0.1, "Element scaling:", true, dialog.movementTab )


dialog.normalElemMove = editingControl.slider:create{["x"]=0.02,["y"]=0.18,["width"]=0.4,["height"]=0.11,["relative"]=true,["parent"]=dialog.movementTab,
["min"]=0.075,
@@ -110,11 +109,27 @@ function createOptionsDialog()
["min"]=0.01,
["max"]=0.5,
}
dialog.elemScaling = editingControl.slider:create{["x"]=0.5,["y"]=0.78,["width"]=0.4,["height"]=0.11,["relative"]=true,["parent"]=dialog.movementTab,
["min"]=0.01,
["max"]=1,
}
dialog.lockToAxes = editingControl.boolean:create{["x"]=0.02,["y"]=0.78,["width"]=0.4,["height"]=0.1,["relative"]=true,["parent"]=dialog.movementTab,["label"]="Lock movement to axes"}
--create advanced settings
guiCreateLabel ( 0.5, 0.04, 1, 0.1, "Normal element scaling speed:", true, dialog.advancedTab )
guiCreateLabel ( 0.5, 0.24, 1, 0.1, "Fast element scaling speed:", true, dialog.advancedTab )
guiCreateLabel ( 0.5, 0.44, 1, 0.1, "Slow element scaling speed:", true, dialog.advancedTab )

dialog.normalElemScale = editingControl.slider:create{["x"]=0.5,["y"]=0.10,["width"]=0.4,["height"]=0.11,["relative"]=true,["parent"]=dialog.advancedTab,
["min"]=0.01,
["max"]=0.5,
}
dialog.fastElemScale = editingControl.slider:create{["x"]=0.5,["y"]=0.30,["width"]=0.4,["height"]=0.11,["relative"]=true,["parent"]=dialog.advancedTab,
["min"]=0.5,
["max"]=2,
}
dialog.slowElemScale = editingControl.slider:create{["x"]=0.5,["y"]=0.50,["width"]=0.4,["height"]=0.11,["relative"]=true,["parent"]=dialog.advancedTab,
["min"]=0.001,
["max"]=0.05,
}

dialog.randomizeRotation = editingControl.boolean:create{["x"]=0.02,["y"]=0.02,["width"]=0.4,["height"]=0.1,["relative"]=true,["parent"]=dialog.advancedTab,["label"]="Randomize rotation on element creation"}
dialog.randomizeRotationAxis = editingControl.dropdown:create{["x"]=0.02,["y"]=0.12,["width"]=0.4,["height"]=0.07,["dropWidth"]=0.4,["dropHeight"]=0.5,["relative"]=true,["parent"]=dialog.advancedTab,["rows"]={"X","Y","Z","XY","XZ","YZ","XYZ"}}
--
loadXMLSettings()
addEventHandler ( "onClientGUIClick", dialog.ok, confirmSettings,false )
9 changes: 7 additions & 2 deletions [editor]/editor_gui/client/outputmessage.lua
Original file line number Diff line number Diff line change
@@ -32,6 +32,11 @@ end

function outputMessage ( text, r, g, b, time )
cleanup()

if message.outputting then
removeHandler()
end

if type(text) ~= "string" then
return false
end
@@ -48,7 +53,7 @@ function outputMessage ( text, r, g, b, time )
message.y = g_screenY - message.height
if message.width > g_screenX then
message.x = 5
local movedistance = message.width - screenX*0.75
local movedistance = message.width - g_screenX*0.75
local movetime = movedistance/MOVE_SPEED
time = math.max(time,movetime)
--Create our animations
@@ -67,7 +72,7 @@ function outputMessage ( text, r, g, b, time )
table.insert(message.timers, setTimer ( removeHandler, MOVE_DELAY + time, 1 ))

else
message.x = screenX/2 - message.width/2
message.x = g_screenX/2 - message.width/2
doAnimation (setAlpha,
{{ from = 1, to = 140, time = FADE_TIME, fn = setAlpha }})
table.insert(message.timers, setTimer ( function() doAnimation (setAlpha,
14 changes: 14 additions & 0 deletions [editor]/editor_gui/client/test.lua
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ local hideDialog
local g_suspended
local inBasicTest = false
local lastTestGamemode
local lastGridListGamemode
local g_colPatchSetting

function createTestDialog()
@@ -30,6 +31,19 @@ end

function quickTest()
if tutorialVars.blockQuickTest then return end
-- get the last gamemode that was addded to the map
local rowCount = guiGridListGetRowCount(mapsettings.addedGamemodes)
local currentLastGamemode = false
if rowCount > 0 then
currentLastGamemode = guiGridListGetItemText(mapsettings.addedGamemodes, rowCount - 1, 1)
if currentLastGamemode == "<None>" then
currentLastGamemode = false
end
end
if lastGridListGamemode ~= currentLastGamemode then
lastTestGamemode = currentLastGamemode
lastGridListGamemode = currentLastGamemode
end
if lastTestGamemode == "<None>" then lastTestGamemode = false end
editor_main.dropElement()
triggerServerEvent ( "testResource",localPlayer, lastTestGamemode )
33 changes: 31 additions & 2 deletions [editor]/editor_main/client/elementcreation.lua
Original file line number Diff line number Diff line change
@@ -14,12 +14,37 @@ addEventHandler("doUnloadEDF", root,

triggerServerEvent("onClientRequestEDF", localPlayer)

function getRandomRotation()
if exports["editor_gui"]:sx_getOptionData("randomizeRotation") ~= true then
return {0, 0, 0}
end

local getAxis = exports["editor_gui"]:sx_getOptionData("randomizeRotationAxis")
local rotationMap = {
["X"] = function() return {math.random(0, 360), 0, 0} end,
["Y"] = function() return {0, math.random(0, 360), 0} end,
["Z"] = function() return {0, 0, math.random(0, 360)} end,
["XY"] = function() return {math.random(0, 360), math.random(0, 360), 0} end,
["XZ"] = function() return {math.random(0, 360), 0, math.random(0, 360)} end,
["YZ"] = function() return {0, math.random(0, 360), math.random(0, 360)} end,
["XYZ"] = function() return {math.random(0, 360), math.random(0, 360), math.random(0, 360)} end,
}

local rotationFunc = rotationMap[getAxis] or function() return {0, 0, 0} end
return rotationFunc()
end

-- sends the element creation request
function doCreateElement ( elementType, resourceName, creationParameters, attachLater, shortcut )
creationParameters = creationParameters or {}
if not creationParameters.position then
local targetX, targetY, targetZ = processCameraLineOfSight()
creationParameters.position = {targetX, targetY, targetZ + .5}
if not elementType == "object" or not elementType == "vehicle" then
creationParameters.position = nil
else
creationParameters.position = {targetX, targetY, targetZ + .5}
end
creationParameters.rotation = getRandomRotation()
end

local requiresCreationBox = false
@@ -50,5 +75,9 @@ function doCloneElement ( element, attachMode )
if getSelectedElement() then
dropElement(true)
end
triggerServerEvent( "doCloneElement", element, attachMode )
local rotationData
if exports["editor_gui"]:sx_getOptionData("randomizeRotation") == true then
rotationData = getRandomRotation()
end
triggerServerEvent( "doCloneElement", element, attachMode, rotationData )
end
3 changes: 3 additions & 0 deletions [editor]/editor_main/meta.xml
Original file line number Diff line number Diff line change
@@ -90,6 +90,9 @@
<!-- Incremental rotation with quaternions used by move_freecam, move_cursor, move_keyboard -->
<script src="client/rotation.lua" type="client" />

<!-- Exported server functions -->
<export function="getCurrentMapName" type="server" />

<!-- Exported client functions -->
<export function="startEditor" type="client" />
<export function="selectElement" type="client" />
7 changes: 6 additions & 1 deletion [editor]/editor_main/server/createdestroy.lua
Original file line number Diff line number Diff line change
@@ -56,7 +56,7 @@ addEventHandler ( "doCreateElement", root,
)

addEventHandler ( "doCloneElement", root,
function (attachMode,creator)
function (attachMode,rotationData,creator)
if client and not isPlayerAllowedToDoEditorAction(client,"createElement") then
editor_gui.outputMessage ("You don't have permissions to clone an element!", client,255,0,0)
return
@@ -69,6 +69,11 @@ addEventHandler ( "doCloneElement", root,

if clone then
outputConsole ( "Cloned '"..getElementType(source).."'." )

if rotationData then
edf.edfSetElementRotation(clone, rotationData[1], rotationData[2], rotationData[3])
end

setupNewElement(clone, creator or edf.edfGetCreatorResource(source), client, true, false, attachMode)
setLockedElement(source, nil)
else
6 changes: 5 additions & 1 deletion [editor]/editor_main/server/mapsettingssync.lua
Original file line number Diff line number Diff line change
@@ -40,6 +40,7 @@ end
mapSettingDefaults = defaults
currentMapSettings = defaults
currentMapSettings.gamemodeSettings = {}
currentMapSettings.addedGamemodes = {}

local mapSettingAction = {
timeHour = function ( value )
@@ -127,7 +128,7 @@ function setupMapSettings()
--get the gamemodes
local gamemodes = mapmanager.getGamemodes()
currentMapSettings.availGamemodes = {}
currentMapSettings.addedGamemodes = {}

for k,v in ipairs(gamemodes) do
local name = getResourceName ( v )
if string.lower(name) ~= "freeroam" then
@@ -191,6 +192,9 @@ function passDefaultMapSettings()
end

function passNewMapSettings()

if loadedMap == false then return end

local mapResource = getResourceFromName(loadedMap)

--General settings
13 changes: 10 additions & 3 deletions [editor]/editor_main/server/saveloadtest_server.lua
Original file line number Diff line number Diff line change
@@ -116,7 +116,7 @@ addEventHandler("newResource", root,
triggerClientEvent ( source, "saveloadtest_return", source, "new", true )
triggerEvent("onNewMap", resourceRoot)
dumpSave()
editor_gui.outputMessage(getPlayerName(client).." started a new map.", root, 255, 0, 0)
editor_gui.outputMessage(stripHexCode(getPlayerName(client)).." started a new map.", root, 255, 0, 0)

actionList = {}
currentActionIndex = 0
@@ -138,6 +138,7 @@ function handleOpenResource()
if (isElement(openingSource)) then
triggerClientEvent ( openingSource, "saveloadtest_return", openingSource, "open", true )
playerName = getPlayerName ( openingSource )
playerName = stripHexCode( playerName )
end
local outputStr = playerName.." opened map "..tostring(openingResourceName)..". (opening took "..math.floor(getTickCount() - openingStartTick).." ms)"
editor_gui.outputMessage ( outputStr, root, 255, 0, 0 )
@@ -483,7 +484,7 @@ function saveResourceCoroutineFunction ( resourceName, test, theSaver, client, g
if ( returnValue ) then
loadedMap = resourceName
if (theSaver) then
editor_gui.outputMessage ( getPlayerName(theSaver).." saved to map resource \""..resourceName.."\".", root, 255, 0, 0 )
editor_gui.outputMessage ( stripHexCode(getPlayerName(theSaver)).." saved to map resource \""..resourceName.."\".", root, 255, 0, 0 )
end
end
if ( theSaver ) then
@@ -639,7 +640,7 @@ function doQuickSaveCoroutineFunction(saveAs, dump, client)
triggerClientEvent ( client, "saveloadtest_return", client, "save", true )
end
if ( not dump ) then
editor_gui.outputMessage (getPlayerName(client).." saved the map.", root,255,0,0)
editor_gui.outputMessage (stripHexCode(getPlayerName(client)).." saved the map.", root,255,0,0)
dumpSave()
end
else
@@ -685,6 +686,8 @@ function createElementAttributesForSaving(xmlNode, element)
xmlNodeSetAttribute(elementNode, "rotX", toAttribute(round(dataValue[1], 3)))
xmlNodeSetAttribute(elementNode, "rotY", toAttribute(round(dataValue[2], 3)))
xmlNodeSetAttribute(elementNode, "rotZ", toAttribute(round(dataValue[3], 3)))
elseif ( dataName == "scale" ) then
xmlNodeSetAttribute(elementNode, "scale", toAttribute(round(dataValue, 3)))
elseif ( dataName == "posX" or dataName == "posY" or dataName == "posZ") then
xmlNodeSetAttribute(elementNode, dataName, toAttribute(round(dataValue, 5)))
if (dataName == "posX") then
@@ -943,6 +946,10 @@ addEventHandler("onPlayerLogin", root,
end
)

function getCurrentMapName()
return loadedMap
end

function getBool(var,default)
local result = get(var)
if not result then
4 changes: 4 additions & 0 deletions [editor]/editor_main/server/util.lua
Original file line number Diff line number Diff line change
@@ -7,6 +7,10 @@ function isPlayerAllowedToDoEditorAction(player,action)
return false
end

function stripHexCode(text)
return text:gsub("#%x%x%x%x%x%x","")
end

function table.subtract(t1, t2)
local find, remove = table.find, table.remove
for i=#t1,1,-1 do
18 changes: 13 additions & 5 deletions [editor]/move_cursor/move_cursor.lua
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@ local centerToBaseDistance

local rotationless
local rotX, rotY, rotZ
local scale

local collisionless
local minZ
@@ -172,15 +173,13 @@ local function rotateWithMouseWheel(key, keyState)
--Peds dont have their rotation updated with their attached parents
for i,element in ipairs(getAttachedElements(selectedElement)) do
if getElementType(element) == "ped" then
setElementRotation(element, 0,0,-rotZ)
setPedRotation(element, rotZ)
setElementRotation(element, 0,0,-rotZ, "default", true)
end
end
elseif (elementType == "ped") then
rotZ = rotZ + speed
rotZ = rotZ % 360
setPedRotation(selectedElement, rotZ)
setElementRotation(selectedElement, 0,0,-rotZ%360)
setElementRotation(selectedElement, 0,0,-rotZ%360, "default", true)
end
end
end
@@ -231,6 +230,7 @@ function attachElement(element)
if (getElementType(element) == "object") then
rotationless = false
rotX, rotY, rotZ = getElementRotation(element)
scale = getObjectScale(element)
collisionless = false
_, _, minZ = exports.edf:edfGetElementBoundingBox(element)
end
@@ -240,9 +240,12 @@ function attachElement(element)
rotX, rotY, rotZ = getElementRotation(element)
collisionless = false
_, _, minZ = getElementBoundingBox(element)
if (getElementType(element) == "object") then
scale = getObjectScale(element)
end
elseif (getElementType(element) == "ped") then
rotationless = false
rotX, rotY, rotZ = 0, 0, getPedRotation(element)
_, _, rotZ = getElementRotation(element)
collisionless = false
_, _, minZ = getElementBoundingBox(element)
else
@@ -274,12 +277,17 @@ function detachElement()
rotX, rotY, rotZ = getElementRotation(selectedElement, "ZYX")
triggerServerEvent("syncProperty", localPlayer, "rotation", {rotX, rotY, rotZ}, exports.edf:edfGetAncestor(selectedElement))
end
if (getElementType(selectedElement) == "object") then
scale = getObjectScale(selectedElement)
triggerServerEvent("syncProperty", localPlayer, "scale", {scale}, exports.edf:edfGetAncestor(selectedElement))
end
end
selectedElement = nil

-- clear variables
camX, camY, camZ = nil, nil, nil
rotX, rotY, rotZ = nil, nil, nil
scale = nil
rotationless = nil
minZ = nil
collisionless = nil
16 changes: 10 additions & 6 deletions [editor]/move_freecam/move_freecam.lua
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ local centerToBaseDistance

local rotationless
local rotX, rotY, rotZ
local scale

local collisionless
local minZ
@@ -37,7 +38,7 @@ local mta_getElementRotation = getElementRotation
local function getElementRotation(element)
local elementType = getElementType(element)
if elementType == "player" or elementType == "ped" then
return 0,0,getPedRotation(element)
return mta_getElementRotation(element)
elseif elementType == "object" then
return mta_getElementRotation(element, "ZYX")
elseif elementType == "vehicle" then
@@ -78,15 +79,13 @@ local function rotateWithMouseWheel(key, keyState)
--Peds dont have their rotation updated with their attached parents
for i,element in ipairs(getAttachedElements(selectedElement)) do
if getElementType(element) == "ped" then
setElementRotation(element, 0,0,-rotZ)
setPedRotation(element, rotZ)
setElementRotation(element, 0,0,-rotZ, "default", true)
end
end
elseif (getElementType(selectedElement) == "ped") then
rotZ = rotZ + speed
rotZ = rotZ % 360
setPedRotation(selectedElement, rotZ)
setElementRotation(selectedElement, 0,0,-rotZ%360)
setElementRotation(selectedElement, 0,0,-rotZ%360, "default", true)
end
end
end
@@ -195,6 +194,7 @@ function attachElement(element)
if (getElementType(element) == "object") then
rotationless = false
rotX, rotY, rotZ = getElementRotation(element, "ZYX")
scale = exports.edf:edfGetElementScale(element)
collisionless = false
_, _, minZ = exports.edf:edfGetElementBoundingBox(element)
centerToBaseDistance = exports.edf:edfGetElementDistanceToBase(element)
@@ -209,12 +209,13 @@ function attachElement(element)
elseif (getElementType(element) == "object") then
rotationless = false
rotX, rotY, rotZ = getElementRotation(element, "ZYX")
scale = exports.edf:edfGetElementScale(element)
collisionless = false
_, _, minZ = getElementBoundingBox(element)
centerToBaseDistance = getElementDistanceFromCentreOfMassToBaseOfModel(element)
elseif (getElementType(element) == "ped") then
rotationless = false
rotX, rotY, rotZ = 0, 0, getPedRotation(element)
_, _, rotZ = getElementRotation(element)
collisionless = false
_, _, minZ = getElementBoundingBox(element)
centerToBaseDistance = getElementDistanceFromCentreOfMassToBaseOfModel(element)
@@ -246,6 +247,9 @@ function detachElement()
if hasRotation[getElementType(selectedElement)] then
triggerServerEvent("syncProperty", localPlayer, "rotation", {rotX, rotY, rotZ}, exports.edf:edfGetAncestor(selectedElement))
end
if (getElementType(selectedElement) == "object") then
triggerServerEvent("syncProperty", localPlayer, "scale", scale, exports.edf:edfGetAncestor(selectedElement))
end
end
selectedElement = nil

4 changes: 2 additions & 2 deletions [editor]/move_keyboard/meta.xml
Original file line number Diff line number Diff line change
@@ -11,8 +11,8 @@
<export function="getAttachedElement" type="client" />
<export function="getMoveSpeeds" type="client" />
<export function="getRotateSpeeds" type="client" />
<export function="setScaleIncrement" type="client" />
<export function="getScaleIncrement" type="client" />
<export function="setScalingSpeeds" type="client" />
<export function="getScalingSpeeds" type="client" />
<export function="toggleAxesLock" type="client" />
<export function="enable" type="client" />
<export function="disable" type="client" />
94 changes: 62 additions & 32 deletions [editor]/move_keyboard/move_keyboard.lua
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ local lastKEYSTATES = {}
local ignoreAllSurfaces = true
local moveSpeed = {slow = .025, medium = .25, fast = 2} -- meters per frame
local rotateSpeed = {slow = 1, medium = 8, fast = 40} -- degrees per scroll or frame
local scaleIncrement = 0.1
local scalingSpeed = {slow = .01, medium = .1, fast = 1}

local isEnabled = false

@@ -13,6 +13,7 @@ local selectedElement
local posX, posY, posZ
local rotX, rotY, rotZ
local scale
local size

local collisionless
local lockToAxes = false
@@ -53,7 +54,7 @@ local mta_getElementRotation = getElementRotation
local function getElementRotation(element)
local elementType = getElementType(element)
if elementType == "player" or elementType == "ped" then
return 0,0,getPedRotation(element)
return mta_getElementRotation(element, "default", true)
elseif elementType == "object" then
return mta_getElementRotation(element, "ZYX")
elseif elementType == "vehicle" then
@@ -184,8 +185,7 @@ local function onClientRender_keyboard()
-- check if rotation changed
if (tempRot ~= rotZ) then
if (getElementType(selectedElement) == "ped") then
setElementRotation(selectedElement, 0,0,-tempRot%360)
setPedRotation(selectedElement, tempRot)
setElementRotation(selectedElement, 0,0,-tempRot%360, "default", true)
end
end
rotZ = tempRot
@@ -232,8 +232,7 @@ local function onClientRender_keyboard()
--Peds dont have their rotation updated with their attached parents
for i,element in ipairs(getAttachedElements(selectedElement)) do
if getElementType(element) == "ped" then
setElementRotation(element, 0,0,-tempRotZ%360)
setPedRotation(element, tempRotZ%360)
setElementRotation(element, 0,0,-tempRotZ%360, "default", true)
end
end
rotX, rotY, rotZ = tempRotX, tempRotY, tempRotZ
@@ -280,8 +279,7 @@ local function onClientRender_keyboard()
-- check if rotation changed
if (tempRot ~= rotZ) then
if (getElementType(selectedElement) == "ped") then
setElementRotation(selectedElement, 0,0,-tempRot%360)
setPedRotation(selectedElement, tempRot)
setElementRotation(selectedElement, 0,0,-tempRot%360, "default", true)
end
end
rotZ = tempRot
@@ -329,8 +327,7 @@ local function onClientRender_keyboard()
--Peds dont have their rotation updated with their attached parents
for i,element in ipairs(getAttachedElements(selectedElement)) do
if getElementType(element) == "ped" then
setElementRotation(element, 0,0,-tempRotZ%360)
setPedRotation(element, tempRotZ%360)
setElementRotation(element, 0,0,-tempRotZ%360, "default", true)
end
end
rotX, rotY, rotZ = tempRotX, tempRotY, tempRotZ
@@ -346,29 +343,58 @@ local function onClientRender_keyboard()
rotX, rotY = 0, 0
for i,element in ipairs(getAttachedElements(selectedElement)) do
if getElementType(element) == "ped" then
setElementRotation(element, 0,0,-rotZ%360)
setPedRotation(element, rotZ%360)
setElementRotation(element, 0,0,-rotZ%360, "default", true)
end
end
elseif (getElementType(selectedElement) == "ped") then
rotZ = 0
setPedRotation ( selectedElement, 0, 0, 0 )
setElementRotation ( selectedElement, 0, 0, 0 )
setElementRotation ( selectedElement, 0, 0, 0 , "default", true)
end
end
end
end

-- Scale up/down for objects
if getElementType(selectedElement) == "object" then
local currentScale = getObjectScale(selectedElement)
if getCommandState("element_scale_up") then
currentScale = currentScale + scaleIncrement
-- Scale up/down for objects, markers
local speed
if (getCommandState("mod_slow_speed")) then
speed = scalingSpeed.slow
elseif (getCommandState("mod_fast_speed")) then
speed = scalingSpeed.fast
else
speed = scalingSpeed.medium
end

if getElementType(selectedElement) == "object" then
scale = getObjectScale(selectedElement)
local tempScale = scale
local snaplevel = tonumber(exports["editor_gui"]:sx_getOptionData("elemScalingSnap"))
if getCommandState("element_scale_up") then
tempScale = scale + speed
tempScale = roundToLevel(tempScale,snaplevel,"round")
elseif getCommandState("element_scale_down") then
tempScale = scale - speed
tempScale = roundToLevel(tempScale,snaplevel,"round")
end
if tempScale ~= scale then
setObjectScale(selectedElement, tempScale)
scale = tempScale
end
elseif getElementType(selectedElement) == "marker" then
size = getMarkerSize(selectedElement)
local tempSize = size
local snaplevel = tonumber(exports["editor_gui"]:sx_getOptionData("elemScalingSnap"))
if getCommandState("element_scale_up") then
tempSize = size + speed
tempSize = roundToLevel(tempSize,snaplevel,"round")
elseif getCommandState("element_scale_down") then
currentScale = currentScale - scaleIncrement
end
setObjectScale(selectedElement, currentScale)
end
tempSize = size - speed
tempSize = roundToLevel(tempSize,snaplevel,"round")
end
if tempSize ~= size then
setMarkerSize(selectedElement, tempSize)
size = tempSize
end
end
end
end

@@ -397,15 +423,13 @@ local function rotateWithMouseWheel(key, keyState)
--Peds dont have their rotation updated with their attached parents
for i,element in ipairs(getAttachedElements(selectedElement)) do
if getElementType(element) == "ped" then
setElementRotation(element, 0,0,-rotZ)
setPedRotation(element, rotZ)
setElementRotation(element, 0,0,-rotZ, "default", true)
end
end
elseif (getElementType(selectedElement) == "ped") then
rotZ = rotZ + speed
rotZ = rotZ % 360
setElementRotation(selectedElement, 0,0,-rotZ)
setPedRotation(selectedElement, rotZ)
setElementRotation(selectedElement, 0,0,-rotZ, "default", true)
end
end

@@ -423,7 +447,7 @@ function attachElement(element)
if (getElementType(element) == "vehicle") or (getElementType(element) == "object") then
rotX, rotY, rotZ = getElementRotation(element, "ZYX")
elseif (getElementType(element) == "player") or (getElementType(element) == "ped") then
rotX, rotY, rotZ = 0,0,getPedRotation ( element )
rotX, rotY, rotZ = getElementRotation(element)
end
enable()
return true
@@ -452,6 +476,10 @@ function detachElement()
scale = getObjectScale(selectedElement)
triggerServerEvent("syncProperty", localPlayer, "scale", scale, exports.edf:edfGetAncestor(selectedElement))
end
if getElementType(selectedElement) == "marker" then
size = getMarkerSize(selectedElement)
triggerServerEvent("syncProperty", localPlayer, "size", size, exports.edf:edfGetAncestor(selectedElement))
end
end
selectedElement = nil
posX, posY, posZ = nil, nil, nil
@@ -479,8 +507,10 @@ function setRotateSpeeds(slow, medium, fast)
rotateSpeed.fast = fast
end

function setScaleIncrement(increment)
scaleIncrement = increment
function setScalingSpeeds(slow, medium, fast)
scalingSpeed.slow = slow
scalingSpeed.medium = medium
scalingSpeed.fast = fast
end

function getAttachedElement()
@@ -499,8 +529,8 @@ function getRotateSpeeds()
return rotateSpeed.slow, rotateSpeed.medium, rotateSpeed.fast
end

function getScaleIncrement()
return scaleIncrement
function getScalingSpeeds()
return scalingSpeed.slow, scalingSpeed.medium, scalingSpeed.fast
end

function toggleAxesLock ( bool )