Skip to content

Commit 5e4611f

Browse files
authored
added scaling via keybind (numpad +, -), undo/redo for scale property, model ids to current elements browser (#604)
* added sclaing via keybind (numpad +, -) and undo/redo for scale property * added elemScalingSnap previously used precisionLevel * added missing tutorial step * small fix to check if the element type is an object * added model ids to the current element browser * fix to only receive model ids for valid elements
1 parent 03c0861 commit 5e4611f

19 files changed

+282
-81
lines changed

[editor]/edf/edf.lua

+56
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,7 @@ function edfRepresentElement(theElement, resource, parentData, editorMode, restr
419419
-- get basic element properties
420420
parentData.position = { edfGetElementPosition(theElement) }
421421
parentData.rotation = { edfGetElementRotation(theElement) }
422+
parentData.scale = edfGetElementScale(theElement)
422423
parentData.dimension = edfGetElementDimension(theElement)
423424
parentData.interior = edfGetElementInterior(theElement)
424425
parentData.alpha = edfGetElementAlpha(theElement)
@@ -581,6 +582,7 @@ function edfCreateElement(elementType, creatorClient, fromResource, parametersTa
581582
parametersTable = parametersTable or {}
582583
parametersTable.position = parametersTable.position or {0,0,0}
583584
parametersTable.rotation = parametersTable.rotation or {0,0,0}
585+
parametersTable.scale = parametersTable.scale or 1
584586
parametersTable.interior = parametersTable.interior or 0
585587
parametersTable.dimension = parametersTable.dimension or 0
586588
parametersTable.alpha = parametersTable.alpha or 255
@@ -619,6 +621,8 @@ function edfCreateElement(elementType, creatorClient, fromResource, parametersTa
619621
edfSetElementPosition(newElement, dataValue[1], dataValue[2], dataValue[3])
620622
elseif dataField == "rotation" then
621623
edfSetElementRotation(newElement, dataValue[1], dataValue[2], dataValue[3], dataValue[4])
624+
elseif dataField == "scale" then
625+
edfSetElementScale(newElement, dataValue)
622626
elseif dataField == "interior" then
623627
if dataValue == -1 then
624628
setElementInterior(newElement, 0) -- Interior -1 only works on removeWorldModel (But element data must be set to -1)
@@ -670,6 +674,7 @@ function edfCloneElement(theElement, editorMode )
670674
parametersTable = {}
671675
parametersTable.position = {edfGetElementPosition(theElement)} or {0,0,0}
672676
parametersTable.rotation = {edfGetElementRotation(theElement)} or {0,0,0}
677+
parametersTable.scale = edfGetElementScale(theElement) or 2
673678
parametersTable.interior = edfGetElementInterior(theElement) or 0
674679
parametersTable.dimension = edfGetElementDimension(theElement) or 0
675680
parametersTable.alpha = edfGetElementAlpha(theElement) or 255
@@ -713,6 +718,8 @@ function edfCloneElement(theElement, editorMode )
713718
edfSetElementPosition(newElement, dataValue[1], dataValue[2], dataValue[3])
714719
elseif dataField == "rotation" then
715720
edfSetElementRotation(newElement, dataValue[1], dataValue[2], dataValue[3])
721+
elseif dataField == "scale" then
722+
edfSetElementScale(newElement, dataValue)
716723
else
717724
setElementData(newElement, dataField, dataValue)
718725
end
@@ -875,6 +882,27 @@ function edfGetElementRotation(element)
875882
end
876883
end
877884

885+
--Returns an element's scale, or its scale element data, or false
886+
function edfGetElementScale(element)
887+
local etype = getElementType(element)
888+
if etype == "object" then
889+
scale = getObjectScale(element)
890+
else
891+
local handle = edfGetHandle(element)
892+
if handle then
893+
scale = getObjectScale(handle)
894+
else
895+
scale = tonumber(getElementData(element,"scale"))
896+
end
897+
end
898+
899+
if scale then
900+
return scale
901+
else
902+
return false
903+
end
904+
end
905+
878906
--Sets an element's position, or its posX/Y/Z element data
879907
function edfSetElementPosition(element, px, py, pz)
880908
local ancestor = edfGetAncestor(element) or element
@@ -935,6 +963,32 @@ function edfSetElementRotation(element, rx, ry, rz, rotOrder)
935963
return false
936964
end
937965

966+
--Sets an element's scale, or its scale element data
967+
function edfSetElementScale(element, scale)
968+
local ancestor = edfGetAncestor(element) or element
969+
setElementData(ancestor, "scale", scale)
970+
local etype = getElementType(element)
971+
if etype == "object" then
972+
if setObjectScale(element, scale) then
973+
triggerEvent ( "onElementPropertyChanged", ancestor, "scale" )
974+
return true
975+
end
976+
else
977+
local handle = edfGetHandle(element)
978+
if handle then
979+
if setObjectScale(handle, scale) then
980+
triggerEvent ( "onElementPropertyChanged", ancestor, "scale" )
981+
return true
982+
end
983+
else
984+
setElementData(element, "scale", scale or 1)
985+
triggerEvent ( "onElementPropertyChanged", ancestor, "scale" )
986+
return true
987+
end
988+
end
989+
return false
990+
end
991+
938992
function edfGetElementInterior(element)
939993
return getElementInterior(element) or tonumber(getElementData(element, "interior")) or 0
940994
end
@@ -1324,6 +1378,8 @@ function edfGetChildData(node, dataFields)
13241378
value[1] = xmlNodeGetAttribute(node, "rotX") or 0
13251379
value[2] = xmlNodeGetAttribute(node, "rotY") or 0
13261380
value[3] = xmlNodeGetAttribute(node, "rotZ") or 0
1381+
elseif dataField == "scale" then
1382+
value = xmlNodeGetAttribute(node, "scale") or 1
13271383
else
13281384
value = xmlNodeGetAttribute(node, dataField) or nil
13291385
if value then

[editor]/edf/edf_client.lua

+38
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,27 @@ function edfGetElementRotation(element)
123123
end
124124
end
125125

126+
--Returns an element's scale, or its scale element data, or 1
127+
function edfGetElementScale(element)
128+
local scale
129+
if isBasic[getElementType(element)] then
130+
scale = getElementData(element, "scale")
131+
else
132+
local handle = edfGetHandle(element)
133+
if handle then
134+
return getElementData(handle, "scale")
135+
else
136+
scale = getElementData(element, "scale")
137+
end
138+
end
139+
140+
if scale then
141+
return scale
142+
else
143+
return 1
144+
end
145+
end
146+
126147
--Setsan element's position, or its posX/Y/Z element data
127148
function edfSetElementPosition(element, px, py, pz)
128149
if px and py and pz then
@@ -165,6 +186,23 @@ function edfSetElementRotation(element, rx, ry, rz)
165186
end
166187
end
167188

189+
--Sets an element's scale, or its scale element data
190+
function edfSetElementScale(element, scale)
191+
if scale then
192+
if isBasic[getElementType(element)] then
193+
return setElementData(element, "scale", scale)
194+
else
195+
local handle = edfGetHandle(element)
196+
if handle then
197+
return setElementData(handle, "scale", scale)
198+
else
199+
setElementData(element, "scale", scale)
200+
return true
201+
end
202+
end
203+
end
204+
end
205+
168206
function edfGetElementInterior(element)
169207
return getElementInterior(element) or tonumber(getElementData(element, "interior")) or 0
170208
end

[editor]/edf/meta.xml

+4
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
<export function="edfSetElementPosition" /> <!-- bool -->
4444
<export function="edfGetElementRotation" /> <!-- number, number, number -->
4545
<export function="edfSetElementRotation" /> <!-- bool -->
46+
<export function="edfGetElementScale" /> <!-- number -->
47+
<export function="edfSetElementScale" /> <!-- number -->
4648
<export function="edfGetElementInterior" /> <!-- number -->
4749
<export function="edfSetElementInterior" /> <!-- bool -->
4850
<export function="edfGetElementDimension" /> <!-- number -->
@@ -61,6 +63,8 @@
6163
<export function="edfSetElementPosition" type="client" /> <!-- bool -->
6264
<export function="edfGetElementRotation" type="client" /> <!-- number, number, number -->
6365
<export function="edfSetElementRotation" type="client" /> <!-- bool -->
66+
<export function="edfGetElementScale" type="client" /> <!-- number -->
67+
<export function="edfSetElementScale" type="client" /> <!-- number -->
6468
<export function="edfGetElementInterior" type="client" /> <!-- number -->
6569
<export function="edfSetElementInterior" type="client" /> <!-- bool -->
6670
<export function="edfGetElementDimension" type="client" /> <!-- number -->

[editor]/editor_gui/client/currentbrowser.lua

+63-49
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ function createCurrentBrowser ()
2929
local windowWidth = screenX*width
3030
local windowHeight = screenY*height
3131
currentBrowserGUI.browser = guiCreateWindow ( 1 - width, 0, width, height, "Current Elements...", true )
32-
currentBrowserGUI.gridlist = browserList:create(12, 85, windowWidth, windowHeight-128,{{["Name"]=0.85}},false, currentBrowserGUI.browser )
32+
currentBrowserGUI.gridlist = browserList:create(12, 85, windowWidth, windowHeight-128,{{["Name [ID]"]=0.85}},false, currentBrowserGUI.browser )
3333
currentBrowserGUI.search = guiCreateEdit ( 12, 50, windowWidth, 30, "Search...", false, currentBrowserGUI.browser )
3434
currentBrowserGUI.dropdown = editingControl.dropdown:create{["x"]=12,["y"]=25,["width"]=windowWidth,["height"]=20,["dropWidth"]=windowWidth,["dropHeight"]=200,["relative"]=false,["parent"]=currentBrowserGUI.browser,["rows"]={""}}
3535
--linked to options
@@ -178,25 +178,29 @@ function currentBrowser.isolateElement (element,bool)
178178
end
179179

180180

181-
function currentBrowser.gridlistClick (cellrow)
182-
if cellrow ~= 0 then
183-
local id = currentBrowserGUI.gridlist:getSelectedText()
184-
cSelectedElement = getElementByID ( id )
185-
editor_main.selectElement ( cSelectedElement, 2, false, cSelectedElement, cSelectedElement, true)
186-
if ( dialog.autosnap:getValue() ) then
187-
autoSnap ( cSelectedElement )
188-
end
189-
if ( dimensionElement ) then
190-
setElementDimension ( dimensionElement, workingDimension )
191-
setElementDimension ( cSelectedElement, hiddenDimension )
192-
dimensionElement = cSelectedElement
193-
end
194-
elseif ( dimensionElement ) then
195-
setElementDimension ( dimensionElement, workingDimension )
196-
setElementDimension ( localPlayer, workingDimension )
197-
guiCheckBoxSetSelected ( currentBrowserGUI.isolate, false )
198-
dimensionElement = false
199-
end
181+
function currentBrowser.gridlistClick(cellrow)
182+
if cellrow ~= 0 then
183+
local fullText = currentBrowserGUI.gridlist:getSelectedText()
184+
-- Extract just the element name portion (before the bracket)
185+
local elementName = string.match(fullText, "^([^%[]+)")
186+
-- Trim any spaces at the end
187+
elementName = string.gsub(elementName, "%s+$", "")
188+
cSelectedElement = getElementByID(elementName)
189+
editor_main.selectElement(cSelectedElement, 2, false, cSelectedElement, cSelectedElement, true)
190+
if (dialog.autosnap:getValue()) then
191+
autoSnap(cSelectedElement)
192+
end
193+
if (dimensionElement) then
194+
setElementDimension(dimensionElement, workingDimension)
195+
setElementDimension(cSelectedElement, hiddenDimension)
196+
dimensionElement = cSelectedElement
197+
end
198+
elseif (dimensionElement) then
199+
setElementDimension(dimensionElement, workingDimension)
200+
setElementDimension(localPlayer, workingDimension)
201+
guiCheckBoxSetSelected(currentBrowserGUI.isolate, false)
202+
dimensionElement = false
203+
end
200204
end
201205

202206
function currentBrowser.doubleClick()
@@ -303,10 +307,16 @@ function applySearch ( array, query )
303307
end
304308

305309
function setTableElementIDs(elemTable)
306-
for k,v in pairs (elemTable) do
307-
elemTable[k] = tostring(getElementID(v))
308-
end
309-
return elemTable
310+
local elementsWithIDs = {}
311+
for k, v in pairs(elemTable) do
312+
local elementID = getElementID(v)
313+
local numericID = ""
314+
if getElementType(v) == "object" or getElementType(v) == "vehicle" or getElementType(v) == "ped" then
315+
numericID = "[" .. (getElementData(v, "model") or getElementModel(v) or "Unknown") .. "]"
316+
end
317+
elementsWithIDs[k] = tostring(elementID) .. " " .. tostring(numericID)
318+
end
319+
return elementsWithIDs
310320
end
311321

312322
function clearReps ( elemTable )
@@ -429,31 +439,35 @@ function showCurrentBrowser ( elementArray, ignoredElements, elementType, resour
429439
end
430440

431441
function closeCurrentBrowser()
432-
if ( not currentBrowser.showing ) then return end
433-
currentBrowser.showing = false
434-
cSelectedElement = false
435-
if ( callbackFunction ) then
436-
local id = currentBrowserGUI.gridlist:getSelectedText()
437-
if ( not id ) then
438-
callbackFunction(false)
439-
else
440-
callbackFunction(id)
441-
end
442-
callbackFunction = nil
443-
end
444-
currentBrowserGUI.gridlist:disable()
445-
guiCheckBoxSetSelected ( currentBrowserGUI.isolate, false )
446-
if ( dimensionElement ) then
447-
setElementDimension ( dimensionElement, workingDimension )
448-
setElementDimension ( localPlayer, workingDimension )
449-
dimensionElement = false
450-
end
451-
guiSetVisible ( currentBrowserGUI.browser, false )
452-
dumpSettings()
453-
xmlSaveFile ( settingsXML )
454-
removeEventHandler ( "onClientGUIWorldClick", root, currentBrowser.searchClick )
455-
removeEventHandler ( "onClientElementCreate",root,currentBrowser.prepareSearch )
456-
removeEventHandler ( "onClientElementDestroyed",root,currentBrowser.prepareSearch )
442+
if (not currentBrowser.showing) then return end
443+
currentBrowser.showing = false
444+
cSelectedElement = false
445+
if (callbackFunction) then
446+
local fullText = currentBrowserGUI.gridlist:getSelectedText()
447+
if (not fullText) then
448+
callbackFunction(false)
449+
else
450+
-- Extract just the element name portion (before the bracket)
451+
local elementName = string.match(fullText, "^([^%[]+)")
452+
-- Trim any spaces at the end
453+
elementName = string.gsub(elementName, "%s+$", "")
454+
callbackFunction(elementName)
455+
end
456+
callbackFunction = nil
457+
end
458+
currentBrowserGUI.gridlist:disable()
459+
guiCheckBoxSetSelected(currentBrowserGUI.isolate, false)
460+
if (dimensionElement) then
461+
setElementDimension(dimensionElement, workingDimension)
462+
setElementDimension(localPlayer, workingDimension)
463+
dimensionElement = false
464+
end
465+
guiSetVisible(currentBrowserGUI.browser, false)
466+
dumpSettings()
467+
xmlSaveFile(settingsXML)
468+
removeEventHandler("onClientGUIWorldClick", root, currentBrowser.searchClick)
469+
removeEventHandler("onClientElementCreate", root, currentBrowser.prepareSearch)
470+
removeEventHandler("onClientElementDestroyed", root, currentBrowser.prepareSearch)
457471
end
458472

459473
function restoreSelectedElement()

[editor]/editor_gui/client/options_action.lua

+6
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ function optionsActions.precisionRotLevel(value)
3131
optionsData.precisionRotLevel = tonumber(value)
3232
end
3333

34+
function optionsActions.elemScalingSnap(value)
35+
optionsData.elemScalingSnap = tonumber(value)
36+
end
37+
3438
function optionsActions.enableColPatch(value)
3539
local success, isLoaded = editor_main.toggleColPatch(value)
3640
if success then
@@ -166,6 +170,8 @@ function setEditorMoveSpeeds()
166170
move_cursor.setRotateSpeeds ( dialog.slowElemRotate:getValue(), dialog.normalElemRotate:getValue(), dialog.fastElemRotate:getValue() )
167171
move_freecam.setRotateSpeeds ( dialog.slowElemRotate:getValue(), dialog.normalElemRotate:getValue(), dialog.fastElemRotate:getValue() )
168172

173+
move_keyboard.setScaleIncrement ( dialog.elemScaling:getValue() )
174+
169175
move_keyboard.toggleAxesLock ( dialog.lockToAxes:getValue() )
170176
end
171177

[editor]/editor_gui/client/options_backend.lua

+6
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ local xmlVariants = {
1717
["normalElemRotate"]="rotate_normal_speed",
1818
["fastElemRotate"]="rotate_fast_speed",
1919
["slowElemRotate"]="rotate_slow_speed",
20+
["elemScaling"]="scaling_increment",
2021
["lockToAxes"]="movement_lock_to_axes",
2122
["autosnap"]="currentbrowser_autosnap",
2223
["tutorialOnStart"]="tutorial_on_start",
2324
["enableBox"]="enablebox",
2425
["enableXYZlines"]="enablexyzlines",
2526
["precisionLevel"]="precisionlevel",
2627
["precisionRotLevel"]="precisionrotlevel",
28+
["elemScalingSnap"]="scalingSnap",
2729
["enablePrecisionSnap"]="enableprecisionsnap",
2830
["enablePrecisionRotation"]="enableprecisionrotation",
2931
["enableColPatch"]="enablecolpatch",
@@ -47,13 +49,15 @@ local nodeTypes = {
4749
["normalElemRotate"]="progress",
4850
["fastElemRotate"]="progress",
4951
["slowElemRotate"]="progress",
52+
["elemScaling"]="progress",
5053
["lockToAxes"]="bool",
5154
["autosnap"]="bool",
5255
["tutorialOnStart"]="bool",
5356
["enableDumpSave"]="bool",
5457
["enableBox"]="bool",
5558
["precisionLevel"]={"10","5","2","1","0.1","0.01","0.001","0.0001"},
5659
["precisionRotLevel"]={"180","90","45","30","20","10","5","1"},
60+
["elemScalingSnap"]={"1","0.1","0.01","0.001","0.0001"},
5761
["enablePrecisionSnap"]="bool",
5862
["enablePrecisionRotation"]="bool",
5963
["enableXYZlines"]="bool",
@@ -78,12 +82,14 @@ local defaults = {
7882
["normalElemRotate"]=2,
7983
["fastElemRotate"]=10,
8084
["slowElemRotate"]=.25,
85+
["elemScaling"]=.1,
8186
["lockToAxes"]=false,
8287
["autosnap"]=true,
8388
["tutorialOnStart"]=true,
8489
["enableBox"]=true,
8590
["precisionLevel"]="0.1",
8691
["precisionRotLevel"]="30",
92+
["elemScalingSnap"]="0.1",
8793
["enablePrecisionSnap"]=true,
8894
["enablePrecisionRotation"]=false,
8995
["enableXYZlines"]=true,

0 commit comments

Comments
 (0)