GODOT IS OPEN SOURCE

This commit is contained in:
Juan Linietsky 2014-02-09 22:10:30 -03:00
parent 0e49da1687
commit 0b806ee0fc
3138 changed files with 1294441 additions and 0 deletions

301
SConstruct Normal file
View file

@ -0,0 +1,301 @@
EnsureSConsVersion(0,14);
import os
import os.path
import glob
import sys
import methods
methods.update_version()
# scan possible build platforms
platform_list = [] # list of platforms
platform_opts = {} # options for each platform
platform_flags = {} # flags for each platform
active_platforms=[]
active_platform_ids=[]
platform_exporters=[]
global_defaults=[]
for x in glob.glob("platform/*"):
if (not os.path.isdir(x)):
continue
tmppath="./"+x
sys.path.append(tmppath)
import detect
if (os.path.exists(x+"/export/export.cpp")):
platform_exporters.append(x[9:])
if (os.path.exists(x+"/globals/global_defaults.cpp")):
global_defaults.append(x[9:])
if (detect.is_active()):
active_platforms.append( detect.get_name() )
active_platform_ids.append(x);
if (detect.can_build()):
x=x.replace("platform/","") # rest of world
x=x.replace("platform\\","") # win32
platform_list+=[x]
platform_opts[x]=detect.get_opts()
platform_flags[x]=detect.get_flags()
sys.path.remove(tmppath)
sys.modules.pop('detect')
module_list=methods.detect_modules()
print "Detected Platforms: "+str(platform_list)
print("Detected Modules: "+str(module_list))
methods.save_active_platforms(active_platforms,active_platform_ids)
custom_tools=['default']
if (os.name=="posix"):
pass
elif (os.name=="nt"):
if (os.getenv("VSINSTALLDIR")==None):
custom_tools=['mingw']
env_base=Environment(tools=custom_tools,ENV = {'PATH' : os.environ['PATH']});
#env_base=Environment(tools=custom_tools);
env_base.global_defaults=global_defaults
env_base.android_source_modules=[]
env_base.android_source_files=[]
env_base.android_module_libraries=[]
env_base.android_manifest_chunk=""
env_base.disabled_modules=[]
env_base.__class__.android_module_source = methods.android_module_source
env_base.__class__.android_module_library = methods.android_module_library
env_base.__class__.android_module_file = methods.android_module_file
env_base.__class__.android_module_manifest = methods.android_module_manifest
env_base.__class__.disable_module = methods.disable_module
env_base.__class__.add_source_files = methods.add_source_files
customs = ['custom.py']
profile = ARGUMENTS.get("profile", False)
if profile:
import os.path
if os.path.isfile(profile):
customs.append(profile)
elif os.path.isfile(profile+".py"):
customs.append(profile+".py")
opts=Options(customs, ARGUMENTS)
opts.Add('target', 'Compile Target (debug/profile/release).', "debug")
opts.Add('platform','Platform: '+str(platform_list)+'(sfml).',"")
opts.Add('python','Build Python Support: (yes/no)','no')
opts.Add('squirrel','Build Squirrel Support: (yes/no)','no')
opts.Add('tools','Build Tools (Including Editor): (yes/no)','yes')
opts.Add('lua','Build Lua Support: (yes/no)','no')
opts.Add('rfd','Remote Filesystem Driver: (yes/no)','no')
opts.Add('gdscript','Build GDSCript support: (yes/no)','yes')
opts.Add('vorbis','Build Ogg Vorbis Support: (yes/no)','yes')
opts.Add('minizip','Build Minizip Archive Support: (yes/no)','yes')
opts.Add('opengl', 'Build OpenGL Support: (yes/no)', 'yes')
opts.Add('game', 'Game (custom) Code Directory', "")
opts.Add('squish','Squish BC Texture Compression (yes/no)','yes')
opts.Add('theora','Theora Video (yes/no)','yes')
opts.Add('freetype','Freetype support in editor','yes')
opts.Add('speex','Speex Audio (yes/no)','yes')
opts.Add('xml','XML Save/Load support (yes/no)','yes')
opts.Add('png','PNG Image loader support (yes/no)','yes')
opts.Add('jpg','JPG Image loader support (yes/no)','yes')
opts.Add('webp','WEBP Image loader support (yes/no)','yes')
opts.Add('dds','DDS Texture loader support (yes/no)','yes')
opts.Add('pvr','PVR (PowerVR) Texture loader support (yes/no)','yes')
opts.Add('builtin_zlib','Use built-in zlib (yes/no)','yes')
opts.Add('musepack','Musepack Audio (yes/no)','yes')
opts.Add('default_gui_theme','Default GUI theme (yes/no)','yes')
opts.Add("CXX", "Compiler");
opts.Add("nedmalloc", "Add nedmalloc support", 'yes');
opts.Add("CCFLAGS", "Custom flags for the C++ compiler");
opts.Add("CFLAGS", "Custom flags for the C compiler");
opts.Add("LINKFLAGS", "Custom flags for the linker");
opts.Add('disable_3d', 'Disable 3D nodes for smaller executable (yes/no)', "no")
opts.Add('disable_advanced_gui', 'Disable advance 3D gui nodes and behaviors (yes/no)', "no")
opts.Add('old_scenes', 'Compatibility with old-style scenes', "yes")
# add platform specific options
for k in platform_opts.keys():
opt_list = platform_opts[k]
for o in opt_list:
opts.Add(o[0],o[1],o[2])
for x in module_list:
opts.Add('module_'+x+'_enabled', "Enable module '"+x+"'.", "yes")
opts.Update(env_base) # update environment
Help(opts.GenerateHelpText(env_base)) # generate help
# add default include paths
env_base.Append(CPPPATH=['#core','#core/math','#tools','#drivers','#'])
# configure ENV for platform
env_base.detect_python=True
env_base.platform_exporters=platform_exporters
"""
sys.path.append("./platform/"+env_base["platform"])
import detect
detect.configure(env_base)
sys.path.remove("./platform/"+env_base["platform"])
sys.modules.pop('detect')
"""
if (env_base['target']=='debug'):
env_base.Append(CPPFLAGS=['-DDEBUG_MEMORY_ALLOC']);
env_base.Append(CPPFLAGS=['-DSCI_NAMESPACE'])
env_base.platforms = {}
for p in platform_list:
sys.path.append("./platform/"+p)
import detect
if "create" in dir(detect):
env = detect.create(env_base)
else:
env = env_base.Clone()
detect.configure(env)
env['platform'] = p
sys.path.remove("./platform/"+p)
sys.modules.pop('detect')
flag_list = platform_flags[p]
for f in flag_list:
env[f[0]] = f[1]
env.module_list=[]
for x in module_list:
if env['module_'+x+'_enabled'] != "yes":
continue
tmppath="./modules/"+x
sys.path.append(tmppath)
env.current_module=x
import config
if (config.can_build(p)):
config.configure(env)
env.module_list.append(x)
sys.path.remove(tmppath)
sys.modules.pop('config')
if (env['musepack']=='yes'):
env.Append(CPPFLAGS=['-DMUSEPACK_ENABLED']);
if (env["old_scenes"]=='yes'):
env.Append(CPPFLAGS=['-DOLD_SCENE_FORMAT_ENABLED'])
if (env["rfd"]=='yes'):
env.Append(CPPFLAGS=['-DRFD_ENABLED'])
if (env["builtin_zlib"]=='yes'):
env.Append(CPPPATH=['#drivers/builtin_zlib/zlib'])
if (env['squirrel']=='yes'):
env.Append(CPPFLAGS=['-DSQUIRREL_ENABLED'])
env.Append(CPPPATH=['#script/squirrel/src'])
# to test 64 bits compiltion
# env.Append(CPPFLAGS=['-m64'])
if (env['lua']=='yes'):
env.Append(CPPFLAGS=['-DLUA_ENABLED'])
env.Append(CPPPATH=['#script/lua/src'])
if (env_base['squish']=='yes'):
env.Append(CPPFLAGS=['-DSQUISH_ENABLED']);
if (env['vorbis']=='yes'):
env.Append(CPPFLAGS=['-DVORBIS_ENABLED']);
if (env['theora']=='yes'):
env.Append(CPPFLAGS=['-DTHEORA_ENABLED']);
if (env['png']=='yes'):
env.Append(CPPFLAGS=['-DPNG_ENABLED']);
if (env['dds']=='yes'):
env.Append(CPPFLAGS=['-DDDS_ENABLED']);
if (env['pvr']=='yes'):
env.Append(CPPFLAGS=['-DPVR_ENABLED']);
if (env['jpg']=='yes'):
env.Append(CPPFLAGS=['-DJPG_ENABLED']);
if (env['webp']=='yes'):
env.Append(CPPFLAGS=['-DWEBP_ENABLED']);
if (env['speex']=='yes'):
env.Append(CPPFLAGS=['-DSPEEX_ENABLED']);
if (env['tools']=='yes'):
env.Append(CPPFLAGS=['-DTOOLS_ENABLED'])
if (env['disable_3d']=='yes'):
env.Append(CPPFLAGS=['-D_3D_DISABLED'])
if (env['gdscript']=='yes'):
env.Append(CPPFLAGS=['-DGDSCRIPT_ENABLED'])
if (env['disable_advanced_gui']=='yes'):
env.Append(CPPFLAGS=['-DADVANCED_GUI_DISABLED'])
if (env['minizip'] == 'yes'):
env.Append(CPPFLAGS=['-DMINIZIP_ENABLED'])
if (env['xml']=='yes'):
env.Append(CPPFLAGS=['-DXML_ENABLED'])
if (env['default_gui_theme']=='no'):
env.Append(CPPFLAGS=['-DDEFAULT_THEME_DISABLED'])
if (env["python"]=='yes'):
detected=False;
if (env.detect_python):
print("Python 3.0 Prefix:");
pycfg_exec="python3-config"
errorval=os.system(pycfg_exec+" --prefix")
prefix=""
if (not errorval):
#gah, why can't it get both at the same time like pkg-config, sdl-config, etc?
env.ParseConfig(pycfg_exec+" --cflags")
env.ParseConfig(pycfg_exec+" --libs")
detected=True
if (detected):
env.Append(CPPFLAGS=['-DPYTHON_ENABLED'])
#remove annoying warnings
if ('-Wstrict-prototypes' in env["CCFLAGS"]):
env["CCFLAGS"].remove('-Wstrict-prototypes');
if ('-fwrapv' in env["CCFLAGS"]):
env["CCFLAGS"].remove('-fwrapv');
else:
print("Python 3.0 not detected ("+pycfg_exec+") support disabled.");
#if env['nedmalloc'] == 'yes':
# env.Append(CPPFLAGS = ['-DNEDMALLOC_ENABLED'])
Export('env')
#build subdirs, the build order is dependent on link order.
SConscript("core/SCsub")
SConscript("servers/SCsub")
SConscript("scene/SCsub")
SConscript("tools/SCsub")
SConscript("script/SCsub");
SConscript("drivers/SCsub")
SConscript("bin/SCsub")
if env['game']:
SConscript(env['game']+'/SCsub')
SConscript("modules/SCsub")
SConscript("main/SCsub")
SConscript("platform/"+p+"/SCsub"); # build selected platform

4
bin/SCsub Normal file
View file

@ -0,0 +1,4 @@
Import('env')
Export('env')
SConscript('tests/SCsub');

14
bin/tests/SCsub Normal file
View file

@ -0,0 +1,14 @@
Import('env')
env.tests_sources=[]
env.add_source_files(env.tests_sources,"*.cpp")
Export('env')
#SConscript('math/SCsub');
lib = env.Library("tests",env.tests_sources)
env.Prepend(LIBS=[lib])

View file

@ -0,0 +1,107 @@
/*************************************************************************/
/* test_containers.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 "test_containers.h"
#include "dvector.h"
#include "set.h"
#include "print_string.h"
#include "math_funcs.h"
#include "servers/visual/default_mouse_cursor.xpm"
#include "variant.h"
#include "list.h"
#include "image.h"
namespace TestContainers {
MainLoop * test() {
/*
HashMap<int,int> int_map;
for (int i=0;i<68000;i++) {
int num=(int)Math::random(0,1024);
int_map[i]=num;
}
*/
{
// static const int size = 16;
Image img;
img.create(default_mouse_cursor_xpm);
{
for (int i=0; i<8; i++) {
Image mipmap;
//img.make_mipmap(mipmap);
img = mipmap;
if (img.get_width() <= 4) break;
};
};
};
#if 0
Set<int> set;
print_line("Begin Insert");
for (int i=0;i<1100;i++) {
int num=i;//(int)Math::random(0,1024);
// print_line("inserting "+itos(num));
set.insert( num );
}
/*
for (int i=0;i<400;i++) {
int num=(int)Math::random(0,1024);
set.erase(num);
}
*/
//set.print_tree();
for(Set<int>::Element *I=set.front();I;I=I->next()) {
print_line("inserted "+itos(I->get())+" prev is "+itos(I->prev()?I->prev()->get():-100));
}
print_line("depth is "+itos(set.calculate_depth()));
print_line("Insert Success");
#endif
return NULL;
}
}

View file

@ -0,0 +1,43 @@
/*************************************************************************/
/* test_containers.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef TEST_CONTAINERS_H
#define TEST_CONTAINERS_H
#include "os/main_loop.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
namespace TestContainers {
MainLoop * test();
}
#endif

217
bin/tests/test_detailer.cpp Normal file
View file

@ -0,0 +1,217 @@
/*************************************************************************/
/* test_detailer.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 "test_detailer.h"
#include "servers/visual_server.h"
#include "os/main_loop.h"
#include "math_funcs.h"
#include "print_string.h"
#include "geometry.h"
#include "quick_hull.h"
namespace TestMultiMesh {
class TestMainLoop : public MainLoop {
RID instance;
RID camera;
RID viewport;
RID light;
RID mesh;
RID scenario;
#define MULTIMESH_COUNT 1500
float ofs_x,ofs_y;
bool quit;
public:
virtual void _update_qh() {
VisualServer *vs=VisualServer::get_singleton();
Vector<Vector3> vts;
/*
static const int s = 20;
for(int i=0;i<s;i++) {
Matrix3 rot(Vector3(0,1,0),i*Math_PI/s);
for(int j=0;j<s;j++) {
Vector3 v;
v.x=Math::sin(j*Math_PI*2/s);
v.y=Math::cos(j*Math_PI*2/s);
vts.push_back( rot.xform(v*2 ) );
}
}*/
/*
Math::seed(0);
for(int i=0;i<50;i++) {
vts.push_back( Vector3(Math::randf()*2-1.0,Math::randf()*2-1.0,Math::randf()*2-1.0).normalized()*2);
}*/
/*
vts.push_back(Vector3(0,0,1));
vts.push_back(Vector3(0,0,-1));
vts.push_back(Vector3(0,1,0));
vts.push_back(Vector3(0,-1,0));
vts.push_back(Vector3(1,0,0));
vts.push_back(Vector3(-1,0,0));*/
/*
vts.push_back(Vector3(1,1,1));
vts.push_back(Vector3(1,-1,1));
vts.push_back(Vector3(-1,1,1));
vts.push_back(Vector3(-1,-1,1));
vts.push_back(Vector3(1,1,-1));
vts.push_back(Vector3(1,-1,-1));
vts.push_back(Vector3(-1,1,-1));
vts.push_back(Vector3(-1,-1,-1));
*/
DVector<Plane> convex_planes = Geometry::build_cylinder_planes(0.5,0.7,4,Vector3::AXIS_Z);
Geometry::MeshData convex_data = Geometry::build_convex_mesh(convex_planes);
vts=convex_data.vertices;
Geometry::MeshData md;
Error err = QuickHull::build(vts,md);
print_line("ERR: "+itos(err));
vs->mesh_remove_surface(mesh,0);
vs->mesh_add_surface_from_mesh_data(mesh,md);
//vs->scenario_set_debug(scenario,VS::SCENARIO_DEBUG_WIREFRAME);
/*
RID sm = vs->shader_create();
//vs->shader_set_fragment_code(sm,"OUT_ALPHA=mod(TIME,1);");
//vs->shader_set_vertex_code(sm,"OUT_VERTEX=IN_VERTEX*mod(TIME,1);");
vs->shader_set_fragment_code(sm,"OUT_DIFFUSE=vec3(1,0,1);OUT_GLOW=abs(sin(TIME));");
RID tcmat = vs->mesh_surface_get_material(test_cube,0);
vs->material_set_shader(tcmat,sm);
*/
}
virtual void input_event(const InputEvent& p_event) {
if (p_event.type==InputEvent::MOUSE_MOTION && p_event.mouse_motion.button_mask&4) {
ofs_x+=p_event.mouse_motion.relative_y/200.0;
ofs_y+=p_event.mouse_motion.relative_x/200.0;
}
if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed && p_event.mouse_button.button_index==1) {
QuickHull::debug_stop_after++;
_update_qh();
}
if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed && p_event.mouse_button.button_index==2) {
if (QuickHull::debug_stop_after>0)
QuickHull::debug_stop_after--;
_update_qh();
}
}
virtual void request_quit() {
quit=true;
}
virtual void init() {
VisualServer *vs=VisualServer::get_singleton();
mesh = vs->mesh_create();
scenario = vs->scenario_create();
QuickHull::debug_stop_after=0;
_update_qh();
instance = vs->instance_create2(mesh,scenario);
camera = vs->camera_create();
vs->camera_set_perspective( camera, 60.0,0.1, 100.0 );
viewport = vs->viewport_create();
vs->viewport_attach_camera( viewport, camera );
vs->viewport_attach_to_screen(viewport);
vs->viewport_set_scenario( viewport, scenario );
vs->camera_set_transform(camera, Transform( Matrix3(), Vector3(0,0,2 ) ) );
RID lightaux = vs->light_create( VisualServer::LIGHT_DIRECTIONAL );
vs->light_set_color( lightaux, VisualServer::LIGHT_COLOR_AMBIENT, Color(0.3,0.3,0.3) );
light = vs->instance_create2( lightaux,scenario );
vs->instance_set_transform(light,Transform(Matrix3(Vector3(0.1,0.4,0.7).normalized(),0.9)));
ofs_x=0;
ofs_y=0;
quit=false;
}
virtual bool idle(float p_time) {
return false;
}
virtual bool iteration(float p_time) {
VisualServer *vs=VisualServer::get_singleton();
Transform tr_camera;
tr_camera.rotate( Vector3(0,1,0), ofs_y );
tr_camera.rotate( Vector3(1,0,0),ofs_x );
tr_camera.translate(0,0,10);
vs->camera_set_transform( camera, tr_camera );
return quit;
}
virtual void finish() {
}
};
MainLoop* test() {
return memnew(TestMainLoop);
}
}

44
bin/tests/test_detailer.h Normal file
View file

@ -0,0 +1,44 @@
/*************************************************************************/
/* test_detailer.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef TEST_MULTIMESH_H
#define TEST_MULTIMESH_H
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
#include "os/main_loop.h"
namespace TestMultiMesh {
MainLoop* test();
}
#endif

1003
bin/tests/test_gdscript.cpp Normal file

File diff suppressed because it is too large Load diff

46
bin/tests/test_gdscript.h Normal file
View file

@ -0,0 +1,46 @@
/*************************************************************************/
/* test_gdscript.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef TEST_GDSCRIPT_H
#define TEST_GDSCRIPT_H
#include "os/main_loop.h"
namespace TestGDScript {
enum TestType {
TEST_TOKENIZER,
TEST_PARSER,
TEST_COMPILER
};
MainLoop* test(TestType p_type);
}
#endif // TEST_GDSCRIPT_H

399
bin/tests/test_gui.cpp Normal file
View file

@ -0,0 +1,399 @@
/*************************************************************************/
/* test_gui.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. */
/*************************************************************************/
#ifndef _3D_DISABLED
#include "test_gui.h"
#include "scene/main/scene_main_loop.h"
#include "os/os.h"
#include "scene/gui/control.h"
#include "scene/gui/button.h"
#include "scene/gui/label.h"
#include "scene/gui/line_edit.h"
#include "scene/gui/scroll_bar.h"
#include "scene/gui/popup_menu.h"
#include "scene/gui/option_button.h"
#include "scene/gui/spin_box.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/progress_bar.h"
#include "scene/gui/panel.h"
#include "scene/gui/tab_container.h"
#include "scene/gui/tree.h"
#include "scene/gui/rich_text_label.h"
#include "scene/gui/texture_frame.h"
#include "io/image_loader.h"
#include "print_string.h"
#include "scene/2d/sprite.h"
#include "scene/main/viewport.h"
#include "scene/3d/camera.h"
#include "scene/3d/test_cube.h"
namespace TestGUI {
class TestMainLoop : public SceneMainLoop {
Control *control;
public:
virtual void request_quit() {
quit();
}
virtual void init() {
SceneMainLoop::init();
#if 0
Viewport *vp = memnew( Viewport );
vp->set_world( Ref<World>( memnew( World )));
get_root()->add_child(vp);
vp->set_rect(Rect2(0,0,256,256));
vp->set_as_render_target(true);
vp->set_render_target_update_mode(Viewport::RENDER_TARGET_UPDATE_ALWAYS);
Camera *camera = memnew( Camera );
vp->add_child(camera);
camera->make_current();
TestCube *testcube = memnew( TestCube );
vp->add_child(testcube);
testcube->set_transform(Transform( Matrix3().rotated(Vector3(0,1,0),Math_PI*0.25), Vector3(0,0,-8)));
Sprite *sp = memnew( Sprite );
sp->set_texture( vp->get_render_target_texture() );
// sp->set_texture( ResourceLoader::load("res://ball.png") );
sp->set_pos(Point2(300,300));
get_root()->add_child(sp);
return;
#endif
Panel * frame = memnew( Panel );
frame->set_anchor( MARGIN_RIGHT, Control::ANCHOR_END );
frame->set_anchor( MARGIN_BOTTOM, Control::ANCHOR_END );
frame->set_end( Point2(0,0) );
get_root()->add_child( frame );
Label *label = memnew( Label );
label->set_pos( Point2( 80,90 ) );
label->set_size( Point2( 170,80 ) );
label->set_align( Label::ALIGN_FILL );
//label->set_text("There");
label->set_text("There was once upon a time a beautiful unicorn that loved to play with little girls...");
frame->add_child(label);
Button *button = memnew( Button );
button->set_pos( Point2( 20,20 ) );
button->set_size( Point2( 1,1 ) );
button->set_text("This is a biggie button");
frame->add_child( button );
#if 0
Sprite *tf = memnew( Sprite );
frame->add_child(tf);
Image img;
ImageLoader::load_image("LarvoClub.png",&img);
img.resize(512,512);
img.generate_mipmaps();
img.compress();
Ref<Texture> text = memnew( Texture );
text->create_from_image(img);
tf->set_texture(text);
tf->set_pos(Point2(50,50));
//tf->set_scale(Point2(0.3,0.3));
return;
#endif
Tree * tree = memnew( Tree );
tree->set_columns(2);
tree->set_pos( Point2( 230,210 ) );
tree->set_size( Point2( 150,250 ) );
TreeItem *item = tree->create_item();
item->set_editable(0,true);
item->set_text(0,"root");
item = tree->create_item( tree->get_root() );
item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
item->set_editable(0,true);
item->set_text(0,"check");
item->set_cell_mode(1, TreeItem::CELL_MODE_CHECK);
item->set_editable(1,true);
item->set_text(1,"check2");
item = tree->create_item( tree->get_root() );
item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
item->set_editable(0,true);
item->set_range_config(0,0,20,0.1);
item->set_range(0,2);
item->add_button(0,Theme::get_default()->get_icon("folder","FileDialog"));
item->set_cell_mode(1, TreeItem::CELL_MODE_RANGE);
item->set_editable(1,true);
item->set_range_config(1,0,20,0.1);
item->set_range(1,3);
item = tree->create_item( tree->get_root() );
item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
item->set_editable(0,true);
item->set_text(0,"Have,Many,Several,Options!");
item->set_range(0,2);
item = tree->create_item( item );
item->set_editable(0,true);
item->set_text(0,"Gershwin!");
frame->add_child(tree);
//control = memnew( Control );
//root->add_child( control );
LineEdit *line_edit = memnew( LineEdit );
line_edit->set_pos( Point2( 30,190 ) );
line_edit->set_size( Point2( 180,1 ) );
frame->add_child(line_edit);
HScrollBar *hscroll = memnew( HScrollBar );
hscroll->set_pos( Point2( 30,290 ) );
hscroll->set_size( Point2( 180,1 ) );
hscroll->set_max(10);
hscroll->set_page(4);
frame->add_child(hscroll);
SpinBox *spin = memnew( SpinBox );
spin->set_pos( Point2( 30,260 ) );
spin->set_size( Point2( 120,1 ) );
frame->add_child(spin);
hscroll->share(spin);
ProgressBar *progress = memnew( ProgressBar );
progress->set_pos( Point2( 30,330 ) );
progress->set_size( Point2( 120,1 ) );
frame->add_child(progress);
hscroll->share(progress);
MenuButton *menu_button = memnew( MenuButton );
menu_button->set_text("I'm a menu!");
menu_button->set_pos( Point2( 30,380 ) );
menu_button->set_size( Point2( 1,1 ) );
frame->add_child(menu_button);
PopupMenu *popup = menu_button->get_popup();
popup->add_item("Hello, testing");
popup->add_item("My Dearest");
popup->add_separator();
popup->add_item("Popup");
popup->add_check_item("Check Popup");
popup->set_item_checked(4,true);
OptionButton *options = memnew( OptionButton );
options->add_item("Hello, testing");
options->add_item("My Dearest");
options->set_pos( Point2( 230,180 ) );
options->set_size( Point2( 1,1 ) );
frame->add_child(options);
/*
Tree * tree = memnew( Tree );
tree->set_columns(2);
tree->set_pos( Point2( 230,210 ) );
tree->set_size( Point2( 150,250 ) );
TreeItem *item = tree->create_item();
item->set_editable(0,true);
item->set_text(0,"root");
item = tree->create_item( tree->get_root() );
item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
item->set_editable(0,true);
item->set_text(0,"check");
item = tree->create_item( tree->get_root() );
item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
item->set_editable(0,true);
item->set_range_config(0,0,20,0.1);
item->set_range(0,2);
item->add_button(0,Theme::get_default()->get_icon("folder","FileDialog"));
item = tree->create_item( tree->get_root() );
item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
item->set_editable(0,true);
item->set_text(0,"Have,Many,Several,Options!");
item->set_range(0,2);
frame->add_child(tree);
*/
RichTextLabel *richtext = memnew( RichTextLabel );
richtext->set_pos( Point2( 600,210 ) );
richtext->set_size( Point2( 180,250 ) );
richtext->set_anchor_and_margin(MARGIN_RIGHT,Control::ANCHOR_END,20);
frame->add_child(richtext);
richtext->add_text("Hello, My Friends!\n\nWelcome to the amazing world of ");
richtext->add_newline();
richtext->add_newline();
richtext->push_color(Color(1,0.5,0.5));
richtext->add_text("leprechauns");
richtext->pop();
#if 0
richtext->add_text(" and ");
richtext->push_color(Color(0,1.0,0.5));
richtext->add_text("faeries.\n");
richtext->pop();
richtext->add_text("In this new episode, we will attemp to ");
richtext->push_font(richtext->get_font("mono_font","Fonts"));
richtext->push_color(Color(0.7,0.5,1.0));
richtext->add_text("deliver something nice");
richtext->pop();
richtext->pop();
richtext->add_text(" to all the viewers! Unfortunately, I need to ");
richtext->push_underline();
richtext->add_text("keep writing a lot of text");
richtext->pop();
richtext->add_text(" so the label control overflows and the scrollbar appears.\n");
//richtext->push_indent(1);
//richtext->add_text("By the way, testing indent levels! Yohohoho! Everything should appear to the right sightly here!\n");
//richtext->pop();
richtext->push_meta("http://www.scrollingcapabilities.xz");
richtext->add_text("This allows to test for the scrolling capabilities ");
richtext->pop();
richtext->add_text("of the rich text label for huge text (not like this text will really be huge but, you know).\nAs long as it is so long that it will work nicely for a test/demo, then it's welcomed in my book...\nChanging subject, the day is cloudy today and I'm wondering if I'll get che chance to travel somewhere nice. Sometimes, watching the clouds from satellite images may give a nice insight about how pressure zones in our planet work, althogh it also makes it pretty obvious to see why most weather forecasts get it wrong so often.\nClouds are so difficult to predict!\nBut it's pretty cool how our civilization has adapted to having water falling from the sky each time it rains...");
//richtext->add_text("Hello!\nGorgeous..");
#endif
//richtext->push_meta("http://www.scrollingcapabilities.xz");
///richtext->add_text("Hello!\n");
//richtext->pop();
richtext->set_anchor(MARGIN_RIGHT,Control::ANCHOR_END);
TabContainer * tabc = memnew( TabContainer );
Control *ctl= memnew( Control );
ctl->set_name("tab 1");
tabc->add_child(ctl);
ctl= memnew( Control );
ctl->set_name("tab 2");
tabc->add_child(ctl);
label = memnew( Label );
label->set_text("Some Label");
label->set_pos( Point2(20,20) );
ctl->add_child(label);;
ctl= memnew( Control );
ctl->set_name("tab 3");
button = memnew( Button );
button->set_text("Some Button");
button->set_pos( Point2(30,50) );
ctl->add_child(button);;
tabc->add_child(ctl);
frame->add_child(tabc);
tabc->set_pos( Point2( 400,210 ) );
tabc->set_size( Point2( 180,250 ) );
Ref<ImageTexture> text = memnew( ImageTexture );
text->load("test_data/concave.png");
Sprite* sprite = memnew(Sprite);
sprite->set_texture(text);
sprite->set_pos(Point2(300, 300));
frame->add_child(sprite);
sprite->show();
Sprite* sprite2 = memnew(Sprite);
sprite->set_texture(text);
sprite->add_child(sprite2);
sprite2->set_pos(Point2(50, 50));
sprite2->show();
}
};
MainLoop* test() {
return memnew( TestMainLoop );
}
}
#endif

44
bin/tests/test_gui.h Normal file
View file

@ -0,0 +1,44 @@
/*************************************************************************/
/* test_gui.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef TEST_GUI_H
#define TEST_GUI_H
#include "os/main_loop.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
namespace TestGUI {
MainLoop* test();
}
#endif

77
bin/tests/test_image.cpp Normal file
View file

@ -0,0 +1,77 @@
/*************************************************************************/
/* test_image.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 "test_image.h"
#include "os/main_loop.h"
#include "math_funcs.h"
#include "print_string.h"
#include "io/image_loader.h"
namespace TestImage {
class TestMainLoop : public MainLoop {
bool quit;
public:
virtual void input_event(const InputEvent& p_event) {
}
virtual void init() {
quit=false;
}
virtual bool iteration(float p_time) {
return quit;
}
virtual bool idle(float p_time) {
return quit;
}
virtual void finish() {
}
};
MainLoop* test() {
Image img;
ImageLoader::load_image("as1.png",&img);
img.resize(512,512);
return memnew( TestMainLoop );
}
}

44
bin/tests/test_image.h Normal file
View file

@ -0,0 +1,44 @@
/*************************************************************************/
/* test_image.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef TEST_IMAGE_H
#define TEST_IMAGE_H
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
#include "os/main_loop.h"
namespace TestImage {
MainLoop* test();
}
#endif

208
bin/tests/test_io.cpp Normal file
View file

@ -0,0 +1,208 @@
/*************************************************************************/
/* test_io.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 "test_io.h"
#ifdef MINIZIP_ENABLED
#include "os/main_loop.h"
#include "os/os.h"
#include "scene/resources/texture.h"
#include "print_string.h"
#include "io/resource_loader.h"
#include "io/resource_saver.h"
#include "os/dir_access.h"
#include "core/globals.h"
#include "io/file_access_memory.h"
namespace TestIO {
class TestMainLoop : public MainLoop {
bool quit;
public:
virtual void input_event(const InputEvent& p_event) {
}
virtual bool idle(float p_time) {
return false;
}
virtual void request_quit() {
quit=true;
}
virtual void init() {
quit=true;
}
virtual bool iteration(float p_time) {
return quit;
}
virtual void finish() {
}
};
MainLoop* test() {
print_line("this is test io");
DirAccess* da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
da->change_dir(".");
print_line("Opening current dir "+ da->get_current_dir());
String entry;
da->list_dir_begin();
while ( (entry = da->get_next()) != "") {
print_line("entry "+entry+" is dir: " + Variant(da->current_is_dir()));
};
da->list_dir_end();
RES texture = ResourceLoader::load("test_data/rock.png");
ERR_FAIL_COND_V(texture.is_null(), NULL);
ResourceSaver::save("test_data/rock.xml",texture);
print_line("localize paths");
print_line(Globals::get_singleton()->localize_path("algo.xml"));
print_line(Globals::get_singleton()->localize_path("c:\\windows\\algo.xml"));
print_line(Globals::get_singleton()->localize_path(Globals::get_singleton()->get_resource_path()+"/something/something.xml"));
print_line(Globals::get_singleton()->localize_path("somedir/algo.xml"));
{
FileAccess* z = FileAccess::open("test_data/archive.zip", FileAccess::READ);
int len = z->get_len();
Vector<uint8_t> zip;
zip.resize(len);
z->get_buffer(&zip[0], len);
z->close();
memdelete(z);
FileAccessMemory::register_file("a_package", zip);
FileAccess::make_default<FileAccessMemory>(FileAccess::ACCESS_RESOURCES);
FileAccess::make_default<FileAccessMemory>(FileAccess::ACCESS_FILESYSTEM);
FileAccess::make_default<FileAccessMemory>(FileAccess::ACCESS_USERDATA);
print_line("archive test");
#if 0
Archive arch;
Archive::get_singleton()->add_package("a_package");
FileAccessArchive f;
print_line("opening for read");
f._open("file.txt", FileAccess::READ);
int pos = f.get_pos();
printf("file has %i bytes, initial pos %i\n", (int)f.get_len(), pos);
do {
printf("%c", f.get_8());
} while (!f.eof_reached());
print_line("opening for stored seek");
f.open("seek.bin", FileAccess::READ);
pos = f.get_pos();
printf("byte at pos %i is %i\n", pos, (int)f.get_8());
f.seek(128);
pos = f.get_pos();
printf("byte at pos %i is %i\n", pos, (int)f.get_8());
print_line("opening for deflated seek");
f.open("seek_deflated.bin", FileAccess::READ);
pos = f.get_pos();
printf("byte at pos %i is %i\n", pos, (int)f.get_8());
f.seek(128);
pos = f.get_pos();
printf("byte at pos %i is %i\n", pos, (int)f.get_8());
pos = f.get_pos();
printf("byte at pos %i is %i\n", pos, (int)f.get_8());
pos = f.get_pos();
printf("byte at pos %i is %i\n", pos, (int)f.get_8());
f.seek(256);
pos = f.get_pos();
printf("byte at pos %i is %i\n", pos, (int)f.get_8());
pos = f.get_pos();
printf("byte at pos %i is %i\n", pos, (int)f.get_8());
pos = f.get_pos();
printf("byte at pos %i is %i\n", pos, (int)f.get_8());
f.seek(4);
pos = f.get_pos();
printf("byte at pos %i is %i\n", pos, (int)f.get_8());
pos = f.get_pos();
printf("byte at pos %i is %i\n", pos, (int)f.get_8());
pos = f.get_pos();
printf("byte at pos %i is %i\n", pos, (int)f.get_8());
f.close();
DirAccessArchive d;
String dir = "../blah1/blah2/blahask/../blah3/.//blah4/";
printf("changing dir to %s\n", dir.utf8().get_data());
d.change_dir(dir);
printf("current dir is %s\n", d.get_current_dir().utf8().get_data());
FileAccessMemory::cleanup();
#endif
};
print_line("test done");
return memnew( TestMainLoop );
}
}
#else
namespace TestIO {
MainLoop* test() {
return NULL;
}
}
#endif

44
bin/tests/test_io.h Normal file
View file

@ -0,0 +1,44 @@
/*************************************************************************/
/* test_io.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef TEST_IO_H
#define TEST_IO_H
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
#include "os/main_loop.h"
namespace TestIO {
MainLoop* test();
}
#endif

192
bin/tests/test_main.cpp Normal file
View file

@ -0,0 +1,192 @@
/*************************************************************************/
/* test_main.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 "list.h"
#include "os/main_loop.h"
#ifdef DEBUG_ENABLED
#include "test_string.h"
#include "test_containers.h"
#include "test_math.h"
#include "test_gui.h"
#include "test_render.h"
#include "test_sound.h"
#include "test_misc.h"
#include "test_physics.h"
#include "test_physics_2d.h"
#include "test_python.h"
#include "test_io.h"
#include "test_particles.h"
#include "test_detailer.h"
#include "test_shader_lang.h"
#include "test_gdscript.h"
#include "test_image.h"
const char ** tests_get_names() {
static const char* test_names[]={
"string",
"containers",
"math",
"render",
"particles",
"multimesh",
"gui",
"io",
"shaderlang",
NULL
};
return test_names;
}
MainLoop* test_main(String p_test,const List<String>& p_args) {
if (p_test=="string") {
return TestString::test();
}
if (p_test=="containers") {
return TestContainers::test();
}
if (p_test=="math") {
return TestMath::test();
}
if (p_test=="physics") {
return TestPhysics::test();
}
if (p_test=="physics_2d") {
return TestPhysics2D::test();
}
if (p_test=="misc") {
return TestMisc::test();
}
if (p_test=="render") {
return TestRender::test();
}
#ifndef _3D_DISABLED
if (p_test=="gui") {
return TestGUI::test();
}
#endif
if (p_test=="sound") {
return TestSound::test();
}
if (p_test=="io") {
return TestIO::test();
}
if (p_test=="particles") {
return TestParticles::test();
}
if (p_test=="multimesh") {
return TestMultiMesh::test();
}
if (p_test=="shaderlang") {
return TestShaderLang::test();
}
if (p_test=="gd_tokenizer") {
return TestGDScript::test(TestGDScript::TEST_TOKENIZER);
}
if (p_test=="gd_parser") {
return TestGDScript::test(TestGDScript::TEST_PARSER);
}
if (p_test=="gd_compiler") {
return TestGDScript::test(TestGDScript::TEST_COMPILER);
}
if (p_test=="image") {
return TestImage::test();
}
if (p_test=="detailer") {
return TestMultiMesh::test();
}
#ifdef PYTHON_ENABLED
if (p_test=="python") {
return TestPython::test();
}
#endif
return NULL;
}
#else
const char ** tests_get_names() {
static const char* test_names[]={
NULL
};
return test_names;
}
MainLoop* test_main(String p_test,const List<String>& p_args) {
return NULL;
}
#endif

41
bin/tests/test_main.h Normal file
View file

@ -0,0 +1,41 @@
/*************************************************************************/
/* test_main.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef TEST_MAIN_H
#define TEST_MAIN_H
#include "ustring.h"
#include "list.h"
const char ** tests_get_names();
MainLoop* test_main(String p_test,const List<String>& p_args);
#endif

300
bin/tests/test_math.cpp Normal file
View file

@ -0,0 +1,300 @@
/*************************************************************************/
/* test_math.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 "test_math.h"
#include "ustring.h"
#include "print_string.h"
#include "transform.h"
#include "matrix3.h"
#include "math_funcs.h"
#include "camera_matrix.h"
#include "scene/main/node.h"
#include "variant.h"
#include "servers/visual/shader_language.h"
#include "os/keyboard.h"
#include "scene/resources/texture.h"
#include "vmap.h"
#include "os/os.h"
namespace TestMath {
void test_vec(Plane p_vec) {
CameraMatrix cm;
cm.set_perspective(45,1,0,100);
Plane v0=cm.xform4(p_vec);
print_line("out: "+v0);
v0.normal.z = (v0.d/100.0 *2.0-1.0) * v0.d;
print_line("out_F: "+v0);
/*v0: 0, 0, -0.1, 0.1
v1: 0, 0, 0, 0.1
fix: 0, 0, 0, 0.1
v0: 0, 0, 1.302803, 1.5
v1: 0, 0, 1.401401, 1.5
fix: 0, 0, 1.401401, 1.5
v0: 0, 0, 25.851850, 26
v1: 0, 0, 25.925926, 26
fix: 0, 0, 25.925924, 26
v0: 0, 0, 49.899902, 50
v1: 0, 0, 49.949947, 50
fix: 0, 0, 49.949951, 50
v0: 0, 0, 100, 100
v1: 0, 0, 100, 100
fix: 0, 0, 100, 100
*/
}
MainLoop* test() {
{
// print_line("NUM: "+itos(237641278346127));
print_line("NUM: "+itos(-128));
return NULL;
}
{
Vector3 v(1,2,3);
v.normalize();
float a=0.3;
//Quat q(v,a);
Matrix3 m(v,a);
Vector3 v2(7,3,1);
v2.normalize();
float a2=0.8;
//Quat q(v,a);
Matrix3 m2(v2,a2);
Quat q=m;
Quat q2=m2;
Matrix3 m3 = m.inverse() * m2;
Quat q3 = (q.inverse() * q2);//.normalized();
print_line(Quat(m3));
print_line(q3);
print_line("before v: "+v+" a: "+rtos(a));
q.get_axis_and_angle(v,a);
print_line("after v: "+v+" a: "+rtos(a));
}
return NULL;
String ret;
List<String> args;
args.push_back("-l");
Error err = OS::get_singleton()->execute("/bin/ls",args,true,NULL,&ret);
print_line("error: "+itos(err));
print_line(ret);
return NULL;
Matrix3 m3;
m3.rotate(Vector3(1,0,0),0.2);
m3.rotate(Vector3(0,1,0),1.77);
m3.rotate(Vector3(0,0,1),212);
Matrix3 m32;
m32.set_euler(m3.get_euler());
print_line("ELEULEEEEEEEEEEEEEEEEEER: "+m3.get_euler()+" vs "+m32.get_euler());
return NULL;
{
Dictionary d;
d["momo"]=1;
Dictionary b=d;
b["44"]=4;
}
return NULL;
print_line("inters: "+rtos(Geometry::segment_intersects_circle(Vector2(-5,0),Vector2(-2,0),Vector2(),1.0)));
print_line("cross: "+Vector3(1,2,3).cross(Vector3(4,5,7)));
print_line("dot: "+rtos(Vector3(1,2,3).dot(Vector3(4,5,7))));
print_line("abs: "+Vector3(-1,2,-3).abs());
print_line("distance_to: "+rtos(Vector3(1,2,3).distance_to(Vector3(4,5,7))));
print_line("distance_squared_to: "+rtos(Vector3(1,2,3).distance_squared_to(Vector3(4,5,7))));
print_line("plus: "+(Vector3(1,2,3)+Vector3(Vector3(4,5,7))));
print_line("minus: "+(Vector3(1,2,3)-Vector3(Vector3(4,5,7))));
print_line("mul: "+(Vector3(1,2,3)*Vector3(Vector3(4,5,7))));
print_line("div: "+(Vector3(1,2,3)/Vector3(Vector3(4,5,7))));
print_line("mul scalar: "+(Vector3(1,2,3)*2));
print_line("premul scalar: "+(2*Vector3(1,2,3)));
print_line("div scalar: "+(Vector3(1,2,3)/3.0));
print_line("length: "+rtos(Vector3(1,2,3).length()));
print_line("length squared: "+rtos(Vector3(1,2,3).length_squared()));
print_line("normalized: "+Vector3(1,2,3).normalized());
print_line("inverse: "+Vector3(1,2,3).inverse());
{
Vector3 v(4,5,7);
v.normalize();
print_line("normalize: "+v);
}
{
Vector3 v(4,5,7);
v+=Vector3(1,2,3);
print_line("+=: "+v);
}
{
Vector3 v(4,5,7);
v-=Vector3(1,2,3);
print_line("-=: "+v);
}
{
Vector3 v(4,5,7);
v*=Vector3(1,2,3);
print_line("*=: "+v);
}
{
Vector3 v(4,5,7);
v/=Vector3(1,2,3);
print_line("/=: "+v);
}
{
Vector3 v(4,5,7);
v*=2.0;
print_line("scalar *=: "+v);
}
{
Vector3 v(4,5,7);
v/=2.0;
print_line("scalar /=: "+v);
}
#if 0
print_line(String("C:\\momo\\.\\popo\\..\\gongo").simplify_path());
print_line(String("res://../popo/..//gongo").simplify_path());
print_line(String("res://..").simplify_path());
DVector<uint8_t> a;
DVector<uint8_t> b;
a.resize(20);
b=a;
b.resize(30);
a=b;
#endif
#if 0
String za = String::utf8("á");
printf("unicode: %x\n",za[0]);
CharString cs=za.utf8();
for(int i=0;i<cs.size();i++) {
uint32_t v = uint8_t(cs[i]);
printf("%i - %x\n",i,v);
}
return NULL;
print_line(String("C:\\window\\system\\momo").path_to("C:\\window\\momonga"));
print_line(String("res://momo/sampler").path_to("res://pindonga"));
print_line(String("/margarito/terere").path_to("/margarito/pilates"));
print_line(String("/algo").path_to("/algo"));
print_line(String("c:").path_to("c:\\"));
print_line(String("/").path_to("/"));
print_line(itos(sizeof(Variant)));
return NULL;
Vector<StringName> path;
path.push_back("three");
path.push_back("two");
path.push_back("one");
path.push_back("comeon");
path.revert();
NodePath np(path,true);
print_line(np);
return NULL;
bool a=2;
print_line(Variant(a));
Matrix32 mat2_1;
mat2_1.rotate(0.5);
Matrix32 mat2_2;
mat2_2.translate(Vector2(1,2));
Matrix32 mat2_3 = mat2_1 * mat2_2;
mat2_3.affine_invert();
print_line(mat2_3.elements[0]);
print_line(mat2_3.elements[1]);
print_line(mat2_3.elements[2]);
Transform mat3_1;
mat3_1.basis.rotate(Vector3(0,0,1),0.5);
Transform mat3_2;
mat3_2.translate(Vector3(1,2,0));
Transform mat3_3 = mat3_1 * mat3_2;
mat3_3.affine_invert();
print_line(mat3_3.basis.get_axis(0));
print_line(mat3_3.basis.get_axis(1));
print_line(mat3_3.origin);
#endif
return NULL;
}
}

40
bin/tests/test_math.h Normal file
View file

@ -0,0 +1,40 @@
/*************************************************************************/
/* test_math.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef TEST_MATH_H
#define TEST_MATH_H
#include "os/main_loop.h"
namespace TestMath {
MainLoop* test();
}
#endif

499
bin/tests/test_misc.cpp Normal file
View file

@ -0,0 +1,499 @@
/*************************************************************************/
/* test_misc.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 "test_misc.h"
#include "servers/visual_server.h"
#include "os/main_loop.h"
#include "math_funcs.h"
#include "print_string.h"
namespace TestMisc {
struct ConvexTestResult
{
Vector3 edgeA[2];
Vector3 edgeB[2];
bool valid;
Vector3 contactA;
Vector3 contactB;
Vector3 contactNormal;
float depth;
/*
Vector3 contactA;
Vector3 contactB;
Vector3 contactNormal;
Vector3 contactX;
Vector3 contactY;
Vector3 edgeA[2];
Vector3 edgeB[2];
float depth;
bool valid;
bool isEdgeEdge;
bool needTransform;
neBool ComputerEdgeContactPoint(ConvexTestResult & res);
neBool ComputerEdgeContactPoint2(float & au, float & bu);
void Reverse()
{
neSwap(contactA, contactB);
contactNormal *= -1.0f;
}*/
bool ComputerEdgeContactPoint2(float & au, float & bu);
};
bool ConvexTestResult::ComputerEdgeContactPoint2(float & au, float & bu)
{
float d1343, d4321, d1321, d4343, d2121;
float numer, denom;
Vector3 p13;
Vector3 p43;
Vector3 p21;
Vector3 diff;
p13 = (edgeA[0]) - (edgeB[0]);
p43 = (edgeB[1]) - (edgeB[0]);
if ( p43.length_squared() < CMP_EPSILON2 )
{
valid = false;
goto ComputerEdgeContactPoint2_Exit;
}
p21 = (edgeA[1]) - (edgeA[0]);
if ( p21.length_squared()<CMP_EPSILON2 )
{
valid = false;
goto ComputerEdgeContactPoint2_Exit;
}
d1343 = p13.dot(p43);
d4321 = p43.dot(p21);
d1321 = p13.dot(p21);
d4343 = p43.dot(p43);
d2121 = p21.dot(p21);
denom = d2121 * d4343 - d4321 * d4321;
if (ABS(denom) < CMP_EPSILON)
{
valid = false;
goto ComputerEdgeContactPoint2_Exit;
}
numer = d1343 * d4321 - d1321 * d4343;
au = numer / denom;
bu = (d1343 + d4321 * (au)) / d4343;
if (au < 0.0f || au >= 1.0f)
{
valid = false;
}
else if (bu < 0.0f || bu >= 1.0f)
{
valid = false;
}
else
{
valid = true;
}
{
Vector3 tmpv;
tmpv = p21 * au;
contactA = (edgeA[0]) + tmpv;
tmpv = p43 * bu;
contactB = (edgeB[0]) + tmpv;
}
diff = contactA - contactB;
depth = Math::sqrt(diff.dot(diff));
return true;
ComputerEdgeContactPoint2_Exit:
return false;
}
struct neCollisionResult {
float depth;
bool penetrate;
Matrix3 collisionFrame;
Vector3 contactA;
Vector3 contactB;
};
struct TConvex {
float radius;
float half_height;
float CylinderRadius() const { return radius; }
float CylinderHalfHeight() const { return half_height; }
};
float GetDistanceFromLine2(Vector3 v, Vector3 & project, const Vector3 & pointA, const Vector3 & pointB)
{
Vector3 ba = pointB - pointA;
float len = ba.length();
if (len<CMP_EPSILON)
ba=Vector3();
else
ba *= 1.0f / len;
Vector3 pa = v - pointA;
float k = pa.dot(ba);
project = pointA + ba * k;
Vector3 diff = v - project;
return diff.length();
}
void TestCylinderVertEdge(neCollisionResult & result, Vector3 & edgeA1, Vector3 & edgeA2, Vector3 & vertB,
TConvex & cA, TConvex & cB, Transform & transA, Transform & transB, bool flip)
{
Vector3 project;
float dist = GetDistanceFromLine2(vertB,project, edgeA1, edgeA2);
float depth = cA.CylinderRadius() + cB.CylinderRadius() - dist;
if (depth <= 0.0f)
return;
if (depth <= result.depth)
return;
result.penetrate = true;
result.depth = depth;
if (!flip)
{
result.collisionFrame.set_axis(2,(project - vertB).normalized());
result.contactA = project - result.collisionFrame.get_axis(2) * cA.CylinderRadius();
result.contactB = vertB + result.collisionFrame.get_axis(2) * cB.CylinderRadius();
}
else
{
result.collisionFrame.set_axis(2,(vertB - project).normalized());
result.contactA = vertB - result.collisionFrame.get_axis(2) * cB.CylinderRadius();
result.contactB = project + result.collisionFrame.get_axis(2) * cA.CylinderRadius();
}
}
void TestCylinderVertVert(neCollisionResult & result, Vector3 & vertA, Vector3 & vertB,
TConvex & cA, TConvex & cB, Transform & transA, Transform & transB)
{
Vector3 diff = vertA - vertB;
float dist = diff.length();
float depth = cA.CylinderRadius() + cB.CylinderRadius() - dist;
if (depth <= 0.0f)
return;
if (depth <= result.depth)
return;
result.penetrate = true;
result.depth = depth;
result.collisionFrame.set_axis(2, diff * (1.0f / dist));
result.contactA = vertA - result.collisionFrame.get_axis(2) * cA.CylinderRadius();
result.contactB = vertB + result.collisionFrame.get_axis(2) * cB.CylinderRadius();
}
void Cylinder2CylinderTest(neCollisionResult & result, TConvex & cA, Transform & transA, TConvex & cB, Transform & transB)
{
result.penetrate = false;
Vector3 dir = transA.basis.get_axis(1).cross(transB.basis.get_axis(1));
float len = dir.length();
// bool isParallel = len<CMP_EPSILON;
// int doVertCheck = 0;
ConvexTestResult cr;
cr.edgeA[0] = transA.origin + transA.basis.get_axis(1) * cA.CylinderHalfHeight();
cr.edgeA[1] = transA.origin - transA.basis.get_axis(1) * cA.CylinderHalfHeight();
cr.edgeB[0] = transB.origin + transB.basis.get_axis(1) * cB.CylinderHalfHeight();
cr.edgeB[1] = transB.origin - transB.basis.get_axis(1) * cB.CylinderHalfHeight();
// float dot = transA.basis.get_axis(1).dot(transB.basis.get_axis(1));
if (len>CMP_EPSILON)
{
float au, bu;
cr.ComputerEdgeContactPoint2(au, bu);
if (cr.valid)
{
float depth = cA.CylinderRadius() + cB.CylinderRadius() - cr.depth;
if (depth <= 0.0f)
return;
result.depth = depth;
result.penetrate = true;
result.collisionFrame.set_axis(2, (cr.contactA - cr.contactB)*(1.0f / cr.depth));
result.contactA = cr.contactA - result.collisionFrame.get_axis(2) * cA.CylinderRadius();
result.contactB = cr.contactB + result.collisionFrame.get_axis(2) * cB.CylinderRadius();
return;
}
}
result.depth = -1.0e6f;
int i;
for (i = 0; i < 2; i++)
{
//project onto edge b
Vector3 diff = cr.edgeA[i] - cr.edgeB[1];
float dot = diff.dot(transB.basis.get_axis(1));
if (dot < 0.0f)
{
TestCylinderVertVert(result, cr.edgeA[i], cr.edgeB[1], cA, cB, transA, transB);
}
else if (dot > (2.0f * cB.CylinderHalfHeight()))
{
TestCylinderVertVert(result, cr.edgeA[i], cr.edgeB[0], cA, cB, transA, transB);
}
else
{
TestCylinderVertEdge(result, cr.edgeB[0], cr.edgeB[1], cr.edgeA[i], cB, cA, transB, transA, true);
}
}
for (i = 0; i < 2; i++)
{
//project onto edge b
Vector3 diff = cr.edgeB[i] - cr.edgeA[1];
float dot = diff.dot(transA.basis.get_axis(1));
if (dot < 0.0f)
{
TestCylinderVertVert(result, cr.edgeB[i], cr.edgeA[1], cA, cB, transA, transB);
}
else if (dot > (2.0f * cB.CylinderHalfHeight()))
{
TestCylinderVertVert(result, cr.edgeB[i], cr.edgeA[0], cA, cB, transA, transB);
}
else
{
TestCylinderVertEdge(result, cr.edgeA[0], cr.edgeA[1], cr.edgeB[i], cA, cB, transA, transB, false);
}
}
}
class TestMainLoop : public MainLoop {
RID meshA;
RID meshB;
RID poly;
RID instance;
RID camera;
RID viewport;
RID boxA;
RID boxB;
RID scenario;
Transform rot_a;
Transform rot_b;
bool quit;
public:
virtual void input_event(const InputEvent& p_event) {
if (p_event.type==InputEvent::MOUSE_MOTION && p_event.mouse_motion.button_mask&BUTTON_MASK_LEFT) {
rot_b.origin.y+=-p_event.mouse_motion.relative_y/100.0;
rot_b.origin.x+=p_event.mouse_motion.relative_x/100.0;
}
if (p_event.type==InputEvent::MOUSE_MOTION && p_event.mouse_motion.button_mask&BUTTON_MASK_MIDDLE) {
//rot_b.origin.x+=-p_event.mouse_motion.relative_y/100.0;
rot_b.origin.z+=p_event.mouse_motion.relative_x/100.0;
}
if (p_event.type==InputEvent::MOUSE_MOTION && p_event.mouse_motion.button_mask&BUTTON_MASK_RIGHT) {
float rot_x=-p_event.mouse_motion.relative_y/100.0;
float rot_y=p_event.mouse_motion.relative_x/100.0;
rot_b.basis = rot_b.basis * Matrix3(Vector3(1,0,0),rot_x) * Matrix3(Vector3(0,1,0),rot_y);
}
}
virtual void request_quit() {
quit=true;
}
virtual void init() {
VisualServer *vs=VisualServer::get_singleton();
camera = vs->camera_create();
viewport = vs->viewport_create();
vs->viewport_attach_to_screen(viewport);
vs->viewport_attach_camera( viewport, camera );
vs->camera_set_transform(camera, Transform( Matrix3(), Vector3(0,0,3 ) ) );
/* CONVEX SHAPE */
DVector<Plane> cylinder_planes = Geometry::build_cylinder_planes(0.5,2,9,Vector3::AXIS_Y);
RID cylinder_material = vs->fixed_material_create();
vs->fixed_material_set_param( cylinder_material, VisualServer::FIXED_MATERIAL_PARAM_DIFFUSE, Color(0.8,0.2,0.9));
vs->material_set_flag( cylinder_material, VisualServer::MATERIAL_FLAG_ONTOP,true);
vs->material_set_flag( cylinder_material, VisualServer::MATERIAL_FLAG_WIREFRAME,true);
vs->material_set_flag( cylinder_material, VisualServer::MATERIAL_FLAG_DOUBLE_SIDED,true);
vs->material_set_flag( cylinder_material, VisualServer::MATERIAL_FLAG_UNSHADED,true);
RID cylinder_mesh = vs->mesh_create();
Geometry::MeshData cylinder_data = Geometry::build_convex_mesh(cylinder_planes);
vs->mesh_add_surface_from_mesh_data(cylinder_mesh,cylinder_data);
vs->mesh_surface_set_material( cylinder_mesh, 0, cylinder_material );
meshA=vs->instance_create2(cylinder_mesh,scenario);
meshB=vs->instance_create2(cylinder_mesh,scenario);
boxA=vs->instance_create2(vs->get_test_cube(),scenario);
boxB=vs->instance_create2(vs->get_test_cube(),scenario);
/*
RID lightaux = vs->light_create( VisualServer::LIGHT_OMNI );
vs->light_set_var( lightaux, VisualServer::LIGHT_VAR_RADIUS, 80 );
vs->light_set_var( lightaux, VisualServer::LIGHT_VAR_ATTENUATION, 1 );
vs->light_set_var( lightaux, VisualServer::LIGHT_VAR_ENERGY, 1.5 );
light = vs->instance_create2( lightaux );
*/
RID lightaux = vs->light_create( VisualServer::LIGHT_DIRECTIONAL );
vs->light_set_color( lightaux, VisualServer::LIGHT_COLOR_AMBIENT, Color(0.0,0.0,0.0) );
//vs->light_set_shadow( lightaux, true );
RID light = vs->instance_create2( lightaux,scenario );
//rot_a=Transform(Matrix3(Vector3(1,0,0),Math_PI/2.0),Vector3());
rot_b=Transform(Matrix3(),Vector3(2,0,0));
//rot_x=0;
//rot_y=0;
quit=false;
}
virtual bool idle(float p_time) {
VisualServer *vs=VisualServer::get_singleton();
vs->instance_set_transform(meshA,rot_a);
vs->instance_set_transform(meshB,rot_b);
neCollisionResult res;
TConvex a;
a.radius=0.5;
a.half_height=1;
Cylinder2CylinderTest(res,a,rot_a,a,rot_b);
if (res.penetrate) {
Matrix3 scale;
scale.scale(Vector3(0.1,0.1,0.1));
vs->instance_set_transform(boxA,Transform(scale,res.contactA));
vs->instance_set_transform(boxB,Transform(scale,res.contactB));
print_line("depth: "+rtos(res.depth));
} else {
Matrix3 scale;
scale.scale(Vector3());
vs->instance_set_transform(boxA,Transform(scale,res.contactA));
vs->instance_set_transform(boxB,Transform(scale,res.contactB));
}
print_line("collided: "+itos(res.penetrate));
return false;
}
virtual bool iteration(float p_time) {
return quit;
}
virtual void finish() {
}
};
MainLoop* test() {
return memnew( TestMainLoop );
}
}

40
bin/tests/test_misc.h Normal file
View file

@ -0,0 +1,40 @@
/*************************************************************************/
/* test_misc.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef TEST_MISC_H
#define TEST_MISC_H
#include "os/main_loop.h"
namespace TestMisc {
MainLoop* test();
}
#endif

View file

@ -0,0 +1,121 @@
/*************************************************************************/
/* test_particles.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 "test_particles.h"
#include "servers/visual_server.h"
#include "os/main_loop.h"
#include "math_funcs.h"
#include "print_string.h"
namespace TestParticles {
class TestMainLoop : public MainLoop {
RID particles;
RID instance;
RID camera;
RID viewport;
RID light;
RID scenario;
struct InstanceInfo {
RID instance;
Transform base;
Vector3 rot_axis;
};
List<InstanceInfo> instances;
float ofs;
bool quit;
public:
virtual void input_event(const InputEvent& p_event) {
}
virtual void request_quit() {
quit=true;
}
virtual void init() {
VisualServer *vs=VisualServer::get_singleton();
particles = vs->particles_create();
vs->particles_set_amount(particles,1000);
instance = vs->instance_create2(particles,scenario);
camera = vs->camera_create();
// vs->camera_set_perspective( camera, 60.0,0.1, 100.0 );
viewport = vs->viewport_create();
vs->viewport_attach_camera( viewport, camera );
vs->camera_set_transform(camera, Transform( Matrix3(), Vector3(0,0,20 ) ) );
/*
RID lightaux = vs->light_create( VisualServer::LIGHT_OMNI );
vs->light_set_var( lightaux, VisualServer::LIGHT_VAR_RADIUS, 80 );
vs->light_set_var( lightaux, VisualServer::LIGHT_VAR_ATTENUATION, 1 );
vs->light_set_var( lightaux, VisualServer::LIGHT_VAR_ENERGY, 1.5 );
light = vs->instance_create2( lightaux );
*/
RID lightaux = vs->light_create( VisualServer::LIGHT_DIRECTIONAL );
vs->light_set_color( lightaux, VisualServer::LIGHT_COLOR_AMBIENT, Color(0.0,0.0,0.0) );
light = vs->instance_create2( lightaux, scenario );
ofs=0;
quit=false;
}
virtual bool idle(float p_time) {
return false;
}
virtual bool iteration(float p_time) {
// VisualServer *vs=VisualServer::get_singleton();
ofs+=p_time;
return quit;
}
virtual void finish() {
}
};
MainLoop* test() {
return memnew( TestMainLoop );
}
}

View file

@ -0,0 +1,43 @@
/*************************************************************************/
/* test_particles.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef TEST_PARTICLES_H
#define TEST_PARTICLES_H
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
#include "os/main_loop.h"
namespace TestParticles {
MainLoop* test();
}
#endif

662
bin/tests/test_physics.cpp Normal file
View file

@ -0,0 +1,662 @@
/*************************************************************************/
/* test_physics.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 "test_physics.h"
#include "servers/visual_server.h"
#include "servers/physics_server.h"
#include "os/main_loop.h"
#include "math_funcs.h"
#include "print_string.h"
#include "map.h"
#include "os/os.h"
#include "quick_hull.h"
class TestPhysicsMainLoop : public MainLoop {
OBJ_TYPE( TestPhysicsMainLoop, MainLoop );
enum {
LINK_COUNT = 20,
};
RID test_cube;
RID plane;
RID sphere;
RID light;
RID camera;
RID mover;
RID scenario;
RID space;
RID character;
float ofs_x,ofs_y;
Point2 joy_direction;
List<RID> bodies;
Map<PhysicsServer::ShapeType,RID> type_shape_map;
Map<PhysicsServer::ShapeType,RID> type_mesh_map;
void body_changed_transform(Object *p_state, RID p_visual_instance) {
PhysicsDirectBodyState *state = (PhysicsDirectBodyState*)p_state;
VisualServer *vs=VisualServer::get_singleton();
Transform t=state->get_transform();
//t.basis.scale( Vector3(1.0,0.5,0.2) );
vs->instance_set_transform(p_visual_instance,t);
}
bool quit;
protected:
static void _bind_methods() {
ObjectTypeDB::bind_method("body_changed_transform",&TestPhysicsMainLoop::body_changed_transform);
}
RID create_body(PhysicsServer::ShapeType p_shape, PhysicsServer::BodyMode p_body,const Transform p_location,bool p_active_default=true,const Transform&p_shape_xform=Transform()) {
VisualServer *vs=VisualServer::get_singleton();
PhysicsServer * ps = PhysicsServer::get_singleton();
RID mesh_instance = vs->instance_create2(type_mesh_map[p_shape],scenario);
RID body = ps->body_create(p_body,!p_active_default);
ps->body_set_space(body,space);
ps->body_set_param(body,PhysicsServer::BODY_PARAM_BOUNCE,0.5);
//todo set space
ps->body_add_shape(body,type_shape_map[p_shape]);
ps->body_set_force_integration_callback(body,this,"body_changed_transform",mesh_instance);
ps->body_set_state( body, PhysicsServer::BODY_STATE_TRANSFORM,p_location);
bodies.push_back(body);
if (p_body==PhysicsServer::BODY_MODE_STATIC) {
vs->instance_set_transform(mesh_instance,p_location);
}
return body;
}
RID create_static_plane(const Plane& p_plane) {
PhysicsServer * ps = PhysicsServer::get_singleton();
RID plane_shape = ps->shape_create(PhysicsServer::SHAPE_PLANE);;
ps->shape_set_data( plane_shape, p_plane );
RID b = ps->body_create( PhysicsServer::BODY_MODE_STATIC );
ps->body_set_space(b,space);
//todo set space
ps->body_add_shape(b, plane_shape);
return b;
}
void configure_body(RID p_body,float p_mass, float p_friction, float p_bounce) {
PhysicsServer * ps = PhysicsServer::get_singleton();
ps->body_set_param( p_body, PhysicsServer::BODY_PARAM_MASS, p_mass );
ps->body_set_param( p_body, PhysicsServer::BODY_PARAM_FRICTION, p_friction );
ps->body_set_param( p_body, PhysicsServer::BODY_PARAM_BOUNCE, p_bounce );
}
void init_shapes() {
VisualServer *vs=VisualServer::get_singleton();
PhysicsServer * ps = PhysicsServer::get_singleton();
/* SPHERE SHAPE */
RID sphere_mesh = vs->make_sphere_mesh(10,20,0.5);
RID sphere_material = vs->fixed_material_create();
//vs->material_set_flag( sphere_material, VisualServer::MATERIAL_FLAG_WIREFRAME, true );
vs->fixed_material_set_param( sphere_material, VisualServer::FIXED_MATERIAL_PARAM_DIFFUSE, Color(0.7,0.8,3.0) );
vs->mesh_surface_set_material( sphere_mesh, 0, sphere_material );
type_mesh_map[PhysicsServer::SHAPE_SPHERE]=sphere_mesh;
RID sphere_shape=ps->shape_create(PhysicsServer::SHAPE_SPHERE);
ps->shape_set_data( sphere_shape, 0.5 );
type_shape_map[PhysicsServer::SHAPE_SPHERE]=sphere_shape;
/* BOX SHAPE */
DVector<Plane> box_planes = Geometry::build_box_planes(Vector3(0.5,0.5,0.5));
RID box_material = vs->fixed_material_create();
vs->fixed_material_set_param( box_material, VisualServer::FIXED_MATERIAL_PARAM_DIFFUSE, Color(1.0,0.2,0.2) );
RID box_mesh = vs->mesh_create();
Geometry::MeshData box_data = Geometry::build_convex_mesh(box_planes);
vs->mesh_add_surface_from_mesh_data(box_mesh,box_data);
vs->mesh_surface_set_material( box_mesh, 0, box_material );
type_mesh_map[PhysicsServer::SHAPE_BOX]=box_mesh;
RID box_shape=ps->shape_create(PhysicsServer::SHAPE_BOX);
ps->shape_set_data( box_shape, Vector3(0.5,0.5,0.5) );
type_shape_map[PhysicsServer::SHAPE_BOX]=box_shape;
/* CAPSULE SHAPE */
DVector<Plane> capsule_planes = Geometry::build_capsule_planes(0.5,0.7,12,Vector3::AXIS_Z);
RID capsule_material = vs->fixed_material_create();
vs->fixed_material_set_param( capsule_material, VisualServer::FIXED_MATERIAL_PARAM_DIFFUSE, Color(0.3,0.4,1.0) );
RID capsule_mesh = vs->mesh_create();
Geometry::MeshData capsule_data = Geometry::build_convex_mesh(capsule_planes);
vs->mesh_add_surface_from_mesh_data(capsule_mesh,capsule_data);
vs->mesh_surface_set_material( capsule_mesh, 0, capsule_material );
type_mesh_map[PhysicsServer::SHAPE_CAPSULE]=capsule_mesh;
RID capsule_shape=ps->shape_create(PhysicsServer::SHAPE_CAPSULE);
Dictionary capsule_params;
capsule_params["radius"]=0.5;
capsule_params["height"]=1.4;
ps->shape_set_data( capsule_shape, capsule_params );
type_shape_map[PhysicsServer::SHAPE_CAPSULE]=capsule_shape;
/* CONVEX SHAPE */
DVector<Plane> convex_planes = Geometry::build_cylinder_planes(0.5,0.7,5,Vector3::AXIS_Z);
RID convex_material = vs->fixed_material_create();
vs->fixed_material_set_param( convex_material, VisualServer::FIXED_MATERIAL_PARAM_DIFFUSE, Color(0.8,0.2,0.9));
RID convex_mesh = vs->mesh_create();
Geometry::MeshData convex_data = Geometry::build_convex_mesh(convex_planes);
QuickHull::build(convex_data.vertices,convex_data);
vs->mesh_add_surface_from_mesh_data(convex_mesh,convex_data);
vs->mesh_surface_set_material( convex_mesh, 0, convex_material );
type_mesh_map[PhysicsServer::SHAPE_CONVEX_POLYGON]=convex_mesh;
RID convex_shape=ps->shape_create(PhysicsServer::SHAPE_CONVEX_POLYGON);
ps->shape_set_data( convex_shape, convex_data.vertices );
type_shape_map[PhysicsServer::SHAPE_CONVEX_POLYGON]=convex_shape;
}
void make_trimesh(Vector<Vector3> p_faces,const Transform& p_xform=Transform()) {
VisualServer *vs=VisualServer::get_singleton();
PhysicsServer * ps = PhysicsServer::get_singleton();
RID trimesh_shape = ps->shape_create(PhysicsServer::SHAPE_CONCAVE_POLYGON);
ps->shape_set_data(trimesh_shape, p_faces);
p_faces=ps->shape_get_data(trimesh_shape); // optimized one
Vector<Vector3> normals; // for drawing
for (int i=0;i<p_faces.size()/3;i++) {
Plane p( p_faces[i*3+0],p_faces[i*3+1], p_faces[i*3+2] );
normals.push_back(p.normal);
normals.push_back(p.normal);
normals.push_back(p.normal);
}
RID trimesh_mesh = vs->mesh_create();
Array d;
d.resize(VS::ARRAY_MAX);
d[VS::ARRAY_VERTEX]=p_faces;
d[VS::ARRAY_NORMAL]=normals;
vs->mesh_add_surface(trimesh_mesh, VS::PRIMITIVE_TRIANGLES, d );
RID trimesh_mat = vs->fixed_material_create();
vs->fixed_material_set_param( trimesh_mat, VisualServer::FIXED_MATERIAL_PARAM_DIFFUSE, Color(1.0,0.5,0.8));
//vs->material_set_flag( trimesh_mat, VisualServer::MATERIAL_FLAG_UNSHADED,true);
vs->mesh_surface_set_material( trimesh_mesh, 0, trimesh_mat );
RID triins = vs->instance_create2(trimesh_mesh,scenario);
RID tribody = ps->body_create( PhysicsServer::BODY_MODE_STATIC);
ps->body_set_space(tribody,space);
//todo set space
ps->body_add_shape(tribody, trimesh_shape);
Transform tritrans = p_xform;
ps->body_set_state( tribody, PhysicsServer::BODY_STATE_TRANSFORM, tritrans );
vs->instance_set_transform( triins, tritrans );
//RID trimesh_material = vs->fixed_material_create();
//vs->material_generate( trimesh_material, Color(0.2,0.4,0.6) );
//vs->mesh_surface_set_material( trimesh_mesh, 0, trimesh_material );
}
void make_grid(int p_width,int p_height,float p_cellsize,float p_cellheight,const Transform& p_xform=Transform()) {
Vector< Vector< float > > grid;
grid.resize(p_width);
for (int i=0;i<p_width;i++) {
grid[i].resize(p_height);
for (int j=0;j<p_height;j++) {
grid[i][j]=1.0+Math::random(-p_cellheight, p_cellheight );
}
}
Vector<Vector3> faces;
for (int i=1;i<p_width;i++) {
for (int j=1;j<p_height;j++) {
#define MAKE_VERTEX(m_x,m_z)\
faces.push_back( Vector3( (m_x-p_width/2)*p_cellsize, grid[m_x][m_z], (m_z-p_height/2)*p_cellsize ) )
MAKE_VERTEX(i,j-1);
MAKE_VERTEX(i,j);
MAKE_VERTEX(i-1,j);
MAKE_VERTEX(i-1,j-1);
MAKE_VERTEX(i,j-1);
MAKE_VERTEX(i-1,j);
}
}
make_trimesh(faces,p_xform);
}
public:
virtual void input_event(const InputEvent& p_event) {
if (p_event.type==InputEvent::MOUSE_MOTION && p_event.mouse_motion.button_mask&4) {
ofs_y-=p_event.mouse_motion.relative_y/200.0;
ofs_x+=p_event.mouse_motion.relative_x/200.0;
}
if (p_event.type==InputEvent::MOUSE_MOTION && p_event.mouse_motion.button_mask&1) {
float y=-p_event.mouse_motion.relative_y/20.0;
float x=p_event.mouse_motion.relative_x/20.0;
if (mover.is_valid()) {
PhysicsServer * ps = PhysicsServer::get_singleton();
Transform t = ps->body_get_state(mover,PhysicsServer::BODY_STATE_TRANSFORM);
t.origin+=Vector3(x,y,0);
ps->body_set_state(mover,PhysicsServer::BODY_STATE_TRANSFORM,t);
}
}
if (p_event.type == InputEvent::JOYSTICK_MOTION) {
if (p_event.joy_motion.axis == 0) {
joy_direction.x = p_event.joy_motion.axis_value;
};
if (p_event.joy_motion.axis == 1) {
joy_direction.y = p_event.joy_motion.axis_value;
};
};
}
virtual void request_quit() {
quit=true;
}
virtual void init() {
ofs_x=ofs_y=0;
init_shapes();
PhysicsServer *ps = PhysicsServer::get_singleton();
space=ps->space_create();
ps->space_set_active(space,true);
VisualServer *vs=VisualServer::get_singleton();
/* LIGHT */
RID lightaux = vs->light_create( VisualServer::LIGHT_DIRECTIONAL );
//vs->light_set_color( lightaux, VisualServer::LIGHT_COLOR_AMBIENT, Color(0.0,0.0,0.0) );
scenario = vs->scenario_create();
vs->light_set_shadow(lightaux,true);
light = vs->instance_create2( lightaux,scenario );
Transform t;
t.rotate(Vector3(1.0,0,0),0.6);
vs->instance_set_transform(light,t);
/* CAMERA */
camera = vs->camera_create();
RID viewport = vs->viewport_create();
vs->viewport_attach_camera( viewport, camera );
vs->viewport_attach_to_screen(viewport);
vs->viewport_set_scenario( viewport, scenario );
vs->camera_set_perspective(camera,60,0.1,40.0);
vs->camera_set_transform(camera,Transform( Matrix3(), Vector3(0,9,12)));
//vs->scenario_set_debug(scenario,VS::SCENARIO_DEBUG_WIREFRAME);
Transform gxf;
gxf.basis.scale(Vector3(1.4,0.4,1.4));
gxf.origin=Vector3(-2,1,-2);
make_grid(5,5,2.5,1,gxf);
// create_body(PhysicsServer::SHAPE_BOX,PhysicsServer::BODY_MODE_STATIC,gxf);
//create_static_plane( Plane( Vector3(0,1,0), -2) );
// test_joint();
test_fall();
//test_joint();
/*
Vector<Vector3> faces;
faces.push_back( Vector3(10,0,-5) );
faces.push_back( Vector3(0,0,10) );
faces.push_back( Vector3(-10,-0.2,-5) );
make_trimesh(faces);
*/
/* Make Trimesh */
quit=false;
return;
#if 0
#define GRID_SIZE 5
float grid[GRID_SIZE][GRID_SIZE];
for (int i=0;i<GRID_SIZE;i++) {
for (int j=0;j<GRID_SIZE;j++) {
grid[j][i]=Math::random(0.0, 1.0 );
}
}
Vector<Vector3> faces;
for (int i=1;i<GRID_SIZE;i++) {
for (int j=1;j<GRID_SIZE;j++) {
#define MAKE_VERTEX(m_x,m_z)\
faces.push_back( Vector3( m_x-GRID_SIZE/2.0, grid[m_x][m_z], m_z-GRID_SIZE/2.0 )*3.0 )
MAKE_VERTEX(i,j-1);
MAKE_VERTEX(i,j);
MAKE_VERTEX(i-1,j);
MAKE_VERTEX(i-1,j-1);
MAKE_VERTEX(i,j-1);
MAKE_VERTEX(i-1,j);
}
}
/*
faces.clear();
faces.push_back( Vector3(0,0,-5) );
faces.push_back( Vector3(1,0,-1) );
faces.push_back( Vector3(-1,-0,-1) );
*/
RID trimesh_shape = ps->shape_create();
ps->shape_set_data(trimesh_shape, PhysicsServer::SHAPE_CONCAVE_POLYGON,faces);
faces=ps->shape_get_shape(trimesh_shape, 0);
Vector<Vector3> normals; // for drawing
for (int i=0;i<faces.size()/3;i++) {
Plane p( faces[i*3+0],faces[i*3+1], faces[i*3+2] );
normals.push_back(p.normal);
normals.push_back(p.normal);
normals.push_back(p.normal);
}
RID trimesh_mesh = vs->mesh_create();
vs->mesh_add_surface(trimesh_mesh, VS::PRIMITIVE_TRIANGLES, VS::ARRAY_FORMAT_VERTEX|VS::ARRAY_FORMAT_NORMAL, faces.size() );
vs->mesh_surface_set_array(trimesh_mesh,0,VS::ARRAY_VERTEX, faces );
vs->mesh_surface_set_array(trimesh_mesh,0,VS::ARRAY_NORMAL, normals );
RID trimesh_mat = vs->fixed_material_create();
vs->material_generate( trimesh_mat, Color(1.0,0.5,0.3) );
vs->mesh_surface_set_material( trimesh_mesh, 0, trimesh_mat );
RID triins = vs->instance_create2(trimesh_mesh);
RID tribody = ps->body_create( PhysicsServer::BODY_MODE_STATIC, trimesh_shape);
Transform tritrans = Transform( Matrix3(), Vector3(0,0,-2) );
ps->body_set_state( tribody, PhysicsServer::BODY_STATE_TRANSFORM, tritrans );
vs->instance_set_transform( triins, tritrans );
RID trimesh_material = vs->fixed_material_create();
vs->material_generate( trimesh_material, Color(0.2,0.4,0.6) );
vs->mesh_surface_set_material( trimesh_mesh, 0, trimesh_material );
#endif
}
virtual bool iteration(float p_time) {
if (mover) {
static float joy_speed = 10;
PhysicsServer * ps = PhysicsServer::get_singleton();
Transform t = ps->body_get_state(mover,PhysicsServer::BODY_STATE_TRANSFORM);
t.origin+=Vector3(joy_speed * joy_direction.x * p_time, -joy_speed * joy_direction.y * p_time,0);
ps->body_set_state(mover,PhysicsServer::BODY_STATE_TRANSFORM,t);
};
Transform cameratr;
cameratr.rotate(Vector3(0,1,0),ofs_x);
cameratr.rotate(Vector3(1,0,0),-ofs_y);
cameratr.translate(Vector3(0,2,8));
VisualServer *vs=VisualServer::get_singleton();
vs->camera_set_transform(camera,cameratr);
return quit;
}
virtual void finish() {
}
void test_joint() {
#if 0
PhysicsServer * ps = PhysicsServer::get_singleton();
mover = create_body(PhysicsServer::SHAPE_BOX,PhysicsServer::BODY_MODE_STATIC,Transform(Matrix3(),Vector3(0,0,-24)));
RID b = create_body(PhysicsServer::SHAPE_CAPSULE,PhysicsServer::BODY_MODE_RIGID,Transform());
ps->joint_create_double_pin(b,Vector3(0,0,1.0),mover,Vector3(0,0,0));
ps->body_add_collision_exception(mover,b);
List<String> cmdline = OS::get_singleton()->get_cmdline_args();
int link_count = LINK_COUNT;
if (cmdline.size() > 0 && cmdline[cmdline.size()-1].to_int()) {
link_count = cmdline[cmdline.size()-1].to_int();
};
for(int i=0;i<link_count;i++) {
RID c = create_body(PhysicsServer::SHAPE_CAPSULE,PhysicsServer::BODY_MODE_RIGID,Transform());
ps->joint_create_double_pin(b,Vector3(0,0,-0.7),c,Vector3(0,0,0.7));
ps->body_add_collision_exception(c,b);
b=c;
}
create_static_plane(Plane(Vector3(0,1,0),-8));
#endif
}
void test_hinge() {
#if 0
PhysicsServer * ps = PhysicsServer::get_singleton();
mover = create_body(PhysicsServer::SHAPE_BOX,PhysicsServer::BODY_MODE_STATIC,Transform(Matrix3(),Vector3(0,0,-24)));
RID b = create_body(PhysicsServer::SHAPE_BOX,PhysicsServer::BODY_MODE_RIGID,Transform());
ps->joint_create_double_hinge(b,Transform(Matrix3(),Vector3(1,1,1.0)),mover,Transform(Matrix3(),Vector3(0,0,0)));
ps->body_add_collision_exception(mover,b);
/*
for(int i=0;i<20;i++) {
RID c = create_body(PhysicsServer::SHAPE_CAPSULE,PhysicsServer::BODY_MODE_RIGID,Transform());
ps->joint_create_double_hinge(b,Transform(Matrix3(),Vector3(0,0,-0.7)),c,Transform(Matrix3(),Vector3(0,0,0.7)));
ps->body_add_collision_exception(c,b);
b=c;
}
*/
//create_static_plane(Plane(Vector3(0,1,0),-8));
#endif
}
void test_character() {
VisualServer *vs=VisualServer::get_singleton();
PhysicsServer * ps = PhysicsServer::get_singleton();
DVector<Plane> capsule_planes = Geometry::build_capsule_planes(0.5,1,12,5,Vector3::AXIS_Y);
RID capsule_material = vs->fixed_material_create();
vs->fixed_material_set_param( capsule_material, VisualServer::FIXED_MATERIAL_PARAM_DIFFUSE, Color(1,1,1) );
RID capsule_mesh = vs->mesh_create();
Geometry::MeshData capsule_data = Geometry::build_convex_mesh(capsule_planes);
vs->mesh_add_surface_from_mesh_data(capsule_mesh,capsule_data);
vs->mesh_surface_set_material( capsule_mesh, 0, capsule_material );
type_mesh_map[PhysicsServer::SHAPE_CAPSULE]=capsule_mesh;
RID capsule_shape=ps->shape_create(PhysicsServer::SHAPE_CAPSULE);
Dictionary capsule_params;
capsule_params["radius"]=0.5;
capsule_params["height"]=1;
Transform shape_xform;
shape_xform.rotate(Vector3(1,0,0),Math_PI/2.0);
//shape_xform.origin=Vector3(1,1,1);
ps->shape_set_data( capsule_shape, capsule_params);
RID mesh_instance = vs->instance_create2(capsule_mesh,scenario);
character = ps->body_create(PhysicsServer::BODY_MODE_CHARACTER);
ps->body_set_space(character,space);
//todo add space
ps->body_add_shape(character,capsule_shape);
ps->body_set_force_integration_callback(character,this,"body_changed_transform",mesh_instance);
ps->body_set_state( character, PhysicsServer::BODY_STATE_TRANSFORM,Transform(Matrix3(),Vector3(-2,5,-2)));
bodies.push_back(character);
}
void test_fall() {
for (int i=0;i<35;i++) {
static const PhysicsServer::ShapeType shape_idx[]={
PhysicsServer::SHAPE_CAPSULE,
PhysicsServer::SHAPE_BOX,
PhysicsServer::SHAPE_SPHERE,
PhysicsServer::SHAPE_CONVEX_POLYGON
};
PhysicsServer::ShapeType type=shape_idx[i%4];
//type=PhysicsServer::SHAPE_CONVEX_POLYGON;
Transform t;
t.origin=Vector3(0.0*i,3.5+1.1*i,0.7+0.0*i);
//t.origin=Vector3(-0.7+0.0*i,0.5+4.1*i,0);
t.basis.rotate(Vector3(0.2,-1,0),Math_PI/2*0.6);
//t.basis.rotate(Vector3(0,-1,0),Math_PI/4*i);
//t.basis.rotate(Vector3(0,-1,0),Math_PI/4*i);
//t.basis.rotate(Vector3(-1,0,0),Math_PI/4*i);
RID b = create_body(type,PhysicsServer::BODY_MODE_RIGID,t);
//RID b = create_body(type,i==0?PhysicsServer::BODY_MODE_STATIC:PhysicsServer::BODY_MODE_RIGID,t);
}
create_static_plane( Plane( Vector3(0,1,0), -1) );
/*
create_static_plane( Plane( Vector3(1,0,0), -2) );
create_static_plane( Plane( Vector3(-1,0,0), -2) );
create_static_plane( Plane( Vector3(0,0,1), -2) );
create_static_plane( Plane( Vector3(0,0,-1), -2) );
*/
}
void test_activate() {
create_body(PhysicsServer::SHAPE_BOX,PhysicsServer::BODY_MODE_RIGID,Transform(Matrix3(),Vector3(0,2,0)),true);
//create_body(PhysicsServer::SHAPE_SPHERE,PhysicsServer::BODY_MODE_RIGID,Transform(Matrix3(),Vector3(0,6,0)),true);
create_static_plane( Plane( Vector3(0,1,0), -1) );
}
virtual bool idle(float p_time) {
return false;
}
TestPhysicsMainLoop() {
}
};
namespace TestPhysics {
MainLoop* test() {
return memnew( TestPhysicsMainLoop );
}
}

44
bin/tests/test_physics.h Normal file
View file

@ -0,0 +1,44 @@
/*************************************************************************/
/* test_physics.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef TEST_PHYSICS_H
#define TEST_PHYSICS_H
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
#include "os/main_loop.h"
namespace TestPhysics {
MainLoop* test();
}
#endif

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,41 @@
/*************************************************************************/
/* test_physics_2d.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef TEST_PHYSICS_2D_H
#define TEST_PHYSICS_2D_H
#include "os/main_loop.h"
namespace TestPhysics2D {
MainLoop* test();
}
#endif // TEST_PHYSICS_2D_H

56
bin/tests/test_python.cpp Normal file
View file

@ -0,0 +1,56 @@
/*************************************************************************/
/* test_python.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 "test_python.h"
#ifdef PYTHON_ENABLED
#include "Python.h"
#include "print_string.h"
namespace TestPython {
void test() {
print_line("testing python");
PyRun_SimpleString("import engine\n");
PyRun_SimpleString("def test(self):\n\tprint(\"noway\")\n");
PyRun_SimpleString("a=engine.ObjectPtr()\n");
PyRun_SimpleString("a.noway(22,'hello')\n");
PyRun_SimpleString("a.normalize()\n");
PyRun_SimpleString("class Moch(engine.ObjectPtr):\n\tdef mooch(self):\n\t\tprint('muchi')\n");
PyRun_SimpleString("b=Moch();\n");
PyRun_SimpleString("b.mooch();\n");
PyRun_SimpleString("b.meis();\n");
}
}
#endif

43
bin/tests/test_python.h Normal file
View file

@ -0,0 +1,43 @@
/*************************************************************************/
/* test_python.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef TEST_PYTHON_H
#define TEST_PYTHON_H
#ifdef PYTHON_ENABLED
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
namespace TestPython {
void test();
}
#endif
#endif

257
bin/tests/test_render.cpp Normal file
View file

@ -0,0 +1,257 @@
/*************************************************************************/
/* test_render.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 "test_render.h"
#include "servers/visual_server.h"
#include "os/main_loop.h"
#include "math_funcs.h"
#include "print_string.h"
#include "os/os.h"
#include "quick_hull.h"
#define OBJECT_COUNT 50
namespace TestRender {
class TestMainLoop : public MainLoop {
RID test_cube;
RID instance;
RID camera;
RID viewport;
RID light;
RID scenario;
struct InstanceInfo {
RID instance;
Transform base;
Vector3 rot_axis;
};
List<InstanceInfo> instances;
float ofs;
bool quit;
public:
virtual void input_event(const InputEvent& p_event) {
}
virtual void init() {
print_line("INITIALIZING TEST RENDER");
VisualServer *vs=VisualServer::get_singleton();
test_cube = vs->get_test_cube();
scenario = vs->scenario_create();
Vector<Vector3> vts;
/*
DVector<Plane> sp = Geometry::build_sphere_planes(2,5,5);
Geometry::MeshData md2 = Geometry::build_convex_mesh(sp);
vts=md2.vertices;
*/
/*
static const int s = 20;
for(int i=0;i<s;i++) {
Matrix3 rot(Vector3(0,1,0),i*Math_PI/s);
for(int j=0;j<s;j++) {
Vector3 v;
v.x=Math::sin(j*Math_PI*2/s);
v.y=Math::cos(j*Math_PI*2/s);
vts.push_back( rot.xform(v*2 ) );
}
}*/
/*for(int i=0;i<100;i++) {
vts.push_back( Vector3(Math::randf()*2-1.0,Math::randf()*2-1.0,Math::randf()*2-1.0).normalized()*2);
}*/
/*
vts.push_back(Vector3(0,0,1));
vts.push_back(Vector3(0,0,-1));
vts.push_back(Vector3(0,1,0));
vts.push_back(Vector3(0,-1,0));
vts.push_back(Vector3(1,0,0));
vts.push_back(Vector3(-1,0,0));*/
vts.push_back(Vector3(1,1,1));
vts.push_back(Vector3(1,-1,1));
vts.push_back(Vector3(-1,1,1));
vts.push_back(Vector3(-1,-1,1));
vts.push_back(Vector3(1,1,-1));
vts.push_back(Vector3(1,-1,-1));
vts.push_back(Vector3(-1,1,-1));
vts.push_back(Vector3(-1,-1,-1));
Geometry::MeshData md;
Error err = QuickHull::build(vts,md);
print_line("ERR: "+itos(err));
test_cube = vs->mesh_create();
vs->mesh_add_surface_from_mesh_data(test_cube,md);
//vs->scenario_set_debug(scenario,VS::SCENARIO_DEBUG_WIREFRAME);
/*
RID sm = vs->shader_create();
//vs->shader_set_fragment_code(sm,"OUT_ALPHA=mod(TIME,1);");
//vs->shader_set_vertex_code(sm,"OUT_VERTEX=IN_VERTEX*mod(TIME,1);");
vs->shader_set_fragment_code(sm,"OUT_DIFFUSE=vec3(1,0,1);OUT_GLOW=abs(sin(TIME));");
RID tcmat = vs->mesh_surface_get_material(test_cube,0);
vs->material_set_shader(tcmat,sm);
*/
List<String> cmdline = OS::get_singleton()->get_cmdline_args();
int object_count = OBJECT_COUNT;
if (cmdline.size() > 0 && cmdline[cmdline.size()-1].to_int()) {
object_count = cmdline[cmdline.size()-1].to_int();
};
for (int i=0;i<object_count;i++) {
InstanceInfo ii;
ii.instance = vs->instance_create2( test_cube, scenario );
ii.base.translate( Math::random(-20,20), Math::random(-20,20),Math::random(-20,18) );
ii.base.rotate( Vector3(0,1,0), Math::randf() * Math_PI );
ii.base.rotate( Vector3(1,0,0), Math::randf() * Math_PI );
vs->instance_set_transform( ii.instance, ii.base );
ii.rot_axis = Vector3( Math::random(-1,1), Math::random(-1,1), Math::random(-1,1) ).normalized();
instances.push_back(ii);
}
camera = vs->camera_create();
// vs->camera_set_perspective( camera, 60.0,0.1, 100.0 );
viewport = vs->viewport_create();
vs->viewport_attach_to_screen(viewport);
vs->viewport_attach_camera( viewport, camera );
vs->viewport_set_scenario( viewport, scenario );
vs->camera_set_transform(camera, Transform( Matrix3(), Vector3(0,3,30 ) ) );
vs->camera_set_perspective( camera, 60, 0.1, 1000);
/*
RID lightaux = vs->light_create( VisualServer::LIGHT_OMNI );
vs->light_set_var( lightaux, VisualServer::LIGHT_VAR_RADIUS, 80 );
vs->light_set_var( lightaux, VisualServer::LIGHT_VAR_ATTENUATION, 1 );
vs->light_set_var( lightaux, VisualServer::LIGHT_VAR_ENERGY, 1.5 );
light = vs->instance_create( lightaux );
*/
RID lightaux;
//*
lightaux = vs->light_create( VisualServer::LIGHT_DIRECTIONAL );
vs->light_set_color( lightaux, VisualServer::LIGHT_COLOR_AMBIENT, Color(0.0,0.0,0.0) );
vs->light_set_color( lightaux, VisualServer::LIGHT_COLOR_DIFFUSE, Color(1.0,1.0,1.0) );
//vs->light_set_shadow( lightaux, true );
light = vs->instance_create2( lightaux, scenario );
Transform lla;
//lla.set_look_at(Vector3(),Vector3(1,-1,1),Vector3(0,1,0));
lla.set_look_at(Vector3(),Vector3(-0.000000,-0.836026,-0.548690),Vector3(0,1,0));
vs->instance_set_transform( light, lla );
// */
//*
lightaux = vs->light_create( VisualServer::LIGHT_OMNI );
vs->light_set_color( lightaux, VisualServer::LIGHT_COLOR_AMBIENT, Color(0.0,0.0,1.0) );
vs->light_set_color( lightaux, VisualServer::LIGHT_COLOR_DIFFUSE, Color(1.0,1.0,0.0) );
vs->light_set_param( lightaux, VisualServer::LIGHT_PARAM_RADIUS, 4 );
vs->light_set_param( lightaux, VisualServer::LIGHT_PARAM_ENERGY, 8 );
//vs->light_set_shadow( lightaux, true );
//light = vs->instance_create( lightaux );
// */
ofs=0;
quit=false;
}
virtual bool iteration(float p_time) {
VisualServer *vs=VisualServer::get_singleton();
//Transform t;
//t.rotate(Vector3(0, 1, 0), ofs);
//t.translate(Vector3(0,0,20 ));
//vs->camera_set_transform(camera, t);
ofs+=p_time*0.05;
//return quit;
for(List<InstanceInfo>::Element *E=instances.front();E;E=E->next()) {
Transform pre( Matrix3(E->get().rot_axis, ofs), Vector3() );
vs->instance_set_transform( E->get().instance, pre * E->get().base );
/*
if( !E->next() ) {
vs->free( E->get().instance );
instances.erase(E );
}*/
}
return quit;
}
virtual bool idle(float p_time) {
return quit;
}
virtual void finish() {
}
};
MainLoop* test() {
return memnew( TestMainLoop );
}
}

44
bin/tests/test_render.h Normal file
View file

@ -0,0 +1,44 @@
/*************************************************************************/
/* test_render.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef TEST_RENDER_H
#define TEST_RENDER_H
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
#include "os/main_loop.h"
namespace TestRender {
MainLoop* test();
}
#endif

View file

@ -0,0 +1,339 @@
/*************************************************************************/
/* test_shader_lang.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 "test_shader_lang.h"
#include "os/main_loop.h"
#include "os/os.h"
#include "os/file_access.h"
#include "scene/gui/control.h"
#include "scene/gui/text_edit.h"
#include "print_string.h"
#include "servers/visual/shader_language.h"
#include "drivers/gles2/shader_compiler_gles2.h"
typedef ShaderLanguage SL;
namespace TestShaderLang {
static String _mktab(int p_level) {
String tb;
for(int i=0;i<p_level;i++) {
tb+="\t";
}
return tb;
}
static String _typestr(SL::DataType p_type) {
switch(p_type) {
case SL::TYPE_VOID: return "void";
case SL::TYPE_BOOL: return "bool";
case SL::TYPE_FLOAT: return "float";
case SL::TYPE_VEC2: return "vec2";
case SL::TYPE_VEC3: return "vec3";
case SL::TYPE_VEC4: return "vec4";
case SL::TYPE_MAT3: return "mat3";
case SL::TYPE_MAT4: return "mat4";
case SL::TYPE_TEXTURE: return "texture";
case SL::TYPE_CUBEMAP: return "cubemap";
default: {}
}
return "";
}
static String _opstr(SL::Operator p_op) {
switch(p_op) {
case SL::OP_ASSIGN: return "=";
case SL::OP_ADD: return "+";
case SL::OP_SUB: return "-";
case SL::OP_MUL: return "*";
case SL::OP_DIV: return "/";
case SL::OP_ASSIGN_ADD: return "+=";
case SL::OP_ASSIGN_SUB: return "-=";
case SL::OP_ASSIGN_MUL: return "*=";
case SL::OP_ASSIGN_DIV: return "/=";
case SL::OP_NEG: return "-";
case SL::OP_NOT: return "!";
case SL::OP_CMP_EQ: return "==";
case SL::OP_CMP_NEQ: return "!=";
case SL::OP_CMP_LEQ: return "<=";
case SL::OP_CMP_GEQ: return ">=";
case SL::OP_CMP_LESS: return "<";
case SL::OP_CMP_GREATER: return ">";
case SL::OP_CMP_OR: return "||";
case SL::OP_CMP_AND: return "&&";
default: return "";
}
return "";
}
static String dump_node_code(SL::Node *p_node,int p_level) {
String code;
switch(p_node->type) {
case SL::Node::TYPE_PROGRAM: {
SL::ProgramNode *pnode=(SL::ProgramNode*)p_node;
for(Map<StringName,SL::Uniform>::Element *E=pnode->uniforms.front();E;E=E->next()) {
String ucode="uniform ";
ucode+=_typestr(E->get().type)+"="+String(E->get().default_value)+"\n";
code+=ucode;
}
for(int i=0;i<pnode->functions.size();i++) {
SL::FunctionNode *fnode=pnode->functions[i].function;
String header;
header=_typestr(fnode->return_type)+" "+fnode->name+"(";
for(int i=0;i<fnode->arguments.size();i++) {
if (i>0)
header+=", ";
header+=_typestr(fnode->arguments[i].type)+" "+fnode->arguments[i].name;
}
header+=") {\n";
code+=header;
code+=dump_node_code(fnode->body,p_level+1);
code+="}\n";
}
code+=dump_node_code(pnode->body,p_level);
} break;
case SL::Node::TYPE_FUNCTION: {
} break;
case SL::Node::TYPE_BLOCK: {
SL::BlockNode *bnode=(SL::BlockNode*)p_node;
//variables
for(Map<StringName,SL::DataType>::Element *E=bnode->variables.front();E;E=E->next()) {
code+=_mktab(p_level)+_typestr(E->value())+" "+E->key()+";\n";
}
for(int i=0;i<bnode->statements.size();i++) {
code+=_mktab(p_level)+dump_node_code(bnode->statements[i],p_level)+";\n";
}
} break;
case SL::Node::TYPE_VARIABLE: {
SL::VariableNode *vnode=(SL::VariableNode*)p_node;
code=vnode->name;
} break;
case SL::Node::TYPE_CONSTANT: {
SL::ConstantNode *cnode=(SL::ConstantNode*)p_node;
switch(cnode->datatype) {
case SL::TYPE_BOOL: code=cnode->value.operator bool()?"true":"false"; break;
case SL::TYPE_FLOAT: code=cnode->value; break;
case SL::TYPE_VEC2: { Vector2 v = cnode->value; code="vec2("+rtos(v.x)+", "+rtos(v.y)+")"; } break;
case SL::TYPE_VEC3: { Vector3 v = cnode->value; code="vec3("+rtos(v.x)+", "+rtos(v.y)+", "+rtos(v.z)+")"; } break;
case SL::TYPE_VEC4: { Plane v = cnode->value; code="vec4("+rtos(v.normal.x)+", "+rtos(v.normal.y)+", "+rtos(v.normal.z)+", "+rtos(v.d)+")"; } break;
case SL::TYPE_MAT3: { Matrix3 x = cnode->value; code="mat3( vec3("+rtos(x.get_axis(0).x)+", "+rtos(x.get_axis(0).y)+", "+rtos(x.get_axis(0).z)+"), vec3("+rtos(x.get_axis(1).x)+", "+rtos(x.get_axis(1).y)+", "+rtos(x.get_axis(1).z)+"), vec3("+rtos(x.get_axis(2).x)+", "+rtos(x.get_axis(2).y)+", "+rtos(x.get_axis(2).z)+"))"; } break;
case SL::TYPE_MAT4: { Transform x = cnode->value; code="mat4( vec3("+rtos(x.basis.get_axis(0).x)+", "+rtos(x.basis.get_axis(0).y)+", "+rtos(x.basis.get_axis(0).z)+"), vec3("+rtos(x.basis.get_axis(1).x)+", "+rtos(x.basis.get_axis(1).y)+", "+rtos(x.basis.get_axis(1).z)+"), vec3("+rtos(x.basis.get_axis(2).x)+", "+rtos(x.basis.get_axis(2).y)+", "+rtos(x.basis.get_axis(2).z)+"), vec3("+rtos(x.origin.x)+", "+rtos(x.origin.y)+", "+rtos(x.origin.z)+"))"; } break;
default: code="<error: "+Variant::get_type_name(cnode->value.get_type())+" ("+itos(cnode->datatype)+">";
}
} break;
case SL::Node::TYPE_OPERATOR: {
SL::OperatorNode *onode=(SL::OperatorNode*)p_node;
switch(onode->op) {
case SL::OP_ASSIGN:
case SL::OP_ASSIGN_ADD:
case SL::OP_ASSIGN_SUB:
case SL::OP_ASSIGN_MUL:
case SL::OP_ASSIGN_DIV:
code=dump_node_code(onode->arguments[0],p_level)+_opstr(onode->op)+dump_node_code(onode->arguments[1],p_level);
break;
case SL::OP_ADD:
case SL::OP_SUB:
case SL::OP_MUL:
case SL::OP_DIV:
case SL::OP_CMP_EQ:
case SL::OP_CMP_NEQ:
case SL::OP_CMP_LEQ:
case SL::OP_CMP_GEQ:
case SL::OP_CMP_LESS:
case SL::OP_CMP_GREATER:
case SL::OP_CMP_OR:
case SL::OP_CMP_AND:
code="("+dump_node_code(onode->arguments[0],p_level)+_opstr(onode->op)+dump_node_code(onode->arguments[1],p_level)+")";
break;
case SL::OP_NEG:
case SL::OP_NOT:
code=_opstr(onode->op)+dump_node_code(onode->arguments[0],p_level);
break;
case SL::OP_CALL:
case SL::OP_CONSTRUCT:
code=dump_node_code(onode->arguments[0],p_level)+"(";
for(int i=1;i<onode->arguments.size();i++) {
if (i>1)
code+=", ";
code+=dump_node_code(onode->arguments[i],p_level);
}
code+=")";
break;
default: {}
}
} break;
case SL::Node::TYPE_CONTROL_FLOW: {
SL::ControlFlowNode *cfnode=(SL::ControlFlowNode*)p_node;
if (cfnode->flow_op==SL::FLOW_OP_IF) {
code+="if ("+dump_node_code(cfnode->statements[0],p_level)+") {\n";
code+=dump_node_code(cfnode->statements[1],p_level+1);
if (cfnode->statements.size()==3) {
code+="} else {\n";
code+=dump_node_code(cfnode->statements[2],p_level+1);
}
code+="}\n";
} else if (cfnode->flow_op==SL::FLOW_OP_RETURN) {
if (cfnode->statements.size()) {
code="return "+dump_node_code(cfnode->statements[0],p_level);
} else {
code="return";
}
}
} break;
case SL::Node::TYPE_MEMBER: {
SL::MemberNode *mnode=(SL::MemberNode*)p_node;
code=dump_node_code(mnode->owner,p_level)+"."+mnode->name;
} break;
}
return code;
}
static void recreate_code(void *p_str,SL::ProgramNode *p_program) {
print_line("recr");
String *str=(String*)p_str;
*str=dump_node_code(p_program,0);
}
MainLoop* test() {
List<String> cmdlargs = OS::get_singleton()->get_cmdline_args();
if (cmdlargs.empty()) {
//try editor!
return NULL;
}
String test = cmdlargs.back()->get();
FileAccess *fa = FileAccess::open(test,FileAccess::READ);
if (!fa) {
memdelete(fa);
ERR_FAIL_V(NULL);
}
String code;
while(true) {
CharType c = fa->get_8();
if (fa->eof_reached())
break;
code+=c;
}
int errline;
int errcol;
String error;
print_line(SL::lex_debug(code));
Error err = SL::compile(code,ShaderLanguage::SHADER_MATERIAL_FRAGMENT,NULL,NULL,&error,&errline,&errcol);
if (err) {
print_line("Error: "+itos(errline)+":"+itos(errcol)+" "+error);
return NULL;
}
print_line("Compile OK! - pretty printing");
String rcode;
err = SL::compile(code,ShaderLanguage::SHADER_MATERIAL_FRAGMENT,recreate_code,&rcode,&error,&errline,&errcol);
if (!err) {
print_line(rcode);
}
ShaderCompilerGLES2 comp;
String codeline,globalsline;
SL::VarInfo vi;
vi.name="mongs";
vi.type=SL::TYPE_VEC3;
ShaderCompilerGLES2::Flags fl;
comp.compile(code,ShaderLanguage::SHADER_MATERIAL_FRAGMENT,codeline,globalsline,fl);
return NULL;
}
}

View file

@ -0,0 +1,40 @@
/*************************************************************************/
/* test_shader_lang.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef TEST_SHADER_LANG_H
#define TEST_SHADER_LANG_H
#include "os/main_loop.h"
namespace TestShaderLang {
MainLoop* test();
}
#endif // TEST_SHADER_LANG_H

95
bin/tests/test_sound.cpp Normal file
View file

@ -0,0 +1,95 @@
/*************************************************************************/
/* test_sound.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 "test_sound.h"
#include "servers/visual_server.h"
#include "os/main_loop.h"
#include "math_funcs.h"
#include "scene/resources/sample.h"
#include "io/resource_loader.h"
#include "print_string.h"
#include "servers/audio_server.h"
#include "os/os.h"
namespace TestSound {
class TestMainLoop : public MainLoop {
bool quit;
Ref<Sample> sample;
public:
virtual void input_event(const InputEvent& p_event) {
}
virtual void request_quit() {
quit=true;
}
virtual void init() {
List<String> cmdline = OS::get_singleton()->get_cmdline_args();
quit=false;
if (cmdline.size()) {
sample=ResourceLoader::load(cmdline.back()->get());
ERR_FAIL_COND(sample.is_null());
print_line("Sample loaded OK");
}
RID voice = AudioServer::get_singleton()->voice_create();
AudioServer::get_singleton()->voice_play( voice, sample->get_rid() );
}
virtual bool idle(float p_time) {
return false;
}
virtual bool iteration(float p_time) {
return quit;
}
virtual void finish() {
}
};
MainLoop* test() {
return memnew( TestMainLoop );
}
}

40
bin/tests/test_sound.h Normal file
View file

@ -0,0 +1,40 @@
/*************************************************************************/
/* test_sound.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef TEST_SOUND_H
#define TEST_SOUND_H
#include "os/main_loop.h"
namespace TestSound {
MainLoop* test();
}
#endif // TEST_SOUND_H

546
bin/tests/test_string.cpp Normal file
View file

@ -0,0 +1,546 @@
/*************************************************************************/
/* test_string.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 "ustring.h"
#include <wchar.h>
//#include "math_funcs.h"
#include <stdio.h>
#include "os/os.h"
#include "drivers/trex/regex.h"
#include "test_string.h"
namespace TestString {
bool test_1() {
OS::get_singleton()->print("\n\nTest 1: Assign from cstr\n");
String s = "Hello";
OS::get_singleton()->print("\tExpected: Hello\n");
OS::get_singleton()->print("\tResulted: %ls\n",s.c_str());
return (wcscmp(s.c_str(),L"Hello")==0);
}
bool test_2() {
OS::get_singleton()->print("\n\nTest 2: Assign from string (operator=)\n");
String s = "Dolly";
String t = s;
OS::get_singleton()->print("\tExpected: Dolly\n");
OS::get_singleton()->print("\tResulted: %ls\n",t.c_str());
return (wcscmp(t.c_str(),L"Dolly")==0);
}
bool test_3() {
OS::get_singleton()->print("\n\nTest 3: Assign from c-string (copycon)\n");
String s("Sheep");
String t(s);
OS::get_singleton()->print("\tExpected: Sheep\n");
OS::get_singleton()->print("\tResulted: %ls\n",t.c_str());
return (wcscmp(t.c_str(),L"Sheep")==0);
}
bool test_4() {
OS::get_singleton()->print("\n\nTest 4: Assign from c-widechar (operator=)\n");
String s(L"Give me");
OS::get_singleton()->print("\tExpected: Give me\n");
OS::get_singleton()->print("\tResulted: %ls\n",s.c_str());
return (wcscmp(s.c_str(),L"Give me")==0);
}
bool test_5() {
OS::get_singleton()->print("\n\nTest 5: Assign from c-widechar (copycon)\n");
String s(L"Wool");
OS::get_singleton()->print("\tExpected: Wool\n");
OS::get_singleton()->print("\tResulted: %ls\n",s.c_str());
return (wcscmp(s.c_str(),L"Wool")==0);
}
bool test_6() {
OS::get_singleton()->print("\n\nTest 6: comparisons (equal)\n");
String s="Test Compare";
OS::get_singleton()->print("\tComparing to \"Test Compare\"\n");
if (! ( s=="Test Compare" ) )
return false;
if (! ( s==L"Test Compare" ) )
return false;
if (! ( s==String("Test Compare") ) )
return false;
return true;
}
bool test_7() {
OS::get_singleton()->print("\n\nTest 7: comparisons (unequal)\n");
String s="Test Compare";
OS::get_singleton()->print("\tComparing to \"Test Compare\"\n");
if (! ( s!="Peanut" ) )
return false;
if (! ( s!=L"Coconut" ) )
return false;
if (! ( s!=String("Butter") ) )
return false;
return true;
}
bool test_8() {
OS::get_singleton()->print("\n\nTest 8: comparisons (operator<)\n");
String s="Bees";
OS::get_singleton()->print("\tComparing to \"Bees\"\n");
if ( ! (s < "Elephant") )
return false;
if ( s < L"Amber" )
return false;
if ( s < String("Beatrix") )
return false;
return true;
}
bool test_9() {
OS::get_singleton()->print("\n\nTest 9: Concatenation\n");
String s;
s+="Have";
s+=' ';
s+='a';
s+=String(" ");
s = s + L"Nice";
s = s + " ";
s = s + String("Day");
OS::get_singleton()->print("\tComparing to \"Have a Nice Day\"\n");
return (s == "Have a Nice Day");
}
bool test_10() {
OS::get_singleton()->print("\n\nTest 10: Misc funcs (size/length/empty/etc)\n");
if (! String("").empty())
return false;
if (String("Mellon").size() != 7)
return false;
if (String("Oranges").length() != 7)
return false;
return true;
}
bool test_11() {
OS::get_singleton()->print("\n\nTest 11: Operator[]\n");
String a="Kugar Sane";
a[0]='S';
a[6]='C';
if (a != "Sugar Cane")
return false;
if (a[1]!='u')
return false;
return true;
}
bool test_12() {
OS::get_singleton()->print("\n\nTest 12: case functions\n");
String a="MoMoNgA";
if (a.to_upper() != "MOMONGA")
return false;
if (a.nocasecmp_to("momonga")!=0)
return false;
return true;
}
bool test_13() {
OS::get_singleton()->print("\n\nTest 13: UTF8\n");
/* how can i embed UTF in here? */
static const CharType ustr[] = { 0x304A , 0x360F, 0x3088, 0x3046, 0 };
// static const wchar_t ustr[] = { 'P', 0xCE, 'p',0xD3, 0 };
String s=ustr;
OS::get_singleton()->print("\tUnicode: %ls\n",ustr);
s.parse_utf8( s.utf8().get_data() );
OS::get_singleton()->print("\tConvert/Parse UTF8: %ls\n",s.c_str());
return (s==ustr);
}
bool test_14() {
OS::get_singleton()->print("\n\nTest 14: ASCII\n");
String s = L"Primero Leche";
OS::get_singleton()->print("\tAscii: %s\n",s.ascii().get_data());
String t=s.ascii().get_data();
return (s==t);
}
bool test_15() {
OS::get_singleton()->print("\n\nTest 15: substr\n");
String s="Killer Baby";
OS::get_singleton()->print("\tsubstr(3,4) of \"%ls\" is \"%ls\"\n",s.c_str(),s.substr(3,4).c_str());
return (s.substr(3,4)=="ler ");
}
bool test_16() {
OS::get_singleton()->print("\n\nTest 16: find\n");
String s="Pretty Woman";
OS::get_singleton()->print("\tString: %ls\n",s.c_str());
OS::get_singleton()->print("\t\"tty\" is at %i pos.\n",s.find("tty"));
OS::get_singleton()->print("\t\"Revenge of the Monster Truck\" is at %i pos.\n",s.find("Revenge of the Monster Truck"));
if (s.find("tty")!=3)
return false;
if (s.find("Revenge of the Monster Truck")!=-1)
return false;
return true;
}
bool test_17() {
OS::get_singleton()->print("\n\nTest 17: find no case\n");
String s="Pretty Whale";
OS::get_singleton()->print("\tString: %ls\n",s.c_str());
OS::get_singleton()->print("\t\"WHA\" is at %i pos.\n",s.findn("WHA"));
OS::get_singleton()->print("\t\"Revenge of the Monster SawFish\" is at %i pos.\n",s.findn("Revenge of the Monster Truck"));
if (s.findn("WHA")!=7)
return false;
if (s.findn("Revenge of the Monster SawFish")!=-1)
return false;
return true;
}
bool test_18() {
OS::get_singleton()->print("\n\nTest 18: find no case\n");
String s="Pretty Whale";
OS::get_singleton()->print("\tString: %ls\n",s.c_str());
OS::get_singleton()->print("\t\"WHA\" is at %i pos.\n",s.findn("WHA"));
OS::get_singleton()->print("\t\"Revenge of the Monster SawFish\" is at %i pos.\n",s.findn("Revenge of the Monster Truck"));
if (s.findn("WHA")!=7)
return false;
if (s.findn("Revenge of the Monster SawFish")!=-1)
return false;
return true;
}
bool test_19() {
OS::get_singleton()->print("\n\nTest 19: Search & replace\n");
String s="Happy Birthday, Anna!";
OS::get_singleton()->print("\tString: %ls\n",s.c_str());
s=s.replace("Birthday","Halloween");
OS::get_singleton()->print("\tReplaced Birthday/Halloween: %ls.\n",s.c_str());
return (s=="Happy Halloween, Anna!");
}
bool test_20() {
OS::get_singleton()->print("\n\nTest 20: Insertion\n");
String s="Who is Frederic?";
OS::get_singleton()->print("\tString: %ls\n",s.c_str());
s=s.insert( s.find("?")," Chopin" );
OS::get_singleton()->print("\tInserted Chopin: %ls.\n",s.c_str());
return (s=="Who is Frederic Chopin?");
}
bool test_21() {
OS::get_singleton()->print("\n\nTest 21: Number -> String\n");
OS::get_singleton()->print("\tPi is %f\n",33.141593);
OS::get_singleton()->print("\tPi String is %ls\n",String::num(3.141593).c_str());
return String::num(3.141593)=="3.141593";
}
bool test_22() {
OS::get_singleton()->print("\n\nTest 22: String -> Int\n");
static const char* nums[4]={ "1237461283", "- 22", "0", " - 1123412" };
static const int num[4]={ 1237461283, -22, 0, -1123412 };
for (int i=0;i<4;i++) {
OS::get_singleton()->print("\tString: \"%s\" as Int is %i\n",nums[i],String(nums[i]).to_int());
if (String(nums[i]).to_int()!=num[i])
return false;
}
return true;
}
bool test_23() {
OS::get_singleton()->print("\n\nTest 23: String -> Float\n");
static const char* nums[4]={ "-12348298412.2", "0.05", "2.0002", " -0.0001" };
static const double num[4]={ -12348298412.2, 0.05, 2.0002, -0.0001 };
for (int i=0;i<4;i++) {
OS::get_singleton()->print("\tString: \"%s\" as Float is %f\n",nums[i],String(nums[i]).to_double());
if ( ABS(String(nums[i]).to_double()-num[i])>0.00001)
return false;
}
return true;
}
bool test_24() {
OS::get_singleton()->print("\n\nTest 24: Slicing\n");
String s="Mars,Jupiter,Saturn,Uranus";
const char*slices[4]={"Mars","Jupiter","Saturn","Uranus"};
OS::get_singleton()->print("\tSlicing \"%ls\" by \"%s\"..\n",s.c_str(),",");
for (int i=0;i<s.get_slice_count(",");i++) {
OS::get_singleton()->print("\t\t%i- %ls\n",i+1,s.get_slice(",",i).c_str());
if (s.get_slice(",",i)!=slices[i])
return false;
}
return true;
}
bool test_25() {
OS::get_singleton()->print("\n\nTest 25: Erasing\n");
String s="Josephine is such a cute girl!";
OS::get_singleton()->print("\tString: %ls\n",s.c_str());
OS::get_singleton()->print("\tRemoving \"cute\"\n");
s.erase(s.find("cute "),String("cute ").length());
OS::get_singleton()->print("\tResult: %ls\n",s.c_str());
return (s=="Josephine is such a girl!");
}
bool test_26() {
OS::get_singleton()->print("\n\nTest 26: RegEx\n");
RegEx regexp("(.*):(.*)");
List<String> captures;
bool match = regexp.match("name:password", &captures);
printf("\tmatch: %s\n", match?"true":"false");
printf("\t%i captures:\n", captures.size());
List<String>::Element *I = captures.front();
while (I) {
printf("%ls\n", I->get().c_str());
I = I->next();
};
return captures.size();
};
typedef bool (*TestFunc)(void);
TestFunc test_funcs[] = {
test_1,
test_2,
test_3,
test_4,
test_5,
test_6,
test_7,
test_8,
test_9,
test_10,
test_11,
test_12,
test_13,
test_14,
test_15,
test_16,
test_17,
test_18,
test_19,
test_20,
test_21,
test_22,
test_23,
test_24,
test_25,
test_26,
0
};
MainLoop* test() {
/** A character length != wchar_t may be forced, so the tests wont work */
ERR_FAIL_COND_V( sizeof(CharType) != sizeof(wchar_t), NULL );
int count=0;
int passed=0;
while(true) {
if (!test_funcs[count])
break;
bool pass=test_funcs[count]();
if (pass)
passed++;
OS::get_singleton()->print("\t%s\n",pass?"PASS":"FAILED");
count++;
}
OS::get_singleton()->print("\n\n\n");
OS::get_singleton()->print("*************\n");
OS::get_singleton()->print("***TOTALS!***\n");
OS::get_singleton()->print("*************\n");
OS::get_singleton()->print("Passed %i of %i tests\n",count,passed);
return NULL;
}
}

44
bin/tests/test_string.h Normal file
View file

@ -0,0 +1,44 @@
/*************************************************************************/
/* test_string.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef TEST_STRING_H
#define TEST_STRING_H
#include "ustring.h"
#include "os/main_loop.h"
namespace TestString {
MainLoop* test();
}
#endif

39
core/SCsub Normal file
View file

@ -0,0 +1,39 @@
Import('env')
env.core_sources=[]
gd_call=""
gd_inc=""
for x in env.global_defaults:
env.core_sources.append("#platform/"+x+"/globals/global_defaults.cpp")
gd_inc+='#include "platform/'+x+'/globals/global_defaults.h"\n'
gd_call+="\tregister_"+x+"_global_defaults();\n"
gd_cpp='#include "globals.h"\n'
gd_cpp+=gd_inc
gd_cpp+="void Globals::register_global_defaults() {\n"+gd_call+"\n}\n"
f = open("global_defaults.cpp","wb")
f.write(gd_cpp)
f.close()
env.add_source_files(env.core_sources,"*.cpp")
Export('env')
import make_binders
env.Command('method_bind.inc', 'make_binders.py', make_binders.run)
SConscript('os/SCsub');
SConscript('math/SCsub');
SConscript('io/SCsub');
SConscript('bind/SCsub');
lib = env.Library("core",env.core_sources)
env.Prepend(LIBS=[lib])

198
core/allocators.h Normal file
View file

@ -0,0 +1,198 @@
/*************************************************************************/
/* allocators.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef ALLOCATORS_H
#define ALLOCATORS_H
#include "os/memory.h"
template<int PREALLOC_COUNT=64, int MAX_HANDS=8>
class BalloonAllocator {
enum {
USED_FLAG=(1<<30),
USED_MASK=USED_FLAG-1
};
struct Balloon {
Balloon *next;
Balloon *prev;
uint32_t hand;
};
struct Hand {
int used;
int allocated;
Balloon *first;
Balloon *last;
};
Hand hands[MAX_HANDS];
public:
void* alloc(size_t p_size) {
size_t max=(1<<MAX_HANDS);
ERR_FAIL_COND_V( p_size>max, NULL );
unsigned int hand=0;
while(p_size>(size_t)(1<<hand)) ++hand;
Hand &h=hands[hand];
if (h.used==h.allocated) {
for(int i=0;i<PREALLOC_COUNT;i++) {
Balloon *b = (Balloon*)memalloc(sizeof(Balloon)+(1<<hand));
b->hand=hand;
if (h.last) {
b->prev=h.last;
h.last->next=b;
h.last=b;
} else {
b->prev=NULL;
h.last=b;
h.first=b;
}
}
h.last->next=NULL;
h.allocated+=PREALLOC_COUNT;
}
Balloon *pick=h.last;
ERR_FAIL_COND_V( (pick->hand&USED_FLAG), NULL );
// remove last
h.last=h.last->prev;
h.last->next=NULL;
pick->next=h.first;
h.first->prev=pick;
pick->prev=NULL;
h.first=pick;
h.used++;
pick->hand|=USED_FLAG;
return (void*)(pick+1);
}
void free(void* p_ptr) {
Balloon *b=(Balloon*)p_ptr;
b-=1;
ERR_FAIL_COND(!(b->hand&USED_FLAG) );
b->hand=b->hand&USED_MASK; // not used
int hand=b->hand;
Hand &h=hands[hand];
if (b==h.first)
h.first=b->next;
if (b->prev)
b->prev->next=b->next;
if (b->next)
b->next->prev=b->prev;
if (h.last!=b) {
h.last->next=b;
b->prev=h.last;
b->next=NULL;
h.last=b;
}
h.used--;
if (h.used<=(h.allocated-(PREALLOC_COUNT*2))) { // this is done to ensure no alloc/free is done constantly
for(int i=0;i<PREALLOC_COUNT;i++) {
ERR_CONTINUE( h.last->hand& USED_FLAG );
Balloon *new_last=h.last->prev;
if (new_last)
new_last->next=NULL;
memfree( h.last );
h.last=new_last;
}
h.allocated-=PREALLOC_COUNT;
}
}
BalloonAllocator() {
for(int i=0;i<MAX_HANDS;i++) {
hands[i].allocated=0;
hands[i].used=0;
hands[i].first=NULL;
hands[i].last=NULL;
}
}
void clear() {
for(int i=0;i<MAX_HANDS;i++) {
while(hands[i].first) {
Balloon *b=hands[i].first;
hands[i].first=b->next;
memfree(b);
}
hands[i].allocated=0;
hands[i].used=0;
hands[i].first=NULL;
hands[i].last=NULL;
}
}
~BalloonAllocator() {
clear();
}
};
#endif // ALLOCATORS_H

241
core/array.cpp Normal file
View file

@ -0,0 +1,241 @@
/*************************************************************************/
/* array.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 "array.h"
#include "vector.h"
#include "hashfuncs.h"
#include "variant.h"
#include "object.h"
struct ArrayPrivate {
SafeRefCount refcount;
Vector<Variant> array;
bool shared;
};
void Array::_ref(const Array& p_from) const {
ArrayPrivate *_fp = p_from._p;
ERR_FAIL_COND(!_fp); // should NOT happen.
if (_fp == _p)
return; //wathever it is, nothing to do here move along
bool success = _fp->refcount.ref();
ERR_FAIL_COND(!success); //should really not happen either
_unref();
if (_fp->shared) {
_p = p_from._p;
} else {
_p = memnew( ArrayPrivate );
_p->shared=false;
_p->refcount.init();
_p->array=_fp->array;
if (_fp->refcount.unref())
memdelete(_fp);
}
}
void Array::_unref() const {
if (!_p)
return;
if (_p->refcount.unref()) {
memdelete(_p);
}
_p=NULL;
}
Variant& Array::operator[](int p_idx) {
return _p->array[p_idx];
}
const Variant& Array::operator[](int p_idx) const {
return _p->array[p_idx];
}
int Array::size() const {
return _p->array.size();
}
bool Array::empty() const {
return _p->array.empty();
}
void Array::clear() {
_p->array.clear();
}
bool Array::is_shared() const {
return _p->shared;
}
bool Array::operator==(const Array& p_array) const {
return _p==p_array._p;
}
uint32_t Array::hash() const {
uint32_t h=hash_djb2_one_32(0);
for (int i=0;i<_p->array.size();i++) {
h = hash_djb2_one_32( _p->array[i].hash(), h);
}
return h;
}
void Array::operator=(const Array& p_array) {
_ref(p_array);
}
void Array::push_back(const Variant& p_value) {
_p->array.push_back(p_value);
}
Error Array::resize(int p_new_size) {
return _p->array.resize(p_new_size);
}
void Array::insert(int p_pos, const Variant& p_value) {
_p->array.insert(p_pos,p_value);
}
void Array::erase(const Variant& p_value) {
_p->array.erase(p_value);
}
int Array::find(const Variant& p_value) const {
return _p->array.find(p_value);
}
void Array::remove(int p_pos) {
_p->array.remove(p_pos);
}
void Array::set(int p_idx,const Variant& p_value) {
operator[](p_idx)=p_value;
}
const Variant& Array::get(int p_idx) const {
return operator[](p_idx);
}
struct _ArrayVariantSort {
_FORCE_INLINE_ bool operator()(const Variant& p_l, const Variant& p_r) const {
bool valid=false;
Variant res;
Variant::evaluate(Variant::OP_LESS,p_l,p_r,res,valid);
if (!valid)
res=false;
return res;
}
};
void Array::sort() {
_p->array.sort_custom<_ArrayVariantSort>();
}
struct _ArrayVariantSortCustom {
Object *obj;
StringName func;
_FORCE_INLINE_ bool operator()(const Variant& p_l, const Variant& p_r) const {
const Variant*args[2]={&p_l,&p_r};
Variant::CallError err;
bool res = obj->call(func,args,2,err);
if (err.error!=Variant::CallError::CALL_OK)
res=false;
return res;
}
};
void Array::sort_custom(Object *p_obj,const StringName& p_function){
ERR_FAIL_NULL(p_obj);
SortArray<Variant,_ArrayVariantSortCustom> avs;
avs.compare.obj=p_obj;
avs.compare.func=p_function;
avs.sort(_p->array.ptr(),_p->array.size());
}
void Array::invert(){
_p->array.invert();
}
Array::Array(const Array& p_from) {
_p=NULL;
_ref(p_from);
}
Array::Array(bool p_shared) {
_p = memnew( ArrayPrivate );
_p->refcount.init();
_p->shared=p_shared;
}
Array::~Array() {
_unref();
}

84
core/array.h Normal file
View file

@ -0,0 +1,84 @@
/*************************************************************************/
/* array.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef ARRAY_H
#define ARRAY_H
#include "typedefs.h"
class Variant;
class ArrayPrivate;
class Object;
class StringName;
class Array {
mutable ArrayPrivate *_p;
void _ref(const Array& p_from) const;
void _unref() const;
public:
Variant& operator[](int p_idx);
const Variant& operator[](int p_idx) const;
void set(int p_idx,const Variant& p_value);
const Variant& get(int p_idx) const;
int size() const;
bool empty() const;
void clear();
bool is_shared() const;
bool operator==(const Array& p_array) const;
uint32_t hash() const;
void operator=(const Array& p_array);
void push_back(const Variant& p_value);
_FORCE_INLINE_ void append(const Variant& p_value) { push_back(p_value); } //for python compatibility
Error resize(int p_new_size);
void insert(int p_pos, const Variant& p_value);
void remove(int p_pos);
void sort();
void sort_custom(Object *p_obj,const StringName& p_function);
void invert();
int find(const Variant& p_value) const;
void erase(const Variant& p_value);
Array(const Array& p_from);
Array(bool p_shared=false);
~Array();
};
#endif // ARRAY_H

35
core/balloon_allocator.h Normal file
View file

@ -0,0 +1,35 @@
/*************************************************************************/
/* balloon_allocator.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef BALLOON_ALLOCATOR_H
#define BALLOON_ALLOCATOR_H
#include "os/memory.h"
#include "allocators.h"
#endif // BALLOON_ALLOCATOR_H

7
core/bind/SCsub Normal file
View file

@ -0,0 +1,7 @@
Import('env')
env.add_source_files(env.core_sources,"*.cpp")
Export('env')

1436
core/bind/core_bind.cpp Normal file

File diff suppressed because it is too large Load diff

417
core/bind/core_bind.h Normal file
View file

@ -0,0 +1,417 @@
#ifndef CORE_BIND_H
#define CORE_BIND_H
#include "io/resource_loader.h"
#include "io/resource_saver.h"
#include "os/file_access.h"
#include "os/dir_access.h"
#include "os/thread.h"
#include "os/semaphore.h"
class _ResourceLoader : public Object {
OBJ_TYPE(_ResourceLoader,Object);
protected:
static void _bind_methods();
static _ResourceLoader *singleton;
public:
static _ResourceLoader *get_singleton() { return singleton; }
Ref<ResourceInteractiveLoader> load_interactive(const String& p_path,const String& p_type_hint="");
RES load(const String &p_path,const String& p_type_hint="");
DVector<String> get_recognized_extensions_for_type(const String& p_type);
void set_abort_on_missing_resources(bool p_abort);
StringArray get_dependencies(const String& p_path);
bool has(const String& p_path);
_ResourceLoader();
};
class _ResourceSaver : public Object {
OBJ_TYPE(_ResourceSaver,Object);
protected:
static void _bind_methods();
static _ResourceSaver *singleton;
public:
static _ResourceSaver *get_singleton() { return singleton; }
Error save(const String &p_path,const RES& p_resource, uint32_t p_flags);
DVector<String> get_recognized_extensions(const RES& p_resource);
_ResourceSaver();
};
class MainLoop;
class _OS : public Object {
OBJ_TYPE(_OS,Object);
protected:
static void _bind_methods();
static _OS *singleton;
public:
enum Weekday {
DAY_SUNDAY,
DAY_MONDAY,
DAY_TUESDAY,
DAY_WEDNESDAY,
DAY_THURSDAY,
DAY_FRIDAY,
DAY_SATURDAY
};
enum Month {
MONTH_JANUARY,
MONTH_FEBRUARY,
MONTH_MARCH,
MONTH_APRIL,
MONTH_MAY,
MONTH_JUNE,
MONTH_JULY,
MONTH_AUGUST,
MONTH_SEPTEMBER,
MONTH_OCTOBER,
MONTH_NOVEMBER,
MONTH_DECEMBER
};
Point2 get_mouse_pos() const;
void set_window_title(const String& p_title);
int get_mouse_button_state() const;
void set_clipboard(const String& p_text);
String get_clipboard() const;
void set_video_mode(const Size2& p_size, bool p_fullscreen,bool p_resizeable,int p_screen=0);
Size2 get_video_mode(int p_screen=0) const;
bool is_video_mode_fullscreen(int p_screen=0) const;
bool is_video_mode_resizable(int p_screen=0) const;
Array get_fullscreen_mode_list(int p_screen=0) const;
void set_iterations_per_second(int p_ips);
int get_iterations_per_second() const;
void set_low_processor_usage_mode(bool p_enabled);
bool is_in_low_processor_usage_mode() const;
String get_executable_path() const;
int execute(const String& p_path, const Vector<String> & p_arguments,bool p_blocking);
Error kill(int p_pid);
Error shell_open(String p_uri);
bool has_environment(const String& p_var) const;
String get_environment(const String& p_var) const;
String get_name() const;
Vector<String> get_cmdline_args();
String get_locale() const;
String get_model_name() const;
MainLoop *get_main_loop() const;
String get_custom_level() const;
float get_frames_per_second() const;
void dump_memory_to_file(const String& p_file);
void dump_resources_to_file(const String& p_file);
void print_resources_in_use(bool p_short=false);
void print_all_resources(const String& p_to_file);
bool has_touchscreen_ui_hint() const;
String get_unique_ID() const;
/*
struct Date {
int year;
Month month;
int day;
Weekday weekday;
bool dst;
};
struct Time {
int hour;
int min;
int sec;
};
*/
void set_icon(const Image& p_icon);
Dictionary get_date() const;
Dictionary get_time() const;
uint64_t get_unix_time() const;
int get_static_memory_usage() const;
int get_static_memory_peak_usage() const;
int get_dynamic_memory_usage() const;
void delay_usec(uint32_t p_usec) const;
void delay_msec(uint32_t p_msec) const;
uint32_t get_ticks_msec() const;
bool can_draw() const;
int get_frames_drawn();
bool is_stdout_verbose() const;
int get_processor_count() const;
String get_data_dir() const;
static _OS *get_singleton() { return singleton; }
_OS();
};
class _Geometry : public Object {
OBJ_TYPE(_Geometry, Object);
static _Geometry *singleton;
protected:
static void _bind_methods();
public:
static _Geometry *get_singleton();
DVector<Plane> build_box_planes(const Vector3& p_extents);
DVector<Plane> build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis=Vector3::AXIS_Z);
DVector<Plane> build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis=Vector3::AXIS_Z);
Variant segment_intersects_segment_2d(const Vector2& p_from_a,const Vector2& p_to_a,const Vector2& p_from_b,const Vector2& p_to_b);
DVector<Vector2> get_closest_points_between_segments_2d( const Vector2& p1,const Vector2& q1, const Vector2& p2,const Vector2& q2);
DVector<Vector3> get_closest_points_between_segments(const Vector3& p1,const Vector3& p2,const Vector3& q1,const Vector3& q2);
Vector3 get_closest_point_to_segment(const Vector3& p_point, const Vector3& p_a,const Vector3& p_b);
Variant ray_intersects_triangle( const Vector3& p_from, const Vector3& p_dir, const Vector3& p_v0,const Vector3& p_v1,const Vector3& p_v2);
Variant segment_intersects_triangle( const Vector3& p_from, const Vector3& p_to, const Vector3& p_v0,const Vector3& p_v1,const Vector3& p_v2);
DVector<Vector3> segment_intersects_sphere( const Vector3& p_from, const Vector3& p_to, const Vector3& p_sphere_pos,real_t p_sphere_radius);
DVector<Vector3> segment_intersects_cylinder( const Vector3& p_from, const Vector3& p_to, float p_height,float p_radius);
DVector<Vector3> segment_intersects_convex(const Vector3& p_from, const Vector3& p_to,const Vector<Plane>& p_planes);
real_t segment_intersects_circle(const Vector2& p_from, const Vector2& p_to, const Vector2& p_circle_pos, real_t p_circle_radius);
Vector<int> triangulate_polygon(const Vector<Vector2>& p_polygon);
_Geometry();
};
class _File : public Reference {
OBJ_TYPE(_File,Reference);
FileAccess *f;
bool eswap;
protected:
static void _bind_methods();
public:
enum ModeFlags {
READ=1,
WRITE=2,
READ_WRITE=3,
};
Error open(const String& p_path, int p_mode_flags); ///< open a file
void close(); ///< close a file
bool is_open() const; ///< true when file is open
void seek(int64_t p_position); ///< seek to a given position
void seek_end(int64_t p_position=0); ///< seek from the end of file
int64_t get_pos() const; ///< get position in the file
int64_t get_len() const; ///< get size of the file
bool eof_reached() const; ///< reading passed EOF
uint8_t get_8() const; ///< get a byte
uint16_t get_16() const; ///< get 16 bits uint
uint32_t get_32() const; ///< get 32 bits uint
uint64_t get_64() const; ///< get 64 bits uint
float get_float() const;
double get_double() const;
real_t get_real() const;
Variant get_var() const;
DVector<uint8_t> get_buffer(int p_length) const; ///< get an array of bytes
String get_line() const;
String get_as_text() const;
/**< use this for files WRITTEN in _big_ endian machines (ie, amiga/mac)
* It's not about the current CPU type but file formats.
* this flags get reset to false (little endian) on each open
*/
void set_endian_swap(bool p_swap);
bool get_endian_swap();
Error get_error() const; ///< get last error
void store_8(uint8_t p_dest); ///< store a byte
void store_16(uint16_t p_dest); ///< store 16 bits uint
void store_32(uint32_t p_dest); ///< store 32 bits uint
void store_64(uint64_t p_dest); ///< store 64 bits uint
void store_float(float p_dest);
void store_double(double p_dest);
void store_real(real_t p_real);
void store_string(const String& p_string);
void store_line(const String& p_string);
Vector<String> get_csv_line() const;
void store_buffer(const DVector<uint8_t>& p_buffer); ///< store an array of bytes
void store_var(const Variant& p_var);
bool file_exists(const String& p_name) const; ///< return true if a file exists
_File();
virtual ~_File();
};
class _Directory : public Reference {
OBJ_TYPE(_Directory,Reference);
DirAccess *d;
protected:
static void _bind_methods();
public:
Error open(const String& p_path);
bool list_dir_begin(); ///< This starts dir listing
String get_next();
bool current_is_dir() const;
void list_dir_end(); ///<
int get_drive_count();
String get_drive(int p_drive);
Error change_dir(String p_dir); ///< can be relative or absolute, return false on success
String get_current_dir(); ///< return current dir location
Error make_dir(String p_dir);
Error make_dir_recursive(String p_dir);
bool file_exists(String p_file);
int get_space_left();
Error copy(String p_from,String p_to);
Error rename(String p_from, String p_to);
Error remove(String p_name);
_Directory();
virtual ~_Directory();
};
class _Marshalls : public Reference {
OBJ_TYPE(_Marshalls,Reference);
protected:
static void _bind_methods();
public:
String variant_to_base64(const Variant& p_var);
Variant base64_to_variant(const String& p_str);
_Marshalls() {};
};
class _Mutex : public Reference {
OBJ_TYPE(_Mutex,Reference);
Mutex *mutex;
static void _bind_methods();
public:
void lock();
Error try_lock();
void unlock();
_Mutex();
~_Mutex();
};
class _Semaphore : public Reference {
OBJ_TYPE(_Semaphore,Reference);
Semaphore *semaphore;
static void _bind_methods();
public:
Error wait();
Error post();
_Semaphore();
~_Semaphore();
};
class _Thread : public Reference {
OBJ_TYPE(_Thread,Reference);
protected:
Variant ret;
Variant userdata;
volatile bool active;
Object *target_instance;
StringName target_method;
Thread *thread;
static void _bind_methods();
static void _start_func(void *ud);
public:
enum Priority {
PRIORITY_LOW,
PRIORITY_NORMAL,
PRIORITY_HIGH
};
Error start(Object *p_instance,const StringName& p_method,const Variant& p_userdata=Variant(),int p_priority=PRIORITY_NORMAL);
String get_id() const;
bool is_active() const;
Variant wait_to_finish();
_Thread();
~_Thread();
};
#endif // CORE_BIND_H

377
core/color.cpp Normal file
View file

@ -0,0 +1,377 @@
/*************************************************************************/
/* color.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 "color.h"
#include "math_funcs.h"
#include "print_string.h"
uint32_t Color::to_ARGB32() const {
uint32_t c=(uint8_t)(a*255);
c<<=8;
c|=(uint8_t)(r*255);
c<<=8;
c|=(uint8_t)(g*255);
c<<=8;
c|=(uint8_t)(b*255);
return c;
}
uint32_t Color::to_32() const {
uint32_t c=(uint8_t)(a*255);
c<<=8;
c|=(uint8_t)(r*255);
c<<=8;
c|=(uint8_t)(g*255);
c<<=8;
c|=(uint8_t)(b*255);
return c;
}
float Color::get_h() const {
float min = MIN( r, g );
min = MIN( min, b );
float max = MAX( r, g );
max = MAX( max, b );
float delta = max - min;
if( delta == 0 )
return 0;
float h;
if( r == max )
h = ( g - b ) / delta; // between yellow & magenta
else if( g == max )
h = 2 + ( b - r ) / delta; // between cyan & yellow
else
h = 4 + ( r - g ) / delta; // between magenta & cyan
h/=6.0;
if (h<0)
h+=1.0;
return h;
}
float Color::get_s() const {
float min = MIN( r, g );
min = MIN( min, b );
float max = MAX( r, g );
max = MAX( max, b );
float delta = max - min;
return (max!=0) ? (delta / max) : 0;
}
float Color::get_v() const {
float max = MAX( r, g );
max = MAX( max, b );
return max;
}
void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) {
int i;
float f, p, q, t;
a=p_alpha;
if( p_s == 0 ) {
// acp_hromatic (grey)
r = g = b = p_v;
return;
}
p_h *=6.0;
i = Math::floor( p_h );
f = p_h - i;
p = p_v * ( 1 - p_s );
q = p_v * ( 1 - p_s * f );
t = p_v * ( 1 - p_s * ( 1 - f ) );
switch( i ) {
case 0:
r = p_v;
g = t;
b = p;
break;
case 1:
r = q;
g = p_v;
b = p;
break;
case 2:
r = p;
g = p_v;
b = t;
break;
case 3:
r = p;
g = q;
b = p_v;
break;
case 4:
r = t;
g = p;
b = p_v;
break;
default: // cap_se 5:
r = p_v;
g = p;
b = q;
break;
}
}
void Color::invert() {
r=1.0-r;
g=1.0-g;
g=1.0-b;
}
void Color::contrast() {
r=Math::fmod(r+0.5,1.0);
g=Math::fmod(g+0.5,1.0);
b=Math::fmod(b+0.5,1.0);
}
Color Color::hex(uint32_t p_hex) {
float a = (p_hex&0xFF)/255.0;
p_hex>>=8;
float b = (p_hex&0xFF)/255.0;
p_hex>>=8;
float g = (p_hex&0xFF)/255.0;
p_hex>>=8;
float r = (p_hex&0xFF)/255.0;
return Color(r,g,b,a);
}
static float _parse_col(const String& p_str, int p_ofs) {
int ig=0;
for(int i=0;i<2;i++) {
int c=p_str[i+p_ofs];
int v=0;
if (c>='0' && c<='9') {
v=c-'0';
} else if (c>='a' && c<='f') {
v=c-'a';
v+=10;
} else if (c>='A' && c<='F') {
v=c-'A';
v+=10;
} else {
return -1;
}
if (i==0)
ig+=v*16;
else
ig+=v;
}
return ig;
}
Color Color::inverted() const {
Color c=*this;
c.invert();
return c;
}
Color Color::contrasted() const {
Color c=*this;
c.contrasted();
return c;
}
Color Color::html(const String& p_color) {
String color = p_color;
if (color.length()==0)
return Color();
if (color[0]=='#')
color=color.substr(1,color.length()-1);
bool alpha=false;
if (color.length()==8) {
alpha=true;
} else if (color.length()==6) {
alpha=false;
} else {
ERR_EXPLAIN("Invalid Color Code: "+p_color);
ERR_FAIL_V(Color());
}
int a=255;
if (alpha) {
a=_parse_col(color,0);
if (a<0) {
ERR_EXPLAIN("Invalid Color Code: "+p_color);
ERR_FAIL_V(Color());
}
}
int from=alpha?2:0;
int r=_parse_col(color,from+0);
if (r<0) {
ERR_EXPLAIN("Invalid Color Code: "+p_color);
ERR_FAIL_V(Color());
}
int g=_parse_col(color,from+2);
if (g<0) {
ERR_EXPLAIN("Invalid Color Code: "+p_color);
ERR_FAIL_V(Color());
}
int b=_parse_col(color,from+4);
if (b<0) {
ERR_EXPLAIN("Invalid Color Code: "+p_color);
ERR_FAIL_V(Color());
}
return Color(r/255.0,g/255.0,b/255.0,a/255.0);
}
bool Color::html_is_valid(const String& p_color) {
String color = p_color;
if (color.length()==0)
return false;
if (color[0]=='#')
color=color.substr(1,color.length()-1);
bool alpha=false;
if (color.length()==8) {
alpha=true;
} else if (color.length()==6) {
alpha=false;
} else {
return false;
}
int a=255;
if (alpha) {
a=_parse_col(color,0);
if (a<0) {
return false;
}
}
int from=alpha?2:0;
int r=_parse_col(color,from+0);
if (r<0) {
return false;
}
int g=_parse_col(color,from+2);
if (g<0) {
return false;
}
int b=_parse_col(color,from+4);
if (b<0) {
return false;
}
return true;
}
String _to_hex(float p_val) {
int v = p_val * 255;
v = CLAMP(v,0,255);
String ret;
for(int i=0;i<2;i++) {
CharType c[2]={0,0};
int lv = v&0xF;
if (lv<10)
c[0]='0'+lv;
else
c[0]='a'+lv-10;
v>>=4;
String cs=(const CharType*)c;
ret = cs + ret;
}
return ret;
}
String Color::to_html(bool p_alpha) const {
String txt;
txt+=_to_hex(r);
txt+=_to_hex(g);
txt+=_to_hex(b);
if (p_alpha)
txt=_to_hex(a)+txt;
return txt;
}
float Color::gray() const {
return (r+g+b)/3.0;
}
Color::operator String() const {
return rtos(r)+", "+rtos(g)+", "+rtos(b)+", "+rtos(a);
}

136
core/color.h Normal file
View file

@ -0,0 +1,136 @@
/*************************************************************************/
/* color.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef COLOR_H
#define COLOR_H
#include "ustring.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
struct Color {
union {
struct {
float r;
float g;
float b;
float a;
};
float components[4];
};
bool operator==(const Color &p_color) const { return (r==p_color.r && g==p_color.g && b==p_color.b && a==p_color.a ); }
bool operator!=(const Color &p_color) const { return (r!=p_color.r || g!=p_color.g || b!=p_color.b || a!=p_color.a ); }
uint32_t to_32() const;
uint32_t to_ARGB32() const;
float gray() const;
float get_h() const;
float get_s() const;
float get_v() const;
void set_hsv(float p_h, float p_s, float p_v, float p_alpha=1.0);
_FORCE_INLINE_ float& operator[](int idx) {
return components[idx];
}
_FORCE_INLINE_ const float& operator[](int idx) const {
return components[idx];
}
void invert();
void contrast();
Color inverted() const;
Color contrasted() const;
_FORCE_INLINE_ Color linear_interpolate(const Color& p_b, float p_t) const {
Color res=*this;
res.r+= (p_t * (p_b.r-r));
res.g+= (p_t * (p_b.g-g));
res.b+= (p_t * (p_b.b-b));
res.a+= (p_t * (p_b.a-a));
return res;
}
_FORCE_INLINE_ Color blend(const Color& p_over) const {
Color res;
float sa = 1.0 - p_over.a;
res.a = a*sa+p_over.a;
if (res.a==0) {
return Color(0,0,0,0);
} else {
res.r = (r*a*sa + p_over.r * p_over.a)/res.a;
res.g = (g*a*sa + p_over.g * p_over.a)/res.a;
res.b = (b*a*sa + p_over.b * p_over.a)/res.a;
}
return res;
}
static Color hex(uint32_t p_hex);
static Color html(const String& p_color);
static bool html_is_valid(const String& p_color);
String to_html(bool p_alpha=true) const;
_FORCE_INLINE_ bool operator<(const Color& p_color) const; //used in set keys
operator String() const;
/**
* No construct parameters, r=0, g=0, b=0. a=255
*/
_FORCE_INLINE_ Color() {
r=0; g=0; b=0; a=1.0;
}
/**
* RGB / RGBA construct parameters. Alpha is optional, but defaults to 1.0
*/
_FORCE_INLINE_ Color(float p_r,float p_g,float p_b,float p_a=1.0) { r=p_r; g=p_g; b=p_b; a=p_a; }
};
bool Color::operator<(const Color& p_color) const {
if (r==p_color.r) {
if (g==p_color.g) {
if(b==p_color.b) {
return (a<p_color.a);
} else
return (b<p_color.b);
} else
return g<p_color.g;
} else
return r<p_color.r;
}
#endif

107
core/command_queue_mt.cpp Normal file
View file

@ -0,0 +1,107 @@
/*************************************************************************/
/* command_queue_mt.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 "command_queue_mt.h"
#include "os/os.h"
void CommandQueueMT::lock() {
if (mutex)
mutex->lock();
}
void CommandQueueMT::unlock() {
if (mutex)
mutex->unlock();
}
void CommandQueueMT::wait_for_flush() {
// wait one millisecond for a flush to happen
OS::get_singleton()->delay_usec(1000);
}
CommandQueueMT::SyncSemaphore* CommandQueueMT::_alloc_sync_sem() {
int idx=-1;
while(true) {
for(int i=0;i<SYNC_SEMAPHORES;i++) {
if (!sync_sems[i].in_use) {
sync_sems[i].in_use=true;
idx=i;
break;
}
}
if (idx==-1) {
wait_for_flush();
} else {
break;
}
}
return &sync_sems[idx];
}
CommandQueueMT::CommandQueueMT(bool p_sync){
read_ptr=0;
write_ptr=0;
mutex = Mutex::create();
for(int i=0;i<SYNC_SEMAPHORES;i++) {
sync_sems[i].sem=Semaphore::create();
sync_sems[i].in_use=false;
}
if (p_sync)
sync = Semaphore::create();
else
sync=NULL;
}
CommandQueueMT::~CommandQueueMT() {
if (sync)
memdelete(sync);
memdelete(mutex);
for(int i=0;i<SYNC_SEMAPHORES;i++) {
memdelete(sync_sems[i].sem);
}
}

999
core/command_queue_mt.h Normal file
View file

@ -0,0 +1,999 @@
/*************************************************************************/
/* command_queue_mt.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef COMMAND_QUEUE_MT_H
#define COMMAND_QUEUE_MT_H
#include "typedefs.h"
#include "os/semaphore.h"
#include "os/mutex.h"
#include "os/memory.h"
#include "simple_type.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
class CommandQueueMT {
struct SyncSemaphore {
Semaphore *sem;
bool in_use;
};
struct CommandBase {
virtual void call()=0;
virtual ~CommandBase() {};
};
template<class T,class M>
struct Command0 : public CommandBase {
T*instance;
M method;
virtual void call() { (instance->*method)(); }
};
template<class T,class M,class P1>
struct Command1 : public CommandBase {
T*instance;
M method;
typename GetSimpleTypeT<P1>::type_t p1;
virtual void call() { (instance->*method)(p1); }
};
template<class T,class M,class P1,class P2>
struct Command2 : public CommandBase {
T*instance;
M method;
typename GetSimpleTypeT<P1>::type_t p1;
typename GetSimpleTypeT<P2>::type_t p2;
virtual void call() { (instance->*method)(p1,p2); }
};
template<class T,class M,class P1,class P2,class P3>
struct Command3 : public CommandBase {
T*instance;
M method;
typename GetSimpleTypeT<P1>::type_t p1;
typename GetSimpleTypeT<P2>::type_t p2;
typename GetSimpleTypeT<P3>::type_t p3;
virtual void call() { (instance->*method)(p1,p2,p3); }
};
template<class T,class M,class P1,class P2,class P3,class P4>
struct Command4 : public CommandBase {
T*instance;
M method;
typename GetSimpleTypeT<P1>::type_t p1;
typename GetSimpleTypeT<P2>::type_t p2;
typename GetSimpleTypeT<P3>::type_t p3;
typename GetSimpleTypeT<P4>::type_t p4;
virtual void call() { (instance->*method)(p1,p2,p3,p4); }
};
template<class T,class M,class P1,class P2,class P3,class P4,class P5>
struct Command5 : public CommandBase {
T*instance;
M method;
typename GetSimpleTypeT<P1>::type_t p1;
typename GetSimpleTypeT<P2>::type_t p2;
typename GetSimpleTypeT<P3>::type_t p3;
typename GetSimpleTypeT<P4>::type_t p4;
typename GetSimpleTypeT<P5>::type_t p5;
virtual void call() { (instance->*method)(p1,p2,p3,p4,p5); }
};
template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6>
struct Command6 : public CommandBase {
T*instance;
M method;
typename GetSimpleTypeT<P1>::type_t p1;
typename GetSimpleTypeT<P2>::type_t p2;
typename GetSimpleTypeT<P3>::type_t p3;
typename GetSimpleTypeT<P4>::type_t p4;
typename GetSimpleTypeT<P5>::type_t p5;
typename GetSimpleTypeT<P6>::type_t p6;
virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6); }
};
template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class P7>
struct Command7 : public CommandBase {
T*instance;
M method;
typename GetSimpleTypeT<P1>::type_t p1;
typename GetSimpleTypeT<P2>::type_t p2;
typename GetSimpleTypeT<P3>::type_t p3;
typename GetSimpleTypeT<P4>::type_t p4;
typename GetSimpleTypeT<P5>::type_t p5;
typename GetSimpleTypeT<P6>::type_t p6;
typename GetSimpleTypeT<P7>::type_t p7;
virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6,p7); }
};
/* comands that return */
template<class T,class M,class R>
struct CommandRet0 : public CommandBase {
T*instance;
M method;
R* ret;
SyncSemaphore *sync;
virtual void call() { *ret = (instance->*method)(); sync->sem->post(); sync->in_use=false; ; }
};
template<class T,class M,class P1,class R>
struct CommandRet1 : public CommandBase {
T*instance;
M method;
typename GetSimpleTypeT<P1>::type_t p1;
R* ret;
SyncSemaphore *sync;
virtual void call() { *ret = (instance->*method)(p1); sync->sem->post(); sync->in_use=false; ; }
};
template<class T,class M,class P1,class P2,class R>
struct CommandRet2 : public CommandBase {
T*instance;
M method;
typename GetSimpleTypeT<P1>::type_t p1;
typename GetSimpleTypeT<P2>::type_t p2;
R* ret;
SyncSemaphore *sync;
virtual void call() { *ret = (instance->*method)(p1,p2); sync->sem->post(); sync->in_use=false; ; }
};
template<class T,class M,class P1,class P2,class P3,class R>
struct CommandRet3 : public CommandBase {
T*instance;
M method;
typename GetSimpleTypeT<P1>::type_t p1;
typename GetSimpleTypeT<P2>::type_t p2;
typename GetSimpleTypeT<P3>::type_t p3;
R* ret;
SyncSemaphore *sync;
virtual void call() { *ret = (instance->*method)(p1,p2,p3); sync->sem->post(); sync->in_use=false; ; }
};
template<class T,class M,class P1,class P2,class P3,class P4,class R>
struct CommandRet4 : public CommandBase {
T*instance;
M method;
typename GetSimpleTypeT<P1>::type_t p1;
typename GetSimpleTypeT<P2>::type_t p2;
typename GetSimpleTypeT<P3>::type_t p3;
typename GetSimpleTypeT<P4>::type_t p4;
R* ret;
SyncSemaphore *sync;
virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4); sync->sem->post(); sync->in_use=false; ; }
};
template<class T,class M,class P1,class P2,class P3,class P4,class P5,class R>
struct CommandRet5 : public CommandBase {
T*instance;
M method;
typename GetSimpleTypeT<P1>::type_t p1;
typename GetSimpleTypeT<P2>::type_t p2;
typename GetSimpleTypeT<P3>::type_t p3;
typename GetSimpleTypeT<P4>::type_t p4;
typename GetSimpleTypeT<P5>::type_t p5;
R* ret;
SyncSemaphore *sync;
virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4,p5); sync->sem->post(); sync->in_use=false; ; }
};
template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class R>
struct CommandRet6 : public CommandBase {
T*instance;
M method;
typename GetSimpleTypeT<P1>::type_t p1;
typename GetSimpleTypeT<P2>::type_t p2;
typename GetSimpleTypeT<P3>::type_t p3;
typename GetSimpleTypeT<P4>::type_t p4;
typename GetSimpleTypeT<P5>::type_t p5;
typename GetSimpleTypeT<P6>::type_t p6;
R* ret;
SyncSemaphore *sync;
virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4,p5,p6); sync->sem->post(); sync->in_use=false; ; }
};
template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class P7,class R>
struct CommandRet7 : public CommandBase {
T*instance;
M method;
typename GetSimpleTypeT<P1>::type_t p1;
typename GetSimpleTypeT<P2>::type_t p2;
typename GetSimpleTypeT<P3>::type_t p3;
typename GetSimpleTypeT<P4>::type_t p4;
typename GetSimpleTypeT<P5>::type_t p5;
typename GetSimpleTypeT<P6>::type_t p6;
typename GetSimpleTypeT<P7>::type_t p7;
R* ret;
SyncSemaphore *sync;
virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4,p5,p6,p7); sync->sem->post(); sync->in_use=false; ; }
};
/** commands that don't return but sync */
/* comands that return */
template<class T,class M>
struct CommandSync0 : public CommandBase {
T*instance;
M method;
SyncSemaphore *sync;
virtual void call() { (instance->*method)(); sync->sem->post(); sync->in_use=false; ; }
};
template<class T,class M,class P1>
struct CommandSync1 : public CommandBase {
T*instance;
M method;
typename GetSimpleTypeT<P1>::type_t p1;
SyncSemaphore *sync;
virtual void call() { (instance->*method)(p1); sync->sem->post(); sync->in_use=false; ; }
};
template<class T,class M,class P1,class P2>
struct CommandSync2 : public CommandBase {
T*instance;
M method;
typename GetSimpleTypeT<P1>::type_t p1;
typename GetSimpleTypeT<P2>::type_t p2;
SyncSemaphore *sync;
virtual void call() { (instance->*method)(p1,p2); sync->sem->post(); sync->in_use=false; ; }
};
template<class T,class M,class P1,class P2,class P3>
struct CommandSync3 : public CommandBase {
T*instance;
M method;
typename GetSimpleTypeT<P1>::type_t p1;
typename GetSimpleTypeT<P2>::type_t p2;
typename GetSimpleTypeT<P3>::type_t p3;
SyncSemaphore *sync;
virtual void call() { (instance->*method)(p1,p2,p3); sync->sem->post(); sync->in_use=false; ; }
};
template<class T,class M,class P1,class P2,class P3,class P4>
struct CommandSync4 : public CommandBase {
T*instance;
M method;
typename GetSimpleTypeT<P1>::type_t p1;
typename GetSimpleTypeT<P2>::type_t p2;
typename GetSimpleTypeT<P3>::type_t p3;
typename GetSimpleTypeT<P4>::type_t p4;
SyncSemaphore *sync;
virtual void call() { (instance->*method)(p1,p2,p3,p4); sync->sem->post(); sync->in_use=false; ; }
};
template<class T,class M,class P1,class P2,class P3,class P4,class P5>
struct CommandSync5 : public CommandBase {
T*instance;
M method;
typename GetSimpleTypeT<P1>::type_t p1;
typename GetSimpleTypeT<P2>::type_t p2;
typename GetSimpleTypeT<P3>::type_t p3;
typename GetSimpleTypeT<P4>::type_t p4;
typename GetSimpleTypeT<P5>::type_t p5;
SyncSemaphore *sync;
virtual void call() { (instance->*method)(p1,p2,p3,p4,p5); sync->sem->post(); sync->in_use=false; ; }
};
template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6>
struct CommandSync6 : public CommandBase {
T*instance;
M method;
typename GetSimpleTypeT<P1>::type_t p1;
typename GetSimpleTypeT<P2>::type_t p2;
typename GetSimpleTypeT<P3>::type_t p3;
typename GetSimpleTypeT<P4>::type_t p4;
typename GetSimpleTypeT<P5>::type_t p5;
typename GetSimpleTypeT<P6>::type_t p6;
SyncSemaphore *sync;
virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6); sync->sem->post(); sync->in_use=false; ; }
};
template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class P7>
struct CommandSync7 : public CommandBase {
T*instance;
M method;
typename GetSimpleTypeT<P1>::type_t p1;
typename GetSimpleTypeT<P2>::type_t p2;
typename GetSimpleTypeT<P3>::type_t p3;
typename GetSimpleTypeT<P4>::type_t p4;
typename GetSimpleTypeT<P5>::type_t p5;
typename GetSimpleTypeT<P6>::type_t p6;
typename GetSimpleTypeT<P7>::type_t p7;
SyncSemaphore *sync;
virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6,p7); sync->sem->post(); sync->in_use=false; ; }
};
/***** BASE *******/
enum {
COMMAND_MEM_SIZE_KB=256,
COMMAND_MEM_SIZE=COMMAND_MEM_SIZE_KB*1024,
SYNC_SEMAPHORES=8
};
uint8_t command_mem[COMMAND_MEM_SIZE];
uint32_t read_ptr;
uint32_t write_ptr;
SyncSemaphore sync_sems[SYNC_SEMAPHORES];
Mutex *mutex;
Semaphore *sync;
template<class T>
T* allocate() {
// alloc size is size+T+safeguard
uint32_t alloc_size=sizeof(T)+sizeof(uint32_t);
tryagain:
if (write_ptr < read_ptr) {
// behind read_ptr, check that there is room
if ( (read_ptr-write_ptr) <= alloc_size )
return NULL;
} else if (write_ptr >= read_ptr) {
// ahead of read_ptr, check that there is room
if ( (COMMAND_MEM_SIZE-write_ptr) < alloc_size+4 ) {
// no room at the end, wrap down;
if (read_ptr==0) // dont want write_ptr to become read_ptr
return NULL;
// if this happens, it's a bug
ERR_FAIL_COND_V( (COMMAND_MEM_SIZE-write_ptr) < sizeof(uint32_t), NULL );
// zero means, wrap to begining
uint32_t * p = (uint32_t*)&command_mem[write_ptr];
*p=0;
write_ptr=0;
goto tryagain;
}
}
// allocate the size
uint32_t * p = (uint32_t*)&command_mem[write_ptr];
*p=sizeof(T);
write_ptr+=sizeof(uint32_t);
// allocate the command
T* cmd = memnew_placement( &command_mem[write_ptr], T );
write_ptr+=sizeof(T);
return cmd;
}
template<class T>
T* allocate_and_lock() {
lock();
T* ret;
while ( (ret=allocate<T>())==NULL ) {
unlock();
// sleep a little until fetch happened and some room is made
wait_for_flush();
lock();
}
return ret;
}
bool flush_one() {
tryagain:
// tried to read an empty queue
if (read_ptr == write_ptr )
return false;
uint32_t size = *(uint32_t*)( &command_mem[read_ptr] );
if (size==0) {
//end of ringbuffer, wrap
read_ptr=0;
goto tryagain;
}
read_ptr+=sizeof(uint32_t);
CommandBase *cmd = reinterpret_cast<CommandBase*>( &command_mem[read_ptr] );
cmd->call();
cmd->~CommandBase();
read_ptr+=size;
return true;
}
void lock();
void unlock();
void wait_for_flush();
SyncSemaphore* _alloc_sync_sem();
public:
/* NORMAL PUSH COMMANDS */
template<class T, class M>
void push( T * p_instance, M p_method ) {
Command0<T,M> * cmd = allocate_and_lock< Command0<T,M> >();
cmd->instance=p_instance;
cmd->method=p_method;
unlock();
if (sync) sync->post();
}
template<class T, class M, class P1>
void push( T * p_instance, M p_method, P1 p1 ) {
Command1<T,M,P1> * cmd = allocate_and_lock< Command1<T,M,P1> >();
cmd->instance=p_instance;
cmd->method=p_method;
cmd->p1=p1;
unlock();
if (sync) sync->post();
}
template<class T, class M, class P1, class P2>
void push( T * p_instance, M p_method, P1 p1, P2 p2 ) {
Command2<T,M,P1,P2> * cmd = allocate_and_lock< Command2<T,M,P1,P2> >();
cmd->instance=p_instance;
cmd->method=p_method;
cmd->p1=p1;
cmd->p2=p2;
unlock();
if (sync) sync->post();
}
template<class T, class M, class P1, class P2, class P3>
void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3 ) {
Command3<T,M,P1,P2,P3> * cmd = allocate_and_lock< Command3<T,M,P1,P2,P3> >();
cmd->instance=p_instance;
cmd->method=p_method;
cmd->p1=p1;
cmd->p2=p2;
cmd->p3=p3;
unlock();
if (sync) sync->post();
}
template<class T, class M, class P1, class P2, class P3, class P4>
void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4 ) {
Command4<T,M,P1,P2,P3,P4> * cmd = allocate_and_lock< Command4<T,M,P1,P2,P3,P4> >();
cmd->instance=p_instance;
cmd->method=p_method;
cmd->p1=p1;
cmd->p2=p2;
cmd->p3=p3;
cmd->p4=p4;
unlock();
if (sync) sync->post();
}
template<class T, class M, class P1, class P2, class P3, class P4, class P5>
void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 ) {
Command5<T,M,P1,P2,P3,P4,P5> * cmd = allocate_and_lock< Command5<T,M,P1,P2,P3,P4,P5> >();
cmd->instance=p_instance;
cmd->method=p_method;
cmd->p1=p1;
cmd->p2=p2;
cmd->p3=p3;
cmd->p4=p4;
cmd->p5=p5;
unlock();
if (sync) sync->post();
}
template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6>
void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6 ) {
Command6<T,M,P1,P2,P3,P4,P5,P6> * cmd = allocate_and_lock< Command6<T,M,P1,P2,P3,P4,P5,P6> >();
cmd->instance=p_instance;
cmd->method=p_method;
cmd->p1=p1;
cmd->p2=p2;
cmd->p3=p3;
cmd->p4=p4;
cmd->p5=p5;
cmd->p6=p6;
unlock();
if (sync) sync->post();
}
template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7>
void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7 ) {
Command7<T,M,P1,P2,P3,P4,P5,P6,P7> * cmd = allocate_and_lock< Command7<T,M,P1,P2,P3,P4,P5,P6,P7> >();
cmd->instance=p_instance;
cmd->method=p_method;
cmd->p1=p1;
cmd->p2=p2;
cmd->p3=p3;
cmd->p4=p4;
cmd->p5=p5;
cmd->p6=p6;
cmd->p7=p7;
unlock();
if (sync) sync->post();
}
/*** PUSH AND RET COMMANDS ***/
template<class T, class M,class R>
void push_and_ret( T * p_instance, M p_method, R* r_ret) {
CommandRet0<T,M,R> * cmd = allocate_and_lock< CommandRet0<T,M,R> >();
cmd->instance=p_instance;
cmd->method=p_method;
cmd->ret=r_ret;
SyncSemaphore *ss=_alloc_sync_sem();
cmd->sync=ss;
unlock();
if (sync) sync->post();
ss->sem->wait();
}
template<class T, class M, class P1,class R>
void push_and_ret( T * p_instance, M p_method, P1 p1, R* r_ret) {
CommandRet1<T,M,P1,R> * cmd = allocate_and_lock< CommandRet1<T,M,P1,R> >();
cmd->instance=p_instance;
cmd->method=p_method;
cmd->p1=p1;
cmd->ret=r_ret;
SyncSemaphore *ss=_alloc_sync_sem();
cmd->sync=ss;
unlock();
if (sync) sync->post();
ss->sem->wait();
}
template<class T, class M, class P1, class P2,class R>
void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, R* r_ret) {
CommandRet2<T,M,P1,P2,R> * cmd = allocate_and_lock< CommandRet2<T,M,P1,P2,R> >();
cmd->instance=p_instance;
cmd->method=p_method;
cmd->p1=p1;
cmd->p2=p2;
cmd->ret=r_ret;
SyncSemaphore *ss=_alloc_sync_sem();
cmd->sync=ss;
unlock();
if (sync) sync->post();
ss->sem->wait();
}
template<class T, class M, class P1, class P2, class P3,class R>
void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, R* r_ret ) {
CommandRet3<T,M,P1,P2,P3,R> * cmd = allocate_and_lock< CommandRet3<T,M,P1,P2,P3,R> >();
cmd->instance=p_instance;
cmd->method=p_method;
cmd->p1=p1;
cmd->p2=p2;
cmd->p3=p3;
cmd->ret=r_ret;
SyncSemaphore *ss=_alloc_sync_sem();
cmd->sync=ss;
unlock();
if (sync) sync->post();
ss->sem->wait();
}
template<class T, class M, class P1, class P2, class P3, class P4,class R>
void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, R* r_ret ) {
CommandRet4<T,M,P1,P2,P3,P4,R> * cmd = allocate_and_lock< CommandRet4<T,M,P1,P2,P3,P4,R> >();
cmd->instance=p_instance;
cmd->method=p_method;
cmd->p1=p1;
cmd->p2=p2;
cmd->p3=p3;
cmd->p4=p4;
cmd->ret=r_ret;
SyncSemaphore *ss=_alloc_sync_sem();
cmd->sync=ss;
unlock();
if (sync) sync->post();
ss->sem->wait();
}
template<class T, class M, class P1, class P2, class P3, class P4, class P5,class R>
void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, R* r_ret ) {
CommandRet5<T,M,P1,P2,P3,P4,P5,R> * cmd = allocate_and_lock< CommandRet5<T,M,P1,P2,P3,P4,P5,R> >();
cmd->instance=p_instance;
cmd->method=p_method;
cmd->p1=p1;
cmd->p2=p2;
cmd->p3=p3;
cmd->p4=p4;
cmd->p5=p5;
cmd->ret=r_ret;
SyncSemaphore *ss=_alloc_sync_sem();
cmd->sync=ss;
unlock();
if (sync) sync->post();
ss->sem->wait();
}
template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6,class R>
void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, R* r_ret ) {
CommandRet6<T,M,P1,P2,P3,P4,P5,P6,R> * cmd = allocate_and_lock< CommandRet6<T,M,P1,P2,P3,P4,P5,P6,R> >();
cmd->instance=p_instance;
cmd->method=p_method;
cmd->p1=p1;
cmd->p2=p2;
cmd->p3=p3;
cmd->p4=p4;
cmd->p5=p5;
cmd->p6=p6;
cmd->ret=r_ret;
SyncSemaphore *ss=_alloc_sync_sem();
cmd->sync=ss;
unlock();
if (sync) sync->post();
ss->sem->wait();
}
template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6,class P7,class R>
void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6,P7 p7, R* r_ret ) {
CommandRet7<T,M,P1,P2,P3,P4,P5,P6,P7,R> * cmd = allocate_and_lock< CommandRet7<T,M,P1,P2,P3,P4,P5,P6,P7,R> >();
cmd->instance=p_instance;
cmd->method=p_method;
cmd->p1=p1;
cmd->p2=p2;
cmd->p3=p3;
cmd->p4=p4;
cmd->p5=p5;
cmd->p6=p6;
cmd->p7=p7;
cmd->ret=r_ret;
SyncSemaphore *ss=_alloc_sync_sem();
cmd->sync=ss;
unlock();
if (sync) sync->post();
ss->sem->wait();
}
template<class T, class M>
void push_and_sync( T * p_instance, M p_method) {
CommandSync0<T,M> * cmd = allocate_and_lock< CommandSync0<T,M> >();
cmd->instance=p_instance;
cmd->method=p_method;
SyncSemaphore *ss=_alloc_sync_sem();
cmd->sync=ss;
unlock();
if (sync) sync->post();
ss->sem->wait();
}
template<class T, class M, class P1>
void push_and_sync( T * p_instance, M p_method, P1 p1) {
CommandSync1<T,M,P1> * cmd = allocate_and_lock< CommandSync1<T,M,P1> >();
cmd->instance=p_instance;
cmd->method=p_method;
cmd->p1=p1;
SyncSemaphore *ss=_alloc_sync_sem();
cmd->sync=ss;
unlock();
if (sync) sync->post();
ss->sem->wait();
}
template<class T, class M, class P1, class P2>
void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2) {
CommandSync2<T,M,P1,P2> * cmd = allocate_and_lock< CommandSync2<T,M,P1,P2> >();
cmd->instance=p_instance;
cmd->method=p_method;
cmd->p1=p1;
cmd->p2=p2;
SyncSemaphore *ss=_alloc_sync_sem();
cmd->sync=ss;
unlock();
if (sync) sync->post();
ss->sem->wait();
}
template<class T, class M, class P1, class P2, class P3>
void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3 ) {
CommandSync3<T,M,P1,P2,P3> * cmd = allocate_and_lock< CommandSync3<T,M,P1,P2,P3> >();
cmd->instance=p_instance;
cmd->method=p_method;
cmd->p1=p1;
cmd->p2=p2;
cmd->p3=p3;
SyncSemaphore *ss=_alloc_sync_sem();
cmd->sync=ss;
unlock();
if (sync) sync->post();
ss->sem->wait();
}
template<class T, class M, class P1, class P2, class P3, class P4>
void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4 ) {
CommandSync4<T,M,P1,P2,P3,P4> * cmd = allocate_and_lock< CommandSync4<T,M,P1,P2,P3,P4> >();
cmd->instance=p_instance;
cmd->method=p_method;
cmd->p1=p1;
cmd->p2=p2;
cmd->p3=p3;
cmd->p4=p4;
SyncSemaphore *ss=_alloc_sync_sem();
cmd->sync=ss;
unlock();
if (sync) sync->post();
ss->sem->wait();
}
template<class T, class M, class P1, class P2, class P3, class P4, class P5>
void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 ) {
CommandSync5<T,M,P1,P2,P3,P4,P5> * cmd = allocate_and_lock< CommandSync5<T,M,P1,P2,P3,P4,P5> >();
cmd->instance=p_instance;
cmd->method=p_method;
cmd->p1=p1;
cmd->p2=p2;
cmd->p3=p3;
cmd->p4=p4;
cmd->p5=p5;
SyncSemaphore *ss=_alloc_sync_sem();
cmd->sync=ss;
unlock();
if (sync) sync->post();
ss->sem->wait();
}
template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6>
void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6 ) {
CommandSync6<T,M,P1,P2,P3,P4,P5,P6> * cmd = allocate_and_lock< CommandSync6<T,M,P1,P2,P3,P4,P5,P6> >();
cmd->instance=p_instance;
cmd->method=p_method;
cmd->p1=p1;
cmd->p2=p2;
cmd->p3=p3;
cmd->p4=p4;
cmd->p5=p5;
cmd->p6=p6;
SyncSemaphore *ss=_alloc_sync_sem();
cmd->sync=ss;
unlock();
if (sync) sync->post();
ss->sem->wait();
}
template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6,class P7>
void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6,P7 p7 ) {
CommandSync7<T,M,P1,P2,P3,P4,P5,P6,P7> * cmd = allocate_and_lock< CommandSync7<T,M,P1,P2,P3,P4,P5,P6,P7> >();
cmd->instance=p_instance;
cmd->method=p_method;
cmd->p1=p1;
cmd->p2=p2;
cmd->p3=p3;
cmd->p4=p4;
cmd->p5=p5;
cmd->p6=p6;
cmd->p7=p7;
SyncSemaphore *ss=_alloc_sync_sem();
cmd->sync=ss;
unlock();
if (sync) sync->post();
ss->sem->wait();
}
void wait_and_flush_one() {
ERR_FAIL_COND(!sync);
sync->wait();
lock();
flush_one();
unlock();
}
void flush_all() {
ERR_FAIL_COND(sync);
lock();
while (true) {
bool exit = !flush_one();
if (exit)
break;
}
unlock();
}
CommandQueueMT(bool p_sync);
~CommandQueueMT();
};
#endif

View file

@ -0,0 +1,534 @@
/*************************************************************************/
/* compressed_translation.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 "compressed_translation.h"
#include "pair.h"
#include <string.h>
/////////// SMAZ /////////////
/*
Copyright (c) 2006-2009, Salvatore Sanfilippo
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of Smaz nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Our compression codebook, used for compression */
static const char *Smaz_cb[241] = {
"\002s,\266", "\003had\232\002leW", "\003on \216", "", "\001yS",
"\002ma\255\002li\227", "\003or \260", "", "\002ll\230\003s t\277",
"\004fromg\002mel", "", "\003its\332", "\001z\333", "\003ingF", "\001>\336",
"\001 \000\003 (\002nc\344", "\002nd=\003 on\312",
"\002ne\213\003hat\276\003re q", "", "\002ngT\003herz\004have\306\003s o\225",
"", "\003ionk\003s a\254\002ly\352", "\003hisL\003 inN\003 be\252", "",
"\003 fo\325\003 of \003 ha\311", "", "\002of\005",
"\003 co\241\002no\267\003 ma\370", "", "", "\003 cl\356\003enta\003 an7",
"\002ns\300\001\"e", "\003n t\217\002ntP\003s, \205",
"\002pe\320\003 we\351\002om\223", "\002on\037", "", "\002y G", "\003 wa\271",
"\003 re\321\002or*", "", "\002=\"\251\002ot\337", "\003forD\002ou[",
"\003 toR", "\003 th\r", "\003 it\366",
"\003but\261\002ra\202\003 wi\363\002</\361", "\003 wh\237", "\002 4",
"\003nd ?", "\002re!", "", "\003ng c", "",
"\003ly \307\003ass\323\001a\004\002rir", "", "", "", "\002se_", "\003of \"",
"\003div\364\002ros\003ere\240", "", "\002ta\310\001bZ\002si\324", "",
"\003and\a\002rs\335", "\002rt\362", "\002teE", "\003ati\316", "\002so\263",
"\002th\021", "\002tiJ\001c\034\003allp", "\003ate\345", "\002ss\246",
"\002stM", "", "\002><\346", "\002to\024", "\003arew", "\001d\030",
"\002tr\303", "", "\001\n1\003 a \222", "\003f tv\002veo", "\002un\340", "",
"\003e o\242", "\002a \243\002wa\326\001e\002", "\002ur\226\003e a\274",
"\002us\244\003\n\r\n\247", "\002ut\304\003e c\373", "\002we\221", "", "",
"\002wh\302", "\001f,", "", "", "", "\003d t\206", "", "", "\003th \343",
"\001g;", "", "", "\001\r9\003e s\265", "\003e t\234", "", "\003to Y",
"\003e\r\n\236", "\002d \036\001h\022", "", "\001,Q", "\002 a\031", "\002 b^",
"\002\r\n\025\002 cI", "\002 d\245", "\002 e\253", "\002 fh\001i\b\002e \v",
"", "\002 hU\001-\314", "\002 i8", "", "", "\002 l\315", "\002 m{",
"\002f :\002 n\354", "\002 o\035", "\002 p}\001.n\003\r\n\r\250", "",
"\002 r\275", "\002 s>", "\002 t\016", "", "\002g \235\005which+\003whi\367",
"\002 w5", "\001/\305", "\003as \214", "\003at \207", "", "\003who\331", "",
"\001l\026\002h \212", "", "\002, $", "", "\004withV", "", "", "", "\001m-", "",
"", "\002ac\357", "\002ad\350", "\003TheH", "", "", "\004this\233\001n\t",
"", "\002. y", "", "\002alX\003e, \365", "\003tio\215\002be\\",
"\002an\032\003ver\347", "", "\004that0\003tha\313\001o\006", "\003was2",
"\002arO", "\002as.", "\002at'\003the\001\004they\200\005there\322\005theird",
"\002ce\210", "\004were]", "", "\002ch\231\002l \264\001p<", "", "",
"\003one\256", "", "\003he \023\002dej", "\003ter\270", "\002cou", "",
"\002by\177\002di\201\002eax", "", "\002ec\327", "\002edB", "\002ee\353", "",
"", "\001r\f\002n )", "", "", "", "\002el\262", "", "\003in i\002en3", "",
"\002o `\001s\n", "", "\002er\033", "\003is t\002es6", "", "\002ge\371",
"\004.com\375", "\002fo\334\003our\330", "\003ch \301\001t\003", "\002hab", "",
"\003men\374", "", "\002he\020", "", "", "\001u&", "\002hif", "",
"\003not\204\002ic\203", "\003ed @\002id\355", "", "", "\002ho\273",
"\002r K\001vm", "", "", "", "\003t t\257\002il\360", "\002im\342",
"\003en \317\002in\017", "\002io\220", "\002s \027\001wA", "", "\003er |",
"\003es ~\002is%", "\002it/", "", "\002iv\272", "",
"\002t #\ahttp://C\001x\372", "\002la\211", "\001<\341", "\003, a\224"
};
/* Reverse compression codebook, used for decompression */
static const char *Smaz_rcb[254] = {
" ", "the", "e", "t", "a", "of", "o", "and", "i", "n", "s", "e ", "r", " th",
" t", "in", "he", "th", "h", "he ", "to", "\r\n", "l", "s ", "d", " a", "an",
"er", "c", " o", "d ", "on", " of", "re", "of ", "t ", ", ", "is", "u", "at",
" ", "n ", "or", "which", "f", "m", "as", "it", "that", "\n", "was", "en",
" ", " w", "es", " an", " i", "\r", "f ", "g", "p", "nd", " s", "nd ", "ed ",
"w", "ed", "http://", "for", "te", "ing", "y ", "The", " c", "ti", "r ", "his",
"st", " in", "ar", "nt", ",", " to", "y", "ng", " h", "with", "le", "al", "to ",
"b", "ou", "be", "were", " b", "se", "o ", "ent", "ha", "ng ", "their", "\"",
"hi", "from", " f", "in ", "de", "ion", "me", "v", ".", "ve", "all", "re ",
"ri", "ro", "is ", "co", "f t", "are", "ea", ". ", "her", " m", "er ", " p",
"es ", "by", "they", "di", "ra", "ic", "not", "s, ", "d t", "at ", "ce", "la",
"h ", "ne", "as ", "tio", "on ", "n t", "io", "we", " a ", "om", ", a", "s o",
"ur", "li", "ll", "ch", "had", "this", "e t", "g ", "e\r\n", " wh", "ere",
" co", "e o", "a ", "us", " d", "ss", "\n\r\n", "\r\n\r", "=\"", " be", " e",
"s a", "ma", "one", "t t", "or ", "but", "el", "so", "l ", "e s", "s,", "no",
"ter", " wa", "iv", "ho", "e a", " r", "hat", "s t", "ns", "ch ", "wh", "tr",
"ut", "/", "have", "ly ", "ta", " ha", " on", "tha", "-", " l", "ati", "en ",
"pe", " re", "there", "ass", "si", " fo", "wa", "ec", "our", "who", "its", "z",
"fo", "rs", ">", "ot", "un", "<", "im", "th ", "nc", "ate", "><", "ver", "ad",
" we", "ly", "ee", " n", "id", " cl", "ac", "il", "</", "rt", " wi", "div",
"e, ", " it", "whi", " ma", "ge", "x", "e c", "men", ".com"
};
static int smaz_compress(const char *in, int inlen, char *out, int outlen) {
unsigned int h1,h2,h3=0;
int verblen = 0, _outlen = outlen;
char verb[256], *_out = out;
while(inlen) {
int j = 7, needed;
char *flush = NULL;
const char *slot;
h1 = h2 = in[0]<<3;
if (inlen > 1) h2 += in[1];
if (inlen > 2) h3 = h2^in[2];
if (j > inlen) j = inlen;
/* Try to lookup substrings into the hash table, starting from the
* longer to the shorter substrings */
for (; j > 0; j--) {
switch(j) {
case 1: slot = Smaz_cb[h1%241]; break;
case 2: slot = Smaz_cb[h2%241]; break;
default: slot = Smaz_cb[h3%241]; break;
}
while(slot[0]) {
if (slot[0] == j && memcmp(slot+1,in,j) == 0) {
/* Match found in the hash table,
* prepare a verbatim bytes flush if needed */
if (verblen) {
needed = (verblen == 1) ? 2 : 2+verblen;
flush = out;
out += needed;
outlen -= needed;
}
/* Emit the byte */
if (outlen <= 0) return _outlen+1;
out[0] = slot[slot[0]+1];
out++;
outlen--;
inlen -= j;
in += j;
goto out;
} else {
slot += slot[0]+2;
}
}
}
/* Match not found - add the byte to the verbatim buffer */
verb[verblen] = in[0];
verblen++;
inlen--;
in++;
out:
/* Prepare a flush if we reached the flush length limit, and there
* is not already a pending flush operation. */
if (!flush && (verblen == 256 || (verblen > 0 && inlen == 0))) {
needed = (verblen == 1) ? 2 : 2+verblen;
flush = out;
out += needed;
outlen -= needed;
if (outlen < 0) return _outlen+1;
}
/* Perform a verbatim flush if needed */
if (flush) {
if (verblen == 1) {
flush[0] = (signed char)254;
flush[1] = verb[0];
} else {
flush[0] = (signed char)255;
flush[1] = (signed char)(verblen-1);
memcpy(flush+2,verb,verblen);
}
flush = NULL;
verblen = 0;
}
}
return out-_out;
}
static int smaz_decompress(const char *in, int inlen, char *out, int outlen) {
unsigned char *c = (unsigned char*) in;
char *_out = out;
int _outlen = outlen;
while(inlen) {
if (*c == 254) {
/* Verbatim byte */
if (outlen < 1) return _outlen+1;
*out = *(c+1);
out++;
outlen--;
c += 2;
inlen -= 2;
} else if (*c == 255) {
/* Verbatim string */
int len = (*(c+1))+1;
if (outlen < len) return _outlen+1;
memcpy(out,c+2,len);
out += len;
outlen -= len;
c += 2+len;
inlen -= 2+len;
} else {
/* Codebook entry */
const char *s = Smaz_rcb[*c];
int len = strlen(s);
if (outlen < len) return _outlen+1;
memcpy(out,s,len);
out += len;
outlen -= len;
c++;
inlen--;
}
}
return out-_out;
}
/////////// END OF SMAZ /////////////
struct _PHashTranslationCmp {
int orig_len;
CharString compressed;
int offset;
};
void PHashTranslation::generate(const Ref<Translation> &p_from) {
#ifdef TOOLS_ENABLED
List<StringName> keys;
p_from->get_message_list(&keys);
int size=Math::larger_prime(keys.size());
print_line("compressing keys: "+itos(keys.size()));
Vector< Vector< Pair<int,CharString> > > buckets;
Vector< Map< uint32_t, int > > table;
Vector< uint32_t > hfunc_table;
Vector< _PHashTranslationCmp > compressed;
table.resize(size);
hfunc_table.resize(size);
buckets.resize(size);
compressed.resize(keys.size());
int idx=0;
int total_compression_size=0;
int total_string_size=0;
for(List<StringName>::Element *E=keys.front();E;E=E->next()) {
//hash string
CharString cs = E->get().operator String().utf8();
uint32_t h = hash(0,cs.get_data());
Pair<int,CharString> p;
p.first=idx;
p.second=cs;
buckets[h % size].push_back(p);
//compress string
CharString src_s = p_from->get_message(E->get()).operator String().utf8();
_PHashTranslationCmp ps;
ps.orig_len=src_s.size();
ps.offset=total_compression_size;
if (ps.orig_len!=0) {
CharString dst_s;
dst_s.resize(src_s.size());
int ret = smaz_compress(src_s.get_data(),src_s.size(),&dst_s[0],src_s.size());
if (ret>=src_s.size()) {
//if compressed is larger than original, just use original
ps.orig_len=src_s.size();
ps.compressed=src_s;
} else {
dst_s.resize(ret);
//ps.orig_len=;
ps.compressed=dst_s;
}
} else {
ps.orig_len=1;
ps.compressed.resize(1);
ps.compressed[0]=0;
}
compressed[idx]=ps;
total_compression_size+=ps.compressed.size();
total_string_size+=src_s.size();
idx++;
}
int bucket_table_size=0;
print_line("total compressed string size: "+itos(total_compression_size)+" ("+itos(total_string_size)+" uncompressed).");
for(int i=0;i<size;i++) {
Vector< Pair<int,CharString> > &b = buckets[i];
Map< uint32_t, int > &t=table[i];
if (b.size()==0)
continue;
//print_line("bucket: "+itos(i)+" - elements: "+itos(b.size()));
int d = 1;
int item =0;
while(item < b.size()) {
uint32_t slot = hash(d,b[item].second.get_data());
if (t.has(slot)) {
item=0;
d++;
t.clear();
} else {
t[slot]=b[item].first;
item++;
}
}
hfunc_table[i]=d;
bucket_table_size+=2+b.size()*4;
}
print_line("bucket table size: "+itos(bucket_table_size*4));
print_line("hash table size: "+itos(size*4));
hash_table.resize(size);
bucket_table.resize(bucket_table_size);
DVector<int>::Write htwb = hash_table.write();
DVector<int>::Write btwb = bucket_table.write();
uint32_t *htw = (uint32_t*)&htwb[0];
uint32_t *btw = (uint32_t*)&btwb[0];
int btindex=0;
int collisions=0;
for(int i=0;i<size;i++) {
Map< uint32_t, int > &t=table[i];
if (t.size()==0) {
htw[i]=0xFFFFFFFF; //nothing
continue;
} else if (t.size()>1) {
collisions+=t.size()-1;
}
htw[i]=btindex;
btw[btindex++]=t.size();
btw[btindex++]=hfunc_table[i];
for( Map< uint32_t, int >::Element *E=t.front();E;E=E->next()) {
btw[btindex++]=E->key();
btw[btindex++]=compressed[E->get()].offset;
btw[btindex++]=compressed[E->get()].compressed.size();
btw[btindex++]=compressed[E->get()].orig_len;
}
}
print_line("total collisions: "+itos(collisions));
strings.resize(total_compression_size);
DVector<uint8_t>::Write cw = strings.write();
for(int i=0;i<compressed.size();i++) {
memcpy(&cw[compressed[i].offset],compressed[i].compressed.get_data(),compressed[i].compressed.size());
}
ERR_FAIL_COND(btindex!=bucket_table_size);
set_locale(p_from->get_locale());
#endif
}
bool PHashTranslation::_set(const StringName& p_name, const Variant& p_value) {
String name = p_name.operator String();
if (name=="hash_table") {
hash_table=p_value;
print_line("translation: loaded hash table of size: "+itos(hash_table.size()));
} else if (name=="bucket_table") {
bucket_table=p_value;
print_line("translation: loaded bucket table of size: "+itos(bucket_table.size()));
} else if (name=="strings") {
strings=p_value;
print_line("translation: loaded string table of size: "+itos(strings.size()));
} else if (name=="load_from") {
print_line("generating");
generate(p_value);
} else
return false;
return true;
}
bool PHashTranslation::_get(const StringName& p_name,Variant &r_ret) const{
String name = p_name.operator String();
if (name=="hash_table")
r_ret=hash_table;
else if (name=="bucket_table")
r_ret=bucket_table;
else if (name=="strings")
r_ret=strings;
else
return false;
return true;
}
StringName PHashTranslation::get_message(const StringName& p_src_text) const {
int htsize = hash_table.size();
if (htsize==0)
return StringName();
CharString str = p_src_text.operator String().utf8();
uint32_t h = hash(0,str.get_data());
DVector<int>::Read htr = hash_table.read();
const uint32_t *htptr = (const uint32_t*)&htr[0];
DVector<int>::Read btr = bucket_table.read();
const uint32_t *btptr = (const uint32_t*)&btr[0];
DVector<uint8_t>::Read sr = strings.read();
const char *sptr= (const char*)&sr[0];
uint32_t p = htptr[ h % htsize];
//print_line("String: "+p_src_text.operator String());
//print_line("Hash: "+itos(p));
if (p==0xFFFFFFFF) {
// print_line("GETMSG: Nothing!");
return StringName(); //nothing
}
const Bucket &bucket = *(const Bucket*)&btptr[p];
h = hash(bucket.func,str.get_data());
int idx=-1;
for(int i=0;i<bucket.size;i++) {
if (bucket.elem[i].key==h) {
idx=i;
break;
}
}
//print_line("bucket pos: "+itos(idx));
if (idx==-1) {
// print_line("GETMSG: Not in Bucket!");
return StringName();
}
if (bucket.elem[idx].comp_size == bucket.elem[idx].uncomp_size) {
String rstr;
rstr.parse_utf8(&sptr[ bucket.elem[idx].str_offset ], bucket.elem[idx].uncomp_size );
// print_line("Uncompressed, size: "+itos(bucket.elem[idx].comp_size));
// print_line("Return: "+rstr);
return rstr;
} else {
CharString uncomp;
uncomp.resize( bucket.elem[idx].uncomp_size+1 );
smaz_decompress(&sptr[ bucket.elem[idx].str_offset ], bucket.elem[idx].comp_size,uncomp.ptr(),bucket.elem[idx].uncomp_size );
String rstr;
rstr.parse_utf8(uncomp.get_data());
// print_line("Compressed, size: "+itos(bucket.elem[idx].comp_size));
// print_line("Return: "+rstr);
return rstr;
}
}
void PHashTranslation::_get_property_list( List<PropertyInfo> *p_list) const{
p_list->push_back( PropertyInfo(Variant::INT_ARRAY, "hash_table"));
p_list->push_back( PropertyInfo(Variant::INT_ARRAY, "bucket_table"));
p_list->push_back( PropertyInfo(Variant::RAW_ARRAY, "strings"));
p_list->push_back( PropertyInfo(Variant::OBJECT, "load_from",PROPERTY_HINT_RESOURCE_TYPE,"Translation",PROPERTY_USAGE_EDITOR));
}
void PHashTranslation::_bind_methods() {
ObjectTypeDB::bind_method(_MD("generate","from:Translation"),&PHashTranslation::generate);
}
PHashTranslation::PHashTranslation()
{
}

View file

@ -0,0 +1,93 @@
/*************************************************************************/
/* compressed_translation.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef COMPRESSED_TRANSLATION_H
#define COMPRESSED_TRANSLATION_H
#include "translation.h"
class PHashTranslation : public Translation {
OBJ_TYPE(PHashTranslation,Translation);
//this translation uses a sort of modified perfect hash algorithm
//it requieres hashing strings twice and then does a binary search,
//so it's slower, but at the same time it has an extreemly high chance
//of catching untranslated strings
//load/store friendly types
DVector<int> hash_table;
DVector<int> bucket_table;
DVector<uint8_t> strings;
struct Bucket {
int size;
uint32_t func;
struct Elem {
uint32_t key;
uint32_t str_offset;
uint32_t comp_size;
uint32_t uncomp_size;
};
Elem elem[1];
};
_FORCE_INLINE_ uint32_t hash( uint32_t d, const char *p_str ) const {
if (d==0)
d=0x1000193;
while(*p_str) {
d = (d * 0x1000193) ^ uint32_t(*p_str);
p_str++;
}
return d;
}
protected:
bool _set(const StringName& p_name, const Variant& p_value);
bool _get(const StringName& p_name,Variant &r_ret) const;
void _get_property_list( List<PropertyInfo> *p_list) const;
static void _bind_methods();
public:
virtual StringName get_message(const StringName& p_src_text) const; //overridable for other implementations
void generate(const Ref<Translation> &p_from);
PHashTranslation();
};
#endif // COMPRESSED_TRANSLATION_H

View file

@ -0,0 +1,47 @@
/*************************************************************************/
/* core_string_names.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 "core_string_names.h"
CoreStringNames* CoreStringNames::singleton=NULL;
CoreStringNames::CoreStringNames() {
_free=StaticCString::create("free");
changed=StaticCString::create("changed");
_meta=StaticCString::create("__meta__");
_script=StaticCString::create("script/script");
script_changed=StaticCString::create("script_changed");
___pdcdata=StaticCString::create("___pdcdata");
__getvar=StaticCString::create("__getvar");
_iter_init=StaticCString::create("_iter_init");
_iter_next=StaticCString::create("_iter_next");
_iter_get=StaticCString::create("_iter_get");
}

62
core/core_string_names.h Normal file
View file

@ -0,0 +1,62 @@
/*************************************************************************/
/* core_string_names.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef CORE_STRING_NAMES_H
#define CORE_STRING_NAMES_H
#include "string_db.h"
class CoreStringNames {
friend void register_core_types();
friend void unregister_core_types();
static CoreStringNames* singleton;
static void create() { singleton = memnew(CoreStringNames); }
static void free() { memdelete( singleton); singleton=NULL; }
CoreStringNames();
public:
_FORCE_INLINE_ static CoreStringNames* get_singleton() { return singleton; }
StringName _free;
StringName changed;
StringName _meta;
StringName _script;
StringName script_changed;
StringName ___pdcdata;
StringName __getvar;
StringName _iter_init;
StringName _iter_next;
StringName _iter_get;
};
#endif // SCENE_STRING_NAMES_H

229
core/dictionary.cpp Normal file
View file

@ -0,0 +1,229 @@
/*************************************************************************/
/* dictionary.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 "dictionary.h"
#include "safe_refcount.h"
#include "variant.h"
#include "io/json.h"
struct _DictionaryVariantHash {
static _FORCE_INLINE_ uint32_t hash(const Variant &p_variant) { return p_variant.hash(); }
};
struct DictionaryPrivate {
SafeRefCount refcount;
HashMap<Variant,Variant,_DictionaryVariantHash> variant_map;
bool shared;
};
void Dictionary::get_key_list( List<Variant> *p_keys) const {
_p->variant_map.get_key_list(p_keys);
}
void Dictionary::_copy_on_write() const {
//make a copy of what we have
if (_p->shared)
return;
DictionaryPrivate *p = memnew(DictionaryPrivate);
p->shared=_p->shared;
p->variant_map=_p->variant_map;
p->refcount.init();
_unref();
_p=p;
}
Variant& Dictionary::operator[](const Variant& p_key) {
_copy_on_write();
return _p->variant_map[p_key];
}
const Variant& Dictionary::operator[](const Variant& p_key) const {
return _p->variant_map[p_key];
}
const Variant* Dictionary::getptr(const Variant& p_key) const {
return _p->variant_map.getptr(p_key);
}
Variant* Dictionary::getptr(const Variant& p_key) {
_copy_on_write();
return _p->variant_map.getptr(p_key);
}
Variant Dictionary::get_valid(const Variant& p_key) const {
const Variant *v = getptr(p_key);
if (!v)
return Variant();
return *v;
}
int Dictionary::size() const {
return _p->variant_map.size();
}
bool Dictionary::empty() const {
return !_p->variant_map.size();
}
bool Dictionary::has(const Variant& p_key) const {
return _p->variant_map.has(p_key);
}
void Dictionary::erase(const Variant& p_key) {
_copy_on_write();
_p->variant_map.erase(p_key);
}
bool Dictionary::operator==(const Dictionary& p_dictionary) const {
return _p==p_dictionary._p;
}
void Dictionary::_ref(const Dictionary& p_from) const {
//make a copy first (thread safe)
if (!p_from._p->refcount.ref())
return; // couldn't copy
//if this is the same, unreference the other one
if (p_from._p==_p) {
_p->refcount.unref();
return;
}
if (_p)
_unref();
_p=p_from._p;
}
void Dictionary::clear() {
_copy_on_write();
_p->variant_map.clear();
}
bool Dictionary::is_shared() const {
return _p->shared;
}
void Dictionary::_unref() const {
ERR_FAIL_COND(!_p);
if (_p->refcount.unref()) {
memdelete(_p);
}
_p=NULL;
}
uint32_t Dictionary::hash() const {
return hash_djb2_one_64(make_uint64_t(_p));
}
Array Dictionary::keys() const {
Array karr;
karr.resize(size());
const Variant *K=NULL;
int idx=0;
while((K=next(K))) {
karr[idx++]=(*K);
}
return karr;
}
const Variant* Dictionary::next(const Variant* p_key) const {
return _p->variant_map.next(p_key);
}
Error Dictionary::parse_json(const String& p_json) {
String errstr;
int errline=0;
Error err = JSON::parse(p_json,*this,errstr,errline);
if (err!=OK) {
ERR_EXPLAIN("Error parsing JSON: "+errstr+" at line: "+itos(errline));
ERR_FAIL_COND_V(err!=OK,err);
}
return OK;
}
String Dictionary::to_json() const {
return JSON::print(*this);
}
void Dictionary::operator=(const Dictionary& p_dictionary) {
_ref(p_dictionary);
}
Dictionary::Dictionary(const Dictionary& p_from) {
_p=NULL;
_ref(p_from);
}
Dictionary::Dictionary(bool p_shared) {
_p=memnew( DictionaryPrivate );
_p->refcount.init();
_p->shared=p_shared;
}
Dictionary::~Dictionary() {
_unref();
}

88
core/dictionary.h Normal file
View file

@ -0,0 +1,88 @@
/*************************************************************************/
/* dictionary.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef DICTIONARY_H
#define DICTIONARY_H
#include "list.h"
#include "array.h"
#include "ustring.h"
class Variant;
struct DictionaryPrivate;
class Dictionary {
mutable DictionaryPrivate *_p;
void _copy_on_write() const;
void _ref(const Dictionary& p_from) const;
void _unref() const;
public:
void get_key_list( List<Variant> *p_keys) const;
Variant& operator[](const Variant& p_key);
const Variant& operator[](const Variant& p_key) const;
const Variant* getptr(const Variant& p_key) const;
Variant* getptr(const Variant& p_key);
Variant get_valid(const Variant& p_key) const;
int size() const;
bool empty() const;
void clear();
Error parse_json(const String& p_json);
String to_json() const;
bool is_shared() const;
bool has(const Variant& p_key) const;
void erase(const Variant& p_key);
bool operator==(const Dictionary& p_dictionary) const;
uint32_t hash() const;
void operator=(const Dictionary& p_dictionary);
const Variant* next(const Variant* p_key=NULL) const;
Array keys() const;
Dictionary(const Dictionary& p_from);
Dictionary(bool p_shared=false);
~Dictionary();
};
#endif // DICTIONARY_H

32
core/dvector.cpp Normal file
View file

@ -0,0 +1,32 @@
/*************************************************************************/
/* dvector.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 "dvector.h"
Mutex* dvector_lock=NULL;

412
core/dvector.h Normal file
View file

@ -0,0 +1,412 @@
/*************************************************************************/
/* dvector.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef DVECTOR_H
#define DVECTOR_H
#include "os/memory.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
extern Mutex* dvector_lock;
template<class T>
class DVector {
mutable MID mem;
void copy_on_write() {
if (!mem.is_valid())
return;
if (dvector_lock)
dvector_lock->lock();
MID_Lock lock( mem );
if ( *(int*)lock.data() == 1 ) {
// one reference, means no refcount changes
if (dvector_lock)
dvector_lock->unlock();
return;
}
MID new_mem= dynalloc( mem.get_size() );
if (!new_mem.is_valid()) {
if (dvector_lock)
dvector_lock->unlock();
ERR_FAIL_COND( new_mem.is_valid() ); // out of memory
}
MID_Lock dst_lock( new_mem );
int *rc = (int*)dst_lock.data();
*rc=1;
T * dst = (T*)(rc + 1 );
T * src =(T*) ((int*)lock.data() + 1 );
int count = (mem.get_size() - sizeof(int)) / sizeof(T);
for (int i=0;i<count;i++) {
memnew_placement( &dst[i], T(src[i]) );
}
(*(int*)lock.data())--;
// unlock all
dst_lock=MID_Lock();
lock=MID_Lock();
mem=new_mem;
if (dvector_lock)
dvector_lock->unlock();
}
void reference( const DVector& p_dvector ) {
unreference();
if (dvector_lock)
dvector_lock->lock();
if (!p_dvector.mem.is_valid()) {
if (dvector_lock)
dvector_lock->unlock();
return;
}
MID_Lock lock(p_dvector.mem);
int * rc = (int*)lock.data();
(*rc)++;
lock = MID_Lock();
mem=p_dvector.mem;
if (dvector_lock)
dvector_lock->unlock();
}
void unreference() {
if (dvector_lock)
dvector_lock->lock();
if (!mem.is_valid()) {
if (dvector_lock)
dvector_lock->unlock();
return;
}
MID_Lock lock(mem);
int * rc = (int*)lock.data();
(*rc)--;
if (*rc==0) {
// no one else using it, destruct
T * t= (T*)(rc+1);
int count = (mem.get_size() - sizeof(int)) / sizeof(T);
for (int i=0;i<count;i++) {
t[i].~T();
}
}
lock = MID_Lock();
mem = MID ();
if (dvector_lock)
dvector_lock->unlock();
}
public:
class Read {
friend class DVector;
MID_Lock lock;
const T * mem;
public:
_FORCE_INLINE_ const T& operator[](int p_index) const { return mem[p_index]; }
_FORCE_INLINE_ const T *ptr() const { return mem; }
Read() { mem=NULL; }
};
class Write {
friend class DVector;
MID_Lock lock;
T * mem;
public:
_FORCE_INLINE_ T& operator[](int p_index) { return mem[p_index]; }
_FORCE_INLINE_ T *ptr() { return mem; }
Write() { mem=NULL; }
};
Read read() const {
Read r;
if (mem.is_valid()) {
r.lock = MID_Lock( mem );
r.mem = (const T*)((int*)r.lock.data()+1);
}
return r;
}
Write write() {
Write w;
if (mem.is_valid()) {
copy_on_write();
w.lock = MID_Lock( mem );
w.mem = (T*)((int*)w.lock.data()+1);
}
return w;
}
template<class MC>
void fill_with(const MC& p_mc) {
int c=p_mc.size();
resize(c);
Write w=write();
int idx=0;
for(const typename MC::Element *E=p_mc.front();E;E=E->next()) {
w[idx++]=E->get();
}
}
void remove(int p_index) {
int s = size();
ERR_FAIL_INDEX(p_index, s);
Write w = write();
for (int i=p_index; i<s-1; i++) {
w[i]=w[i+1];
};
w = Write();
resize(s-1);
}
inline int size() const;
T get(int p_index) const;
void set(int p_index, const T& p_val);
void push_back(const T& p_val);
void append(const T& p_val) { push_back(p_val); }
void append_array(const DVector<T>& p_arr) {
int ds = p_arr.size();
if (ds==0)
return;
int bs = size();
resize( bs + ds);
Write w = write();
Read r = p_arr.read();
for(int i=0;i<ds;i++)
w[bs+i]=r[i];
}
bool is_locked() const { return mem.is_locked(); }
inline const T operator[](int p_index) const;
Error resize(int p_size);
void operator=(const DVector& p_dvector) { reference(p_dvector); }
DVector() {}
DVector(const DVector& p_dvector) { reference(p_dvector); }
~DVector() { unreference(); }
};
template<class T>
int DVector<T>::size() const {
return mem.is_valid() ? ((mem.get_size() - sizeof(int)) / sizeof(T) ) : 0;
}
template<class T>
T DVector<T>::get(int p_index) const {
return operator[](p_index);
}
template<class T>
void DVector<T>::set(int p_index, const T& p_val) {
if (p_index<0 || p_index>=size()) {
ERR_FAIL_COND(p_index<0 || p_index>=size());
}
Write w = write();
w[p_index]=p_val;
}
template<class T>
void DVector<T>::push_back(const T& p_val) {
resize( size() + 1 );
set( size() -1, p_val );
}
template<class T>
const T DVector<T>::operator[](int p_index) const {
if (p_index<0 || p_index>=size()) {
T& aux=*((T*)0); //nullreturn
ERR_FAIL_COND_V(p_index<0 || p_index>=size(),aux);
}
Read r = read();
return r[p_index];
}
template<class T>
Error DVector<T>::resize(int p_size) {
if (dvector_lock)
dvector_lock->lock();
bool same = p_size==size();
if (dvector_lock)
dvector_lock->unlock();
// no further locking is necesary because we are supposed to own the only copy of this (using copy on write)
if (same)
return OK;
if (p_size == 0 ) {
unreference();
return OK;
}
copy_on_write(); // make it unique
ERR_FAIL_COND_V( mem.is_locked(), ERR_LOCKED ); // if after copy on write, memory is locked, fail.
if (p_size > size() ) {
int oldsize=size();
MID_Lock lock;
if (oldsize==0) {
mem = dynalloc( p_size * sizeof(T) + sizeof(int) );
lock=MID_Lock(mem);
int *rc = ((int*)lock.data());
*rc=1;
} else {
if (dynrealloc( mem, p_size * sizeof(T) + sizeof(int) )!=OK ) {
ERR_FAIL_V(ERR_OUT_OF_MEMORY); // out of memory
}
lock=MID_Lock(mem);
}
T *t = (T*)((int*)lock.data() + 1);
for (int i=oldsize;i<p_size;i++) {
memnew_placement(&t[i], T );
}
lock = MID_Lock(); // clear
} else {
int oldsize=size();
MID_Lock lock(mem);
T *t = (T*)((int*)lock.data() + 1);
for (int i=p_size;i<oldsize;i++) {
t[i].~T();
}
lock = MID_Lock(); // clear
if (dynrealloc( mem, p_size * sizeof(T) + sizeof(int) )!=OK ) {
ERR_FAIL_V(ERR_OUT_OF_MEMORY); // wtf error
}
}
return OK;
}
#endif

95
core/error_list.h Normal file
View file

@ -0,0 +1,95 @@
/*************************************************************************/
/* error_list.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef ERROR_LIST_H
#define ERROR_LIST_H
/** Error List. Please never compare an error against FAILED
* Either do result != OK , or !result. This way, Error fail
* values can be more detailed in the future.
*
* This is a generic error list, mainly for organizing a language of returning errors.
*/
enum Error {
OK,
FAILED, ///< Generic fail error
ERR_UNAVAILABLE, ///< What is requested is unsupported/unavailable
ERR_UNCONFIGURED, ///< The object being used hasnt been properly set up yet
ERR_UNAUTHORIZED, ///< Missing credentials for requested resource
ERR_PARAMETER_RANGE_ERROR, ///< Parameter given out of range (5)
ERR_OUT_OF_MEMORY, ///< Out of memory
ERR_FILE_NOT_FOUND,
ERR_FILE_BAD_DRIVE,
ERR_FILE_BAD_PATH,
ERR_FILE_NO_PERMISSION, // (10)
ERR_FILE_ALREADY_IN_USE,
ERR_FILE_CANT_OPEN,
ERR_FILE_CANT_WRITE,
ERR_FILE_CANT_READ,
ERR_FILE_UNRECOGNIZED, // (15)
ERR_FILE_CORRUPT,
ERR_FILE_EOF,
ERR_CANT_OPEN, ///< Can't open a resource/socket/file
ERR_CANT_CREATE,
ERROR_QUERY_FAILED, // (20)
ERR_ALREADY_IN_USE,
ERR_LOCKED, ///< resource is locked
ERR_TIMEOUT,
ERR_CANT_CONNECT,
ERR_CANT_RESOLVE, // (25)
ERR_CONNECTION_ERROR,
ERR_CANT_AQUIRE_RESOURCE,
ERR_CANT_FORK,
ERR_INVALID_DATA, ///< Data passed is invalid
ERR_INVALID_PARAMETER, ///< Parameter passed is invalid (30)
ERR_ALREADY_EXISTS, ///< When adding, item already exists
ERR_DOES_NOT_EXIST, ///< When retrieving/erasing, it item does not exist
ERR_DATABASE_CANT_READ, ///< database is full
ERR_DATABASE_CANT_WRITE, ///< database is full
ERR_COMPILATION_FAILED, // (35)
ERR_METHOD_NOT_FOUND,
ERR_LINK_FAILED,
ERR_SCRIPT_FAILED,
ERR_CYCLIC_LINK,
ERR_INVALID_DECLARATION, // (40)
ERR_DUPLICATE_SYMBOL,
ERR_PARSE_ERROR,
ERR_BUSY,
ERR_SKIP,
ERR_HELP, ///< user requested help!! (45)
ERR_BUG, ///< a bug in the software certainly happened, due to a double check failing or unexpected behavior.
ERR_PRINTER_ON_FIRE, /// the parallel port printer is engulfed in flames
ERR_OMFG_THIS_IS_VERY_VERY_BAD, ///< shit happens, has never been used, though
ERR_WTF = ERR_OMFG_THIS_IS_VERY_VERY_BAD ///< short version of the above
};
#endif

102
core/error_macros.cpp Normal file
View file

@ -0,0 +1,102 @@
/*************************************************************************/
/* error_macros.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 "error_macros.h"
#include "os/os.h"
bool _err_error_exists=false;
static ErrorHandlerList *error_handler_list=NULL;
void _err_set_last_error(const char* p_err) {
OS::get_singleton()->set_last_error(p_err);
}
void _err_clear_last_error() {
OS::get_singleton()->clear_last_error();
}
void add_error_handler(ErrorHandlerList *p_handler) {
_global_lock();
p_handler->next=error_handler_list;
error_handler_list=p_handler;
_global_unlock();
}
void remove_error_handler(ErrorHandlerList *p_handler) {
_global_lock();
ErrorHandlerList *prev = NULL;
ErrorHandlerList *l = error_handler_list;
while(l) {
if (l==p_handler) {
if (prev)
prev->next=l->next;
else
error_handler_list=l->next;
break;
}
prev=l;
l=l->next;
}
_global_unlock();
}
void _err_print_error(const char* p_function, const char* p_file,int p_line,const char *p_error,ErrorHandlerType p_type) {
OS::get_singleton()->print_error(p_function,p_file,p_line,p_error,_err_error_exists?OS::get_singleton()->get_last_error():"",(OS::ErrorType)p_type);
_global_lock();
ErrorHandlerList *l = error_handler_list;
while(l) {
l->errfunc(l->userdata,p_function,p_file,p_line,p_error,_err_error_exists?OS::get_singleton()->get_last_error():"",p_type);
l=l->next;
}
_global_unlock();
if (_err_error_exists) {
OS::get_singleton()->clear_last_error();
_err_error_exists=false;
}
}

222
core/error_macros.h Normal file
View file

@ -0,0 +1,222 @@
/*************************************************************************/
/* error_macros.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef ERROR_MACROS_H
#define ERROR_MACROS_H
/**
* Error macros. Unlike exceptions and asserts, these macros try to mantain consistency and stability
* inside the code. It is recommended to always return processable data, so in case of an error, the
* engine can stay working well.
* In most cases, bugs and/or invalid data are not fatal and should never allow a perfectly running application
* to fail or crash.
*/
/**
* Pointer to the error macro priting function. Reassign to any function to have errors printed
*/
/** Function used by the error macros */
// function, file, line, error, explanation
enum ErrorHandlerType {
ERR_HANDLER_ERROR,
ERR_HANDLER_WARNING,
ERR_HANDLER_SCRIPT
};
typedef void (*ErrorHandlerFunc)(void*,const char*,const char*,int p_line,const char *, const char *,ErrorHandlerType p_type);
void _err_set_last_error(const char* p_err);
void _err_clear_last_error();
struct ErrorHandlerList {
ErrorHandlerFunc errfunc;
void *userdata;
ErrorHandlerList*next;
ErrorHandlerList() { errfunc=0; next=0; userdata=0; }
};
void add_error_handler(ErrorHandlerList *p_handler);
void remove_error_handler(ErrorHandlerList *p_handler);
void _err_print_error(const char* p_function,const char* p_file,int p_line,const char *p_error,ErrorHandlerType p_type=ERR_HANDLER_ERROR);
#ifndef _STR
#define _STR(m_x) #m_x
#define _MKSTR(m_x) _STR(m_x)
#endif
#define _FNL __FILE__":"
/** An index has failed if m_index<0 or m_index >=m_size, the function exists */
extern bool _err_error_exists;
#ifdef DEBUG_ENABLED
/** Print a warning string.
*/
#define ERR_EXPLAINC(m_reason) {_err_set_last_error(m_reason); _err_error_exists=true;}
#define ERR_EXPLAIN(m_string) {_err_set_last_error(String(m_string).utf8().get_data()); _err_error_exists=true;}
#else
#define ERR_EXPLAIN( m_text )
#define ERR_EXPLAINC( m_text )
#endif
#ifdef __GNUC__
//#define FUNCTION_STR __PRETTY_FUNCTION__ - too annoying
#define FUNCTION_STR __FUNCTION__
#else
#define FUNCTION_STR __FUNCTION__
#endif
#define ERR_FAIL_INDEX(m_index,m_size) \
do {if ((m_index)<0 || (m_index)>=(m_size)) { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Index "_STR(m_index)" out of size ("_STR(m_size)")."); \
return; \
} else _err_error_exists=false; } while(0); \
/** An index has failed if m_index<0 or m_index >=m_size, the function exists.
* This function returns an error value, if returning Error, please select the most
* appropriate error condition from error_macros.h
*/
#define ERR_FAIL_INDEX_V(m_index,m_size,m_retval) \
do {if ((m_index)<0 || (m_index)>=(m_size)) { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Index "_STR(m_index)" out of size ("_STR(m_size)")."); \
return m_retval; \
} else _err_error_exists=false;} while (0);
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
* the function will exit.
*/
#define ERR_FAIL_NULL(m_param) \
{ if ( !m_param ) { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Parameter ' "_STR(m_param)" ' is null."); \
return; \
}else _err_error_exists=false; } \
#define ERR_FAIL_NULL_V(m_param,m_retval) \
{ if ( !m_param ) { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Parameter ' "_STR(m_param)" ' is null."); \
return m_retval; \
}else _err_error_exists=false; } \
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
* the function will exit.
*/
#define ERR_FAIL_COND(m_cond) \
{ if ( m_cond ) { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' "_STR(m_cond)" ' is true."); \
return; \
}else _err_error_exists=false; } \
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
* the function will exit.
* This function returns an error value, if returning Error, please select the most
* appropriate error condition from error_macros.h
*/
#define ERR_FAIL_COND_V(m_cond,m_retval) \
{ if ( m_cond ) { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' "_STR(m_cond)" ' is true. returned: "_STR(m_retval)); \
return m_retval; \
}else _err_error_exists=false; } \
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
* the loop will skip to the next iteration.
*/
#define ERR_CONTINUE(m_cond) \
{ if ( m_cond ) { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' "_STR(m_cond)" ' is true. Continuing..:"); \
continue;\
} else _err_error_exists=false;} \
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
* the loop will break
*/
#define ERR_BREAK(m_cond) \
{ if ( m_cond ) { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' "_STR(m_cond)" ' is true. Breaking..:"); \
break;\
} else _err_error_exists=false;} \
/** Print an error string and return
*/
#define ERR_FAIL() \
{ \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Method/Function Failed."); \
_err_error_exists=false;\
return;\
} \
/** Print an error string and return with value
*/
#define ERR_FAIL_V(m_value) \
{ \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Method/Function Failed, returning: "__STR(m_value)); \
_err_error_exists=false; \
return m_value;\
} \
/** Print an error string.
*/
#define ERR_PRINT(m_string) \
{ \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,m_string); \
_err_error_exists=false;\
} \
/** Print a warning string.
*/
#define WARN_PRINT(m_string) \
{ \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,m_string,ERR_HANDLER_WARNING); \
_err_error_exists=false;\
} \
#endif

153
core/event_queue.cpp Normal file
View file

@ -0,0 +1,153 @@
/*************************************************************************/
/* event_queue.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 "event_queue.h"
Error EventQueue::push_call(uint32_t p_instance_ID, const StringName& p_method, VARIANT_ARG_DECLARE) {
uint8_t room_needed=sizeof(Event);
int args=0;
if (p_arg5.get_type()!=Variant::NIL)
args=5;
else if (p_arg4.get_type()!=Variant::NIL)
args=4;
else if (p_arg3.get_type()!=Variant::NIL)
args=3;
else if (p_arg2.get_type()!=Variant::NIL)
args=2;
else if (p_arg1.get_type()!=Variant::NIL)
args=1;
else
args=0;
room_needed+=sizeof(Variant)*args;
ERR_FAIL_COND_V( (buffer_end+room_needed) >= buffer_size , ERR_OUT_OF_MEMORY );
Event * ev = memnew_placement( &event_buffer[ buffer_end ], Event );
ev->args=args;
ev->instance_ID=p_instance_ID;
ev->method=p_method;
buffer_end+=sizeof(Event);
if (args==1) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
buffer_end+=sizeof(Variant);
*v=p_arg1;
} else if (args==2) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
buffer_end+=sizeof(Variant);
*v=p_arg2;
} else if (args==3) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
buffer_end+=sizeof(Variant);
*v=p_arg3;
} else if (args==4) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
buffer_end+=sizeof(Variant);
*v=p_arg4;
} else if (args==5) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
buffer_end+=sizeof(Variant);
*v=p_arg5;
}
if (buffer_max_used>buffer_end);
buffer_max_used=buffer_end;
return OK;
}
void EventQueue::flush_events() {
uint32_t read_pos=0;
while (read_pos < buffer_end ) {
Event *event = (Event*)&event_buffer[ read_pos ];
Variant *args= (Variant*)(event+1);
Object *obj = ObjectDB::get_instance(event->instance_ID);
if (obj) {
// events don't expect a return value
obj->call( event->method,
(event->args>=1) ? args[0] : Variant(),
(event->args>=2) ? args[1] : Variant(),
(event->args>=3) ? args[2] : Variant(),
(event->args>=4) ? args[3] : Variant(),
(event->args>=5) ? args[4] : Variant() );
}
if (event->args>=1) args[0].~Variant();
if (event->args>=2) args[1].~Variant();
if (event->args>=3) args[2].~Variant();
if (event->args>=4) args[3].~Variant();
if (event->args>=5) args[4].~Variant();
event->~Event();
read_pos+=sizeof(Event)+sizeof(Variant)*event->args;
}
buffer_end=0; // reset buffer
}
EventQueue::EventQueue(uint32_t p_buffer_size) {
buffer_end=0;
buffer_max_used=0;
buffer_size=p_buffer_size;
event_buffer = memnew_arr( uint8_t, buffer_size );
}
EventQueue::~EventQueue() {
uint32_t read_pos=0;
while (read_pos < buffer_end ) {
Event *event = (Event*)&event_buffer[ read_pos ];
Variant *args= (Variant*)(event+1);
for (int i=0;i<event->args;i++)
args[i].~Variant();
event->~Event();
read_pos+=sizeof(Event)+sizeof(Variant)*event->args;
}
memdelete_arr(event_buffer);
event_buffer=NULL;
}

66
core/event_queue.h Normal file
View file

@ -0,0 +1,66 @@
/*************************************************************************/
/* event_queue.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef EVENT_QUEUE_H
#define EVENT_QUEUE_H
#include "object.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
class EventQueue {
enum {
DEFAULT_EVENT_QUEUE_SIZE_KB=256
};
struct Event {
uint32_t instance_ID;
StringName method;
int args;
};
uint8_t *event_buffer;
uint32_t buffer_end;
uint32_t buffer_max_used;
uint32_t buffer_size;
public:
Error push_call(uint32_t p_instance_ID, const StringName& p_method, VARIANT_ARG_LIST);
void flush_events();
EventQueue(uint32_t p_buffer_size=DEFAULT_EVENT_QUEUE_SIZE_KB*1024);
~EventQueue();
};
#endif

28
core/fpstr.cpp Normal file
View file

@ -0,0 +1,28 @@
/*************************************************************************/
/* fpstr.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. */
/*************************************************************************/

28
core/fpstr.h Normal file
View file

@ -0,0 +1,28 @@
/*************************************************************************/
/* fpstr.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/

516
core/global_constants.cpp Normal file
View file

@ -0,0 +1,516 @@
/*************************************************************************/
/* global_constants.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 "global_constants.h"
#include "variant.h"
#include "os/keyboard.h"
#include "object.h"
struct _GlobalConstant {
const char *name;
int value;
};
#define BIND_GLOBAL_CONSTANT(m_constant) {#m_constant,m_constant}
static _GlobalConstant _global_constants[]={
//{ KEY_BACKSPACE, VK_BACK },// (0x08) // backspace
BIND_GLOBAL_CONSTANT( MARGIN_LEFT ),
BIND_GLOBAL_CONSTANT( MARGIN_TOP ),
BIND_GLOBAL_CONSTANT( MARGIN_RIGHT ),
BIND_GLOBAL_CONSTANT( MARGIN_BOTTOM ),
BIND_GLOBAL_CONSTANT( VERTICAL ),
BIND_GLOBAL_CONSTANT( HORIZONTAL ),
BIND_GLOBAL_CONSTANT( HALIGN_LEFT ),
BIND_GLOBAL_CONSTANT( HALIGN_CENTER ),
BIND_GLOBAL_CONSTANT( HALIGN_RIGHT ),
BIND_GLOBAL_CONSTANT( VALIGN_TOP ),
BIND_GLOBAL_CONSTANT( VALIGN_CENTER ),
BIND_GLOBAL_CONSTANT( VALIGN_BOTTOM ),
// hueg list of keys
BIND_GLOBAL_CONSTANT( SPKEY ),
BIND_GLOBAL_CONSTANT( KEY_ESCAPE ),
BIND_GLOBAL_CONSTANT( KEY_TAB ),
BIND_GLOBAL_CONSTANT( KEY_BACKTAB ),
BIND_GLOBAL_CONSTANT( KEY_BACKSPACE ),
BIND_GLOBAL_CONSTANT( KEY_RETURN ),
BIND_GLOBAL_CONSTANT( KEY_ENTER ),
BIND_GLOBAL_CONSTANT( KEY_INSERT ),
BIND_GLOBAL_CONSTANT( KEY_DELETE ),
BIND_GLOBAL_CONSTANT( KEY_PAUSE ),
BIND_GLOBAL_CONSTANT( KEY_PRINT ),
BIND_GLOBAL_CONSTANT( KEY_SYSREQ ),
BIND_GLOBAL_CONSTANT( KEY_CLEAR ),
BIND_GLOBAL_CONSTANT( KEY_HOME ),
BIND_GLOBAL_CONSTANT( KEY_END ),
BIND_GLOBAL_CONSTANT( KEY_LEFT ),
BIND_GLOBAL_CONSTANT( KEY_UP ),
BIND_GLOBAL_CONSTANT( KEY_RIGHT ),
BIND_GLOBAL_CONSTANT( KEY_DOWN ),
BIND_GLOBAL_CONSTANT( KEY_PAGEUP ),
BIND_GLOBAL_CONSTANT( KEY_PAGEDOWN ),
BIND_GLOBAL_CONSTANT( KEY_SHIFT ),
BIND_GLOBAL_CONSTANT( KEY_CONTROL ),
BIND_GLOBAL_CONSTANT( KEY_META ),
BIND_GLOBAL_CONSTANT( KEY_ALT ),
BIND_GLOBAL_CONSTANT( KEY_CAPSLOCK ),
BIND_GLOBAL_CONSTANT( KEY_NUMLOCK ),
BIND_GLOBAL_CONSTANT( KEY_SCROLLLOCK ),
BIND_GLOBAL_CONSTANT( KEY_F1 ),
BIND_GLOBAL_CONSTANT( KEY_F2 ),
BIND_GLOBAL_CONSTANT( KEY_F3 ),
BIND_GLOBAL_CONSTANT( KEY_F4 ),
BIND_GLOBAL_CONSTANT( KEY_F5 ),
BIND_GLOBAL_CONSTANT( KEY_F6 ),
BIND_GLOBAL_CONSTANT( KEY_F7 ),
BIND_GLOBAL_CONSTANT( KEY_F8 ),
BIND_GLOBAL_CONSTANT( KEY_F9 ),
BIND_GLOBAL_CONSTANT( KEY_F10 ),
BIND_GLOBAL_CONSTANT( KEY_F11 ),
BIND_GLOBAL_CONSTANT( KEY_F12 ),
BIND_GLOBAL_CONSTANT( KEY_F13 ),
BIND_GLOBAL_CONSTANT( KEY_F14 ),
BIND_GLOBAL_CONSTANT( KEY_F15 ),
BIND_GLOBAL_CONSTANT( KEY_F16 ),
BIND_GLOBAL_CONSTANT( KEY_KP_ENTER ),
BIND_GLOBAL_CONSTANT( KEY_KP_MULTIPLY ),
BIND_GLOBAL_CONSTANT( KEY_KP_DIVIDE ),
BIND_GLOBAL_CONSTANT( KEY_KP_SUBSTRACT ),
BIND_GLOBAL_CONSTANT( KEY_KP_PERIOD ),
BIND_GLOBAL_CONSTANT( KEY_KP_ADD ),
BIND_GLOBAL_CONSTANT( KEY_KP_0 ),
BIND_GLOBAL_CONSTANT( KEY_KP_1 ),
BIND_GLOBAL_CONSTANT( KEY_KP_2 ),
BIND_GLOBAL_CONSTANT( KEY_KP_3 ),
BIND_GLOBAL_CONSTANT( KEY_KP_4 ),
BIND_GLOBAL_CONSTANT( KEY_KP_5 ),
BIND_GLOBAL_CONSTANT( KEY_KP_6 ),
BIND_GLOBAL_CONSTANT( KEY_KP_7 ),
BIND_GLOBAL_CONSTANT( KEY_KP_8 ),
BIND_GLOBAL_CONSTANT( KEY_KP_9 ),
BIND_GLOBAL_CONSTANT( KEY_SUPER_L ),
BIND_GLOBAL_CONSTANT( KEY_SUPER_R ),
BIND_GLOBAL_CONSTANT( KEY_MENU ),
BIND_GLOBAL_CONSTANT( KEY_HYPER_L ),
BIND_GLOBAL_CONSTANT( KEY_HYPER_R ),
BIND_GLOBAL_CONSTANT( KEY_HELP ),
BIND_GLOBAL_CONSTANT( KEY_DIRECTION_L ),
BIND_GLOBAL_CONSTANT( KEY_DIRECTION_R ),
BIND_GLOBAL_CONSTANT( KEY_BACK ),
BIND_GLOBAL_CONSTANT( KEY_FORWARD ),
BIND_GLOBAL_CONSTANT( KEY_STOP ),
BIND_GLOBAL_CONSTANT( KEY_REFRESH ),
BIND_GLOBAL_CONSTANT( KEY_VOLUMEDOWN ),
BIND_GLOBAL_CONSTANT( KEY_VOLUMEMUTE ),
BIND_GLOBAL_CONSTANT( KEY_VOLUMEUP ),
BIND_GLOBAL_CONSTANT( KEY_BASSBOOST ),
BIND_GLOBAL_CONSTANT( KEY_BASSUP ),
BIND_GLOBAL_CONSTANT( KEY_BASSDOWN ),
BIND_GLOBAL_CONSTANT( KEY_TREBLEUP ),
BIND_GLOBAL_CONSTANT( KEY_TREBLEDOWN ),
BIND_GLOBAL_CONSTANT( KEY_MEDIAPLAY ),
BIND_GLOBAL_CONSTANT( KEY_MEDIASTOP ),
BIND_GLOBAL_CONSTANT( KEY_MEDIAPREVIOUS ),
BIND_GLOBAL_CONSTANT( KEY_MEDIANEXT ),
BIND_GLOBAL_CONSTANT( KEY_MEDIARECORD ),
BIND_GLOBAL_CONSTANT( KEY_HOMEPAGE ),
BIND_GLOBAL_CONSTANT( KEY_FAVORITES ),
BIND_GLOBAL_CONSTANT( KEY_SEARCH ),
BIND_GLOBAL_CONSTANT( KEY_STANDBY ),
BIND_GLOBAL_CONSTANT( KEY_OPENURL ),
BIND_GLOBAL_CONSTANT( KEY_LAUNCHMAIL ),
BIND_GLOBAL_CONSTANT( KEY_LAUNCHMEDIA ),
BIND_GLOBAL_CONSTANT( KEY_LAUNCH0 ),
BIND_GLOBAL_CONSTANT( KEY_LAUNCH1 ),
BIND_GLOBAL_CONSTANT( KEY_LAUNCH2 ),
BIND_GLOBAL_CONSTANT( KEY_LAUNCH3 ),
BIND_GLOBAL_CONSTANT( KEY_LAUNCH4 ),
BIND_GLOBAL_CONSTANT( KEY_LAUNCH5 ),
BIND_GLOBAL_CONSTANT( KEY_LAUNCH6 ),
BIND_GLOBAL_CONSTANT( KEY_LAUNCH7 ),
BIND_GLOBAL_CONSTANT( KEY_LAUNCH8 ),
BIND_GLOBAL_CONSTANT( KEY_LAUNCH9 ),
BIND_GLOBAL_CONSTANT( KEY_LAUNCHA ),
BIND_GLOBAL_CONSTANT( KEY_LAUNCHB ),
BIND_GLOBAL_CONSTANT( KEY_LAUNCHC ),
BIND_GLOBAL_CONSTANT( KEY_LAUNCHD ),
BIND_GLOBAL_CONSTANT( KEY_LAUNCHE ),
BIND_GLOBAL_CONSTANT( KEY_LAUNCHF ),
BIND_GLOBAL_CONSTANT( KEY_UNKNOWN ),
BIND_GLOBAL_CONSTANT( KEY_SPACE ),
BIND_GLOBAL_CONSTANT( KEY_EXCLAM ),
BIND_GLOBAL_CONSTANT( KEY_QUOTEDBL ),
BIND_GLOBAL_CONSTANT( KEY_NUMBERSIGN ),
BIND_GLOBAL_CONSTANT( KEY_DOLLAR ),
BIND_GLOBAL_CONSTANT( KEY_PERCENT ),
BIND_GLOBAL_CONSTANT( KEY_AMPERSAND ),
BIND_GLOBAL_CONSTANT( KEY_APOSTROPHE ),
BIND_GLOBAL_CONSTANT( KEY_PARENLEFT ),
BIND_GLOBAL_CONSTANT( KEY_PARENRIGHT ),
BIND_GLOBAL_CONSTANT( KEY_ASTERISK ),
BIND_GLOBAL_CONSTANT( KEY_PLUS ),
BIND_GLOBAL_CONSTANT( KEY_COMMA ),
BIND_GLOBAL_CONSTANT( KEY_MINUS ),
BIND_GLOBAL_CONSTANT( KEY_PERIOD ),
BIND_GLOBAL_CONSTANT( KEY_SLASH ),
BIND_GLOBAL_CONSTANT( KEY_0 ),
BIND_GLOBAL_CONSTANT( KEY_1 ),
BIND_GLOBAL_CONSTANT( KEY_2 ),
BIND_GLOBAL_CONSTANT( KEY_3 ),
BIND_GLOBAL_CONSTANT( KEY_4 ),
BIND_GLOBAL_CONSTANT( KEY_5 ),
BIND_GLOBAL_CONSTANT( KEY_6 ),
BIND_GLOBAL_CONSTANT( KEY_7 ),
BIND_GLOBAL_CONSTANT( KEY_8 ),
BIND_GLOBAL_CONSTANT( KEY_9 ),
BIND_GLOBAL_CONSTANT( KEY_COLON ),
BIND_GLOBAL_CONSTANT( KEY_SEMICOLON ),
BIND_GLOBAL_CONSTANT( KEY_LESS ),
BIND_GLOBAL_CONSTANT( KEY_EQUAL ),
BIND_GLOBAL_CONSTANT( KEY_GREATER ),
BIND_GLOBAL_CONSTANT( KEY_QUESTION ),
BIND_GLOBAL_CONSTANT( KEY_AT ),
BIND_GLOBAL_CONSTANT( KEY_A ),
BIND_GLOBAL_CONSTANT( KEY_B ),
BIND_GLOBAL_CONSTANT( KEY_C ),
BIND_GLOBAL_CONSTANT( KEY_D ),
BIND_GLOBAL_CONSTANT( KEY_E ),
BIND_GLOBAL_CONSTANT( KEY_F ),
BIND_GLOBAL_CONSTANT( KEY_G ),
BIND_GLOBAL_CONSTANT( KEY_H ),
BIND_GLOBAL_CONSTANT( KEY_I ),
BIND_GLOBAL_CONSTANT( KEY_J ),
BIND_GLOBAL_CONSTANT( KEY_K ),
BIND_GLOBAL_CONSTANT( KEY_L ),
BIND_GLOBAL_CONSTANT( KEY_M ),
BIND_GLOBAL_CONSTANT( KEY_N ),
BIND_GLOBAL_CONSTANT( KEY_O ),
BIND_GLOBAL_CONSTANT( KEY_P ),
BIND_GLOBAL_CONSTANT( KEY_Q ),
BIND_GLOBAL_CONSTANT( KEY_R ),
BIND_GLOBAL_CONSTANT( KEY_S ),
BIND_GLOBAL_CONSTANT( KEY_T ),
BIND_GLOBAL_CONSTANT( KEY_U ),
BIND_GLOBAL_CONSTANT( KEY_V ),
BIND_GLOBAL_CONSTANT( KEY_W ),
BIND_GLOBAL_CONSTANT( KEY_X ),
BIND_GLOBAL_CONSTANT( KEY_Y ),
BIND_GLOBAL_CONSTANT( KEY_Z ),
BIND_GLOBAL_CONSTANT( KEY_BRACKETLEFT ),
BIND_GLOBAL_CONSTANT( KEY_BACKSLASH ),
BIND_GLOBAL_CONSTANT( KEY_BRACKETRIGHT ),
BIND_GLOBAL_CONSTANT( KEY_ASCIICIRCUM ),
BIND_GLOBAL_CONSTANT( KEY_UNDERSCORE ),
BIND_GLOBAL_CONSTANT( KEY_QUOTELEFT ),
BIND_GLOBAL_CONSTANT( KEY_BRACELEFT ),
BIND_GLOBAL_CONSTANT( KEY_BAR ),
BIND_GLOBAL_CONSTANT( KEY_BRACERIGHT ),
BIND_GLOBAL_CONSTANT( KEY_ASCIITILDE ),
BIND_GLOBAL_CONSTANT( KEY_NOBREAKSPACE ),
BIND_GLOBAL_CONSTANT( KEY_EXCLAMDOWN ),
BIND_GLOBAL_CONSTANT( KEY_CENT ),
BIND_GLOBAL_CONSTANT( KEY_STERLING ),
BIND_GLOBAL_CONSTANT( KEY_CURRENCY ),
BIND_GLOBAL_CONSTANT( KEY_YEN ),
BIND_GLOBAL_CONSTANT( KEY_BROKENBAR ),
BIND_GLOBAL_CONSTANT( KEY_SECTION ),
BIND_GLOBAL_CONSTANT( KEY_DIAERESIS ),
BIND_GLOBAL_CONSTANT( KEY_COPYRIGHT ),
BIND_GLOBAL_CONSTANT( KEY_ORDFEMININE ),
BIND_GLOBAL_CONSTANT( KEY_GUILLEMOTLEFT ),
BIND_GLOBAL_CONSTANT( KEY_NOTSIGN ),
BIND_GLOBAL_CONSTANT( KEY_HYPHEN ),
BIND_GLOBAL_CONSTANT( KEY_REGISTERED ),
BIND_GLOBAL_CONSTANT( KEY_MACRON ),
BIND_GLOBAL_CONSTANT( KEY_DEGREE ),
BIND_GLOBAL_CONSTANT( KEY_PLUSMINUS ),
BIND_GLOBAL_CONSTANT( KEY_TWOSUPERIOR ),
BIND_GLOBAL_CONSTANT( KEY_THREESUPERIOR ),
BIND_GLOBAL_CONSTANT( KEY_ACUTE ),
BIND_GLOBAL_CONSTANT( KEY_MU ),
BIND_GLOBAL_CONSTANT( KEY_PARAGRAPH ),
BIND_GLOBAL_CONSTANT( KEY_PERIODCENTERED ),
BIND_GLOBAL_CONSTANT( KEY_CEDILLA ),
BIND_GLOBAL_CONSTANT( KEY_ONESUPERIOR ),
BIND_GLOBAL_CONSTANT( KEY_MASCULINE ),
BIND_GLOBAL_CONSTANT( KEY_GUILLEMOTRIGHT ),
BIND_GLOBAL_CONSTANT( KEY_ONEQUARTER ),
BIND_GLOBAL_CONSTANT( KEY_ONEHALF ),
BIND_GLOBAL_CONSTANT( KEY_THREEQUARTERS ),
BIND_GLOBAL_CONSTANT( KEY_QUESTIONDOWN ),
BIND_GLOBAL_CONSTANT( KEY_AGRAVE ),
BIND_GLOBAL_CONSTANT( KEY_AACUTE ),
BIND_GLOBAL_CONSTANT( KEY_ACIRCUMFLEX ),
BIND_GLOBAL_CONSTANT( KEY_ATILDE ),
BIND_GLOBAL_CONSTANT( KEY_ADIAERESIS ),
BIND_GLOBAL_CONSTANT( KEY_ARING ),
BIND_GLOBAL_CONSTANT( KEY_AE ),
BIND_GLOBAL_CONSTANT( KEY_CCEDILLA ),
BIND_GLOBAL_CONSTANT( KEY_EGRAVE ),
BIND_GLOBAL_CONSTANT( KEY_EACUTE ),
BIND_GLOBAL_CONSTANT( KEY_ECIRCUMFLEX ),
BIND_GLOBAL_CONSTANT( KEY_EDIAERESIS ),
BIND_GLOBAL_CONSTANT( KEY_IGRAVE ),
BIND_GLOBAL_CONSTANT( KEY_IACUTE ),
BIND_GLOBAL_CONSTANT( KEY_ICIRCUMFLEX ),
BIND_GLOBAL_CONSTANT( KEY_IDIAERESIS ),
BIND_GLOBAL_CONSTANT( KEY_ETH ),
BIND_GLOBAL_CONSTANT( KEY_NTILDE ),
BIND_GLOBAL_CONSTANT( KEY_OGRAVE ),
BIND_GLOBAL_CONSTANT( KEY_OACUTE ),
BIND_GLOBAL_CONSTANT( KEY_OCIRCUMFLEX ),
BIND_GLOBAL_CONSTANT( KEY_OTILDE ),
BIND_GLOBAL_CONSTANT( KEY_ODIAERESIS ),
BIND_GLOBAL_CONSTANT( KEY_MULTIPLY ),
BIND_GLOBAL_CONSTANT( KEY_OOBLIQUE ),
BIND_GLOBAL_CONSTANT( KEY_UGRAVE ),
BIND_GLOBAL_CONSTANT( KEY_UACUTE ),
BIND_GLOBAL_CONSTANT( KEY_UCIRCUMFLEX ),
BIND_GLOBAL_CONSTANT( KEY_UDIAERESIS ),
BIND_GLOBAL_CONSTANT( KEY_YACUTE ),
BIND_GLOBAL_CONSTANT( KEY_THORN ),
BIND_GLOBAL_CONSTANT( KEY_SSHARP ),
BIND_GLOBAL_CONSTANT( KEY_DIVISION ),
BIND_GLOBAL_CONSTANT( KEY_YDIAERESIS ),
BIND_GLOBAL_CONSTANT( KEY_CODE_MASK ),
BIND_GLOBAL_CONSTANT( KEY_MODIFIER_MASK ),
BIND_GLOBAL_CONSTANT( KEY_MASK_SHIFT ),
BIND_GLOBAL_CONSTANT( KEY_MASK_ALT ),
BIND_GLOBAL_CONSTANT( KEY_MASK_META ),
BIND_GLOBAL_CONSTANT( KEY_MASK_CTRL ),
BIND_GLOBAL_CONSTANT( KEY_MASK_KPAD ),
BIND_GLOBAL_CONSTANT( KEY_MASK_GROUP_SWITCH ),
// joysticks
BIND_GLOBAL_CONSTANT( BUTTON_LEFT ),
BIND_GLOBAL_CONSTANT( BUTTON_RIGHT ),
BIND_GLOBAL_CONSTANT( BUTTON_MIDDLE ),
BIND_GLOBAL_CONSTANT( BUTTON_WHEEL_UP ),
BIND_GLOBAL_CONSTANT( BUTTON_WHEEL_DOWN ),
BIND_GLOBAL_CONSTANT( BUTTON_MASK_LEFT ),
BIND_GLOBAL_CONSTANT( BUTTON_MASK_RIGHT ),
BIND_GLOBAL_CONSTANT( BUTTON_MASK_MIDDLE ),
BIND_GLOBAL_CONSTANT( JOY_BUTTON_0 ),
BIND_GLOBAL_CONSTANT( JOY_BUTTON_1 ),
BIND_GLOBAL_CONSTANT( JOY_BUTTON_2 ),
BIND_GLOBAL_CONSTANT( JOY_BUTTON_3 ),
BIND_GLOBAL_CONSTANT( JOY_BUTTON_4 ),
BIND_GLOBAL_CONSTANT( JOY_BUTTON_5 ),
BIND_GLOBAL_CONSTANT( JOY_BUTTON_6 ),
BIND_GLOBAL_CONSTANT( JOY_BUTTON_7 ),
BIND_GLOBAL_CONSTANT( JOY_BUTTON_8 ),
BIND_GLOBAL_CONSTANT( JOY_BUTTON_9 ),
BIND_GLOBAL_CONSTANT( JOY_BUTTON_10 ),
BIND_GLOBAL_CONSTANT( JOY_BUTTON_11 ),
BIND_GLOBAL_CONSTANT( JOY_BUTTON_12 ),
BIND_GLOBAL_CONSTANT( JOY_BUTTON_13 ),
BIND_GLOBAL_CONSTANT( JOY_BUTTON_14 ),
BIND_GLOBAL_CONSTANT( JOY_BUTTON_15 ),
BIND_GLOBAL_CONSTANT( JOY_BUTTON_MAX ),
BIND_GLOBAL_CONSTANT( JOY_SNES_A ),
BIND_GLOBAL_CONSTANT( JOY_SNES_B ),
BIND_GLOBAL_CONSTANT( JOY_SNES_X ),
BIND_GLOBAL_CONSTANT( JOY_SNES_Y ),
BIND_GLOBAL_CONSTANT( JOY_SONY_CIRCLE ),
BIND_GLOBAL_CONSTANT( JOY_SONY_X ),
BIND_GLOBAL_CONSTANT( JOY_SONY_SQUARE ),
BIND_GLOBAL_CONSTANT( JOY_SONY_TRIANGLE ),
BIND_GLOBAL_CONSTANT( JOY_SEGA_B ),
BIND_GLOBAL_CONSTANT( JOY_SEGA_A ),
BIND_GLOBAL_CONSTANT( JOY_SEGA_X ),
BIND_GLOBAL_CONSTANT( JOY_SEGA_Y ),
BIND_GLOBAL_CONSTANT( JOY_XBOX_B ),
BIND_GLOBAL_CONSTANT( JOY_XBOX_A ),
BIND_GLOBAL_CONSTANT( JOY_XBOX_X ),
BIND_GLOBAL_CONSTANT( JOY_XBOX_Y ),
BIND_GLOBAL_CONSTANT( JOY_DS_A ),
BIND_GLOBAL_CONSTANT( JOY_DS_B ),
BIND_GLOBAL_CONSTANT( JOY_DS_X ),
BIND_GLOBAL_CONSTANT( JOY_DS_Y ),
BIND_GLOBAL_CONSTANT( JOY_SELECT ),
BIND_GLOBAL_CONSTANT( JOY_START ),
BIND_GLOBAL_CONSTANT( JOY_DPAD_UP ),
BIND_GLOBAL_CONSTANT( JOY_DPAD_DOWN ),
BIND_GLOBAL_CONSTANT( JOY_DPAD_LEFT ),
BIND_GLOBAL_CONSTANT( JOY_DPAD_RIGHT ),
BIND_GLOBAL_CONSTANT( JOY_L ),
BIND_GLOBAL_CONSTANT( JOY_L2 ),
BIND_GLOBAL_CONSTANT( JOY_L3 ),
BIND_GLOBAL_CONSTANT( JOY_R ),
BIND_GLOBAL_CONSTANT( JOY_R2 ),
BIND_GLOBAL_CONSTANT( JOY_R3 ),
BIND_GLOBAL_CONSTANT( JOY_AXIS_0 ),
BIND_GLOBAL_CONSTANT( JOY_AXIS_1 ),
BIND_GLOBAL_CONSTANT( JOY_AXIS_2 ),
BIND_GLOBAL_CONSTANT( JOY_AXIS_3 ),
BIND_GLOBAL_CONSTANT( JOY_AXIS_4 ),
BIND_GLOBAL_CONSTANT( JOY_AXIS_5 ),
BIND_GLOBAL_CONSTANT( JOY_AXIS_6 ),
BIND_GLOBAL_CONSTANT( JOY_AXIS_7 ),
BIND_GLOBAL_CONSTANT( JOY_AXIS_MAX ),
BIND_GLOBAL_CONSTANT( JOY_ANALOG_0_X ),
BIND_GLOBAL_CONSTANT( JOY_ANALOG_0_Y ),
BIND_GLOBAL_CONSTANT( JOY_ANALOG_1_X ),
BIND_GLOBAL_CONSTANT( JOY_ANALOG_1_Y ),
BIND_GLOBAL_CONSTANT( JOY_ANALOG_2_X ),
BIND_GLOBAL_CONSTANT( JOY_ANALOG_2_Y ),
// error list
BIND_GLOBAL_CONSTANT( OK ),
BIND_GLOBAL_CONSTANT( FAILED ), ///< Generic fail error
BIND_GLOBAL_CONSTANT( ERR_UNAVAILABLE ), ///< What is requested is unsupported/unavailable
BIND_GLOBAL_CONSTANT( ERR_UNCONFIGURED ), ///< The object being used hasnt been properly set up yet
BIND_GLOBAL_CONSTANT( ERR_UNAUTHORIZED ), ///< Missing credentials for requested resource
BIND_GLOBAL_CONSTANT( ERR_PARAMETER_RANGE_ERROR ), ///< Parameter given out of range
BIND_GLOBAL_CONSTANT( ERR_OUT_OF_MEMORY ), ///< Out of memory
BIND_GLOBAL_CONSTANT( ERR_FILE_NOT_FOUND ),
BIND_GLOBAL_CONSTANT( ERR_FILE_BAD_DRIVE ),
BIND_GLOBAL_CONSTANT( ERR_FILE_BAD_PATH ),
BIND_GLOBAL_CONSTANT( ERR_FILE_NO_PERMISSION ),
BIND_GLOBAL_CONSTANT( ERR_FILE_ALREADY_IN_USE ),
BIND_GLOBAL_CONSTANT( ERR_FILE_CANT_OPEN ),
BIND_GLOBAL_CONSTANT( ERR_FILE_CANT_WRITE ),
BIND_GLOBAL_CONSTANT( ERR_FILE_CANT_READ ),
BIND_GLOBAL_CONSTANT( ERR_FILE_UNRECOGNIZED ),
BIND_GLOBAL_CONSTANT( ERR_FILE_CORRUPT ),
BIND_GLOBAL_CONSTANT( ERR_FILE_EOF ),
BIND_GLOBAL_CONSTANT( ERR_CANT_OPEN ), ///< Can't open a resource/socket/file
BIND_GLOBAL_CONSTANT( ERR_CANT_CREATE ),
BIND_GLOBAL_CONSTANT( ERROR_QUERY_FAILED ),
BIND_GLOBAL_CONSTANT( ERR_ALREADY_IN_USE ),
BIND_GLOBAL_CONSTANT( ERR_LOCKED ), ///< resource is locked
BIND_GLOBAL_CONSTANT( ERR_TIMEOUT ),
BIND_GLOBAL_CONSTANT( ERR_CANT_AQUIRE_RESOURCE ),
BIND_GLOBAL_CONSTANT( ERR_INVALID_DATA ), ///< Data passed is invalid
BIND_GLOBAL_CONSTANT( ERR_INVALID_PARAMETER ), ///< Parameter passed is invalid
BIND_GLOBAL_CONSTANT( ERR_ALREADY_EXISTS ), ///< When adding ), item already exists
BIND_GLOBAL_CONSTANT( ERR_DOES_NOT_EXIST ), ///< When retrieving/erasing ), it item does not exist
BIND_GLOBAL_CONSTANT( ERR_DATABASE_CANT_READ ), ///< database is full
BIND_GLOBAL_CONSTANT( ERR_DATABASE_CANT_WRITE ), ///< database is full
BIND_GLOBAL_CONSTANT( ERR_COMPILATION_FAILED ),
BIND_GLOBAL_CONSTANT( ERR_METHOD_NOT_FOUND ),
BIND_GLOBAL_CONSTANT( ERR_LINK_FAILED ),
BIND_GLOBAL_CONSTANT( ERR_SCRIPT_FAILED ),
BIND_GLOBAL_CONSTANT( ERR_CYCLIC_LINK ),
BIND_GLOBAL_CONSTANT( ERR_BUSY ),
BIND_GLOBAL_CONSTANT( ERR_HELP ), ///< user requested help!!
BIND_GLOBAL_CONSTANT( ERR_BUG ), ///< a bug in the software certainly happened ), due to a double check failing or unexpected behavior.
BIND_GLOBAL_CONSTANT( ERR_WTF ),
BIND_GLOBAL_CONSTANT( PROPERTY_HINT_NONE ),
BIND_GLOBAL_CONSTANT( PROPERTY_HINT_RANGE ),
BIND_GLOBAL_CONSTANT( PROPERTY_HINT_EXP_RANGE ),
BIND_GLOBAL_CONSTANT( PROPERTY_HINT_ENUM ),
BIND_GLOBAL_CONSTANT( PROPERTY_HINT_LENGTH ),
BIND_GLOBAL_CONSTANT( PROPERTY_HINT_FLAGS ),
BIND_GLOBAL_CONSTANT( PROPERTY_HINT_FILE ),
BIND_GLOBAL_CONSTANT( PROPERTY_HINT_DIR ),
BIND_GLOBAL_CONSTANT( PROPERTY_HINT_RESOURCE_TYPE ),
BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_STORAGE ),
BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_STORAGE ),
BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_EDITOR ),
BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_NETWORK ),
BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_DEFAULT ),
{"TYPE_NIL",Variant::NIL},
{"TYPE_BOOL",Variant::BOOL},
{"TYPE_INT",Variant::INT},
{"TYPE_REAL",Variant::REAL},
{"TYPE_STRING",Variant::STRING},
{"TYPE_VECTOR2",Variant::VECTOR2}, // 5
{"TYPE_RECT2",Variant::RECT2},
{"TYPE_VECTOR3",Variant::VECTOR3},
{"TYPE_MATRIX32",Variant::MATRIX32},
{"TYPE_PLANE",Variant::PLANE},
{"TYPE_QUAT",Variant::QUAT}, // 10
{"TYPE_AABB",Variant::_AABB}, //sorry naming convention fail :( not like it's used often
{"TYPE_MATRIX3",Variant::MATRIX3},
{"TYPE_TRANSFORM",Variant::TRANSFORM},
{"TYPE_COLOR",Variant::COLOR},
{"TYPE_IMAGE",Variant::IMAGE}, // 15
{"TYPE_NODE_PATH",Variant::NODE_PATH},
{"TYPE_RID",Variant::_RID},
{"TYPE_OBJECT",Variant::OBJECT},
{"TYPE_INPUT_EVENT",Variant::INPUT_EVENT},
{"TYPE_DICTIONARY",Variant::DICTIONARY}, // 20
{"TYPE_ARRAY",Variant::ARRAY},
{"TYPE_RAW_ARRAY",Variant::RAW_ARRAY},
{"TYPE_INT_ARRAY",Variant::INT_ARRAY},
{"TYPE_REAL_ARRAY",Variant::REAL_ARRAY},
{"TYPE_STRING_ARRAY",Variant::STRING_ARRAY}, // 25
{"TYPE_VECTOR2_ARRAY",Variant::VECTOR2_ARRAY},
{"TYPE_VECTOR3_ARRAY",Variant::VECTOR3_ARRAY},
{"TYPE_COLOR_ARRAY",Variant::COLOR_ARRAY},
{"TYPE_MAX",Variant::VARIANT_MAX},
{NULL,0}
};
int GlobalConstants::get_global_constant_count() {
int i=0;
while(_global_constants[i].name)
i++;
return i;
}
const char *GlobalConstants::get_global_constant_name(int p_idx) {
return _global_constants[p_idx].name;
}
int GlobalConstants::get_global_constant_value(int p_idx) {
return _global_constants[p_idx].value;
}

41
core/global_constants.h Normal file
View file

@ -0,0 +1,41 @@
/*************************************************************************/
/* global_constants.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef GLOBAL_CONSTANTS_H
#define GLOBAL_CONSTANTS_H
class GlobalConstants {
public:
static int get_global_constant_count();
static const char *get_global_constant_name(int p_idx);
static int get_global_constant_value(int p_idx);
};
#endif // GLOBAL_CONSTANTS_H

1447
core/globals.cpp Normal file

File diff suppressed because it is too large Load diff

138
core/globals.h Normal file
View file

@ -0,0 +1,138 @@
/*************************************************************************/
/* globals.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef GLOBALS_H
#define GLOBALS_H
#include "object.h"
#include "set.h"
#include "os/thread_safe.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
class Globals : public Object {
OBJ_TYPE( Globals, Object );
_THREAD_SAFE_CLASS_
public:
typedef Map<String,Variant> CustomMap;
struct Singleton {
StringName name;
Object *ptr;
Singleton(const StringName& p_name=StringName(), Object *p_ptr=NULL) { name=p_name; ptr=p_ptr; }
};
protected:
struct VariantContainer {
int order;
bool persist;
Variant variant;
bool hide_from_editor;
bool overrided;
VariantContainer(){ order=0; hide_from_editor=false; persist=false; overrided=false; }
VariantContainer(const Variant& p_variant, int p_order, bool p_persist=false) { variant=p_variant; order=p_order; hide_from_editor=false; persist=p_persist; overrided=false; }
};
int last_order;
HashMap<String,VariantContainer> props;
String resource_path;
HashMap<String,PropertyInfo> custom_prop_info;
bool disable_platform_override;
bool _set(const StringName& p_name, const Variant& p_value);
bool _get(const StringName& p_name,Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
static Globals *singleton;
Error _load_settings(const String p_path);
Error _load_settings_binary(const String p_path);
Error _save_settings_text(const String& p_file,const Map<String,List<String> > &props,const CustomMap& p_custom=CustomMap());
Error _save_settings_binary(const String& p_file,const Map<String,List<String> > &props,const CustomMap& p_custom=CustomMap());
List<Singleton> singletons;
bool _load_resource_pack(const String& p_pack);
protected:
static void _bind_methods();
public:
bool has(String p_var) const;
String localize_path(const String& p_path) const;
String globalize_path(const String& p_path) const;
void set_persisting(const String& p_name, bool p_persist);
bool is_persisting(const String& p_name) const;
String get_resource_path() const;
static Globals *get_singleton();
void clear(const String& p_name);
int get_order(const String& p_name) const;
void set_order(const String& p_name, int p_order);
Error setup(const String& p_path);
Error save_custom(const String& p_path="",const CustomMap& p_custom=CustomMap(),const Set<String>& p_ignore_masks=Set<String>());
Error save();
void set_custom_property_info(const String& p_prop,const PropertyInfo& p_info);
void add_singleton(const Singleton &p_singleton);
void get_singletons(List<Singleton> *p_singletons);
bool has_singleton(const String& p_name) const;
Vector<String> get_optimizer_presets() const;
void set_disable_platform_override(bool p_disable);
Object* get_singleton_object(const String& p_name) const;
void register_global_defaults();
Globals();
~Globals();
};
//not a macro any longer
Variant _GLOBAL_DEF( const String& p_var, const Variant& p_default);
#define GLOBAL_DEF(m_var,m_value) _GLOBAL_DEF(m_var,m_value)
#endif

630
core/hash_map.h Normal file
View file

@ -0,0 +1,630 @@
/*************************************************************************/
/* hash_map.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef HASH_MAP_H
#define HASH_MAP_H
#include "hashfuncs.h"
#include "error_macros.h"
#include "ustring.h"
#include "os/memory.h"
#include "list.h"
class HashMapHahserDefault {
public:
static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); }
static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); }
static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) {
uint64_t v=p_int;
v = (~v) + (v << 18); // v = (v << 18) - v - 1;
v = v ^ (v >> 31);
v = v * 21; // v = (v + (v << 2)) + (v << 4);
v = v ^ (v >> 11);
v = v + (v << 6);
v = v ^ (v >> 22);
return (int) v;
}
static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash(uint64_t(p_int)); }
static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return p_int; }
static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return (uint32_t)p_int; }
static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return p_int; }
static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return (uint32_t)p_int; }
static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return p_int; }
static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return (uint32_t)p_int; }
static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return (uint32_t)p_wchar; }
// static _FORCE_INLINE_ uint32_t hash(const void* p_ptr) { return uint32_t(uint64_t(p_ptr))*(0x9e3779b1L); }
};
/**
* @class HashMap
* @author Juan Linietsky <reduzio@gmail.com>
*
* Implementation of a standard Hashing HashMap, for quick lookups of Data associated with a Key.
* The implementation provides hashers for the default types, if you need a special kind of hasher, provide
* your own.
* @param TKey Key, search is based on it, needs to be hasheable. It is unique in this container.
* @param TData Data, data associated with the key
* @param Hasher Hasher object, needs to provide a valid static hash function for TKey
* @param MIN_HASH_TABLE_POWER Miminum size of the hash table, as a power of two. You rarely need to change this parameter.
* @param RELATIONSHIP Relationship at which the hash table is resized. if amount of elements is RELATIONSHIP
* times bigger than the hash table, table is resized to solve this condition. if RELATIONSHIP is zero, table is always MIN_HASH_TABLE_POWER.
*
*/
template<class TKey, class TData, class Hasher=HashMapHahserDefault,uint8_t MIN_HASH_TABLE_POWER=3,uint8_t RELATIONSHIP=8>
class HashMap {
public:
struct Pair {
TKey key;
TData data;
Pair() {}
Pair(const TKey& p_key, const TData& p_data) { key=p_key; data=p_data; }
};
private:
struct Entry {
uint32_t hash;
Entry *next;
Pair pair;
Entry() { next=0; }
};
Entry **hash_table;
uint8_t hash_table_power;
uint32_t elements;
void make_hash_table() {
ERR_FAIL_COND( hash_table );
hash_table = memnew_arr( Entry*, (1<<MIN_HASH_TABLE_POWER) );
hash_table_power = MIN_HASH_TABLE_POWER;
elements=0;
for (int i=0;i<(1<<MIN_HASH_TABLE_POWER);i++)
hash_table[i]=0;
}
void erase_hash_table() {
ERR_FAIL_COND(elements);
memdelete_arr( hash_table );
hash_table=0;
hash_table_power=0;
elements=0;
}
void check_hash_table() {
int new_hash_table_power=-1;
if ((int)elements > ( (1<<hash_table_power) * RELATIONSHIP ) ) {
/* rehash up */
new_hash_table_power=hash_table_power+1;
while( (int)elements > ( (1<<new_hash_table_power) * RELATIONSHIP ) ) {
new_hash_table_power++;
}
} else if ( (hash_table_power>(int)MIN_HASH_TABLE_POWER) && ((int)elements < ( (1<<(hash_table_power-1)) * RELATIONSHIP ) ) ) {
/* rehash down */
new_hash_table_power=hash_table_power-1;
while( (int)elements < ( (1<<(new_hash_table_power-1)) * RELATIONSHIP ) ) {
new_hash_table_power--;
}
if (new_hash_table_power<(int)MIN_HASH_TABLE_POWER)
new_hash_table_power=MIN_HASH_TABLE_POWER;
}
if (new_hash_table_power==-1)
return;
Entry ** new_hash_table = memnew_arr( Entry*, (1<<new_hash_table_power) );
if (!new_hash_table) {
ERR_PRINT("Out of Memory");
return;
}
for (int i=0;i<(1<<new_hash_table_power);i++) {
new_hash_table[i]=0;
}
for (int i=0;i<(1<<hash_table_power);i++) {
while( hash_table[i] ) {
Entry *se=hash_table[i];
hash_table[i]=se->next;
int new_pos = se->hash & ((1<<new_hash_table_power)-1);
se->next=new_hash_table[new_pos];
new_hash_table[new_pos]=se;
}
}
if (hash_table)
memdelete_arr( hash_table );
hash_table=new_hash_table;
hash_table_power=new_hash_table_power;
}
/* I want to have only one function.. */
_FORCE_INLINE_ const Entry * get_entry( const TKey& p_key ) const {
uint32_t hash = Hasher::hash( p_key );
uint32_t index = hash&((1<<hash_table_power)-1);
Entry *e = hash_table[index];
while (e) {
/* checking hash first avoids comparing key, which may take longer */
if (e->hash == hash && e->pair.key == p_key ) {
/* the pair exists in this hashtable, so just update data */
return e;
}
e=e->next;
}
return NULL;
}
Entry * create_entry(const TKey& p_key) {
/* if entry doesn't exist, create it */
Entry *e = memnew( Entry );
ERR_FAIL_COND_V(!e,NULL); /* out of memory */
uint32_t hash = Hasher::hash( p_key );
uint32_t index = hash&((1<<hash_table_power)-1);
e->next = hash_table[index];
e->hash = hash;
e->pair.key=p_key;
hash_table[index]=e;
elements++;
return e;
}
void copy_from(const HashMap& p_t) {
if (&p_t==this)
return; /* much less bother with that */
clear();
if (!p_t.hash_table || p_t.hash_table_power==0)
return; /* not copying from empty table */
hash_table = memnew_arr(Entry*,1<<p_t.hash_table_power);
hash_table_power=p_t.hash_table_power;
elements=p_t.elements;
for (int i=0;i<( 1<<p_t.hash_table_power );i++) {
hash_table[i]=NULL;
/* elements will be in the reverse order, but it doesn't matter */
const Entry *e = p_t.hash_table[i];
while(e) {
Entry *le = memnew( Entry ); /* local entry */
*le=*e; /* copy data */
/* add to list and reassign pointers */
le->next=hash_table[i];
hash_table[i]=le;
e=e->next;
}
}
}
public:
void set( const TKey& p_key, const TData& p_data ) {
set( Pair( p_key, p_data ) );
}
void set( const Pair& p_pair ) {
if (!hash_table)
make_hash_table(); // if no table, make one
else
check_hash_table(); // perform mantenience routine
/* As said, i want to have only one get_entry */
Entry *e = const_cast<Entry*>( get_entry(p_pair.key) );
/* if we made it up to here, the pair doesn't exist, create and assign */
if (!e) {
e=create_entry(p_pair.key);
if (!e)
return;
}
e->pair.data = p_pair.data;
}
bool has( const TKey& p_key ) const {
return getptr(p_key)!=NULL;
}
/**
* Get a key from data, return a const reference.
* WARNING: this doesn't check errors, use either getptr and check NULL, or check
* first with has(key)
*/
const TData& get( const TKey& p_key ) const {
const TData* res = getptr(p_key);
ERR_FAIL_COND_V(!res,*res);
return *res;
}
TData& get( const TKey& p_key ) {
TData* res = getptr(p_key);
ERR_FAIL_COND_V(!res,*res);
return *res;
}
/**
* Same as get, except it can return NULL when item was not found.
* This is mainly used for speed purposes.
*/
_FORCE_INLINE_ TData* getptr( const TKey& p_key ) {
if (!hash_table)
return NULL;
Entry *e=const_cast<Entry*>(get_entry(p_key ));
if (e)
return &e->pair.data;
return NULL;
}
_FORCE_INLINE_ const TData* getptr( const TKey& p_key ) const {
if (!hash_table)
return NULL;
const Entry *e=const_cast<Entry*>(get_entry(p_key ));
if (e)
return &e->pair.data;
return NULL;
}
/**
* Same as get, except it can return NULL when item was not found.
* This version is custom, will take a hash and a custom key (that should support operator==()
*/
template<class C>
_FORCE_INLINE_ TData* custom_getptr( C p_custom_key,uint32_t p_custom_hash ) {
if (!hash_table)
return NULL;
uint32_t hash = p_custom_hash;
uint32_t index = hash&((1<<hash_table_power)-1);
Entry *e = hash_table[index];
while (e) {
/* checking hash first avoids comparing key, which may take longer */
if (e->hash == hash && e->pair.key == p_custom_key ) {
/* the pair exists in this hashtable, so just update data */
return &e->pair.data;
}
e=e->next;
}
return NULL;
}
template<class C>
_FORCE_INLINE_ const TData* custom_getptr( C p_custom_key,uint32_t p_custom_hash ) const {
if (!hash_table)
return NULL;
uint32_t hash = p_custom_hash;
uint32_t index = hash&((1<<hash_table_power)-1);
const Entry *e = hash_table[index];
while (e) {
/* checking hash first avoids comparing key, which may take longer */
if (e->hash == hash && e->pair.key == p_custom_key ) {
/* the pair exists in this hashtable, so just update data */
return &e->pair.data;
}
e=e->next;
}
return NULL;
}
/**
* Erase an item, return true if erasing was succesful
*/
bool erase( const TKey& p_key ) {
if (!hash_table)
return false;
uint32_t hash = Hasher::hash( p_key );
uint32_t index = hash&((1<<hash_table_power)-1);
Entry *e = hash_table[index];
Entry *p=NULL;
while (e) {
/* checking hash first avoids comparing key, which may take longer */
if (e->hash == hash && e->pair.key == p_key ) {
if (p) {
p->next=e->next;
} else {
//begin of list
hash_table[index]=e->next;
}
memdelete(e);
elements--;
if (elements==0)
erase_hash_table();
else
check_hash_table();
return true;
}
p=e;
e=e->next;
}
return false;
}
inline const TData& operator[](const TKey& p_key) const { //constref
return get(p_key);
}
inline TData& operator[](const TKey& p_key ) { //assignment
if (!hash_table)
make_hash_table(); // if no table, make one
else
check_hash_table(); // perform mantenience routine
Entry *e = const_cast<Entry*>( get_entry(p_key) );
/* if we made it up to here, the pair doesn't exist, create */
if (!e) {
e=create_entry(p_key);
if (!e)
return *(TData*)NULL; /* panic! */
}
return e->pair.data;
}
/**
* Get the next key to p_key, and the first key if p_key is null.
* Returns a pointer to the next key if found, NULL otherwise.
* Adding/Removing elements while iterating will, of course, have unexpected results, don't do it.
*
* Example:
*
* const TKey *k=NULL;
*
* while( (k=table.next(k)) ) {
*
* print( *k );
* }
*
*/
const TKey* next(const TKey* p_key) const {
if (!hash_table) return NULL;
if (!p_key) { /* get the first key */
for (int i=0;i<(1<<hash_table_power);i++) {
if (hash_table[i]) {
return &hash_table[i]->pair.key;
}
}
} else { /* get the next key */
const Entry *e = get_entry( *p_key );
ERR_FAIL_COND_V( !e, NULL ); /* invalid key supplied */
if (e->next) {
/* if there is a "next" in the list, return that */
return &e->next->pair.key;
} else {
/* go to next entries */
uint32_t index = e->hash&((1<<hash_table_power)-1);
index++;
for (int i=index;i<(1<<hash_table_power);i++) {
if (hash_table[i]) {
return &hash_table[i]->pair.key;
}
}
}
/* nothing found, was at end */
}
return NULL; /* nothing found */
}
inline unsigned int size() const {
return elements;
}
inline bool empty() const {
return elements==0;
}
void clear() {
/* clean up */
if (hash_table) {
for (int i=0;i<(1<<hash_table_power);i++) {
while (hash_table[i]) {
Entry *e=hash_table[i];
hash_table[i]=e->next;
memdelete( e );
}
}
memdelete_arr( hash_table );
}
hash_table=0;
hash_table_power=0;
elements=0;
}
void operator=(const HashMap& p_table) {
copy_from(p_table);
}
HashMap() {
hash_table=NULL;
elements=0;
hash_table_power=0;
}
void get_key_list(List<TKey> *p_keys) const {
if (!hash_table)
return;
for(int i=0;i<(1<<hash_table_power);i++) {
Entry *e=hash_table[i];
while(e) {
p_keys->push_back(e->pair.key);
e=e->next;
}
}
}
HashMap(const HashMap& p_table) {
hash_table=NULL;
elements=0;
hash_table_power=0;
copy_from(p_table);
}
~HashMap() {
clear();
}
};
#endif

116
core/hashfuncs.h Normal file
View file

@ -0,0 +1,116 @@
/*************************************************************************/
/* hashfuncs.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef HASHFUNCS_H
#define HASHFUNCS_H
#include "typedefs.h"
/**
* Hashing functions
*/
/**
* DJB2 Hash function
* @param C String
* @return 32-bits hashcode
*/
static inline uint32_t hash_djb2(const char *p_cstr) {
const unsigned char* chr=(const unsigned char*)p_cstr;
uint32_t hash = 5381;
uint32_t c;
while ((c = *chr++))
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
return hash;
}
static inline uint32_t hash_djb2_buffer(uint8_t *p_buff, int p_len) {
uint32_t hash = 5381;
for(int i=0;i<p_len;i++)
hash = ((hash << 5) + hash) + p_buff[i]; /* hash * 33 + c */
return hash;
}
static inline uint32_t hash_djb2_one_32(uint32_t p_in,uint32_t p_prev=5381) {
return ((p_prev<<5)+p_prev)+p_in;
}
static inline uint32_t hash_djb2_one_float(float p_in,uint32_t p_prev=5381) {
union {
float f;
uint32_t i;
} u;
u.f=p_in;
return ((p_prev<<5)+p_prev)+u.i;
}
template<class T>
static inline uint32_t make_uint32_t(T p_in) {
union {
T t;
uint32_t _u32;
} _u;
_u._u32=0;
_u.t=p_in;
return _u._u32;
}
static inline uint64_t hash_djb2_one_64(uint64_t p_in,uint64_t p_prev=5381) {
return ((p_prev<<5)+p_prev)+p_in;
}
template<class T>
static inline uint64_t make_uint64_t(T p_in) {
union {
T t;
uint64_t _u64;
} _u;
_u._u64=0; // in case p_in is smaller
_u.t=p_in;
return _u._u64;
}
#endif

1737
core/image.cpp Normal file

File diff suppressed because it is too large Load diff

336
core/image.h Normal file
View file

@ -0,0 +1,336 @@
/*************************************************************************/
/* image.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef IMAGE_H
#define IMAGE_H
#include "dvector.h"
#include "color.h"
#include "math_2d.h"
/**
* @author Juan Linietsky <reduzio@gmail.com>
*
* Image storage class. This is used to store an image in user memory, as well as
* providing some basic methods for image manipulation.
* Images can be loaded from a file, or registered into the Render object as textures.
*/
class Image {
enum {
MAX_WIDTH=4096, // force a limit somehow
MAX_HEIGHT=4096 // force a limit somehow
};
public:
enum Format {
FORMAT_GRAYSCALE, ///< one byte per pixel, 0-255
FORMAT_INTENSITY, ///< one byte per pixel, 0-255
FORMAT_GRAYSCALE_ALPHA, ///< two bytes per pixel, 0-255. alpha 0-255
FORMAT_RGB, ///< one byte R, one byte G, one byte B
FORMAT_RGBA, ///< one byte R, one byte G, one byte B, one byte A
FORMAT_INDEXED, ///< index byte 0-256, and after image end, 256*3 bytes of palette
FORMAT_INDEXED_ALPHA, ///< index byte 0-256, and after image end, 256*4 bytes of palette (alpha)
FORMAT_YUV_422,
FORMAT_YUV_444,
FORMAT_BC1, // DXT1
FORMAT_BC2, // DXT3
FORMAT_BC3, // DXT5
FORMAT_BC4, // ATI1
FORMAT_BC5, // ATI2
FORMAT_PVRTC2,
FORMAT_PVRTC2_ALPHA,
FORMAT_PVRTC4,
FORMAT_PVRTC4_ALPHA,
FORMAT_ETC, // regular ETC, no transparency
/*FORMAT_ETC2_R, for the future..
FORMAT_ETC2_RG,
FORMAT_ETC2_RGB,
FORMAT_ETC2_RGBA1,
FORMAT_ETC2_RGBA,*/
FORMAT_CUSTOM,
FORMAT_MAX
};
enum Interpolation {
INTERPOLATE_NEAREST,
INTERPOLATE_BILINEAR,
/* INTERPOLATE GAUSS */
};
static Image (*_png_mem_loader_func)(const uint8_t* p_png);
static void (*_image_compress_bc_func)(Image *);
static void (*_image_compress_pvrtc2_func)(Image *);
static void (*_image_compress_pvrtc4_func)(Image *);
static void (*_image_compress_etc_func)(Image *);
static void (*_image_decompress_pvrtc)(Image *);
static void (*_image_decompress_bc)(Image *);
static void (*_image_decompress_etc)(Image *);
static DVector<uint8_t> (*lossy_packer)(const Image& p_image,float p_quality);
static Image (*lossy_unpacker)(const DVector<uint8_t>& p_buffer);
static DVector<uint8_t> (*lossless_packer)(const Image& p_image);
static Image (*lossless_unpacker)(const DVector<uint8_t>& p_buffer);
private:
//internal byte based color
struct BColor {
union {
uint8_t col[4];
struct {
uint8_t r,g,b,a;
};
};
bool operator==(const BColor& p_color) const { for(int i=0;i<4;i++) {if (col[i]!=p_color.col[i]) return false; } return true; }
_FORCE_INLINE_ uint8_t gray() const { return (uint16_t(col[0])+uint16_t(col[1])+uint16_t(col[2]))/3; }
_FORCE_INLINE_ BColor() {}
BColor(uint8_t p_r,uint8_t p_g,uint8_t p_b,uint8_t p_a=255) { col[0]=p_r; col[1]=p_g; col[2]=p_b; col[3]=p_a; }
};
//median cut classes
struct BColorPos {
uint32_t index;
BColor color;
struct SortR {
bool operator()(const BColorPos& ca, const BColorPos& cb) const { return ca.color.r < cb.color.r; }
};
struct SortG {
bool operator()(const BColorPos& ca, const BColorPos& cb) const { return ca.color.g < cb.color.g; }
};
struct SortB {
bool operator()(const BColorPos& ca, const BColorPos& cb) const { return ca.color.b < cb.color.b; }
};
struct SortA {
bool operator()(const BColorPos& ca, const BColorPos& cb) const { return ca.color.a < cb.color.a; }
};
};
struct SPTree {
bool leaf;
uint8_t split_plane;
uint8_t split_value;
union {
int left;
int color;
};
int right;
SPTree() { leaf=true; left=-1; right=-1;}
};
struct MCBlock {
BColorPos min_color,max_color;
BColorPos *colors;
int sp_idx;
int color_count;
int get_longest_axis_index() const;
int get_longest_axis_length() const;
bool operator<(const MCBlock& p_block) const;
void shrink();
MCBlock();
MCBlock(BColorPos *p_colors,int p_color_count);
};
Format format;
DVector<uint8_t> data;
int width,height,mipmaps;
_FORCE_INLINE_ BColor _get_pixel(int p_x,int p_y,const unsigned char *p_data,int p_data_size) const;
_FORCE_INLINE_ BColor _get_pixelw(int p_x,int p_y,int p_width,const unsigned char *p_data,int p_data_size) const;
_FORCE_INLINE_ void _put_pixelw(int p_x,int p_y, int p_width, const BColor& p_color, unsigned char *p_data);
_FORCE_INLINE_ void _put_pixel(int p_x,int p_y, const BColor& p_color, unsigned char *p_data);
_FORCE_INLINE_ void _get_mipmap_offset_and_size(int p_mipmap,int &r_offset, int &r_width, int &r_height) const; //get where the mipmap begins in data
_FORCE_INLINE_ static void _get_format_min_data_size(Format p_format,int &r_w, int &r_h);
static int _get_dst_image_size(int p_width, int p_height, Format p_format,int &r_mipmaps,int p_mipmaps=-1);
bool _can_modify(Format p_format) const;
public:
int get_width() const; ///< Get image width
int get_height() const; ///< Get image height
int get_mipmaps() const;
/**
* Get a pixel from the image. for grayscale or indexed formats, use Color::gray to obtain the actual
* value.
*/
Color get_pixel(int p_x,int p_y,int p_mipmap=0) const;
/**
* Set a pixel into the image. for grayscale or indexed formats, a suitable Color constructor.
*/
void put_pixel(int p_x,int p_y, const Color& p_color,int p_mipmap=0); /* alpha and index are averaged */
/**
* Convert the image to another format, as close as it can be done.
*/
void convert( Format p_new_format );
/**
* Get the current image format.
*/
Format get_format() const;
int get_mipmap_offset(int p_mipmap) const; //get where the mipmap begins in data
void get_mipmap_offset_and_size(int p_mipmap,int &r_ofs, int &r_size) const; //get where the mipmap begins in data
/**
* Resize the image, using the prefered interpolation method.
* Indexed-Color images always use INTERPOLATE_NEAREST.
*/
void resize_to_po2(bool p_square=false);
void resize( int p_width, int p_height, Interpolation p_interpolation=INTERPOLATE_BILINEAR );
Image resized( int p_width, int p_height, int p_interpolation=INTERPOLATE_BILINEAR );
/**
* Crop the image to a specific size, if larger, then the image is filled by black
*/
void crop( int p_width, int p_height );
void flip_x();
void flip_y();
/**
* Generate a mipmap to an image (creates an image 1/4 the size, with averaging of 4->1)
*/
Error generate_mipmaps(int p_amount=-1,bool p_keep_existing=false);
void clear_mipmaps();
/**
* Generate a normal map from a grayscale image
*/
void make_normalmap(float p_height_scale=1.0);
/**
* Create a new image of a given size and format. Current image will be lost
*/
void create(int p_width, int p_height, bool p_use_mipmaps, Format p_format);
void create(int p_width, int p_height, int p_mipmaps, Format p_format, const DVector<uint8_t>& p_data);
void create( const char ** p_xpm );
/**
* returns true when the image is empty (0,0) in size
*/
bool empty() const;
DVector<uint8_t> get_data() const;
Error load(const String& p_path);
/**
* create an empty image
*/
Image();
/**
* create an empty image of a specific size and format
*/
Image(int p_width, int p_height, bool p_use_mipmaps, Format p_format);
/**
* import an image of a specific size and format from a pointer
*/
Image(int p_width, int p_height, int p_mipmaps, Format p_format, const DVector<uint8_t>& p_data);
enum AlphaMode {
ALPHA_NONE,
ALPHA_BIT,
ALPHA_BLEND
};
AlphaMode detect_alpha() const;
void put_indexed_pixel(int p_x, int p_y, uint8_t p_idx,int p_mipmap=0);
uint8_t get_indexed_pixel(int p_x, int p_y,int p_mipmap=0) const;
void set_pallete(const DVector<uint8_t>& p_data);
static int get_format_pixel_size(Format p_format);
static int get_format_pixel_rshift(Format p_format);
static int get_format_pallete_size(Format p_format);
static int get_image_data_size(int p_width, int p_height, Format p_format,int p_mipmaps=0);
static int get_image_required_mipmaps(int p_width, int p_height, Format p_format);
bool operator==(const Image& p_image) const;
void quantize();
enum CompressMode {
COMPRESS_BC,
COMPRESS_PVRTC2,
COMPRESS_PVRTC4,
COMPRESS_ETC
};
Error compress(CompressMode p_mode=COMPRESS_BC);
Image compressed(int p_mode); /* from the Image::CompressMode enum */
void decompress();
void fix_alpha_edges();
void blit_rect(const Image& p_src, const Rect2& p_src_rect,const Point2& p_dest);
void brush_transfer(const Image& p_src, const Image& p_brush, const Point2& p_dest);
Image brushed(const Image& p_src, const Image& p_brush, const Point2& p_dest) const;
Rect2 get_used_rect() const;
Image get_rect(const Rect2& p_area) const;
static void set_compress_bc_func(void (*p_compress_func)(Image *));
Image(const uint8_t* p_mem_png);
Image(const char **p_xpm);
~Image();
};
#endif

370
core/image_quantize.cpp Normal file
View file

@ -0,0 +1,370 @@
/*************************************************************************/
/* image_quantize.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 "image.h"
#include <stdio.h>
#include "print_string.h"
#ifdef TOOLS_ENABLED
#include "set.h"
#include "sort.h"
#include "os/os.h"
//#define QUANTIZE_SPEED_OVER_QUALITY
Image::MCBlock::MCBlock() {
}
Image::MCBlock::MCBlock(BColorPos *p_colors,int p_color_count) {
colors=p_colors;
color_count=p_color_count;
min_color.color=BColor(255,255,255,255);
max_color.color=BColor(0,0,0,0);
shrink();
}
int Image::MCBlock::get_longest_axis_index() const {
int max_dist=-1;
int max_index=0;
for(int i=0;i<4;i++) {
int d = max_color.color.col[i]-min_color.color.col[i];
//printf(" ai:%i - %i\n",i,d);
if (d>max_dist) {
max_index=i;
max_dist=d;
}
}
return max_index;
}
int Image::MCBlock::get_longest_axis_length() const {
int max_dist=-1;
int max_index=0;
for(int i=0;i<4;i++) {
int d = max_color.color.col[i]-min_color.color.col[i];
if (d>max_dist) {
max_index=i;
max_dist=d;
}
}
return max_dist;
}
bool Image::MCBlock::operator<(const MCBlock& p_block) const {
int alen = get_longest_axis_length();
int blen = p_block.get_longest_axis_length();
if (alen==blen) {
return colors < p_block.colors;
} else
return alen < blen;
}
void Image::MCBlock::shrink() {
min_color=colors[0];
max_color=colors[0];
for(int i=1;i<color_count;i++) {
for(int j=0;j<4;j++) {
min_color.color.col[j]=MIN(min_color.color.col[j],colors[i].color.col[j]);
max_color.color.col[j]=MAX(max_color.color.col[j],colors[i].color.col[j]);
}
}
}
void Image::quantize() {
Image::Format orig_format=format;
bool has_alpha = detect_alpha()!=ALPHA_NONE;
bool quantize_fast=OS::get_singleton()->has_environment("QUANTIZE_FAST");
convert(FORMAT_RGBA);
ERR_FAIL_COND( format!=FORMAT_RGBA );
DVector<uint8_t> indexed_data;
{
int color_count = data.size()/4;
ERR_FAIL_COND(color_count==0);
Set<MCBlock> block_queue;
DVector<BColorPos> data_colors;
data_colors.resize(color_count);
DVector<BColorPos>::Write dcw=data_colors.write();
DVector<uint8_t>::Read dr = data.read();
const BColor * drptr=(const BColor*)&dr[0];
BColorPos *bcptr=&dcw[0];
{
for(int i=0;i<color_count;i++) {
//uint32_t data_ofs=i<<2;
bcptr[i].color=drptr[i];//BColor(drptr[data_ofs+0],drptr[data_ofs+1],drptr[data_ofs+2],drptr[data_ofs+3]);
bcptr[i].index=i;
}
}
//printf("color count: %i\n",color_count);
/*
for(int i=0;i<color_count;i++) {
BColor bc = ((BColor*)&wb[0])[i];
printf("%i - %i,%i,%i,%i\n",i,bc.r,bc.g,bc.b,bc.a);
}*/
MCBlock initial_block((BColorPos*)&dcw[0],color_count);
block_queue.insert(initial_block);
while( block_queue.size() < 256 && block_queue.back()->get().color_count > 1 ) {
MCBlock longest = block_queue.back()->get();
//printf("longest: %i (%i)\n",longest.get_longest_axis_index(),longest.get_longest_axis_length());
block_queue.erase(block_queue.back());
BColorPos *first = longest.colors;
BColorPos *median = longest.colors + (longest.color_count+1)/2;
BColorPos *end = longest.colors + longest.color_count;
#if 0
int lai =longest.get_longest_axis_index();
switch(lai) {
#if 0
case 0: { SortArray<BColorPos,BColorPos::SortR> sort; sort.sort(first,end-first); } break;
case 1: { SortArray<BColorPos,BColorPos::SortG> sort; sort.sort(first,end-first); } break;
case 2: { SortArray<BColorPos,BColorPos::SortB> sort; sort.sort(first,end-first); } break;
case 3: { SortArray<BColorPos,BColorPos::SortA> sort; sort.sort(first,end-first); } break;
#else
case 0: { SortArray<BColorPos,BColorPos::SortR> sort; sort.nth_element(0,end-first,median-first,first); } break;
case 1: { SortArray<BColorPos,BColorPos::SortG> sort; sort.nth_element(0,end-first,median-first,first); } break;
case 2: { SortArray<BColorPos,BColorPos::SortB> sort; sort.nth_element(0,end-first,median-first,first); } break;
case 3: { SortArray<BColorPos,BColorPos::SortA> sort; sort.nth_element(0,end-first,median-first,first); } break;
#endif
}
//avoid same color from being split in 2
//search forward and flip
BColorPos *median_end=median;
BColorPos *p=median_end+1;
while(p!=end) {
if (median_end->color==p->color) {
SWAP(*(median_end+1),*p);
median_end++;
}
p++;
}
//search backward and flip
BColorPos *median_begin=median;
p=median_begin-1;
while(p!=(first-1)) {
if (median_begin->color==p->color) {
SWAP(*(median_begin-1),*p);
median_begin--;
}
p--;
}
if (first < median_begin) {
median=median_begin;
} else if (median_end < end-1) {
median=median_end+1;
} else {
break; //shouldn't have arrived here, since it means all pixels are equal, but wathever
}
MCBlock left(first,median-first);
MCBlock right(median,end-median);
block_queue.insert(left);
block_queue.insert(right);
#else
switch(longest.get_longest_axis_index()) {
case 0: { SortArray<BColorPos,BColorPos::SortR> sort; sort.nth_element(0,end-first,median-first,first); } break;
case 1: { SortArray<BColorPos,BColorPos::SortG> sort; sort.nth_element(0,end-first,median-first,first); } break;
case 2: { SortArray<BColorPos,BColorPos::SortB> sort; sort.nth_element(0,end-first,median-first,first); } break;
case 3: { SortArray<BColorPos,BColorPos::SortA> sort; sort.nth_element(0,end-first,median-first,first); } break;
}
MCBlock left(first,median-first);
MCBlock right(median,end-median);
block_queue.insert(left);
block_queue.insert(right);
#endif
}
while(block_queue.size() > 256) {
block_queue.erase(block_queue.front());// erase least significant
}
int res_colors=0;
int comp_size = (has_alpha?4:3);
indexed_data.resize(color_count + 256*comp_size);
DVector<uint8_t>::Write iw = indexed_data.write();
uint8_t *iwptr=&iw[0];
BColor pallete[256];
// print_line("applying quantization - res colors "+itos(block_queue.size()));
while(block_queue.size()) {
const MCBlock &b = block_queue.back()->get();
uint64_t sum[4]={0,0,0,0};
for(int i=0;i<b.color_count;i++) {
sum[0]+=b.colors[i].color.col[0];
sum[1]+=b.colors[i].color.col[1];
sum[2]+=b.colors[i].color.col[2];
sum[3]+=b.colors[i].color.col[3];
}
BColor c( sum[0]/b.color_count, sum[1]/b.color_count, sum[2]/b.color_count, sum[3]/b.color_count );
//printf(" %i: %i,%i,%i,%i out of %i\n",res_colors,c.r,c.g,c.b,c.a,b.color_count);
for(int i=0;i<comp_size;i++) {
iwptr[ color_count + res_colors * comp_size + i ] = c.col[i];
}
if (quantize_fast) {
for(int i=0;i<b.color_count;i++) {
iwptr[b.colors[i].index]=res_colors;
}
} else {
pallete[res_colors]=c;
}
res_colors++;
block_queue.erase(block_queue.back());
}
if (!quantize_fast) {
for(int i=0;i<color_count;i++) {
const BColor &c=drptr[i];
uint8_t best_dist_idx=0;
uint32_t dist=0xFFFFFFFF;
for(int j=0;j<res_colors;j++) {
const BColor &pc=pallete[j];
uint32_t d = 0;
{ int16_t v = (int16_t)c.r-(int16_t)pc.r; d+=v*v; }
{ int16_t v = (int16_t)c.g-(int16_t)pc.g; d+=v*v; }
{ int16_t v = (int16_t)c.b-(int16_t)pc.b; d+=v*v; }
{ int16_t v = (int16_t)c.a-(int16_t)pc.a; d+=v*v; }
if (d<=dist) {
best_dist_idx=j;
dist=d;
}
}
iwptr[ i ] = best_dist_idx;
}
}
//iw = DVector<uint8_t>::Write();
//dr = DVector<uint8_t>::Read();
//wb = DVector<uint8_t>::Write();
}
print_line(itos(indexed_data.size()));
data=indexed_data;
format=has_alpha?FORMAT_INDEXED_ALPHA:FORMAT_INDEXED;
} //do none
#else
void Image::quantize() {} //do none
#endif

209
core/input_map.cpp Normal file
View file

@ -0,0 +1,209 @@
/*************************************************************************/
/* input_map.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 "input_map.h"
#include "globals.h"
InputMap *InputMap::singleton=NULL;
void InputMap::add_action(const StringName& p_action) {
ERR_FAIL_COND( input_map.has(p_action) );
input_map[p_action]=Action();
static int last_id=1;
input_map[p_action].id=last_id;
input_id_map[last_id]=p_action;
last_id++;
}
void InputMap::erase_action(const StringName& p_action) {
ERR_FAIL_COND( !input_map.has(p_action) );
input_id_map.erase(input_map[p_action].id);
input_map.erase(p_action);
}
StringName InputMap::get_action_from_id(int p_id) const {
ERR_FAIL_COND_V(!input_id_map.has(p_id),StringName());
return input_id_map[p_id];
}
List<InputEvent>::Element *InputMap::_find_event(List<InputEvent> &p_list,const InputEvent& p_event) const {
for (List<InputEvent>::Element *E=p_list.front();E;E=E->next()) {
const InputEvent& e=E->get();
if(e.type!=p_event.type)
continue;
if (e.type!=InputEvent::KEY && e.device!=p_event.device)
continue;
bool same=false;
switch(p_event.type) {
case InputEvent::KEY: {
same=(e.key.scancode==p_event.key.scancode && e.key.mod == p_event.key.mod);
} break;
case InputEvent::JOYSTICK_BUTTON: {
same=(e.joy_button.button_index==p_event.joy_button.button_index);
} break;
case InputEvent::MOUSE_BUTTON: {
same=(e.mouse_button.button_index==p_event.mouse_button.button_index);
} break;
case InputEvent::JOYSTICK_MOTION: {
same=(e.joy_motion.axis==p_event.joy_motion.axis);
} break;
}
if (same)
return E;
}
return NULL;
}
bool InputMap::has_action(const StringName& p_action) const {
return input_map.has(p_action);
}
void InputMap::action_add_event(const StringName& p_action,const InputEvent& p_event) {
ERR_FAIL_COND(p_event.type==InputEvent::ACTION);
ERR_FAIL_COND( !input_map.has(p_action) );
if (_find_event(input_map[p_action].inputs,p_event))
return; //already gots
input_map[p_action].inputs.push_back(p_event);
}
int InputMap::get_action_id(const StringName& p_action) const {
ERR_FAIL_COND_V(!input_map.has(p_action),-1);
return input_map[p_action].id;
}
bool InputMap::action_has_event(const StringName& p_action,const InputEvent& p_event) {
ERR_FAIL_COND_V( !input_map.has(p_action), false );
return (_find_event(input_map[p_action].inputs,p_event)!=NULL);
}
void InputMap::action_erase_event(const StringName& p_action,const InputEvent& p_event) {
ERR_FAIL_COND( !input_map.has(p_action) );
List<InputEvent>::Element *E=_find_event(input_map[p_action].inputs,p_event);
if (E)
return; //already gots
input_map[p_action].inputs.erase(E);
}
const List<InputEvent> *InputMap::get_action_list(const StringName& p_action) {
const Map<StringName, Action>::Element *E=input_map.find(p_action);
if (!E)
return NULL;
return &E->get().inputs;
}
bool InputMap::event_is_action(const InputEvent& p_event, const StringName& p_action) const {
Map<StringName,Action >::Element *E=input_map.find(p_action);
if(!E) {
ERR_EXPLAIN("Request for unexisting InputMap action: "+String(p_action));
ERR_FAIL_COND_V(!E,false);
}
if (p_event.type==InputEvent::ACTION) {
return p_event.action.action==E->get().id;
}
return _find_event(E->get().inputs,p_event)!=NULL;
}
void InputMap::load_from_globals() {
input_map.clear();;
List<PropertyInfo> pinfo;
Globals::get_singleton()->get_property_list(&pinfo);
for(List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
const PropertyInfo &pi=E->get();
if (!pi.name.begins_with("input/"))
continue;
String name = pi.name.substr(pi.name.find("/")+1,pi.name.length());
add_action(name);
Array va = Globals::get_singleton()->get(pi.name);;
for(int i=0;i<va.size();i++) {
InputEvent ie=va[i];
if (ie.type==InputEvent::NONE)
continue;
action_add_event(name,ie);
}
}
}
InputMap::InputMap() {
ERR_FAIL_COND(singleton);
singleton=this;
}

73
core/input_map.h Normal file
View file

@ -0,0 +1,73 @@
/*************************************************************************/
/* input_map.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef INPUT_MAP_H
#define INPUT_MAP_H
#include "object.h"
class InputMap : public Object {
OBJ_TYPE( InputMap, Object );
static InputMap *singleton;
struct Action {
int id;
List<InputEvent> inputs;
};
mutable Map<StringName, Action> input_map;
mutable Map<int,StringName> input_id_map;
List<InputEvent>::Element *_find_event(List<InputEvent> &p_list,const InputEvent& p_event) const;
public:
static _FORCE_INLINE_ InputMap *get_singleton() { return singleton; }
bool has_action(const StringName& p_action) const;
int get_action_id(const StringName& p_action) const;
StringName get_action_from_id(int p_id) const;
void add_action(const StringName& p_action);
void erase_action(const StringName& p_action);
void action_add_event(const StringName& p_action,const InputEvent& p_event);
bool action_has_event(const StringName& p_action,const InputEvent& p_event);
void action_erase_event(const StringName& p_action,const InputEvent& p_event);
const List<InputEvent> *get_action_list(const StringName& p_action);
bool event_is_action(const InputEvent& p_event, const StringName& p_action) const;
void load_from_globals();
InputMap();
};
#endif // INPUT_MAP_H

56
core/int_types.h Normal file
View file

@ -0,0 +1,56 @@
/*************************************************************************/
/* int_types.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifdef _MSC_VER
typedef signed __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef signed __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef signed __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else
#ifdef NO_STDINT_H
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef unsigned short uint16_t;
typedef signed short int16_t;
typedef unsigned int uint32_t;
typedef signed int int32_t;
typedef long long int64_t;
typedef unsigned long long int64_t;
#else
#include <stdint.h>
#endif
#endif

9
core/io/SCsub Normal file
View file

@ -0,0 +1,9 @@
Import('env')
env.add_source_files(env.core_sources,"*.cpp")
env.add_source_files(env.core_sources,"*.c")
#env.core_sources.append("io/fastlz.c")
Export('env')

110
core/io/base64.c Normal file
View file

@ -0,0 +1,110 @@
#include <string.h>
char b64string[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
long base64_encode (to, from, len)
char *to, *from;
unsigned int len;
{
char *fromp = from;
char *top = to;
unsigned char cbyte;
unsigned char obyte;
char end[3];
for (; len >= 3; len -= 3) {
cbyte = *fromp++;
*top++ = b64string[(int)(cbyte >> 2)];
obyte = (cbyte << 4) & 0x30; /* 0011 0000 */
cbyte = *fromp++;
obyte |= (cbyte >> 4); /* 0000 1111 */
*top++ = b64string[(int)obyte];
obyte = (cbyte << 2) & 0x3C; /* 0011 1100 */
cbyte = *fromp++;
obyte |= (cbyte >> 6); /* 0000 0011 */
*top++ = b64string[(int)obyte];
*top++ = b64string[(int)(cbyte & 0x3F)];/* 0011 1111 */
}
if (len) {
end[0] = *fromp++;
if (--len) end[1] = *fromp++; else end[1] = 0;
end[2] = 0;
cbyte = end[0];
*top++ = b64string[(int)(cbyte >> 2)];
obyte = (cbyte << 4) & 0x30; /* 0011 0000 */
cbyte = end[1];
obyte |= (cbyte >> 4);
*top++ = b64string[(int)obyte];
obyte = (cbyte << 2) & 0x3C; /* 0011 1100 */
if (len) *top++ = b64string[(int)obyte];
else *top++ = '=';
*top++ = '=';
}
*top = 0;
return top - to;
}
/* badchar(): check if c is decent; puts either the */
/* location of c or null into p. */
#define badchar(c,p) (!(p = memchr(b64string, c, 64)))
long base64_decode (to, from, len)
char *to, *from;
unsigned int len;
{
char *fromp = from;
char *top = to;
char *p;
unsigned char cbyte;
unsigned char obyte;
int padding = 0;
for (; len >= 4; len -= 4) {
if ((cbyte = *fromp++) == '=') cbyte = 0;
else {
if (badchar(cbyte, p)) return -1;
cbyte = (p - b64string);
}
obyte = cbyte << 2; /* 1111 1100 */
if ((cbyte = *fromp++) == '=') cbyte = 0;
else {
if (badchar(cbyte, p)) return -1;
cbyte = p - b64string;
}
obyte |= cbyte >> 4; /* 0000 0011 */
*top++ = obyte;
obyte = cbyte << 4; /* 1111 0000 */
if ((cbyte = *fromp++) == '=') { cbyte = 0; padding++; }
else {
padding = 0;
if (badchar (cbyte, p)) return -1;
cbyte = p - b64string;
}
obyte |= cbyte >> 2; /* 0000 1111 */
*top++ = obyte;
obyte = cbyte << 6; /* 1100 0000 */
if ((cbyte = *fromp++) == '=') { cbyte = 0; padding++; }
else {
padding = 0;
if (badchar (cbyte, p)) return -1;
cbyte = p - b64string;
}
obyte |= cbyte; /* 0011 1111 */
*top++ = obyte;
}
*top = 0;
if (len) return -1;
return (top - to) - padding;
}

11
core/io/base64.h Normal file
View file

@ -0,0 +1,11 @@
#ifndef BASE64_H
#define BASE64_H
extern "C" {
uint32_t base64_encode (char* to, char* from, uint32_t len);
uint32_t base64_decode (char* to, char* from, uint32_t len);
};
#endif /* BASE64_H */

91
core/io/compression.cpp Normal file
View file

@ -0,0 +1,91 @@
/*************************************************************************/
/* compression.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 "compression.h"
#include "fastlz.h"
#include "os/copymem.h"
int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size,Mode p_mode) {
switch(p_mode) {
case MODE_FASTLZ: {
if (p_src_size<16) {
uint8_t src[16];
zeromem(&src[p_src_size],16-p_src_size);
copymem(src,p_src,p_src_size);
return fastlz_compress(src,16,p_dst);
} else {
return fastlz_compress(p_src,p_src_size,p_dst);
}
} break;
}
ERR_FAIL_V(-1);
}
int Compression::get_max_compressed_buffer_size(int p_src_size,Mode p_mode){
switch(p_mode) {
case MODE_FASTLZ: {
int ss = p_src_size+p_src_size*6/100;
if (ss<66)
ss=66;
return ss;
} break;
}
ERR_FAIL_V(-1);
}
void Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size,Mode p_mode){
switch(p_mode) {
case MODE_FASTLZ: {
if (p_dst_max_size<16) {
uint8_t dst[16];
fastlz_decompress(p_src,p_src_size,dst,16);
copymem(p_dst,dst,p_dst_max_size);
} else {
fastlz_decompress(p_src,p_src_size,p_dst,p_dst_max_size);
}
return;
} break;
}
ERR_FAIL();
}

53
core/io/compression.h Normal file
View file

@ -0,0 +1,53 @@
/*************************************************************************/
/* compression.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef COMPRESSION_H
#define COMPRESSION_H
#include "typedefs.h"
class Compression
{
public:
enum Mode {
MODE_FASTLZ,
MODE_DEFLATE
};
static int compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size,Mode p_mode=MODE_FASTLZ);
static int get_max_compressed_buffer_size(int p_src_size,Mode p_mode=MODE_FASTLZ);
static void decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size,Mode p_mode=MODE_FASTLZ);
Compression();
};
#endif // COMPRESSION_H

744
core/io/config_file.cpp Normal file
View file

@ -0,0 +1,744 @@
/*************************************************************************/
/* config_file.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 "config_file.h"
#include "os/keyboard.h"
#include "os/file_access.h"
StringArray ConfigFile::_get_sections() const {
List<String> s;
get_sections(&s);
StringArray arr;
arr.resize(s.size());
int idx=0;
for(const List<String>::Element *E=s.front();E;E=E->next()) {
arr.set(idx++,E->get());
}
return arr;
}
StringArray ConfigFile::_get_section_keys(const String& p_section) const{
List<String> s;
get_section_keys(p_section,&s);
StringArray arr;
arr.resize(s.size());
int idx=0;
for(const List<String>::Element *E=s.front();E;E=E->next()) {
arr.set(idx++,E->get());
}
return arr;
}
void ConfigFile::set_value(const String& p_section, const String& p_key, const Variant& p_value){
if (p_value.get_type()==Variant::NIL) {
//erase
if (!values.has(p_section))
return; // ?
values[p_section].erase(p_key);
if (values[p_section].empty()) {
values.erase(p_section);
}
} else {
if (!values.has(p_section)) {
values[p_section]=Map<String, Variant>();
}
values[p_section][p_key]=p_value;
}
}
Variant ConfigFile::get_value(const String& p_section, const String& p_key) const{
ERR_FAIL_COND_V(!values.has(p_section),Variant());
ERR_FAIL_COND_V(!values[p_section].has(p_key),Variant());
return values[p_section][p_key];
}
bool ConfigFile::has_section(const String& p_section) const {
return values.has(p_section);
}
bool ConfigFile::has_section_key(const String& p_section,const String& p_key) const {
if (!values.has(p_section))
return false;
return values[p_section].has(p_key);
}
void ConfigFile::get_sections(List<String> *r_sections) const{
for(const Map< String, Map<String, Variant> >::Element *E=values.front();E;E=E->next()) {
r_sections->push_back(E->key());
}
}
void ConfigFile::get_section_keys(const String& p_section,List<String> *r_keys) const{
ERR_FAIL_COND(!values.has(p_section));
for(const Map<String, Variant> ::Element *E=values[p_section].front();E;E=E->next()) {
r_keys->push_back(E->key());
}
}
static String _encode_variant(const Variant& p_variant) {
switch(p_variant.get_type()) {
case Variant::BOOL: {
bool val = p_variant;
return (val?"true":"false");
} break;
case Variant::INT: {
int val = p_variant;
return itos(val);
} break;
case Variant::REAL: {
float val = p_variant;
return rtos(val)+(val==int(val)?".0":"");
} break;
case Variant::STRING: {
String val = p_variant;
return "\""+val.xml_escape()+"\"";
} break;
case Variant::COLOR: {
Color val = p_variant;
return "#"+val.to_html();
} break;
case Variant::STRING_ARRAY:
case Variant::INT_ARRAY:
case Variant::REAL_ARRAY:
case Variant::ARRAY: {
Array arr = p_variant;
String str="[";
for(int i=0;i<arr.size();i++) {
if (i>0)
str+=", ";
str+=_encode_variant(arr[i]);
}
str+="]";
return str;
} break;
case Variant::DICTIONARY: {
Dictionary d = p_variant;
String str="{";
List<Variant> keys;
d.get_key_list(&keys);
for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
if (E!=keys.front())
str+=", ";
str+=_encode_variant(E->get());
str+=":";
str+=_encode_variant(d[E->get()]);
}
str+="}";
return str;
} break;
case Variant::IMAGE: {
String str="img(";
Image img=p_variant;
if (!img.empty()) {
String format;
switch(img.get_format()) {
case Image::FORMAT_GRAYSCALE: format="grayscale"; break;
case Image::FORMAT_INTENSITY: format="intensity"; break;
case Image::FORMAT_GRAYSCALE_ALPHA: format="grayscale_alpha"; break;
case Image::FORMAT_RGB: format="rgb"; break;
case Image::FORMAT_RGBA: format="rgba"; break;
case Image::FORMAT_INDEXED : format="indexed"; break;
case Image::FORMAT_INDEXED_ALPHA: format="indexed_alpha"; break;
case Image::FORMAT_BC1: format="bc1"; break;
case Image::FORMAT_BC2: format="bc2"; break;
case Image::FORMAT_BC3: format="bc3"; break;
case Image::FORMAT_BC4: format="bc4"; break;
case Image::FORMAT_BC5: format="bc5"; break;
case Image::FORMAT_CUSTOM: format="custom custom_size="+itos(img.get_data().size())+""; break;
default: {}
}
str+=format+", ";
str+=itos(img.get_mipmaps())+", ";
str+=itos(img.get_width())+", ";
str+=itos(img.get_height())+", ";
DVector<uint8_t> data = img.get_data();
int ds=data.size();
DVector<uint8_t>::Read r = data.read();
for(int i=0;i<ds;i++) {
uint8_t byte = r[i];
const char hex[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
char bstr[3]={ hex[byte>>4], hex[byte&0xF], 0};
str+=bstr;
}
}
str+=")";
return str;
} break;
case Variant::INPUT_EVENT: {
InputEvent ev = p_variant;
switch(ev.type) {
case InputEvent::KEY: {
String mods;
if (ev.key.mod.control)
mods+="C";
if (ev.key.mod.shift)
mods+="S";
if (ev.key.mod.alt)
mods+="A";
if (ev.key.mod.meta)
mods+="M";
if (mods!="")
mods=", "+mods;
return "key("+keycode_get_string(ev.key.scancode)+mods+")";
} break;
case InputEvent::MOUSE_BUTTON: {
return "mbutton("+itos(ev.device)+", "+itos(ev.mouse_button.button_index)+")";
} break;
case InputEvent::JOYSTICK_BUTTON: {
return "jbutton("+itos(ev.device)+", "+itos(ev.joy_button.button_index)+")";
} break;
case InputEvent::JOYSTICK_MOTION: {
return "jaxis("+itos(ev.device)+", "+itos(ev.joy_motion.axis)+")";
} break;
default: {
return "nil";
} break;
}
} break;
default: {}
}
return "nil"; //don't know wha to do with this
}
Error ConfigFile::save(const String& p_path){
Error err;
FileAccess *file = FileAccess::open(p_path,FileAccess::WRITE,&err);
if (err) {
return err;
}
for(Map< String, Map<String, Variant> >::Element *E=values.front();E;E=E->next()) {
if (E!=values.front())
file->store_string("\n");
file->store_string("["+E->key()+"]\n\n");
for(Map<String, Variant>::Element *F=E->get().front();F;F=F->next()) {
file->store_string(F->key()+"="+_encode_variant(F->get())+"\n");
}
}
memdelete(file);
return OK;
}
static Vector<String> _decode_params(const String& p_string) {
int begin=p_string.find("(");
ERR_FAIL_COND_V(begin==-1,Vector<String>());
begin++;
int end=p_string.find(")");
ERR_FAIL_COND_V(end<begin,Vector<String>());
return p_string.substr(begin,end-begin).split(",");
}
static String _get_chunk(const String& str,int &pos, int close_pos) {
enum {
MIN_COMMA,
MIN_COLON,
MIN_CLOSE,
MIN_QUOTE,
MIN_PARENTHESIS,
MIN_CURLY_OPEN,
MIN_OPEN
};
int min_pos=close_pos;
int min_what=MIN_CLOSE;
#define TEST_MIN(m_how,m_what) \
{\
int res = str.find(m_how,pos);\
if (res!=-1 && res < min_pos) {\
min_pos=res;\
min_what=m_what;\
}\
}\
TEST_MIN(",",MIN_COMMA);
TEST_MIN("[",MIN_OPEN);
TEST_MIN("{",MIN_CURLY_OPEN);
TEST_MIN("(",MIN_PARENTHESIS);
TEST_MIN("\"",MIN_QUOTE);
int end=min_pos;
switch(min_what) {
case MIN_COMMA: {
} break;
case MIN_CLOSE: {
//end because it's done
} break;
case MIN_QUOTE: {
end=str.find("\"",min_pos+1)+1;
ERR_FAIL_COND_V(end==-1,Variant());
} break;
case MIN_PARENTHESIS: {
end=str.find(")",min_pos+1)+1;
ERR_FAIL_COND_V(end==-1,Variant());
} break;
case MIN_OPEN: {
int level=1;
while(end<close_pos) {
if (str[end]=='[')
level++;
if (str[end]==']') {
level--;
if (level==0)
break;
}
end++;
}
ERR_FAIL_COND_V(level!=0,Variant());
end++;
} break;
case MIN_CURLY_OPEN: {
int level=1;
while(end<close_pos) {
if (str[end]=='{')
level++;
if (str[end]=='}') {
level--;
if (level==0)
break;
}
end++;
}
ERR_FAIL_COND_V(level!=0,Variant());
end++;
} break;
}
String ret = str.substr(pos,end-pos);
pos=end;
while(pos<close_pos) {
if (str[pos]!=',' && str[pos]!=' ' && str[pos]!=':')
break;
pos++;
}
return ret;
}
static Variant _decode_variant(const String& p_string) {
String str = p_string.strip_edges();
if (str.nocasecmp_to("true")==0)
return Variant(true);
if (str.nocasecmp_to("false")==0)
return Variant(false);
if (str.nocasecmp_to("nil")==0)
return Variant();
if (str.is_valid_float()) {
if (str.find(".")==-1)
return str.to_int();
else
return str.to_double();
}
if (str.begins_with("#")) { //string
return Color::html(str);
}
if (str.begins_with("\"")) { //string
int end = str.find_last("\"");
ERR_FAIL_COND_V(end==0,Variant());
return str.substr(1,end-1).xml_unescape();
}
if (str.begins_with("[")) { //array
int close_pos = str.find_last("]");
ERR_FAIL_COND_V(close_pos==-1,Variant());
Array array;
int pos=1;
while(pos<close_pos) {
String s = _get_chunk(str,pos,close_pos);
array.push_back(_decode_variant(s));
}
return array;
}
if (str.begins_with("{")) { //array
int close_pos = str.find_last("}");
ERR_FAIL_COND_V(close_pos==-1,Variant());
Dictionary d;
int pos=1;
while(pos<close_pos) {
String key = _get_chunk(str,pos,close_pos);
String data = _get_chunk(str,pos,close_pos);
d[_decode_variant(key)]=_decode_variant(data);
}
return d;
}
if (str.begins_with("key")) {
Vector<String> params = _decode_params(p_string);
ERR_FAIL_COND_V(params.size()!=1 && params.size()!=2,Variant());
int scode=0;
if (params[0].is_numeric())
scode=params[0].to_int();
else
scode=find_keycode(params[0]);
InputEvent ie;
ie.type=InputEvent::KEY;
ie.key.scancode=scode;
if (params.size()==2) {
String mods=params[1];
if (mods.findn("C")!=-1)
ie.key.mod.control=true;
if (mods.findn("A")!=-1)
ie.key.mod.alt=true;
if (mods.findn("S")!=-1)
ie.key.mod.shift=true;
if (mods.findn("M")!=-1)
ie.key.mod.meta=true;
}
return ie;
}
if (str.begins_with("mbutton")) {
Vector<String> params = _decode_params(p_string);
ERR_FAIL_COND_V(params.size()!=2,Variant());
InputEvent ie;
ie.type=InputEvent::MOUSE_BUTTON;
ie.device=params[0].to_int();
ie.mouse_button.button_index=params[1].to_int();
return ie;
}
if (str.begins_with("jbutton")) {
Vector<String> params = _decode_params(p_string);
ERR_FAIL_COND_V(params.size()!=2,Variant());
InputEvent ie;
ie.type=InputEvent::JOYSTICK_BUTTON;
ie.device=params[0].to_int();
ie.joy_button.button_index=params[1].to_int();
return ie;
}
if (str.begins_with("jaxis")) {
Vector<String> params = _decode_params(p_string);
ERR_FAIL_COND_V(params.size()!=2,Variant());
InputEvent ie;
ie.type=InputEvent::JOYSTICK_MOTION;
ie.device=params[0].to_int();
ie.joy_motion.axis=params[1].to_int();
return ie;
}
if (str.begins_with("img")) {
Vector<String> params = _decode_params(p_string);
if (params.size()==0) {
return Image();
}
ERR_FAIL_COND_V(params.size()!=5,Image());
String format=params[0].strip_edges();
Image::Format imgformat;
if (format=="grayscale") {
imgformat=Image::FORMAT_GRAYSCALE;
} else if (format=="intensity") {
imgformat=Image::FORMAT_INTENSITY;
} else if (format=="grayscale_alpha") {
imgformat=Image::FORMAT_GRAYSCALE_ALPHA;
} else if (format=="rgb") {
imgformat=Image::FORMAT_RGB;
} else if (format=="rgba") {
imgformat=Image::FORMAT_RGBA;
} else if (format=="indexed") {
imgformat=Image::FORMAT_INDEXED;
} else if (format=="indexed_alpha") {
imgformat=Image::FORMAT_INDEXED_ALPHA;
} else if (format=="bc1") {
imgformat=Image::FORMAT_BC1;
} else if (format=="bc2") {
imgformat=Image::FORMAT_BC2;
} else if (format=="bc3") {
imgformat=Image::FORMAT_BC3;
} else if (format=="bc4") {
imgformat=Image::FORMAT_BC4;
} else if (format=="bc5") {
imgformat=Image::FORMAT_BC5;
} else if (format=="custom") {
imgformat=Image::FORMAT_CUSTOM;
} else {
ERR_FAIL_V( Image() );
}
int mipmaps=params[1].to_int();
int w=params[2].to_int();
int h=params[3].to_int();
if (w == 0 && w == 0) {
//r_v = Image(w, h, imgformat);
return Image();
};
String data=params[4];
int datasize=data.length()/2;
DVector<uint8_t> pixels;
pixels.resize(datasize);
DVector<uint8_t>::Write wb = pixels.write();
const CharType *cptr=data.c_str();
int idx=0;
uint8_t byte;
while( idx<datasize*2) {
CharType c=*(cptr++);
ERR_FAIL_COND_V(c=='<',ERR_FILE_CORRUPT);
if ( (c>='0' && c<='9') || (c>='A' && c<='F') || (c>='a' && c<='f') ) {
if (idx&1) {
byte|=HEX2CHR(c);
wb[idx>>1]=byte;
} else {
byte=HEX2CHR(c)<<4;
}
idx++;
}
}
wb = DVector<uint8_t>::Write();
return Image(w,h,mipmaps,imgformat,pixels);
}
if (str.find(",")!=-1) { //vector2 or vector3
Vector<float> farr = str.split_floats(",",true);
if (farr.size()==2) {
return Point2(farr[0],farr[1]);
}
if (farr.size()==3) {
return Vector3(farr[0],farr[1],farr[2]);
}
ERR_FAIL_V(Variant());
}
return Variant();
}
Error ConfigFile::load(const String& p_path) {
Error err;
FileAccess *f= FileAccess::open(p_path,FileAccess::READ,&err);
if (err!=OK) {
return err;
}
String line;
String section;
String subpath;
int line_count = 0;
while(!f->eof_reached()) {
String line = f->get_line().strip_edges();
line_count++;
if (line=="")
continue;
// find comments
{
int pos=0;
while (true) {
int ret = line.find(";",pos);
if (ret==-1)
break;
int qc=0;
for(int i=0;i<ret;i++) {
if (line[i]=='"')
qc++;
}
if ( !(qc&1) ) {
//not inside string, real comment
line=line.substr(0,ret);
break;
}
pos=ret+1;
}
}
if (line.begins_with("[")) {
int end = line.find_last("]");
ERR_CONTINUE(end!=line.length()-1);
section=line.substr(1,line.length()-2);
} else if (line.find("=")!=-1) {
int eqpos = line.find("=");
String var=line.substr(0,eqpos).strip_edges();
String value=line.substr(eqpos+1,line.length()).strip_edges();
Variant val = _decode_variant(value);
set_value(section,var,val);
} else {
if (line.length() > 0) {
ERR_PRINT(String("Syntax error on line "+itos(line_count)+" of file "+p_path).ascii().get_data());
};
};
}
memdelete(f);
return OK;
}
void ConfigFile::_bind_methods(){
ObjectTypeDB::bind_method(_MD("set_value","section","key","value"),&ConfigFile::set_value);
ObjectTypeDB::bind_method(_MD("get_value","section","key"),&ConfigFile::get_value);
ObjectTypeDB::bind_method(_MD("has_section","section"),&ConfigFile::has_section);
ObjectTypeDB::bind_method(_MD("has_section_key","section","key"),&ConfigFile::has_section_key);
ObjectTypeDB::bind_method(_MD("get_sections"),&ConfigFile::_get_sections);
ObjectTypeDB::bind_method(_MD("get_section_keys"),&ConfigFile::_get_section_keys);
ObjectTypeDB::bind_method(_MD("load:Error","path"),&ConfigFile::load);
ObjectTypeDB::bind_method(_MD("save:Error","path"),&ConfigFile::save);
}
ConfigFile::ConfigFile()
{
}

63
core/io/config_file.h Normal file
View file

@ -0,0 +1,63 @@
/*************************************************************************/
/* config_file.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef CONFIG_FILE_H
#define CONFIG_FILE_H
#include "reference.h"
class ConfigFile : public Reference {
OBJ_TYPE(ConfigFile,Reference);
Map< String, Map<String, Variant> > values;
StringArray _get_sections() const;
StringArray _get_section_keys(const String& p_section) const;
protected:
static void _bind_methods();
public:
void set_value(const String& p_section, const String& p_key, const Variant& p_value);
Variant get_value(const String& p_section, const String& p_key) const;
bool has_section(const String& p_section) const;
bool has_section_key(const String& p_section,const String& p_key) const;
void get_sections(List<String> *r_sections) const;
void get_section_keys(const String& p_section,List<String> *r_keys) const;
Error save(const String& p_path);
Error load(const String& p_path);
ConfigFile();
};
#endif // CONFIG_FILE_H

131
core/io/crypt.h Normal file
View file

@ -0,0 +1,131 @@
/* crypt.h -- base code for crypt/uncrypt ZIPfile
Version 1.01e, February 12th, 2005
Copyright (C) 1998-2005 Gilles Vollant
This code is a modified version of crypting code in Infozip distribution
The encryption/decryption parts of this source code (as opposed to the
non-echoing password parts) were originally written in Europe. The
whole source package can be freely distributed, including from the USA.
(Prior to January 2000, re-export from the US was a violation of US law.)
This encryption code is a direct transcription of the algorithm from
Roger Schlafly, described by Phil Katz in the file appnote.txt. This
file (appnote.txt) is distributed with the PKZIP program (even in the
version without encryption capabilities).
If you don't need crypting in your application, just define symbols
NOCRYPT and NOUNCRYPT.
This code support the "Traditional PKWARE Encryption".
The new AES encryption added on Zip format by Winzip (see the page
http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong
Encryption is not supported.
*/
#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
/***********************************************************************
* Return the next byte in the pseudo-random sequence
*/
static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
{
unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
* unpredictable manner on 16-bit systems; not a problem
* with any known compiler so far, though */
temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
}
/***********************************************************************
* Update the encryption keys with the next byte of plain text
*/
static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)
{
(*(pkeys+0)) = CRC32((*(pkeys+0)), c);
(*(pkeys+1)) += (*(pkeys+0)) & 0xff;
(*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
{
register int keyshift = (int)((*(pkeys+1)) >> 24);
(*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
}
return c;
}
/***********************************************************************
* Initialize the encryption keys and the random header according to
* the given password.
*/
static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)
{
*(pkeys+0) = 305419896L;
*(pkeys+1) = 591751049L;
*(pkeys+2) = 878082192L;
while (*passwd != '\0') {
update_keys(pkeys,pcrc_32_tab,(int)*passwd);
passwd++;
}
}
#define zdecode(pkeys,pcrc_32_tab,c) \
(update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
#define zencode(pkeys,pcrc_32_tab,c,t) \
(t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))
#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
#define RAND_HEAD_LEN 12
/* "last resort" source for second part of crypt seed pattern */
# ifndef ZCR_SEED2
# define ZCR_SEED2 3141592654UL /* use PI as default pattern */
# endif
static int crypthead(const char* passwd, /* password string */
unsigned char* buf, /* where to write header */
int bufSize,
unsigned long* pkeys,
const unsigned long* pcrc_32_tab,
unsigned long crcForCrypting)
{
int n; /* index in random header */
int t; /* temporary */
int c; /* random byte */
unsigned char header[RAND_HEAD_LEN-2]; /* random header */
static unsigned calls = 0; /* ensure different random header each time */
if (bufSize<RAND_HEAD_LEN)
return 0;
/* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
* output of rand() to get less predictability, since rand() is
* often poorly implemented.
*/
if (++calls == 1)
{
srand((unsigned)(time(NULL) ^ ZCR_SEED2));
}
init_keys(passwd, pkeys, pcrc_32_tab);
for (n = 0; n < RAND_HEAD_LEN-2; n++)
{
c = (rand() >> 7) & 0xff;
header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
}
/* Encrypt random header (last two bytes is high word of crc) */
init_keys(passwd, pkeys, pcrc_32_tab);
for (n = 0; n < RAND_HEAD_LEN-2; n++)
{
buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);
}
buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
return n;
}
#endif

551
core/io/fastlz.c Normal file
View file

@ -0,0 +1,551 @@
/*
FastLZ - lightning-fast lossless compression library
Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
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.
*/
#if !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR)
/*
* Always check for bound when decompressing.
* Generally it is best to leave it defined.
*/
#define FASTLZ_SAFE
/*
* Give hints to the compiler for branch prediction optimization.
*/
#if defined(__GNUC__) && (__GNUC__ > 2)
#define FASTLZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1))
#define FASTLZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0))
#else
#define FASTLZ_EXPECT_CONDITIONAL(c) (c)
#define FASTLZ_UNEXPECT_CONDITIONAL(c) (c)
#endif
/*
* Use inlined functions for supported systems.
*/
#if defined(__GNUC__) || defined(__DMC__) || defined(__POCC__) || defined(__WATCOMC__) || defined(__SUNPRO_C)
#define FASTLZ_INLINE inline
#elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__LCC__)
#define FASTLZ_INLINE __inline
#else
#define FASTLZ_INLINE
#endif
/*
* Prevent accessing more than 8-bit at once, except on x86 architectures.
*/
#if !defined(FASTLZ_STRICT_ALIGN)
#define FASTLZ_STRICT_ALIGN
#if defined(__i386__) || defined(__386) /* GNU C, Sun Studio */
#undef FASTLZ_STRICT_ALIGN
#elif defined(__i486__) || defined(__i586__) || defined(__i686__) /* GNU C */
#undef FASTLZ_STRICT_ALIGN
#elif defined(_M_IX86) /* Intel, MSVC */
#undef FASTLZ_STRICT_ALIGN
#elif defined(__386)
#undef FASTLZ_STRICT_ALIGN
#elif defined(_X86_) /* MinGW */
#undef FASTLZ_STRICT_ALIGN
#elif defined(__I86__) /* Digital Mars */
#undef FASTLZ_STRICT_ALIGN
#endif
#endif
/*
* FIXME: use preprocessor magic to set this on different platforms!
*/
typedef unsigned char flzuint8;
typedef unsigned short flzuint16;
typedef unsigned int flzuint32;
/* prototypes */
int fastlz_compress(const void* input, int length, void* output);
int fastlz_compress_level(int level, const void* input, int length, void* output);
int fastlz_decompress(const void* input, int length, void* output, int maxout);
#define MAX_COPY 32
#define MAX_LEN 264 /* 256 + 8 */
#define MAX_DISTANCE 8192
#if !defined(FASTLZ_STRICT_ALIGN)
#define FASTLZ_READU16(p) *((const flzuint16*)(p))
#else
#define FASTLZ_READU16(p) ((p)[0] | (p)[1]<<8)
#endif
#define HASH_LOG 13
#define HASH_SIZE (1<< HASH_LOG)
#define HASH_MASK (HASH_SIZE-1)
#define HASH_FUNCTION(v,p) { v = FASTLZ_READU16(p); v ^= FASTLZ_READU16(p+1)^(v>>(16-HASH_LOG));v &= HASH_MASK; }
#undef FASTLZ_LEVEL
#define FASTLZ_LEVEL 1
#undef FASTLZ_COMPRESSOR
#undef FASTLZ_DECOMPRESSOR
#define FASTLZ_COMPRESSOR fastlz1_compress
#define FASTLZ_DECOMPRESSOR fastlz1_decompress
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
#include "fastlz.c"
#undef FASTLZ_LEVEL
#define FASTLZ_LEVEL 2
#undef MAX_DISTANCE
#define MAX_DISTANCE 8191
#define MAX_FARDISTANCE (65535+MAX_DISTANCE-1)
#undef FASTLZ_COMPRESSOR
#undef FASTLZ_DECOMPRESSOR
#define FASTLZ_COMPRESSOR fastlz2_compress
#define FASTLZ_DECOMPRESSOR fastlz2_decompress
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
#include "fastlz.c"
int fastlz_compress(const void* input, int length, void* output)
{
/* for short block, choose fastlz1 */
if(length < 65536)
return fastlz1_compress(input, length, output);
/* else... */
return fastlz2_compress(input, length, output);
}
int fastlz_decompress(const void* input, int length, void* output, int maxout)
{
/* magic identifier for compression level */
int level = ((*(const flzuint8*)input) >> 5) + 1;
if(level == 1)
return fastlz1_decompress(input, length, output, maxout);
if(level == 2)
return fastlz2_decompress(input, length, output, maxout);
/* unknown level, trigger error */
return 0;
}
int fastlz_compress_level(int level, const void* input, int length, void* output)
{
if(level == 1)
return fastlz1_compress(input, length, output);
if(level == 2)
return fastlz2_compress(input, length, output);
return 0;
}
#else /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output)
{
const flzuint8* ip = (const flzuint8*) input;
const flzuint8* ip_bound = ip + length - 2;
const flzuint8* ip_limit = ip + length - 12;
flzuint8* op = (flzuint8*) output;
const flzuint8* htab[HASH_SIZE];
const flzuint8** hslot;
flzuint32 hval;
flzuint32 copy;
/* sanity check */
if(FASTLZ_UNEXPECT_CONDITIONAL(length < 4))
{
if(length)
{
/* create literal copy only */
*op++ = length-1;
ip_bound++;
while(ip <= ip_bound)
*op++ = *ip++;
return length+1;
}
else
return 0;
}
/* initializes hash table */
for (hslot = htab; hslot < htab + HASH_SIZE; hslot++)
*hslot = ip;
/* we start with literal copy */
copy = 2;
*op++ = MAX_COPY-1;
*op++ = *ip++;
*op++ = *ip++;
/* main loop */
while(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
{
const flzuint8* ref;
flzuint32 distance;
/* minimum match length */
flzuint32 len = 3;
/* comparison starting-point */
const flzuint8* anchor = ip;
/* check for a run */
#if FASTLZ_LEVEL==2
if(ip[0] == ip[-1] && FASTLZ_READU16(ip-1)==FASTLZ_READU16(ip+1))
{
distance = 1;
ip += 3;
ref = anchor - 1 + 3;
goto match;
}
#endif
/* find potential match */
HASH_FUNCTION(hval,ip);
hslot = htab + hval;
ref = htab[hval];
/* calculate distance to the match */
distance = anchor - ref;
/* update hash table */
*hslot = anchor;
/* is this a match? check the first 3 bytes */
if(distance==0 ||
#if FASTLZ_LEVEL==1
(distance >= MAX_DISTANCE) ||
#else
(distance >= MAX_FARDISTANCE) ||
#endif
*ref++ != *ip++ || *ref++!=*ip++ || *ref++!=*ip++)
goto literal;
#if FASTLZ_LEVEL==2
/* far, needs at least 5-byte match */
if(distance >= MAX_DISTANCE)
{
if(*ip++ != *ref++ || *ip++!= *ref++)
goto literal;
len += 2;
}
match:
#endif
/* last matched byte */
ip = anchor + len;
/* distance is biased */
distance--;
if(!distance)
{
/* zero distance means a run */
flzuint8 x = ip[-1];
while(ip < ip_bound)
if(*ref++ != x) break; else ip++;
}
else
for(;;)
{
/* safe because the outer check against ip limit */
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
while(ip < ip_bound)
if(*ref++ != *ip++) break;
break;
}
/* if we have copied something, adjust the copy count */
if(copy)
/* copy is biased, '0' means 1 byte copy */
*(op-copy-1) = copy-1;
else
/* back, to overwrite the copy count */
op--;
/* reset literal counter */
copy = 0;
/* length is biased, '1' means a match of 3 bytes */
ip -= 3;
len = ip - anchor;
/* encode the match */
#if FASTLZ_LEVEL==2
if(distance < MAX_DISTANCE)
{
if(len < 7)
{
*op++ = (len << 5) + (distance >> 8);
*op++ = (distance & 255);
}
else
{
*op++ = (7 << 5) + (distance >> 8);
for(len-=7; len >= 255; len-= 255)
*op++ = 255;
*op++ = len;
*op++ = (distance & 255);
}
}
else
{
/* far away, but not yet in the another galaxy... */
if(len < 7)
{
distance -= MAX_DISTANCE;
*op++ = (len << 5) + 31;
*op++ = 255;
*op++ = distance >> 8;
*op++ = distance & 255;
}
else
{
distance -= MAX_DISTANCE;
*op++ = (7 << 5) + 31;
for(len-=7; len >= 255; len-= 255)
*op++ = 255;
*op++ = len;
*op++ = 255;
*op++ = distance >> 8;
*op++ = distance & 255;
}
}
#else
if(FASTLZ_UNEXPECT_CONDITIONAL(len > MAX_LEN-2))
while(len > MAX_LEN-2)
{
*op++ = (7 << 5) + (distance >> 8);
*op++ = MAX_LEN - 2 - 7 -2;
*op++ = (distance & 255);
len -= MAX_LEN-2;
}
if(len < 7)
{
*op++ = (len << 5) + (distance >> 8);
*op++ = (distance & 255);
}
else
{
*op++ = (7 << 5) + (distance >> 8);
*op++ = len - 7;
*op++ = (distance & 255);
}
#endif
/* update the hash at match boundary */
HASH_FUNCTION(hval,ip);
htab[hval] = ip++;
HASH_FUNCTION(hval,ip);
htab[hval] = ip++;
/* assuming literal copy */
*op++ = MAX_COPY-1;
continue;
literal:
*op++ = *anchor++;
ip = anchor;
copy++;
if(FASTLZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY))
{
copy = 0;
*op++ = MAX_COPY-1;
}
}
/* left-over as literal copy */
ip_bound++;
while(ip <= ip_bound)
{
*op++ = *ip++;
copy++;
if(copy == MAX_COPY)
{
copy = 0;
*op++ = MAX_COPY-1;
}
}
/* if we have copied something, adjust the copy length */
if(copy)
*(op-copy-1) = copy-1;
else
op--;
#if FASTLZ_LEVEL==2
/* marker for fastlz2 */
*(flzuint8*)output |= (1 << 5);
#endif
return op - (flzuint8*)output;
}
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout)
{
const flzuint8* ip = (const flzuint8*) input;
const flzuint8* ip_limit = ip + length;
flzuint8* op = (flzuint8*) output;
flzuint8* op_limit = op + maxout;
flzuint32 ctrl = (*ip++) & 31;
int loop = 1;
do
{
const flzuint8* ref = op;
flzuint32 len = ctrl >> 5;
flzuint32 ofs = (ctrl & 31) << 8;
if(ctrl >= 32)
{
#if FASTLZ_LEVEL==2
flzuint8 code;
#endif
len--;
ref -= ofs;
if (len == 7-1)
#if FASTLZ_LEVEL==1
len += *ip++;
ref -= *ip++;
#else
do
{
code = *ip++;
len += code;
} while (code==255);
code = *ip++;
ref -= code;
/* match from 16-bit distance */
if(FASTLZ_UNEXPECT_CONDITIONAL(code==255))
if(FASTLZ_EXPECT_CONDITIONAL(ofs==(31 << 8)))
{
ofs = (*ip++) << 8;
ofs += *ip++;
ref = op - ofs - MAX_DISTANCE;
}
#endif
#ifdef FASTLZ_SAFE
if (FASTLZ_UNEXPECT_CONDITIONAL(op + len + 3 > op_limit))
return 0;
if (FASTLZ_UNEXPECT_CONDITIONAL(ref-1 < (flzuint8 *)output))
return 0;
#endif
if(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
ctrl = *ip++;
else
loop = 0;
if(ref == op)
{
/* optimize copy for a run */
flzuint8 b = ref[-1];
*op++ = b;
*op++ = b;
*op++ = b;
for(; len; --len)
*op++ = b;
}
else
{
#if !defined(FASTLZ_STRICT_ALIGN)
const flzuint16* p;
flzuint16* q;
#endif
/* copy from reference */
ref--;
*op++ = *ref++;
*op++ = *ref++;
*op++ = *ref++;
#if !defined(FASTLZ_STRICT_ALIGN)
/* copy a byte, so that now it's word aligned */
if(len & 1)
{
*op++ = *ref++;
len--;
}
/* copy 16-bit at once */
q = (flzuint16*) op;
op += len;
p = (const flzuint16*) ref;
for(len>>=1; len > 4; len-=4)
{
*q++ = *p++;
*q++ = *p++;
*q++ = *p++;
*q++ = *p++;
}
for(; len; --len)
*q++ = *p++;
#else
for(; len; --len)
*op++ = *ref++;
#endif
}
}
else
{
ctrl++;
#ifdef FASTLZ_SAFE
if (FASTLZ_UNEXPECT_CONDITIONAL(op + ctrl > op_limit))
return 0;
if (FASTLZ_UNEXPECT_CONDITIONAL(ip + ctrl > ip_limit))
return 0;
#endif
*op++ = *ip++;
for(--ctrl; ctrl; ctrl--)
*op++ = *ip++;
loop = FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit);
if(loop)
ctrl = *ip++;
}
}
while(FASTLZ_EXPECT_CONDITIONAL(loop));
return op - (flzuint8*)output;
}
#endif /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */

100
core/io/fastlz.h Normal file
View file

@ -0,0 +1,100 @@
/*
FastLZ - lightning-fast lossless compression library
Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
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.
*/
#ifndef FASTLZ_H
#define FASTLZ_H
#define FASTLZ_VERSION 0x000100
#define FASTLZ_VERSION_MAJOR 0
#define FASTLZ_VERSION_MINOR 0
#define FASTLZ_VERSION_REVISION 0
#define FASTLZ_VERSION_STRING "0.1.0"
#if defined (__cplusplus)
extern "C" {
#endif
/**
Compress a block of data in the input buffer and returns the size of
compressed block. The size of input buffer is specified by length. The
minimum input buffer size is 16.
The output buffer must be at least 5% larger than the input buffer
and can not be smaller than 66 bytes.
If the input is not compressible, the return value might be larger than
length (input buffer size).
The input buffer and the output buffer can not overlap.
*/
int fastlz_compress(const void* input, int length, void* output);
/**
Decompress a block of compressed data and returns the size of the
decompressed block. If error occurs, e.g. the compressed data is
corrupted or the output buffer is not large enough, then 0 (zero)
will be returned instead.
The input buffer and the output buffer can not overlap.
Decompression is memory safe and guaranteed not to write the output buffer
more than what is specified in maxout.
*/
int fastlz_decompress(const void* input, int length, void* output, int maxout);
/**
Compress a block of data in the input buffer and returns the size of
compressed block. The size of input buffer is specified by length. The
minimum input buffer size is 16.
The output buffer must be at least 5% larger than the input buffer
and can not be smaller than 66 bytes.
If the input is not compressible, the return value might be larger than
length (input buffer size).
The input buffer and the output buffer can not overlap.
Compression level can be specified in parameter level. At the moment,
only level 1 and level 2 are supported.
Level 1 is the fastest compression and generally useful for short data.
Level 2 is slightly slower but it gives better compression ratio.
Note that the compressed data, regardless of the level, can always be
decompressed using the function fastlz_decompress above.
*/
int fastlz_compress_level(int level, const void* input, int length, void* output);
#if defined (__cplusplus)
}
#endif
#endif /* FASTLZ_H */

View file

@ -0,0 +1,184 @@
/*************************************************************************/
/* file_access_buffered.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 "file_access_buffered.h"
#include <string.h>
#include "error_macros.h"
Error FileAccessBuffered::set_error(Error p_error) const {
return (last_error = p_error);
};
void FileAccessBuffered::set_cache_size(int p_size) {
cache_size = p_size;
};
int FileAccessBuffered::get_cache_size() {
return cache_size;
};
int FileAccessBuffered::cache_data_left() const {
if (file.offset >= file.size) {
return 0;
};
if (cache.offset == -1 || file.offset < cache.offset || file.offset >= cache.offset + cache.buffer.size()) {
return read_data_block(file.offset, cache_size);
} else {
return cache.buffer.size() - (file.offset - cache.offset);
};
return 0;
};
void FileAccessBuffered::seek(size_t p_position) {
file.offset = p_position;
};
void FileAccessBuffered::seek_end(int64_t p_position) {
file.offset = file.size + p_position;
};
size_t FileAccessBuffered::get_pos() const {
return file.offset;
};
size_t FileAccessBuffered::get_len() const {
return file.size;
};
bool FileAccessBuffered::eof_reached() const {
return file.offset > file.size;
};
uint8_t FileAccessBuffered::get_8() const {
ERR_FAIL_COND_V(!file.open,0);
uint8_t byte = 0;
if (cache_data_left() >= 1) {
byte = cache.buffer[file.offset - cache.offset];
};
++file.offset;
return byte;
};
int FileAccessBuffered::get_buffer(uint8_t *p_dest,int p_elements) const {
ERR_FAIL_COND_V(!file.open, -1);
if (p_elements > cache_size) {
int total_read = 0;
if (!(cache.offset == -1 || file.offset < cache.offset || file.offset >= cache.offset + cache.buffer.size())) {
int size = (cache.buffer.size() - (file.offset - cache.offset));
size = size - (size % 4);
//DVector<uint8_t>::Read read = cache.buffer.read();
//memcpy(p_dest, read.ptr() + (file.offset - cache.offset), size);
memcpy(p_dest, cache.buffer.ptr() + (file.offset - cache.offset), size);
p_dest += size;
p_elements -= size;
file.offset += size;
total_read += size;
};
int err = read_data_block(file.offset, p_elements, p_dest);
if (err >= 0) {
total_read += err;
file.offset += err;
};
return total_read;
};
int to_read = p_elements;
int total_read = 0;
while (to_read > 0) {
int left = cache_data_left();
if (left == 0) {
if (to_read > 0) {
file.offset += to_read;
};
return total_read;
};
if (left < 0) {
return left;
};
int r = MIN(left, to_read);
//DVector<uint8_t>::Read read = cache.buffer.read();
//memcpy(p_dest+total_read, &read.ptr()[file.offset - cache.offset], r);
memcpy(p_dest+total_read, cache.buffer.ptr() + (file.offset - cache.offset), r);
file.offset += r;
total_read += r;
to_read -= r;
};
return p_elements;
};
bool FileAccessBuffered::is_open() const {
return file.open;
};
Error FileAccessBuffered::get_error() const {
return last_error;
};
FileAccessBuffered::FileAccessBuffered() {
cache_size = DEFAULT_CACHE_SIZE;
};
FileAccessBuffered::~FileAccessBuffered(){
}

View file

@ -0,0 +1,97 @@
/*************************************************************************/
/* file_access_buffered.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef FILE_ACCESS_BUFFERED_H
#define FILE_ACCESS_BUFFERED_H
#include "os/file_access.h"
#include "dvector.h"
#include "ustring.h"
class FileAccessBuffered : public FileAccess {
public:
enum {
DEFAULT_CACHE_SIZE = 128 * 1024,
};
private:
int cache_size;
int cache_data_left() const;
mutable Error last_error;
protected:
Error set_error(Error p_error) const;
mutable struct File {
bool open;
int size;
int offset;
String name;
int access_flags;
} file;
mutable struct Cache {
Vector<uint8_t> buffer;
int offset;
} cache;
virtual int read_data_block(int p_offset, int p_size, uint8_t *p_dest = 0) const =0;
void set_cache_size(int p_size);
int get_cache_size();
public:
virtual size_t get_pos() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file
virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position=0); ///< seek from the end of file
virtual bool eof_reached() const;
virtual uint8_t get_8() const;
virtual int get_buffer(uint8_t *p_dst,int p_length) const; ///< get an array of bytes
virtual bool is_open() const;
virtual Error get_error() const;
FileAccessBuffered();
virtual ~FileAccessBuffered();
};
#endif

View file

@ -0,0 +1,147 @@
/*************************************************************************/
/* file_access_buffered_fa.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef FILE_ACCESS_BUFFERED_FA_H
#define FILE_ACCESS_BUFFERED_FA_H
#include "core/io/file_access_buffered.h"
template<class T>
class FileAccessBufferedFA : public FileAccessBuffered {
T f;
int read_data_block(int p_offset, int p_size, uint8_t *p_dest = 0) const {
ERR_FAIL_COND_V( !f.is_open(), -1 );
((T*)&f)->seek(p_offset);
if (p_dest) {
f.get_buffer(p_dest, p_size);
return p_size;
} else {
cache.offset = p_offset;
cache.buffer.resize(p_size);
// on dvector
//DVector<uint8_t>::Write write = cache.buffer.write();
//f.get_buffer(write.ptr(), p_size);
// on vector
f.get_buffer(cache.buffer.ptr(), p_size);
return p_size;
};
};
static FileAccess* create() {
return memnew( FileAccessBufferedFA<T>() );
};
protected:
virtual void _set_access_type(AccessType p_access) {
f._set_access_type(p_access);
FileAccessBuffered::_set_access_type(p_access);
};
public:
void store_8(uint8_t p_dest) {
f.store_8(p_dest);
};
void store_buffer(const uint8_t *p_src,int p_length) {
f.store_buffer(p_src, p_length);
};
bool file_exists(const String& p_name) {
return f.file_exists(p_name);
};
Error _open(const String& p_path, int p_mode_flags) {
close();
Error ret = f._open(p_path, p_mode_flags);
if (ret !=OK)
return ret;
//ERR_FAIL_COND_V( ret != OK, ret );
file.size = f.get_len();
file.offset = 0;
file.open = true;
file.name = p_path;
file.access_flags = p_mode_flags;
cache.buffer.resize(0);
cache.offset = 0;
return set_error(OK);
};
void close() {
f.close();
file.offset = 0;
file.size = 0;
file.open = false;
file.name = "";
cache.buffer.resize(0);
cache.offset = 0;
set_error(OK);
};
// static void make_default() {
//FileAccess::create_func = FileAccessBufferedFA<T>::create;
// };
virtual uint64_t _get_modified_time(const String& p_file) {
return f._get_modified_time(p_file);
}
FileAccessBufferedFA() {
};
};
#endif // FILE_ACCESS_BUFFERED_FA_H

View file

@ -0,0 +1,421 @@
/*************************************************************************/
/* file_access_compressed.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 "file_access_compressed.h"
#include "print_string.h"
void FileAccessCompressed::configure(const String& p_magic, Compression::Mode p_mode, int p_block_size) {
magic=p_magic.ascii().get_data();
if (magic.length()>4)
magic=magic.substr(0,4);
else {
while(magic.length()<4)
magic+=" ";
}
cmode=p_mode;
block_size=p_block_size;
}
#define WRITE_FIT(m_bytes) \
{\
if (write_pos+(m_bytes) > write_max) {\
write_max=write_pos+(m_bytes);\
}\
if (write_max > write_buffer_size) {\
write_buffer_size = nearest_power_of_2( write_max );\
buffer.resize(write_buffer_size);\
write_ptr=buffer.ptr();\
}\
}
Error FileAccessCompressed::open_after_magic(FileAccess *p_base) {
f=p_base;
cmode=(Compression::Mode)f->get_32();
block_size=f->get_32();
read_total=f->get_32();
int bc = (read_total/block_size)+1;
int acc_ofs=f->get_pos()+bc*4;
int max_bs=0;
for(int i=0;i<bc;i++) {
ReadBlock rb;
rb.offset=acc_ofs;
rb.csize=f->get_32();
acc_ofs+=rb.csize;
max_bs=MAX(max_bs,rb.csize);
read_blocks.push_back(rb);
}
comp_buffer.resize(max_bs);
buffer.resize(block_size);
read_ptr=buffer.ptr();
f->get_buffer(comp_buffer.ptr(),read_blocks[0].csize);
at_end=false;
read_eof=false;
read_block_count=bc;
read_block_size=read_blocks.size()==1?read_total:block_size;
Compression::decompress(buffer.ptr(),read_block_size,comp_buffer.ptr(),read_blocks[0].csize,cmode);
read_block=0;
read_pos=0;
return OK;
}
Error FileAccessCompressed::_open(const String& p_path, int p_mode_flags){
ERR_FAIL_COND_V(p_mode_flags==READ_WRITE,ERR_UNAVAILABLE);
if (f)
close();
Error err;
f = FileAccess::open(p_path,p_mode_flags,&err);
if (err!=OK) {
//not openable
f=NULL;
return err;
}
if (p_mode_flags&WRITE) {
buffer.clear();
writing=true;
write_pos=0;
write_buffer_size=256;
buffer.resize(256);
write_max=0;
write_ptr=buffer.ptr();
//don't store anything else unless it's done saving!
} else {
char rmagic[5];
f->get_buffer((uint8_t*)rmagic,4);
rmagic[4]=0;
if (magic!=rmagic) {
memdelete(f);
f=NULL;
return ERR_FILE_UNRECOGNIZED;
}
open_after_magic(f);
}
return OK;
}
void FileAccessCompressed::close(){
if (!f)
return;
if (writing) {
//save block table and all compressed blocks
CharString mgc = magic.utf8();
f->store_buffer((const uint8_t*)mgc.get_data(),mgc.length()); //write header 4
f->store_32(cmode); //write compression mode 4
f->store_32(block_size); //write block size 4
f->store_32(write_max); //max amount of data written 4
int bc=(write_max/block_size)+1;
for(int i=0;i<bc;i++) {
f->store_32(0); //compressed sizes, will update later
}
Vector<int> block_sizes;
for(int i=0;i<bc;i++) {
int bl = i==(bc-1) ? write_max % block_size : block_size;
uint8_t *bp = &write_ptr[i*block_size];
Vector<uint8_t> cblock;
cblock.resize(Compression::get_max_compressed_buffer_size(bl,cmode));
int s = Compression::compress(cblock.ptr(),bp,bl,cmode);
f->store_buffer(cblock.ptr(),s);
block_sizes.push_back(s);
}
f->seek(16); //ok write block sizes
for(int i=0;i<bc;i++)
f->store_32(block_sizes[i]);
f->seek_end();
f->store_buffer((const uint8_t*)mgc.get_data(),mgc.length()); //magic at the end too
buffer.clear();
} else {
comp_buffer.clear();
buffer.clear();
read_blocks.clear();
}
memdelete(f);
f=NULL;
}
bool FileAccessCompressed::is_open() const{
return f!=NULL;
}
void FileAccessCompressed::seek(size_t p_position){
ERR_FAIL_COND(!f);
if (writing) {
ERR_FAIL_COND(p_position>write_max);
write_pos=p_position;
} else {
ERR_FAIL_COND(p_position>read_total);
if (p_position==read_total) {
at_end=true;
} else {
int block_idx = p_position/block_size;
if (block_idx!=read_block) {
read_block=block_idx;
f->seek(read_blocks[read_block].offset);
f->get_buffer(comp_buffer.ptr(),read_blocks[read_block].csize);
Compression::decompress(buffer.ptr(),read_blocks.size()==1?read_total:block_size,comp_buffer.ptr(),read_blocks[read_block].csize,cmode);
read_block_size=read_block==read_block_count-1?read_total%block_size:block_size;
}
read_pos=p_position%block_size;
}
}
}
void FileAccessCompressed::seek_end(int64_t p_position){
ERR_FAIL_COND(!f);
if (writing) {
seek(write_max+p_position);
} else {
seek(read_total+p_position);
}
}
size_t FileAccessCompressed::get_pos() const{
ERR_FAIL_COND_V(!f,0);
if (writing) {
return write_pos;
} else {
return read_block*block_size+read_pos;
}
}
size_t FileAccessCompressed::get_len() const{
ERR_FAIL_COND_V(!f,0);
if (writing) {
return write_max;
} else {
return read_total;
}
}
bool FileAccessCompressed::eof_reached() const{
ERR_FAIL_COND_V(!f,false);
if (writing) {
return false;
} else {
return read_eof;
}
}
uint8_t FileAccessCompressed::get_8() const{
ERR_FAIL_COND_V(writing,0);
ERR_FAIL_COND_V(!f,0);
if (at_end) {
read_eof=true;
return 0;
}
uint8_t ret = read_ptr[read_pos];
read_pos++;
if (read_pos>=read_block_size) {
read_block++;
if (read_block<read_block_count) {
//read another block of compressed data
f->get_buffer(comp_buffer.ptr(),read_blocks[read_block].csize);
Compression::decompress(buffer.ptr(),read_blocks.size()==1?read_total:block_size,comp_buffer.ptr(),read_blocks[read_block].csize,cmode);
read_block_size=read_block==read_block_count-1?read_total%block_size:block_size;
read_pos=0;
} else {
read_block--;
at_end=true;
ret =0;
}
}
return ret;
}
int FileAccessCompressed::get_buffer(uint8_t *p_dst, int p_length) const{
ERR_FAIL_COND_V(writing,0);
ERR_FAIL_COND_V(!f,0);
if (at_end) {
read_eof=true;
return 0;
}
for(int i=0;i<p_length;i++) {
p_dst[i]=read_ptr[read_pos];
read_pos++;
if (read_pos>=read_block_size) {
read_block++;
if (read_block<read_block_count) {
//read another block of compressed data
f->get_buffer(comp_buffer.ptr(),read_blocks[read_block].csize);
Compression::decompress(buffer.ptr(),read_blocks.size()==1?read_total:block_size,comp_buffer.ptr(),read_blocks[read_block].csize,cmode);
read_block_size=read_block==read_block_count-1?read_total%block_size:block_size;
read_pos=0;
} else {
read_block--;
at_end=true;
if (i<p_length-1)
read_eof=true;
return i;
}
}
}
return p_length;
}
Error FileAccessCompressed::get_error() const{
return read_eof?ERR_FILE_EOF:OK;
}
void FileAccessCompressed::store_8(uint8_t p_dest){
ERR_FAIL_COND(!f);
ERR_FAIL_COND(!writing);
WRITE_FIT(1);
write_ptr[write_pos++]=p_dest;
}
bool FileAccessCompressed::file_exists(const String& p_name){
FileAccess *fa = FileAccess::open(p_name,FileAccess::READ);
if (!fa)
return false;
memdelete(fa);
return true;
}
uint64_t FileAccessCompressed::_get_modified_time(const String& p_file) {
if (f)
return f->get_modified_time(p_file);
else
return 0;
}
FileAccessCompressed::FileAccessCompressed() {
f=NULL;
magic="GCMP";
block_size=4096;
cmode=Compression::MODE_FASTLZ;
writing=false;
write_ptr=0;
write_buffer_size=0;
write_max=0;
block_size=0;
read_eof=false;
at_end=false;
read_total=0;
read_ptr=NULL;
read_block=0;
read_block_count=0;
read_block_size=0;
read_pos=0;
}
FileAccessCompressed::~FileAccessCompressed(){
if (f)
close();
}

View file

@ -0,0 +1,101 @@
/*************************************************************************/
/* file_access_compressed.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef FILE_ACCESS_COMPRESSED_H
#define FILE_ACCESS_COMPRESSED_H
#include "io/compression.h"
#include "os/file_access.h"
class FileAccessCompressed : public FileAccess {
Compression::Mode cmode;
bool writing;
int write_pos;
uint8_t*write_ptr;
int write_buffer_size;
int write_max;
int block_size;
mutable bool read_eof;
mutable bool at_end;
struct ReadBlock {
int csize;
int offset;
};
mutable Vector<uint8_t> comp_buffer;
uint8_t *read_ptr;
mutable int read_block;
int read_block_count;
mutable int read_block_size;
mutable int read_pos;
Vector<ReadBlock> read_blocks;
int read_total;
String magic;
mutable Vector<uint8_t> buffer;
FileAccess *f;
public:
void configure(const String& p_magic, Compression::Mode p_mode=Compression::MODE_FASTLZ, int p_block_size=4096);
Error open_after_magic(FileAccess *p_base);
virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file
virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open
virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position=0); ///< seek from the end of file
virtual size_t get_pos() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
virtual uint8_t get_8() const; ///< get a byte
virtual int get_buffer(uint8_t *p_dst, int p_length) const;
virtual Error get_error() const; ///< get last error
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual bool file_exists(const String& p_name); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String& p_file);
FileAccessCompressed();
virtual ~FileAccessCompressed();
};
#endif // FILE_ACCESS_COMPRESSED_H

View file

@ -0,0 +1,188 @@
/*************************************************************************/
/* file_access_memory.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 "file_access_memory.h"
#include "os/dir_access.h"
#include "os/copymem.h"
#include "globals.h"
#include "map.h"
static Map<String, Vector<uint8_t> >* files = NULL;
void FileAccessMemory::register_file(String p_name, Vector<uint8_t> p_data) {
if (!files) {
files = memnew((Map<String, Vector<uint8_t> >));
};
String name;
if (Globals::get_singleton())
name = Globals::get_singleton()->globalize_path(p_name);
else
name = p_name;
name = DirAccess::normalize_path(name);
(*files)[name] = p_data;
};
void FileAccessMemory::cleanup() {
if (!files)
return;
memdelete(files);
};
FileAccess* FileAccessMemory::create() {
return memnew(FileAccessMemory);
};
bool FileAccessMemory::file_exists(const String& p_name) {
String name = fix_path(p_name);
name = DirAccess::normalize_path(name);
return files && (files->find(name) != NULL);
};
Error FileAccessMemory::_open(const String& p_path, int p_mode_flags) {
ERR_FAIL_COND_V(!files, ERR_FILE_NOT_FOUND);
String name = fix_path(p_path);
name = DirAccess::normalize_path(name);
Map<String, Vector<uint8_t> >::Element* E = files->find(name);
ERR_FAIL_COND_V(!E, ERR_FILE_NOT_FOUND);
data = &(E->get()[0]);
length = E->get().size();
pos = 0;
return OK;
};
void FileAccessMemory::close() {
data = NULL;
};
bool FileAccessMemory::is_open() const {
return data != NULL;
};
void FileAccessMemory::seek(size_t p_position) {
ERR_FAIL_COND(!data);
pos = p_position;
};
void FileAccessMemory::seek_end(int64_t p_position) {
ERR_FAIL_COND(!data);
pos = length + p_position;
};
size_t FileAccessMemory::get_pos() const {
ERR_FAIL_COND_V(!data, 0);
return pos;
};
size_t FileAccessMemory::get_len() const {
ERR_FAIL_COND_V(!data, 0);
return length;
};
bool FileAccessMemory::eof_reached() const {
return pos >= length;
};
uint8_t FileAccessMemory::get_8() const {
uint8_t ret;
if (pos < length) {
ret = data[pos];
};
++pos;
return ret;
};
int FileAccessMemory::get_buffer(uint8_t *p_dst,int p_length) const {
ERR_FAIL_COND_V(!data, -1);
int left = length - pos;
int read = MIN(p_length, left);
if (read < p_length) {
WARN_PRINT("Reading less data than requested");
};
copymem(p_dst, &data[pos], read);
pos += p_length;
return read;
};
Error FileAccessMemory::get_error() const {
return pos >= length ? ERR_FILE_EOF : OK;
};
void FileAccessMemory::store_8(uint8_t p_byte) {
ERR_FAIL_COND(!data);
ERR_FAIL_COND(pos >= length);
data[pos++] = p_byte;
};
void FileAccessMemory::store_buffer(const uint8_t *p_src,int p_length) {
int left = length - pos;
int write = MIN(p_length, left);
if (write < p_length) {
WARN_PRINT("Writing less data than requested");
};
copymem(&data[pos], p_src, write);
pos += p_length;
};
FileAccessMemory::FileAccessMemory() {
data = NULL;
}

View file

@ -0,0 +1,76 @@
/*************************************************************************/
/* file_access_memory.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef FILE_ACCESS_MEMORY_H
#define FILE_ACCESS_MEMORY_H
#include "os/file_access.h"
class FileAccessMemory : public FileAccess {
uint8_t* data;
int length;
mutable int pos;
static FileAccess* create();
public:
static void register_file(String p_name, Vector<uint8_t> p_data);
static void cleanup();
virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file
virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open
virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position); ///< seek from the end of file
virtual size_t get_pos() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
virtual uint8_t get_8() const; ///< get a byte
virtual int get_buffer(uint8_t *p_dst,int p_length) const; ///< get an array of bytes
virtual Error get_error() const; ///< get last error
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual void store_buffer(const uint8_t *p_src,int p_length); ///< store an array of bytes
virtual bool file_exists(const String& p_name); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String& p_file) { return 0; }
FileAccessMemory();
};
#endif // FILE_ACCESS_MEMORY_H

View file

@ -0,0 +1,566 @@
/*************************************************************************/
/* file_access_network.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 "file_access_network.h"
#include "marshalls.h"
#include "globals.h"
#include "os/os.h"
#include "io/ip.h"
#define DEBUG_PRINT(m_p) print_line(m_p)
//#define DEBUG_TIME(m_what) printf("MS: %s - %lli\n",m_what,OS::get_singleton()->get_ticks_usec());
//#define DEBUG_PRINT(m_p)
#define DEBUG_TIME(m_what)
void FileAccessNetworkClient::lock_mutex() {
mutex->lock();
lockcount++;
}
void FileAccessNetworkClient::unlock_mutex() {
lockcount--;
mutex->unlock();
}
void FileAccessNetworkClient::put_32(int p_32) {
uint8_t buf[4];
encode_uint32(p_32,buf);
client->put_data(buf,4);
DEBUG_PRINT("put32: "+itos(p_32));
}
void FileAccessNetworkClient::put_64(int64_t p_64) {
uint8_t buf[8];
encode_uint64(p_64,buf);
client->put_data(buf,8);
DEBUG_PRINT("put64: "+itos(p_64));
}
int FileAccessNetworkClient::get_32() {
uint8_t buf[4];
client->get_data(buf,4);
return decode_uint32(buf);
}
int64_t FileAccessNetworkClient::get_64() {
uint8_t buf[8];
client->get_data(buf,8);
return decode_uint64(buf);
}
void FileAccessNetworkClient::_thread_func() {
client->set_nodelay(true);
while(!quit) {
DEBUG_PRINT("SEM WAIT - "+itos(sem->get()));
Error err = sem->wait();
DEBUG_TIME("sem_unlock");
//DEBUG_PRINT("semwait returned "+itos(werr));
DEBUG_PRINT("MUTEX LOCK "+itos(lockcount));
DEBUG_PRINT("POPO");
DEBUG_PRINT("PEPE");
lock_mutex();
DEBUG_PRINT("MUTEX PASS");
blockrequest_mutex->lock();
while(block_requests.size()) {
put_32(block_requests.front()->get().id);
put_32(FileAccessNetwork::COMMAND_READ_BLOCK);
put_64(block_requests.front()->get().offset);
put_32(block_requests.front()->get().size);
block_requests.pop_front();
}
blockrequest_mutex->unlock();
DEBUG_PRINT("THREAD ITER");
DEBUG_TIME("sem_read");
int id = get_32();
int response = get_32();
DEBUG_PRINT("GET RESPONSE: "+itos(response));
FileAccessNetwork *fa=NULL;
if (response!=FileAccessNetwork::RESPONSE_DATA) {
ERR_FAIL_COND(!accesses.has(id));
}
if (accesses.has(id))
fa=accesses[id];
switch(response) {
case FileAccessNetwork::RESPONSE_OPEN: {
DEBUG_TIME("sem_open");
int status = get_32();
if (status!=OK) {
fa->_respond(0,Error(status));
} else {
uint64_t len = get_64();
fa->_respond(len,Error(status));
}
fa->sem->post();
} break;
case FileAccessNetwork::RESPONSE_DATA: {
int64_t offset = get_64();
uint32_t len = get_32();
Vector<uint8_t> block;
block.resize(len);
client->get_data(block.ptr(),len);
if (fa) //may have been queued
fa->_set_block(offset,block);
} break;
case FileAccessNetwork::RESPONSE_FILE_EXISTS: {
int status = get_32();
fa->exists_modtime=status!=0;
fa->sem->post();
} break;
case FileAccessNetwork::RESPONSE_GET_MODTIME: {
uint64_t status = get_64();
fa->exists_modtime=status;
fa->sem->post();
} break;
}
unlock_mutex();
}
}
void FileAccessNetworkClient::_thread_func(void *s) {
FileAccessNetworkClient *self =(FileAccessNetworkClient*)s;
self->_thread_func();
}
Error FileAccessNetworkClient::connect(const String& p_host,int p_port,const String& p_password) {
IP_Address ip;
if (p_host.is_valid_ip_address()) {
ip=p_host;
} else {
ip=IP::get_singleton()->resolve_hostname(p_host);
}
DEBUG_PRINT("IP: "+String(ip)+" port "+itos(p_port));
Error err = client->connect(ip,p_port);
ERR_FAIL_COND_V(err,err);
while(client->get_status()==StreamPeerTCP::STATUS_CONNECTING) {
//DEBUG_PRINT("trying to connect....");
OS::get_singleton()->delay_usec(1000);
}
if (client->get_status()!=StreamPeerTCP::STATUS_CONNECTED) {
return ERR_CANT_CONNECT;
}
CharString cs = p_password.utf8();
put_32(cs.length());
client->put_data((const uint8_t*)cs.ptr(),cs.length());
int e = get_32();
if (e!=OK) {
return ERR_INVALID_PARAMETER;
}
thread = Thread::create(_thread_func,this);
return OK;
}
FileAccessNetworkClient *FileAccessNetworkClient::singleton=NULL;
FileAccessNetworkClient::FileAccessNetworkClient() {
thread=NULL;
mutex = Mutex::create();
blockrequest_mutex = Mutex::create();
quit=false;
singleton=this;
last_id=0;
client = Ref<StreamPeerTCP>( StreamPeerTCP::create() );
sem=Semaphore::create();
lockcount=0;
}
FileAccessNetworkClient::~FileAccessNetworkClient() {
if (thread) {
quit=true;
sem->post();
Thread::wait_to_finish(thread);
}
memdelete(blockrequest_mutex);
memdelete(mutex);
memdelete(sem);
}
void FileAccessNetwork::_set_block(size_t p_offset,const Vector<uint8_t>& p_block) {
int page = p_offset/page_size;
ERR_FAIL_INDEX(page,pages.size());
if (page<pages.size()-1) {
ERR_FAIL_COND(p_block.size()!=page_size);
} else {
ERR_FAIL_COND( (p_block.size() != (total_size%page_size)));
}
buffer_mutex->lock();
pages[page].buffer=p_block;
pages[page].queued=false;
buffer_mutex->unlock();
if (waiting_on_page==page) {
waiting_on_page=-1;
page_sem->post();
}
}
void FileAccessNetwork::_respond(size_t p_len,Error p_status) {
DEBUG_PRINT("GOT RESPONSE - len: "+itos(p_len)+" status: "+itos(p_status));
response=p_status;
if (response!=OK)
return;
opened=true;
total_size=p_len;
int pc = ((total_size-1)/page_size)+1;
pages.resize(pc);
}
Error FileAccessNetwork::_open(const String& p_path, int p_mode_flags) {
ERR_FAIL_COND_V(p_mode_flags!=READ,ERR_UNAVAILABLE);
if (opened)
close();
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
DEBUG_PRINT("open: "+p_path);
DEBUG_TIME("open_begin");
nc->lock_mutex();
nc->put_32(id);
nc->accesses[id]=this;
nc->put_32(COMMAND_OPEN_FILE);
CharString cs =p_path.utf8();
nc->put_32(cs.length());
nc->client->put_data((const uint8_t*)cs.ptr(),cs.length());
pos=0;
eof_flag=false;
last_page=-1;
last_page_buff=NULL;
// buffers.clear();
nc->unlock_mutex();
DEBUG_PRINT("OPEN POST");
DEBUG_TIME("open_post");
nc->sem->post(); //awaiting answer
DEBUG_PRINT("WAIT...");
sem->wait();
DEBUG_TIME("open_end");
DEBUG_PRINT("WAIT ENDED...");
return response;
}
void FileAccessNetwork::close(){
if (!opened)
return;
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
DEBUG_PRINT("CLOSE");
nc->lock_mutex();
nc->put_32(id);
nc->put_32(COMMAND_CLOSE);
pages.clear();
opened=false;
nc->unlock_mutex();
}
bool FileAccessNetwork::is_open() const{
return opened;
}
void FileAccessNetwork::seek(size_t p_position){
ERR_FAIL_COND(!opened);
eof_flag=p_position>total_size;
if (p_position>=total_size) {
p_position=total_size;
}
pos=p_position;
}
void FileAccessNetwork::seek_end(int64_t p_position){
seek(total_size+p_position);
}
size_t FileAccessNetwork::get_pos() const{
ERR_FAIL_COND_V(!opened,0);
return pos;
}
size_t FileAccessNetwork::get_len() const{
ERR_FAIL_COND_V(!opened,0);
return total_size;
}
bool FileAccessNetwork::eof_reached() const{
ERR_FAIL_COND_V(!opened,false);
return eof_flag;
}
uint8_t FileAccessNetwork::get_8() const{
uint8_t v;
get_buffer(&v,1);
return v;
}
void FileAccessNetwork::_queue_page(int p_page) const {
if (p_page>=pages.size())
return;
if (pages[p_page].buffer.empty() && !pages[p_page].queued) {
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
nc->blockrequest_mutex->lock();
FileAccessNetworkClient::BlockRequest br;
br.id=id;
br.offset=size_t(p_page)*page_size;
br.size=page_size;
nc->block_requests.push_back(br);
pages[p_page].queued=true;
nc->blockrequest_mutex->unlock();
DEBUG_PRINT("QUEUE PAGE POST");
nc->sem->post();
DEBUG_PRINT("queued "+itos(p_page));
}
}
int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const{
//bool eof=false;
if (pos+p_length>total_size) {
eof_flag=true;
}
if (pos+p_length>=total_size) {
p_length=total_size-pos;
}
// FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
uint8_t *buff=last_page_buff;
for(int i=0;i<p_length;i++) {
int page=pos/page_size;
if (page!=last_page) {
buffer_mutex->lock();
if (pages[page].buffer.empty()) {
//fuck
waiting_on_page=page;
for(int j=0;j<read_ahead;j++) {
_queue_page(page+j);
}
buffer_mutex->unlock();
DEBUG_PRINT("wait");
page_sem->wait();
DEBUG_PRINT("done");
} else {
for(int j=0;j<read_ahead;j++) {
_queue_page(page+j);
}
buff=pages[page].buffer.ptr();
//queue pages
buffer_mutex->unlock();
}
buff=pages[page].buffer.ptr();
last_page_buff=buff;
last_page=page;
}
p_dst[i]=buff[pos-uint64_t(page)*page_size];
pos++;
}
return p_length;
}
Error FileAccessNetwork::get_error() const{
return pos==total_size?ERR_FILE_EOF:OK;
}
void FileAccessNetwork::store_8(uint8_t p_dest) {
ERR_FAIL();
}
bool FileAccessNetwork::file_exists(const String& p_path){
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
nc->lock_mutex();
nc->put_32(id);
nc->put_32(COMMAND_FILE_EXISTS);
CharString cs=p_path.utf8();
nc->put_32(cs.length());
nc->client->put_data((const uint8_t*)cs.ptr(),cs.length());
nc->unlock_mutex();
DEBUG_PRINT("FILE EXISTS POST");
nc->sem->post();
sem->wait();
return exists_modtime!=0;
}
uint64_t FileAccessNetwork::_get_modified_time(const String& p_file){
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
nc->lock_mutex();
nc->put_32(id);
nc->put_32(COMMAND_GET_MODTIME);
CharString cs=p_file.utf8();
nc->put_32(cs.length());
nc->client->put_data((const uint8_t*)cs.ptr(),cs.length());
nc->unlock_mutex();
DEBUG_PRINT("MODTIME POST");
nc->sem->post();
sem->wait();
return exists_modtime;
}
FileAccessNetwork::FileAccessNetwork() {
eof_flag=false;
opened=false;
pos=0;
sem=Semaphore::create();
page_sem=Semaphore::create();
buffer_mutex=Mutex::create();
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
nc->lock_mutex();
id=nc->last_id++;
nc->accesses[id]=this;
nc->unlock_mutex();
page_size = GLOBAL_DEF("remote_fs/page_size",65536);
read_ahead = GLOBAL_DEF("remote_fs/page_read_ahead",4);
max_pages = GLOBAL_DEF("remote_fs/max_pages",20);
last_activity_val=0;
waiting_on_page=-1;
last_page=-1;
}
FileAccessNetwork::~FileAccessNetwork() {
close();
memdelete(sem);
memdelete(page_sem);
memdelete(buffer_mutex);
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
nc->lock_mutex();
id=nc->last_id++;
nc->accesses.erase(id);
nc->unlock_mutex();
}

View file

@ -0,0 +1,169 @@
/*************************************************************************/
/* file_access_network.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef FILE_ACCESS_NETWORK_H
#define FILE_ACCESS_NETWORK_H
#include "os/file_access.h"
#include "os/semaphore.h"
#include "os/thread.h"
#include "io/stream_peer_tcp.h"
class FileAccessNetwork;
class FileAccessNetworkClient {
struct BlockRequest {
int id;
uint64_t offset;
int size;
};
int ml;
List<BlockRequest> block_requests;
Semaphore *sem;
Thread *thread;
bool quit;
Mutex *mutex;
Mutex *blockrequest_mutex;
Map<int,FileAccessNetwork*> accesses;
Ref<StreamPeerTCP> client;
int last_id;
Vector<uint8_t> block;
void _thread_func();
static void _thread_func(void *s);
void put_32(int p_32);
void put_64(int64_t p_64);
int get_32();
int64_t get_64();
int lockcount;
void lock_mutex();
void unlock_mutex();
friend class FileAccessNetwork;
static FileAccessNetworkClient *singleton;
public:
static FileAccessNetworkClient *get_singleton() { return singleton; }
Error connect(const String& p_host,int p_port,const String& p_password="");
FileAccessNetworkClient();
~FileAccessNetworkClient();
};
class FileAccessNetwork : public FileAccess {
Semaphore *sem;
Semaphore *page_sem;
Mutex *buffer_mutex;
bool opened;
size_t total_size;
mutable size_t pos;
int id;
mutable bool eof_flag;
mutable int last_page;
mutable uint8_t *last_page_buff;
uint32_t page_size;
int read_ahead;
int max_pages;
mutable int waiting_on_page;
mutable int last_activity_val;
struct Page {
int activity;
bool queued;
Vector<uint8_t> buffer;
Page() { activity=0; queued=false; }
};
mutable Vector< Page > pages;
mutable Error response;
uint64_t exists_modtime;
friend class FileAccessNetworkClient;
void _queue_page(int p_page) const;
void _respond(size_t p_len,Error p_status);
void _set_block(size_t p_offset,const Vector<uint8_t>& p_block);
public:
enum Command {
COMMAND_OPEN_FILE,
COMMAND_READ_BLOCK,
COMMAND_CLOSE,
COMMAND_FILE_EXISTS,
COMMAND_GET_MODTIME,
};
enum Response {
RESPONSE_OPEN,
RESPONSE_DATA,
RESPONSE_FILE_EXISTS,
RESPONSE_GET_MODTIME,
};
virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file
virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open
virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position=0); ///< seek from the end of file
virtual size_t get_pos() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
virtual uint8_t get_8() const; ///< get a byte
virtual int get_buffer(uint8_t *p_dst, int p_length) const;
virtual Error get_error() const; ///< get last error
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual bool file_exists(const String& p_path); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String& p_file);
FileAccessNetwork();
~FileAccessNetwork();
};
#endif // FILE_ACCESS_NETWORK_H

View file

@ -0,0 +1,469 @@
/*************************************************************************/
/* file_access_pack.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 "file_access_pack.h"
#include "version.h"
#include <stdio.h>
Error PackedData::add_pack(const String& p_path) {
for (int i=0; i<sources.size(); i++) {
if (sources[i]->try_open_pack(p_path)) {
return OK;
};
};
return ERR_FILE_UNRECOGNIZED;
};
void PackedData::add_path(const String& pkg_path, const String& path, uint64_t ofs, uint64_t size, PackSource* p_src) {
bool exists = files.has(path);
PackedFile pf;
pf.pack=pkg_path;
pf.offset=ofs;
pf.size=size;
pf.src = p_src;
files[path]=pf;
if (!exists) {
//search for dir
String p = path.replace_first("res://","");
PackedDir *cd=root;
if (p.find("/")!=-1) { //in a subdir
Vector<String> ds=p.get_base_dir().split("/");
for(int j=0;j<ds.size();j++) {
if (!cd->subdirs.has(ds[j])) {
PackedDir *pd = memnew( PackedDir );
pd->name=ds[j];
pd->parent=cd;
cd->subdirs[pd->name]=pd;
cd=pd;
} else {
cd=cd->subdirs[ds[j]];
}
}
}
cd->files.insert(path.get_file());
}
}
void PackedData::add_pack_source(PackSource *p_source) {
sources.push_back(p_source);
};
PackedData *PackedData::singleton=NULL;
PackedData::PackedData() {
singleton=this;
root=memnew(PackedDir);
root->parent=NULL;
disabled=false;
add_pack_source(memnew(PackedSourcePCK));
}
//////////////////////////////////////////////////////////////////
bool PackedSourcePCK::try_open_pack(const String& p_path) {
FileAccess *f = FileAccess::open(p_path,FileAccess::READ);
if (!f)
return false;
uint32_t magic= f->get_32();
if (magic != 0x4b435047) {
//maybe at he end.... self contained exe
f->seek_end();
f->seek( f->get_pos() -4 );
magic = f->get_32();
if (magic != 0x4b435047) {
memdelete(f);
return false;
}
f->seek( f->get_pos() -12 );
uint64_t ds = f->get_64();
f->seek( f->get_pos() -ds-8 );
magic = f->get_32();
if (magic != 0x4b435047) {
memdelete(f);
return false;
}
}
uint32_t ver_major = f->get_32();
uint32_t ver_minor = f->get_32();
uint32_t ver_rev = f->get_32();
ERR_EXPLAIN("Pack created with a newer version of the engine: "+itos(ver_major)+"."+itos(ver_minor)+"."+itos(ver_rev));
ERR_FAIL_COND_V( ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR), ERR_INVALID_DATA);
for(int i=0;i<16;i++) {
//reserved
f->get_32();
}
int file_count = f->get_32();
for(int i=0;i<file_count;i++) {
uint32_t sl = f->get_32();
CharString cs;
cs.resize(sl+1);
f->get_buffer((uint8_t*)cs.ptr(),sl);
cs[sl]=0;
String path;
path.parse_utf8(cs.ptr());
uint64_t ofs = f->get_64();
uint64_t size = f->get_64();
PackedData::get_singleton()->add_path(p_path, path, ofs, size, this);
};
return true;
};
FileAccess* PackedSourcePCK::get_file(const String &p_path, PackedData::PackedFile* p_file) {
return memnew( FileAccessPack(p_path, *p_file));
};
//////////////////////////////////////////////////////////////////
Error FileAccessPack::_open(const String& p_path, int p_mode_flags) {
ERR_FAIL_V(ERR_UNAVAILABLE);
return ERR_UNAVAILABLE;
}
void FileAccessPack::close() {
f->close();
}
bool FileAccessPack::is_open() const{
return f->is_open();
}
void FileAccessPack::seek(size_t p_position){
if (p_position>pf.size) {
eof=true;
} else {
eof=false;
}
f->seek(pf.offset+p_position);
}
void FileAccessPack::seek_end(int64_t p_position){
seek(pf.size+p_position);
}
size_t FileAccessPack::get_pos() const {
return pos;
}
size_t FileAccessPack::get_len() const{
return pf.size;
}
bool FileAccessPack::eof_reached() const{
return eof;
}
uint8_t FileAccessPack::get_8() const {
if (pos>=pf.size) {
eof=true;
return 0;
}
pos++;
return f->get_8();
}
int FileAccessPack::get_buffer(uint8_t *p_dst,int p_length) const {
if (eof)
return 0;
int64_t to_read=p_length;
if (to_read+pos > pf.size) {
eof=true;
to_read=int64_t(pf.size)-int64_t(pos);
}
pos+=p_length;
if (to_read<=0)
return 0;
f->get_buffer(p_dst,to_read);
return to_read;
}
void FileAccessPack::set_endian_swap(bool p_swap) {
FileAccess::set_endian_swap(p_swap);
f->set_endian_swap(p_swap);
}
Error FileAccessPack::get_error() const {
if (eof)
return ERR_FILE_EOF;
return OK;
}
void FileAccessPack::store_8(uint8_t p_dest) {
ERR_FAIL();
}
void FileAccessPack::store_buffer(const uint8_t *p_src,int p_length) {
ERR_FAIL();
}
bool FileAccessPack::file_exists(const String& p_name) {
return false;
}
FileAccessPack::FileAccessPack(const String& p_path, const PackedData::PackedFile& p_file) {
pf=p_file;
f=FileAccess::open(pf.pack,FileAccess::READ);
if (!f) {
ERR_EXPLAIN("Can't open pack-referenced file: "+String(pf.pack));
ERR_FAIL_COND(!f);
}
f->seek(pf.offset);
pos=0;
eof=false;
}
FileAccessPack::~FileAccessPack() {
if (f)
memdelete(f);
}
//////////////////////////////////////////////////////////////////////////////////
// DIR ACCESS
//////////////////////////////////////////////////////////////////////////////////
bool DirAccessPack::list_dir_begin() {
list_dirs.clear();
list_files.clear();
for (Map<String,PackedData::PackedDir*>::Element *E=current->subdirs.front();E;E=E->next()) {
list_dirs.push_back(E->key());
}
for (Set<String>::Element *E=current->files.front();E;E=E->next()) {
list_files.push_back(E->get());
}
return true;
}
String DirAccessPack::get_next(){
if (list_dirs.size()) {
cdir=true;
String d = list_dirs.front()->get();
list_dirs.pop_front();
return d;
} else if (list_files.size()) {
cdir=false;
String f = list_files.front()->get();
list_files.pop_front();
return f;
} else {
return String();
}
}
bool DirAccessPack::current_is_dir() const{
return cdir;
}
void DirAccessPack::list_dir_end() {
list_dirs.clear();
list_files.clear();
}
int DirAccessPack::get_drive_count() {
return 0;
}
String DirAccessPack::get_drive(int p_drive) {
return "";
}
Error DirAccessPack::change_dir(String p_dir) {
String nd = p_dir.replace("\\","/");
bool absolute=false;
if (nd.begins_with("res://")) {
nd=nd.replace_first("res://","");
absolute=true;
}
nd=nd.simplify_path();
if (nd.begins_with("/")) {
nd=nd.replace_first("/","") ;
absolute=true;
}
Vector<String> paths = nd.split("/");
PackedData::PackedDir *pd;
if (absolute)
pd = PackedData::get_singleton()->root;
else
pd = current;
for(int i=0;i<paths.size();i++) {
String p = paths[i];
if (p==".") {
continue;
} else if (p=="..") {
if (pd->parent) {
pd=pd->parent;
}
} else if (pd->subdirs.has(p)) {
pd=pd->subdirs[p];
} else {
return ERR_INVALID_PARAMETER;
}
}
current=pd;
return OK;
}
String DirAccessPack::get_current_dir() {
String p;
PackedData::PackedDir *pd = current;
while(pd->parent) {
if (pd!=current)
p="/"+p;
p=p+pd->name;
}
return "res://"+p;
}
bool DirAccessPack::file_exists(String p_file){
return current->files.has(p_file);
}
Error DirAccessPack::make_dir(String p_dir){
return ERR_UNAVAILABLE;
}
Error DirAccessPack::rename(String p_from, String p_to){
return ERR_UNAVAILABLE;
}
Error DirAccessPack::remove(String p_name){
return ERR_UNAVAILABLE;
}
size_t DirAccessPack::get_space_left(){
return 0;
}
DirAccessPack::DirAccessPack() {
current=PackedData::get_singleton()->root;
cdir=false;
}
DirAccessPack::~DirAccessPack() {
}

204
core/io/file_access_pack.h Normal file
View file

@ -0,0 +1,204 @@
/*************************************************************************/
/* file_access_pack.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef FILE_ACCESS_PACK_H
#define FILE_ACCESS_PACK_H
#include "os/file_access.h"
#include "os/dir_access.h"
#include "map.h"
#include "list.h"
#include "print_string.h"
class PackSource;
class PackedData {
friend class FileAccessPack;
friend class DirAccessPack;
friend class PackSource;
public:
struct PackedFile {
String pack;
uint64_t offset;
uint64_t size;
PackSource* src;
};
private:
struct PackedDir {
PackedDir *parent;
String name;
Map<String,PackedDir*> subdirs;
Set<String> files;
};
Map<String,PackedFile> files;
Vector<PackSource*> sources;
PackedDir *root;
//Map<String,PackedDir*> dirs;
static PackedData *singleton;
bool disabled;
public:
void add_pack_source(PackSource* p_source);
void add_path(const String& pkg_path, const String& path, uint64_t ofs, uint64_t size, PackSource* p_src); // for PackSource
void set_disabled(bool p_disabled) { disabled=p_disabled; }
_FORCE_INLINE_ bool is_disabled() const { return disabled; }
static PackedData *get_singleton() { return singleton; }
Error add_pack(const String& p_path);
_FORCE_INLINE_ FileAccess *try_open_path(const String& p_path);
_FORCE_INLINE_ bool has_path(const String& p_path);
PackedData();
};
class PackSource {
public:
virtual bool try_open_pack(const String& p_path)=0;
virtual FileAccess* get_file(const String& p_path, PackedData::PackedFile* p_file)=0;
};
class PackedSourcePCK : public PackSource {
public:
virtual bool try_open_pack(const String &p_path);
virtual FileAccess* get_file(const String& p_path, PackedData::PackedFile* p_file);
};
class FileAccessPack : public FileAccess {
PackedData::PackedFile pf;
mutable size_t pos;
mutable bool eof;
FileAccess *f;
virtual Error _open(const String& p_path, int p_mode_flags);
virtual uint64_t _get_modified_time(const String& p_file) { return 0; }
public:
virtual void close();
virtual bool is_open() const;
virtual void seek(size_t p_position);
virtual void seek_end(int64_t p_position=0);
virtual size_t get_pos() const;
virtual size_t get_len() const;
virtual bool eof_reached() const;
virtual uint8_t get_8() const;
virtual int get_buffer(uint8_t *p_dst,int p_length) const;
virtual void set_endian_swap(bool p_swap);
virtual Error get_error() const;
virtual void store_8(uint8_t p_dest);
virtual void store_buffer(const uint8_t *p_src,int p_length);
virtual bool file_exists(const String& p_name);
FileAccessPack(const String& p_path, const PackedData::PackedFile& p_file);
~FileAccessPack();
};
FileAccess *PackedData::try_open_path(const String& p_path) {
if (files.has(p_path)) {
return files[p_path].src->get_file(p_path, &files[p_path]);
}
return NULL;
}
bool PackedData::has_path(const String& p_path) {
return files.has(p_path);
}
class DirAccessPack : public DirAccess {
PackedData::PackedDir *current;
List<String> list_dirs;
List<String> list_files;
bool cdir;
public:
virtual bool list_dir_begin();
virtual String get_next();
virtual bool current_is_dir() const;
virtual void list_dir_end();
virtual int get_drive_count();
virtual String get_drive(int p_drive);
virtual Error change_dir(String p_dir);
virtual String get_current_dir();
virtual bool file_exists(String p_file);
virtual Error make_dir(String p_dir);
virtual Error rename(String p_from, String p_to);
virtual Error remove(String p_name);
size_t get_space_left();
DirAccessPack();
~DirAccessPack();
};
#endif // FILE_ACCESS_PACK_H

367
core/io/file_access_zip.cpp Normal file
View file

@ -0,0 +1,367 @@
/*************************************************************************/
/* file_access_zip.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. */
/*************************************************************************/
#ifdef MINIZIP_ENABLED
#include "file_access_zip.h"
#include "core/os/file_access.h"
ZipArchive* ZipArchive::instance = NULL;
extern "C" {
static void* godot_open(void* data, const char* p_fname, int mode) {
if (mode & ZLIB_FILEFUNC_MODE_WRITE) {
return NULL;
};
FileAccess* f = (FileAccess*)data;
f->open(p_fname, FileAccess::READ);
return f->is_open()?data:NULL;
};
static uLong godot_read(void* data, void* fdata, void* buf, uLong size) {
FileAccess* f = (FileAccess*)data;
f->get_buffer((uint8_t*)buf, size);
return size;
};
static uLong godot_write(voidpf opaque, voidpf stream, const void* buf, uLong size) {
return 0;
};
static long godot_tell (voidpf opaque, voidpf stream) {
FileAccess* f = (FileAccess*)opaque;
return f->get_pos();
};
static long godot_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
FileAccess* f = (FileAccess*)opaque;
int pos = offset;
switch (origin) {
case ZLIB_FILEFUNC_SEEK_CUR:
pos = f->get_pos() + offset;
break;
case ZLIB_FILEFUNC_SEEK_END:
pos = f->get_len() + offset;
break;
default:
break;
};
f->seek(pos);
return 0;
};
static int godot_close(voidpf opaque, voidpf stream) {
FileAccess* f = (FileAccess*)opaque;
f->close();
return 0;
};
static int godot_testerror(voidpf opaque, voidpf stream) {
FileAccess* f = (FileAccess*)opaque;
return f->get_error()!=OK?1:0;
};
};
void ZipArchive::close_handle(unzFile p_file) const {
ERR_FAIL_COND(!p_file);
FileAccess* f = (FileAccess*)unzGetOpaque(p_file);
unzCloseCurrentFile(p_file);
unzClose(p_file);
memdelete(f);
};
unzFile ZipArchive::get_file_handle(String p_file) const {
ERR_FAIL_COND_V(!file_exists(p_file), NULL);
File file = files[p_file];
FileAccess* f = FileAccess::open(packages[file.package].filename, FileAccess::READ);
ERR_FAIL_COND_V(!f, NULL);
zlib_filefunc_def io;
io.opaque = f;
io.zopen_file = godot_open;
io.zread_file = godot_read;
io.zwrite_file = godot_write;
io.ztell_file = godot_tell;
io.zseek_file = godot_seek;
io.zclose_file = godot_close;
io.zerror_file = godot_testerror;
unzFile pkg = unzOpen2(packages[file.package].filename.utf8().get_data(), &io);
ERR_FAIL_COND_V(!pkg, NULL);
unzGoToFilePos(pkg, &file.file_pos);
if (unzOpenCurrentFile(pkg) != UNZ_OK) {
unzClose(pkg);
ERR_FAIL_V(NULL);
};
return pkg;
};
bool ZipArchive::try_open_pack(const String& p_name) {
printf("opening pack %ls, %i, %i\n", p_name.c_str(), p_name.extension().nocasecmp_to("zip"), p_name.extension().nocasecmp_to("pcz"));
if (p_name.extension().nocasecmp_to("zip") != 0 && p_name.extension().nocasecmp_to("pcz") != 0)
return false;
zlib_filefunc_def io;
FileAccess* f = FileAccess::open(p_name, FileAccess::READ);
if (!f)
return false;
io.opaque = f;
io.zopen_file = godot_open;
io.zread_file = godot_read;
io.zwrite_file = godot_write;
io.ztell_file = godot_tell;
io.zseek_file = godot_seek;
io.zclose_file = godot_close;
io.zerror_file = godot_testerror;
unzFile zfile = unzOpen2(p_name.utf8().get_data(), &io);
ERR_FAIL_COND_V(!zfile, false);
unz_global_info64 gi;
int err = unzGetGlobalInfo64(zfile, &gi);
ERR_FAIL_COND_V(err!=UNZ_OK, false);
Package pkg;
pkg.filename = p_name;
pkg.zfile = zfile;
packages.push_back(pkg);
int pkg_num = packages.size()-1;
for (unsigned int i=0;i<gi.number_entry;i++) {
char filename_inzip[256];
unz_file_info64 file_info;
err = unzGetCurrentFileInfo64(zfile,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
ERR_CONTINUE(err != UNZ_OK);
File f;
f.package = pkg_num;
unzGetFilePos(zfile, &f.file_pos);
String fname = String("res://") + filename_inzip;
files[fname] = f;
PackedData::get_singleton()->add_path(p_name, fname, 0, 0, this);
if ((i+1)<gi.number_entry) {
unzGoToNextFile(zfile);
};
};
return true;
};
bool ZipArchive::file_exists(String p_name) const {
return files.has(p_name);
};
FileAccess* ZipArchive::get_file(const String& p_path, PackedData::PackedFile* p_file) {
return memnew(FileAccessZip(p_path, *p_file));
};
ZipArchive* ZipArchive::get_singleton() {
if (instance == NULL) {
instance = memnew(ZipArchive);
};
return instance;
};
ZipArchive::ZipArchive() {
instance = this;
//fa_create_func = FileAccess::get_create_func();
};
ZipArchive::~ZipArchive() {
for (int i=0; i<packages.size(); i++) {
FileAccess* f = (FileAccess*)unzGetOpaque(packages[i].zfile);
unzClose(packages[i].zfile);
memdelete(f);
};
packages.clear();
};
Error FileAccessZip::_open(const String& p_path, int p_mode_flags) {
close();
ERR_FAIL_COND_V(p_mode_flags & FileAccess::WRITE, FAILED);
ZipArchive* arch = ZipArchive::get_singleton();
ERR_FAIL_COND_V(!arch, FAILED);
zfile = arch->get_file_handle(p_path);
ERR_FAIL_COND_V(!zfile, FAILED);
int err = unzGetCurrentFileInfo64(zfile,&file_info,NULL,0,NULL,0,NULL,0);
ERR_FAIL_COND_V(err != UNZ_OK, FAILED);
return OK;
};
void FileAccessZip::close() {
if (!zfile)
return;
ZipArchive* arch = ZipArchive::get_singleton();
ERR_FAIL_COND(!arch);
arch->close_handle(zfile);
zfile = NULL;
};
bool FileAccessZip::is_open() const {
return zfile != NULL;
};
void FileAccessZip::seek(size_t p_position) {
ERR_FAIL_COND(!zfile);
unzSeekCurrentFile(zfile, p_position);
};
void FileAccessZip::seek_end(int64_t p_position) {
ERR_FAIL_COND(!zfile);
unzSeekCurrentFile(zfile, get_len() + p_position);
};
size_t FileAccessZip::get_pos() const {
ERR_FAIL_COND_V(!zfile, 0);
return unztell(zfile);
};
size_t FileAccessZip::get_len() const {
ERR_FAIL_COND_V(!zfile, 0);
return file_info.uncompressed_size;
};
bool FileAccessZip::eof_reached() const {
ERR_FAIL_COND_V(!zfile, true);
return at_eof;
};
uint8_t FileAccessZip::get_8() const {
uint8_t ret = 0;
get_buffer(&ret, 1);
return ret;
};
int FileAccessZip::get_buffer(uint8_t *p_dst,int p_length) const {
ERR_FAIL_COND_V(!zfile, -1);
at_eof = unzeof(zfile);
if (at_eof)
return 0;
int read = unzReadCurrentFile(zfile, p_dst, p_length);
ERR_FAIL_COND_V(read < 0, read);
if (read < p_length)
at_eof = true;
return read;
};
Error FileAccessZip::get_error() const {
if (!zfile) {
return ERR_UNCONFIGURED;
};
if (eof_reached()) {
return ERR_FILE_EOF;
};
return OK;
};
void FileAccessZip::store_8(uint8_t p_dest) {
ERR_FAIL();
};
bool FileAccessZip::file_exists(const String& p_name) {
return false;
};
FileAccessZip::FileAccessZip(const String& p_path, const PackedData::PackedFile& p_file) {
zfile = NULL;
_open(p_path, FileAccess::READ);
};
FileAccessZip::~FileAccessZip() {
close();
};
#endif

125
core/io/file_access_zip.h Normal file
View file

@ -0,0 +1,125 @@
/*************************************************************************/
/* file_access_zip.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifdef MINIZIP_ENABLED
#ifndef FILE_ACCESS_Zip_H
#define FILE_ACCESS_Zip_H
#include <stdlib.h>
#include "core/io/file_access_pack.h"
#include "unzip.h"
#include "map.h"
class ZipArchive : public PackSource {
public:
struct File {
int package;
unz_file_pos file_pos;
File() {
package = -1;
};
};
private:
struct Package {
String filename;
unzFile zfile;
};
Vector<Package> packages;
Map<String,File> files;
static ZipArchive* instance;
FileAccess::CreateFunc fa_create_func;
public:
void close_handle(unzFile p_file) const;
unzFile get_file_handle(String p_file) const;
Error add_package(String p_name);
bool file_exists(String p_name) const;
virtual bool try_open_pack(const String& p_path);
FileAccess* get_file(const String& p_path, PackedData::PackedFile* p_file);
static ZipArchive* get_singleton();
ZipArchive();
~ZipArchive();
};
class FileAccessZip : public FileAccess {
unzFile zfile;
unz_file_info64 file_info;
mutable bool at_eof;
ZipArchive* archive;
public:
virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file
virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open
virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position=0); ///< seek from the end of file
virtual size_t get_pos() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
virtual uint8_t get_8() const; ///< get a byte
virtual int get_buffer(uint8_t *p_dst,int p_length) const;
virtual Error get_error() const; ///< get last error
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual bool file_exists(const String& p_name); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String& p_file) { return 0; } // todo
FileAccessZip(const String& p_path, const PackedData::PackedFile& p_file);
~FileAccessZip();
};
#endif // FILE_ACCESS_ZIP_H
#endif

641
core/io/http_client.cpp Normal file
View file

@ -0,0 +1,641 @@
/*************************************************************************/
/* http_client.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 "http_client.h"
Error HTTPClient::connect_url(const String& p_url) {
return OK;
}
Error HTTPClient::connect(const String &p_host,int p_port){
close();
conn_port=p_port;
conn_host=p_host;
if (conn_host.begins_with("http://")) {
conn_host=conn_host.replace_first("http://","");
} else if (conn_host.begins_with("https://")) {
//use https
conn_host=conn_host.replace_first("https://","");
}
connection=tcp_connection;
if (conn_host.is_valid_ip_address()) {
//is ip
Error err = tcp_connection->connect(IP_Address(conn_host),p_port);
if (err) {
status=STATUS_CANT_CONNECT;
return err;
}
status=STATUS_CONNECTING;
} else {
//is hostname
resolving=IP::get_singleton()->resolve_hostname_queue_item(conn_host);
status=STATUS_RESOLVING;
}
return OK;
}
void HTTPClient::set_connection(const Ref<StreamPeer>& p_connection){
close();
connection=p_connection;
}
Error HTTPClient::request( Method p_method, const String& p_url, const Vector<String>& p_headers,const String& p_body) {
ERR_FAIL_INDEX_V(p_method,METHOD_MAX,ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(status!=STATUS_CONNECTED,ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(connection.is_null(),ERR_INVALID_DATA);
static const char* _methods[METHOD_MAX]={
"GET",
"HEAD",
"POST",
"PUT",
"DELETE",
"OPTIONS",
"TRACE",
"CONNECT"};
String request=String(_methods[p_method])+" "+p_url+" HTTP/1.1\r\n";
request+="Host: "+conn_host+":"+itos(conn_port)+"\r\n";
for(int i=0;i<p_headers.size();i++) {
request+=p_headers[i]+"\r\n";
}
request+="\r\n";
request+=p_body;
CharString cs=request.utf8();
Error err = connection->put_data((const uint8_t*)cs.ptr(),cs.length());
if (err) {
close();
status=STATUS_CONNECTION_ERROR;
return err;
}
status=STATUS_REQUESTING;
return OK;
}
Error HTTPClient::send_body_text(const String& p_body){
return OK;
}
Error HTTPClient::send_body_data(const ByteArray& p_body){
return OK;
}
bool HTTPClient::has_response() const {
return response_headers.size()!=0;
}
bool HTTPClient::is_response_chunked() const {
return chunked;
}
int HTTPClient::get_response_code() const {
return response_num;
}
Error HTTPClient::get_response_headers(List<String> *r_response) {
if (!response_headers.size())
return ERR_INVALID_PARAMETER;
for(int i=0;i<response_headers.size();i++) {
r_response->push_back(response_headers[i]);
}
response_headers.clear();
return OK;
}
void HTTPClient::close(){
if (tcp_connection->get_status()!=StreamPeerTCP::STATUS_NONE)
tcp_connection->disconnect();
connection.unref();
status=STATUS_DISCONNECTED;
if (resolving!=IP::RESOLVER_INVALID_ID) {
IP::get_singleton()->erase_resolve_item(resolving);
resolving=IP::RESOLVER_INVALID_ID;
}
response_headers.clear();
response_str.clear();
body_size=0;
body_left=0;
chunk_left=0;
response_num=0;
}
Error HTTPClient::poll(){
switch(status) {
case STATUS_RESOLVING: {
ERR_FAIL_COND_V(resolving==IP::RESOLVER_INVALID_ID,ERR_BUG);
IP::ResolverStatus rstatus = IP::get_singleton()->get_resolve_item_status(resolving);
switch(rstatus) {
case IP::RESOLVER_STATUS_WAITING: return OK; //still resolving
case IP::RESOLVER_STATUS_DONE: {
IP_Address host = IP::get_singleton()->get_resolve_item_address(resolving);
Error err = tcp_connection->connect(host,conn_port);
IP::get_singleton()->erase_resolve_item(resolving);
resolving=IP::RESOLVER_INVALID_ID;
if (err) {
status=STATUS_CANT_CONNECT;
return err;
}
status=STATUS_CONNECTING;
} break;
case IP::RESOLVER_STATUS_NONE:
case IP::RESOLVER_STATUS_ERROR: {
IP::get_singleton()->erase_resolve_item(resolving);
resolving=IP::RESOLVER_INVALID_ID;
close();
status=STATUS_CANT_RESOLVE;
return ERR_CANT_RESOLVE;
} break;
}
} break;
case STATUS_CONNECTING: {
StreamPeerTCP::Status s = tcp_connection->get_status();
switch(s) {
case StreamPeerTCP::STATUS_CONNECTING: {
return OK; //do none
} break;
case StreamPeerTCP::STATUS_CONNECTED: {
status=STATUS_CONNECTED;
return OK;
} break;
case StreamPeerTCP::STATUS_ERROR:
case StreamPeerTCP::STATUS_NONE: {
close();
status=STATUS_CANT_CONNECT;
return ERR_CANT_CONNECT;
} break;
}
} break;
case STATUS_CONNECTED: {
//request something please
return OK;
} break;
case STATUS_REQUESTING: {
while(true) {
uint8_t byte;
int rec=0;
Error err = connection->get_partial_data(&byte,1,rec);
if (err!=OK) {
close();
status=STATUS_CONNECTION_ERROR;
return ERR_CONNECTION_ERROR;
}
if (rec==0)
return OK; //keep trying!
response_str.push_back(byte);
int rs = response_str.size();
if (
(rs>=2 && response_str[rs-2]=='\n' && response_str[rs-1]=='\n') ||
(rs>=4 && response_str[rs-4]=='\r' && response_str[rs-3]=='\n' && rs>=4 && response_str[rs-2]=='\r' && response_str[rs-1]=='\n')
) {
//end of response, parse.
response_str.push_back(0);
String response;
response.parse_utf8((const char*)response_str.ptr());
print_line("END OF RESPONSE? :\n"+response+"\n------");
Vector<String> responses = response.split("\n");
body_size=0;
chunked=false;
body_left=0;
chunk_left=0;
response_headers.clear();
response_num = RESPONSE_OK;
for(int i=0;i<responses.size();i++) {
String s = responses[i].strip_edges();
if (s.length()==0)
continue;
if (s.begins_with("Content-Length:")) {
body_size = s.substr(s.find(":")+1,s.length()).strip_edges().to_int();
body_left=body_size;
}
if (s.begins_with("Transfer-Encoding:")) {
String encoding = s.substr(s.find(":")+1,s.length()).strip_edges();
print_line("TRANSFER ENCODING: "+encoding);
if (encoding=="chunked") {
chunked=true;
}
}
if (i==0 && responses[i].begins_with("HTTP")) {
String num = responses[i].get_slice(" ",1);
response_num=num.to_int();
} else {
response_headers.push_back(s);
}
}
if (body_size==0 && !chunked) {
status=STATUS_CONNECTED; //ask for something again?
} else {
status=STATUS_BODY;
}
return OK;
}
}
//wait for response
return OK;
} break;
case STATUS_DISCONNECTED: {
return ERR_UNCONFIGURED;
} break;
case STATUS_CONNECTION_ERROR: {
return ERR_CONNECTION_ERROR;
} break;
case STATUS_CANT_CONNECT: {
return ERR_CANT_CONNECT;
} break;
case STATUS_CANT_RESOLVE: {
return ERR_CANT_RESOLVE;
} break;
}
return OK;
}
Dictionary HTTPClient::_get_response_headers_as_dictionary() {
List<String> rh;
get_response_headers(&rh);
Dictionary ret;
for(const List<String>::Element *E=rh.front();E;E=E->next()) {
String s = E->get();
int sp = s.find(":");
if (sp==-1)
continue;
String key = s.substr(0,sp).strip_edges();
String value = s.substr(sp+1,s.length()).strip_edges();
ret[key]=value;
}
return ret;
}
StringArray HTTPClient::_get_response_headers() {
List<String> rh;
get_response_headers(&rh);
StringArray ret;
ret.resize(rh.size());
int idx=0;
for(const List<String>::Element *E=rh.front();E;E=E->next()) {
ret.set(idx++,E->get());
}
return ret;
}
int HTTPClient::get_response_body_length() const {
return body_size;
}
ByteArray HTTPClient::read_response_body_chunk() {
ERR_FAIL_COND_V( status !=STATUS_BODY, ByteArray() );
Error err=OK;
if (chunked) {
while(true) {
if (chunk_left==0) {
//reading len
uint8_t b;
int rec=0;
err = connection->get_partial_data(&b,1,rec);
if (rec==0)
break;
chunk.push_back(b);
if (chunk.size()>32) {
ERR_PRINT("HTTP Invalid chunk hex len");
status=STATUS_CONNECTION_ERROR;
return ByteArray();
}
if (chunk.size()>2 && chunk[chunk.size()-2]=='\r' && chunk[chunk.size()-1]=='\n') {
int len=0;
for(int i=0;i<chunk.size()-2;i++) {
char c = chunk[i];
int v=0;
if (c>='0' && c<='9')
v=c-'0';
else if (c>='a' && c<='f')
v=c-'a'+10;
else if (c>='A' && c<='F')
v=c-'A'+10;
else {
ERR_PRINT("HTTP Chunk len not in hex!!");
status=STATUS_CONNECTION_ERROR;
return ByteArray();
}
len<<=4;
len|=v;
if (len>(1<<24)) {
ERR_PRINT("HTTP Chunk too big!! >16mb");
status=STATUS_CONNECTION_ERROR;
return ByteArray();
}
}
if (len==0) {
//end!
status=STATUS_CONNECTED;
chunk.clear();
return ByteArray();
}
chunk_left=len+2;
chunk.resize(chunk_left);
}
} else {
int rec=0;
err = connection->get_partial_data(&chunk[chunk.size()-chunk_left],chunk_left,rec);
if (rec==0) {
break;
}
chunk_left-=rec;
if (chunk_left==0) {
if (chunk[chunk.size()-2]!='\r' || chunk[chunk.size()-1]!='\n') {
ERR_PRINT("HTTP Invalid chunk terminator (not \\r\\n)");
status=STATUS_CONNECTION_ERROR;
return ByteArray();
}
ByteArray ret;
ret.resize(chunk.size()-2);
{
ByteArray::Write w = ret.write();
copymem(w.ptr(),chunk.ptr(),chunk.size()-2);
}
chunk.clear();
return ret;
}
break;
}
}
} else {
ByteArray::Write r = tmp_read.write();
int rec=0;
err = connection->get_partial_data(r.ptr(),MIN(body_left,tmp_read.size()),rec);
if (rec>0) {
ByteArray ret;
ret.resize(rec);
ByteArray::Write w = ret.write();
copymem(w.ptr(),r.ptr(),rec);
body_left-=rec;
if (body_left==0) {
status=STATUS_CONNECTED;
}
return ret;
}
}
if (err!=OK) {
close();
if (err==ERR_FILE_EOF) {
status=STATUS_DISCONNECTED; //server disconnected
} else {
status=STATUS_CONNECTION_ERROR;
}
} else if (body_left==0 && !chunked) {
status=STATUS_CONNECTED;
}
return ByteArray();
}
HTTPClient::Status HTTPClient::get_status() const {
return status;
}
void HTTPClient::_bind_methods() {
ObjectTypeDB::bind_method(_MD("connect:Error","host","port"),&HTTPClient::connect);
ObjectTypeDB::bind_method(_MD("set_connection","connection:StreamPeer"),&HTTPClient::set_connection);
ObjectTypeDB::bind_method(_MD("request","method","url","headers","body"),&HTTPClient::request,DEFVAL(String()));
ObjectTypeDB::bind_method(_MD("send_body_text","body"),&HTTPClient::send_body_text);
ObjectTypeDB::bind_method(_MD("send_body_data","body"),&HTTPClient::send_body_data);
ObjectTypeDB::bind_method(_MD("close"),&HTTPClient::close);
ObjectTypeDB::bind_method(_MD("has_response"),&HTTPClient::has_response);
ObjectTypeDB::bind_method(_MD("is_response_chunked"),&HTTPClient::is_response_chunked);
ObjectTypeDB::bind_method(_MD("get_response_code"),&HTTPClient::get_response_code);
ObjectTypeDB::bind_method(_MD("get_response_headers"),&HTTPClient::_get_response_headers);
ObjectTypeDB::bind_method(_MD("get_response_headers_as_dictionary"),&HTTPClient::_get_response_headers_as_dictionary);
ObjectTypeDB::bind_method(_MD("get_response_body_length"),&HTTPClient::get_response_body_length);
ObjectTypeDB::bind_method(_MD("read_response_body_chunk"),&HTTPClient::read_response_body_chunk);
ObjectTypeDB::bind_method(_MD("get_status"),&HTTPClient::get_status);
ObjectTypeDB::bind_method(_MD("poll:Error"),&HTTPClient::poll);
BIND_CONSTANT( METHOD_GET );
BIND_CONSTANT( METHOD_HEAD );
BIND_CONSTANT( METHOD_POST );
BIND_CONSTANT( METHOD_PUT );
BIND_CONSTANT( METHOD_DELETE );
BIND_CONSTANT( METHOD_OPTIONS );
BIND_CONSTANT( METHOD_TRACE );
BIND_CONSTANT( METHOD_CONNECT );
BIND_CONSTANT( METHOD_MAX );
BIND_CONSTANT( STATUS_DISCONNECTED );
BIND_CONSTANT( STATUS_RESOLVING ); //resolving hostname (if passed a hostname)
BIND_CONSTANT( STATUS_CANT_RESOLVE );
BIND_CONSTANT( STATUS_CONNECTING ); //connecting to ip
BIND_CONSTANT( STATUS_CANT_CONNECT );
BIND_CONSTANT( STATUS_CONNECTED ); //connected ); requests only accepted here
BIND_CONSTANT( STATUS_REQUESTING ); // request in progress
BIND_CONSTANT( STATUS_BODY ); // request resulted in body ); which must be read
BIND_CONSTANT( STATUS_CONNECTION_ERROR );
BIND_CONSTANT( RESPONSE_CONTINUE );
BIND_CONSTANT( RESPONSE_SWITCHING_PROTOCOLS );
BIND_CONSTANT( RESPONSE_PROCESSING );
// 2xx successful
BIND_CONSTANT( RESPONSE_OK );
BIND_CONSTANT( RESPONSE_CREATED );
BIND_CONSTANT( RESPONSE_ACCEPTED );
BIND_CONSTANT( RESPONSE_NON_AUTHORITATIVE_INFORMATION );
BIND_CONSTANT( RESPONSE_NO_CONTENT );
BIND_CONSTANT( RESPONSE_RESET_CONTENT );
BIND_CONSTANT( RESPONSE_PARTIAL_CONTENT );
BIND_CONSTANT( RESPONSE_MULTI_STATUS );
BIND_CONSTANT( RESPONSE_IM_USED );
// 3xx redirection
BIND_CONSTANT( RESPONSE_MULTIPLE_CHOICES );
BIND_CONSTANT( RESPONSE_MOVED_PERMANENTLY );
BIND_CONSTANT( RESPONSE_FOUND );
BIND_CONSTANT( RESPONSE_SEE_OTHER );
BIND_CONSTANT( RESPONSE_NOT_MODIFIED );
BIND_CONSTANT( RESPONSE_USE_PROXY );
BIND_CONSTANT( RESPONSE_TEMPORARY_REDIRECT );
// 4xx client error
BIND_CONSTANT( RESPONSE_BAD_REQUEST );
BIND_CONSTANT( RESPONSE_UNAUTHORIZED );
BIND_CONSTANT( RESPONSE_PAYMENT_REQUIRED );
BIND_CONSTANT( RESPONSE_FORBIDDEN );
BIND_CONSTANT( RESPONSE_NOT_FOUND );
BIND_CONSTANT( RESPONSE_METHOD_NOT_ALLOWED );
BIND_CONSTANT( RESPONSE_NOT_ACCEPTABLE );
BIND_CONSTANT( RESPONSE_PROXY_AUTHENTICATION_REQUIRED );
BIND_CONSTANT( RESPONSE_REQUEST_TIMEOUT );
BIND_CONSTANT( RESPONSE_CONFLICT );
BIND_CONSTANT( RESPONSE_GONE );
BIND_CONSTANT( RESPONSE_LENGTH_REQUIRED );
BIND_CONSTANT( RESPONSE_PRECONDITION_FAILED );
BIND_CONSTANT( RESPONSE_REQUEST_ENTITY_TOO_LARGE );
BIND_CONSTANT( RESPONSE_REQUEST_URI_TOO_LONG );
BIND_CONSTANT( RESPONSE_UNSUPPORTED_MEDIA_TYPE );
BIND_CONSTANT( RESPONSE_REQUESTED_RANGE_NOT_SATISFIABLE );
BIND_CONSTANT( RESPONSE_EXPECTATION_FAILED );
BIND_CONSTANT( RESPONSE_UNPROCESSABLE_ENTITY );
BIND_CONSTANT( RESPONSE_LOCKED );
BIND_CONSTANT( RESPONSE_FAILED_DEPENDENCY );
BIND_CONSTANT( RESPONSE_UPGRADE_REQUIRED );
// 5xx server error
BIND_CONSTANT( RESPONSE_INTERNAL_SERVER_ERROR );
BIND_CONSTANT( RESPONSE_NOT_IMPLEMENTED );
BIND_CONSTANT( RESPONSE_BAD_GATEWAY );
BIND_CONSTANT( RESPONSE_SERVICE_UNAVAILABLE );
BIND_CONSTANT( RESPONSE_GATEWAY_TIMEOUT );
BIND_CONSTANT( RESPONSE_HTTP_VERSION_NOT_SUPPORTED );
BIND_CONSTANT( RESPONSE_INSUFFICIENT_STORAGE );
BIND_CONSTANT( RESPONSE_NOT_EXTENDED );
}
HTTPClient::HTTPClient(){
tcp_connection = StreamPeerTCP::create();
resolving = IP::RESOLVER_INVALID_ID;
status=STATUS_DISCONNECTED;
conn_port=80;
body_size=0;
chunked=false;
body_left=0;
chunk_left=0;
response_num=0;
tmp_read.resize(4096);
}
HTTPClient::~HTTPClient(){
}

Some files were not shown because too many files have changed in this diff Show more