Mark Sibly 9 лет назад
Родитель
Сommit
dc530d7bec
1 измененных файлов с 390 добавлено и 0 удалено
  1. 390 0
      bananas/vpaint/vpaint.monkey2

+ 390 - 0
bananas/vpaint/vpaint.monkey2

@@ -0,0 +1,390 @@
+#Import "<std>"
+#Import "<mojo>"
+
+Using std..
+Using mojo..
+
+Global title:String="VPaint 0.1 Easter-Show-Spew Release"	
+Global AboutApp:="VPaint Control,Mouse Button=Lift Pen,Mouse Wheel=Zoom,Space Key=Clear,S Key=Smile Box,C Key=Hold,Cursor Left=-RPM,Cursor Right=+RPM,Cursor Up=+Pen Radius,Cursor Down=+Pen Radius,Hold,F1=Toggle Fullscreen,Click To Start"
+Global ContactApp:=",,Latest Source: github.com/nitrologic/m2"
+
+Global instance:AppInstance
+
+Class VPane Extends Image
+	Field canvas:Canvas
+	Field pixmap:Pixmap
+
+	Method New(w:Int,h:Int,bg:Color)		
+		Super.New(w,h,TextureFlags.Dynamic|TextureFlags.Filter|TextureFlags.Mipmap)		
+		canvas=New Canvas(Self)	
+		canvas.Clear(bg)
+		canvas.Alpha=0.8
+		canvas.Translate(w/2,h/2)
+		Handle=New Vec2f(0.5,0.5)		
+	End
+	
+	Method Draw(display:Canvas)	
+		canvas.Flush()
+		display.DrawImage(Self,0,0)
+	End
+	
+	Method Clear(bg:Color)
+		canvas.Clear(bg)
+	End
+	
+	Field segcount:Int
+	Field edge0:Vec2f
+	Field edge1:Vec2f
+	
+	Method EndSegment()
+		segcount=0
+	End
+
+	Method FatSegment(x:Float,y:Float,x1:Float,y1:Float,fat:Float)
+
+		If Not canvas Return
+				
+		Local verts:=New Float[8]
+		
+		Local dy:Float=y1-y
+		Local dx:Float=x1-x
+				
+		Local len:Float=Sqrt(dx*dx+dy*dy) 
+		Local q:Float=fat/len
+				
+		If segcount=0
+			edge0=New Vec2f(x+dy*q,y-dx*q)
+			edge1=New Vec2f(x-dy*q,y+dx*q)
+		Endif
+		segcount+=1
+				
+		Local v0:=edge0
+		Local v1:=New Vec2f(x1+dy*q,y1-dx*q)
+		Local v2:=New Vec2f(x1-dy*q,y1+dx*q)
+		Local v3:=edge1
+				
+		canvas.DrawTriangle(v0,v1,v2)
+		canvas.DrawTriangle(v0,v2,v3)
+				
+		edge0=v1
+		edge1=v2
+	End
+	
+	Function Curve:Float[](seg:Int,p0:Vec2f,p1:Vec2f,p2:Vec2f,p3:Vec2f)
+		Local verts:=New Float[(seg+1)*2]		
+		For Local i:Int=0 To seg		
+			Local mu:Float=i*1.0/seg			    
+        	Local x:Float=CatmullInterpolate(p0.x,p1.x,p2.x,p3.x,mu)
+	       	Local y:Float=CatmullInterpolate(p0.y,p1.y,p2.y,p3.y,mu)
+          	verts[i*2+0]=x
+        	verts[i*2+1]=y
+		Next		
+		Return verts
+	End
+	
+	Method OpenCurve(p0:Vec2f,p1:Vec2f,p2:Vec2f,p3:Vec2f,fat:Float)
+		If Not canvas Return
+		Local seg:Int=6
+		Local verts:=Curve(seg,p0,p1,p2,p3)
+		For Local i:Int=0 Until seg		
+			FatSegment(verts[i*2+0],verts[i*2+1],verts[i*2+2],verts[i*2+3],fat)
+		Next
+	End
+		
+	Method ClosedCurve(p0:Vec2f,p1:Vec2f,p2:Vec2f,p3:Vec2f,fat:Float)
+		If Not canvas Return
+		OpenCurve(p3,p0,p1,p2,fat)
+		OpenCurve(p0,p1,p2,p3,fat)
+		OpenCurve(p1,p2,p3,p0,fat)
+		OpenCurve(p2,p3,p0,p1,fat)
+		EndSegment()
+	End
+
+ 	Function CubicInterpolate:Float(y0:Float,y1:Float,y2:Float,y3:Float,mu:Float)
+		Local a0:Float,a1:Float,a2:Float,a3:Float,mu2:Float
+		mu2 = mu*mu
+		a0 = y3 - y2 - y0 + y1
+		a1 = y0 - y1 - a0
+		a2 = y2 - y0
+		a3 = y1
+		Return(a0*mu*mu2+a1*mu2+a2*mu+a3)
+	End
+		
+ 	Function CatmullInterpolate:Float(y0:Float,y1:Float,y2:Float,y3:Float,mu:Float)
+		Local a0:Float,a1:Float,a2:Float,a3:Float,mu2:Float	
+		mu2 = mu*mu
+		a0 = -0.5*y0 + 1.5*y1 - 1.5*y2 + 0.5*y3
+		a1 = y0 - 2.5*y1 + 2*y2 - 0.5*y3
+		a2 = -0.5*y0 + 0.5*y2
+		a3 = y1
+		Return(a0*mu*mu2+a1*mu2+a2*mu+a3)
+	End
+ 	 	
+ 	Function CubicInterpolate2:Float(p0:Float,p1:Float,p2:Float,p3:Float,x:Float)
+		Return p1 + 0.5 * x*(p2-p0+x*(2.0*p0-5.0*p1+4.0*p2-p3+x*(3.0*(p1-p2)+p3-p0)))
+	End
+
+	Method FatLine(x:Int,y:Int,x1:Int,y1:Int,fat:Float)
+		If Not canvas Return				
+		Local dy:Int=y1-y
+		Local dx:Int=x1-x				
+		Local len:Float=Sqrt(dx*dx+dy*dy) 
+		Local q:Float=fat/len				
+		Local v0:=New Vec2f(x+dy*q,y-dx*q)
+		Local v1:=New Vec2f(x1+dy*q,y1-dx*q)
+		Local v2:=New Vec2f(x1-dy*q,y1+dx*q)
+		Local v3:=New Vec2f(x-dy*q,y+dx*q)				
+		canvas.DrawTriangle(v0,v1,v2)
+		canvas.DrawTriangle(v0,v2,v3)
+	End
+
+
+	Method Smile(x:Float,y:Float,r:Float)
+		Local v0:=New Vec2f(x-100,y+100)
+		Local v1:=New Vec2f(x-100,y-20)
+		Local v2:=New Vec2f(x+100,y-20)
+		Local v3:=New Vec2f(x+100,y+100)
+		EndSegment()
+		OpenCurve(v0,v1,v2,v3,r)
+		EndSegment()
+	End
+		
+	Method Circle(x:Float,y:Float,r:Float)
+		Local v0:=New Vec2f(x-100,y-100)
+		Local v1:=New Vec2f(x+100,y-100)
+		Local v2:=New Vec2f(x+100,y+100)
+		Local v3:=New Vec2f(x-100,y+100)
+		EndSegment()
+		ClosedCurve(v0,v1,v2,v3,r)
+	End
+
+  
+End
+
+Class VBrowse
+
+End
+
+
+Enum AppState
+	Title
+	Draw
+	Browse
+End
+
+Const TickMark:String=String.FromChar(65)	'(0xE2 0x9C 0x93)
+
+Class VTool Extends Window
+	Method New(title:String)
+		Super.New(title,480,34,WindowFlags.Resizable)		
+	End
+End
+
+Class VPaint Extends Window
+	Field appState:AppState
+
+'	Field tool:VTool
+	Field pane:VPane
+	Field browse:VBrowse
+	
+	Field zoom:Float
+	Field ink:Color
+	Field mousex:Int
+	Field mousey:Int
+	Field mousew:Int
+	Field framecount:Int
+	Field drawcount:Int
+	Field mousecount:Int
+	Field cx:Float
+	Field cy:Float
+	Field rot:Float
+	Field rotSpeed:Float
+	Field radius:Float
+	
+	Method ToggleTwo()	
+	End
+	
+	Method New(title:String)
+		Super.New(title,720,560,WindowFlags.Resizable)		
+		zoom=2
+'		pane=New VPane(2048,2048,Color.Black)
+		pane=New VPane(4096,4096,Color.Black)
+		browse=New VBrowse()
+		ink=New Color
+		radius=1.0
+'		tool=New VTool("Tools")
+'		tool.Title="VPaint Pen : RGBCycle"
+	End
+	
+	Method RefreshTitle()	
+		Local r:=rotSpeed*rotSpeed*rotSpeed
+		Local rpm:Int=Abs(60*60*r/(Pi*2))
+		Title="RPM "+rpm+" R="+Int(radius*100)
+	End
+	
+	Method OnRender( display:Canvas ) Override	
+		App.RequestRender()						
+
+		Select appState
+
+			Case AppState.Title
+				Local cy:=40
+				For Local line:=Eachin (AboutApp+","+ContactApp).Split(",")
+					Local cx:=50
+					For Local tab:=Eachin line.Split("=")
+						display.DrawText(tab,cx,cy)
+						cx+=120
+					Next
+					cy+=20
+				Next
+
+			Case AppState.Draw
+				cx=Width/2
+				cy=Height/2
+				display.Translate(cx,cy)
+				Local scale:=-1.0/zoom
+				display.Scale(scale,scale)
+				display.Rotate(rot)		
+				rot+=rotSpeed*rotSpeed*rotSpeed	
+				OnMouseEvent(recentMouseEvent)		
+				pane.Draw(display)		
+				framecount+=1	
+				
+				ink.r=(framecount&255)/255.0
+				ink.g=(framecount&1023)/1023.0
+				ink.b=(framecount&511)/511.0
+				pane.canvas.Color=ink
+
+			Case AppState.Browse
+		End
+
+	End
+
+	Method OnKeyEvent( event:KeyEvent ) Override	
+		Select event.Type
+		Case EventType.KeyDown
+			Select event.Key
+			Case Key.S
+				pane.Smile(mousex,mousey,radius)
+				pane.Circle(mousex,mousey,radius)
+			Case Key.C
+				pane.Clear(ink )
+			Case Key.Escape
+				instance.Terminate()
+			Case Key.F1
+				Fullscreen = Not Fullscreen
+			Case Key.F2
+				ToggleTwo()	
+			Case Key.Space
+				rotSpeed=0
+			Case Key.Left
+				rotSpeed+=0.1			
+			Case Key.Right
+				rotSpeed-=0.1
+			Case Key.Down
+				radius*=0.8			
+			Case Key.Up
+				radius*=1.2			
+			End
+		End
+		RefreshTitle()		
+	End
+	
+	Field linetool:Bool=False
+	Field history:=New Vec2f[4]
+
+	Field recentMouseEvent:MouseEvent
+	
+	Method DrawMode()
+		appState=AppState.Draw
+	End
+							
+	Method OnMouseEvent(event:MouseEvent ) Override
+	
+		If appState=AppState.Title
+			If event.Type=EventType.MouseDown
+				DrawMode()
+			Endif
+			Return
+		Endif
+
+	
+		If event=Null Return
+		
+		Local mx:Int=event.Location.X
+		Local my:Int=event.Location.Y
+		Local b:Int=event.Button
+				
+		mx=(mx-cx)*zoom
+		my=(my-cy)*zoom
+
+		Local x:=-Cos(rot)*mx+Sin(rot)*my
+		Local y:=-Sin(rot)*mx-Cos(rot)*my
+						
+		Local w:Int
+		
+		If recentMouseEvent<>event w=event.Wheel.Y
+		
+		If mousex=x And mousey=y And mousew=w Return
+		
+		recentMouseEvent = event
+		
+		Select event.Type
+		
+		Case EventType.MouseWheel
+			zoom-=w/8.0
+			If zoom<1.0/8 zoom=1.0/8
+				
+		Case EventType.MouseDown
+			pane.EndSegment()
+			
+		Case EventType.MouseMove
+			history[0]=history[1]
+			history[1]=history[2]
+			history[2]=history[3]
+			history[3]=New Vec2f(x,y)
+		End
+		
+If linetool
+		If drawcount	
+			pane.FatLine(mousex,mousey,x,y,radius)		
+		Endif
+Else
+		If drawcount>2 And Not b
+'			pane.FatCurve(mx[0],my[0],mx[1],my[1],mx[2],my[2],mx[3],my[3])				
+			pane.OpenCurve(history[0],history[1],history[2],history[3],radius)				
+		Endif
+Endif
+		drawcount+=1
+
+		mousex=x
+		mousey=y
+		mousew=w
+		
+		mousecount+=1
+	End	
+End
+
+Function Main()
+	Print title
+	instance = New AppInstance	
+	New VPaint(title)
+	App.Run()	
+End
+
+Function SaveTGA(path:String, pixmap:Pixmap)
+	Local stream:=FileStream.Open(path,"w")
+	Local buffer:=New Byte[18]		
+	Local w:=pixmap.Width
+	Local h:=pixmap.Height	
+	buffer[2]=2
+	buffer[12]=w & 255
+	buffer[13]=w Shr 8
+	buffer[14]=h & 255
+	buffer[15]=h Shr 8
+	buffer[16]=32
+	buffer[17]=8
+	stream.Write(Varptr buffer[0],18)	
+	stream.Write(pixmap.Data,w*h*4)
+	stream.Close()
+End Function