• Check out the results of the Techtree Contest #19!
  • Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.
  • Create a void inspired texture for Warcraft 3 and enter Hive's 34th Texturing Contest: Void! Click here to enter!
  • The Hive's 22nd Icon Contest: Creep Abilities is now concluded, time to vote for your favourite set of icons! Click here to vote!

UICamera

Level 19
Joined
Mar 18, 2012
Messages
1,716

UICamera


Handles the camerasetup, while viewing a custom UI.


SCREEN_WIDTH and SCREEN_HEIGHT are empirical values
and may not work for other screen resolution than mine.
If this is the case, there is not much we can do about it.

JASS:
//*  Written by BPower.
library UICamera initializer Init/* v1.0
*************************************************************************************
*
*    Adjusts the camera setup while viewing a UIScreen.
*
*************************************************************************************
*
*   */ uses /*
*  
*       */ UIBasic  /* 
*
************************************************************************************
*
*   Import instruction:
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*       Copy the UICamera script into your map.
*/

	globals
		//*  Constants:
		//*  ==========
		private constant timer TIMER               = CreateTimer()
		private constant real  UPDATE_CAMERA       = (1./32.)
        private constant real  SCREEN_WIDTH        = 1.632//*  Empirical values.
        private constant real  SCREEN_HEIGHT       = 0.906
	endglobals

	globals
		//*  Data structure:
		//*  ===============
		private integer array stack
		private integer       size  = 0

		//*  Variables:
		//*  ==========
		private camerasetup array camera
		private unit        array dummy
		private real        array resetX 
		private real        array resetY
		private real        array update
	endglobals

	private function SetCameraTargetDistance takes integer index, real width, real height, real time returns nothing
        local real d = RMaxBJ(width*SCREEN_HEIGHT, height*SCREEN_WIDTH)
        call CameraSetupSetField(camera[index], CAMERA_FIELD_TARGET_DISTANCE, d, time)
    endfunction

	//*  The stack has a lookup speed of O(n).
    //* This is utterly acceptable as the maximum 
    //* stack size is bj_MAX_PLAYERS, which equals 12.
	private function Get takes player p returns integer
		local integer index = 0
		local integer id    = GetPlayerId(p)
		loop
			exitwhen (index == size)
			if (id == stack[index]) then
				return index
			endif 
			set index = index + 1
		endloop
		return -1
	endfunction

	private function OnPeriodic takes nothing returns nothing
		local integer index = 0
		local integer id
		loop
			exitwhen index == size
			set id = stack[index]
			if GetLocalClient() == Player(id) then
				call CameraSetupApplyForceDuration(camera[id], true, 0.)
				call SetCameraTargetController(dummy[id], 0., 0., false)
			endif
			set index = index + 1
		endloop
	endfunction
    
    //*  Push to stack:
    //*  ==============
    private function Push takes integer id returns nothing
        if (0 == size) then
            call TimerStart(TIMER, UPDATE_CAMERA, true, function OnPeriodic)
        endif
        set stack[size] = id
        set size        = size + 1

		//*  Camera position natives have a internal delay of ~0.05.
        //* In multiplayer seasons it's probably more.
        //* We don't not want to end up between to windows.
        if (update[id] < TimerGetElapsed(UI_STAMP) - 0.5) then
            //*  Always returns coordinates for a local client.
            set resetX[id]  = GetCameraTargetPositionX()
            set resetY[id]  = GetCameraTargetPositionY()
        endif
    endfunction

	function UI_StopCamera takes player p returns nothing
		local integer index = Get(p)
		local integer id    = GetPlayerId(p)
		if (-1 != index) then
			set size 		 = size - 1
			set stack[index] = stack[size]
			if (0 == size) then
				call PauseTimer(TIMER)
			endif

	        if (GetLocalClient() == p) then
                call SetCameraBoundsToRect(bj_mapInitialCameraBounds)
            	call SetCameraTargetController(null, 0., 0., false)
            	call CameraSetSmoothingFactor(1.)
            	call ResetToGameCamera(0.)
            	call SetCameraPosition(resetX[id], resetY[id])
        	endif

        	//*  Bug fix:
        	//*  ========
            set update[id] = TimerGetElapsed(UI_STAMP)
		//*  Only in DEBUG_MODE:
		debug else 
			debug call ThrowWarning((true), "UICamera", "UI_StopCamera", "index", -1, GetPlayerName(p) + " was not found in the stack!")
		endif
	endfunction
	
	function UI_StartCamera takes player p, real originX, real originY, real width, real height returns nothing
		local integer id   = GetPlayerId(p)
        local real    x    = originX + width*.5
        local real    y    = originY + height*.5
        local real    maxX = originX + width
        local real    maxY = originY + height
		if (IsPlayerUser(p)) then

			//*  If the player is not in the stack
			//* function Get will return -1.
			if (-1 == Get(p)) then
                call Push(id)
			endif
            //*  Set camerasetup:
			//*  ================
       		call SetCameraTargetDistance(id, width, height, 0.)
        	call SetUnitX(dummy[id], x)
        	call SetUnitY(dummy[id], y)
        	if (GetLocalClient() == p) then
                call SetCameraBounds(originX, originY, originX, maxY, maxX, maxY, maxX, originY)
            	call CameraSetupSetDestPosition(camera[id], x, y, 0.)
            	call CameraSetSmoothingFactor(0.)
            	call CameraSetupApplyForceDuration(camera[id], true, 0.)
            	call SetCameraTargetController(dummy[id], 0., 0., false)
        	endif

		//*  Only in DEBUG_MODE:
		debug else
			debug call ThrowWarning(true, "UICamera", "UI_StartCamera", "p", 0, GetPlayerName(p) + " is a computer player! Only non-computer players are valid for UI_StartCamera!") 
		endif
	endfunction
	
	private function Init takes nothing returns nothing
        local integer index = 0
        local boolean prev
        loop
            exitwhen (index == bj_MAX_PLAYERS)
            if IsPlayerUser(Player(index)) then
                set prev         = ToogleUnitIndexer(false)
                set dummy[index] = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), UI_CAMERA_DUMMY_ID, 0., 0., 0.)
                call ToogleUnitIndexer(prev)
                //*  In case you don't have those fields set in the object editor.
                call UnitAddAbility(dummy[index], 'Aloc')
                call PauseUnit(dummy[index], true)
                call SetUnitVertexColor(dummy[index], 0, 0, 0, 0)
                set camera[index] = CreateCameraSetup()
                call CameraSetupSetField(camera[index], CAMERA_FIELD_ANGLE_OF_ATTACK, 270., 0.)
                call CameraSetupSetField(camera[index], CAMERA_FIELD_ROLL,            0.,   0.)
                call CameraSetupSetField(camera[index], CAMERA_FIELD_ROTATION,        90.,  0.)
                
                //*  Only in DEBUG_MODE:
                debug call ThrowError((GetUnitTypeId(dummy[index]) == 0), "UICamera", "Init", "dummy", index, "Unable to create a camera dummy. Invalid id for 'UI_CAMERA_DUMMY_ID' in UIBasic!")
            endif
            set index = index + 1
        endloop
	endfunction

endlibrary
Last edited:
Back
Top