Converting Overv's 3d2d wrapper for GM13!

Hey guys! I’ve been spending the last couple hours of my life converting overv’s 3d2d wrapper from GM12(i think) to GM13.

First thing is everyone is free to use this once it’s been converted. It was released publicly by overv and I’m not going to make an ass out of myself and try to claim any level of ownership. Secondly, if someone else does convert this before I do, I would appreciate it if you posted it here so that everyone can see and use it.

I’m very much beginner in regards to using traces, vectors, and angles. That is, of course, where I’ve gotten stuck.

The original files can be found here:

http://forum.facepunch.com/showthread.php?t=1085911

a video of it working as intended can be found here:

A picture of what I’ve got working so far:

Basically just the ability to create an unlimited number of panels, written in derma and simply added through the added function Panel:Paint3D2D which is great. Really there’s only one obstacle, and that would be the detection of the cursor being on the panel, and handling those actions. Obviously he had handled it in GM12, but things have changed in GM13. I’ve looked up all the changelogs since the time from his video being posted, to the current time, searching for any changes that might give me a clue, but nuthin’ cooking. The entire code is posted below.



/*-------------------------------------------------------------------------------------------------------------------------
	3D2D vgui wrapper
		By Overv
-------------------------------------------------------------------------------------------------------------------------*/

local origin, angle, normal, scale

/*-------------------------------------------------------------------------------------------------------------------------
	Helper functions
-------------------------------------------------------------------------------------------------------------------------*/

local function planeLineIntersect( lineStart, lineEnd, planeNormal, planePoint )
	local t = planeNormal:Dot( planePoint - lineStart ) / planeNormal:Dot( lineEnd - lineStart )
	return lineStart + t * ( lineEnd - lineStart )
end

local function getCursorPos()
	local p = planeLineIntersect( LocalPlayer():EyePos(), LocalPlayer():EyePos() + LocalPlayer():GetAimVector() * 16000, normal, origin )
	local offset = origin - p
	
	local angle2 = angle:Angle()
	angle2:RotateAroundAxis( normal, 90 )
	angle2 = angle2:Forward()
	
	local x = Vector( offset.x * angle.x, offset.y * angle.y, offset.z * angle.z ):Length()
	local y = Vector( offset.x * angle2.x, offset.y * angle2.y, offset.z * angle2.z ):Length()
	print(x)
	print(y)
	
	return x, y
end

local function getParents( pnl )
	local parents = {}
	local parent = pnl.Parent
	while ( parent ) do
		table.insert( parents, parent )
		parent = parent.Parent
	end
	return parents
end

local function absolutePanelPos( pnl )
	local x, y = pnl:GetPos()
	local parents = getParents( pnl )
	
	for _, parent in ipairs( parents ) do
		local px, py = parent:GetPos()
		x = x + px
		y = y + py
	end
	
	return x, y
end

local function pointInsidePanel( pnl, x, y )
	local px, py = absolutePanelPos( pnl )
	local sx, sy = pnl:GetSize()
	local IsInside = x >= px and y >= py and x <= px + sx and y <= py + sy
	return IsInside
end

/*-------------------------------------------------------------------------------------------------------------------------
	Input
-------------------------------------------------------------------------------------------------------------------------*/

local inputWindows = {}

local function isMouseOver( pnl )
	return pointInsidePanel( pnl, gui.MouseX(), gui.MouseY() )
end

local function checkHover( pnl )
	pnl.Hovered = isMouseOver( pnl )
	
	for child, _ in pairs( pnl.Childs or {} ) do
		if ( child:IsValid() ) then checkHover( child ) end
	end
end

local function postPanelEvent( pnl, event, ... )

	if ( !pnl:IsValid() or !pointInsidePanel( pnl, gui.MouseX(), gui.MouseY() ) ) then return false end
	
	local handled = false
	
	for child in pairs( pnl.Childs or {} ) do
		if ( postPanelEvent( child, event, ... ) ) then
			handled = true
			break
		end
	end
	
	if ( !handled and pnl[ event ] ) then
		pnl[ event ]( pnl, ... )
		return true
	else
		return false
	end
end

/*-------------------------------------------------------------------------------------------------------------------------
	Mouse input
-------------------------------------------------------------------------------------------------------------------------*/

hook.Add( "KeyPress", "VGUI3D2DMousePress", function( _, key )
	if ( key == IN_USE ) then
		for pnl in pairs( inputWindows ) do
			if ( pnl:IsValid() ) then
				origin = pnl.Origin
				scale = pnl.Scale
				angle = pnl.Angle
				normal = pnl.Normal
				
				postPanelEvent( pnl, "OnMousePressed", MOUSE_LEFT )
			end
		end
	end
end )

hook.Add( "KeyRelease", "VGUI3D2DMouseRelease", function( _, key )
	if ( key == IN_USE ) then
		for pnl in pairs( inputWindows ) do
			if ( pnl:IsValid() ) then
				origin = pnl.Origin
				scale = pnl.Scale
				angle = pnl.Angle
				normal = pnl.Normal
				
				postPanelEvent( pnl, "OnMouseReleased", MOUSE_LEFT )
			end
		end
	end
end )

/*-------------------------------------------------------------------------------------------------------------------------
	Key input
-------------------------------------------------------------------------------------------------------------------------*/



/*-------------------------------------------------------------------------------------------------------------------------
	Drawing
-------------------------------------------------------------------------------------------------------------------------*/

local PANEL = FindMetaTable( "Panel" )

function vgui.Start3D2D( pos, ang, res )
	origin = pos
	scale = res
	angle = ang:Forward()
	
	normal = Angle( ang.p, ang.y, ang.r )
	normal:RotateAroundAxis( ang:Forward(), -90 )
	normal:RotateAroundAxis( ang:Right(), 90 )
	normal = normal:Forward()
	
	cam.Start3D2D( pos, ang, res )
end

function PANEL:Paint3D2D()
	if ( !self:IsValid() ) then return end
	
	// Add it to the list of windows to receive input
	inputWindows[ self ] = true
	
	// Override think of DFrame's to correct the mouse pos by changing the active orientation
	if ( !self.OThink ) then
		self.OThink = self.Think
		
		self.Think = function()
			origin = self.Origin
			scale = self.Scale
			angle = self.Angle
			normal = self.Normal
			
			self:OThink()
		end
	end
	
	// Update the hover state of controls
	checkHover( self )
	
	// Store the orientation of the window to calculate the position outside the render loop
	self.Origin = origin
	self.Scale = scale
	self.Angle = angle
	self.Normal = normal
	
	// Draw it manually
	self:SetPaintedManually( false )
		self:PaintManual()
	self:SetPaintedManually( true )

end

function vgui.End3D2D()
	cam.End3D2D()
end

/*-------------------------------------------------------------------------------------------------------------------------
	Keep track of child controls
-------------------------------------------------------------------------------------------------------------------------*/

if ( !vguiCreate ) then vguiCreate = vgui.Create end
function vgui.Create( class, parent )
	local pnl = vguiCreate( class, parent )
	
	pnl.Parent = parent
	pnl.Class = class
	
	if ( parent ) then
		if ( !parent.Childs ) then parent.Childs = {} end
		parent.Childs[ pnl ] = true
	end
	
	return pnl
end


As far as I can tell, with my limited knowledge, there’s only two functions we really need to correct. The more I look at it, the more I’m sure it’s a simple fix, I’m just unable to do it. the functions are

absolutePanelPos( panel ) and

pointInsidePanel ( panel, mousexpos, mouseypos )

They’re both called every frame, and compare the mouses position in the world to the panels position in the world and see if you’re pointing at it, basically. I did a little bit of debugging, and pointInsidePanel will return false contstantly regardless of any factors I can determine. It is most likely a logic issue. I don’t even really understand what absolutePanelPos is trying to accomplish. I assume that it’s getting the panels position in the world, but I don’t see how it’s doing that. In any case, that’s what I have so far. If anyone has any thoughts or suggestions they’d be GREATLY appreciated!

So what exactly is the error? Be more specific. Is there an actual lua error or does it just draw wrong?

I did say what the error was in my post, but I should have been clearer. When I said that pointInsidePanel() returns false regardless of the position of the mouse, that IS the issue. If we can figure out a way to correctly calculate whether or not the mouse is inside the panel, and handle clicking on the panel, then we’re done, basically.

No, it does not lua error. It simply is unable to tell when you are pointing at the panel.

bump just to keep things alive. New day, I’ll keep working on it!

Someone was working on a 3d2d vgui thing in the WAYWO thread. I don’t think they finished it but it looked pretty solid.

Indeed. I sent him a message but no dice, so here I am :slight_smile:

I fixed this up ages ago, iirc the only thing that was broken was the cursor tracer.

Edit: you have! Oh my god… What’s your license on this? Can it be used for projects and stuff? Reason I ask is I might wanna (maybe not still thinking) use it in a coderhire project I have going. Il credit you fully or something if you grant permission :slight_smile: no worries otherwise.

Hint: Add ent:OBBCenter() to the cursor position. (ent=entity it is drawn on, you have to define that.)

For example if you have cursorpos.x, you add ent:OBBCenter().x

Handsome Matt, would you mind sharing your code?

It’s finished enough for what I needed it for, but not enough for public use :v:

Well perhaps this fine gentleman can pick up where you left off. I’m sure he won’t release anything shitty.

Why though? You already have Overv’s library.

He can’t get it to work.

Matt said he got it to work more or less.

I’ve been working on a project tangentially related to this for the past two days. I’ve made little progress past what I initially posted. I was told in this thread to use OBBCenter but I couldn’t really fiure out the application. I would greatly appreciate either yours or matts code, granted I’m allowed to use it freely :slight_smile:

boop

I love you so hard