2014-02-10 02:10:30 +01:00
/*************************************************************************/
/* timer.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 14:16:55 +02:00
/* https://godotengine.org */
2014-02-10 02:10:30 +01:00
/*************************************************************************/
2021-01-01 20:13:46 +01:00
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
2014-02-10 02:10:30 +01:00
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
2018-01-05 00:50:27 +01:00
2014-02-10 02:10:30 +01:00
# include "timer.h"
2018-09-11 18:13:45 +02:00
# include "core/engine.h"
2017-08-19 01:02:56 +02:00
2014-02-10 02:10:30 +01:00
void Timer : : _notification ( int p_what ) {
2017-03-05 16:44:50 +01:00
switch ( p_what ) {
2014-02-10 02:10:30 +01:00
case NOTIFICATION_READY : {
2014-10-12 07:13:22 +02:00
if ( autostart ) {
2014-10-14 06:01:25 +02:00
# ifdef TOOLS_ENABLED
2021-05-05 12:44:11 +02:00
if ( Engine : : get_singleton ( ) - > is_editor_hint ( ) & & get_tree ( ) - > get_edited_scene_root ( ) & & ( get_tree ( ) - > get_edited_scene_root ( ) = = this | | get_tree ( ) - > get_edited_scene_root ( ) - > is_a_parent_of ( this ) ) ) {
2014-10-12 07:13:22 +02:00
break ;
2021-05-05 12:44:11 +02:00
}
2014-12-07 06:04:20 +01:00
# endif
start ( ) ;
2017-03-05 16:44:50 +01:00
autostart = false ;
2014-10-12 07:13:22 +02:00
}
2014-02-10 02:10:30 +01:00
} break ;
2017-01-10 22:02:19 +01:00
case NOTIFICATION_INTERNAL_PROCESS : {
2020-11-20 00:28:40 +01:00
if ( ! processing | | timer_process_mode = = TIMER_PROCESS_PHYSICS | | ! is_processing_internal ( ) ) {
2015-05-01 16:44:02 +02:00
return ;
2020-11-20 00:28:40 +01:00
}
2014-02-10 02:10:30 +01:00
time_left - = get_process_delta_time ( ) ;
2017-03-05 16:44:50 +01:00
if ( time_left < 0 ) {
2021-05-05 12:44:11 +02:00
if ( ! one_shot ) {
2017-04-05 08:22:41 +02:00
time_left + = wait_time ;
2021-05-05 12:44:11 +02:00
} else {
2014-02-10 02:10:30 +01:00
stop ( ) ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
emit_signal ( " timeout " ) ;
}
} break ;
2017-09-30 16:19:07 +02:00
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS : {
2020-11-20 00:28:40 +01:00
if ( ! processing | | timer_process_mode = = TIMER_PROCESS_IDLE | | ! is_physics_processing_internal ( ) ) {
2015-05-10 16:00:26 +02:00
return ;
2020-11-20 00:28:40 +01:00
}
2017-09-30 16:19:07 +02:00
time_left - = get_physics_process_delta_time ( ) ;
2015-05-10 16:00:26 +02:00
2017-03-05 16:44:50 +01:00
if ( time_left < 0 ) {
2021-05-05 12:44:11 +02:00
if ( ! one_shot ) {
2017-04-05 08:22:41 +02:00
time_left + = wait_time ;
2021-05-05 12:44:11 +02:00
} else {
2015-05-10 16:00:26 +02:00
stop ( ) ;
2021-05-05 12:44:11 +02:00
}
2015-05-10 16:00:26 +02:00
emit_signal ( " timeout " ) ;
}
} break ;
2014-02-10 02:10:30 +01:00
}
}
void Timer : : set_wait_time ( float p_time ) {
2019-08-08 22:11:48 +02:00
ERR_FAIL_COND_MSG ( p_time < = 0 , " Time should be greater than zero. " ) ;
2017-03-05 16:44:50 +01:00
wait_time = p_time ;
2021-10-09 11:36:03 +02:00
update_configuration_warning ( ) ;
2014-02-10 02:10:30 +01:00
}
float Timer : : get_wait_time ( ) const {
return wait_time ;
}
void Timer : : set_one_shot ( bool p_one_shot ) {
2017-03-05 16:44:50 +01:00
one_shot = p_one_shot ;
2014-02-10 02:10:30 +01:00
}
bool Timer : : is_one_shot ( ) const {
return one_shot ;
}
void Timer : : set_autostart ( bool p_start ) {
2017-03-05 16:44:50 +01:00
autostart = p_start ;
2014-02-10 02:10:30 +01:00
}
bool Timer : : has_autostart ( ) const {
return autostart ;
}
2018-04-26 21:42:50 +02:00
void Timer : : start ( float p_time ) {
2019-11-27 16:34:54 +01:00
ERR_FAIL_COND_MSG ( ! is_inside_tree ( ) , " Timer was not added to the SceneTree. Either add it or set autostart to true. " ) ;
2019-09-01 01:25:22 +02:00
2018-04-26 21:42:50 +02:00
if ( p_time > 0 ) {
set_wait_time ( p_time ) ;
}
2017-03-05 16:44:50 +01:00
time_left = wait_time ;
2015-05-10 16:00:26 +02:00
_set_process ( true ) ;
2014-02-10 02:10:30 +01:00
}
void Timer : : stop ( ) {
2017-03-05 16:44:50 +01:00
time_left = - 1 ;
2015-05-10 16:00:26 +02:00
_set_process ( false ) ;
2017-03-05 16:44:50 +01:00
autostart = false ;
2014-02-10 02:10:30 +01:00
}
2017-03-11 18:10:01 +01:00
void Timer : : set_paused ( bool p_paused ) {
2021-05-05 12:44:11 +02:00
if ( paused = = p_paused ) {
2016-03-31 23:23:16 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2016-03-31 23:23:16 +02:00
2017-03-11 18:10:01 +01:00
paused = p_paused ;
2016-03-31 23:23:16 +02:00
_set_process ( processing ) ;
}
2017-03-11 18:10:01 +01:00
bool Timer : : is_paused ( ) const {
return paused ;
}
bool Timer : : is_stopped ( ) const {
return get_time_left ( ) < = 0 ;
2016-03-31 23:23:16 +02:00
}
2014-02-10 02:10:30 +01:00
float Timer : : get_time_left ( ) const {
2017-03-05 16:44:50 +01:00
return time_left > 0 ? time_left : 0 ;
2014-02-10 02:10:30 +01:00
}
2015-05-10 16:00:26 +02:00
void Timer : : set_timer_process_mode ( TimerProcessMode p_mode ) {
2021-05-05 12:44:11 +02:00
if ( timer_process_mode = = p_mode ) {
2015-05-10 16:00:26 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2015-05-10 16:00:26 +02:00
switch ( timer_process_mode ) {
2017-09-30 16:19:07 +02:00
case TIMER_PROCESS_PHYSICS :
if ( is_physics_processing_internal ( ) ) {
set_physics_process_internal ( false ) ;
2017-01-10 22:02:19 +01:00
set_process_internal ( true ) ;
2015-05-10 16:00:26 +02:00
}
2017-03-05 16:44:50 +01:00
break ;
2015-05-10 16:00:26 +02:00
case TIMER_PROCESS_IDLE :
2017-01-10 22:02:19 +01:00
if ( is_processing_internal ( ) ) {
set_process_internal ( false ) ;
2017-09-30 16:19:07 +02:00
set_physics_process_internal ( true ) ;
2015-05-10 16:00:26 +02:00
}
2017-03-05 16:44:50 +01:00
break ;
2015-05-10 16:00:26 +02:00
}
timer_process_mode = p_mode ;
}
2017-03-05 16:44:50 +01:00
Timer : : TimerProcessMode Timer : : get_timer_process_mode ( ) const {
2015-05-10 16:00:26 +02:00
return timer_process_mode ;
}
2017-03-05 16:44:50 +01:00
void Timer : : _set_process ( bool p_process , bool p_force ) {
2015-05-10 16:00:26 +02:00
switch ( timer_process_mode ) {
2021-05-04 14:35:44 +02:00
case TIMER_PROCESS_PHYSICS :
set_physics_process_internal ( p_process & & ! paused ) ;
break ;
case TIMER_PROCESS_IDLE :
set_process_internal ( p_process & & ! paused ) ;
break ;
2015-05-10 16:00:26 +02:00
}
2016-03-31 23:23:16 +02:00
processing = p_process ;
2015-05-10 16:00:26 +02:00
}
2014-02-10 02:10:30 +01:00
2021-10-09 11:36:03 +02:00
String Timer : : get_configuration_warning ( ) const {
String warning = Node : : get_configuration_warning ( ) ;
if ( wait_time < 0.05 - CMP_EPSILON ) {
if ( warning ! = String ( ) ) {
warning + = " \n \n " ;
}
warning + = TTR ( " Very low timer wait times (< 0.05 seconds) may behave in significantly different ways depending on the rendered or physics frame rate. \n Consider using a script's process loop instead of relying on a Timer for very low wait times. " ) ;
}
return warning ;
}
2014-02-10 02:10:30 +01:00
void Timer : : _bind_methods ( ) {
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_wait_time " , " time_sec " ) , & Timer : : set_wait_time ) ;
ClassDB : : bind_method ( D_METHOD ( " get_wait_time " ) , & Timer : : get_wait_time ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_one_shot " , " enable " ) , & Timer : : set_one_shot ) ;
ClassDB : : bind_method ( D_METHOD ( " is_one_shot " ) , & Timer : : is_one_shot ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_autostart " , " enable " ) , & Timer : : set_autostart ) ;
ClassDB : : bind_method ( D_METHOD ( " has_autostart " ) , & Timer : : has_autostart ) ;
2014-02-10 02:10:30 +01:00
2018-04-26 21:42:50 +02:00
ClassDB : : bind_method ( D_METHOD ( " start " , " time_sec " ) , & Timer : : start , DEFVAL ( - 1 ) ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " stop " ) , & Timer : : stop ) ;
2014-02-10 02:10:30 +01:00
2017-03-11 18:10:01 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_paused " , " paused " ) , & Timer : : set_paused ) ;
ClassDB : : bind_method ( D_METHOD ( " is_paused " ) , & Timer : : is_paused ) ;
ClassDB : : bind_method ( D_METHOD ( " is_stopped " ) , & Timer : : is_stopped ) ;
2016-03-31 23:23:16 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_time_left " ) , & Timer : : get_time_left ) ;
2014-02-10 02:10:30 +01:00
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_timer_process_mode " , " mode " ) , & Timer : : set_timer_process_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " get_timer_process_mode " ) , & Timer : : get_timer_process_mode ) ;
2015-05-10 16:00:26 +02:00
2017-03-05 16:44:50 +01:00
ADD_SIGNAL ( MethodInfo ( " timeout " ) ) ;
2014-02-10 02:10:30 +01:00
2017-10-21 16:28:08 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " process_mode " , PROPERTY_HINT_ENUM , " Physics,Idle " ) , " set_timer_process_mode " , " get_timer_process_mode " ) ;
2019-12-28 22:27:38 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : REAL , " wait_time " , PROPERTY_HINT_EXP_RANGE , " 0.001,4096,0.001,or_greater " ) , " set_wait_time " , " get_wait_time " ) ;
2017-03-05 16:44:50 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " one_shot " ) , " set_one_shot " , " is_one_shot " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " autostart " ) , " set_autostart " , " has_autostart " ) ;
2018-01-11 23:35:12 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " paused " , PROPERTY_HINT_NONE , " " , 0 ) , " set_paused " , " is_paused " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : REAL , " time_left " , PROPERTY_HINT_NONE , " " , 0 ) , " " , " get_time_left " ) ;
2015-09-25 20:45:00 +02:00
2017-09-30 16:19:07 +02:00
BIND_ENUM_CONSTANT ( TIMER_PROCESS_PHYSICS ) ;
2017-08-20 17:45:01 +02:00
BIND_ENUM_CONSTANT ( TIMER_PROCESS_IDLE ) ;
2014-02-10 02:10:30 +01:00
}
Timer : : Timer ( ) {
2015-05-10 16:00:26 +02:00
timer_process_mode = TIMER_PROCESS_IDLE ;
2017-03-05 16:44:50 +01:00
autostart = false ;
wait_time = 1 ;
one_shot = false ;
2016-03-31 23:23:16 +02:00
time_left = - 1 ;
processing = false ;
2017-03-11 18:10:01 +01:00
paused = false ;
2014-02-10 02:10:30 +01:00
}