Really fast gui development.

Discuss GUI programming with the MUI Royale plugin here
Post Reply
User avatar
lazi
Posts: 625
Joined: Thu Feb 24, 2011 11:08 pm

Really fast gui development.

Post by lazi »

To prove that how effective MUI Royale, shortly after it launched I made a simple 3D object viewer with nice MUI gui. You will find it on OS4Depot an on Aminet.

The source is here if you want look a really nasty source :)

Code: Select all

;3d Primer
;filled konvex polygon drawing
;
;To do:
;- add size detection and compensation
@REQUIRE "MUIRoyale"
@APPTITLE "ShowGeo"
@APPVERSION "$VER: ShowGeo 1.0 (02.01.13)"
@APPCOPYRIGHT "(C) Copyright 2013 by Lázi"
@APPAUTHOR "Lázi"
@APPDESCRIPTION "Display .geo format 3D polygon objects"

@DISPLAY {hidden=true,width=640,height=400}

@FILE 1,"videoscape/geo/boing"
@FILE 2,"videoscape/geo/theend"

SetFormStyle (#ANTIALIAS)
SetFillStyle (#FILLCOLOR)

world={
obj=0,
YMID=200,
XMID=320,
DIST=90,
ZOM=400,
filled=true,
bw=false
}

obj={{}}

;pontok
obj[0].pt={{x=-10, y=-10, z=-10},
    {x= 10, y=-10, z=-10},
    {x= 10, y= 10, z=-10},
    {x=-10, y= 10, z=-10},
    {x=-10, y=-10, z= 10},
    {x= 10, y=-10, z= 10},
    {x= 10, y= 10, z= 10},
    {x=-10, y= 10, z= 10},

    {x=0,y=0,z=0},
    {x=30,y=0,z=0},
    {x=0,y=30,z=0},
    {x=0,y=0,z=30},
       }

pal={$000000,$0050A0,$008C00,$008C8C,$A00000,$8CA0A0,$A07800,$8C8C8C,$000000,$0078F0,$00F000,$00F0F0,$F00000,$C800F0,$F0C800,$F0F0F0}

;élek
obj[0].P={{0,3,2,1,$0050A0},{0,1,5,4,$008C00},{2,3,7,6,$008C8C},{4,5,6,7,$A00000},{0,4,7,3,$8CA0A0},{1,2,6,5,$A07800}}

;elforgatott pontok
obj[0].rpt=CopyTable(obj[0].pt)

obj[0].rot={0,0,0}

;---------------------------------------------------------------

function p_dragmouse()
   InstallEventHandler({onmousedown=0,onmouseup=p_releasemouse})
   SetInterval(2,p_mousemove,1000/30,{x=MouseX(),y=MouseY()})
endfunction

function p_releasemouse()
    ClearInterval(2)
    InstallEventHandler({onmousedown=p_dragmouse,onmouseup=0,onmousemove=0})
Endfunction

function p_mousemove(msg)
    kappa=Wrap(kappa-MouseX()+msg.userdata.x,0,359)
    phi=Wrap(phi-MouseY()+msg.userdata.y,0,359)
    p_rotate(0,0,0)
    p_mainloop
    SetInterval(2,p_mousemove,1000/30,{x=MouseX(),y=MouseY()})
endfunction

function p_zoomin()
    world.zom=Min(world.zom+50,2500)
    p_mainloop
endfunction

function p_zoomout()
    world.zom=Max(world.zom-50,50)
    p_mainloop
endfunction

factory_val=Val
function Val(s)
    if LeftStr(s,1)="."
        s="0"..s
    elseif LeftStr(s,2)="-."
        s="-0"..s
    endif
    Return(factory_val(s))
endfunction


;---------------------------------------------------------------

function p_loadgeo(o,f$,preopened)
    local points,coords,g, i, n, nagyobb, scale
    local fh=1
    if preopened
        fh=o
    else
       OpenFile(fh,f$,#MODE_READ)
    endif

    if ReadLine(fh)="3DG1"
        obj[o]={pt={},rpt={},p={},rot={0,0,0}}
        pt={}
        points=Val(ReadLine(fh))-1
        for local i=0 to points
           g,n=SplitStr(ReadLine(fh)," ")
           if n=3
            gx=Val(g[0])
            gy=-Val(g[1])
            gz=Val(g[2])
            nagyobb=Max(nagyobb,Abs(gx),Abs(gy),Abs(gz))
            InsertItem(obj[o].pt,{x=gx,y=gy,z=gz},i)
           endif
        next

        scale=10/(nagyobb)
        for i=0 to ListItems(obj[o].pt)-1
            obj[o].pt[i].x=obj[o].pt[i].x*scale
            obj[o].pt[i].y=obj[o].pt[i].y*scale
            obj[o].pt[i].z=obj[o].pt[i].z*scale
        next

        obj[o].rpt=CopyTable(obj[o].pt)
        p={}
        while not Eof(fh)
          ll=TrimStr(ReadLine(fh)," ",false)
          coords,points=SplitStr(ll," ")
          gx={}
          if points>1
             For i=1 To coords[0]+1
               InsertItem(gx,Val(coords[i]) ,i-1)
             Next
             ;color
             ;drop special attributes
             gx[i-2]=pal[gx[i-2] & 15 ]


             InsertItem(obj[o].p,gx)
          endif
        wend
    else
        mui.request("ShowGeo","The selected file is not a .geo file what I can handle","Continue")
        Return(false)
    endif
    CloseFile(fh)
    mui.domethod("object","Insert",o,FilePart(f$))
    Return(true)
endfunction

function p_rotate(dxr,dyr,dzr)
   ; Increment rotation angles around z,x,y
   ;teta=Wrap(teta+dzr,0,359)
   ;phi=Wrap(phi+dxr,0,359)
   ;kappa=Wrap(kappa+dyr,0,359)

   ; Precalculation of COSs and SINs
   Local CPHI=Cos(Rad(PHI))
   Local SPHI=Sin(Rad(PHI))
   Local CTETA=Cos(Rad(TETA))
   Local STETA=Sin(Rad(TETA))
   Local CKAP=Cos(Rad(KAPPA))
   Local SKAP=Sin(Rad(KAPPA))

   ; Calculation of rotated 3D coords of all points
   ; Rotation (X-Z with PHI) & rotation (X-Y with TETA)
   For I=0 To ListItems(pt)-1
      ;x
      rpt[I].z=(pt[I].z*cPHI-pt[I].y*sPHI)
      rpt[I].y=(pt[I].z*sPHI+pt[I].y*cPHI)
      rpt[I].x=pt[I].x

      ;y
      local x=(rpt[I].z*sKAP+rpt[I].x*cKAP)
      rpt[I].z=(rpt[I].z*cKAP-rpt[I].x*sKAP)
      rpt[I].x=x


      ;z
      x=(rpt[I].x*CTETA-rpt[I].y*STETA)
      rpt[I].y=(rpt[I].x*STETA+rpt[I].y*CTETA)
      rpt[I].x=x

   Next
endfunction

function p_drawobject()
; Calculation of A,B,C,D screen coords and draw lines
    local p1,p2,p3,abx,aby,abz,pvx,pvy,pvz,c,ci


    For I=0 To ListItems(p)-1

        if world.bw=false
            c= P[I][ListItems(p[I])-1]
        else
            c=#WHITE
        endif


        if ListItems(p[i])>3 and world.filled=true

             p1=p[i][0]
             p2=p[i][1]
             p3=p[i][2]

            ;' Calculation of AB vector
             abx=rpt[p2].x-rpt[p1].x
             aby=rpt[p2].y-rpt[p1].y
             abz=rpt[p2].z-rpt[p1].z

            ;' Calculaton of AC vector

             acx=rpt[p3].x-rpt[p1].x
             acy=rpt[p3].y-rpt[p1].y
             acz=rpt[p3].z-rpt[p1].z


            ;' Calculation of PV vector = AB^AC

             pvx=aby*acz-abz*acy
             pvy=abz*acx-abx*acz
             pvz=abx*acy-aby*acx

            ;' Calculation of ENL scalair product PV.AB
            ;' (proportionnal with Enlightment of a Face)
            Local ENL= PVX*rpt[p1].x + PVY*rpt[p1].y + PVZ*(rpt[p1].z + world.DIST)

            ;' Positive ENL means that the face is hidden


            If enl<0 or mui.get("hidden","selected")

                enl=(-enl)/(.05*world.dist)
                vert={}

                for t=0 to ListItems(p[i])-3
                    P1=P[I][t]
                    P2=P[I][t+1]

                    ox2=x2
                    oy2=y2

                    x2=world.XMID+(rpt[P2].x*world.ZOM)/(world.DIST+rpt[P2].z)
                    y2=world.YMID+(rpt[P2].y*world.ZOM)/(world.DIST+rpt[P2].z)

                    X1=world.XMID+(rpt[P1].x*world.ZOM)/(world.DIST+rpt[P1].z)
                    Y1=world.YMID+(rpt[P1].y*world.ZOM)/(world.DIST+rpt[P1].z)


                    if mui.get("wireframe","selected")
                     Line (X1,Y1 , X2,Y2,c)
                    endif

                    ;Plot(x1,y1,c)

                    If t=0
                        ox1=x1
                        oy1=y1
                        InsertItem(vert,x1)
                        InsertItem(vert,y1)

                    EndIf

                    InsertItem(vert,x2)
                    InsertItem(vert,y2)
                    next

                    if mui.get("wireframe","selected")
                     Line (x2,y2,ox1,oy1,c)
                    endif

                    ;Plot(x2,y2,c)

                    if mui.get("wireframe","selected")=False
                    InsertItem(vert,ox1)
                    InsertItem(vert,ox2)
                 
                    Polygon(0,0,vert,ListItems(vert)/2-1,c);RGB(enl/2,0,enl/2))
                    endif
            EndIf


        else
            for t=0 to ListItems(p[i])-3
            P1=P[I][t]
            P2=P[I][t+1]

            ox2=x2
            oy2=y2
            x2=world.XMID+(rpt[P2].x*world.ZOM)/(world.DIST+rpt[P2].z)
            y2=world.YMID+(rpt[P2].y*world.ZOM)/(world.DIST+rpt[P2].z)

            X1=world.XMID+(rpt[P1].x*world.ZOM)/(world.DIST+rpt[P1].z)
            Y1=world.YMID+(rpt[P1].y*world.ZOM)/(world.DIST+rpt[P1].z)


            Line (X1,Y1 , X2,Y2,c)

            ;Plot(x1,y1,c)

            If t=0
            ox1=x1
            oy1=y1
            EndIf

            next

            Line (x2,y2,ox1,oy1,c)

            ;Plot(x2,y2,c)

        endif
     next
endfunction


function p_setobject(o)
    p=obj[o].p
    rpt=obj[o].rpt
    pt=obj[o].pt
    phi=obj[o].rot[0]
    kappa=obj[o].rot[1]
    teta=obj[o].rot[2]
endfunction

function p_mainloop()

   Flip(true)
   if mui.get("wvbl","selected") then VWait
   Cls(100)
   
    p_drawobject
    p_rotate(1,2,0)

Endfunction

Function p_EventFunc(msg)
	; has the size of our Hollywood class changed?
	If msg.Action = "SizeWindow"
      		world.xmid = msg.Width/2
		    world.ymid = msg.Height/2
      		Return
   	EndIf

	; handle MUI Royale events
   	Switch msg.class
  	Case "Window":
      		Switch msg.Attribute
      		Case "CloseRequest":
	 		End
  		    EndSwitch
  	Case "Button":
  		Switch msg.Attribute
  		Case "Pressed":
 		Switch msg.ID
 		Case "play":
    			SetInterval(1, p_demorotate, 1000/30)
 		Case "stop":
 			If HaveObject(#INTERVAL, 1) = True
            			ClearInterval(1)
 	    		EndIf
 		EndSwitch
	    EndSwitch
    case "Listview":
        switch msg.id
        case "object":
          world.obj=(mui.get("object","active"))
          p_setobject(world.obj)
        endswitch
    case "Checkmark":
        switch msg.id
        case "wireframe":
            if mui.get("hidden","selected") and mui.get("wireframe","selected")=false
                mui.set("hidden","selected",false)
            endif
        case "antialias":
            if mui.get("antialias","selected")
                SetFormStyle (#ANTIALIAS)
            else
                SetFormStyle (#NONE)
            endif
        case "hidden":
            if mui.get("wireframe","selected")=false and mui.get("hidden","selected")=true
                mui.set("wireframe","selected",true)
            endif
        case "hwdb":
            EndDoubleBuffer
            if mui.get("hwdb","selected")
                BeginDoubleBuffer(true)
            else
                BeginDoubleBuffer(false)
            endif
        endswitch
    case "Popfile":
        switch msg.id
        case "file":
          if p_loadgeo(mui.get("object","entries"),mui.get("file","contents"))
          p_setobject(mui.get("object","entries")-1)
          endif
        endswitch
   	EndSwitch
    p_mainloop
    Flip
EndFunction

function p_demorotate()
 ; Increment rotation angles around z,x,y
   teta=Wrap(teta+1,0,359)
   phi=Wrap(phi+2,0,359)
   kappa=Wrap(kappa+1,0,359)
   p_mainloop
endfunction

mui.CreateGUI([[
<?xml version="1.0" encoding="iso-8859-1"?>
<application base="GEO-View">
   <window title="ShowGeo" muiid="MAIN" notify="closerequest">
   <hgroup>
       <vgroup>
          <listview shorthelp="Loaded object files" notify="active" id="object">
             <column title="Object">
             </column>
          </listview>
          <Label>Load object:</Label>
          <popfile id="file" shorthelp="Add a .geo object file to the list" notify="contents" title="Select .geo file to load"/>
             <colgroup frame="group" frametitle="Draw mode" columns="2">
                 <Label>Wireframe:</Label><checkmark notify="selected" id="wireframe"/>
                 <Label>Antialias:</Label><checkmark notify="selected" id="antialias" selected="true"/>
                 <Label>Hidden lines:</Label><checkmark notify="selected" id="hidden"/>
                 <Label>Hardware db:</Label><checkmark shorthelp="Hardware accelerated double buffered display." disabled="true" notify="selected" id="hwdb"/>
                 <Label>Wait vbl:</Label><checkmark id="wvbl" selected="true"/>
             </colgroup>
       </vgroup>
       <vgroup>
          <text preparse="\33c" frame="text">Use your mouse to rotate the object around, and the wheel to zoom it!</text>
          <hollywood shorthelp="Display area. The object can be zoomed, rotated by the mouse." display="1" minwidth="640" minheight="400"
          maxwidth="640" maxheight="400"/>
          <hgroup>
             <button id="play" notify="pressed">Start rotation</button>
             <button id="stop" notify="pressed">Stop rotation</button>
          </hgroup>
       </vgroup>
   </hgroup>
   </window>
</application>
]])


mui.domethod("object","Insert",0,"Cube")

p_loadgeo(1,"videoscape/geo/boing",true)
p_loadgeo(2,"videoscape/geo/theend",true)
p_setobject(world.obj)

CreateBrush(1,10,10,#WHITE)
CopyBrush(1,2,{hardware=true})
if GetAttribute(#BRUSH,2,#ATTRHARDWARE)
  mui.set("hwdb","disabled",0)
  mui.set("hwdb","selected",true)
endif

FreeBrush(1)
FreeBrush(2)

BeginDoubleBuffer(mui.get("hwdb","disabled"))

SetInterval(1, p_demorotate, 1000/30)

InstallEventHandler({MUIRoyale = p_EventFunc, SizeWindow = p_EventFunc, onmousedown=p_dragmouse,onmouseup=0,onmousemove=0,onwheeldown=p_zoomin,onwheelup=p_zoomout,onrightmousedown=p_change})


Repeat
	WaitEvent
forever                                     

User avatar
airsoftsoftwair
Posts: 5443
Joined: Fri Feb 12, 2010 2:33 pm
Location: Germany
Contact:

Re: Really fast gui development.

Post by airsoftsoftwair »

Congratulations for the first MUI Royale project!
User avatar
fingus
Posts: 269
Joined: Fri Sep 16, 2011 9:53 am

Re: Really fast gui development.

Post by fingus »

Nice!

Now i´m able to add Pulldown-/Popup--Menus to Flipclock 53.1 Beta3! ;)
Post Reply