diff --git a/[editor]/editor_gui/client/options_action.lua b/[editor]/editor_gui/client/options_action.lua index 07149e110..85594fe36 100644 --- a/[editor]/editor_gui/client/options_action.lua +++ b/[editor]/editor_gui/client/options_action.lua @@ -7,13 +7,17 @@ function optionsActions.enableSounds (value) enableSound = value end -function optionsActions.enableBox(value) - optionsData.enableBox = value -end - -function optionsActions.enableXYZlines(value) - optionsData.enableXYZlines = value -end +function optionsActions.enableBox(value) + optionsData.enableBox = value +end + +function optionsActions.enableHoverBoundingBox(value) + optionsData.enableHoverBoundingBox = value +end + +function optionsActions.enableXYZlines(value) + optionsData.enableXYZlines = value +end function optionsActions.enablePrecisionRotation(value) optionsData.enablePrecisionRotation = value diff --git a/[editor]/editor_gui/client/options_backend.lua b/[editor]/editor_gui/client/options_backend.lua index 4dbd9a00a..604034ec9 100644 --- a/[editor]/editor_gui/client/options_backend.lua +++ b/[editor]/editor_gui/client/options_backend.lua @@ -22,9 +22,10 @@ local xmlVariants = { ["slowElemScale"]="scaling_slow_speed", ["lockToAxes"]="movement_lock_to_axes", ["autosnap"]="currentbrowser_autosnap", -["tutorialOnStart"]="tutorial_on_start", -["enableBox"]="enablebox", -["enableXYZlines"]="enablexyzlines", +["tutorialOnStart"]="tutorial_on_start", +["enableBox"]="enablebox", +["enableHoverBoundingBox"]="enablehoverboundingbox", +["enableXYZlines"]="enablexyzlines", ["precisionLevel"]="precisionlevel", ["precisionRotLevel"]="precisionrotlevel", ["elemScalingSnap"]="elemscalingsnap", @@ -59,9 +60,10 @@ local nodeTypes = { ["lockToAxes"]="bool", ["autosnap"]="bool", ["tutorialOnStart"]="bool", -["enableDumpSave"]="bool", -["enableBox"]="bool", -["precisionLevel"]={"10","5","2","1","0.1","0.01","0.001","0.0001"}, +["enableDumpSave"]="bool", +["enableBox"]="bool", +["enableHoverBoundingBox"]="bool", +["precisionLevel"]={"10","5","2","1","0.1","0.01","0.001","0.0001"}, ["precisionRotLevel"]={"180","90","45","30","20","10","5","1"}, ["elemScalingSnap"]={"1","0.1","0.01","0.001","0.0001"}, ["enablePrecisionSnap"]="bool", @@ -95,9 +97,10 @@ local defaults = { ["slowElemScale"]=0.01, ["lockToAxes"]=false, ["autosnap"]=true, -["tutorialOnStart"]=true, -["enableBox"]=true, -["precisionLevel"]="0.1", +["tutorialOnStart"]=true, +["enableBox"]=true, +["enableHoverBoundingBox"]=false, +["precisionLevel"]="0.1", ["precisionRotLevel"]="30", ["elemScalingSnap"]="0.0001", ["enablePrecisionSnap"]=true, diff --git a/[editor]/editor_gui/client/options_gui.lua b/[editor]/editor_gui/client/options_gui.lua index e259c0521..d2ef17c1d 100644 --- a/[editor]/editor_gui/client/options_gui.lua +++ b/[editor]/editor_gui/client/options_gui.lua @@ -32,8 +32,9 @@ function createOptionsDialog() dialog.tutorialOnStart = editingControl.boolean:create{["x"]=0.02,["y"]=0.8,["width"]=0.35,["height"]=0.1,["relative"]=true,["parent"]=dialog.generalTab,["label"]="Query for tutorial on start"} --------------------------------- - dialog.enableBox = editingControl.boolean:create{["x"]=0.60,["y"]=0.02,["width"]=0.35,["height"]=0.1,["relative"]=true,["parent"]=dialog.generalTab,["label"]="Enable Bounding Box"} - dialog.enableXYZlines = editingControl.boolean:create{["x"]=0.60,["y"]=0.12,["width"]=0.35,["height"]=0.1,["relative"]=true,["parent"]=dialog.generalTab,["label"]="Enable XYZ Lines"} + dialog.enableBox = editingControl.boolean:create{["x"]=0.43,["y"]=0.02,["width"]=0.25,["height"]=0.1,["relative"]=true,["parent"]=dialog.generalTab,["label"]="Enable Bounding Box"} + dialog.enableHoverBoundingBox = editingControl.boolean:create{["x"]=0.68,["y"]=0.02,["width"]=0.31,["height"]=0.1,["relative"]=true,["parent"]=dialog.generalTab,["label"]="Bounding box on hover over"} + dialog.enableXYZlines = editingControl.boolean:create{["x"]=0.60,["y"]=0.12,["width"]=0.35,["height"]=0.1,["relative"]=true,["parent"]=dialog.generalTab,["label"]="Enable XYZ Lines"} --------------------------------- dialog.enablePrecisionSnap = editingControl.boolean:create{["x"]=0.60,["y"]=0.22,["width"]=0.35,["height"]=0.1,["relative"]=true,["parent"]=dialog.generalTab,["label"]="Enable Snap - Precise Position"} guiCreateLabel ( 0.47, 0.34, 70, 17, "Position Snap Level:", true, dialog.generalTab ) diff --git a/[editor]/editor_main/client/gridlines.lua b/[editor]/editor_main/client/gridlines.lua index 9f4a1e8f0..b57c23a9b 100644 --- a/[editor]/editor_main/client/gridlines.lua +++ b/[editor]/editor_main/client/gridlines.lua @@ -274,6 +274,7 @@ function drawObjectMoveLines() end function doBasicElementRenders() + renderHoverOverGridLines() if not isElement(attachedToElement) then return end if exports["editor_gui"]:sx_getOptionData("enableBox") then renderGridlines() end if exports["editor_gui"]:sx_getOptionData("enableXYZlines") then drawXYZLines() end @@ -314,3 +315,136 @@ function getOffsetRelativeToElement ( element, x, y, z ) elementMatrix = matrix{x,y,z} * elementMatrix return elementMatrix end + +----------------------------------------------------------- +-- Extra: Highlight on hover (Transparency + Animated Color Box) +----------------------------------------------------------- + +local highlightedElement = nil +local hoverBoundingBoxIgnoreMatrix = { + pickup = true +} + +-- HSV to RGB conversion +local function hsvToRgb(h, s, v) + local r, g, b + + local i = math.floor(h * 6) + local f = h * 6 - i + local p = v * (1 - s) + local q = v * (1 - f * s) + local t = v * (1 - (1 - f * s)) + + i = i % 6 + + if i == 0 then r, g, b = v, t, p + elseif i == 1 then r, g, b = q, v, p + elseif i == 2 then r, g, b = p, v, t + elseif i == 3 then r, g, b = p, q, v + elseif i == 4 then r, g, b = t, p, v + elseif i == 5 then r, g, b = v, p, q + end + + return r*255, g*255, b*255 +end + +local function getElementBoundingBoxCorners(element) + if not isElement(element) then return false end + if getElementDimension(element) ~= getElementDimension(localPlayer) then return false end + + local x, y, z = edf.edfGetElementPosition(element) + if not x then return false end + + local minX, minY, minZ, maxX, maxY, maxZ = edf.edfGetElementBoundingBox(element) + if not minX then + local radius = edf.edfGetElementRadius(element) + if radius then + minX, minY, minZ, maxX, maxY, maxZ = -radius, -radius, -radius, radius, radius, radius + else + return false + end + end + + local halfCenterX = (minX + maxX) * 0.25 + local halfCenterY = (minY + maxY) * 0.25 + local halfCenterZ = (minZ + maxZ) * 0.25 + + minX = minX - halfCenterX + minY = minY - halfCenterY + minZ = minZ - halfCenterZ + maxX = maxX - halfCenterX + maxY = maxY - halfCenterY + maxZ = maxZ - halfCenterZ + + local relativeCorners = { + {minX, minY, minZ}, + {maxX, minY, minZ}, + {maxX, maxY, minZ}, + {minX, maxY, minZ}, + {minX, minY, maxZ}, + {maxX, minY, maxZ}, + {maxX, maxY, maxZ}, + {minX, maxY, maxZ} + } + + local elementMatrix = getElementMatrix(element) + if elementMatrix and not hoverBoundingBoxIgnoreMatrix[getElementType(element)] then + for i, corner in ipairs(relativeCorners) do + relativeCorners[i] = { + corner[1] * elementMatrix[1][1] + corner[2] * elementMatrix[2][1] + corner[3] * elementMatrix[3][1] + elementMatrix[4][1], + corner[1] * elementMatrix[1][2] + corner[2] * elementMatrix[2][2] + corner[3] * elementMatrix[3][2] + elementMatrix[4][2], + corner[1] * elementMatrix[1][3] + corner[2] * elementMatrix[2][3] + corner[3] * elementMatrix[3][3] + elementMatrix[4][3] + } + end + else + for i, corner in ipairs(relativeCorners) do + relativeCorners[i] = {x + corner[1], y + corner[2], z + corner[3]} + end + end + + return relativeCorners +end + +-- Draw 3D bounding box lines +local function drawBoundingBox(corners, r, g, b, a) + if not corners then return end + -- base + dxDrawLine3D(corners[1][1],corners[1][2],corners[1][3], corners[2][1],corners[2][2],corners[2][3], tocolor(r,g,b,a), 2) + dxDrawLine3D(corners[2][1],corners[2][2],corners[2][3], corners[3][1],corners[3][2],corners[3][3], tocolor(r,g,b,a), 2) + dxDrawLine3D(corners[3][1],corners[3][2],corners[3][3], corners[4][1],corners[4][2],corners[4][3], tocolor(r,g,b,a), 2) + dxDrawLine3D(corners[4][1],corners[4][2],corners[4][3], corners[1][1],corners[1][2],corners[1][3], tocolor(r,g,b,a), 2) + -- top + dxDrawLine3D(corners[5][1],corners[5][2],corners[5][3], corners[6][1],corners[6][2],corners[6][3], tocolor(r,g,b,a), 2) + dxDrawLine3D(corners[6][1],corners[6][2],corners[6][3], corners[7][1],corners[7][2],corners[7][3], tocolor(r,g,b,a), 2) + dxDrawLine3D(corners[7][1],corners[7][2],corners[7][3], corners[8][1],corners[8][2],corners[8][3], tocolor(r,g,b,a), 2) + dxDrawLine3D(corners[8][1],corners[8][2],corners[8][3], corners[5][1],corners[5][2],corners[5][3], tocolor(r,g,b,a), 2) + -- vertical + dxDrawLine3D(corners[1][1],corners[1][2],corners[1][3], corners[5][1],corners[5][2],corners[5][3], tocolor(r,g,b,a), 2) + dxDrawLine3D(corners[2][1],corners[2][2],corners[2][3], corners[6][1],corners[6][2],corners[6][3], tocolor(r,g,b,a), 2) + dxDrawLine3D(corners[3][1],corners[3][2],corners[3][3], corners[7][1],corners[7][2],corners[7][3], tocolor(r,g,b,a), 2) + dxDrawLine3D(corners[4][1],corners[4][2],corners[4][3], corners[8][1],corners[8][2],corners[8][3], tocolor(r,g,b,a), 2) +end + +function renderHoverOverGridLines() + if not exports["editor_gui"]:sx_getOptionData("enableHoverBoundingBox") then + highlightedElement = nil + return + end + + local element = getTargetedElement() + if element and element ~= highlightedElement then + highlightedElement = element + elseif not element and highlightedElement then + highlightedElement = nil + end + + -- Draw animated bounding box + if highlightedElement and isElement(highlightedElement) then + local box = getElementBoundingBoxCorners(highlightedElement) + if box then + local tick = getTickCount() / 2000 -- animation speed + local r,g,b = hsvToRgb(tick % 1, 1, 1) -- rainbow color cycle + drawBoundingBox(box, r, g, b, 255) + end + end +end \ No newline at end of file diff --git a/[editor]/editor_main/client/main.lua b/[editor]/editor_main/client/main.lua index de1f55782..3f36f99cd 100644 --- a/[editor]/editor_main/client/main.lua +++ b/[editor]/editor_main/client/main.lua @@ -1404,4 +1404,4 @@ end function disableCharacterSounds() -- CJ stealth breathing, fall screaming etc. setWorldSoundEnabled ( 25, false ) -end +end \ No newline at end of file