How would I emulate Roblox's part "Tilting" functionality?

Hello DevForum, I was hoping for some guiding points on how to create the tilting portion of a drag system such as what Roblox has in-engine.

I’m currently working on a robust in-game toolset that mimicks Roblox’s toolkit, kind of like F3X but more specialized for a game. Much of this is already implemented, but I’m struggling with creating an intuitive way to tilt objects.

I currently have a system that can take a NormalId, surface normal, and an object as an input and output a CFrame that pushes the object off of the normal so that the specified NormalId of the object is flush with the surface normal.
In addition, I have a function that takes a rotational CFrame and outputs the NormalId representation of that CFrame which would be closest to a specified surface normal vector.
With these combined, I can effectively snap an object to any surface with a given orientation.

My tilt system is based on storing a rotation CFrame whose rotation values are added to whenever the tilt key is pressed. The axis chosen to add to is dependent on the axis perpendicular to where the object is being placed (i.e the Y axis if the flush surface is Top or Bottom) and a scalar rotation value which allows the object’s rotation to vary about this axis. This system doesn’t really make a lot of sense to me logically, and is very inconsistent in practice, but was the closest I could come up with to get my desired functionality so far.

There are a few reasons why my system is lacking:

  • Currently, my tilting system does not take the camera’s orientation into account, as I know Roblox’s system does.
  • Even if it accounted for the camera, objects can be rotated arbitrarily via the scalar rotation value. That means that this value, or at least values derivative of it, need to be taken into account when tilting in addition to the camera. I’m not sure what math would be involved in making this consistent.
  • There is a strange bug with items when they are tilted twice on the same axis, where they will flip on an irrelevant axis to the one they are being rotated on. (this can be seen near the start of the video whenever the object is rotated twice from its starting position)
    These issues are demonstrated in this video where I use my system, where I use both the rotate and tilt inputs.

I could add some code if it would be beneficent, but it’s currently embedded in so many layers of systems that it would be difficult to test individually. If anyone is curious about any parts of it though, I will provide.

How would I go about solving these issues? Any concepts or references I should have a go at?