-- **************************************************
-- Provide Moho with the name of this script object
-- **************************************************

ScriptName = "AE_CurveExposure"

-- **************************************************
-- General information about this script
-- **************************************************

AE_CurveExposure = {}

function AE_CurveExposure:Name()
	return "Stroke Exposure"
end

function AE_CurveExposure:Version()
	return "7.2"
end

function AE_CurveExposure:Description()
	return MOHO.Localize("/Scripts/Tool/CurveExposure/Description=Drag side to side to adjust the exposure of a stroke (hold <alt> to expose the opposite end of the stroke)")
end

function AE_CurveExposure:Creator()
	return "Smith Micro Software, Inc."
end

function AE_CurveExposure:UILabel()
	return(MOHO.Localize("/Scripts/Tool/CurveExposure/StrokeExposure=Stroke Exposure"))
end

-- **************************************************
-- Recurring values
-- **************************************************

AE_CurveExposure.selID = -1
AE_CurveExposure.savedVal = 0
AE_CurveExposure.oldEnd = 1
AE_CurveExposure.oldStart = 0
AE_CurveExposure.altKey = false
AE_CurveExposure.workWithEnd = true

-- **************************************************
-- The guts of this script
-- **************************************************

function AE_CurveExposure:IsEnabled(moho)
	if (moho:CountCurves() > 0) then
		return true
	end
	return false
end

function AE_CurveExposure:IsRelevant(moho)
	local mesh = moho:DrawingMesh()
	if (mesh == nil) then
		return false
	end
	return true
end

function AE_CurveExposure:OnMouseDown(moho, mouseEvent)
	local mesh = moho:DrawingMesh()
	if (mesh == nil) then
		return
	end

	moho.document:PrepUndo(moho.drawingLayer)
	moho.document:SetDirty()

	self.selID = -1
	self.altKey = mouseEvent.altKey

	
		local curveID = -1
		local segID = -1
		curveID, segID = mouseEvent.view:PickEdge(mouseEvent.pt, curveID, segID)
		if (curveID >= 0) then
			mesh:SelectNone()
			self.selID = curveID
			local curve = mesh:Curve(self.selID)
			for i = 0, curve:CountPoints() - 1 do
				curve:Point(i).fSelected = true
			end
		
		
			local startPercent, endPercent = 0, 1
			startPercent, endPercent = curve:GetSegmentRange(segID, startPercent, endPercent)

			local closestPoint = mesh:Curve(curveID):ClosestPointOnSegment(segID, mouseEvent.drawingVec, true, true)
			local minDist = 100
			local foundPercent = startPercent + (endPercent - startPercent)/2

			local precision = 0.01
			
			local p1 = LM.Vector2:new_local()
			local p2 = LM.Vector2:new_local()
			local p3 = LM.Vector2:new_local()
			local p4 = LM.Vector2:new_local()
			curve:GetControlPoints(segID, p1, p2, p3, p4, false)
			
			
			for i=startPercent, endPercent, precision do
					--local nextPoint = mesh:Curve(curveID):GetPercentLocation(i) -- it does not work this way

					local t = (i - startPercent)/(endPercent - startPercent)
					local nextPoint = p1*math.pow(1-t, 3) + p2*3*math.pow(1-t, 2)*t + p3*3*(1-t)*math.pow(t,2) + p4*math.pow(t,3)

					
					local dist = (closestPoint - nextPoint):Mag()
					if dist < minDist then
						minDist = dist
						foundPercent = i
					end
			end

		
			self.oldEnd = curve.fEndPercent.value
			self.oldStart = curve.fStartPercent.value
			
			if curve.fStartPercent.value > foundPercent then				
				curve.fStartPercent:SetValue(moho.drawingLayerFrame, foundPercent)
				self.workWithEnd = false
			else
				curve.fEndPercent:SetValue(moho.drawingLayerFrame, foundPercent)
				self.workWithEnd = true
			end
			
			
		

		end
	
	self.savedVal = 0
	mouseEvent.view:DrawMe()
end

function AE_CurveExposure:OnMouseMoved(moho, mouseEvent)
	local mesh = moho:DrawingMesh()
	if (mesh == nil) then
		return
	end

	local newVal = (mouseEvent.pt.x - mouseEvent.startPt.x) / mouseEvent.view:Graphics():Width()
	
	if self.selID >= 0 then
	
		local curve = mesh:Curve(self.selID)
		
		if not mouseEvent.altKey == self.altKey then
			if self.workWithEnd then
				local newVal = curve.fEndPercent.value
				curve.fStartPercent:SetValue(moho.drawingLayerFrame, newVal)
				if newVal < self.oldEnd then
					curve.fEndPercent:SetValue(moho.drawingLayerFrame, self.oldEnd)
				else
					curve.fEndPercent:SetValue(moho.drawingLayerFrame, 1)				
				end
				self.workWithEnd = false
			else
				local newVal = curve.fStartPercent.value
				curve.fEndPercent:SetValue(moho.drawingLayerFrame, newVal)
				if newVal > self.oldStart then
					curve.fStartPercent:SetValue(moho.drawingLayerFrame, self.oldStart)
				else
					curve.fStartPercent:SetValue(moho.drawingLayerFrame, 0)				
				end
				self.workWithEnd = true
			end
			
			self.altKey = mouseEvent.altKey
		end
		
		

			local exp = 0
			if (not self.workWithEnd) then
				exp = curve.fStartPercent.value
			else
				exp = curve.fEndPercent.value
			end
			exp = exp - self.savedVal + newVal
			exp = LM.Clamp(exp, -0.01, 1.01)
			if (not self.workWithEnd) then
				curve.fStartPercent:SetValue(moho.drawingLayerFrame, exp)
			else
				curve.fEndPercent:SetValue(moho.drawingLayerFrame, exp)
			end
			

	
	end

	self.savedVal = newVal
	moho.drawingLayer:UpdateCurFrame()
	mouseEvent.view:DrawMe()
end

function AE_CurveExposure:OnMouseUp(moho, mouseEvent)
	local mesh = moho:DrawingMesh()
	if (mesh == nil) then
		return
	end

	moho:UpdateSelectedChannels()
	moho:NewKeyframe(CHANNEL_CURVEEXP)
end

function AE_CurveExposure:OnKeyDown(moho, keyEvent)
	LM_SelectPoints:OnKeyDown(moho, keyEvent)
end

-- **************************************************
-- Tool options - create and respond to tool's UI
-- **************************************************

AE_CurveExposure.CHANGE_START = MOHO.MSG_BASE + 1
AE_CurveExposure.CHANGE_END = MOHO.MSG_BASE + 2
AE_CurveExposure.DUMMY = MOHO.MSG_BASE + 3
AE_CurveExposure.SELECTITEM = MOHO.MSG_BASE + 4

function AE_CurveExposure:DoLayout(moho, layout)
	self.menu = LM.GUI.Menu(MOHO.Localize("/Scripts/Tool/CurveExposure/SelectGroup=Select Group"))

	self.popup = LM.GUI.PopupMenu(128, false)
	self.popup:SetMenu(self.menu)
	layout:AddChild(self.popup)
	
	layout:AddChild(LM.GUI.StaticText(MOHO.Localize("/Scripts/Tool/FollowCurve/StartPercentage=Start percentage:")))
	self.startPercentage = LM.GUI.TextControl(0, "00.0000", self.CHANGE_START, LM.GUI.FIELD_UFLOAT)
	self.startPercentage:SetWheelInc(1.0)
	layout:AddChild(self.startPercentage)
	
	layout:AddChild(LM.GUI.StaticText(MOHO.Localize("/Scripts/Tool/FollowCurve/EndPercentage=End percentage:")))
	self.endPercentage = LM.GUI.TextControl(0, "00.0000", self.CHANGE_END, LM.GUI.FIELD_UFLOAT)
	self.endPercentage:SetWheelInc(1.0)
	layout:AddChild(self.endPercentage)
end

function AE_CurveExposure:UpdateWidgets(moho)
	if (moho:CurrentTool() ~= "AE_CurveExposure") then
		return -- this could get called when doing a double-tap on a multitouch Wacom device with a different active tool
	end

	local mesh = moho:DrawingMesh()
	if (mesh == nil) then
		return
	end

	MOHO.BuildGroupMenu(self.menu, mesh, self.SELECTITEM, self.DUMMY)
	
	local numCurves = 0
	local startPercent = 0.0
	local endPercent = 0.0
	for i = 0, mesh:CountCurves() - 1 do
		local curve = mesh:Curve(i)
		if (curve:IsSelected()) then
			numCurves = numCurves + 1
			startPercent = startPercent + curve.fStartPercent.value
			endPercent = endPercent + curve.fEndPercent.value
		end
	end
	if (numCurves > 0) then
		startPercent = startPercent * 100.0 / numCurves
		startPercent = LM.Clamp(startPercent, 0.0, 100.0)
		endPercent = endPercent * 100.0 / numCurves
		endPercent = LM.Clamp(endPercent, 0.0, 100.0)
		self.startPercentage:SetValue(startPercent)
		self.startPercentage:Enable(true)
		self.endPercentage:SetValue(endPercent)
		self.endPercentage:Enable(true)
	else
		self.startPercentage:SetValue("")
		self.startPercentage:Enable(false)
		self.endPercentage:SetValue("")
		self.endPercentage:Enable(false)
	end
end

function AE_CurveExposure:HandleMessage(moho, view, msg)
	local mesh = moho:DrawingMesh()
	if (mesh == nil) then
		return
	end

	if (msg == self.CHANGE_START) then
		moho.document:PrepUndo(moho.drawingLayer)
		moho.document:SetDirty()
		local startPercent = self.startPercentage:FloatValue() / 100.0
		startPercent = LM.Clamp(startPercent, 0.0, 1.0)
		if (startPercent < 0.0001) then
			startPercent = -0.01
		end
		for i = 0, mesh:CountCurves() - 1 do
			local curve = mesh:Curve(i)
			if (curve:IsSelected()) then
				curve.fStartPercent:SetValue(moho.drawingLayerFrame, startPercent)
			end
		end
		view:DrawMe()
		moho:NewKeyframe(CHANNEL_CURVEEXP)
		moho:UpdateUI()
	elseif (msg == self.CHANGE_END) then
		moho.document:PrepUndo(moho.drawingLayer)
		moho.document:SetDirty()
		local endPercent = self.endPercentage:FloatValue() / 100.0
		endPercent = LM.Clamp(endPercent, 0.0, 1.0)
		if (endPercent > 0.9999) then
			endPercent = 1.01
		end
		for i = 0, mesh:CountCurves() - 1 do
			local curve = mesh:Curve(i)
			if (curve:IsSelected()) then
				curve.fEndPercent:SetValue(moho.drawingLayerFrame, endPercent)
			end
		end
		view:DrawMe()
		moho:NewKeyframe(CHANNEL_CURVEEXP)
		moho:UpdateUI()
	elseif (msg >= self.SELECTITEM) then
		mesh:SelectNone()
		local i = msg - self.SELECTITEM
		local name = mesh:Group(i):Name()
		mesh:SelectGroup(name)
		moho:UpdateUI()
	end
end

Icon
Tweak for Curve Exposure
Listed

Script type: Tool

Uploaded: Sep 19 2020, 23:04

Last modified: Sep 20 2020, 05:52

Pick the end or start of curve exposure by mouse click
Mouse click sets the end of Curve Exposure. Use Alt to set the Start.
Mouse movement works just like with built-in tool.
Works with only one picked Curve (not Shape like built-in tool)
This script, and all other scripts on this site are distributed as free software under the GNU General Public License 3.0 or later.
Downloads count: 7