From 6e5148e255a86409feaa446270aa29d27aa9849c Mon Sep 17 00:00:00 2001 From: Ian C Date: Thu, 13 Oct 2005 23:24:27 +0000 Subject: 2D Vector Graphics designer --- .cvsignore | 3 + default.vec2d | Bin 0 -> 620 bytes font.bmf | Bin 0 -> 21036 bytes pointer.png | Bin 0 -> 237 bytes vec2ddes.bmx | 657 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 660 insertions(+) create mode 100644 .cvsignore create mode 100644 default.vec2d create mode 100644 font.bmf create mode 100644 pointer.png create mode 100644 vec2ddes.bmx diff --git a/.cvsignore b/.cvsignore new file mode 100644 index 0000000..8cd2c4c --- /dev/null +++ b/.cvsignore @@ -0,0 +1,3 @@ +vec2ddes.debug.exe +vec2ddes.exe +.bmx diff --git a/default.vec2d b/default.vec2d new file mode 100644 index 0000000..175a5d0 Binary files /dev/null and b/default.vec2d differ diff --git a/font.bmf b/font.bmf new file mode 100644 index 0000000..364f158 Binary files /dev/null and b/font.bmf differ diff --git a/pointer.png b/pointer.png new file mode 100644 index 0000000..bb9f0ef Binary files /dev/null and b/pointer.png differ diff --git a/vec2ddes.bmx b/vec2ddes.bmx new file mode 100644 index 0000000..5bc65bd --- /dev/null +++ b/vec2ddes.bmx @@ -0,0 +1,657 @@ +' 2D Vewctor Object desinger. +' Looks a bit odd as ripped from another in-game designer. +' +' Copyright 2005 Ian Cowburn +' +' $Id$ +' +Strict + +Import noddybox.vectorgfx +Import noddybox.bitmapfont +Import noddybox.simplegui + +' Included binaries +' +Incbin "font.bmf" +Incbin "pointer.png" + + +' Initialise +' +SeedRnd(MilliSecs()) + +SetGraphicsDriver GLMax2DDriver() +Graphics 800,600,32,60 +HideMouse + +SetBlend(ALPHABLEND) +SetAlpha(1.0) + +' Globals +' +Global font:TBitmapFont=TBitmapFont.Load("incbin::font.bmf",0) +Global pointer:TImage=LoadImage("incbin::pointer.png",0) +TGUIFont.font=font + +Global quit:Int=False +Global filename:String="Default.vec2d" +Global scale:Double=1.0 + +' **** Main +' +DoDesigner() +EndGraphics +End + + +' **** Types +' +Type TDesObj Abstract + Field selsize:Int + + Function LoadFromObject:TDesObj(o:Object) Abstract + Method CreateForObject:Object() Abstract + Method Draw(normals:Int) Abstract + Method DrawSelect() Abstract + Method MouseOver:Int(x:Int, y:Int) Abstract + Method Drag(x:Int, y:Int) Abstract + Method Edit() Abstract + Method SetInfo(w:TLabel) Abstract + Method Snap() Abstract + + Method DrawSelBox(x:Double, y:Double) + Local x1:Int=x*scale-selsize + Local y1:Int=y*scale-selsize + Local x2:Int=x*scale+selsize + Local y2:Int=y*scale+selsize + + SetColor(255,255,255) + DrawLine(x1,y1,x2,y1) + DrawLine(x2,y1,x2,y2) + DrawLine(x2,y2,x1,y2) + DrawLine(x1,y2,x1,y1) + End Method + + Method InSelBox(px:Double, py:Double, x:Double, y:Double) + Local x1:Int=x*scale-selsize + Local y1:Int=y*scale-selsize + Local x2:Int=x*scale+selsize + Local y2:Int=y*scale+selsize + + Return px>=x1 And px<=x2 And py>=y1 And py<=y2 + End Method + + Method DrawCoord(x:Int, y:Int) + font.Draw(x+","+y,0,0) + End Method + + Method DoubleString:String(v:Double) + Local s:String=v + + If s.Find(".")<>-1 + While s.length>1 And s[s.length-1]=Asc("0") + s=s[..s.length-1] + Wend + + While s.length>1 And s[s.length-1]=Asc(".") + s=s[..s.length-1] + Wend + EndIf + + Return s + End Method + + Method BoolString:String(b:Int) + If b + Return "Yes" + Else + Return "No " + EndIf + End Method + + Method CalcSnap:Int(p:Int) + Return (p+(Designer.GRID/2*Sgn(p)))/Designer.GRID*Designer.GRID + End Method +End Type + +Type TDesLine Extends TDesObj + Field p1:TDesPoint + Field p2:TDesPoint + Field r:Int + Field g:Int + Field b:Int + Field id:Int + + Function Create:TDesLine(p1:TDesPoint,p2:TDesPoint) + Local o:TDesLine=New TDesLine + + o.p1=p1 + o.p2=p2 + o.r=255 + o.g=255 + o.b=255 + o.selsize=3 + + Return o + End Function + + Function LoadFromObject:TDesObj(o:Object) + Local lp:TVectorGfxLine=TVectorGfxLine(o) + Local no:TDesLine=New TDesLine + + no.p1=FindPoint(lp.i1) + no.p2=FindPoint(lp.i2) + no.r=lp.r + no.g=lp.g + no.b=lp.b + no.id=lp.id + no.selsize=3 + + Return no + End Function + + Method CreateForObject:Object() + Return TVectorGfxLine.Create(FindPointIndex(p1),FindPointIndex(p2),r,g,b,id) + End Method + + Method CX:Double() + Return p1.x+(p2.x-p1.x)/2.0 + End Method + + Method CY:Double() + Return p1.y+(p2.y-p1.y)/2.0 + End Method + + Method Draw(normals:Int) + If normals + Local v:TVector=TVector.Create(p2.y-p1.y,p1.x-p2.x) + v.Normalise() + SetColor(r/2,g/2,b/2) + DrawLine(CX()*scale,CY()*scale,CX()*scale+v.x*10,CY()*scale+v.y*10) + EndIf + + SetColor(r,g,b) + DrawLine(p1.x*scale,p1.y*scale,p2.x*scale,p2.y*scale) + End Method + + Method DrawSelect() + DrawSelBox(CX(),CY()) + End Method + + Method MouseOver:Int(x:Int, y:Int) + Return InSelBox(x,y,CX(),CY()) + End Method + + Method Drag(x:Int, y:Int) + x:-CX() + y:-CY() + + p1.x:+x + p2.x:+x + p1.y:+y + p2.y:+y + + DrawCoord(x,y) + End Method + + Method Edit() + Designer.ld_red.text = r + Designer.ld_green.text = g + Designer.ld_blue.text = b + Designer.ld_id.text = id + + If GUIDialog(Designer.ldialog,Designer.ld_ok,Designer.ld_cancel,pointer) + r = Min(255,Designer.ld_red.text.ToInt()) + g = Min(255,Designer.ld_green.text.ToInt()) + b = Min(255,Designer.ld_blue.text.ToInt()) + id = Designer.ld_id.text.ToInt() + EndIf + End Method + + Method SetInfo(w:TLabel) + w.text=p1.x+","+p1.y+" -> "+p2.x+","+p2.y+" ID:"+id + EndMethod + + Method Snap() + p1.x=CalcSnap(p1.x) + p1.y=CalcSnap(p1.y) + p2.x=CalcSnap(p2.x) + p2.y=CalcSnap(p2.y) + End Method + + Method FlipNormal() + Local t:TDesPoint=p1 + p1=p2 + p2=t + End Method +End Type + +Type TDesPoint Extends TDesObj + Field x:Int + Field y:Int + + Function Create:TDesObj(x:Int, y:Int) + Local o:TDesPoint=New TDesPoint + + o.x=x + o.y=y + + o.selsize=3 + + Return o + End Function + + Function LoadFromObject:TDesObj(o:Object) + Local lp:TVectorGfxPoint=TVectorGfxPoint(o) + Local no:TDesPoint=New TDesPoint + + no.x=lp.x + no.y=lp.y + no.selsize=3 + + Return no + End Function + + Method CreateForObject:Object() + Return TVectorGfxPoint.Create(x,y) + End Method + + Method Draw(normals:Int) + SetColor(255,255,255) + DrawRect(x*scale-1,y*scale-1,3,3) + End Method + + Method DrawSelect() + DrawSelBox(x,y) + End Method + + Method MouseOver:Int(x:Int, y:Int) + Return InSelBox(x,y,self.x,self.y) + End Method + + Method Drag(x:Int, y:Int) + self.x=x + self.y=y + DrawCoord(x,y) + End Method + + Method Edit() + End Method + + Method SetInfo(w:TLabel) + w.text=x+","+y + EndMethod + + Method Snap() + x=CalcSnap(x) + y=CalcSnap(y) + End Method +End Type + +' **** Globals +' +' This type acts as a namespace for global variables +' +Type Designer + Global GRID:Int=5 + + Global init:Int=False + + Global obj:TList + + Global gfx:TVectorGfxObject + Global done:Int + + Global gui:TGUIHandler + + Global fname_txt:TText + Global fname_load:TButton + Global fname_save:TButton + Global fname_new:TButton + + Global scale_number:TNumberInt + Global grid_number:TNumberInt + Global info:TLabel + + Global grid_check:TCheckbox + Global normal_check:TCheckbox + + Global quitbut:TButton + + Global ldialog:TGUIHandler + Global ld_red:TText + Global ld_green:TText + Global ld_blue:TText + Global ld_id:TText + Global ld_ok:TButton + Global ld_cancel:TButton + + Function Initialise() + If Not init + Local l:TLabel + Local p:TPanel + + obj = CreateList() + gfx = New TVectorGfxObject + gui = TGUIHandler.Create() + + TLabel.Create(gui,0,0,"File") + fname_txt = TText.Create(gui,70,0,"default.vec2d",32) + fname_load = TButton.Create(gui,fname_txt.x+fname_txt.w+10,0,50,15,"Load",LoadCallback) + fname_save = TButton.Create(gui,fname_load.x+fname_load.w+10,0,50,fname_load.h,"Save",SaveCallback) + fname_new = TButton.Create(gui,fname_save.x+fname_save.w+10,0,50,fname_load.h,"New",NewCallback) + + TLabel.Create(gui,0,15,"Scale") + scale_number = TNumberInt.Create(gui,70,15,ScaleCallback) + scale_number.value=scale + scale_number.minval=1 + scale_number.maxval=10 + scale_number.change=1 + + TLabel.Create(gui,0,30,"Grid size") + grid_number = TNumberInt.Create(gui,70,30,GridSizeCallback) + grid_number.value=GRID + grid_number.minval=2 + grid_number.maxval=10 + grid_number.change=1 + + info = TLabel.Create(gui,0,45,"") + + grid_check = TCheckbox.Create(gui,740,0,"Grid") + normal_check = TCheckbox.Create(gui,740,15,"Normals") + grid_check.checked= True + + quitbut = TButton.Create(gui,750,570,49,29,"Quit",QuitCallback) + + ldialog = TGUIHandler.Create() + p = TPanel.Create(ldialog,-1,-1,400,150) + l = TLabel.Create(ldialog,p.x+5,p.y+10,"Red:") + ld_red = TText.Create(ldialog,l.x+l.w+10,l.y,"",3,TText.NUMERIC|TText.INTEGER|TText.POSITIVE) + l = TLabel.Create(ldialog,p.x+5,p.y+30,"Green:") + ld_green = TText.Create(ldialog,l.x+l.w+10,l.y,"",3,TText.NUMERIC|TText.INTEGER|TText.POSITIVE) + l = TLabel.Create(ldialog,p.x+5,p.y+50,"Blue:") + ld_blue = TText.Create(ldialog,l.x+l.w+10,l.y,"",3,TText.NUMERIC|TText.INTEGER|TText.POSITIVE) + l = TLabel.Create(ldialog,p.x+5,p.y+70,"Collision ID:") + ld_id = TText.Create(ldialog,l.x+l.w+10,l.y,"",30,TText.NUMERIC|TText.INTEGER|TText.POSITIVE) + ld_ok = TButton.Create(ldialog,p.x+5,p.y+p.h-25,p.w/2-10,20,"OK",Null) + ld_cancel = TButton.Create(ldialog,p.x+p.w/2+5,p.y+p.h-25,p.w/2-10,20,"Cancel",Null) + + init=True + EndIf + + done = False + LoadObject() + End Function + + Function SaveObject() + Local lines:TList=CreateList() + Local points:TList=CreateList() + + For Local d:TDesObj=EachIn obj + If IsPoint(d) + points.AddLast(d.CreateForObject()) + Else + lines.AddLast(d.CreateForObject()) + EndIf + Next + + gfx.SetPoints(points.ToArray()) + gfx.SetLines(lines.ToArray()) + gfx.Save(Designer.fname_txt.text) + End Function + + Function LoadObject() + obj.Clear() + For Local p:TVectorGfxPoint=EachIn gfx.points + obj.AddLast(TDesPoint.LoadFromObject(p)) + Next + For Local l:TVectorGfxLine=EachIn gfx.lines + obj.AddLast(TDesLine.LoadFromObject(l)) + Next + End Function +End Type + + +' **** Main Loop +' +Function DoDesigner() + Designer.Initialise() + + Designer.done=False + + Local sel:TDesObj=Null + Local drag:Int=False + Local sel1:TDesObj=Null + Local make_line:Int=False + + While Not Designer.done + Cls + + ' **** START CENTRED + ' + SetOrigin(GraphicsWidth()/2,GraphicsHeight()/2) + + If Designer.grid_check.checked + SetAlpha(0.7) + Local x:Int=0 + While x>-400 + x:-Designer.GRID + Wend + While x<=400 + If x=0 + SetColor(50,50,255) + Else + SetColor(50,50,128) + EndIf + DrawLine(x*scale,-300,x*scale,300) + x:+Designer.GRID + Wend + Local y:Int=0 + While y>-300 + y:-Designer.GRID + Wend + While y<=300 + If y=0 + SetColor(50,50,255) + Else + SetColor(50,50,128) + EndIf + DrawLine(-400,y*scale,400,y*scale) + y:+Designer.GRID + Wend + SetAlpha(1) + EndIf + + Local x:Int=(MouseX()-GraphicsWidth()/2) + Local y:Int=(MouseY()-GraphicsHeight()/2) + + If Not drag + sel=Null + EndIf + + For Local o:TDesObj=EachIn Designer.obj + o.Draw(Designer.normal_check.checked) + + If sel=Null And o.MouseOver(x,y) + sel=o + EndIf + Next + + If sel<>Null + sel.SetInfo(Designer.info) + sel.DrawSelect() + + If make_line And IsPoint(sel) + If sel1=Null + sel1=sel + Else + If sel1<>sel + make_line=False + Designer.obj.AddLast(TDesLine.Create(TDesPoint(sel1),TDesPoint(sel))) + EndIf + EndIf + EndIf + EndIf + + If drag + sel.Drag(x/scale,y/scale) + EndIf + + SetOrigin(0,0) + ' + ' **** END CENTRED + + If Not drag + Designer.gui.EventLoop() + EndIf + + If KeyHit(KEY_MOUSERIGHT) + make_line=False + + If sel<>Null + If IsPoint(sel) + Select GUIMenu("Point Menu",["Snap to grid","Delete"],MouseX(),MouseY(),pointer) + Case 0 + sel.Snap() + Case 1 + Designer.obj.Remove(sel) + + For Local d:TDesLine=EachIn Designer.obj + If d<>Null And (d.p1=sel Or d.p2=sel) + Designer.obj.Remove(d) + EndIf + Next + End Select + Else + Local l:TDesLine=TDesLine(sel) + Select GUIMenu("Line Menu",["Edit","Snap to grid","Flip","Delete"],MouseX(),MouseY(),pointer) + Case 0 + l.Edit() + Case 1 + l.Snap() + Case 2 + l.FlipNormal() + Case 3 + Designer.obj.Remove(l) + End Select + EndIf + Else + Select GUIMenu("Create Menu",["Create Point","Create Line"],MouseX(),MouseY(),pointer) + Case 0 + Designer.obj.AddLast(TDesPoint.Create(x/scale,y/scale)) + Case 1 + sel1=Null + sel=Null + make_line=True + End Select + EndIf + sel=Null + EndIf + + If Not drag + If KeyDown(KEY_MOUSELEFT) And sel<>Null + make_line=False + drag=True + EndIf + Else + If Not KeyDown(KEY_MOUSELEFT) + drag=False + EndIf + EndIf + + SetColor(255,255,255) + + If make_line + If Not sel1 + font.Draw("Move to first point",MouseX()+12,MouseY()+12) + Else + font.Draw("Move to second point",MouseX()+12,MouseY()+12) + EndIf + EndIf + + DrawImage(pointer,MouseX(),MouseY()) + + Flip + FlushMem + Wend +End Function + +Function IsLine:Int(o:Object) + Local p:TDesLine=TDesLine(o) + Return p<>Null +End Function + +Function IsPoint:Int(o:Object) + Local p:TDesPoint=TDesPoint(o) + Return p<>Null +End Function + +Function FindPoint:TDesPoint(i:Int) + For Local o:Object=EachIn Designer.obj + If IsPoint(o) + If i=0 + Return TDesPoint(o) + EndIf + i:-1 + EndIf + Next + Return Null +End Function + +Function FindPointIndex:Int(p:TDesPoint) + Local i:Int=0 + + For Local o:Object=EachIn Designer.obj + If IsPoint(o) + If o=p + Return i + EndIf + i:+1 + EndIf + Next + + Return 0 +End Function + + +' **** Callbacks +' +Function QuitCallback(w:TWidget) + Designer.done=GUIYesNo("Quit?",pointer) +End Function + +Function LoadCallback(w:TWidget) + Local o:TVectorGfxObject=TVectorGfxObject.Load(Designer.fname_txt.text) + + If o<>Null + Designer.gfx=o + Designer.gfx.x=0 + Designer.gfx.y=0 + Designer.gfx.ang=0 + Designer.LoadObject() + Else + GUINotify("Failed to load '" + Designer.fname_txt.text + "'",pointer) + EndIf +End Function + +Function SaveCallback(w:TWidget) + Designer.SaveObject() +End Function + +Function NewCallback(w:TWidget) + If GUIYesNo("Lose current object?",pointer) + Designer.gfx=New TVectorGfxObject + Designer.LoadObject() + EndIf +End Function + +Function ScaleCallback(w:TWidget) + Local c:TNumberInt=TNumberInt(w) + scale=c.value +End Function + +Function GridSizeCallback(w:TWidget) + Local c:TNumberInt=TNumberInt(w) + Designer.GRID=c.value +End Function -- cgit v1.2.3