GGEngine + UDF [UPDATE 15.2.13]

  • Hi,
    in der letzten Zeit hab ich an einem Projekt gearbeitet, das das ganze _createNewBmp32 Zeug ersetzen (vereinfachen) soll. Man kann mit 5 Zeilen eine GUI erstellen und den ASM Code aufrufe, der die GUI füllt und es anzeigen. Zusätzlich soll es auch ein Stück weit bei Spielen helfen. Es gibt Funktionen zum Bilder laden, speichern und einfache Mausabfragen für Clientkoordinaten.
    Der ein oder andere hat mich sicher in der SB verzweifeln sehen :P

    GGEngine sollte ursprünglich GameGraphicsEngine heißen, es passt aber eigentlich eher GUI-Graphics oder ASM-Graphics-Engine ^^

    Das ganze hab ich in eine DLL verpackt und gleich noch eine Doku und ne UDF für geschrieben. Jetzt kann ich mit jeder Programmiersprachen ganz einfach einen Mustergenerator machen ^^ Und weil es so schön war, gibts eine Mustergeneratorversion als Beispiel dazu ^^

    CreateNewBMP32 ist jetzt in der Funktion IMGcreate drin. Ich hab es gehasst immer in meinen Dateien zu suchen, woher ich die kopieren kann ^^

    Die Doku ist in der Doku.txt (in der zip)
    Hier 2 Beispiele (auch in der zip):

    Mustergenerator
    [autoit]

    #include <GGEngine.au3>
    #include <assembleit.au3>

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $w=500
    $h=500
    $bildwert=0.01

    [/autoit] [autoit][/autoit] [autoit]

    _GGinit()
    $gui=_GGGUIcreate("GGE ASM Test",$w,$h)
    $ptr=_GGGUIgetIMGptr($gui)

    [/autoit] [autoit][/autoit] [autoit]

    _assembleit("float","_ASM","int",$w,"int",$h,"ptr",$ptr,"float",$bildwert)
    _GGGUIupdate($gui)

    [/autoit] [autoit][/autoit] [autoit]

    While Not _GGGUIclosed($gui)
    Sleep(10)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    _GGGUIdelete($gui)
    _GGfree()

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;Mein alter ASM-Code aus dem Mustergenerator :P (1:1)
    Func _ASM()
    _("use32")
    _("org " & FasmGetBasePtr($Fasm))
    _("finit") ;Co Prozessor starten
    ;
    _("mov eax,[esp+4]") ;
    _("mov [w],eax") ;w
    _("mov eax,[esp+8]") ;
    _("mov [h],eax") ;h
    ;startadresse in ebx, dann muss ebx immer nur um 4 erhöht werden, um das nächste pixel zu schreiben
    _("mov ebx,[esp+12]") ;scan0
    _("mov eax,[w]") ;an das ende setzen, weil die schleifen auch von hinten anfangen
    _("imul eax,[h]") ;w*h
    _("imul eax,4") ;je pixel 4 bytes: w*h*4
    _("add ebx,eax") ;scan0 += size
    _("sub ebx,4")
    _("mov eax,[esp+16]") ;start / bildwert
    _("mov [start],eax") ;

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;register im coprostack belegen,

    [/autoit] [autoit][/autoit] [autoit]

    _("fld [start]") ;st0=start
    _("mov edx,[h]") ;Schleifenzähler edx für y, For $edx=$h to 0 Step -1
    _("for_y:") ;Schleifenlabel

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    _("mov ecx,[w]") ;Schleifenzähler ecx für x
    _("for_x:") ;Schleifenlabel
    ;Berechung
    ;st0=start
    _("mov [ftemp],edx") ;st0=start
    _("fild [ftemp]") ;st0=y st1=start
    _("fmul st0,st1") ;st0=y*start st1=start
    _("fptan") ;st0=1 st1=tangens !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!, (tan, in ASM umgekehrt, bgra)
    _("fstp st0") ;stack sauber machen
    _("mov [ftemp],ecx") ;
    _("fild [ftemp]") ;st0=x st1=sin(y*start) st2=start
    _("fmulp") ;st0=x*sin(y*start) st1=start
    _("fistp dword[r]") ;st0=start ACHTUNG, entweder stack immer komplett leermachen oder einfach die werte weiterbenutzen!!
    ;ansonsten läuft der stack über...stackoverflow

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    _("mov [ftemp],edx") ;das ganze mit g und cos
    _("fild [ftemp]") ;st0=y st1=start
    _("fmul st0,st1") ;st0=y*start st1=start
    _("fcos") ;
    _("mov [ftemp],ecx") ;
    _("fild [ftemp]") ;st0=x st1=y*start st2=start
    _("fmulp") ;st1=x*(y*start) st1=start
    _("fistp dword[g]") ;st0=start

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    _("mov [ftemp],edx") ;und b und tan
    _("fild [ftemp]") ;
    _("fmul st0,st1") ;
    _("fsin") ;st0=sin(y*start) st1=start
    _("mov [ftemp],ecx") ;st0=tangens
    _("fild [ftemp]") ;
    _("fmulp") ;
    _("fistp dword[b]") ;st0=start, stack muss gecleant werden in der schleife!

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    _("mov byte[code=c],255") ;alpha auf 255 setzen
    _("mov eax,dword[r]") ;die 4 aufeinanderfolgenden bytes holen
    _("mov DWORD[ebx],eax") ;color in [ebx] (bild) schreiben
    _("sub ebx,4") ;ein pixel weiter bzw. zurück

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    _("dec ecx") ;Zähler dekrementieren
    _("jnz for_x") ;Wenn Zähler <> 0 dann wiederhole Schleife
    _("dec edx") ;Zähler dekrementieren
    _("jnz for_y") ;Wenn Zähler <> 0 dann wiederhole Schleife

    [/autoit] [autoit][/autoit] [autoit]

    _("fstp st0") ;stack sauber machen
    _("fld [start]") ;Rückgabewert=Start / Bildwert
    _("ret") ;Ende, Rückgabewert ist der letzte Wert des ERSTEN! Pixels (Scheife geht Rückwärts)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    _("r db 0") ;
    _("g db 0") ;
    _("b db 0") ;
    _("c dd 0") ;dummy, platz zum schreiben von dword nach [b]
    _("ftemp dd 0.0") ;zum schreiben von edx/ecx auf floating stack

    [/autoit] [autoit][/autoit] [autoit]

    _("start dd 0.0") ;für berechnung
    _("w dd 0") ;Speicher für Parameter reservieren
    _("h dd 0") ;
    EndFunc

    [/autoit]
    BSP mit fast allen Funktionen
    [autoit]

    #Region ;**** Directives created by AutoIt3Wrapper_GUI ****
    #AutoIt3Wrapper_Res_requestedExecutionLevel=asInvoker
    #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
    #include <ScreenCapture.au3>
    #include <GGEngine.au3>

    [/autoit] [autoit][/autoit] [autoit]

    _GGinit()
    $gui=_GGGUIcreate("Test",500,500)
    $hwnd=_GGGUIgetHWND($gui)
    $img=DllStructCreate("dword["&(500*500)&"]",_GGGUIgetIMGptr($gui))

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    WinSetTitle($hwnd,"","Test - Neu")

    [/autoit] [autoit][/autoit] [autoit]

    Local $screenbmp=_ScreenCapture_Capture("",0,0,249,249,True)
    $screenimg=_GGIMGcreatefromBMP($screenbmp,250,250)
    _WinAPI_DeleteObject($screenbmp)
    $screenbmp=_GGIMGgetDC($screenimg)
    _GGGUIdrawDC($gui,$screenbmp,0,0,250,250)
    _GGIMGsave($screenimg,"screen.raw")

    [/autoit] [autoit][/autoit] [autoit]

    For $y=0 To 249
    For $x=250 To 500
    DllStructSetData($img,1,0xFF00FF00,$y*500+$x)
    Next
    Next

    [/autoit] [autoit][/autoit] [autoit]

    $buffer=_GGIMGcreate(250,250)
    $bufptr=DllStructCreate("dword["&(250*250)&"]",_GGIMGgetPTR($buffer))
    For $y=0 To 250
    For $x=0 To 250
    DllStructSetData($bufptr,1,0x7F00FF00,$y*250+$x)
    Next
    Next
    _GGIMGdraw($screenimg,$buffer,0,0)
    _GGGUIdraw($gui,$screenimg,0,250)
    _GGIMGdelete($buffer)
    _GGIMGdelete($screenimg)

    [/autoit] [autoit][/autoit] [autoit]

    _GGGUIupdate($gui)

    [/autoit] [autoit][/autoit] [autoit]

    _GGGUIsavescreen($gui,"test.raw")

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $loaded=_GGIMGcreatefromRAW("screen.raw")

    [/autoit] [autoit][/autoit] [autoit]

    Local $mx=0,$my=0,$me=0
    While True
    If _GGGUIclosed($gui) Then ExitLoop
    If _GGIsPressed(0x1B) And WinActive($hwnd) Then ExitLoop
    $me=_GGGUIgetMouseEvent($gui,$mx,$my)
    If $me=$GGDOWN And $mx>250 And $mx<500 And $my>250 And $my<500 Then ;DOWN
    _GGGUIdraw($gui,$loaded,250,250)
    _GGGUIupdate($gui)
    ElseIf $me=$GGUP And $mx>250 And $mx<500 And $my>250 And $my<500 Then ;UP
    For $y=250 To 500
    For $x=250 To 500
    DllStructSetData($img,1,0xFF000000,$y*500+$x)
    Next
    Next
    _GGGUIupdate($gui)
    EndIf
    Sleep(10)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    _GGIMGdelete($loaded)

    [/autoit] [autoit][/autoit] [autoit]

    _GGGUIdelete($gui)
    _GGfree()
    Exit 0

    [/autoit]

    Beispiel mit GDI+ (only Autoit UDF) und neuen Funktionen.

    Spoiler anzeigen
    [autoit]

    #include <GGEngine.au3>

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    _GGinit()

    [/autoit] [autoit][/autoit] [autoit]

    $img=_GGIMGcreatefromFILE("Farben.jpg")
    $w=_GGIMGgetW($img)
    $h=_GGIMGgetH($img)
    _GGIMGsavetoFILE($img,"Farben.png")

    [/autoit] [autoit][/autoit] [autoit]

    $gui=_GGGUIcreate("GGE GDI+ Image viewer",$w,$h)

    [/autoit] [autoit][/autoit] [autoit]

    _GGGUIdraw($gui,$img,0,0)
    _GGIMGdelete($img)
    _GGGUIupdate($gui)

    [/autoit] [autoit][/autoit] [autoit]

    While Not _GGGUIclosed($gui)
    Sleep(10)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    _GGGUIdelete($gui)
    _GGfree()

    [/autoit]


    Ich hatte keine Lust sämtliche Bildformate zu lernen zu entpacken und dann zu verwenden. Daher hab ich das einfachstmöglichste Format der Welt namens RAW erschaffen und gleich einen Converter dazu in die zip gepackt ^^ (mit AU3 Code)

    Das UDF-include GGEngine.au3 und die DLL sind natürlich auch mit der zip

    Mustergenerator-Beispiel Screenshot:
    autoit.de/wcf/attachment/18632/

    Ich hoffe es gefällt und hilft euch. Ich freu mich auf euer Feedback.
    Viel Spaß :)
    mfg
    TheShadowAE


    EDIT:
    Ganz vergessen Andy zu danken, er hat mir mal wieder geholfen ein Problem zu lösen ^^

    EDIT: UPDATE:
    Ich hab Andys genannten Fehler mal gefixt. Und hab mal für die, die es noch nicht haben, die assembleit angehangen.

    UPDATE:
    Ich habs geschafft, die DLL ist jetzt im include enthalten. Dh. man braucht nur die au3 und schon läuft alles :) Zusätzlich hab ich noch eine kleine Korrektur gemacht, wodurch beim Klicken ca. 100 Ticks weniger verbraucht werden :whistling:

    UPDATE:
    Jetzt kann man jede Bildformate öffnen und speichern mit den neuen Funktionen (3. Beispiel) und Width und Height abfragen.

  • Interessant. Das verfolgt ähnlich aber gleichzeitig völlig unterschiedliche Ansätze wie meine (im Bau befindliche) M2D (Mars 2D) UDF.
    Ich werde mir auf jeden Fall alles durchlesen und mal schauen welche "Redewndungen" in meiner UDF Gebrauch finden könnten. (du wirst dann natürlich erwähnt).

  • Hi!

    Sehr, sehr nice! :thumbup:
    Pack die DLL noch in die GGengine.au3, dann muss die auch keiner mehr mitschleppen (direkt dort in den Speicher laden, UEZ hat imho da mal etwas dafür gebastelt)

    Das ist ideal, um kleine Demos zu machen!

    Spoiler anzeigen
    [autoit]

    #include <GGEngine.au3>

    [/autoit] [autoit][/autoit] [autoit]

    $w = 256
    $h = 256

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    _GGinit()
    $gui = _GGGUIcreate("GGE Demo", $w, $h)
    $ptr = _GGGUIgetIMGptr($gui)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $struct = DllStructCreate("dword[" & $w * $h & "]", $ptr) ;struct erstellen an der Position der bitmap

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    While Not _GGGUIclosed($gui)

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 1 To $w * $h - 1 ;jedes einzelne pixel....
    DllStructSetData($struct, 1, Random(1, 2 ^ 31 - 1, 1), $i);....mit random-farbe beschreiben ;
    Next
    _GGGUIupdate($gui)
    Sleep(10)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    _GGGUIdelete($gui)
    _GGfree()

    [/autoit]


    Schau doch mal nach, warum dieser Code NACH dem schliessen des Fensters abstürzt!

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    Einmal editiert, zuletzt von Andy (26. Januar 2013 um 22:24)

  • Hmm, wenn du vor dem GUIdelete ein $struct=0 machst, dann funktioniert alles. Anscheinend mag Autoit nicht, wenn jemand den benutzten Speicher löschen will ^^
    Nach dem DLL-Binary guck ich mal, hab ich auch schon irgendwo gesehen.

    EDIT: Das war wohl nur beim ersten mal so.. Mist

    EDIT: Das Beschreiben der Bitmapdaten dauert zu lange.. Beim GUI schließen ist das Bild weg und schon gibts ein Memoryerror.. Ich versuche das mal zu fixen.

    Einmal editiert, zuletzt von TheShadowAE (26. Januar 2013 um 22:41)

  • Ist nun gefixt, dein Skript funktioniert mit der neuen Version Andy. Wenn ich die DLL als Binary in den Source packen will, laggt Scite aufs Übelste ^^ Das wird nichts mit der MemoryDLL ^^ Man kann es ja auch mit FileInstall ermöglichen, dann ist zumindest die EXE unabhängig.

  • Das liegt bestimmt an der hohen Größe der Dll.
    Wenn du die Dll mit UPX kleinmachst (param --ultra-brute) kommt der Spaß bei mir auf 116kb (ca. 1/4)
    Vllt anschließend nochmal versuchen das binär einzubinden. Wenns dann noch laggt müsstest du es in ein Include (welches nur die Res enthält) auslagern.
    Irgendwie in den Code einbauen solltest du es aber schon. Eine Dll die zusätzlich benötigt wird ist immer ein Klotz am Bein.

  • Moin Leute, gute Nachrichten. Die DLL ist jetzt im Code und wird wenn sie nicht vorhanden ist, einfach geschrieben. Zusätzlich noch eine mini Optimierung vorgenommen.
    Ich hab jetzt mal mit VC++ kompiliert und schon hatte ich nurnoch 100 KB und mit UPX gepackt sind es jetzt nurnoch 60 KB ^^ Also von 420 auf 60 runter, das ist doch was ^^
    Jetzt könnt ihr euch von den Platzängsten befreien und sorgenlos Tests durchführen ^^

  • Hi,
    aus aktuellem Anlass grabe ich den Thread wieder aus.

    TheShadowAE, schau mal, ob du nicht eine 64-Bit-Version der DLL bzw der Engine erstellen kannst. Ich habe VC++ nur in der 32-Bitversion.
    Wenn das Stress bedeutet, lass es bitte!

    Bin gerade am Basteln, mit 64Bit-ASM-Code bzw AVX Grafiken zu bearbeiten. AssembleIt() soll auf eine höhere Stufe gehoben werden 8o