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

ScriptName = "MR_CurveTool"

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

MR_CurveTool = {}

function MR_CurveTool:Name()
	return self:Localize('UILabel')
end

function MR_CurveTool:Version()
	return '1.0'
end

function MR_CurveTool:UILabel()
	return self:Localize('UILabel')
end

function MR_CurveTool:Creator()
	return 'Eugene Babich'
end

function MR_CurveTool:Description()
	return self:Localize('Description')
end

-- **************************************************
-- Is Relevant / Is Enabled
-- **************************************************

function MR_CurveTool:IsRelevant(moho)
	local mesh = moho:DrawingMesh()
	if (mesh == nil) then
		return false
	end
	
	local v1, v2, v3 = self:GetMohoVersion(moho)
	self.isMoho13_5_3 = true
	if not v3 then
		v3 = 0
	end
	if v1 < 13 then
		self.isMoho13_5_3 = false
	elseif v2 < 5 then
		self.isMoho13_5_3 = false
	elseif v3 < 3 then	
		self.isMoho13_5_3 = false
	end
	
	self.selectedPointID = -1
	self.drawingStatus = false
	self.drawWeldPoint = false
	self.startPoint = 1000000
	return true
end

function MR_CurveTool:IsEnabled(moho)
	local mesh = moho:DrawingMesh()
	if (mesh == nil) then
		return false
	end
	
	if (moho.drawingLayer:CurrentAction() ~= "") then
		return false
	end
	
	local v1, v2, v3 = self:GetMohoVersion(moho)
	self.isMoho13_5_2 = true
	if not v3 then
		v3 = 0
	end
	if v1 < 13 then
		self.isMoho13_5_2 = false
	elseif v2 < 5 then
		self.isMoho13_5_2 = false
	elseif v3 < 3 then	
		self.isMoho13_5_2 = false
	end
	
	if self.isMoho13_5_2 then
		if (mesh:ContinuousTriangulation()) then
			return false
		end
	end	
	
	if moho:CurrentTool() ~= 'MR_CurveTool' then
		self.selectedPointID = -1
		self.drawingStatus = false
		self.drawWeldPoint = false
		self.startPoint = 1000000
	end
	return true
end

-- **************************************************
-- Recurring Values
-- **************************************************

MR_CurveTool.drawingStatus = false
MR_CurveTool.fixedHandles = true
MR_CurveTool.autoWeldRadius = 144
MR_CurveTool.selectedPointID = -1
MR_CurveTool.lastSelectedPointID = -1
MR_CurveTool.curvature = 0.33
MR_CurveTool.lastClickVec = LM.Vector2:new_local()
MR_CurveTool.closest = 100000
MR_CurveTool.closestID = -1
MR_CurveTool.endWeldVec = LM.Vector2:new_local()
MR_CurveTool.endWeldVec:Set(-10000000, -10000000)
MR_CurveTool.endWeldToPoint = true
MR_CurveTool.drawWeldPoint = false
MR_CurveTool.startPoint = -1
MR_CurveTool.startPointClick = false
MR_CurveTool.isBackspace = false

-- **************************************************
-- Prefs
-- **************************************************

function MR_CurveTool:LoadPrefs(prefs)
	self.curvature = prefs:GetFloat("MR_CurveTool.curvature", 0.33)
	self.fixedHandles = prefs:GetBool("MR_CurveTool.fixedHandles", true)
end

function MR_CurveTool:SavePrefs(prefs)
	prefs:SetFloat("MR_CurveTool.curvature", self.curvature)
	prefs:SetBool("MR_CurveTool.fixedHandles", self.fixedHandles)
end

function MR_CurveTool:ResetPrefs()
	self.curvature = 0.33
	self.fixedHandles = true
end

-- **************************************************
-- Keyboard/Mouse Control
-- **************************************************

function MR_CurveTool:NonDragMouseMove()
	return true
end

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

	if not self.drawingStatus then
		moho.document:PrepUndo(moho.drawingLayer)
		moho.document:SetDirty()
	end	
	
	local closestID = -1
	local closest = 1e6

	local selectedPoint
	local doNotAddNewPoint = false
	
	local clickVec = LM.Vector2:new_local()
	clickVec:Set(mouseEvent.drawingVec)
	
	local testVec1 = LM.Vector2:new_local()
	testVec1:Set(mouseEvent.drawingVec)
	closestID = mesh:ClosestPoint(testVec1)
	if closestID >= 0 then
		local testVec2 = LM.Vector2:new_local()
		testVec2:Set(mesh:Point(closestID).fPos)
		closest = self:GetColosestVec(moho, mouseEvent, testVec1,testVec2)
	end
	
	if self.selectedPointID < 0 then
		if not mouseEvent.altKey then
			if closest < self.autoWeldRadius then
				selectedPoint = mesh:Point(closestID)
				self.selectedPointID = closestID
				mesh:SelectNone()
				selectedPoint.fSelected = true
				
				if mesh:Point(closestID):IsEndpoint() then
					if mouseEvent.ctrlKey then
						selectedPoint:SetCurvature(MOHO.PEAKED, 0)
					else
						selectedPoint:SetCurvature(self.curvature, 0)
					end
					selectedPoint:ResetControlHandles(0)
					self:ClearPointKeys(moho, self.selectedPointID)
				end
				
				if closestID >= 0 then
					local testPoint = mesh:Point(closestID)
					if not testPoint:IsEndpoint() then
						doNotAddNewPoint = true
						mesh:AddPoint(mouseEvent.drawingVec, -1, 0)
						mesh:WeldPoints(mesh:CountPoints() - 1, closestID, 0)
						self.selectedPointID = mesh:CountPoints() - 1
						self.startPoint = self.selectedPointID
						mesh:SelectNone()
						selectedPoint = mesh:Point(self.selectedPointID)
						selectedPoint.fSelected = true
						moho:UpdateSelectedChannels()
					else
						self.startPointClick = true
					end
				end	
			else
				if self:AddPointOnCurve(moho, mouseEvent) then
					mesh:SelectNone()
					self.selectedPointID = - 1
					doNotAddNewPoint = true
					self.drawingStatus = false
					self.drawWeldPoint = false
				end
			end
		end
	else
		mesh:SelectNone()
	end

	if self.selectedPointID < 0 then
		if not doNotAddNewPoint then
			mesh:SelectNone()
			if (moho.gridOn) then
				moho:SnapToGrid(mouseEvent.drawingVec)
			end
			
			mesh:AddPoint(mouseEvent.drawingVec, -1, moho.drawingLayerFrame)
			self.selectedPointID = mesh:CountPoints() - 1
			self.startPoint = self.selectedPointID
			
			self.lastSelectedPointID = self.selectedPointID
			local pt = mesh:Point(mesh:CountPoints() - 2)
			
			if mouseEvent.ctrlKey then
				pt:SetCurvature(MOHO.PEAKED, 0)
			else
				pt:SetCurvature(self.curvature, 0)
			end
			pt:ResetControlHandles(0)
			self.selectedPointID = mesh:CountPoints() - 1
			self.drawingStatus = true
			pt = mesh:Point(mesh:CountPoints() - 1)
			pt:SetCurvature(self.curvature, 0)
			pt:ResetControlHandles(0)
			self:ClearPointKeys(moho, mesh:CountPoints() - 2)
			self:ClearPointKeys(moho, mesh:CountPoints() - 1)
		end	
	else
		local testVec1 = LM.Vector2:new_local()
		testVec1:Set(mouseEvent.drawingVec)
		local drawingClosestID = mesh:ClosestPoint(testVec1, mesh:CountPoints() - 1)
		local testVec2 = LM.Vector2:new_local()
		testVec2:Set(self.lastClickVec)
		
		local dis = self:GetColosestVec(moho, mouseEvent, testVec1, testVec2)
		local drawingClosest = self:GetColosestVec(moho, mouseEvent, testVec1, mesh:Point(drawingClosestID).fPos)
		
		if dis < self.autoWeldRadius * 1.5 and self.drawingStatus then
			self.drawingStatus = false
			self.drawWeldPoint = false
			mesh:DeletePoint(mesh:CountPoints() - 1)
			mesh:SelectNone()
			local totalPoints = mesh:CountPoints()
			if totalPoints > 0 then
				local pt = mesh:Point(totalPoints - 1)
				pt:SetCurvature(self.curvature, 0)
				pt:ResetControlHandles(0)
			end	
			self.selectedPointID = -1
			self.lastSelectedPointID = -1
			self.startPoint = 1000000
			self:ClearPointKeys(moho, totalPoints - 1)
			moho:UpdateUI()
		else
			if drawingClosest < self.autoWeldRadius * 1.5 and drawingClosestID ~= self.lastSelectedPointID
			and self.drawingStatus and not mouseEvent.altKey then
				local targetPointID = mesh:CountPoints() - 1
				local isEndPoint = mesh:Point(drawingClosestID):IsEndpoint()
				mesh:WeldPoints(targetPointID, drawingClosestID, 0)
				if isEndPoint then
					local pt = mesh:Point(drawingClosestID)
					if mouseEvent.ctrlKey then
						pt:SetCurvature(MOHO.PEAKED, 0)
					else
						pt:SetCurvature(self.curvature, 0)
					end	
					pt:ResetControlHandles(0)
				end
				moho:Click()
				mesh:SelectNone()
				self.drawingStatus = false
				self.drawWeldPoint = false
				self:ClearPointKeys(moho, mesh:CountPoints() - 1)
				self:ClearPointKeys(moho, drawingClosestID)
				self.selectedPointID = -1
				moho:UpdateUI()
			else
				if not mouseEvent.altKey and self.drawingStatus then
					local m = LM.Matrix:new_local()
					local v = LM.Vector2:new_local()
					local pt = LM.Point:new_local()
					local curveID = -1
					local segID = -1
					local pickWidth = 5
					if (moho.gridOn) then
						moho:SnapToGrid(mouseEvent.drawingVec)
					end
					moho.drawingLayer:GetFullTransform(moho.frame, m, moho.document)
					v:Set(mesh:Point(self.selectedPointID).fPos)
					m:Transform(v)
					mouseEvent.view:Graphics():WorldToScreen(v, pt)
					curveID, segID = mesh:Point(self.selectedPointID):GetEndpointEdge(curveID, segID)
					curveID, segID = moho.view:PickEdge(pt, curveID, segID, pickWidth)
					if (curveID >= 0) then -- add a point in the middle of some curve
						if (not mesh:Curve(curveID):IsPointOnSegment(self.selectedPointID, segID)) and
							(not mesh:Curve(curveID):IsPointOnSegment(self.selectedPointID, segID - 1)) and
							(not mesh:Curve(curveID):IsPointOnSegment(self.selectedPointID, segID + 1)) then 
							local curve = mesh:Curve(curveID)
							mesh:AddPoint(curve:ClosestPointOnSegment(segID, mesh:Point(self.selectedPointID).fPos, true, true), curveID, segID, 0)
							mesh:WeldPoints(self.selectedPointID, mesh:CountPoints() - 1, 0)
							moho:Click()
							self.drawingStatus = false
							self.drawWeldPoint = false

							if mouseEvent.ctrlKey then
								mesh:Point(mesh:CountPoints() - 1):SetCurvature(MOHO.PEAKED, 0)
							end
							
							self:ClearPointKeys(moho, self.selectedPointID)
							self.selectedPointID = -1
							moho:UpdateUI()
							goto endOfOnClickFunction
						end
					end
				end

				local pt = mesh:Point(mesh:CountPoints() - 1)
				if mouseEvent.ctrlKey then
					pt:SetCurvature(MOHO.PEAKED, 0)
				else
					pt:SetCurvature(self.curvature, 0)
				end
				pt:ResetControlHandles(0)
				if not doNotAddNewPoint then
					mesh:AddPoint(mouseEvent.drawingVec, self.selectedPointID, 0)
					self.lastSelectedPointID = self.selectedPointID
					self.selectedPointID = mesh:CountPoints() - 1
					if self.startPointClick then
						self.startPoint = self.selectedPointID
						self.startPointClick = false
					end	
					if self.isBackspace then
						pt.fAnimPos:SetValue(moho.drawingFrame, mouseEvent.drawingVec)
						self.isBackspace = false
					end	
					self:ClearPointKeys(moho, self.selectedPointID)
					self:ClearPointKeys(moho, self.lastSelectedPointID)
				else
					self.lastSelectedPointID = self.selectedPointID
					self.selectedPointID = mesh:CountPoints() - 1
					self:ClearPointKeys(moho, self.selectedPointID)
					self:ClearPointKeys(moho, self.lastSelectedPointID)
				end
				mesh:Point(self.selectedPointID).fTempPos = mouseEvent.drawingVec
				self.drawingStatus = true
				::endOfOnClickFunction::
			end	
		end	
	end
	self.lastClickVec:Set(clickVec)
	mouseEvent.view:DrawMe()
end

function MR_CurveTool:OnMouseMoved(moho, mouseEvent)
	local mesh = moho:DrawingMesh()
	if (mesh == nil) then
		return
	end
	
	if (mesh:CountPoints() < 1) then
		return
	end
	if not self.drawingStatus then
		return
	end
	
	local curVec = mouseEvent.drawingVec - mouseEvent.drawingStartVec
	self.closestID = -1
	self.closest = 1e6
	
	local clickVec = LM.Vector2:new_local()
	clickVec:Set(mouseEvent.drawingVec)
	
	local pt = mesh:Point(self.selectedPointID)
	pt.fPos:Set(mouseEvent.drawingVec)
	if (moho.gridOn) then
		moho:SnapToGrid(pt.fPos)
	end
	
	if not mouseEvent.altKey and pt:IsEndpoint() then
		local m = LM.Matrix:new_local()
		local testVec1 = LM.Vector2:new_local()
		local p1 = LM.Point:new_local()
		local testVec2 = LM.Vector2:new_local()
		local p2 = LM.Point:new_local()
		local dist = 0
		local curveID = -1
		local segID = -1
		local pickWidth = 5

		self.endWeldVec:Set(-10000000, -10000000)
		testVec1:Set(pt.fPos)
		moho.drawingLayer:GetFullTransform(moho.frame, m, moho.document)
		m:Transform(testVec1)
		moho.view:Graphics():WorldToScreen(testVec1, p1)

		self.drawWeldPoint = false

		local closestID = mesh:ClosestPoint(pt.fPos, self.selectedPointID)
		if (closestID >= 0) then
			testVec2:Set(mesh:Point(closestID).fPos)
			m:Transform(testVec2)
			moho.view:Graphics():WorldToScreen(testVec2, p2)
			dist = (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)
			if (dist < self.autoWeldRadius * 1.5 and (not mesh:ArePointsAdjacent(self.selectedPointID, closestID))) then
				self.endWeldToPoint = true
				self.endWeldVec:Set(mesh:Point(closestID).fPos)
				self.drawWeldPoint = true
			else
				curveID, segID = pt:GetEndpointEdge(curveID, segID)
				curveID, segID = moho.view:PickEdge(p1, curveID, segID, pickWidth)
				if (curveID >= 0) then -- add a point in the middle of some curve
					if ((not mesh:Curve(curveID):IsPointOnSegment(self.selectedPointID, segID)) and
						(not mesh:Curve(curveID):IsPointOnSegment(self.selectedPointID, segID - 1)) and
						(not mesh:Curve(curveID):IsPointOnSegment(self.selectedPointID, segID + 1))) then -- don't weld the point back on itself
						self.endWeldToPoint = false
						self.endWeldVec:Set(mesh:Curve(curveID):ClosestPointOnSegment(segID, pt.fPos, true, true))
						self.drawWeldPoint = true
					end
				end
			end
		end
	else	
		self.drawWeldPoint = false
	end

	moho:AddPointKeyframe(0)
	mouseEvent.view:DrawMe()
end

function MR_CurveTool:OnMouseUp(moho, mouseEvent)
	moho:UpdateUI()
	moho.layer:UpdateCurFrame()
	moho:UpdateSelectedChannels()
end

function MR_CurveTool:OnKeyDown(moho, keyEvent)
	local mesh = moho:DrawingMesh()
	if (mesh == nil) then
		return
	end
	if keyEvent.keyCode == LM.GUI.KEY_BIND then
		self.drawingStatus = false
		self.drawWeldPoint = false
		self.selectedPointID = -1
		self.startPoint = -1
		local lastPointID = mesh:CountPoints() -1
		if lastPointID >= 1 then
			local point = mesh:Point(lastPointID)
			point.fAnimPos:SetValue(0, point.fPos)
		end	
		keyEvent.view:DrawMe()
		moho:UpdateUI()
	elseif keyEvent.keyCode == LM.GUI.KEY_BACKSPACE then
		local endPointID = mesh:CountPoints() -1
		if endPointID >= self.startPoint and self.drawingStatus then
			local endPoint = mesh:Point(endPointID)
			mesh:DeletePoint(endPointID)
			if mesh:CountPoints() -1 >= self.startPoint then
				self.selectedPointID = mesh:CountPoints() -1
				mesh:Point(self.selectedPointID):ResetControlHandles(0)
				self:ClearPointKeys(moho, self.selectedPointID)
				moho.layer:UpdateCurFrame()
				self.isBackspace = true
				keyEvent.view:DrawMe()
			else
				self.selectedPointID = -1
				self.drawingStatus = false
				self.drawWeldPoint = false
				moho.layer:UpdateCurFrame()
				keyEvent.view:DrawMe()
				moho:UpdateUI()
			end
			
		end
	end
end

function MR_CurveTool:OnKeyUp(moho, keyEvent)
end

function MR_CurveTool:DrawMe(moho, view)
	local mesh = moho:DrawingMesh()
	if (mesh == nil) then
		return
	end

	if self.drawWeldPoint then
		local g = view:Graphics()
		local matrix = LM.Matrix:new_local()

		moho.drawingLayer:GetFullTransform(moho.frame, matrix, moho.document)
		g:Push()
		g:ApplyMatrix(matrix)

		if (self.endWeldToPoint) then
			g:SetColor(0, 255, 0, 128)
		else
			g:SetColor(255, 0, 0, 128)
		end
		g:SetSmoothing(true)
		g:SetBezierTolerance(2)
		g:FillCircle(self.endWeldVec, moho:PixelToDoc(self.autoWeldRadius * 0.15) / g:CurrentScale(false))
		g:SetSmoothing(false)

		g:Pop()
	end
end

-- **************************************************
-- Tool Panel Layout
-- **************************************************

MR_CurveTool.CURVATURE = MOHO.MSG_BASE
MR_CurveTool.FIXED_HANDLES = MOHO.MSG_BASE + 1

function MR_CurveTool:DoLayout(moho, layout)
	self.curvatureInput = LM.GUI.TextControl(50, '0.3', self.CURVATURE, LM.GUI.FIELD_FLOAT, self:Localize('Curvature'))
	self.curvatureInput:SetWheelInc(0.05)
	layout:AddChild(self.curvatureInput, LM.GUI.ALIGN_LEFT, 0)
	
	self.fixedHandlesImageButton = LM.GUI.ImageButton('ScriptResources/mr_curve_tool/mr_fixed_handles', self:Localize('Fixed Handles Tooltip'), true, self.FIXED_HANDLES, false)
	layout:AddChild(self.fixedHandlesImageButton, LM.GUI.ALIGN_LEFT, 0)
end

function MR_CurveTool:UpdateWidgets(moho)
	self.curvatureInput:SetValue(self.curvature)
	self.fixedHandlesImageButton:SetValue(self.fixedHandles)
end

function MR_CurveTool:HandleMessage(moho, view, msg)
	if msg == self.CURVATURE then
		self.curvature = LM.Clamp(self.curvatureInput:Value(), 0, 1)
		self.curvatureInput:SetValue(self.curvature)
	elseif msg == self.FIXED_HANDLES then
		self.fixedHandles = self.fixedHandlesImageButton:Value()
	end
end

function MR_CurveTool:GetColosestVec(moho, mouseEvent, vec1, vec2)
	local testVec1 = LM.Vector2:new_local()
	testVec1:Set(vec1)
	local testVec2 = LM.Vector2:new_local()
	testVec2:Set(vec2)
	
	local p1 = LM.Point:new_local()
	local p2 = LM.Point:new_local()
	local m = LM.Matrix:new_local()
	moho.drawingLayer:GetFullTransform(moho.frame, m, moho.document)
	m:Transform(testVec1)
	m:Transform(testVec2)
	mouseEvent.view:Graphics():WorldToScreen(testVec1, p1)
	mouseEvent.view:Graphics():WorldToScreen(testVec2, p2)
	p1.x = p1.x - p2.x
	p1.y = p1.y - p2.y
	local closest = (p1.x * p1.x) + (p1.y * p1.y)
	return closest
end

function MR_CurveTool:AddPointOnCurve(moho, mouseEvent)
	local mesh = moho:DrawingMesh()
	if (mesh == nil) then
		return
	end
	local sharpCorners = false
	if mouseEvent.ctrlKey then
		sharpCorners = true
	end
	
	local curveID = -1
	local segID = -1
	local pointWasAdded = false

	if not mouseEvent.altKey then
		local pickWidth = 5
		curveID = -1
		segID = -1
		curveID, segID = mouseEvent.view:PickEdge(mouseEvent.pt, curveID, segID, pickWidth)
	end
	if segID >= 0 then
		if (curveID >= 0) then -- add a point in the middle of some curve
			if (moho.gridOn) then
				moho:SnapToGrid(mouseEvent.drawingStartVec)
				moho:SnapToGrid(mouseEvent.drawingVec)
			end
			local v = mesh:Curve(curveID):ClosestPointOnSegment(segID, mouseEvent.drawingVec, true, true)
			mesh:AddPoint(v, curveID, segID, 0, self.fixedHandles)
			pointWasAdded = true
		else -- add a new curve segment
			if (moho.gridOn) then
				moho:SnapToGrid(mouseEvent.drawingStartVec)
				moho:SnapToGrid(mouseEvent.drawingVec)
			end
			mesh:AddPoint(mouseEvent.drawingVec, -1, moho.drawingLayerFrame)
			if (sharpCorners) then
				mesh:Point(mesh:CountPoints() - 1):SetCurvature(MOHO.PEAKED, 0)
				mesh:Point(mesh:CountPoints() - 2):SetCurvature(MOHO.PEAKED, 0)
			end
			self.secondPtID = mesh:CountPoints() - 2
			pointWasAdded = true
		end
		if (sharpCorners) then
			mesh:Point(mesh:CountPoints() - 1):SetCurvature(MOHO.PEAKED, 0)
		end
	end	
	return pointWasAdded
end

function MR_CurveTool:ClearPointKeys(moho, ptID)
	local mesh = moho:DrawingMesh()
	if (mesh == nil) then
		return
	end

	if (moho.drawingLayerFrame > 0) then
		if (ptID >= 0 and ptID < mesh:CountPoints()) then
			local point = mesh:Point(ptID)
			point.fAnimPos:SetValue(0, point.fAnimPos.value) point.fAnimPos:DeleteKey(moho.drawingLayerFrame)
			point.fWidth:SetValue(0, point.fWidth.value) point.fWidth:DeleteKey(moho.drawingLayerFrame)
			point.fColor:SetValue(0, point.fColor.value) point.fColor:DeleteKey(moho.drawingLayerFrame)
			point.fColorStrength:SetValue(0, point.fColorStrength.value) point.fColorStrength:DeleteKey(moho.drawingLayerFrame)
			if self.isMoho13_5_3 then
				local numCurves = point:CountCurves()
				for i = 0, point:CountCurves() - 1 do
					local curve = nil
					local ptPos = -1
					curve, ptPos = point:Curve(i, ptPos)
					curve:DeleteCurvatureKey(ptPos, moho.drawingLayerFrame)
				end
			end	
		end

		if (ptID >= 0 and ptID < mesh:CountPoints()) then
			mesh:MakePointConsistentWithNeighbors(ptID, moho.drawingLayerFrame)
		end
	end
end

function MR_CurveTool:GetMohoVersion(moho)
	local numVers = {}
	local vers = moho:AppVersion()
	for n in string.gmatch (vers, "%d+") do
		table.insert(numVers, tonumber(n))
	end
	return numVers[1], numVers[2], numVers[3]
end

-- **************************************************
-- Localization
-- **************************************************

function MR_CurveTool:Localize(text)
	local phrase = {}

	phrase['Description'] = 'Create points with a click. Ctrl - create a sharp corner. Alt - disable auto-welding. Backspace - remove the last point. Enter or double-click - finish the curve.'
	phrase['UILabel'] = 'Curve Tool'

	phrase['Curvature'] = 'Curvature'
	phrase['Fixed Handles Tooltip'] = 'Fixed Bezier Handles'

	local fileWord = MOHO.Localize("/Menus/File/File=File")
	if fileWord == "Файл" then
		phrase['Description'] = 'Создавайте точки по клику. Ctrl - сделать острый угол. Alt - не связывать точку с соседней. Backspace - удалить последнюю точку. Enter и Doubleclick - завершить кривую.'
		phrase['UILabel'] = 'Curve Tool'

		phrase['Curvature'] = 'Curvature'
		phrase['Fixed Handles Tooltip'] = 'Fixed Bezier Handles'
	end

	return phrase[text]
end

Icon
MR Curve Tool
Listed

Script type: Tool

Uploaded: Jun 19 2022, 08:59

This tool allows you to create points in Moho by just clicking the left mouse button instead of dragging and holding.

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: 203