' Particle Pinch ' ' Copyright 2005 Ian Cowburn ' ' $Id$ ' Strict Import noddybox.vector Import noddybox.bitmapfont Import noddybox.simplegui Import noddybox.algorithm Import "types.bmx" Import "level.bmx" Import "game.bmx" Function LevelDesigner() DoDesigner() End Function Private ' **** Types ' Type TDesObj Abstract Const SELSIZE:Int=3 Function Create:TDesObj(x:Int, y:Int) Abstract Function CreateFromLevel:TDesObj(o:Object) Abstract Method Draw() Abstract Method DrawSelect() Abstract Method MouseOver:Int(x:Int, y:Int) Abstract Method Drag(x:Int, y:Int) Abstract Method Edit() Abstract Method Save(lev:TLevel) Abstract Method DrawSelBox(x:Int, y:Int) Local x1:Int=x-SELSIZE Local y1:Int=y-SELSIZE Local x2:Int=x+SELSIZE Local y2:Int=y+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:Int, py:Int, x:Int, y:Int) Local x1:Int=x-SELSIZE Local y1:Int=y-SELSIZE Local x2:Int=x+SELSIZE Local y2:Int=y+SELSIZE Return px>=x1 And px<=x2 And py>=y1 And py<=y2 End Method Method DrawCoord(x:Int, y:Int) GameGFX.guifont.Draw(x+","+y,0,0) End Method End Type Type TDesGrav Extends TDesObj Field g:TGravPoint Function Create:TDesObj(x:Int, y:Int) Local o:TDesGrav=New TDesGrav o.g=New TGravPoint o.g.x=x o.g.y=y o.g.friendly=False o.g.mass=25 o.g.repel=False Return o End Function Function CreateFromLevel:TDesObj(o:Object) Local lp:TGravPoint=TGravPoint(o) Local no:TDesGrav=New TDesGrav no.g=New TGravPoint no.g.x=lp.x no.g.y=lp.y no.g.friendly=lp.friendly no.g.mass=lp.mass no.g.repel=lp.repel Return no End Function Method Draw() SetColor(255,255,255) If g.friendly DrawImage(GameGFX.collector,g.x,g.y) Else DrawImage(GameGFX.star,g.x,g.y) EndIf End Method Method DrawSelect() DrawSelBox(g.x,g.y) End Method Method MouseOver:Int(x:Int, y:Int) Return InSelBox(x,y,g.x,g.y) End Method Method Drag(x:Int, y:Int) DrawCoord(x,y) g.x=x g.y=y End Method Method Edit() Designer.md_friendly.checked = g.friendly Designer.md_invert.checked = g.repel Designer.md_mass.text = g.mass If GUIDialog(Designer.mdialog,Designer.md_ok,Designer.md_cancel,GameGFX.pointer) g.friendly = Designer.md_friendly.checked g.repel = Designer.md_invert.checked g.mass = Designer.md_mass.text.ToFloat() EndIf End Method Method Save(lev:TLevel) lev.grav.AddLast(g) End Method End Type Type TDesPoint Extends TDesObj Field l:TPointLine Field over_p1:Int Function Create:TDesObj(x:Int, y:Int) Local o:TDesPoint=New TDesPoint o.over_p1=False o.l=New TPointLine o.l.x1=x o.l.y1=y o.l.y2=y If xNull sel.DrawSelect() EndIf If drag sel.Drag(x,y) EndIf If KeyHit(KEY_MOUSERIGHT) If sel<>Null Select GUIMenu("Object Menu",["Edit","Delete"],x,y,GameGFX.pointer) Case 0 sel.Edit() Case 1 Designer.obj.Remove(sel) End Select Else Select GUIMenu("Create Menu",["Create Gravity Point","Create Particle Line","Edit Level Settings"],x,y,GameGFX.pointer) Case 0 Designer.obj.AddLast(TDesGrav.Create(x,y)) Case 1 Designer.obj.AddLast(TDesPoint.Create(x,y)) Case 2 Designer.EditLevelSettings() End Select EndIf sel=Null EndIf If Not drag If KeyDown(KEY_MOUSELEFT) And sel<>Null drag=True EndIf Else If Not KeyDown(KEY_MOUSELEFT) drag=False EndIf EndIf SetColor(255,255,255) DrawImage(GameGFX.pointer,MouseX(),MouseY()) Flip FlushMem Wend End Function ' **** Utils ' Function ListAt:TLink(l:TList, i:Int) Local tl:TLink=l.FirstLink() While i>0 And tl<>Null i:-1 tl=tl.NextLink() Wend Return tl End Function ' **** Callbacks ' Function HideCallback(w:TWidget) Local c:TCheckbox=TCheckbox(w) Designer.gui.SetEnable(Not c.checked) c.enabled=True End Function Function QuitCallback(w:TWidget) Designer.done=GUIYesNo("Quit back to the|main menu of Particle Pinch?",GameGFX.pointer) End Function Function TestCallback(w:TWidget) Designer.SaveLevel() Local g:TGame=TGame.Create(Designer.level) While Not KeyHit(KEY_ESCAPE) Cls g.Play() SetColor(255,255,255) DrawImage(GameGFX.pointer,MouseX(),MouseY()) FlushMem Flip Wend FlushKeys() End Function Function CheckCallback(w:TWidget) End Function Function LoadCallback(w:TWidget) Try If GUIYesNo("Overwrite current level set?",GameGFX.pointer) Local load:TLevelSet=TLevelSet.Load(Designer.fname_txt.text) Designer.levelset=load Designer.levelindex=0 Designer.levnum.maxval=Designer.levelset.level.Count()-1 Designer.LoadLevel() EndIf Catch e:TLevelException GUINotify("Failed to load '" + Designer.fname_txt.text + "'||"+e.message,GameGFX.pointer) EndTry End Function Function SaveCallback(w:TWidget) Designer.SaveLevel() If Not Designer.levelset.Save(Designer.fname_txt.text) GUINotify("Failed to save '" + Designer.fname_txt.text + "'",GameGFX.pointer) Else GUINotify("'" + Designer.fname_txt.text + "' saved OK",GameGFX.pointer) EndIf End Function Function NewCallback(w:TWidget) If GUIYesNo("Lose current level set?",GameGFX.pointer) Designer.levelindex=0 Designer.levnum.maxval=0 Designer.levelset=New TLevelSet Designer.levelset.level.AddLast(New TLevel) Designer.fname_txt.text="Untitled.ppinch" Designer.LoadLevel() EndIf End Function Function LevelNumberCallback(w:TWidget) Local c:TNumberInt=TNumberInt(w) Designer.SaveLevel() Designer.levelindex=c.value Designer.LoadLevel() End Function Function AddLevelCallback(w:TWidget) Designer.levelset.level.AddLast(New TLevel) Designer.levnum.maxval=Designer.levelset.level.Count()-1 End Function Function InsertLevelCallback(w:TWidget) Designer.SaveLevel() Local l:TLink=ListAt(Designer.levelset.level,Designer.levelindex) Designer.levelset.level.InsertBeforeLink(New TLevel,l) Designer.levnum.maxval=Designer.levelset.level.Count()-1 Designer.LoadLevel() End Function Function DeleteLevelCallback(w:TWidget) If Designer.levelset.level.Count()<2 GUINotify("Must have at least one level!",GameGFX.pointer) Return EndIf If GUIYesNo("Delete this level?||"+Designer.levname_txt.text,GameGFX.pointer) ListAt(Designer.levelset.level,Designer.levelindex).Remove() If Designer.levelindex>=Designer.levelset.level.Count() Designer.levelindex:-1 Designer.levnum.value=Designer.levelindex EndIf Designer.levnum.maxval=Designer.levelset.level.Count()-1 Designer.LoadLevel() EndIf End Function