`Setup
sync on
sync rate 30
autocam off
set display mode 1024,768,16
set window on
maximize window
backgd=rgb(0,0,0)
edit=1
 
`Data
max=65530
type coordXYZ
   x as float
   y as float
   z as float
   sx as float
   sy as float
   sz as float
   rx as float
   ry as float
   rz as float
endtype
dim object(max) as coordXYZ
 
`View data
type view
   x1 as integer
   y1 as integer
   x2 as integer
   y2 as integer
endtype
dim views(3) as view
 
views(0).x1=screen width()/2
views(0).y1=screen height()/2
views(0).x2=screen width()
views(0).y2=screen height()
 
views(1).x1=0
views(1).y1=0
views(1).x2=screen width()/2
views(1).y2=screen height()/2
 
views(2).x1=screen width()/2
views(2).y1=0
views(2).x2=screen width()
views(2).y2=screen height()/2
 
views(3).x1=0
views(3).y1=screen height()/2
views(3).x2=screen width()/2
views(3).y2=screen height()
 
for c=1 to 3
   make camera c
   set current camera c
   color backdrop backgd
next c
set current camera 0
 
`backdrop
color backdrop backgd
create bitmap 1,20,20 : set current bitmap 1
ink rgb(128,128,128),0 : box 0,0,10,10 : box 10,10,20,20
ink rgb(255,255,255),0 : box 0,10,10,20 : box 10,0,20,10
get image 1,0,0,20,20
set current bitmap 0 : delete bitmap 1
make object plain 65534,100,100
xrotate object 65534,90 : fix object pivot 65534
texture object 65534,1 : scale object texture 65534,20,20
set object ambient 65534,0
 
`Axis
make object box 65531,50,.1,.1
make object box 65532,.1,.1,50
make object box 65533,.1,50,.1
color object 65531,rgb(0,0,255)
color object 65532,rgb(0,255,0)
color object 65533,rgb(255,0,0)
position object 65531,-25,.05,0
position object 65532,0,.05,25
position object 65533,0,25,0
 
`used for moving the camera
global camAngle as float = 35.0
global camDist as float = 15.0
global camPitch as float
position camera 0,20,20,20
point camera 0,0,0,0
 
`Menu
create bitmap 1,100,18 : set current bitmap 1
   box 0,0,100,18:ink rgb(200,200,200),0:box 1,0,99,17:get image 2, 0,0,100,18,1:ink rgb(0,0,0),0
set current bitmap 0 : delete bitmap 1
ListText$="Cube;Sphere;Cone;Cylinder;Plain;Triangle;;Move;Scale;Rotate;;Solid;Wireframe;;Exit"
 
 
`**Main Loop**
do
 
ink rgb(255,255,255),0
text 10,100,str$(edit)
 
`Control Objects
Gosub _Control_Objects
 
`Views
Gosub _Create_views
 
`GUI Control
Gosub _GUI_Control
 
   `camera movement
   if controlkey()=1
      if mouseclick()=1 then dec camdist,1
      if mouseclick()=2 then inc camdist,1
      inc camangle,mousemovex()*2
      inc campitch,mousemoveY()
   endif
   if camdist<=0 then camdist=0
   if controlkey()=1 then hide mouse else show mouse
 
   position camera sin(camAngle)*camDist, 15+campitch, cos(camAngle)*camDist
   point camera 0,0,0
 
   `**End Loop**
   sync
loop
 
 
`**Subroutines**
 
_Control_Objects:
 
`Create object
if cube=1
   make_cube=1
   inc crobj
      if selected>0 then hide object bounds selected
else
   make_cube=0
endif
if sphere=1
   make_sphere=1
   inc crobj
      if selected>0 then hide object bounds selected
else
   make_sphere=0
endif
if cone=1
   make_cone=1
   inc crobj
else
   make_cone=0
      if selected>0 then hide object bounds selected
endif
if crobj>3 then inc objects : crobj=0
 
if objects>0
   if object exist(objects)=0 and make_cube=1 then make object cube objects,5 : color object objects,rgb(rnd(255),rnd(255),rnd(255))
   if object exist(objects)=0 and make_sphere=1 then make object sphere objects,5 : color object objects,rgb(rnd(255),rnd(255),rnd(255))
   if object exist(objects)=0 and make_cone=1 then make object cone objects,5 : color object objects,rgb(rnd(255),rnd(255),rnd(255))
endif
 
`Check if mouse is over object
over=pick object(mousex(),mousey(),1,objects)
text 10,10,str$(selected)
 
`Move object
if edit=1
if over>0
   if mouseclick() = 1
   selected=over
      SYS_screenToXZ(selected,mousex(), mousey(), object position y(selected))
      position object selected, object(selected).x, object(selected).y, object(selected).z
   else
      if mouseclick() = 2
      selected=over
         SYS_screenToY(selected,mousex(), mousey(), object position x(selected), object position z(selected))
         position object selected, object position x(selected), object(selected).y, object position z(selected)
      endif
   endif
endif
endif
 
`Scale object
if edit=2
   if mouseclick()=1
   selected=over
      if selected>0
         object(selected).sx=object(selected).sx+(mousemovex())
         object(selected).sz=object(selected).sz+(mousemovey())
      endif
   endif
   if mouseclick()=2
   selected=over
      if selected>0
         object(selected).sy=object(selected).sy+(mousemovey()*-1)
      endif
   endif
if selected>0
   scale object selected,object(selected).sx+5,object(selected).sy+5,object(selected).sz+5
endif
endif
 
`Selected Object
if selected>0
   show object bounds selected,1
endif
 
`Deselect objects
if selected>0
   if over=0 and mouseclick()>0 then hide object bounds selected : selected=0
endif
 
`Delete objects
if selected>0 and keystate(14)=1 or keystate(211)=1
   inc del : if del=1 then delete object selected : selected=0 : del=0
endif
 
`Views
if solid=1
   for o=1 to objects
      if object exist(max)=1 then set object wireframe o,0
   next o
endif
if wire=1
   for o=1 to objects
      if object exist(max)=1 then set object wireframe o,1
   next o
endif
 
Return
 
 
`Create Views
_Create_Views:
 
`Position cameras
position camera 1,-50,0,0
position camera 2,0,50,0
position camera 3,0,0,50
for c=1 to 3
   point camera c,0,0,0
next c
ink rgb(255,255,255),0
line 0,screen height()/4,screen width()/2-1,screen height()/4
line 0,screen height()/2+screen height()/4,screen width()/2-1,screen height()/2+screen height()/4
if camera position y(0)=0
   line screen width()/2+1,screen height()/2+screen height()/4,screen width(),screen height()/2+screen height()/4
endif
 
`Joins
ink rgb(255,128,0),0
box 0,views(1).y2-2,screen width(),views(1).y2+2
box views(1).x2-2,0,views(1).x2+2,screen height()
 
`Create Perspective view
set current camera 0
for c=0 to 3
   set camera view c,views(c).x1,views(c).y1,views(c).x2,views(c).y2
next c
 
 
Return
 
`GUI Control
_GUI_Control:
 
`Create
if mouseclick()=0 then MouseLock=0:Selection=0
if mouseclick()=2 and selected=0 and controlkey()=0
 if MouseLock=0 then tempx=mousex():tempy=mousey():MouseLock=1
 Selection=DropDownList(ListText$,tempx,tempy,2)
endif
 
`Selections
if selection=1 then inc cubemake else cubemake=0
if selection=2 then inc spheremake else spheremake=0
if selection=3 then inc conemake else conemake=0
if selection=4 then inc cylmake else cylmake=0
if selection=5 then inc plainmake else plainmake=0
if selection=6 then inc trimake else trimake=0
if selection=8 then inc editmove else editmove=0
if selection=9 then inc editscale else editscale=0
if selection=10 then inc editrot else editrot=0
if selection=12 then inc viewsolid else viewsolid=0
if selection=13 then inc viewwire else viewwire=0
if Selection=15 then end
selwait=3
if cubemake>selwait then cube=1 else cube=0
if spheremake>selwait then sphere=1 else sphere=0
if conemake>selwait then cone=1 else cone=0
if cylmake>selwait then cylinder=1 else cylinder=0
if plainmake>selwait then plain=1 else plain=0
if trimake>selwait then triangle=1 else triangle=0
if editmove>selwait then move=1 else move=0
if editscale>selwait then scale=1 else scale=0
if editrot>selwait then rotate=1 else rotate=0
if viewsolid>selwait then solid=1 else solid=0
if viewwire>selwait then wire=1 else wire=0
if cubemake>selwait then cubemake=0
if spheremake>selwait then spheremake=0
if conemake>selwait then conemake=0
if cylmake>selwait then cylmake=0
if plainmake>selwait then plainmake=0
if trimake>selwait then trimake=0
 
`Edit
if move=1 then edit=1
if scale=1 then edit=2
if rotate=1 then edit=3
 
`View
if solid=1
   for i=1 to max
      if object exist(i) then set object wireframe i,0
   next i
endif
if wire=1
   for i=1 to max
      if object exist(i) then set object wireframe i,1
   next i
endif
 
Return
 
`**Functions**
 
`Move XZ
function SYS_screenToXZ(obj,screenx as integer, screeny as integer, Yplain as float)
   local pick as CoordXYZ
   local height as float
   local scalar as float
   height = camera position y(0)
   pick screen screenx, screeny, 1.0
   pick.x = get pick vector x()
   pick.y = get pick vector y()
   pick.z = get pick vector z()
   `scalar = Yplain - (height/pick.y)
   scalar = -1*((height - Yplain)/pick.y)
 
   `since it is impossible
   object(obj).x = (camera position x(0) + scalar*pick.x)
   object(obj).y = Yplain
   object(obj).z = (camera position z(0) + scalar*pick.z)
endfunction
 
 
`Move Y
function SYS_screenToY(obj,screenx as integer, screeny as integer, Xpos as float, Zpos as float)
   local vec0A as integer = 1
   local vec1A as integer = 2
   local vecB as integer = 3
   local vecC as integer = 4
   local tmp as float
   local rtrn as float
 
   tmp = make vector3(vec0A)
   tmp = make vector3(vec1A)
   tmp = make vector3(vecB)
   tmp = make vector3(vecC)
 
   `after we make the vectors perform math...
   pick screen screenx, screeny, 1.0
   set vector3 vec0A, Xpos, 0, Zpos
   set vector3 vec1A, 0, 1, 0
   set vector3 vecB,  get pick vector x(), get pick vector y(), get pick vector z()
 
   cross product vector3 vecC, vec1A, vecB
   cross product vector3 vecC, vecC, vecB
   normalize vector3 vecC, vecC
 
   tmp = X Vector3(vecC)*camera position x(0) + Y Vector3(vecC)*camera position y(0) + Z Vector3(vecC)*camera position z(0)
   object(obj).y = (tmp - dot product vector3(vec0A, vecC)) / dot product vector3(vec1A, vecC)
 
   tmp = delete vector3(vec0A)
   tmp = delete vector3(vec1A)
   tmp = delete vector3(vecB)
   tmp = delete vector3(vecC)
endfunction
 
 
`Drop down list
Function DropDownList(ListText$,XPOS,YPOS,ImageNumber)
YPOSinc=18
SpriteStart=20
dim Text$(50):temp$="":temp=1:Segments=1
for t=1 to len(ListText$)
 if mid$(ListText$,t)<>";" then temp$=temp$+mid$(ListText$,t)
 if mid$(ListText$,t)=";" then inc Segments
 if mid$(ListText$,t)=";" or t=len(ListText$) then Text$(temp)=temp$:temp$="":inc temp
next t
for T=1 to Segments
 sprite T+SpriteStart,XPOS,YPOS+(YPOSinc*(T-1)),Imagenumber:hide sprite T+SpriteStart:set sprite T+SpriteStart,0,0:set sprite priority T+SpriteStart,2
 paste sprite T+SpriteStart,XPOS,YPOS+(YPOSinc*(T-1))
 if mousex()>sprite x(T+SpriteStart) and mousey()>sprite y(T+SpriteStart) and mousex()<sprite x(T+SpriteStart)+sprite width(T+SpriteStart) and mousey()<sprite y(T+SpriteStart)+sprite height(T+SpriteStart) and Text$(T)<>"" then ink RGB(109,172,218),RGB(150,150,150):box XPOS+1,YPOS+(YPOSinc*(T-1)),XPOS+(sprite width(T+SpriteStart)-1),YPOS+(YPOSinc*(T-1))+(YPOSinc-1):ink RGB(10,10,10),RGB(150,150,150)
 if mousex()>sprite x(T+SpriteStart) and mousey()>sprite y(T+SpriteStart) and mousex()<sprite x(T+SpriteStart)+sprite width(T+SpriteStart) and mousey()<sprite y(T+SpriteStart)+sprite height(T+SpriteStart) and Text$(T)<>"" then Segment=T
 text XPOS+5,YPOS+(YPOSinc*(T-1))+2,Text$(T)
next T
undim Text$(0)
EndFunction Segment