Jump to content

XY Axle, Angle, Camera


Jayceon

Recommended Posts

Hello dear reader!

A few days ago i'm tried to make the Object Editor by XYZ Axle by cursor.

But when i'm rotate camera to other side, like Y axle and i'm try to move X axle gets fail. I dont know how to get this perfect.

 

Demonstration image:

(red - X axle; green - Y axle; blue - Z axle)

 

The code:

local screenX, screenY = guiGetScreenSize()

local editorFont = dxCreateFont("files/fonts/Roboto.ttf", 8, false, "antialiased")

local editorTable = nil

local editorMenu = {
	{"move", "Move"},
	{"rotate", "Rotate"},
	{"scale", "Scale"},
	{"save", "Save"}
}

local iconSize = 16
local iconHalfSize = iconSize / 2

local axisLineThickness = 1.5

local editorColors = {
	axisX = {200, 50, 60},
	axisY = {50, 200, 60},
	axisZ = {50, 60, 200},
	
	activeMode = {255, 150, 0},
	inactiveMode = {255, 255, 255}
}

bindKey("F4", "down", -- Editor test
	function ()
		local x, y, z = getElementPosition(localPlayer)
		local obj = createObject(2867, x, y, z)
		
		setElementCollisionsEnabled(obj, false)
		attachElements(obj, localPlayer, 0, 0, 0, 0, 0, 0)
		toggleEditor(obj, false)
	end
)

addEventHandler("onClientRender", getRootElement(),
	function ()
		if not editorTable then
			return
		end
		
		local absX, absY = 0, 0
			
		if isCursorShowing() then
			if not isMTAWindowActive() then
				local relX, relY = getCursorPosition()
				
				absX, absY = relX * screenX, relY * screenY
			end
		end
		
		local elementX, elementY, elementZ = getElementPosition(editorTable["element"])
		
		local startX, startY = getScreenFromWorldPosition(elementX, elementY, elementZ, 128)
		
		local xX, xY, xZ = getPositionFromElementOffset(editorTable["element"], editorTable["elementRadius"], 0, 0)
		local yX, yY, yZ = getPositionFromElementOffset(editorTable["element"], 0, editorTable["elementRadius"], 0)
		local zX, zY, zZ = getPositionFromElementOffset(editorTable["element"], 0, 0, editorTable["elementRadius"])
		
		endXX, endXY = getScreenFromWorldPosition(xX, xY, xZ, 128)
		endYX, endYY = getScreenFromWorldPosition(yX, yY, yZ, 128)
		endZX, endZY = getScreenFromWorldPosition(zX, zY, zZ, 128)
		
		if not endXX or not endYX or not endZX or not endXY or not endYY or not endZY then
			return
		end
		
		dxDrawLine(startX, startY, endXX, endXY, tocolor(editorColors["axisX"][1], editorColors["axisX"][2], editorColors["axisX"][3], 255), axisLineThickness, false)
		dxDrawLine(startX, startY, endYX, endYY, tocolor(editorColors["axisY"][1], editorColors["axisY"][2], editorColors["axisY"][3], 255), axisLineThickness, false)
		dxDrawLine(startX, startY, endZX, endZY, tocolor(editorColors["axisZ"][1], editorColors["axisZ"][2], editorColors["axisZ"][3], 255), axisLineThickness, false)
		
		dxDrawRectangle(endXX - iconHalfSize, endXY - iconHalfSize, iconSize, iconSize, tocolor(editorColors["axisX"][1], editorColors["axisX"][2], editorColors["axisX"][3], 255))
		dxDrawRectangle(endYX - iconHalfSize, endYY - iconHalfSize, iconSize, iconSize, tocolor(editorColors["axisY"][1], editorColors["axisY"][2], editorColors["axisY"][3], 255))
		dxDrawRectangle(endZX - iconHalfSize, endZY - iconHalfSize, iconSize, iconSize, tocolor(editorColors["axisZ"][1], editorColors["axisZ"][2], editorColors["axisZ"][3], 255))
		
		dxDrawImage(endXX - iconHalfSize, endXY - iconHalfSize, iconSize, iconSize, "files/images/" .. editorTable["currentMode"] .. ".png")
		dxDrawImage(endYX - iconHalfSize, endYY - iconHalfSize, iconSize, iconSize, "files/images/" .. editorTable["currentMode"] .. ".png")
		dxDrawImage(endZX - iconHalfSize, endZY - iconHalfSize, iconSize, iconSize, "files/images/" .. editorTable["currentMode"] .. ".png")
		
		if editorTable["hoveredMenuIcon"] then
			editorTable["hoveredMenuIcon"] = false
		end
		
		if not editorTable["activeAxis"] then
			for i = 1, #editorMenu do
				local currentColor = editorColors["inactiveMode"]
				
				if editorTable["currentMode"] == editorMenu[i][1] then
					currentColor = editorColors["activeMode"]
				end
				
				local iconX = ((startX - iconHalfSize) + ((i - 1) * (iconSize + 5))) + 32
				local iconY = (startY - iconHalfSize) + 32
				
				dxDrawRectangle(iconX, iconY, iconSize, iconSize, tocolor(currentColor[1], currentColor[2], currentColor[3], 255))
				dxDrawImage(iconX, iconY, iconSize, iconSize, "files/images/" .. editorMenu[i][1] .. ".png")
				
				if absX >= iconX and absX <= iconX + iconSize and absY >= iconY and absY <= iconY + iconSize then
					editorTable["hoveredMenuIcon"] = i
				end
			end
		end
		
		if editorTable["hoveredMenuIcon"] then
			local tooltipWidth = dxGetTextWidth(editorMenu[editorTable["hoveredMenuIcon"]][2], 1.0, editorFont) + 10
			local tooltipHeight = dxGetFontHeight(1.0, editorFont) + 10
				
			dxDrawRectangle(absX + 10, absY, tooltipWidth, tooltipHeight, tocolor(0, 0, 0, 200))
			dxDrawText(editorMenu[editorTable["hoveredMenuIcon"]][2], absX + 10, absY, absX + 10 + tooltipWidth, absY + tooltipHeight, tocolor(255, 255, 255, 255), 1.0, editorFont, "center", "center")
		
			if getKeyState("mouse1") then
				local hoveredMenuIcon = editorMenu[editorTable["hoveredMenuIcon"]][1]
			
				if editorTable["currentMode"] ~= hoveredMenuIcon then
					if hoveredMenuIcon ~= "save" then
						editorTable["currentMode"] = hoveredMenuIcon
					else
						saveEditorElementChanges()
					end
				end
			end
		end
		
		if editorTable and editorTable["hoveredMode"] then
			editorTable["hoveredMode"] = false
		end
		
		if absX >= endXX - iconHalfSize and absX <= endXX - iconHalfSize + iconSize and absY >= endXY - iconHalfSize and absY <= endXY - iconHalfSize + iconSize then
			editorTable["hoveredMode"] = "X"
		elseif absX >= endYX - iconHalfSize and absX <= endYX - iconHalfSize + iconSize and absY >= endYY - iconHalfSize and absY <= endYY - iconHalfSize + iconSize then
			editorTable["hoveredMode"] = "Y"
		elseif absX >= endZX - iconHalfSize and absX <= endZX - iconHalfSize + iconSize and absY >= endZY - iconHalfSize and absY <= endZY - iconHalfSize + iconSize then
			editorTable["hoveredMode"] = "Z"
		end
		
		-- OBJECT MOVE BY AXLES/CURSOR
		if editorTable and editorTable["activeAxis"] then
			if isCursorShowing() and getKeyState("mouse1") then
				local relX, relY = getCursorPosition()
				local cameraRotation = getCameraRotation()

				local elementX, elementY, elementZ = 0, 0, 0
				local elementRX, elementRY, elementRZ = 0, 0, 0
				local elementSX, elementSY, elementSZ = 0, 0, 0
				
				if isElementAttached(editorTable["element"]) then
					elementX, elementY, elementZ, elementRX, elementRY, elementRZ = getElementAttachedOffsets(editorTable["element"])
					
					local attachedElementRX, attachedElementRY, attachedElementRZ = getElementRotation(getElementAttachedTo(editorTable["element"]))
					
					cameraRotation = cameraRotation + attachedElementRZ
				else
					elementX, elementY, elementZ = getElementPosition(editorTable["element"])
					elementRX, elementRY, elementRZ = getElementRotation(editorTable["element"])
				end
				
				if getElementType(editorTable["element"]) == "object" then
					elementSX, elementSY, elementSZ = getObjectScale(editorTable["element"])
				end
				
				if editorTable["currentMode"] == "move" then
					if editorTable["activeAxis"] == "X" then
						elementX = getInFrontOf(elementX, false, -(cameraRotation + 90), ((relX - 0.5) * 5))
					elseif editorTable["activeAxis"] == "Y" then
						elementY = getInFrontOf(false, elementY, -cameraRotation, -((relY - 0.5) * 5))
					elseif editorTable["activeAxis"] == "Z" then
						elementZ = elementZ - ((relY - 0.5) * 5)
					end
				elseif editorTable["currentMode"] == "rotate" then
					if editorTable["activeAxis"] == "X" then
						elementRX = getInFrontOf(elementRX, false, -(cameraRotation + 90), ((relY - 0.5) * 15))
					elseif editorTable["activeAxis"] == "Y" then
						elementRY = getInFrontOf(false, elementRY, -cameraRotation, ((relX - 0.5) * 15))
					elseif editorTable["activeAxis"] == "Z" then
						elementRZ = getInFrontOf(elementRZ, false, -(cameraRotation + 90), -((relX - 0.5) * 15))
					end
				elseif editorTable["currentMode"] == "scale" then
					if editorTable["activeAxis"] == "X" then
						elementSX = getInFrontOf(elementSX, false, -(cameraRotation + 90), ((relX - 0.5) * 5))
					elseif editorTable["activeAxis"] == "Y" then
						elementSY = getInFrontOf(false, elementSY, -cameraRotation, ((relY - 0.5) * 5))
					elseif editorTable["activeAxis"] == "Z" then
						elementSZ = elementSZ - ((relY - 0.5) * 5)
					end
				end
				
				if isElementAttached(editorTable["element"]) then
					setElementAttachedOffsets(editorTable["element"], elementX, elementY, elementZ, elementRX, elementRY, elementRZ)
				else
					setElementPosition(editorTable["element"], elementX, elementY, elementZ)
					setElementRotation(editorTable["element"], elementRX, elementRY, elementRZ)
				end
				
				if getElementType(editorTable["element"]) == "object" then
					elementSX = math.max(0.25, math.min(3.0, elementSX))
					elementSY = math.max(0.25, math.min(3.0, elementSY))
					elementSZ = math.max(0.25, math.min(3.0, elementSZ))
					
					setObjectScale(editorTable["element"], elementSX, elementSY, elementSZ)
				end
				
				setCursorPosition(screenX / 2, screenY / 2)
				setCursorAlpha(0)
			else
				if editorTable["activeAxis"] then
					editorTable["activeAxis"] = false
					setCursorAlpha(255)
				end
			end
		end
	end
)

addEventHandler("onClientClick", getRootElement(),
	function (button, state, absX, absY)
		if not editorTable then
			return
		end
		
		if button == "left" then
			if state == "down" then
				if editorTable["hoveredMode"] then
					setCursorPosition(screenX / 2, screenY / 2)
					setCursorAlpha(0)
					
					editorTable["activeAxis"] = editorTable["hoveredMode"]
				end
			elseif state == "up" then
				local oldActiveAxis = editorTable["activeAxis"]
				
				if oldActiveAxis then
					editorTable["activeAxis"] = false
					
					if oldActiveAxis == "X" then
						setCursorPosition(endXX, endXY)
					elseif oldActiveAxis == "Y" then
						setCursorPosition(endYX, endYY)
					elseif oldActiveAxis == "Z" then
						setCursorPosition(endZX, endZY)
					end
					
					setCursorAlpha(255)
				end
			end
		end
	end
)

function toggleEditor(element, saveFunction, ...)
	if element then
		editorTable = {
			element = element,
			elementRadius = getElementRadius(element) * 1.25,
			
			saveFunction = saveFunction,
			others = {...},

			currentMode = "move",
			hoveredMode = false,
			hoveredMenuIcon = false,
			activeAxis = false,
		}
	else
		editorTable = nil
		setCursorAlpha(255)
	end
end

function saveEditorElementChanges()
	if not editorTable then
		return
	end
	
	if not editorTable["element"] or not isElement(editorTable["element"]) then
		return
	end
	
	if editorTable["saveFunction"] then
		if isElementAttached(editorTable["element"]) then
			local x, y, z, rx, ry, rz = getElementAttachedOffsets(editorTable["element"])
			
			triggerEvent(editorTable["saveFunction"], localPlayer, {{x, y, z}, {rx, ry, rz}, {getObjectScale(editorTable["element"])}}, unpack(editorTable["others"]))
		else
			triggerEvent(editorTable["saveFunction"], localPlayer, {{getElementPosition(editorTable["element"])}, {getElementRotation(editorTable["element"])}, {getObjectScale(editorTable["element"])}}, unpack(editorTable["others"]))
		end
	end
	
	toggleEditor(false)
end

function getPositionFromElementOffset(element, offsetX, offsetY, offsetZ)
	local elementMatrix = getElementMatrix(element, false)
	
    local elementX = offsetX * elementMatrix[1][1] + offsetY * elementMatrix[2][1] + offsetZ * elementMatrix[3][1] + elementMatrix[4][1]
    local elementY = offsetX * elementMatrix[1][2] + offsetY * elementMatrix[2][2] + offsetZ * elementMatrix[3][2] + elementMatrix[4][2]
    local elementZ = offsetX * elementMatrix[1][3] + offsetY * elementMatrix[2][3] + offsetZ * elementMatrix[3][3] + elementMatrix[4][3]
	
    return elementX, elementY, elementZ
end

function getInFrontOf(x, y, angle, distance)
	distance = distance or 1
	
	if x and not y then
		return x + distance * math.sin(math.rad(-angle))
	elseif not x and y then
		return y + distance * math.cos(math.rad(-angle))
	elseif x and y then
		return x + distance * math.sin(math.rad(-angle)), y + distance * math.cos(math.rad(-angle))
	end
end

function getCameraRotation()
	local cx, cy, _, tx, ty = getCameraMatrix()
	
	return math.deg(math.atan2(tx - cx, ty - cy))
end

 

Thanks the replies.

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...