TopLeftVector2 = LM.Vector2:new()
local graphics = view:Graphics()
local pt = LM.Point:new_local()
pt:Set(0, 0)
graphics:ScreenToWorld(pt, TopLeftVector2)
-- ??????
matrix:Transform(TopLeftVector2)
Re: Get top left screen position of layer with ScreenToWorld ?
Posted: Tue Oct 26, 2021 4:12 pm
by SimplSam
I started to answer this twice and stopped (twice) because I figured out - I don't actually understand the question.
Subject says:: "Get top left screen position of layer with ScreenToWorld ?"
- That suggests you want the vector screen position of the top,left corner of a Layer.
Body says:: "Get the position on a layer of the top left screen pixel of the viewport?"
- That suggests you want the position (not sure pix or vec?) of the top,left corner of the screen viewport relative to a layer.
Can you clarify?
Re: Get top left screen position of layer with ScreenToWorld ?
Re: Get top left screen position of layer with ScreenToWorld ?
Posted: Tue Oct 26, 2021 7:47 pm
by Lukas
SimplSam wrote: ↑Tue Oct 26, 2021 4:12 pmCan you clarify?
Ah sorry, it's difficult to express myself with all these technical things that I don't completely understand myself.
Basically what I'm trying to do is set a bone's position to the top-left of the screen, independent of viewport/camera/layer position.
Here's some code, which is probably doing things weirdly/inefficient/completely the wrong approach. It works in some situations, but not when the camera is placed in specific ways. I'm running the function from within "DrawMe" and the 'guiBone' is a global bone variable.
function FO_Draw:DockGUIbone(moho, view)
if guiBone ~= nil then
-- * Fix GUI-bone settings:
guiBone.fConstraints = false
-- * Get layer:
local layer = FO_Utilities:RigLayer(moho)
-- * Get top left position:
TopLeftVector2 = LM.Vector2:new()
local graphics = view:Graphics()
local pt = LM.Point:new_local()
pt:Set(0, 0)
graphics:ScreenToWorld(pt, TopLeftVector2)
-- * Flip GUI bone if nessecary:
local flippedH = false
local flipLayer = layer
local timesFlipped = 0
local totalXScale = 1
while flipLayer ~= nil do
totalXScale = totalXScale * flipLayer.fScale.value.x
if flipLayer.fFlipH:GetValue(moho.frame) or flipLayer.fScale.value.x < 0 then
timesFlipped = timesFlipped + 1
end
flipLayer = flipLayer:Parent()
end
if totalXScale < 0 then
totalXScale = totalXScale * -1
end
guiBone.fFlipH:Clear()
if (timesFlipped % 2 ~= 0) then
-- * Flipped an odd amount fo times
guiBone.fFlipH:SetValue(1, true)
end
-- * Get View rotation:
local viewRotation = graphics:ViewRotation()
-- * Get View zoom:
local viewZoom = graphics:ViewZoom()
-- * Get Camera zoom:
local cameraZoom = (moho.document.fCameraTrack:GetValue(moho.frame).z / 3.7321) / (moho.document.fCameraZoom:GetValue(moho.frame) / 2)
-- * Layer matrix without camera: (write down why...?)
local matrix = FO_Utilities:LayerMatrix(moho, moho.layer, moho.frame)
matrix:Invert()
-- * Camera Matrix: (Doesn't work for Z value or zoom?)
local cameraMatrix = LM.Matrix:new_local()
moho.document:GetCameraMatrix(moho.frame, cameraMatrix)
local cameraScale = cameraMatrix:ScaleValue()
-- * What the hell was I thinking here?
-- *********************
-- * Remember:
local camT = moho.document.fCameraTrack:GetValue(0)
local camZ = moho.document.fCameraZoom:GetValue(0)
local camR = moho.document.fCameraRoll:GetValue(0)
local camP = moho.document.fCameraPanTilt:GetValue(0)
-- * Reset:
local vec3 = LM.Vector3:new()
vec3:Set(0, 0, 3.7321)
moho.document.fCameraTrack:SetValue(0, vec3)
moho.document.fCameraZoom:SetValue(0, 2)
local vec2 = LM.Vector2:new()
vec2:Set(0, 0)
moho.document.fCameraRoll:SetValue(0, 0)
moho.document.fCameraPanTilt:SetValue(0, vec2)
-- * Get REST camera matrix:
local cameraRestMatrix = LM.Matrix:new_local()
moho.document:GetCameraMatrix(0, cameraRestMatrix)
-- * Revert:
moho.document.fCameraTrack:SetValue(0, camT)
moho.document.fCameraZoom:SetValue(0, camZ)
moho.document.fCameraRoll:SetValue(0, camR)
moho.document.fCameraPanTilt:SetValue(0, camP)
-- *********************
-- * What?
cameraMatrix:Invert()
cameraMatrix:Multiply(cameraRestMatrix)
matrix:Multiply(cameraMatrix)
-- * Topleft vec2 position:
matrix:Transform(TopLeftVector2)
-- * Add layer transform rotation to view rotation:
translation, rotationZ, scale, flip, pString, rString, sString, fString = AE_Utilities:Matrix2transform(matrix)
if flippedH then
viewRotation = -viewRotation
end
local rotation = viewRotation - rotationZ
-- * Key GUI-bone position:
guiBone.fAnimPos:Clear()
guiBone.fAnimPos:SetValue(1, TopLeftVector2)
guiBone.fPos = TopLeftVector2
-- * Key GUI-bone angle:
guiBone.fAnimAngle:Clear()
guiBone.fAnimAngle:SetValue(1, -rotation)
guiBone.fAngle = -rotation
-- * Key GUI-bone scale:
local scale = 1/totalXScale / viewZoom/3 * cameraZoom
guiBone.fAnimScale:Clear()
guiBone.fAnimScale:SetValue(1, scale)
-- * Dials:
--[[
for i = 1, #smartBoneDials do
local dial = smartBoneDials[i]
-- * dial Scale:
dial.fAnimScale:Clear()
dial.fAnimScale:SetValue(1, scale*dial.fAnimScale:GetValue(0))
-- * Dial Pos:
-- dial.fAnimPos:Clear()
local dialPos = dial.fAnimPos:GetValue(0)
dialPos:Set(dialPos.x, dialPos.y * scale)
dial.fAnimPos:SetValue(1, dialPos)
end
--]]
-- * Update viewport:
moho.layer:UpdateCurFrame()
end
end
Here's a video showing the WIP tool. The docked 'guiBone' kind of stays put, but it's because the camera is in the default z-position. (In reality, in my scenes the camera is rarely in the default z-position)
Re: Get top left screen position of layer with ScreenToWorld ?
Posted: Tue Oct 26, 2021 8:11 pm
by synthsin75
Personally, I would go with a solution that's completely independent of the camera. For example, you can make a reference of the smart bone layer, delete the original's sublayers, and set it immune to camera. The original will still control the smart bones in the reference (where the rendered art is), but as long as you break the layer transform sync, you can now place your controls anywhere.
Re: Get top left screen position of layer with ScreenToWorld ?
Posted: Wed Oct 27, 2021 5:10 pm
by hayasidist
I looked at this from the opposite direction having failed to get my ideas for the asked question to work.
starting with a mesh point (i.e. M_Point, not LM_Point) in the top left I got the point's fPos and did a world-to-screen on that - and that gave me a crazy result for the screen pixel location; but transforming the fPos with the full document matrix and then doing a world-to-screen on that gave the "right answer". IOW the vec2 you put in to world-to-screen is not the actual "world" vec2 you need... That worked for all the cases I tried - even with the orbit view and multiple camera and layer movements...
so I tried that in reverse: screen-to-world of a point then transform the world result with the inverted document matrix (which is more or less what's in the Transform layer tool that Stan modified) but that didn't work at all.
at this point I decided that I must have been doing something really dumb, so I repeated the concept with the mouse - trying to do a W-T-S on mouseEvent.vec to match mouseEvent.pt -- abject failure on my part!!
===
where I am on this:
what works:
>> W-T-S on a transformed (vec) gives the correct LM Point.
>> S-T-W on that LM Point gives a result that is tolerably equal to the transformed(vec) (+/- quantising because of screen resolution??)
What doesn't want to work: any transformation - most notably using the Invert() of the matrix used to do the transform - that I've tried so far on the transformed vec in an attempt to retrieve the original vec
any ideas?
Re: Get top left screen position of layer with ScreenToWorld ?
local pt = LM.Point:new_local()
local m = LM.Matrix:new_local()
m:Identity()
moho.layer:GetFullTransform(moho.frame, m, moho.document)
pt:Set(0, 0)
local vec2 = view:Point2Vec(pt, m)
mesh:AddLonePoint(vec2, 0)
mesh:AppendPoint(vec2, 0)
Re: Get top left screen position of layer with ScreenToWorld ?
Posted: Thu Oct 28, 2021 11:07 am
by hayasidist
Point2Vec!! well I never knew that was there -- that's cracked it!
local p1 = LM.Point:new_local()
p1:Set(0,0)
local v1 = view:Point2Vec(p1)
p.s. I guess ScreenToWorld is when you are drawing on the screen with Graphics - which is independent of Layer transforms and Camera.
Re: Get top left screen position of layer with ScreenToWorld ?
Posted: Thu Oct 28, 2021 12:13 pm
by hayasidist
the typo (well spotted BTW!) was because the code is actually gathered from a long sequence of failed attempts - much of which is commented out along with the reason for its failures -- and the intervening stuff I deleted left me with an inconsistent pair of get and use the matrix! (I actually had many different matrices in there - graphics, camera only, layer, doc, inverts ...) a slip of the clip!
Re: Get top left screen position of layer with ScreenToWorld ?
Posted: Thu Oct 28, 2021 1:40 pm
by Lukas
Wow, thanks a lot everyone!
I was looking in all the wrong places. I would have never figured that out unless I somehow stumbled upon view:Point2Vec(). It looks like is going to work after all