#include once "WorldSim3D.bi"

'declare sub CheckVideoDriver(byval driver as wDriverTypes)
/'
sub CheckVideoDriver(byval driver as wDriverTypes)
	if not wSystemIsDriverSupported(driver) then
		PrintWithColor("Sorry. This video driver is not supported..",wCFC_RED)
		end
	end if
	cls
end sub
'/

'///Custom utils
declare sub CheckFilePath(byval path as ZString ptr)

declare sub PrintWithColor(byval text as ZString ptr,_
							byval color1 as wConsoleFontColor=wCFC_RED,_
							byval waitKey as Boolean=false)

'///Quake map utils
declare sub ParseQuakeMap(byval BSPMesh as wMesh)
declare sub SetQuakeShadersVisible(byval value as Boolean)

'///Второй вариант парсинга bsp-карты
declare sub ParseQuakeMap2(byval BSPMesh as wMesh)

'///For load resources
declare function wMeshLoadEx(byval path as zstring ptr)as wMesh

'///For animated meshes
declare sub wMeshesUpdateTangentsAndBinormal()

declare function CreateColorTexture(byval tColor as wColor4s )as wTexture

'///For FPS Camera							
Dim shared as wKeyMap wKeyMapDefault(1 to 8)

wKeyMapDefault(1).Action=wKA_MOVE_FORWARD
wKeyMapDefault(1).KeyCode=wKC_KEY_W

wKeyMapDefault(2).Action=wKA_MOVE_FORWARD
wKeyMapDefault(2).KeyCode=wKC_UP

wKeyMapDefault(3).Action=wKA_MOVE_BACKWARD
wKeyMapDefault(3).KeyCode=wKC_KEY_S

wKeyMapDefault(4).Action=wKA_MOVE_BACKWARD
wKeyMapDefault(4).KeyCode=wKC_DOWN

wKeyMapDefault(5).Action=wKA_STRAFE_LEFT
wKeyMapDefault(5).KeyCode=wKC_KEY_A
	
wKeyMapDefault(6).Action=wKA_STRAFE_LEFT
wKeyMapDefault(6).KeyCode=wKC_LEFT

wKeyMapDefault(7).Action=wKA_STRAFE_RIGHT
wKeyMapDefault(7).KeyCode=wKC_KEY_D

wKeyMapDefault(8).Action=wKA_STRAFE_RIGHT
wKeyMapDefault(8).KeyCode=wKC_RIGHT	

'For nodes
declare sub OutlineNode(byval node as wNode, byval _width as Float32, byval lineColor as wColor4s)					

'Custom physics procedures
declare function CreateBullet(byval speed as Float32,byval texture as wTexture)as wNode

declare function MousePick(byval isPick as Boolean)as Boolean

declare sub CreateGround(byval scale as Float32)

'For sound
declare function wSoundLoadEx(byval pathFile as ZString ptr,_
					          byval extFile as const ZString ptr)as wSound
					          
declare function wSoundBufferLoadEx(byval pathFile as ZString ptr,_
									byval extFile as const ZString ptr)as wSoundBuffer

'For shaders
declare function  ShaderGetMaterialType(byval shader as wShader ptr) as wMaterialTypes

'Normal mapping for bsp
declare sub wMeshPrepareToNormalMapping(byval mesh as wMesh,_
										byval matType as wMaterialTypes=wMT_PARALLAX_MAP_SOLID,_
										byval srcTextureLayer as UInt32=0,_
										byval dstTextureLayer as UInt32=1,_
										byval matParam as Float32=0.0035f,_
										byval amplitude as Float32=9.f,_
										byval blurRadius as Float32=1.5f,_
										byval contrast as Float32=10.f,_
										byval brightness as Int32=60)
'Custom WS3D-array										
type wArray
	public:
	declare function size() as UInt32
	declare function get(byval idx as UInt32)as UInt32 ptr
	declare function getIndex(byval element as UInt32 ptr)as Int32
	declare function add(byval element as UInt32 ptr)as Boolean
	declare function insert(byval element as UInt32 ptr,byval idx as UInt32)as Boolean
	declare function remove(byval element as UInt32 ptr,byval isNodeDestroy as Boolean=false)as Boolean
	declare function remove2(byval idx as UInt32,byval isNodeDestroy as Boolean=false)as Boolean
	declare sub clear(byval isNodeDestroy as Boolean=false)
	private:
	Array as UInt32 ptr ptr
	ArraySize as UInt32=0
end type

'Custom GUI-scrollbar
type wScrollbar
    label as wGuiObject=0
    scroll as wGuiObject=0
    horizontal as Boolean=true
    caption as string=""
    isFloat as Boolean=false
		
    declare sub Init(byval position as wVector2i ,byval size as wVector2i,byval capt as string,byval id as Int32,byval maxValue as Float32,byval currentValue as Float32)
    declare sub setValueAsFloat(byval value as Float32)
    declare function getValueAsFloat()as Float32
    declare sub setValueAsInt(byval value as Int32)
    declare function getValueAsInt()as Int32
    declare sub Draw()
end type
															
'///*********************************************************************///
'///*********************************************************************///
'///*********************************************************************///
'///*********************************************************************///
'///*********************************************************************///
sub CheckFilePath(byval path as ZString ptr)
	if Not wFileIsExist(path) then
		wEngineStop()
		'cls
		dim as Int32 def=wConsoleSaveDefaultColors()
		wConsoleSetFontColor(wCFC_RED)
		print(chr(0))
		print("File << "+*path+" >> not found!"+chr(0))
		wConsoleSetFontColor(wCFC_YELLOW)
		print("Warning! Check the paths to your resources!"+chr(0))
		wConsoleResetColors(def)
		print(chr(0))
		print("Press any key to exit..."+chr(0))
		wInputWaitKey()
		end
	endif
end sub

sub PrintWithColor(byval text as ZString ptr,_
					byval color1 as wConsoleFontColor,_
					byval waitKey as Boolean)
	dim as Int32 def=wConsoleSaveDefaultColors()
	wConsoleSetFontColor(color1)
	print(*text+chr(0))
	wConsoleResetColors(def)	
	if waitKey then
		print(chr(0))
		print("Press any key..."+chr(0))
		wInputWaitKey()
	endif
end sub

'///Вспомогательная процедура
declare sub FindAndSetEntity(byval entityList as UInt32 ptr , byval entityName as ZString ptr)
'///Процедура парсинга BSP-карты
sub ParseQuakeMap(byval BSPMesh as wMesh)

    Dim as UInt32 ptr varGroup=0

    Dim as UInt32 ptr list=wBspGetEntityList(BSPMesh)

    FindAndSetEntity(list, "info_player_start")

    FindAndSetEntity(list, "info_player_deathmatch")

    FindAndSetEntity(list, "misc_model")

    FindAndSetEntity(list, "weapon_plasmagun")

    FindAndSetEntity(list, "weapon_railgun")

    FindAndSetEntity(list, "weapon_rocketlauncher")

    FindAndSetEntity(list, "weapon_shotgun")

    FindAndSetEntity(list, "ammo_rockets")

    FindAndSetEntity(list, "ammo_shells")

end sub

sub FindAndSetEntity(byval entityList as UInt32 ptr , byval entityName as zString ptr)
    Dim as UInt32 ptr varGroup=0
    Dim as wVector2i entityIndex
    '///Для сплайн-аниматора по двум точкам
    Dim as wVector3f points(2)
	'///скорость работы сплайн-аниматора
	Dim as Float32 splineSpeed=1.0f
	'///смещение модели по вертикали
	Dim as Int32 splineDelta=4
    '///для сплайн-аниматора
	Dim as Float32 Tightness=0.5
 	'///Скорость работы rotate-аниматора
	Dim as Float32 rotSpeed=1.5
    Dim as wNode node=0
    Dim as wMesh mesh=0
    '///позиция установки объекта
    Dim as wVector3f position
    '///угол поворота
    Dim as Float32 angle
    '//имя модели
    Dim modelName as string
    Dim as UInt32 parsePos=0
    Dim as Int32 count=0
    Dim as Boolean isModel=TRUE
    Dim as Boolean isWeapon=false
    
    entityIndex=wBspGetEntityIndexByName(entityList,entityName)

    if entityIndex.x=-1 then return

    print("Find and set entity: ")
    print(*entityName)
    print("firstIndex= "+str(entityIndex.x))
    print("lastIndex= "+str(entityIndex.y))

    for i as Int32 =entityIndex.x  to entityIndex.y
         
         varGroup=wBspGetVarGroupByIndex(entityList,i)

         parsePos=0
         
         position=wBspGetVarGroupValueAsVec(varGroup,"origin",parsePos)

		select case *entityName
				case "info_player_start"
					isModel=false

					Dim as wVector2f size=(128.0f,12.0f)
					Dim as wColor4s topColor=(255,255,0,0)
					Dim as wColor4s bottomColor=(255,64,0,0)

					Dim as wNode BillBoard=wBillboardCreateText(position,_
                                                      size,_
                                                      wFontGetDefault(),_
                                                      "PLAYER START",_
                                                      topColor,_
                                                      bottomColor)				
				case "info_player_deathmatch"
					isModel=false
					parsePos=0
					angle=wBspGetVarGroupValueAsFloat(varGroup,"angle",parsePos)

					Dim as wVector2f size=(128.0f,12.0f)
					Dim as wColor4s topColor=(255,64,64,0)
					Dim as wColor4s bottomColor=(255,255,255,0)

					Dim as wNode BillBoard=wBillboardCreateText(position,_
                                                      size,_
                                                      wFontGetDefault(),_
                                                      "PLAYER DEATHMATCH No "+str(count+1),_
                                                      topColor,_
                                                      bottomColor)

					if i=entityIndex.y then
						Dim as Float32 radians=wMathDegToRad(angle)
						Dim as wNode cam=wSceneGetActiveCamera()
						position.y+=10
						wNodeSetPosition(cam,position)
						position.x+=100*sin(radians)
						position.z+=100*cos(radians)
						wCameraSetTarget(cam,position)
						position.x=0
						position.y=0
						position.z=-50
						wNodeMove(cam,position)
					endif
					count+=1				
				case "misc_model"
					modelName=*wBspGetVarGroupValueAsString(varGroup,"model")
				case "weapon_railgun"
					mesh=wMeshLoadEx("models/weapons2/railgun/railgun.md3")
					modelName=*entityName
				case "weapon_plasmagun"
					mesh=wMeshLoadEx("models/weapons2/plasma/plasma.md3")
					modelName=*entityName
				case "weapon_rocketlauncher"
					mesh=wMeshLoadEx("models/weapons2/rocketl/rocketl.md3")
					modelName=*entityName
				case "weapon_shotgun"
					mesh=wMeshLoadEx("models/weapons2/shotgun/shotgun.md3")
					modelName=*entityName
				case "ammo_rockets"
					mesh=wMeshLoadEx("models/powerups/ammo/rocketam.md3")
					modelName=*entityName
				case "ammo_shells"
					mesh=wMeshLoadEx("models/weapons2/shells/m_shell.md3")
					modelName=*entityName
		end select

			if mesh<>0 then node=wNodeCreateFromMesh(mesh)

            if node<>0 then
                wNodeSetPosition(node,position)
                Dim as wVector3f rot=(0,rotSpeed,0)
                wAnimatorRotationCreate(node,rot)

                points(0).x=position.x
                points(0).y=position.y+splineDelta
                points(0).z=position.z
                points(1).x=position.x
                points(1).y=position.y-splineDelta
                points(1).z=position.z
                wAnimatorSplineCreate(node,2,@points(0),1,splineSpeed,Tightness)

                wNodeSetName(node,modelName)

                if *entityName="ammo_shells" then
					dim as wVector3f scale=(5,5,5)
                    wNodeSetScale(node,scale)
                endif
                    
           endif


           if isModel then print(modelName)

          print(chr(0))
          print("Position: "+str(position.x)+" , "+str(position.y)+" , "+str(position.z))
          print("Angle: "+str(angle))

     next i

end sub

'///Вспомогательная процедура
declare sub SetEntityObject(byval _name as const ZString ptr,_
							byval file as ZString ptr,_
							byval position as wVector3f )

'///Другой вариант парсинга BSP-карты
sub ParseQuakeMap2(byval BSPMesh as wMesh)
    Dim as UInt32 ptr varGroup=0

    Dim as UInt32 ptr list=wBspGetEntityList(BSPMesh)
    
    for i as Int32=0 to wBspGetEntityListSize(list)-1
        varGroup=wBspGetVarGroupByIndex(list,i)
        Dim as Const ZString ptr _name=wBspGetVarGroupValueAsString(varGroup,"classname")

         if *_name="info_player_deathmatch" then

             Dim as String tempBuffer="PLAYER DEATHMATCH"
             Dim as wVector3f position=wBspGetVarGroupValueAsVec(varGroup,"origin",0)
             Dim as Float32 angle=wBspGetVarGroupValueAsFloat(varGroup,"angle",0)

             Dim as wVector2f size=(128.0f,12.0f)
             Dim as wColor4s topColor=(255,64,64,0)
             Dim as wColor4s bottomColor=(255,255,255,0)

             Dim as wNode BillBoard=wBillboardCreateText(position,_
                                                      size,_
                                                      wFontGetDefault(),_
                                                      tempBuffer,_
                                                      topColor,_
                                                      bottomColor)
                                                      
              Dim as Float32 radians=wMathDegToRad(angle)
              Dim as wNode cam=wSceneGetActiveCamera()
              position.y+=10
              wNodeSetPosition(cam,position)
              position.x+=100*sin(radians)
              position.z+=100*cos(radians)
              wCameraSetTarget(cam,position)
              
              position.x=0
              position.y=0
              position.z=-50
              wNodeMove(cam,position)
        endif

        if *_name="weapon_plasmagun" then
             Dim as wVector3f position=wBspGetVarGroupValueAsVec(varGroup,"origin",0)
             SetEntityObject("weapon_plasmagun","models/weapons2/plasma/plasma.md3",position)
        endif

        if *_name="weapon_shotgun" then
             Dim as wVector3f position=wBspGetVarGroupValueAsVec(varGroup,"origin",0)
             SetEntityObject("weapon_shotgun","models/weapons2/shotgun/shotgun.md3",position)
        endif

        if *_name="weapon_rocketlauncher" then
             Dim as wVector3f position=wBspGetVarGroupValueAsVec(varGroup,"origin",0)
             SetEntityObject("weapon_rocketlauncher","models/weapons2/rocketl/rocketl.md3",position)
        endif

        if *_name="weapon_railgun" then
             Dim as wVector3f position=wBspGetVarGroupValueAsVec(varGroup,"origin",0)
             SetEntityObject("weapon_railgun","models/weapons2/railgun/railgun.md3",position)
        endif

   next i
end sub


sub SetEntityObject(byval _name as const Zstring ptr,_
					byval file as ZString ptr,_
					byval position as wVector3f)
    Dim as wMesh mesh=0
    Dim as wNode node=0
    Dim as wVector3f points(2)
	Dim as Float32 splineSpeed=1.0f
	Dim as Int32 splineDelta=4
	Dim as Float32 Tightness=0.5
	Dim as Float32 rotSpeed=1.5

    mesh=wMeshLoadEx(file)
    
    if mesh <>0 then node=wNodeCreateFromMesh(mesh)
    if node<>0 then
          wNodeSetPosition(node,position)
          Dim as wVector3f rot=(0,rotSpeed,0)
          wAnimatorRotationCreate(node,rot)

          points(0).x=position.x
          points(0).y=position.y+splineDelta
          points(0).z=position.z
          points(1).x=position.x
          points(1).y=position.y-splineDelta
          points(1).z=position.z
          wAnimatorSplineCreate(node,2,@points(0),1,splineSpeed,Tightness)

          wNodeSetName(node,_name)
       endif
end sub

sub SetQuakeShadersVisible(byval value as Boolean)
    Dim as wNode root=wSceneGetRootNode()
    Dim as UInt32 ptr iter=new UInt32
    Dim as wNode node=wNodeGetFirstChild(root,iter)

    while Not wNodeIsLastChild(root,iter)
        node=wNodeGetNextChild(root,iter)
        if node<>0 then
            if wNodeGetType(node)=wSNT_Q3SHADER_SCENE_NODE then
                wNodeSetVisibility(node,value)
            endif
        end if
    wend
    delete iter
end sub

function wMeshLoadEx(byval path as zstring ptr)as wMesh
    Dim as wMesh mesh=0
    if wSceneIsMeshLoaded(path) then
        mesh=wSceneGetMeshByName(path)
        if mesh<>0 then return mesh
    endif
    
    if wFileIsExist(path) then mesh=wMeshLoad(path)
    
    return mesh
end function

sub wMeshesUpdateTangentsAndBinormal()
	for i as UInt32=0 to wSceneGetMeshesCount()-1
		dim as wMesh mesh=wSceneGetMeshByIndex(i)
		if wMeshGetType(mesh)=wAMT_SKINNED or wAMT_MD2 or wAMT_MD3 or wAMT_MDL_HALFLIFE then
			wMeshUpdateTangentsAndBinormals(mesh)
		endif
	next i
end sub

function CreateColorTexture(byval tColor as wColor4s )as wTexture
    Dim as wTexture t=wTextureCreate("colorTexture",wVECTOR2i_ONE,wCF_A8R8G8B8)
    Dim as UInt32 ptr _lock=wTextureLock(t)
    *_lock=wUtilColor4sToUInt(tColor)
    wTextureUnlock(t)
    return t
end function

sub OutlineNode(byval node as wNode, byval _width as Float32, byval lineColor as wColor4s)
	if node=0 then return
	Dim as Boolean vis=wNodeIsVisible(node)
	wNodeSetVisibility(node,true)
	Dim as UInt32 mCount=wNodeGetMaterialsCount(node)
	type wMaterialInfo
		diffuseColor as wColor4s 
		emissiveColor as wColor4s 
		ambientColor as wColor4s 
		specularColor as wColor4s 
		backfaceCulling as Boolean 
		frontfaceCulling as Boolean 
		thickness as Float32 
		lighting as Boolean 
		wireframe as Boolean 
	end type

   Dim as  wMaterialInfo curMat(mCount)

   Dim as wMaterialInfo matInfo

	matInfo.diffuseColor.alpha = lineColor.alpha : matInfo.diffuseColor.red=lineColor.red 
	matInfo.diffuseColor.green=lineColor.green: matInfo.diffuseColor.blue=lineColor.blue
	
	matInfo.specularColor.alpha = lineColor.alpha : matInfo.specularColor.red=lineColor.red 
	matInfo.specularColor.green=lineColor.green: matInfo.specularColor.blue=lineColor.blue

	matInfo.ambientColor.alpha = lineColor.alpha : matInfo.ambientColor.red=lineColor.red 
	matInfo.ambientColor.green=lineColor.green: matInfo.ambientColor.blue=lineColor.blue
	
	matInfo.emissiveColor.alpha = lineColor.alpha : matInfo.emissiveColor.red=lineColor.red 
	matInfo.emissiveColor.green=lineColor.green: matInfo.emissiveColor.blue=lineColor.blue
	
	matInfo.backfaceCulling = false
	matInfo.frontfaceCulling = true
	matInfo.lighting = true
	matInfo.thickness = _Width
	matInfo.wireframe = true

	for i as Int32 = 0 to mCount-1
		Dim as wMaterial mat = wNodeGetMaterial(node,i)
			curMat(i).diffuseColor      =   wMaterialGetDiffuseColor(mat)
			curMat(i).specularColor     =   wMaterialGetSpecularColor(mat)
			curMat(i).ambientColor      =   wMaterialGetAmbientColor(mat)
			curMat(i).emissiveColor     =   wMaterialGetEmissiveColor(mat)
			curMat(i).thickness         =   wMaterialGetLineThickness(mat)
            curMat(i).wireframe         =   wMaterialGetFlag(mat,wMF_WIREFRAME)
            curMat(i).backfaceCulling   =   wMaterialGetFlag(mat,wMF_BACK_FACE_CULLING)
            curMat(i).frontfaceCulling  =   wMaterialGetFlag(mat,wMF_FRONT_FACE_CULLING)
            curMat(i).lighting          =   wMaterialGetFlag(mat,wMF_LIGHTING)

            wMaterialSetDiffuseColor(mat,matInfo.diffuseColor)
            wMaterialSetSpecularColor(mat,matInfo.specularColor)
            wMaterialSetAmbientColor(mat,matInfo.ambientColor)
            wMaterialSetEmissiveColor(mat,matInfo.emissiveColor)
            wMaterialSetLineThickness(mat,matInfo.thickness)
            wMaterialSetFlag(mat,wMF_WIREFRAME,matInfo.wireframe)
            wMaterialSetFlag(mat,wMF_LIGHTING,matInfo.lighting)
            wMaterialSetFlag(mat,wMF_FRONT_FACE_CULLING,matInfo.frontfaceCulling)
            wMaterialSetFlag(mat,wMF_BACK_FACE_CULLING,matInfo.backfaceCulling)
	next i

	wNodeDraw(node)

    for i as Int32 =0 to mCount-1
        Dim as wMaterial mat = wNodeGetMaterial(node,i)
        wMaterialSetDiffuseColor(mat,curMat(i).diffuseColor)
        wMaterialSetSpecularColor(mat,curMat(i).specularColor)
        wMaterialSetAmbientColor(mat,curMat(i).ambientColor)
        wMaterialSetEmissiveColor(mat,curMat(i).emissiveColor)
        wMaterialSetLineThickness(mat,curMat(i).thickness)
        wMaterialSetFlag(mat,wMF_WIREFRAME,curMat(i).wireframe)
        wMaterialSetFlag(mat,wMF_LIGHTING,curMat(i).lighting)
        wMaterialSetFlag(mat,wMF_FRONT_FACE_CULLING,curMat(i).frontfaceCulling)
        wMaterialSetFlag(mat,wMF_BACK_FACE_CULLING,curMat(i).backfaceCulling)
    next i

	wNodeSetVisibility(node,vis)
end sub

sub CreateGround(byval scale as Float32)
    Dim as wMaterial material=0
	Dim as Int32 matGround=wPhysMaterialCreate()
	wPhysMaterialSetFriction(matGround,matGround,0.9f,0.9f)

	Dim as wNode mesh(6)
	Dim as wNode body(6)
	Dim as wTexture tex=wTextureLoad("../../Assets/Textures/rockwall.bmp")
	Dim as wTexture tex2=wTextureLoad("../../Assets/Textures/brick_1.jpg")
	
	Dim as wVector3f vec1

    '///1
	mesh(0)= wNodeCreateCube(1)
	vec1.x=512*scale: vec1.y=20: vec1.z=1*scale
	wNodeSetScale(mesh(0),vec1)
	vec1.x=0: vec1.y=10: vec1.z=256*scale
	wNodeSetPosition(mesh(0),vec1)
	material=wNodeGetMaterial(mesh(0),0)
	wMaterialSetTexture(material,0,tex2)
	wMaterialSetFlag(material,wMF_LIGHTING,false)
	Dim as wVector2f scaleTex=(4*scale,2*scale)
	wMaterialSetTextureScale(material,0,scaleTex)

	vec1.x=512*scale: vec1.y=20: vec1.z=1*scale
	body(0) = wPhysBodyCreateCube(vec1,0)
	wNodeSetParent(body(0),mesh(0))
	vec1.x=0: vec1.y=10: vec1.z=256*scale
	wNodeSetPosition(body(0),vec1)
	wPhysBodySetMaterial(body(0),matGround)

	'///2
	mesh(1) = wNodeCreateCube(1)
	vec1.x=1*scale: vec1.y=20: vec1.z=512*scale
	wNodeSetScale(mesh(1),vec1)
	vec1.x=256*scale: vec1.y=10: vec1.z=0
	wNodeSetPosition(mesh(1),vec1)
	material=wNodeGetMaterial(mesh(1),0)
	wMaterialSetTexture(material,0,tex2)
	wMaterialSetFlag(material,wMF_LIGHTING,false)
	scaleTex.x=4*scale: scaleTex.y=2*scale
	wMaterialSetTextureScale(material,0,scaleTex)

	vec1.x=1*scale: vec1.y=20: vec1.z=512*scale
	body(1) = wPhysBodyCreateCube(vec1,0)
	wNodeSetParent(body(1),mesh(1))
	vec1.x=256*scale: vec1.y=10: vec1.z=0
	wNodeSetPosition(body(1),vec1)
	wPhysBodySetMaterial(body(1),matGround)

	'///3
	mesh(2) = wNodeCreateCube(1)
	vec1.x=512*scale: vec1.y=20: vec1.z=1*scale
	wNodeSetScale(mesh(2),vec1)
	vec1.x=0: vec1.y=10: vec1.z=-256*scale
	wNodeSetPosition(mesh(2),vec1)
	material=wNodeGetMaterial(mesh(2),0)
	wMaterialSetTexture(material,0,tex2)
	wMaterialSetFlag(material,wMF_LIGHTING,false)
	scaleTex.x=4*scale: scaleTex.y=2*scale
	wMaterialSetTextureScale(material,0,scaleTex)

	vec1.x=512*scale: vec1.y=20: vec1.z=1*scale
	body(2) = wPhysBodyCreateCube(vec1,0)
	wNodeSetParent(body(2),mesh(2))
	vec1.x=0: vec1.y=10: vec1.z=-256*scale
	wNodeSetPosition(body(2),vec1)
	wPhysBodySetMaterial(body(2),matGround)

	'///4
	mesh(3) = wNodeCreateCube(1)
	vec1.x=1*scale: vec1.y=20: vec1.z=512*scale
	wNodeSetScale(mesh(3),vec1)
	vec1.x=-256*scale: vec1.y=10: vec1.z=0
	wNodeSetPosition(mesh(3),vec1)
	material=wNodeGetMaterial(mesh(3),0)
	wMaterialSetTexture(material,0,tex2)
	wMaterialSetFlag(material,wMF_LIGHTING,false)
	scaleTex.x=4*scale: scaleTex.y=2*scale
	wMaterialSetTextureScale(material,0,scaleTex)

	vec1.x=1*scale: vec1.y=20: vec1.z=512*scale
	body(3) = wPhysBodyCreateCube(vec1,0)
	wNodeSetParent(body(3),mesh(3))
	vec1.x=-256*scale: vec1.y=10: vec1.z=0
	wNodeSetPosition(body(3),vec1)
	wPhysBodySetMaterial(body(3),matGround)

	'///5
	mesh(4) = wNodeCreateCube(1)
	vec1.x=512*scale: vec1.y=1: vec1.z=512*scale
	wNodeSetScale(mesh(4),vec1)
	vec1.x=0: vec1.y=0: vec1.z=0
	wNodeSetPosition(mesh(4),vec1)
	material=wNodeGetMaterial(mesh(4),0)
	wMaterialSetTexture(material,0,tex)
	wMaterialSetFlag(material,wMF_LIGHTING,false)
	scaleTex.x=8*scale: scaleTex.y=8*scale
	wMaterialSetTextureScale(material,0,scaleTex)

	vec1.x=512*scale: vec1.y=1: vec1.z=512*scale
	body(4) = wPhysBodyCreateCube(vec1,0)
	wNodeSetParent(body(4),mesh(4))
	vec1.x=0: vec1.y=0: vec1.z=0
	wNodeSetPosition(body(4),vec1)
	wPhysBodySetMaterial(body(4),matGround)

	wPhysBodySetName(body(4),"ground")
	
	wNodeSetName(mesh(4),"ground")

end sub

function wSoundLoadEx(byval pathFile as ZString ptr,byval extFile as const ZString ptr)as wSound
    Dim as wFile snd                      =0
    Dim as Int32  sndLen                  =0
    Dim as Any ptr  sndBuf                =0 
    Dim as wSound sound                   =0
    snd= wFileOpenForRead(pathFile)
    sndLen=wFileGetSize(snd)
    sndBuf=Callocate(sndLen,sizeof(ZString))
    wFileRead(snd,sndBuf,sndLen)
    sound= wSoundLoadFromMemory(wFileGetAbsolutePath(pathFile),Cptr(ZString ptr,sndBuf),sndLen,extFile)
    Deallocate(sndBuf)
    wFileClose(snd)
    return sound
end function

function wSoundBufferLoadEx(byval pathFile as ZString ptr,byval extFile as const ZString ptr)as wSoundBuffer
    Dim as wFile snd                      =0
    Dim as Int32  sndLen                  =0
    Dim as Any ptr  sndBuf                =0 
    Dim as wSoundBuffer soundBuffer       =0
    snd= wFileOpenForRead(pathFile)
    sndLen=wFileGetSize(snd)
    sndBuf=Callocate(sndLen,sizeof(ZString))
    wFileRead(snd,sndBuf,sndLen)
    soundBuffer= wSoundBufferLoadFromMemory(Cptr(ZString ptr,sndBuf),sndLen,extFile)
    Deallocate(sndBuf)
    wFileClose(snd)
    return soundBuffer
end function

'///For shaders
function ShaderGetMaterialType(byval shader as wShader ptr)as wMaterialTypes
    return Cast(wMaterialTypes,shader->material_type)
end function

sub wMeshPrepareToNormalMapping(byval mesh as wMesh,_
								byval matType as wMaterialTypes,_
								byval srcTextureLayer as UInt32,_
								byval dstTextureLayer as UInt32,_
								byval matParam as Float32,_
								byval amplitude as Float32,_
								byval blurRadius as Float32,_
								byval contrast as Float32,_
								byval brightness as Int32)
    if mesh=0 then return
    if wMeshIsEmpty(mesh) then return
    Dim as wMaterial material=0
    Dim as wMeshBuffer meshBuffer=0
    if(srcTextureLayer>6) then srcTextureLayer=6
    if(dstTextureLayer>7) then dstTextureLayer=7
    Dim as UInt32 bufCount=wMeshGetBuffersCount(mesh,0)
    print("")
    print("MeshBuffers count: "+str(bufCount))
    print("")
    
    for i as Int32=0 to bufCount-1
        meshBuffer=wMeshGetBuffer(mesh,0,i)
        material=wMeshBufferGetMaterial(meshBuffer)
        Dim as wTexture texture=wMaterialGetTexture(material,srcTextureLayer)
        if(texture<>0) then
            Dim as string tName=*wTextureGetFullName(texture)
            Print("")
            print("Texture name: "+str(tName))
            Print("")
            Dim as wTexture texture_copy=wTextureCopy(texture,tName+"_copy")
            wTextureSetBrightness(@texture_copy,brightness)
            wTextureSetBlur(@texture_copy,blurRadius)
            wTextureSetContrast(@texture_copy,contrast)
            wTextureMakeNormalMap(texture_copy,amplitude)
            wMaterialSetTexture(material,dstTextureLayer,texture_copy)
        endif
        wMaterialSetTypeParameter(material,matParam)
        wMaterialSetType(material,matType)
    next						
end sub

function CreateBullet(byval speed as Float32,byval texture as wTexture)as wNode

	Dim as wNode camera=wSceneGetActiveCamera()
	if camera=0 then return 0
	Dim as wVector3f target,position
	target=wCameraGetTarget(camera)
	position=wNodeGetAbsolutePosition(camera)

	Dim as wNode bulletNode=wNodeCreateSphere(10.f, 16)
	Dim as wMaterial mat=wNodeGetMaterial(bulletNode,0)
	wMaterialSetFlag(mat,wMF_LIGHTING,false)
	wMaterialSetTexture(mat,0,texture)

	Dim as wVector3f radius=(10,10,10)
	Dim as wNode bulletBody =wPhysBodyCreateSphere(radius,5.f)
	wNodeSetParent(bulletBody,bulletNode)
	wNodeSetPosition(bulletBody,position)
	wPhysBodySetName(bulletBody,"bullet")

	target.x-=position.x
	target.y-=position.y
	target.z-=position.z
	target=wMathVector3fNormalize(target)
	target.x*=speed
	target.y*=speed
	target.z*=speed
	
	wPhysBodySetLinearVelocity(bulletBody,target)
	target.x=wMathRandomRange(-10,10)
	target.y=wMathRandomRange(-10,10)
	target.z=wMathRandomRange(-10,10)
	wPhysBodySetAngularVelocity(bulletBody,target)
	
	return bulletBody
end function


function MousePick(byval isPick as Boolean)as Boolean
	Dim as wVector2i mPos
	wInputGetMousePosition(@mPos)
	Dim as wNode tempNode=wPhysGetBodyPicked(mPos,isPick)
	if tempNode <>0 then
        if isPick then
            if wPhysBodyGetMass(tempNode)>0 then
                wPhysBodyDraw(tempNode)
                return true
            endif
        endif
    endif
    return false
end function

'=================================='
function wArray.size() as UInt32
	return this.ArraySize
end function
'=================================='
function wArray.add(byval element as UInt32 ptr)as Boolean
	if this.ArraySize=0 then
		this.ArraySize=1
		this.Array=CAllocate(this.ArraySize,sizeof(UInt32 ptr))
		if this.Array<>0 then 
			this.Array[0]=element
			return true
		endif
	else
		this.Array=Reallocate(this.Array,(this.ArraySize+1)*sizeof(UInt32 ptr))
		if this.Array<>0 then
			this.ArraySize+=1
			this.Array[ArraySize-1]=element
			return true
		endif
	endif
    return false
end function
'=================================='
function wArray.get(byval idx as UInt32)as UInt32 ptr
    if idx>this.ArraySize-1 then return 0
    return this.Array[idx]
end function
'=================================='
function wArray.getIndex(byval element as UInt32 ptr)as Int32
   for i as Int32 =0 to this.ArraySize-1
      if this.Array[i]=element then return i
   next
   return -1
end function
'=================================='
function wArray.insert(byval element as UInt32 ptr, byval idx as UInt32)as Boolean
    if idx>this.ArraySize-1 then
       return this.add(element)
    else
        Dim as UInt32 ptr ptr temp=Callocate(this.ArraySize+1,sizeof(UInt32 ptr))
        if temp=0 then return false
        for i as Int32 =0 to idx-1
           temp[i]=this.Array[i]
        next
        temp[idx]=element
        for i as Int32 =idx to this.ArraySize-1
            temp[i+1]=Array[i]
        next
        Deallocate(this.Array)
        this.Array=temp
        this.ArraySize+=1
        return true
    endif
end function
'=================================='
function wArray.remove(byval element as UInt32 ptr,byval isNodeDestroy as Boolean=false)as Boolean
    for i as Int32=0 to this.ArraySize-1
        if Array[i]=element then return this.remove2(i,isNodeDestroy)
    next
    return false
end function
'=================================='
function wArray.remove2(byval idx as UInt32,byval isNodeDestroy as Boolean=false)as Boolean
    if idx>this.ArraySize-1 then return false
 
    Dim as UInt32 ptr ptr temp=CAllocate(this.ArraySize-1,sizeof(UInt32 ptr))
 
    if temp=0 then return false
 
    for i as Int32=0 to idx-1
        temp[i]=this.Array[i]
    next
    
    for i as Int32=idx to this.ArraySize-2
        temp[i]=this.Array[i+1]
    next
 
    if isNodeDestroy then
        Dim as wNode node=this.get(idx)
        wNodeDestroy(node)
    endif
 
    Deallocate(Array)
    this.Array=temp
    this.ArraySize-=1
    return true
end function
'=================================='
sub wArray.clear(byval isNodeDestroy as Boolean=false)
    if isNodeDestroy then
       for i as Int32=0 to this.ArraySize-1
          Dim as wNode node=this.get(i)
          wNodeDestroy(node)
       next
    endif
    Deallocate(Array)
    ArraySize=0
end sub

'=================================='
sub wScrollbar.Init(byval position as wVector2i ,byval size as wVector2i,byval capt as string,byval id as Int32,byval maxValue as Float32,byval currentValue as Float32)
    Dim as wVector2i fromPos,toPos
    fromPos.x=position.x
    fromPos.y=position.y
    if this.horizontal then
        toPos.x=fromPos.x+size.x
        toPos.y=fromPos.y+size.y
    else
        toPos.x=fromPos.x+size.y
        toPos.y=fromPos.y+size.x
    endif
    
    if(maxValue<0) then maxValue*=-1
    if(currentValue<0) then currentValue*=-1
    if(currentValue>maxValue) then
        currentValue=maxValue
    endif
    this.caption=capt
    this.scroll=wGuiScrollBarCreate(horizontal,fromPos,toPos)
    if this.isFloat then maxValue*=100
    wGuiScrollBarSetMaxValue(this.scroll,wMathCeil(maxValue))
    wGuiScrollBarSetMinValue(this.scroll,0)
    if(this.isFloat) then currentValue*=100
    wGuiScrollBarSetValue(this.scroll,wMathCeil(currentValue))
    wGuiScrollBarSetSmallStep(this.scroll,1)
    wGuiScrollBarSetLargeStep(this.scroll,1)
    wGuiObjectSetId(this.scroll,id)

    if not this.horizontal then
       Dim as wVector2i temp
       temp.x=toPos.y
       temp.y=toPos.x
       toPos.x=temp.x
       toPos.y=temp.y
    endif
    
    fromPos.y-=30
    toPos.y=fromPos.y+30
    this.label=wGuiLabelCreate(this.caption,fromPos,toPos)
end sub

sub wScrollbar.setValueAsFloat(byval value as Float32)
	wGuiScrollBarSetValue(this.scroll,Cast(Int32,(100*value)))
end sub

function wScrollbar.getValueAsFloat()as Float32
	return Cast(Float32,wGuiScrollBarGetValue(this.scroll)/100.f)
end function

sub wScrollbar.setValueAsInt(byval value as Int32)
	wGuiScrollBarSetValue(this.scroll,value)
end sub

function wScrollbar.getValueAsInt()as Int32
	return wGuiScrollBarGetValue(this.scroll)
end function

sub wScrollbar.Draw()
	Dim as  string text
    if this.isFloat then
        Dim as Float32 value=Cast(Float32,wGuiScrollBarGetValue(this.scroll)/100.f)
        text=this.caption+" ["+str(value)+"]"
    else
        Dim as Int32 value=wGuiScrollBarGetValue(this.scroll)
        text=this.caption+" ["+str(Cast(Int32,value))+"]"
    endif

    wGuiObjectSetText(this.label,text)
    wGuiObjectDraw(this.label)
    wGuiObjectDraw(this.scroll)
end sub
