2014-02-10 01:10:30 +00:00
/*************************************************************************/
/* gd_functions.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/*************************************************************************/
# include "gd_functions.h"
# include "math_funcs.h"
# include "object_type_db.h"
# include "reference.h"
# include "gd_script.h"
2014-03-14 01:57:24 +00:00
# include "func_ref.h"
2014-02-10 01:10:30 +00:00
# include "os/os.h"
const char * GDFunctions : : get_func_name ( Function p_func ) {
ERR_FAIL_INDEX_V ( p_func , FUNC_MAX , " " ) ;
static const char * _names [ FUNC_MAX ] = {
" sin " ,
" cos " ,
" tan " ,
" sinh " ,
" cosh " ,
" tanh " ,
" asin " ,
" acos " ,
" atan " ,
" atan2 " ,
" sqrt " ,
" fmod " ,
" fposmod " ,
" floor " ,
" ceil " ,
" round " ,
" abs " ,
" sign " ,
" pow " ,
" log " ,
" exp " ,
" is_nan " ,
" is_inf " ,
" ease " ,
" decimals " ,
" stepify " ,
" lerp " ,
" dectime " ,
" randomize " ,
" randi " ,
" randf " ,
" rand_range " ,
" rand_seed " ,
" deg2rad " ,
" rad2deg " ,
" linear2db " ,
" db2linear " ,
" max " ,
" min " ,
" clamp " ,
" nearest_po2 " ,
" weakref " ,
2014-03-14 01:57:24 +00:00
" funcref " ,
2014-02-10 01:10:30 +00:00
" convert " ,
" typeof " ,
" str " ,
" print " ,
" printt " ,
" printerr " ,
" printraw " ,
" range " ,
2014-02-16 00:16:33 +00:00
" load " ,
2014-02-10 01:10:30 +00:00
" inst2dict " ,
" dict2inst " ,
" print_stack " ,
} ;
return _names [ p_func ] ;
}
void GDFunctions : : call ( Function p_func , const Variant * * p_args , int p_arg_count , Variant & r_ret , Variant : : CallError & r_error ) {
r_error . error = Variant : : CallError : : CALL_OK ;
# ifdef DEBUG_ENABLED
# define VALIDATE_ARG_COUNT(m_count) \
if ( p_arg_count < m_count ) { \
r_error . error = Variant : : CallError : : CALL_ERROR_TOO_FEW_ARGUMENTS ; \
r_error . argument = m_count ; \
return ; \
} \
if ( p_arg_count > m_count ) { \
r_error . error = Variant : : CallError : : CALL_ERROR_TOO_MANY_ARGUMENTS ; \
r_error . argument = m_count ; \
return ; \
}
# define VALIDATE_ARG_NUM(m_arg) \
if ( ! p_args [ m_arg ] - > is_num ( ) ) { \
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_ARGUMENT ; \
r_error . argument = m_arg ; \
r_error . expected = Variant : : REAL ; \
return ; \
}
# else
# define VALIDATE_ARG_COUNT(m_count)
# define VALIDATE_ARG_NUM(m_arg)
# endif
//using a switch, so the compiler generates a jumptable
switch ( p_func ) {
case MATH_SIN : {
VALIDATE_ARG_COUNT ( 1 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
r_ret = Math : : sin ( * p_args [ 0 ] ) ;
} break ;
case MATH_COS : {
VALIDATE_ARG_COUNT ( 1 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
r_ret = Math : : cos ( * p_args [ 0 ] ) ;
} break ;
case MATH_TAN : {
VALIDATE_ARG_COUNT ( 1 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
r_ret = Math : : tan ( * p_args [ 0 ] ) ;
} break ;
case MATH_SINH : {
VALIDATE_ARG_COUNT ( 1 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
r_ret = Math : : sinh ( * p_args [ 0 ] ) ;
} break ;
case MATH_COSH : {
VALIDATE_ARG_COUNT ( 1 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
r_ret = Math : : cosh ( * p_args [ 0 ] ) ;
} break ;
case MATH_TANH : {
VALIDATE_ARG_COUNT ( 1 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
r_ret = Math : : tanh ( * p_args [ 0 ] ) ;
} break ;
case MATH_ASIN : {
VALIDATE_ARG_COUNT ( 1 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
r_ret = Math : : asin ( * p_args [ 0 ] ) ;
} break ;
case MATH_ACOS : {
VALIDATE_ARG_COUNT ( 1 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
r_ret = Math : : acos ( * p_args [ 0 ] ) ;
} break ;
case MATH_ATAN : {
VALIDATE_ARG_COUNT ( 1 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
r_ret = Math : : atan ( * p_args [ 0 ] ) ;
} break ;
case MATH_ATAN2 : {
VALIDATE_ARG_COUNT ( 2 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
VALIDATE_ARG_NUM ( 1 ) ;
r_ret = Math : : atan2 ( * p_args [ 0 ] , * p_args [ 1 ] ) ;
} break ;
case MATH_SQRT : {
VALIDATE_ARG_COUNT ( 1 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
r_ret = Math : : sqrt ( * p_args [ 0 ] ) ;
} break ;
case MATH_FMOD : {
VALIDATE_ARG_COUNT ( 2 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
VALIDATE_ARG_NUM ( 1 ) ;
r_ret = Math : : fmod ( * p_args [ 0 ] , * p_args [ 1 ] ) ;
} break ;
case MATH_FPOSMOD : {
VALIDATE_ARG_COUNT ( 2 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
VALIDATE_ARG_NUM ( 1 ) ;
r_ret = Math : : fposmod ( * p_args [ 0 ] , * p_args [ 1 ] ) ;
} break ;
case MATH_FLOOR : {
VALIDATE_ARG_COUNT ( 1 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
r_ret = Math : : floor ( * p_args [ 0 ] ) ;
} break ;
case MATH_CEIL : {
VALIDATE_ARG_COUNT ( 1 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
r_ret = Math : : ceil ( * p_args [ 0 ] ) ;
} break ;
case MATH_ROUND : {
VALIDATE_ARG_COUNT ( 1 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
r_ret = Math : : round ( * p_args [ 0 ] ) ;
} break ;
case MATH_ABS : {
VALIDATE_ARG_COUNT ( 1 ) ;
if ( p_args [ 0 ] - > get_type ( ) = = Variant : : INT ) {
int64_t i = * p_args [ 0 ] ;
r_ret = ABS ( i ) ;
} else if ( p_args [ 0 ] - > get_type ( ) = = Variant : : REAL ) {
real_t r = * p_args [ 0 ] ;
r_ret = Math : : abs ( r ) ;
} else {
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_ARGUMENT ;
r_error . argument = 0 ;
r_error . expected = Variant : : REAL ;
}
} break ;
case MATH_SIGN : {
VALIDATE_ARG_COUNT ( 1 ) ;
if ( p_args [ 0 ] - > get_type ( ) = = Variant : : INT ) {
int64_t i = * p_args [ 0 ] ;
r_ret = i < 0 ? - 1 : ( i > 0 ? + 1 : 0 ) ;
} else if ( p_args [ 0 ] - > get_type ( ) = = Variant : : REAL ) {
real_t r = * p_args [ 0 ] ;
r_ret = r < 0.0 ? - 1.0 : ( r > 0.0 ? + 1.0 : 0.0 ) ;
} else {
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_ARGUMENT ;
r_error . argument = 0 ;
r_error . expected = Variant : : REAL ;
}
} break ;
case MATH_POW : {
VALIDATE_ARG_COUNT ( 2 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
VALIDATE_ARG_NUM ( 1 ) ;
r_ret = Math : : pow ( * p_args [ 0 ] , * p_args [ 1 ] ) ;
} break ;
case MATH_LOG : {
VALIDATE_ARG_COUNT ( 1 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
r_ret = Math : : log ( * p_args [ 0 ] ) ;
} break ;
case MATH_EXP : {
VALIDATE_ARG_COUNT ( 1 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
r_ret = Math : : exp ( * p_args [ 0 ] ) ;
} break ;
case MATH_ISNAN : {
VALIDATE_ARG_COUNT ( 1 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
r_ret = Math : : is_nan ( * p_args [ 0 ] ) ;
} break ;
case MATH_ISINF : {
VALIDATE_ARG_COUNT ( 1 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
r_ret = Math : : is_inf ( * p_args [ 0 ] ) ;
} break ;
case MATH_EASE : {
VALIDATE_ARG_COUNT ( 2 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
VALIDATE_ARG_NUM ( 1 ) ;
r_ret = Math : : ease ( * p_args [ 0 ] , * p_args [ 1 ] ) ;
} break ;
case MATH_DECIMALS : {
VALIDATE_ARG_COUNT ( 1 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
r_ret = Math : : decimals ( * p_args [ 0 ] ) ;
} break ;
case MATH_STEPIFY : {
VALIDATE_ARG_COUNT ( 2 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
VALIDATE_ARG_NUM ( 1 ) ;
r_ret = Math : : stepify ( * p_args [ 0 ] , * p_args [ 1 ] ) ;
} break ;
case MATH_LERP : {
VALIDATE_ARG_COUNT ( 3 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
VALIDATE_ARG_NUM ( 1 ) ;
VALIDATE_ARG_NUM ( 2 ) ;
r_ret = Math : : lerp ( * p_args [ 0 ] , * p_args [ 1 ] , * p_args [ 2 ] ) ;
} break ;
case MATH_DECTIME : {
VALIDATE_ARG_COUNT ( 3 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
VALIDATE_ARG_NUM ( 1 ) ;
VALIDATE_ARG_NUM ( 2 ) ;
r_ret = Math : : dectime ( * p_args [ 0 ] , * p_args [ 1 ] , * p_args [ 2 ] ) ;
} break ;
case MATH_RANDOMIZE : {
Math : : randomize ( ) ;
r_ret = Variant ( ) ;
} break ;
case MATH_RAND : {
r_ret = Math : : rand ( ) ;
} break ;
case MATH_RANDF : {
r_ret = Math : : randf ( ) ;
} break ;
case MATH_RANDOM : {
VALIDATE_ARG_COUNT ( 2 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
VALIDATE_ARG_NUM ( 1 ) ;
r_ret = Math : : random ( * p_args [ 0 ] , * p_args [ 1 ] ) ;
} break ;
case MATH_RANDSEED : {
VALIDATE_ARG_COUNT ( 1 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
uint32_t seed = * p_args [ 0 ] ;
int ret = Math : : rand_from_seed ( & seed ) ;
Array reta ;
reta . push_back ( ret ) ;
reta . push_back ( seed ) ;
r_ret = reta ;
} break ;
case MATH_DEG2RAD : {
VALIDATE_ARG_COUNT ( 1 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
r_ret = Math : : deg2rad ( * p_args [ 0 ] ) ;
} break ;
case MATH_RAD2DEG : {
VALIDATE_ARG_COUNT ( 1 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
r_ret = Math : : rad2deg ( * p_args [ 0 ] ) ;
} break ;
case MATH_LINEAR2DB : {
VALIDATE_ARG_COUNT ( 1 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
r_ret = Math : : linear2db ( * p_args [ 0 ] ) ;
} break ;
case MATH_DB2LINEAR : {
VALIDATE_ARG_COUNT ( 1 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
r_ret = Math : : db2linear ( * p_args [ 0 ] ) ;
} break ;
case LOGIC_MAX : {
VALIDATE_ARG_COUNT ( 2 ) ;
if ( p_args [ 0 ] - > get_type ( ) = = Variant : : INT & & p_args [ 1 ] - > get_type ( ) = = Variant : : INT ) {
int64_t a = * p_args [ 0 ] ;
int64_t b = * p_args [ 1 ] ;
r_ret = MAX ( a , b ) ;
} else {
VALIDATE_ARG_NUM ( 0 ) ;
VALIDATE_ARG_NUM ( 1 ) ;
real_t a = * p_args [ 0 ] ;
real_t b = * p_args [ 1 ] ;
r_ret = MAX ( a , b ) ;
}
} break ;
case LOGIC_MIN : {
VALIDATE_ARG_COUNT ( 2 ) ;
if ( p_args [ 0 ] - > get_type ( ) = = Variant : : INT & & p_args [ 1 ] - > get_type ( ) = = Variant : : INT ) {
int64_t a = * p_args [ 0 ] ;
int64_t b = * p_args [ 1 ] ;
r_ret = MIN ( a , b ) ;
} else {
VALIDATE_ARG_NUM ( 0 ) ;
VALIDATE_ARG_NUM ( 1 ) ;
real_t a = * p_args [ 0 ] ;
real_t b = * p_args [ 1 ] ;
r_ret = MIN ( a , b ) ;
}
} break ;
case LOGIC_CLAMP : {
VALIDATE_ARG_COUNT ( 3 ) ;
if ( p_args [ 0 ] - > get_type ( ) = = Variant : : INT & & p_args [ 1 ] - > get_type ( ) = = Variant : : INT & & p_args [ 2 ] - > get_type ( ) = = Variant : : INT ) {
int64_t a = * p_args [ 0 ] ;
int64_t b = * p_args [ 1 ] ;
int64_t c = * p_args [ 2 ] ;
r_ret = CLAMP ( a , b , c ) ;
} else {
VALIDATE_ARG_NUM ( 0 ) ;
VALIDATE_ARG_NUM ( 1 ) ;
VALIDATE_ARG_NUM ( 2 ) ;
real_t a = * p_args [ 0 ] ;
real_t b = * p_args [ 1 ] ;
real_t c = * p_args [ 2 ] ;
r_ret = CLAMP ( a , b , c ) ;
}
} break ;
case LOGIC_NEAREST_PO2 : {
VALIDATE_ARG_COUNT ( 1 ) ;
VALIDATE_ARG_NUM ( 0 ) ;
int64_t num = * p_args [ 0 ] ;
r_ret = nearest_power_of_2 ( num ) ;
} break ;
case OBJ_WEAKREF : {
VALIDATE_ARG_COUNT ( 1 ) ;
if ( p_args [ 0 ] - > get_type ( ) ! = Variant : : OBJECT ) {
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_ARGUMENT ;
r_error . argument = 0 ;
r_error . expected = Variant : : OBJECT ;
return ;
}
if ( p_args [ 0 ] - > is_ref ( ) ) {
REF r = * p_args [ 0 ] ;
if ( ! r . is_valid ( ) ) {
r_ret = Variant ( ) ;
return ;
}
Ref < WeakRef > wref = memnew ( WeakRef ) ;
wref - > set_ref ( r ) ;
r_ret = wref ;
} else {
Object * obj = * p_args [ 0 ] ;
if ( ! obj ) {
r_ret = Variant ( ) ;
return ;
}
Ref < WeakRef > wref = memnew ( WeakRef ) ;
wref - > set_obj ( obj ) ;
r_ret = wref ;
}
2014-03-14 01:57:24 +00:00
} break ;
case FUNC_FUNCREF : {
VALIDATE_ARG_COUNT ( 2 ) ;
if ( p_args [ 0 ] - > get_type ( ) ! = Variant : : OBJECT ) {
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_ARGUMENT ;
r_error . argument = 0 ;
r_error . expected = Variant : : OBJECT ;
r_ret = Variant ( ) ;
return ;
}
if ( p_args [ 1 ] - > get_type ( ) ! = Variant : : STRING & & p_args [ 1 ] - > get_type ( ) ! = Variant : : NODE_PATH ) {
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_ARGUMENT ;
r_error . argument = 1 ;
r_error . expected = Variant : : STRING ;
r_ret = Variant ( ) ;
return ;
}
Ref < FuncRef > fr = memnew ( FuncRef ) ;
Object * obj = * p_args [ 0 ] ;
fr - > set_instance ( * p_args [ 0 ] ) ;
fr - > set_function ( * p_args [ 1 ] ) ;
r_ret = fr ;
2014-02-10 01:10:30 +00:00
} break ;
case TYPE_CONVERT : {
VALIDATE_ARG_COUNT ( 2 ) ;
VALIDATE_ARG_NUM ( 1 ) ;
int type = * p_args [ 1 ] ;
if ( type < 0 | | type > = Variant : : VARIANT_MAX ) {
ERR_PRINT ( " Invalid type argument to convert() " ) ;
r_ret = Variant : : NIL ;
} else {
r_ret = Variant : : construct ( Variant : : Type ( type ) , p_args , 1 , r_error ) ;
}
} break ;
case TYPE_OF : {
VALIDATE_ARG_COUNT ( 1 ) ;
r_ret = p_args [ 0 ] - > get_type ( ) ;
} break ;
case TEXT_STR : {
String str ;
for ( int i = 0 ; i < p_arg_count ; i + + ) {
String os = p_args [ i ] - > operator String ( ) ; ;
if ( i = = 0 )
str = os ;
else
str + = os ;
}
r_ret = str ;
} break ;
case TEXT_PRINT : {
String str ;
for ( int i = 0 ; i < p_arg_count ; i + + ) {
str + = p_args [ i ] - > operator String ( ) ;
}
//str+="\n";
print_line ( str ) ;
r_ret = Variant ( ) ;
} break ;
case TEXT_PRINT_TABBED : {
String str ;
for ( int i = 0 ; i < p_arg_count ; i + + ) {
if ( i )
str + = " \t " ;
str + = p_args [ i ] - > operator String ( ) ;
}
//str+="\n";
print_line ( str ) ;
r_ret = Variant ( ) ;
} break ;
case TEXT_PRINTERR : {
String str ;
for ( int i = 0 ; i < p_arg_count ; i + + ) {
str + = p_args [ i ] - > operator String ( ) ;
}
//str+="\n";
OS : : get_singleton ( ) - > printerr ( " %s \n " , str . utf8 ( ) . get_data ( ) ) ;
r_ret = Variant ( ) ;
} break ;
case TEXT_PRINTRAW : {
String str ;
for ( int i = 0 ; i < p_arg_count ; i + + ) {
str + = p_args [ i ] - > operator String ( ) ;
}
//str+="\n";
OS : : get_singleton ( ) - > print ( " %s \n " , str . utf8 ( ) . get_data ( ) ) ;
r_ret = Variant ( ) ;
} break ;
case GEN_RANGE : {
switch ( p_arg_count ) {
case 0 : {
r_error . error = Variant : : CallError : : CALL_ERROR_TOO_FEW_ARGUMENTS ;
r_error . argument = 1 ;
} break ;
case 1 : {
VALIDATE_ARG_NUM ( 0 ) ;
int count = * p_args [ 0 ] ;
Array arr ( true ) ;
if ( count < = 0 ) {
r_ret = arr ;
return ;
}
Error err = arr . resize ( count ) ;
if ( err ! = OK ) {
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_METHOD ;
r_ret = Variant ( ) ;
return ;
}
for ( int i = 0 ; i < count ; i + + ) {
arr [ i ] = i ;
}
r_ret = arr ;
} break ;
case 2 : {
VALIDATE_ARG_NUM ( 0 ) ;
VALIDATE_ARG_NUM ( 1 ) ;
int from = * p_args [ 0 ] ;
int to = * p_args [ 1 ] ;
Array arr ( true ) ;
if ( from > = to ) {
r_ret = arr ;
return ;
}
Error err = arr . resize ( to - from ) ;
if ( err ! = OK ) {
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_METHOD ;
r_ret = Variant ( ) ;
return ;
}
for ( int i = from ; i < to ; i + + )
arr [ i - from ] = i ;
r_ret = arr ;
} break ;
case 3 : {
VALIDATE_ARG_NUM ( 0 ) ;
VALIDATE_ARG_NUM ( 1 ) ;
VALIDATE_ARG_NUM ( 2 ) ;
int from = * p_args [ 0 ] ;
int to = * p_args [ 1 ] ;
int incr = * p_args [ 2 ] ;
if ( incr = = 0 ) {
ERR_EXPLAIN ( " step argument is zero! " ) ;
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_METHOD ;
ERR_FAIL ( ) ;
}
Array arr ( true ) ;
if ( from > = to & & incr > 0 ) {
r_ret = arr ;
return ;
}
if ( from < = to & & incr < 0 ) {
r_ret = arr ;
return ;
}
//calculate how many
int count = 0 ;
if ( incr > 0 ) {
count = ( ( to - from - 1 ) / incr ) + 1 ;
} else {
count = ( ( from - to - 1 ) / - incr ) + 1 ;
}
Error err = arr . resize ( count ) ;
if ( err ! = OK ) {
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_METHOD ;
r_ret = Variant ( ) ;
return ;
}
if ( incr > 0 ) {
int idx = 0 ;
for ( int i = from ; i < to ; i + = incr ) {
arr [ idx + + ] = i ;
}
} else {
int idx = 0 ;
for ( int i = from ; i > to ; i + = incr ) {
arr [ idx + + ] = i ;
}
}
r_ret = arr ;
} break ;
default : {
r_error . error = Variant : : CallError : : CALL_ERROR_TOO_MANY_ARGUMENTS ;
r_error . argument = 3 ;
} break ;
}
} break ;
2014-02-16 00:16:33 +00:00
case RESOURCE_LOAD : {
VALIDATE_ARG_COUNT ( 1 ) ;
if ( p_args [ 0 ] - > get_type ( ) ! = Variant : : STRING ) {
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_ARGUMENT ;
r_error . argument = 0 ;
r_ret = Variant ( ) ;
}
r_ret = ResourceLoader : : load ( * p_args [ 0 ] ) ;
2014-03-14 01:57:24 +00:00
} break ;
2014-02-10 01:10:30 +00:00
case INST2DICT : {
VALIDATE_ARG_COUNT ( 1 ) ;
if ( p_args [ 0 ] - > get_type ( ) = = Variant : : NIL ) {
r_ret = Variant ( ) ;
} else if ( p_args [ 0 ] - > get_type ( ) ! = Variant : : OBJECT ) {
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_ARGUMENT ;
r_error . argument = 0 ;
r_ret = Variant ( ) ;
} else {
Object * obj = * p_args [ 0 ] ;
if ( ! obj ) {
r_ret = Variant ( ) ;
} else if ( ! obj - > get_script_instance ( ) | | obj - > get_script_instance ( ) - > get_language ( ) ! = GDScriptLanguage : : get_singleton ( ) ) {
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_ARGUMENT ;
r_error . argument = 0 ;
r_error . expected = Variant : : DICTIONARY ;
ERR_PRINT ( " Not a script with an instance " ) ;
} else {
GDInstance * ins = static_cast < GDInstance * > ( obj - > get_script_instance ( ) ) ;
Ref < GDScript > base = ins - > get_script ( ) ;
if ( base . is_null ( ) ) {
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_ARGUMENT ;
r_error . argument = 0 ;
r_error . expected = Variant : : DICTIONARY ;
ERR_PRINT ( " Not based on a script " ) ;
return ;
}
GDScript * p = base . ptr ( ) ;
Vector < StringName > sname ;
while ( p - > _owner ) {
sname . push_back ( p - > name ) ;
p = p - > _owner ;
}
sname . invert ( ) ;
if ( ! p - > path . is_resource_file ( ) ) {
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_ARGUMENT ;
r_error . argument = 0 ;
r_error . expected = Variant : : DICTIONARY ;
print_line ( " PATH: " + p - > path ) ;
ERR_PRINT ( " Not based on a resource file " ) ;
return ;
}
NodePath cp ( sname , Vector < StringName > ( ) , false ) ;
Dictionary d ( true ) ;
d [ " @subpath " ] = cp ;
d [ " @path " ] = p - > path ;
p = base . ptr ( ) ;
while ( p ) {
for ( Set < StringName > : : Element * E = p - > members . front ( ) ; E ; E = E - > next ( ) ) {
Variant value ;
if ( ins - > get ( E - > get ( ) , value ) ) {
String k = E - > get ( ) ;
if ( ! d . has ( k ) ) {
d [ k ] = value ;
}
}
}
p = p - > _base ;
}
r_ret = d ;
}
}
} break ;
case DICT2INST : {
VALIDATE_ARG_COUNT ( 1 ) ;
if ( p_args [ 0 ] - > get_type ( ) ! = Variant : : DICTIONARY ) {
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_ARGUMENT ;
r_error . argument = 0 ;
r_error . expected = Variant : : DICTIONARY ;
return ;
}
Dictionary d = * p_args [ 0 ] ;
if ( ! d . has ( " @path " ) ) {
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_ARGUMENT ;
r_error . argument = 0 ;
r_error . expected = Variant : : OBJECT ;
return ;
}
Ref < Script > scr = ResourceLoader : : load ( d [ " @path " ] ) ;
if ( ! scr . is_valid ( ) ) {
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_ARGUMENT ;
r_error . argument = 0 ;
r_error . expected = Variant : : OBJECT ;
return ;
}
Ref < GDScript > gdscr = scr ;
if ( ! gdscr . is_valid ( ) ) {
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_ARGUMENT ;
r_error . argument = 0 ;
r_error . expected = Variant : : OBJECT ;
return ;
}
NodePath sub ;
if ( d . has ( " @subpath " ) ) {
sub = d [ " @subpath " ] ;
}
for ( int i = 0 ; i < sub . get_name_count ( ) ; i + + ) {
gdscr = gdscr - > subclasses [ sub . get_name ( i ) ] ;
if ( ! gdscr . is_valid ( ) ) {
r_error . error = Variant : : CallError : : CALL_ERROR_INVALID_ARGUMENT ;
r_error . argument = 0 ;
r_error . expected = Variant : : OBJECT ;
return ;
}
}
r_ret = gdscr - > _new ( NULL , 0 , r_error ) ;
} break ;
case PRINT_STACK : {
ScriptLanguage * script = GDScriptLanguage : : get_singleton ( ) ;
for ( int i = 0 ; i < script - > debug_get_stack_level_count ( ) ; i + + ) {
print_line ( " Frame " + itos ( i ) + " - " + script - > debug_get_stack_level_source ( i ) + " : " + itos ( script - > debug_get_stack_level_line ( i ) ) + " in function ' " + script - > debug_get_stack_level_function ( i ) + " ' " ) ;
} ;
} break ;
case FUNC_MAX : {
ERR_FAIL_V ( ) ;
} break ;
}
}
bool GDFunctions : : is_deterministic ( Function p_func ) {
//man i couldn't have chosen a worse function name,
//way too controversial..
switch ( p_func ) {
case MATH_SIN :
case MATH_COS :
case MATH_TAN :
case MATH_SINH :
case MATH_COSH :
case MATH_TANH :
case MATH_ASIN :
case MATH_ACOS :
case MATH_ATAN :
case MATH_ATAN2 :
case MATH_SQRT :
case MATH_FMOD :
case MATH_FPOSMOD :
case MATH_FLOOR :
case MATH_CEIL :
case MATH_ROUND :
case MATH_ABS :
case MATH_SIGN :
case MATH_POW :
case MATH_LOG :
case MATH_EXP :
case MATH_ISNAN :
case MATH_ISINF :
case MATH_EASE :
case MATH_DECIMALS :
case MATH_STEPIFY :
case MATH_LERP :
case MATH_DECTIME :
case MATH_DEG2RAD :
case MATH_RAD2DEG :
case MATH_LINEAR2DB :
case MATH_DB2LINEAR :
case LOGIC_MAX :
case LOGIC_MIN :
case LOGIC_CLAMP :
case LOGIC_NEAREST_PO2 :
case TYPE_CONVERT :
case TYPE_OF :
case TEXT_STR :
// enable for debug only, otherwise not desirable - case GEN_RANGE:
return true ;
default :
return false ;
}
return false ;
}
MethodInfo GDFunctions : : get_info ( Function p_func ) {
# ifdef TOOLS_ENABLED
//using a switch, so the compiler generates a jumptable
switch ( p_func ) {
case MATH_SIN : {
MethodInfo mi ( " sin " , PropertyInfo ( Variant : : REAL , " s " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_COS : {
MethodInfo mi ( " cos " , PropertyInfo ( Variant : : REAL , " s " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_TAN : {
MethodInfo mi ( " tan " , PropertyInfo ( Variant : : REAL , " s " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_SINH : {
MethodInfo mi ( " sinh " , PropertyInfo ( Variant : : REAL , " s " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_COSH : {
MethodInfo mi ( " cosh " , PropertyInfo ( Variant : : REAL , " s " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_TANH : {
MethodInfo mi ( " tanh " , PropertyInfo ( Variant : : REAL , " s " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_ASIN : {
MethodInfo mi ( " asin " , PropertyInfo ( Variant : : REAL , " s " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_ACOS : {
MethodInfo mi ( " acos " , PropertyInfo ( Variant : : REAL , " s " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_ATAN : {
MethodInfo mi ( " atan " , PropertyInfo ( Variant : : REAL , " s " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_ATAN2 : {
MethodInfo mi ( " atan2 " , PropertyInfo ( Variant : : REAL , " x " ) , PropertyInfo ( Variant : : REAL , " y " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_SQRT : {
MethodInfo mi ( " sqrt " , PropertyInfo ( Variant : : REAL , " s " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_FMOD : {
MethodInfo mi ( " fmod " , PropertyInfo ( Variant : : REAL , " x " ) , PropertyInfo ( Variant : : REAL , " y " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_FPOSMOD : {
MethodInfo mi ( " fposmod " , PropertyInfo ( Variant : : REAL , " x " ) , PropertyInfo ( Variant : : REAL , " y " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_FLOOR : {
MethodInfo mi ( " floor " , PropertyInfo ( Variant : : REAL , " s " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_CEIL : {
MethodInfo mi ( " ceil " , PropertyInfo ( Variant : : REAL , " s " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_ROUND : {
MethodInfo mi ( " round " , PropertyInfo ( Variant : : REAL , " s " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_ABS : {
MethodInfo mi ( " abs " , PropertyInfo ( Variant : : REAL , " s " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_SIGN : {
MethodInfo mi ( " sign " , PropertyInfo ( Variant : : REAL , " s " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_POW : {
MethodInfo mi ( " pow " , PropertyInfo ( Variant : : REAL , " x " ) , PropertyInfo ( Variant : : REAL , " y " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_LOG : {
MethodInfo mi ( " log " , PropertyInfo ( Variant : : REAL , " s " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_EXP : {
MethodInfo mi ( " exp " , PropertyInfo ( Variant : : REAL , " s " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_ISNAN : {
MethodInfo mi ( " isnan " , PropertyInfo ( Variant : : REAL , " s " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_ISINF : {
MethodInfo mi ( " isinf " , PropertyInfo ( Variant : : REAL , " s " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_EASE : {
MethodInfo mi ( " ease " , PropertyInfo ( Variant : : REAL , " s " ) , PropertyInfo ( Variant : : REAL , " curve " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_DECIMALS : {
MethodInfo mi ( " decimals " , PropertyInfo ( Variant : : REAL , " step " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_STEPIFY : {
MethodInfo mi ( " stepify " , PropertyInfo ( Variant : : REAL , " s " ) , PropertyInfo ( Variant : : REAL , " step " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_LERP : {
MethodInfo mi ( " lerp " , PropertyInfo ( Variant : : REAL , " a " ) , PropertyInfo ( Variant : : REAL , " b " ) , PropertyInfo ( Variant : : REAL , " c " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_DECTIME : {
MethodInfo mi ( " dectime " , PropertyInfo ( Variant : : REAL , " value " ) , PropertyInfo ( Variant : : REAL , " amount " ) , PropertyInfo ( Variant : : REAL , " step " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_RANDOMIZE : {
MethodInfo mi ( " randomize " ) ;
mi . return_val . type = Variant : : NIL ;
return mi ;
} break ;
case MATH_RAND : {
MethodInfo mi ( " rand " ) ;
mi . return_val . type = Variant : : INT ;
return mi ;
} break ;
case MATH_RANDF : {
MethodInfo mi ( " randf " ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_RANDOM : {
MethodInfo mi ( " rand_range " , PropertyInfo ( Variant : : REAL , " from " ) , PropertyInfo ( Variant : : REAL , " to " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_RANDSEED : {
MethodInfo mi ( " rand_seed " , PropertyInfo ( Variant : : REAL , " seed " ) ) ;
mi . return_val . type = Variant : : ARRAY ;
return mi ;
} break ;
case MATH_DEG2RAD : {
MethodInfo mi ( " deg2rad " , PropertyInfo ( Variant : : REAL , " deg " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_RAD2DEG : {
MethodInfo mi ( " rad2deg " , PropertyInfo ( Variant : : REAL , " rad " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_LINEAR2DB : {
MethodInfo mi ( " linear2db " , PropertyInfo ( Variant : : REAL , " nrg " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case MATH_DB2LINEAR : {
MethodInfo mi ( " db2linear " , PropertyInfo ( Variant : : REAL , " db " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case LOGIC_MAX : {
MethodInfo mi ( " max " , PropertyInfo ( Variant : : REAL , " a " ) , PropertyInfo ( Variant : : REAL , " b " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case LOGIC_MIN : {
MethodInfo mi ( " min " , PropertyInfo ( Variant : : REAL , " a " ) , PropertyInfo ( Variant : : REAL , " b " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case LOGIC_CLAMP : {
MethodInfo mi ( " clamp " , PropertyInfo ( Variant : : REAL , " val " ) , PropertyInfo ( Variant : : REAL , " min " ) , PropertyInfo ( Variant : : REAL , " max " ) ) ;
mi . return_val . type = Variant : : REAL ;
return mi ;
} break ;
case LOGIC_NEAREST_PO2 : {
MethodInfo mi ( " nearest_po2 " , PropertyInfo ( Variant : : INT , " val " ) ) ;
mi . return_val . type = Variant : : INT ;
return mi ;
} break ;
case OBJ_WEAKREF : {
MethodInfo mi ( " weakref " , PropertyInfo ( Variant : : OBJECT , " obj " ) ) ;
mi . return_val . type = Variant : : OBJECT ;
return mi ;
} break ;
2014-03-14 01:57:24 +00:00
case FUNC_FUNCREF : {
MethodInfo mi ( " funcref " , PropertyInfo ( Variant : : OBJECT , " instance " ) , PropertyInfo ( Variant : : STRING , " funcname " ) ) ;
mi . return_val . type = Variant : : OBJECT ;
return mi ;
} break ;
2014-02-10 01:10:30 +00:00
case TYPE_CONVERT : {
MethodInfo mi ( " convert " , PropertyInfo ( Variant : : NIL , " what " ) , PropertyInfo ( Variant : : INT , " type " ) ) ;
mi . return_val . type = Variant : : OBJECT ;
return mi ;
} break ;
case TYPE_OF : {
MethodInfo mi ( " typeof " , PropertyInfo ( Variant : : NIL , " what " ) ) ;
mi . return_val . type = Variant : : INT ;
} ;
case TEXT_STR : {
MethodInfo mi ( " str " , PropertyInfo ( Variant : : NIL , " what " ) , PropertyInfo ( Variant : : NIL , " ... " ) ) ;
mi . return_val . type = Variant : : STRING ;
return mi ;
} break ;
case TEXT_PRINT : {
MethodInfo mi ( " print " , PropertyInfo ( Variant : : NIL , " what " ) , PropertyInfo ( Variant : : NIL , " ... " ) ) ;
mi . return_val . type = Variant : : NIL ;
return mi ;
} break ;
case TEXT_PRINT_TABBED : {
MethodInfo mi ( " printt " , PropertyInfo ( Variant : : NIL , " what " ) , PropertyInfo ( Variant : : NIL , " ... " ) ) ;
mi . return_val . type = Variant : : NIL ;
return mi ;
} break ;
case TEXT_PRINTERR : {
MethodInfo mi ( " printerr " , PropertyInfo ( Variant : : NIL , " what " ) , PropertyInfo ( Variant : : NIL , " ... " ) ) ;
mi . return_val . type = Variant : : NIL ;
return mi ;
} break ;
case TEXT_PRINTRAW : {
MethodInfo mi ( " printraw " , PropertyInfo ( Variant : : NIL , " what " ) , PropertyInfo ( Variant : : NIL , " ... " ) ) ;
mi . return_val . type = Variant : : NIL ;
return mi ;
} break ;
case GEN_RANGE : {
MethodInfo mi ( " range " , PropertyInfo ( Variant : : NIL , " ... " ) ) ;
mi . return_val . type = Variant : : ARRAY ;
return mi ;
} break ;
2014-02-16 00:16:33 +00:00
case RESOURCE_LOAD : {
MethodInfo mi ( " load " , PropertyInfo ( Variant : : STRING , " path " ) ) ;
mi . return_val . type = Variant : : OBJECT ;
return mi ;
} break ;
2014-02-10 01:10:30 +00:00
case INST2DICT : {
MethodInfo mi ( " inst2dict " , PropertyInfo ( Variant : : OBJECT , " inst " ) ) ;
mi . return_val . type = Variant : : DICTIONARY ;
return mi ;
} break ;
case DICT2INST : {
MethodInfo mi ( " dict2inst " , PropertyInfo ( Variant : : DICTIONARY , " dict " ) ) ;
mi . return_val . type = Variant : : OBJECT ;
return mi ;
} break ;
case PRINT_STACK : {
MethodInfo mi ( " print_stack " ) ;
mi . return_val . type = Variant : : NIL ;
return mi ;
} break ;
case FUNC_MAX : {
ERR_FAIL_V ( MethodInfo ( ) ) ;
} break ;
}
# endif
return MethodInfo ( ) ;
}