Seite 1 von 1

XML PolygonEditor für pb 4.60

Verfasst: 18.09.2011 22:50
von mpz
Hi Leute,

hier kommt ein einfacher Polygoneditor um Umrisse von Grafiken zu erzeugen. Ich benötige Ihn um 2d Physik Objekte aus Grafiken erstellen zu können. Die Vorlage kam von STARGÅTE und ich habe für meien Zwecke erweitert. Zukünftig soll noch eine automatische Polygonerkennung eingebaut werden, aber die derzeitige Löung ist schon funktionell.

Gruß Michael

Code: Alles auswählen

;////////////////////////////////////////////////////////////////
;//
;// Project Title: MP 2D PolygonEditor 
;// Dateiname: MP_2D_PolygonEditor.pb
;// Erstellt am: 18.09.2011
;// Update am  : 
;// Author: STARGÅTE, Erweiterungen Michael Paulwitz
;// PB Version ab 4.60
;// 
;// Info: 
;// Create a XML Polygon from a grafic file
;// Erzeugt ein XML Polygon von einer Grafikdatei
;//
;// CodeExample from STARGÅTE, many thanks to him
;//
;////////////////////////////////////////////////////////////////

;- ProgrammStart

Enumeration
   #Window
   #Menu
   #Image
   #CanvasGadget
   #MenuItem_LoadImage
   #MenuItem_SavePolygon
   #MenuItem_LoadPolygon
   #MenuItem_FreePolygon
   #MenuItem_Kreis
   #MenuItem_Viereck
   #MenuItem_Polygon
   #MenuItem_Help
   #XML
EndEnumeration

Structure Integer2D
   X.i
   Y.i
EndStructure

Procedure.s GetNamePart(FullPathName.s)
   If GetExtensionPart(FullPathName)
      ProcedureReturn Left(GetFilePart(FullPathName), Len(GetFilePart(FullPathName))-Len(GetExtensionPart(FullPathName))-1)
   Else
      ProcedureReturn GetFilePart(FullPathName)
   EndIf
EndProcedure

UsePNGImageDecoder()
UseJPEGImageDecoder()

OpenWindow(#Window, 0, 0, 400, 300, "PolygonCreator", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
   
   CreateMenu(#Menu, WindowID(#Window))
      MenuTitle("Datei")
         MenuItem(#MenuItem_LoadImage, "Bild laden...")
         MenuBar()
         MenuItem(#MenuItem_LoadPolygon, "Polygon laden...")
         MenuItem(#MenuItem_SavePolygon, "Polygon speichern...")
      MenuTitle("Art")
         MenuItem(#MenuItem_FreePolygon, "Polygon löschen")
         MenuBar()
         MenuItem(#MenuItem_Polygon, "Polygon")
         SetMenuItemState(#Menu,#MenuItem_Polygon,1)
         MenuItem(#MenuItem_Kreis,   "Kreis")
         MenuItem(#MenuItem_Viereck, "Viereck")
      MenuTitle("Help")
         MenuItem(#MenuItem_Help,   "Help")
      
   CanvasGadget(#CanvasGadget, 0, 0, 0, 0)
   SetGadgetAttribute(#CanvasGadget, #PB_Canvas_Cursor, #PB_Cursor_Cross)

Global NewList Corner.Integer2D()
Global *SelectedCorner.Integer2D
Global EditModus = 1

Procedure UpdateCanvasGadget()
   Protected *PreviousCorner.Integer2D
   If StartDrawing(CanvasOutput(#CanvasGadget))
      Box(0, 0, OutputWidth(), OutputHeight(), $FFFFFF)
      If IsImage(#Image)
         DrawAlphaImage(ImageID(#Image), 0, 0, 128)
      EndIf
      If LastElement(Corner())
         *PreviousCorner.Integer2D = @Corner()
      EndIf
      If EditModus = 2
         If ListSize (Corner()) = 2
           SelectElement(Corner(), 0)
           X1 = Corner()\X
           Y1 = Corner()\y
           SelectElement(Corner(), 1)
           X2 = Corner()\X
           Y2 = Corner()\y 
           sx = x2-x1
           sy = y2-y1
           Radius = Sqr(sx*sx + sy*sy) -1
           For a.l = 0 To 2 * #PI * Radius ;Step 2 
             x.f = Cos(a / Radius) * Radius + X1
             y.f = Sin(a / Radius) * Radius + Y1
             If x > 0 And x < ImageWidth(#Image) -1
               If y > 0 And y < ImageHeight(#Image) -1
                  Plot(x,  y,RGB(255,0,0)) 
               EndIf   
             EndIf  
           Next 
        EndIf
      EndIf
      ForEach Corner()
         LineXY(*PreviousCorner\X, *PreviousCorner\Y, Corner()\X, Corner()\Y, $000000)
         Circle(Corner()\X, Corner()\Y, 4, $0000FF)
         *PreviousCorner = @Corner()
      Next
      If *SelectedCorner
         Circle(*SelectedCorner\X, *SelectedCorner\Y, 4, $00FF00)
      EndIf

      StopDrawing()
   EndIf
EndProcedure

Define ImageFileName.s, XMLFileName.s
Define Mouse.Integer2D
Define MoveCorner.i
Define *MainNode, *Node

Repeat
   
   Select WaitWindowEvent()
         
      Case #PB_Event_CloseWindow
         End
      
      Case #PB_Event_Gadget
         Select EventGadget()
            Case #CanvasGadget
               Mouse\X = GetGadgetAttribute(#CanvasGadget, #PB_Canvas_MouseX)
               Mouse\Y = GetGadgetAttribute(#CanvasGadget, #PB_Canvas_MouseY)
               Select EventType()
                  Case #PB_EventType_LeftButtonDown
                   If EditModus = 1 
                     Repeat
                        ForEach Corner()
                           If Pow(Corner()\X-Mouse\X,2)+Pow(Corner()\Y-Mouse\Y,2) < 8*8
                              *SelectedCorner = @Corner()
                              Break 2
                           EndIf
                        Next
                        If *SelectedCorner
                           ChangeCurrentElement(Corner(), *SelectedCorner)
                        EndIf
                        *SelectedCorner = AddElement(Corner())
                        Corner() = Mouse
                     Until #True
                     UpdateCanvasGadget()
                   ElseIf EditModus = 2 
                   ElseIf EditModus = 3 
                   EndIf
                 Case #PB_EventType_RightButtonDown
                   If EditModus = 1 
                     ForEach Corner()
                        If Pow(Corner()\X-Mouse\X,2)+Pow(Corner()\Y-Mouse\Y,2) < 8*8
                           *SelectedCorner = @Corner()
                        EndIf
                     Next
                     MoveCorner = #True
                     UpdateCanvasGadget()
                   ElseIf EditModus = 2 
                     ForEach Corner()
                        If Pow(Corner()\X-Mouse\X,2)+Pow(Corner()\Y-Mouse\Y,2) < 8*8
                           *SelectedCorner = @Corner()
                        EndIf
                     Next
                     MoveCorner = #True
                     UpdateCanvasGadget()
                   ElseIf EditModus = 3
                     Zahl = 0 
                     ForEach Corner()
                        If Pow(Corner()\X-Mouse\X,2)+Pow(Corner()\Y-Mouse\Y,2) < 8*8
                          *SelectedCorner = @Corner()
                          Break
                        EndIf
                        Zahl + 1
                     Next
                     MoveCorner = #True
                     UpdateCanvasGadget()
                   EndIf
                 Case #PB_EventType_MouseMove
                   If EditModus = 1 
                     If MoveCorner And *SelectedCorner
                        CopyStructure(@Mouse, *SelectedCorner, Integer2D)
                        UpdateCanvasGadget()
                     EndIf
                   ElseIf EditModus = 2 
                     If MoveCorner
                        CopyStructure(@Mouse, *SelectedCorner, Integer2D)
                        UpdateCanvasGadget()
                      EndIf
                   ElseIf EditModus = 3
                     If MoveCorner
                        CopyStructure(@Mouse, *SelectedCorner, Integer2D)
                        UpdateCanvasGadget()
                        If Zahl = 0 
                          SelectElement(Corner(), 1)
                          Corner()\y = *SelectedCorner\y
                          SelectElement(Corner(), 3)
                          Corner()\x = *SelectedCorner\x
                        ElseIf Zahl = 1
                          SelectElement(Corner(), 0)
                          Corner()\y = *SelectedCorner\y
                          SelectElement(Corner(), 2)
                          Corner()\x = *SelectedCorner\x
                        ElseIf Zahl = 2
                          SelectElement(Corner(), 1)
                          Corner()\x = *SelectedCorner\x
                          SelectElement(Corner(), 3)
                          Corner()\y = *SelectedCorner\y
                        ElseIf Zahl = 3
                          SelectElement(Corner(), 2)
                          Corner()\y = *SelectedCorner\y
                          SelectElement(Corner(), 0)
                          Corner()\x = *SelectedCorner\x
                        EndIf 
                     EndIf
                   EndIf
                  Case #PB_EventType_RightButtonUp
                   If EditModus = 1 
                     MoveCorner = #False
                     UpdateCanvasGadget()
                   ElseIf EditModus = 2 
                     MoveCorner = #False
                     UpdateCanvasGadget()
                   ElseIf EditModus = 3
                     MoveCorner = #False
                     UpdateCanvasGadget()
                   EndIf
                 Case #PB_EventType_MiddleButtonDown
                   If EditModus = 1 
                     ForEach Corner()
                        If Pow(Corner()\X-Mouse\X,2)+Pow(Corner()\Y-Mouse\Y,2) < 8*8
                           DeleteElement(Corner())
                           UpdateCanvasGadget()
                           Break
                        EndIf
                     Next
                     If ListIndex(Corner()) > -1
                       *SelectedCorner = @Corner()
                     EndIf
                   ElseIf EditModus = 2 
                   ElseIf EditModus = 3 
                   EndIf
                 
               EndSelect
         EndSelect
      
      Case #PB_Event_Menu
         Select EventMenu()
            Case #MenuItem_LoadImage
               ImageFileName = OpenFileRequester("Bild laden...", "", "Bilddateien|*.png;*.bmp;*.jpg", 0)
               If ImageFileName And LoadImage(#Image, ImageFileName)
                  ResizeWindow(#Window, #PB_Ignore, #PB_Ignore, ImageWidth(#Image), ImageHeight(#Image)+MenuHeight())
                  ResizeGadget(#CanvasGadget, 0, 0, ImageWidth(#Image), ImageHeight(#Image))
                  UpdateCanvasGadget()
               EndIf
            Case #MenuItem_LoadPolygon
               XMLFileName = OpenFileRequester("Bild laden...", "", "XML|*.xml", 0)
               If XMLFileName And LoadXML(#XML, XMLFileName)
                  ClearList(Corner())
                  *MainNode = MainXMLNode(#XML)
                  
                  If GetXMLNodeName(*MainNode) = "Polygon"
                    EditModus = 1 
                  ElseIf GetXMLNodeName(*MainNode) = "Rectangle"
                    EditModus = 2 
                  ElseIf GetXMLNodeName(*MainNode) = "Circle"
                    EditModus = 3 
                  EndIf 
                  
                  ImageFileName = GetXMLAttribute(*MainNode, "Image")
                  If LoadImage(#Image, ImageFileName)
                     ResizeWindow(#Window, #PB_Ignore, #PB_Ignore, ImageWidth(#Image), ImageHeight(#Image)+MenuHeight())
                     ResizeGadget(#CanvasGadget, 0, 0, ImageWidth(#Image), ImageHeight(#Image))
                  EndIf
                  *Node = ChildXMLNode(*MainNode)
                  While *Node
                     AddElement(Corner())
                     Corner()\X = Val(GetXMLAttribute(*Node, "X"))
                     Corner()\Y = Val(GetXMLAttribute(*Node, "Y"))
                     *Node = NextXMLNode(*Node)
                  Wend
                  UpdateCanvasGadget()
               EndIf
            Case #MenuItem_SavePolygon
               XMLFileName = SaveFileRequester("Polygon speichern...", GetNamePart(ImageFileName)+".xml", "XML|*.xml", 0)
               If XMLFileName And CreateXML(#XML)
                  *MainNode = CreateXMLNode(RootXMLNode(#XML)) 
                  If EditModus = 1 
                    SetXMLNodeName(*MainNode, "Polygon")
                  ElseIf EditModus = 2 
                    SetXMLNodeName(*MainNode, "Rectangle")
                  ElseIf EditModus = 3 
                    SetXMLNodeName(*MainNode, "Circle")
                  EndIf
                  SetXMLAttribute(*MainNode, "Image", ImageFileName)
                  ForEach Corner()
                     *Node = CreateXMLNode(*MainNode)
                     SetXMLNodeName(*Node, "Corner")
                     SetXMLAttribute(*Node, "X", Str(Corner()\X))
                     SetXMLAttribute(*Node, "Y", Str(Corner()\Y))
                  Next
                  FormatXML(#XML, #PB_XML_ReFormat)
                  SaveXML(#XML, XMLFileName)
               EndIf
            Case #MenuItem_FreePolygon
               ClearList(Corner())
               *SelectedCorner = 0
               MoveCorner = #False
               UpdateCanvasGadget()
               EditModus = 1
               SetMenuItemState(#Menu,#MenuItem_Polygon,1)
               SetMenuItemState(#Menu,#MenuItem_Kreis,0)
               SetMenuItemState(#Menu,#MenuItem_Viereck,0)
             Case #MenuItem_Polygon
               SetMenuItemState(#Menu,#MenuItem_Polygon,1)
               SetMenuItemState(#Menu,#MenuItem_Kreis,0)
               SetMenuItemState(#Menu,#MenuItem_Viereck,0)
               EditModus = 1
               ClearList(Corner())
               *SelectedCorner = 0
               UpdateCanvasGadget()
            Case #MenuItem_Kreis
               SetMenuItemState(#Menu,#MenuItem_Polygon,0)
               SetMenuItemState(#Menu,#MenuItem_Kreis,1)
               SetMenuItemState(#Menu,#MenuItem_Viereck,0)
               EditModus = 2
               ClearList(Corner())
               *SelectedCorner = 0
               If IsImage(#Image)
                 AddElement(Corner())
                 Corner()\X = ImageWidth(#Image)/2
                 Corner()\Y = ImageHeight(#Image)/2  
                 AddElement(Corner())
                 If ImageHeight(#Image) > ImageWidth(#Image) 
                   Corner()\X = ImageWidth(#Image)
                   Corner()\Y = ImageHeight(#Image)/2
                 Else
                   Corner()\X = ImageWidth(#Image)/2
                   Corner()\Y = ImageHeight(#Image)
                 EndIf  
               EndIf
               UpdateCanvasGadget()
            Case #MenuItem_Viereck
               SetMenuItemState(#Menu,#MenuItem_Polygon,0)
               SetMenuItemState(#Menu,#MenuItem_Kreis,0)
               SetMenuItemState(#Menu,#MenuItem_Viereck,1)
               EditModus = 3
               ClearList(Corner())
               *SelectedCorner = 0
               If IsImage(#Image)
                 AddElement(Corner())
                 Corner()\X = 0
                 Corner()\Y = 0  
                 AddElement(Corner())
                 Corner()\X = ImageWidth(#Image)
                 Corner()\Y = 0  
                 AddElement(Corner())
                 Corner()\X = ImageWidth(#Image)
                 Corner()\Y = ImageHeight(#Image)  
                 AddElement(Corner())
                 Corner()\X = 0
                 Corner()\Y = ImageHeight(#Image)  
               EndIf
               UpdateCanvasGadget()
              Case #MenuItem_Help
                a$ = "Hilfetext" + Chr(13)+ Chr(13)
                a$ + "Nur Polygon, Linke Maustaste addiert Eckpunkt" + Chr(13)
                a$ + "Nur Polygon, Mittlere Maustaste löscht Eckpunkt" + Chr(13)
                a$ + "Alle , rechte Maustaste verschiebt Eckpunkt" + Chr(13)+ Chr(13)
                
               MessageRequester("Hilfe", a$, #PB_MessageRequester_Ok)
         EndSelect
         
   EndSelect
   
ForEver

Re: XML PolygonEditor für pb 4.60

Verfasst: 19.09.2011 00:49
von NicTheQuick
Bei mir kommt unter PB 4.60 RC 1 für Ubuntu x64 ein Speicherzugriffsfehler:
[ERROR] Ungültiger Speicherzugriff.
In Zeile 259:

Code: Alles auswählen

ImageFileName = OpenFileRequester("Bild laden...", "", "Bilddateien|*.png;*.bmp;*.jpg", 0)
Also wenn ich ein Bild öffnen möchte.

Ist das ein Bug von PB, den mir jemanden bestätigen kann?

Re: XML PolygonEditor für pb 4.60

Verfasst: 19.09.2011 07:16
von DrShrek
Hallo Michael,

Hier mal ein kommerzielles Beispiel eines Polygon-/PhysicEditors: http://www.physicseditor.de/
NUr damit Du siehst wohin der Weg hingeht ;-.)

Re: XML PolygonEditor für pb 4.60

Verfasst: 19.09.2011 09:21
von mpz
Hi,

Die Idee ist mir auch schon gekommen einfach noch ein paar Physikeigenschaften wie friction etc einzubauen. Auch der Shape tracer soll noch rein, als Grundlage kann man von DarkDragon das vectorizing Programm nehmen (http://www.bradan.eu/files/vectorizing.zip). Aber jetz baue ich erst einmal die 2d Physikelement kreis, Viereck, Polygon und Line in meine Engine ein. Deine Chipmunk.lib ist dafür bestens geeignet...

Gruß Michael