Custom camera Y axis limit

I am currently having trouble of how I would combine this 2 parts rotation and place it on a camera. Any ideas will be help full.

Also the solution might be with VectorUp and VectorRight but I’m not sure of how to convert the red part and the green part CFrame to camera CFrame with offset.

Code
local TweenService = game:GetService("TweenService")
local UIS = game:GetService("UserInputService")

local camera = workspace.CurrentCamera
local partX = workspace.Model.PrimaryPart
local partY = workspace.Model.Y
local currentY = partY.CFrame
local currentX = partX.CFrame

local mouseHold = false
camera.CameraSubject = partY

UIS.InputChanged:Connect(function(key, isTyping)
	if isTyping then return end
	
	if mouseHold and key.UserInputType == Enum.UserInputType.MouseMovement then
		--camera.CameraType = Enum.CameraType.Scriptable
		updateCameraFunction(key.Delta.X, key.Delta.Y)
	end
end)

UIS.InputBegan:Connect(function(key, isTyping)
	if isTyping then return end
	
	if key.UserInputType == Enum.UserInputType.MouseButton2 then
		mouseHold = true
		UIS.MouseBehavior = Enum.MouseBehavior.LockCurrentPosition
	end
end)

UIS.InputEnded:Connect(function(key, isTyping)
	if key.UserInputType == Enum.UserInputType.MouseButton2 then
		mouseHold = false
		UIS.MouseBehavior = Enum.MouseBehavior.Default
		--camera.CameraType = Enum.CameraType.Custom
	end
end)

function updateCameraFunction(X, Y)
	currentY = CFrame.new(partX.Position) * (partY.CFrame.Rotation * CFrame.fromEulerAnglesXYZ(0, 0, -Y * 0.05))
	currentX *= CFrame.fromEulerAnglesXYZ(0, math.rad(X) * 0.5, 0)
	
	local rX, rY, rZ = currentY:ToEulerAnglesXYZ()
	local cameraAngle = math.deg(rZ)
	local clampped = math.clamp(cameraAngle, -15, 80)
	
	if clampped == 80 then
		currentY = CFrame.new(partX.Position) * (CFrame.fromEulerAnglesXYZ(0, 0, math.rad(clampped)))
	elseif clampped == -15 then
		currentY = CFrame.new(partX.Position) * (CFrame.fromEulerAnglesXYZ(0, 0, math.rad(clampped)))
	end
	
	TweenService:Create(partY, TweenInfo.new(0.2), {CFrame = currentY}):Play()
	TweenService:Create(partX, TweenInfo.new(0.2), {CFrame = currentX}):Play()
	
	print(currentY.UpVector * currentX.RightVector)
end

what do you mean by combining the rotations?
(rotation1+rotation2)/2
?

I’m trying to make like a custom camera, the video shown is what should be combined into the camera.

The green part is the Y axis, and the red part is the X axis, I tried just doing the simple thing which was CFrame.fromEulerAnglesXYZ(X, Y, 0)) but this just make the camera go crazy.

Actually never mind I forgot that you can just multiply angle X and angle Y.

local TweenService = game:GetService("TweenService")
local UIS = game:GetService("UserInputService")

local Player = game.Players.LocalPlayer
local character = Player.Character or Player.CharacterAdded:Wait()
local camera = workspace.CurrentCamera
local baord = workspace.Board

local cameraOffset = Vector3.new(0, 0, 10)
local controlDown = false
local mouseHold = false

local cameraAngleX = 0
local cameraAngleY = 0
local currentFOV = 70
local cameraZoom = 10

camera.CameraSubject = baord
camera.CameraType = Enum.CameraType.Scriptable

local rayPart : Part = nil

local rayParams = RaycastParams.new()
rayParams.FilterDescendantsInstances = {camera, baord, workspace.Chess}

UIS.InputChanged:Connect(function(key, isTyping)
	if isTyping then return end
	
	if mouseHold and key.UserInputType == Enum.UserInputType.MouseMovement then
		updateCameraCFrame(key.Delta.X, key.Delta.Y)
	elseif controlDown and key.UserInputType == Enum.UserInputType.MouseWheel then
		updateCameraFOV(key.Position.Z)
	elseif key.UserInputType == Enum.UserInputType.MouseWheel then
		updateCameraZoom(key.Position.Z)
	end
end)

UIS.InputBegan:Connect(function(key, isTyping)
	if isTyping then return end
	
	if key.UserInputType == Enum.UserInputType.MouseButton2 then
		mouseHold = true
		UIS.MouseBehavior = Enum.MouseBehavior.LockCurrentPosition
	elseif key.KeyCode == Enum.KeyCode.LeftControl then
		controlDown = true
	end
end)

UIS.InputEnded:Connect(function(key, isTyping)
	if key.UserInputType == Enum.UserInputType.MouseButton2 then
		mouseHold = false
		UIS.MouseBehavior = Enum.MouseBehavior.Default
	elseif key.KeyCode == Enum.KeyCode.LeftControl then
		controlDown = false
	end
end)

function updateCameraCFrame(X, Y)
	cameraAngleY = math.clamp(cameraAngleY - Y * 0.4, -75, -5)
	cameraAngleX -= X
	
	local currentCFrame = CFrame.new(baord.CFrame.Position) * CFrame.Angles(0, math.rad(cameraAngleX), 0) * CFrame.Angles(math.rad(cameraAngleY), 0, 0)
	local cameraCFrame = currentCFrame:PointToWorldSpace(cameraOffset)
	local cameraFocus = currentCFrame:PointToWorldSpace()
	
	local ray = checkIfBlocking(cameraFocus, cameraCFrame - cameraFocus)

	if ray then
		cameraCFrame = currentCFrame:PointToWorldSpace(ray)
	end
	
	camera.CFrame = CFrame.lookAt(cameraCFrame, cameraFocus)
end

function updateCameraZoom(Z)
	cameraZoom = math.clamp(cameraZoom - Z * 5, 3, 50)
	cameraOffset = Vector3.new(0, 0, cameraZoom)
	
	local currentCFrame = CFrame.new(baord.CFrame.Position) * camera.CFrame.Rotation
	local cameraCFrame = currentCFrame:PointToWorldSpace(cameraOffset)
	local cameraFocus = currentCFrame:PointToWorldSpace()

	local ray = checkIfBlocking(cameraFocus, cameraCFrame - cameraFocus)

	if ray then
		cameraCFrame = currentCFrame:PointToWorldSpace(ray)
	end

	camera.CFrame = CFrame.lookAt(cameraCFrame, cameraFocus)
end

function updateCameraFOV(Z)
	currentFOV = math.clamp(currentFOV - Z * 10, 1, 120)
	
	TweenService:Create(camera, TweenInfo.new(1), {FieldOfView = currentFOV}):Play()
end

function checkIfBlocking(origin, direction)
	if rayPart then
		rayPart:Destroy()
	end
	
	local ray = workspace:Raycast(origin, direction, rayParams)
	
	if ray then
		local distance = (origin - ray.Position).Magnitude
		rayPart = Instance.new("Part", workspace)
		rayPart.Anchored = true
		rayPart.CanTouch = false
		rayPart.BrickColor = BrickColor.Red()
		rayPart.Material = Enum.Material.Neon
		rayPart.Size = Vector3.new(0.1, 0.1, distance)
		rayPart.CFrame = CFrame.new(origin, ray.Position) * CFrame.new(0, 0, -distance/2)
		
		return Vector3.new(0, 0, distance - 1)
	end
end