here the class of gizmo of my editor (ediTable, Bmax+minib3D):

is not powerfull like 3dsmax ones, but I find it quite comfortable too...
Type tGizmo
'status flags
Field using:Int
Field mode:String = "MOVE"
'main entities
Field entity:TEntity
Field entityScale:TEntity
Field pivotRotate:TEntity
'gizmo handles
Field arrow :TMesh[3] 'move / cone
Field arrowR:TMesh[3] 'rotate / sphere
Field arrowS:TMesh[3] 'scale / cube
Field planeM:TMesh[3] 'move2axis / plane
'projection variables
Field CX2D:Int , CY2D:Int '2Dcoords of center of gizmo
Field AX2D:Int[3] , AY2D:Int[3] '2Dcoords of arrow
Field PrjX:Int[3] , PrjY:Int[3] '2Dcoords of arrow mesh
Field VX2D:Float[3] , VY2D:Float[3] '2Dcoords of unitary vector of axis
Field showLines:Int
Rem
===========================================================================================
bbdoc: create:tGizmo() - ediTable Gizmo
about: create a gizmo
===========================================================================================
End Rem
Function create:tGizmo()
Local temp:tGizmo = New tGizmo
'create the main entities----------------------------------------------------------------
temp.entity = CreatePivot()
temp.pivotRotate = CreatePivot(temp.entity)
temp.entityScale = CreatePivot(temp.entity)
'create the handles----------------------------------------------------------------------
For Local i:Int = 0 To 2
temp.arrow[i] = CreateCone(8, True, temp.entityScale)
ScaleEntity (temp.arrow[i] , 0.11, 0.11, 0.11) ; EntityOrder (temp.arrow[i] , - 100)
EntityPickMode (temp.arrow[i] , 2)
temp.arrowR[i] = CreateSphere(6, temp.entityScale)
ScaleEntity (temp.arrowR[i] , 0.08, 0.08, 0.08) ; EntityOrder (temp.arrowR[i] , - 99)
EntityPickMode (temp.arrowR[i] , 2)
temp.arrowS[i] = CreateCube(temp.entityScale)
ScaleEntity (temp.arrowS[i] , 0.06, 0.06, 0.06) ; EntityOrder (temp.arrowS[i] , - 98)
EntityPickMode (temp.arrowS[i] , 2)
temp.planeM[i] = CreateCube(temp.entityScale)
ScaleEntity (temp.planeM[i] , 0.4, 0.001, 0.4) ; EntityOrder (temp.planeM[i] , - 97)
EntityPickMode (temp.planeM[i] , 2 ) ; EntityAlpha (temp.planeM[i] , 0.5)
Next
'initialize the handles -----------------------------------------------------------------
MoveEntity (temp.arrow[0] , - 2 , 0, 0 ); MoveEntity (temp.arrow[1] , 0 , 2 , 0 ); MoveEntity (temp.arrow[2] , 0 , 0, 2)
MoveEntity (temp.arrowR[0] , - 1.5, 0, 0 ); MoveEntity (temp.arrowR[1] , 0 , 1.5, 0 ); MoveEntity (temp.arrowR[2] , 0 , 0, 1.5)
MoveEntity (temp.arrowS[0] , - 1 , 0, 0 ); MoveEntity (temp.arrowS[1] , 0 , 1 , 0 ); MoveEntity (temp.arrowS[2] , 0 , 0, 1)
MoveEntity (temp.planeM[0] , 0 , 1, 1 ); MoveEntity (temp.planeM[1] , -1, 0 , 1 ); MoveEntity (temp.planeM[2] , -1, 1, 0)
RotateEntity (temp.arrow[0] , 0 , 0, 90)
RotateEntity (temp.arrow[2] , 90, 0, 0)
RotateEntity (temp.planeM[0] , 0 , 0, 90)
RotateEntity (temp.planeM[2] , 90, 0, 0)
EntityColor (temp.arrow[0] , 255, 0, 0) ; EntityColor (temp.arrow[1] , 0, 255, 0) ; EntityColor (temp.arrow[2] , 0, 0, 255)
EntityColor (temp.arrowR[0] , 255, 0, 0) ; EntityColor (temp.arrowR[1] , 0, 255, 0) ; EntityColor (temp.arrowR[2] , 0, 0, 255)
EntityColor (temp.arrowS[0] , 255, 0, 0) ; EntityColor (temp.arrowS[1] , 0, 255, 0) ; EntityColor (temp.arrowS[2] , 0, 0, 255)
EntityColor (temp.planeM[0] , 255, 0, 0) ; EntityColor (temp.planeM[1] , 0, 255, 0) ; EntityColor (temp.planeM[2] , 0, 0, 255)
Return temp
End Function
Rem
===========================================================================================
bbdoc: update() - ediTable Gizmo
about: update 3D
===========================================================================================
End Rem
Method update()
'memorize the coords---------------------------------------------------------------------
Local coordArray:Float[4]
coordArray[0] = 0 'X
coordArray[1] = 0 'Y
coordArray[2] = 0 'Z
coordArray[3] = 0 'COUNT
'gizmo controll offset variables---------------------------------------------------------
Local Dx:Float = 0.0 ; Local Dy:Float = 0.0 ; Local Dz:Float = 0.0
Local DAx:Float = 0.0 ; Local DAy:Float = 0.0 ; Local DAz:Float = 0.0
Local DSx:Float = 0 ; Local DSy:Float = 0 ; Local DSz:Float = 0
'update the gizmo size (in function of distance from camera------------------------------
Local DistanceFromCamera:Float = 5
If(ViewMngr.View[viewMngr.SelectedView].prospective = "3D")
DistanceFromCamera = EntityDistance(entity, ViewMngr.View[ViewMngr.SelectedView].CAMERA)
Else
DistanceFromCamera = 5 / (ViewMngr.View[ViewMngr.SelectedView].CAMERA.zoom*4)
EndIf
ScaleEntity Self.entityScale, DistanceFromCamera / 5, DistanceFromCamera / 5, DistanceFromCamera / 5
'check picked handle --------------------------------------------------------------------
If(Using = 0)
'and set mode/using
_pickManage(arrow , 0, "MOVE", 1); _pickManage(arrow , 1, "MOVE", 2) ; _pickManage(arrow, 2 , "MOVE", 3)
_pickManage(arrowR, 0, "ROTATE", 1); _pickManage(arrowR, 1, "ROTATE", 2) ; _pickManage(arrowR, 2, "ROTATE", 3)
_pickManage(arrowS, 0, "SCALE", 1); _pickManage(arrowS, 1, "SCALE", 2) ; _pickManage(arrowS, 2, "SCALE", 3)
_pickManage_invertFX(planeM, 0, "MOVE", 4) ; _pickManage_invertFX(planeM, 1, "MOVE", 5) ; _pickManage_invertFX(planeM, 2, "MOVE", 6)
EndIf
Local distInc:Float=DistanceFromCamera/10.0
RotateEntity PivotRotate,EntityPitch(PivotRotate) mod 360,EntityYaw(PivotRotate) mod 360,EntityRoll(PivotRotate) mod 360,1
'do what must do according to picked handle ----------------------------------------------
'X Handles
If(Using = 1 Or using = 5 Or using = 6)
Local OffX:Float = -(AX2D[0] - CX2D) / 100.00
Local OffY:Float = -(AY2D[0] - CY2D) / 100.00
Local angle:Float = ATan2((VY2D[0] - CY2D), (VX2D[0] - CX2D))
Local modMove:Float = (ProgMngr.Mouse.speedx * Cos(angle) * distInc) / 3.00 + (ProgMngr.Mouse.speedy * Sin(angle) * distInc) / 3.00
Local modRotate:Float = (ProgMngr.Mouse.speedx * Cos(angle+90) * distInc) / 3.00 + (ProgMngr.Mouse.speedy * Sin(angle+90) * distInc) / 3.00
If(mode = "MOVE") Then MoveEntity(entity, - modMove / 10.00, 0, 0) ; Dx = Dx + modMove / 10.00
If(mode = "ROTATE") Then RotateEntity(PivotRotate,(EntityPitch(PivotRotate)+ modRotate) mod 360,EntityYaw(PivotRotate) mod 360,EntityRoll(PivotRotate) mod 360,1)
If(mode = "SCALE") Then DSx = DSx + modMove/10.00
EndIf
'Y Handles
If(Using = 2 Or using = 4 Or using = 6)
Local OffX:Float = -(AX2D[1] - CX2D )/ 100.00
Local OffY:Float = -(AY2D[1] - CY2D) / 100.00
Local angle:Float = ATan2((VY2D[1] - CY2D), (VX2D[1] - CX2D))
Local modMove:Float = (ProgMngr.Mouse.speedx * Cos(angle) * distInc) / 3.00 + (ProgMngr.Mouse.speedy * Sin(angle) * distInc) / 3.00
Local modRotate:Float = (ProgMngr.Mouse.speedx * Cos(angle+90) * distInc) / 3.00 + (ProgMngr.Mouse.speedy * Sin(angle+90) * distInc) / 3.00
If(mode = "MOVE") Then MoveEntity(entity, 0, modMove / 10.00, 0) ; Dy = Dy + modMove / 10.00
If(mode = "ROTATE") Then RotateEntity(PivotRotate, EntityPitch(PivotRotate) mod 360, Int(EntityYaw(PivotRotate) + modRotate) mod 360, EntityRoll(PivotRotate) mod 360, 1)
If(mode = "SCALE") Then DSy = DSy + modMove/10.00
EndIf
'Z Handles
If(Using = 3 Or using = 4 Or using = 5)
Local OffX:Float = -(AX2D[2] - CX2D) / 100.00
Local OffY:Float = -(AY2D[2] - CY2D) / 100.00
Local angle:Float = ATan2((VY2D[2] - CY2D), (VX2D[2] - CX2D))
Local modMove:Float = (ProgMngr.Mouse.speedx * Cos(angle) * distInc) / 3.00 + (ProgMngr.Mouse.speedy * Sin(angle) * distInc) / 3.00
Local modRotate:Float = (ProgMngr.Mouse.speedx * Cos(angle+90) * distInc) / 3.00 + (ProgMngr.Mouse.speedy * Sin(angle+90) * distInc) / 3.00
If(mode = "MOVE") Then MoveEntity(entity, 0, 0, modMove / 10.00) ; Dz = Dz + modMove / 10.00
If(mode = "ROTATE") Then RotateEntity(PivotRotate, EntityPitch(PivotRotate) mod 360, EntityYaw(PivotRotate) mod 230, Int(EntityRoll(PivotRotate) + modRotate) mod 360, 1)
If(mode = "SCALE") Then DSz = DSz + modMove/10.00
EndIf
RotateEntity PivotRotate,Int(EntityPitch(PivotRotate) mod 360),Int(EntityYaw(PivotRotate) mod 360),Int(EntityRoll(PivotRotate) mod 360),1
'manage parents-----------------------------------------------------------------------------
For Local kk:String = EachIn SceneMngr.ObjMap.keys()
If(Instr(kk,".")<=0)
Local vTemp:VarTypeI=VarTypeI(SceneMngr.ObjMap.ValueForKey(kk))
vTemp.UnparentAllMesh()
EndIf
Next
'mode selection-----------------------------------------------------------------------------
If(mode="ROTATE")
For Local kk:String = EachIn SceneMngr.Selected.keys()
If(Instr(kk,".")<=0)
Local vTemp:VarTypeI=VarTypeI(SceneMngr.Selected.ValueForKey(kk))
vTemp.setAngleAllMesh(0,0,0)
vTemp.parentAllMesh(PivotROTATE)
vTemp.setAngleAllMesh(vTemp.ROTX,vTemp.ROTY,vTemp.ROTZ)
EndIf
Next
EndIf
If(mode="MOVE")
For Local kk:String = EachIn SceneMngr.Selected.keys()
If(Instr(kk,".")<=0)
Local vTemp:VarTypeI=VarTypeI(SceneMngr.Selected.ValueForKey(kk))
CoordArray = vTemp.getCoordsAllMesh(CoordArray)
vTemp.setCoordsAllMesh(- Dx, Dy, Dz)
EndIf
Next
EndIf
If(mode = "SCALE")
For Local kk:String = EachIn SceneMngr.Selected.keys()
If(Instr(kk,".")<=0)
Local vTemp:VarTypeI=VarTypeI(SceneMngr.Selected.ValueForKey(kk))
vTemp.setScaleAllMesh(DSx, DSy, DSz)
EndIf
Next
EndIf
If(coordArray[3]>0)' And mode="MOVE")
PositionEntity entity,CoordArray[0]/coordArray[3],CoordArray[1]/coordArray[3],CoordArray[2]/coordArray[3]
EndIf
If(Not ProgMngr.Mouse.Down[1])
Using=0
EndIf
'Projection update!-------------------------------------------------------------------------
Local vpx:Int = ViewMngr.View[ViewMngr.SelectedView].x
Local vpy:Int = ViewMngr.View[ViewMngr.SelectedView].y
Local vpw:Int = vpx + ViewMngr.View[ViewMngr.SelectedView].W
Local vph:Int = vpy + ViewMngr.View[ViewMngr.SelectedView].H
'Center
CameraProject ViewMngr.View[ViewMngr.SelectedView].Camera,EntityX(entity),EntityY(entity),EntityZ(entity)
CX2D = vpx + ProjectedX()
CY2D = vpy + ProjectedY()
If(CX2D > vpw) Then CX2D = vpw
If(CX2D < vpx) Then CX2D = vpx
If(CY2D > vph) Then CY2D = vph
If(CY2D < vpy) Then CY2D = vpy
'Extreme of axis
Local vectMod:Float = DistanceFromCamera / 2
CameraProject ViewMngr.View[ViewMngr.SelectedView].CAMERA, EntityX(entity) - vectMod, EntityY(entity), EntityZ(entity)
AX2D[0] = vpx + ProjectedX() ; AY2D[0] = vpy + ProjectedY()
CameraProject ViewMngr.View[ViewMngr.SelectedView].CAMERA, EntityX(entity), EntityY(entity) + vectMod, EntityZ(entity)
AX2D[1] = vpx + ProjectedX() ; AY2D[1] = vpy + ProjectedY()
CameraProject ViewMngr.View[ViewMngr.SelectedView].CAMERA, EntityX(entity), EntityY(entity), EntityZ(entity) + vectMod
AX2D[2] = vpx + ProjectedX() ; AY2D[2] = vpy + ProjectedY()
'Unitary axist vector
vectMod:Float = 10
CameraProject (ViewMngr.View[ViewMngr.SelectedView].CAMERA, EntityX(entity) - vectMod, EntityY(entity), EntityZ(entity) )
VX2D[0] = vpx + ProjectedX() ; VY2D[0] = vpy + ProjectedY()
CameraProject (ViewMngr.View[ViewMngr.SelectedView].CAMERA, EntityX(entity), EntityY(entity) + vectMod, EntityZ(entity) )
VX2D[1] = vpx + ProjectedX() ; VY2D[1] = vpy + ProjectedY()
CameraProject (ViewMngr.View[ViewMngr.SelectedView].CAMERA, EntityX(entity), EntityY(entity), EntityZ(entity) + vectMod )
VX2D[2] = vpx + ProjectedX() ; VY2D[2] = vpy + ProjectedY()
showLines=False
'GizmoPoints
If(EntityInView(entity,ViewMngr.View[ViewMngr.SelectedView].CAMERA) )
CameraProject (ViewMngr.View[ViewMngr.SelectedView].CAMERA, EntityX(Arrow[0] , True), EntityY(Arrow[0] , True), EntityZ(Arrow[0] , True) )
PrjX[0] = ViewMngr.View[ViewMngr.SelectedView].x + ProjectedX() ; PrjY[0] = ViewMngr.View[ViewMngr.SelectedView].y + ProjectedY()
CameraProject (ViewMngr.View[ViewMngr.SelectedView].CAMERA, EntityX(Arrow[1] , True), EntityY(Arrow[1] , True), EntityZ(Arrow[1] , True) )
PrjX[1] = ViewMngr.View[ViewMngr.SelectedView].x + ProjectedX() ; PrjY[1] = ViewMngr.View[ViewMngr.SelectedView].y + ProjectedY()
CameraProject (ViewMngr.View[ViewMngr.SelectedView].CAMERA, EntityX(Arrow[2] , True), EntityY(Arrow[2] , True), EntityZ(Arrow[2] , True) )
PrjX[2] = ViewMngr.View[ViewMngr.SelectedView].x + ProjectedX() ; PrjY[2] = ViewMngr.View[ViewMngr.SelectedView].y + ProjectedY()
showLines=True
EndIf
End Method
Rem
===========================================================================================
bbdoc: update2D() - ediTable Gizmo
about: update 2D
===========================================================================================
End Rem
Method update2D()
'Projection update!-------------------------------------------------------------------------
SetViewport ViewMngr.View[ViewMngr.SelectedView].x, ViewMngr.View[ViewMngr.SelectedView].y + 32, ViewMngr.View[ViewMngr.SelectedView].W, ViewMngr.View[ViewMngr.SelectedView].h - 64
If(Using > 0)
DrawText "(" + EntityX(SceneMngr.gizmo.entity) + "," + EntityY(SceneMngr.gizmo.entity) + "," + EntityZ(SceneMngr.gizmo.entity) + ")", SceneMngr.gizmo.CX2D - 100, SceneMngr.gizmo.CY2D + 10
EndIf
glEnable(GL_LINE_SMOOTH) 'Quick antaliasing hack
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
glLineWidth(1.0)
If(showLines)
If(ViewMngr.view[ViewMngr.SelectedView].onLeft(PrjX[0],PrjY[0]) Or ViewMngr.view[ViewMngr.SelectedView].onLeft(CX2D, CY2D))
SetColor 255,0,0
DrawText "X", SceneMngr.gizmo.AX2D[0] , SceneMngr.gizmo.AY2D[0]
DrawLine CX2D, CY2D, PrjX[0] , PrjY[0]
EndIf
If(ViewMngr.view[ViewMngr.SelectedView].onLeft(PrjX[1],PrjY[1]) Or ViewMngr.view[ViewMngr.SelectedView].onLeft(CX2D, CY2D))
SetColor 0,255,0
DrawText "Y", SceneMngr.gizmo.AX2D[1] , SceneMngr.gizmo.AY2D[1]
DrawLine CX2D, CY2D, PrjX[1] , PrjY[1]
EndIf
If(ViewMngr.view[ViewMngr.SelectedView].onLeft(PrjX[2],PrjY[2]) Or ViewMngr.view[ViewMngr.SelectedView].onLeft(CX2D, CY2D))
SetColor 0,0,255
DrawText "Z", SceneMngr.gizmo.AX2D[2] , SceneMngr.gizmo.AY2D[2]
DrawLine CX2D, CY2D, PrjX[2] , PrjY[2]
EndIf
EndIf
'backsetting
SetColor 255, 255, 255
glDisable(GL_LINE_SMOOTH)
SetViewport 0,0,ScreenX,ScreenY
End Method
Rem
===========================================================================================
bbdoc: private pickManage() - ediTable Gizmo
about: pickManage
===========================================================================================
End Rem
Method _pickManage(ent:tEntity[] , dir:Int, resMode:String = "MOVE", resUsing:Int = 1)
'----------------------------------------------------
If(PickedEntity() = ent[dir] )
EntityAlpha ent[dir] , 0.2
If(ProgMngr.Mouse.Down[1] ) Then Using = resUsing ; mode = resMode
Else
EntityAlpha ent[dir] , 1
EndIf
End Method
Rem
===========================================================================================
bbdoc: private pickManage_invertFX() - ediTable Gizmo
about: pickManage variant
===========================================================================================
End Rem
Method _pickManage_invertFX(ent:tEntity[] , dir:Int, resMode:String = "MOVE", resUsing:Int = 1)
'----------------------------------------------------
If(PickedEntity() = ent[dir] )
EntityAlpha ent[dir] , 0.8
If(ProgMngr.Mouse.Down[1] ) Then Using = resUsing ; mode = resMode
Else
EntityAlpha ent[dir] , 0.4
EndIf
End Method
EndType
but is a bit messed up and have a lot of references to other class of program..