library PanelCamera
/*
~ Panel Camera Regulator ~
A complementary system for the panel system. Required in
order to let it reposition itself accurately. It works just
like the native camera, with some hotfixes of course.
By using this, default camera scrolling (mouse & keyboard) will be
disabled. Camera field roll and field of view isn't allowed to be
modified as well. And you are only allowed to use some specific
camera related functions which will be specified below. Deal with it.
I. API
function RefreshCamera takes nothing returns nothing
- Call this everytime you update the camera
function SetCameraFieldEx takes camerafield whichField, real value, real duration returns nothing
- This is a replacement of native SetCameraField
- You can still use the native ones but you can use this instead if you need some extra speed
function RegisterOnCameraRefreshEvent takes code func return triggercondition
function UnregisterOnCameraRefreshEvent takes triggercondition cond return nothing
- (Un)register a function to be executed everytime camera is done refreshing
II. Extra notes
So far you may only use these native and BJ functions:
- SetCameraField
- SetCameraFieldForPlayer [GUI]
- SetCameraPosition
- PanCameraTo
- PanCameraToTimed
- PanCameraToTimedLocForPlayer [GUI]
- CameraSetSmoothingFactor
- CameraSetupApply
- CameraSetupApplyForceDuration
- CameraSetupApplyForPlayer [GUI]
- SetCameraTargetController
- SetCameraTargetControllerNoZForPlayer[GUI]
Just let me know if you need more functions to be supported.
Function call replacements:
(Variable name) = (Replaced function)
LocX = GetCameraTargetPositionX()
LocY = GetCameraTargetPositionY()
ZOffset = CAMERA_FIELD_ZOFFSET / GetCameraTargetPositionZ()
AngleOfAttack = CAMERA_FIELD_ANGLE_OF_ATTACK
CameraFarZ = CAMERA_FIELD_FARZ
Rotation = CAMERA_FIELD_ROTATION
TargetDistance = CAMERA_FIELD_TARGET_DISTANCE
*/
////////////////////
// Configurations //
////////////////////
globals
// Minimum value difference that will be processed by the system
// Must be a positive value
private constant real TOLERANCE = 0.1
// Lower value makes the camera looks smoother but will cause the system
// to work significantly harder
private constant real INTERVAL = 0.03125
endglobals
//////////////////
// System codes //
//////////////////
globals
public real LocX = 0
public real LocY = 0
public real ZOffset = 0
public real TargetDistance = bj_CAMERA_DEFAULT_DISTANCE
public real Rotation = bj_CAMERA_DEFAULT_ROTATION*bj_DEGTORAD
public real AngleOfAttack = bj_CAMERA_DEFAULT_AOA*bj_DEGTORAD
private real LocXTarget = LocX
private real LocYTarget = LocY
private real TargetDistanceTarget = TargetDistance
private real RotationTarget = Rotation
private real AngleOfAttackTarget = AngleOfAttack
private real ZOffsetTarget = ZOffset
private real LocXRate = 0.0
private real LocYRate = 0.0
private real ZOffsetRate = 0.0
private real TargetDistanceRate = 0.0
private real RotationRate = 0.0
private real AngleOfAttackRate = 0.0
private unit CameraMan
private player Locale
private boolean Boole = false
private boolean Notify = true
private timer CamTimer = CreateTimer()
private timer StopTimer = CreateTimer()
private trigger Trigg = CreateTrigger()
private constant real HP = bj_PI/2
private constant real TAU = bj_PI*2
endglobals
private function AngularDifference takes real a, real b returns real
return RAbsBJ(Atan2(Sin(a-b), Cos(a-b)))
endfunction
function RefreshCamera takes nothing returns nothing
set Boole = true
call SetCameraField(CAMERA_FIELD_ROLL, 0, 0)
call SetCameraField(CAMERA_FIELD_FIELD_OF_VIEW, bj_CAMERA_DEFAULT_FOV, 0)
call SetCameraField(CAMERA_FIELD_ROTATION, Rotation*bj_RADTODEG, 0)
call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, AngleOfAttack*bj_RADTODEG, 0)
call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, TargetDistance, 0)
call SetCameraField(CAMERA_FIELD_ZOFFSET, ZOffset, 0)
call SetCameraTargetController(CameraMan, LocX, LocY, false)
set Boole = false
endfunction
private function FireEvent takes nothing returns nothing
if Notify then
call RefreshCamera()
call TriggerEvaluate(Trigg)
endif
endfunction
private function onTick takes nothing returns nothing
set Notify = false
if Rotation != RotationTarget then
if Cos(Rotation-RotationTarget) <= Cos(RotationRate) then
if Sin(RotationTarget-Rotation) >= 0 then
set Rotation = Rotation + RotationRate
else
set Rotation = Rotation - RotationRate
endif
else
set Rotation = RotationTarget
endif
set Notify = true
endif
if AngleOfAttack != AngleOfAttackTarget then
if Cos(AngleOfAttack-AngleOfAttackTarget) <= Cos(AngleOfAttackRate) then
if Sin(AngleOfAttackTarget-AngleOfAttack) >= 0 then
set AngleOfAttack = AngleOfAttack + AngleOfAttackRate
else
set AngleOfAttack = AngleOfAttack - AngleOfAttackRate
endif
else
set AngleOfAttack = AngleOfAttackTarget
endif
set Notify = true
endif
if TargetDistance != TargetDistanceTarget then
if RAbsBJ(TargetDistance-TargetDistanceTarget) <= RAbsBJ(TargetDistanceRate) then
set TargetDistance = TargetDistanceTarget
else
set TargetDistance = TargetDistance + TargetDistanceRate
endif
set Notify = true
endif
if ZOffset != ZOffsetTarget then
if RAbsBJ(ZOffset-ZOffsetTarget) <= RAbsBJ(ZOffsetRate) then
set ZOffset = ZOffsetTarget
else
set ZOffset = ZOffset + ZOffsetRate
endif
set Notify = true
endif
if LocX != LocXTarget then
if RAbsBJ(LocX-LocXTarget) <= RAbsBJ(LocXRate) then
set LocX = LocXTarget
else
set LocX = LocX + LocXRate
endif
set Notify = true
endif
if LocY != LocYTarget then
if RAbsBJ(LocY-LocYTarget) <= RAbsBJ(LocYRate) then
set LocY = LocYTarget
else
set LocY = LocY + LocYRate
endif
set Notify = true
endif
call FireEvent()
set Notify = true
endfunction
function SetCameraFieldEx takes camerafield whichField, real value, real duration returns nothing
if whichField == CAMERA_FIELD_ROTATION then
if AngularDifference(Rotation, value*bj_DEGTORAD) > TOLERANCE*bj_DEGTORAD then
set RotationTarget = value*bj_DEGTORAD
if duration <= 0 then
set Rotation = RotationTarget
call FireEvent()
else
set RotationRate = AngularDifference(Rotation, RotationTarget)/duration*INTERVAL
endif
endif
elseif whichField == CAMERA_FIELD_ANGLE_OF_ATTACK then
if AngularDifference(AngleOfAttack, value*bj_DEGTORAD) > TOLERANCE*bj_DEGTORAD then
set AngleOfAttackTarget = value*bj_DEGTORAD
if duration <= 0 then
set AngleOfAttack = AngleOfAttackTarget
call FireEvent()
else
set AngleOfAttackRate = AngularDifference(AngleOfAttack, AngleOfAttackTarget)/duration*INTERVAL
endif
endif
elseif whichField == CAMERA_FIELD_TARGET_DISTANCE then
if RAbsBJ(TargetDistance-value) > TOLERANCE then
set TargetDistanceTarget = value
if duration <= 0 then
set TargetDistance = value
call FireEvent()
else
set TargetDistanceRate = (value-TargetDistance)/duration*INTERVAL
endif
endif
elseif whichField == CAMERA_FIELD_ZOFFSET then
if RAbsBJ(ZOffset-value) > TOLERANCE then
set ZOffsetTarget = value
if duration <= 0 then
set ZOffset = value
call FireEvent()
else
set ZOffsetRate = (value-ZOffset)/duration*INTERVAL
endif
endif
endif
endfunction
private function SetCameraFieldCatcher takes camerafield whichField, real value, real duration returns nothing
if not Boole then
call SetCameraFieldEx(whichField, value, duration)
endif
endfunction
private function SetCameraFieldForPlayerEx takes player whichPlayer, camerafield whichField, real value, real duration returns nothing
if Locale == whichPlayer then
call SetCameraFieldEx(whichField, value, duration)
endif
endfunction
private function SetCameraPositionEx takes real x, real y returns nothing
set LocX = x
set LocY = y
set LocXTarget = x
set LocYTarget = y
call FireEvent()
endfunction
private function PanCameraToTimedEx takes real x, real y, real duration returns nothing
local boolean updateX = RAbsBJ(LocX-x) > TOLERANCE
local boolean updateY = RAbsBJ(LocY-y) > TOLERANCE
if updateX or updateY then
if duration <= 0 then
call SetCameraPositionEx(x, y)
else
if updateX then
set LocXTarget = x
set LocXRate = (x-LocX)/duration*INTERVAL
endif
if updateY then
set LocYTarget = y
set LocYRate = (y-LocY)/duration*INTERVAL
endif
endif
endif
endfunction
private function PanCameraToTimedLocForPlayerEx takes player whichPlayer, location loc, real duration returns nothing
if Locale == whichPlayer then
call PanCameraToTimedEx(GetLocationX(loc), GetLocationY(loc), duration)
endif
endfunction
private function CameraSetupApplyForceDurationEx takes camerasetup whichSetup, boolean doPan, real forceDuration returns nothing
call SetCameraFieldEx(CAMERA_FIELD_ANGLE_OF_ATTACK, CameraSetupGetField(whichSetup, CAMERA_FIELD_ANGLE_OF_ATTACK), forceDuration)
call SetCameraFieldEx(CAMERA_FIELD_FARZ, CameraSetupGetField(whichSetup, CAMERA_FIELD_FARZ), forceDuration)
call SetCameraFieldEx(CAMERA_FIELD_FIELD_OF_VIEW, CameraSetupGetField(whichSetup, CAMERA_FIELD_FIELD_OF_VIEW), forceDuration)
call SetCameraFieldEx(CAMERA_FIELD_ROLL, CameraSetupGetField(whichSetup, CAMERA_FIELD_ROLL), forceDuration)
call SetCameraFieldEx(CAMERA_FIELD_ROTATION, CameraSetupGetField(whichSetup, CAMERA_FIELD_ROTATION), forceDuration)
call SetCameraFieldEx(CAMERA_FIELD_TARGET_DISTANCE, CameraSetupGetField(whichSetup, CAMERA_FIELD_TARGET_DISTANCE), forceDuration)
call SetCameraFieldEx(CAMERA_FIELD_ZOFFSET, CameraSetupGetField(whichSetup, CAMERA_FIELD_ZOFFSET), forceDuration)
if doPan then
call SetCameraPositionEx(CameraSetupGetDestPositionX(whichSetup), CameraSetupGetDestPositionY(whichSetup))
endif
endfunction
private function CameraSetupApplyEx takes camerasetup whichSetup, boolean doPan, boolean panTimed returns nothing
call CameraSetupApplyForceDurationEx(whichSetup, doPan, 0)
endfunction
private function CameraSetupApplyForPlayerEx takes boolean doPan, camerasetup whichSetup, player whichPlayer, real duration returns nothing
if Locale == whichPlayer then
call CameraSetupApplyForceDurationEx(whichSetup, doPan, duration)
endif
endfunction
private function CameraSetSmoothingFactorEx takes real factor returns nothing
if not Boole then
set Boole = true
call CameraSetSmoothingFactor(0)
set Boole = false
endif
endfunction
private function SetCameraTargetControllerEx takes unit whichUnit, real xoffset, real yoffset, boolean inheritOrientation returns nothing
if not Boole then
set Boole = true
call SetCameraTargetController(CameraMan, LocX, LocY, false)
set Boole = false
endif
endfunction
private function SetCameraTargetControllerNoZForPlayerEx takes player whichPlayer, unit whichUnit, real xoffset, real yoffset, boolean inheritOrientation returns nothing
if Locale == whichPlayer then
call SetCameraTargetControllerEx(CameraMan, LocX, LocY, false)
endif
endfunction
hook SetCameraField SetCameraFieldCatcher
hook SetCameraFieldForPlayer SetCameraFieldForPlayerEx
hook SetCameraPosition SetCameraPositionEx
hook PanCameraTo SetCameraPositionEx
hook PanCameraToTimed PanCameraToTimedEx
hook PanCameraToTimedLocForPlayer PanCameraToTimedLocForPlayerEx
hook CameraSetSmoothingFactor CameraSetSmoothingFactorEx
hook CameraSetupApply CameraSetupApplyEx
hook CameraSetupApplyForceDuration CameraSetupApplyForceDurationEx
hook CameraSetupApplyForPlayer CameraSetupApplyForPlayerEx
hook SetCameraTargetController SetCameraTargetControllerEx
hook SetCameraTargetControllerNoZForPlayer SetCameraTargetControllerNoZForPlayerEx
function RegisterOnCameraRefreshEvent takes code func returns triggercondition
return TriggerAddCondition(Trigg, Condition(func))
endfunction
function UnregisterOnCameraRefreshEvent takes triggercondition cond returns nothing
call TriggerRemoveCondition(Trigg, cond)
endfunction
private module InitModule
private static method onInit takes nothing returns nothing
call init()
endmethod
endmodule
private struct Initializer
private static method init takes nothing returns nothing
set Locale = GetLocalPlayer()
set CameraMan = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'hpea', 0, 0, 0)
call SetUnitPathing(CameraMan, false)
call PauseUnit(CameraMan, true)
call ShowUnit(CameraMan, false)
call SetUnitX(CameraMan, 0)
call SetUnitY(CameraMan, 0)
call SetCameraTargetController(CameraMan, LocX, LocY, false)
call TimerStart(CamTimer, INTERVAL, true, function onTick)
call FireEvent()
endmethod
implement InitModule
endstruct
endlibrary