summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConstruct4
-rw-r--r--bin/tests/test_gui.cpp12
-rw-r--r--core/bind/core_bind.cpp10
-rw-r--r--core/event_queue.cpp18
-rw-r--r--core/image.cpp12
-rw-r--r--core/image.h1
-rw-r--r--core/object.cpp7
-rw-r--r--core/object.h4
-rw-r--r--demos/2d/isometric_light/export.cfg262
-rw-r--r--demos/2d/light_mask/burano.pngbin0 -> 974437 bytes
-rw-r--r--demos/2d/light_mask/engine.cfg8
-rw-r--r--demos/2d/light_mask/lightmask.scnbin0 -> 2916 bytes
-rw-r--r--demos/2d/light_mask/splat.pngbin0 -> 18255 bytes
-rw-r--r--demos/2d/lights_shadows/light_shadows.scnbin4293 -> 4293 bytes
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp136
-rw-r--r--drivers/gles2/rasterizer_gles2.h1
-rw-r--r--drivers/gles2/shader_compiler_gles2.cpp8
-rw-r--r--drivers/gles2/shader_compiler_gles2.h3
-rw-r--r--drivers/gles2/shaders/canvas.glsl78
-rw-r--r--drivers/pvr/AlphaBitmap.h18
-rw-r--r--drivers/pvr/BitScale.cpp184
-rw-r--r--drivers/pvr/BitScale.h28
-rw-r--r--drivers/pvr/BitUtility.h19
-rw-r--r--drivers/pvr/Bitmap.h34
-rw-r--r--drivers/pvr/ColorRgba.h152
-rw-r--r--drivers/pvr/Interval.h21
-rw-r--r--drivers/pvr/MortonTable.cpp43
-rw-r--r--drivers/pvr/MortonTable.h18
-rw-r--r--drivers/pvr/Point2.h17
-rw-r--r--drivers/pvr/PvrTcDecoder.cpp144
-rw-r--r--drivers/pvr/PvrTcDecoder.h25
-rw-r--r--drivers/pvr/PvrTcEncoder.cpp474
-rw-r--r--drivers/pvr/PvrTcEncoder.h40
-rw-r--r--drivers/pvr/PvrTcPacket.cpp209
-rw-r--r--drivers/pvr/PvrTcPacket.h65
-rw-r--r--drivers/pvr/RgbBitmap.h23
-rw-r--r--drivers/pvr/RgbaBitmap.h23
-rw-r--r--drivers/pvr/SCsub6
-rw-r--r--drivers/pvr/texture_loader_pvr.cpp51
-rw-r--r--modules/gdscript/gd_functions.cpp2
-rw-r--r--modules/gdscript/gd_script.cpp2
-rw-r--r--platform/android/detect.py2
-rw-r--r--platform/android/export/export.cpp13
-rw-r--r--platform/android/java/src/com/android/godot/Godot.java28
-rw-r--r--platform/android/java/src/com/android/godot/GodotView.java18
-rw-r--r--platform/android/libs/downloader_library/gen/com/android/vending/expansion/downloader/BuildConfig.java2
-rw-r--r--platform/javascript/os_javascript.cpp6
-rw-r--r--platform/javascript/os_javascript.h1
-rw-r--r--platform/osx/os_osx.h32
-rw-r--r--platform/osx/os_osx.mm158
-rw-r--r--platform/server/os_server.cpp7
-rw-r--r--platform/server/os_server.h2
-rw-r--r--scene/2d/canvas_item.cpp33
-rw-r--r--scene/2d/canvas_item.h15
-rw-r--r--scene/2d/light_2d.cpp42
-rw-r--r--scene/2d/light_2d.h18
-rw-r--r--scene/2d/physics_body_2d.cpp2
-rw-r--r--scene/2d/visibility_notifier_2d.cpp7
-rw-r--r--scene/3d/navigation.cpp6
-rw-r--r--scene/3d/navigation.h2
-rw-r--r--scene/gui/control.cpp2
-rw-r--r--scene/main/scene_main_loop.cpp1
-rw-r--r--scene/main/viewport.cpp2
-rw-r--r--scene/resources/shader_graph.cpp15
-rw-r--r--scene/scene_string_names.cpp1
-rw-r--r--scene/scene_string_names.h1
-rw-r--r--servers/visual/rasterizer.h10
-rw-r--r--servers/visual/rasterizer_dummy.cpp32
-rw-r--r--servers/visual/rasterizer_dummy.h10
-rw-r--r--servers/visual/shader_language.cpp2
-rw-r--r--servers/visual/visual_server_raster.cpp19
-rw-r--r--servers/visual/visual_server_raster.h8
-rw-r--r--servers/visual/visual_server_wrap_mt.h7
-rw-r--r--servers/visual_server.h19
-rw-r--r--tools/editor/editor_help.cpp4
-rw-r--r--tools/editor/plugins/mesh_editor_plugin.cpp5
-rw-r--r--tools/editor/plugins/shader_graph_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/sprite_frames_editor_plugin.cpp37
-rw-r--r--tools/editor/plugins/sprite_frames_editor_plugin.h2
-rw-r--r--tools/editor/pvrtc_compress.cpp28
-rw-r--r--tools/editor/scene_tree_dock.cpp9
-rw-r--r--tools/export/blender25/io_scene_dae/export_dae.py39
-rw-r--r--version.py4
83 files changed, 2358 insertions, 457 deletions
diff --git a/SConstruct b/SConstruct
index 2dc9fa1e70..922dc64fe3 100644
--- a/SConstruct
+++ b/SConstruct
@@ -121,6 +121,7 @@ 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('colored', 'Enable colored output for the compilation (yes/no)', 'no')
+opts.Add('extra_suffix', 'Custom extra suffix added to the base filename of all generated binary files.', '')
# add platform specific options
@@ -176,6 +177,9 @@ if selected_platform in platform_list:
env = env_base.Clone()
env.extra_suffix=""
+
+ if env["extra_suffix"] != '' :
+ env.extra_suffix += '.'+env["extra_suffix"]
CCFLAGS = env.get('CCFLAGS', '')
env['CCFLAGS'] = ''
diff --git a/bin/tests/test_gui.cpp b/bin/tests/test_gui.cpp
index 17a6a4111c..70cff12c44 100644
--- a/bin/tests/test_gui.cpp
+++ b/bin/tests/test_gui.cpp
@@ -132,7 +132,7 @@ public:
frame->add_child( button );
-#if 0
+
Sprite *tf = memnew( Sprite );
frame->add_child(tf);
Image img;
@@ -140,14 +140,14 @@ public:
img.resize(512,512);
img.generate_mipmaps();
- img.compress();
- Ref<Texture> text = memnew( Texture );
- text->create_from_image(img);
- tf->set_texture(text);
+ img.compress(Image::COMPRESS_PVRTC4);
+ Ref<ImageTexture> tt = memnew( ImageTexture );
+ tt->create_from_image(img);
+ tf->set_texture(tt);
tf->set_pos(Point2(50,50));
//tf->set_scale(Point2(0.3,0.3));
-
+#if 0
return;
#endif
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 5839467388..439855fbb7 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -709,13 +709,13 @@ void _OS::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_screen_count"),&_OS::get_screen_count);
ObjectTypeDB::bind_method(_MD("get_current_screen"),&_OS::get_current_screen);
- ObjectTypeDB::bind_method(_MD("set_current_screen"),&_OS::set_current_screen);
- ObjectTypeDB::bind_method(_MD("get_screen_position"),&_OS::get_screen_position,DEFVAL(0));
- ObjectTypeDB::bind_method(_MD("get_screen_size"),&_OS::get_screen_size,DEFVAL(0));
+ ObjectTypeDB::bind_method(_MD("set_current_screen","screen"),&_OS::set_current_screen);
+ ObjectTypeDB::bind_method(_MD("get_screen_position","screen"),&_OS::get_screen_position,DEFVAL(0));
+ ObjectTypeDB::bind_method(_MD("get_screen_size","screen"),&_OS::get_screen_size,DEFVAL(0));
ObjectTypeDB::bind_method(_MD("get_window_position"),&_OS::get_window_position);
- ObjectTypeDB::bind_method(_MD("set_window_position"),&_OS::set_window_position);
+ ObjectTypeDB::bind_method(_MD("set_window_position","position"),&_OS::set_window_position);
ObjectTypeDB::bind_method(_MD("get_window_size"),&_OS::get_window_size);
- ObjectTypeDB::bind_method(_MD("set_window_size"),&_OS::set_window_size);
+ ObjectTypeDB::bind_method(_MD("set_window_size","size"),&_OS::set_window_size);
ObjectTypeDB::bind_method(_MD("set_window_fullscreen","enabled"),&_OS::set_window_fullscreen);
ObjectTypeDB::bind_method(_MD("is_window_fullscreen"),&_OS::is_window_fullscreen);
ObjectTypeDB::bind_method(_MD("set_window_resizable","enabled"),&_OS::set_window_resizable);
diff --git a/core/event_queue.cpp b/core/event_queue.cpp
index cf6e742f79..161fb4fedd 100644
--- a/core/event_queue.cpp
+++ b/core/event_queue.cpp
@@ -56,28 +56,36 @@ Error EventQueue::push_call(uint32_t p_instance_ID, const StringName& p_method,
buffer_end+=sizeof(Event);
- if (args==1) {
+ if (args>=1) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
buffer_end+=sizeof(Variant);
*v=p_arg1;
- } else if (args==2) {
+ }
+
+ if (args>=2) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
buffer_end+=sizeof(Variant);
*v=p_arg2;
- } else if (args==3) {
+ }
+
+ if (args>=3) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
buffer_end+=sizeof(Variant);
*v=p_arg3;
- } else if (args==4) {
+ }
+
+ if (args>=4) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
buffer_end+=sizeof(Variant);
*v=p_arg4;
- } else if (args==5) {
+ }
+
+ if (args>=5) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
buffer_end+=sizeof(Variant);
diff --git a/core/image.cpp b/core/image.cpp
index 17ee569b6b..ea09787f01 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -134,6 +134,18 @@ void Image::get_mipmap_offset_and_size(int p_mipmap,int &r_ofs, int &r_size) con
}
+void Image::get_mipmap_offset_size_and_dimensions(int p_mipmap,int &r_ofs, int &r_size,int &w, int& h) const {
+
+
+ int ofs;
+ _get_mipmap_offset_and_size(p_mipmap,ofs,w,h);
+ int ofs2,w2,h2;
+ _get_mipmap_offset_and_size(p_mipmap+1,ofs2,w2,h2);
+ r_ofs=ofs;
+ r_size=ofs2-ofs;
+
+}
+
void Image::put_pixel(int p_x,int p_y, const Color& p_color,int p_mipmap){
ERR_FAIL_INDEX(p_mipmap,mipmaps+1);
diff --git a/core/image.h b/core/image.h
index f4c96703b9..8ef7a54c78 100644
--- a/core/image.h
+++ b/core/image.h
@@ -236,6 +236,7 @@ public:
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
+ void get_mipmap_offset_size_and_dimensions(int p_mipmap,int &r_ofs, int &r_size,int &w, int& h) const; //get where the mipmap begins in data
/**
* Resize the image, using the prefered interpolation method.
diff --git a/core/object.cpp b/core/object.cpp
index 2b83f728d1..f71521a0ff 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -1503,6 +1503,8 @@ void Object::_bind_methods() {
ObjectTypeDB::bind_method(_MD("XL_MESSAGE","message"),&Object::XL_MESSAGE);
ObjectTypeDB::bind_method(_MD("tr","message"),&Object::tr);
+ ObjectTypeDB::bind_method(_MD("is_queued_for_deletion"),&Object::is_queued_for_deletion);
+
ADD_SIGNAL( MethodInfo("script_changed"));
BIND_VMETHOD( MethodInfo("_notification",PropertyInfo(Variant::INT,"what")) );
@@ -1566,6 +1568,10 @@ void Object::get_translatable_strings(List<String> *p_strings) const {
}
+bool Object::is_queued_for_deletion() const {
+ return _is_queued_for_deletion;
+}
+
#ifdef TOOLS_ENABLED
void Object::set_edited(bool p_edited) {
@@ -1587,6 +1593,7 @@ Object::Object() {
_instance_ID=0;
_instance_ID = ObjectDB::add_instance(this);
_can_translate=true;
+ _is_queued_for_deletion=false;
script_instance=NULL;
#ifdef TOOLS_ENABLED
diff --git a/core/object.h b/core/object.h
index eb885f5d20..0bd3d09c21 100644
--- a/core/object.h
+++ b/core/object.h
@@ -397,7 +397,6 @@ friend void postinitialize_handler(Object*);
protected:
-
virtual bool _use_builtin_script() const { return false; }
virtual void _initialize_typev() { initialize_type(); }
virtual bool _setv(const StringName& p_name,const Variant &p_property) { return false; };
@@ -589,6 +588,9 @@ public:
StringName XL_MESSAGE(const StringName& p_message) const; //translate message (internationalization)
StringName tr(const StringName& p_message) const; //translate message (alternative)
+ bool _is_queued_for_deletion; // set to true by SceneTree::queue_delete()
+ bool is_queued_for_deletion() const;
+
_FORCE_INLINE_ void set_message_translation(bool p_enable) { _can_translate=p_enable; }
_FORCE_INLINE_ bool can_translate_messages() const { return _can_translate; }
Object();
diff --git a/demos/2d/isometric_light/export.cfg b/demos/2d/isometric_light/export.cfg
deleted file mode 100644
index 578d4171b2..0000000000
--- a/demos/2d/isometric_light/export.cfg
+++ /dev/null
@@ -1,262 +0,0 @@
-[convert_images]
-
-action="none"
-compress_quality=0.7
-formats="png"
-shrink=1
-
-[export_filter]
-
-filter=""
-type="resources"
-
-[image_group_files]
-
-files=["res://faceNormal.png", "normal", "res://faceColor.png", "normal", "res://faceMask.png", "normal"]
-
-[image_groups]
-
-normal={"atlas":false, "action":"compress_ram", "shrink":1, "lossy_quality":0.7}
-
-[platform:Android]
-
-apk_expansion/SALT=""
-apk_expansion/enable=false
-apk_expansion/public_key=""
-command_line/extra_args=""
-custom_package/debug=""
-custom_package/release=""
-keystore/release=""
-keystore/release_password=""
-keystore/release_user=""
-one_click_deploy/clear_previous_install=true
-package/icon=""
-package/name=""
-package/signed=true
-package/unique_name="com.android.noname"
-permissions/access_checkin_properties=false
-permissions/access_coarse_location=false
-permissions/access_fine_location=false
-permissions/access_location_extra_commands=false
-permissions/access_mock_location=false
-permissions/access_network_state=false
-permissions/access_surface_flinger=false
-permissions/access_wifi_state=false
-permissions/account_manager=false
-permissions/add_voicemail=false
-permissions/authenticate_accounts=false
-permissions/battery_stats=false
-permissions/bind_accessibility_service=false
-permissions/bind_appwidget=false
-permissions/bind_device_admin=false
-permissions/bind_input_method=false
-permissions/bind_nfc_service=false
-permissions/bind_notification_listener_service=false
-permissions/bind_print_service=false
-permissions/bind_remoteviews=false
-permissions/bind_text_service=false
-permissions/bind_vpn_service=false
-permissions/bind_wallpaper=false
-permissions/bluetooth=false
-permissions/bluetooth_admin=false
-permissions/bluetooth_privileged=false
-permissions/brick=false
-permissions/broadcast_package_removed=false
-permissions/broadcast_sms=false
-permissions/broadcast_sticky=false
-permissions/broadcast_wap_push=false
-permissions/call_phone=false
-permissions/call_privileged=false
-permissions/camera=false
-permissions/capture_audio_output=false
-permissions/capture_secure_video_output=false
-permissions/capture_video_output=false
-permissions/change_component_enabled_state=false
-permissions/change_configuration=false
-permissions/change_network_state=false
-permissions/change_wifi_multicast_state=false
-permissions/change_wifi_state=false
-permissions/clear_app_cache=false
-permissions/clear_app_user_data=false
-permissions/control_location_updates=false
-permissions/delete_cache_files=false
-permissions/delete_packages=false
-permissions/device_power=false
-permissions/diagnostic=false
-permissions/disable_keyguard=false
-permissions/dump=false
-permissions/expand_status_bar=false
-permissions/factory_test=false
-permissions/flashlight=false
-permissions/force_back=false
-permissions/get_accounts=false
-permissions/get_package_size=false
-permissions/get_tasks=false
-permissions/get_top_activity_info=false
-permissions/global_search=false
-permissions/hardware_test=false
-permissions/inject_events=false
-permissions/install_location_provider=false
-permissions/install_packages=false
-permissions/install_shortcut=false
-permissions/internal_system_window=false
-permissions/internet=false
-permissions/kill_background_processes=false
-permissions/location_hardware=false
-permissions/manage_accounts=false
-permissions/manage_app_tokens=false
-permissions/manage_documents=false
-permissions/master_clear=false
-permissions/media_content_control=false
-permissions/modify_audio_settings=false
-permissions/modify_phone_state=false
-permissions/mount_format_filesystems=false
-permissions/mount_unmount_filesystems=false
-permissions/nfc=false
-permissions/persistent_activity=false
-permissions/process_outgoing_calls=false
-permissions/read_calendar=false
-permissions/read_call_log=false
-permissions/read_contacts=false
-permissions/read_external_storage=false
-permissions/read_frame_buffer=false
-permissions/read_history_bookmarks=false
-permissions/read_input_state=false
-permissions/read_logs=false
-permissions/read_phone_state=false
-permissions/read_profile=false
-permissions/read_sms=false
-permissions/read_social_stream=false
-permissions/read_sync_settings=false
-permissions/read_sync_stats=false
-permissions/read_user_dictionary=false
-permissions/reboot=false
-permissions/receive_boot_completed=false
-permissions/receive_mms=false
-permissions/receive_sms=false
-permissions/receive_wap_push=false
-permissions/record_audio=false
-permissions/reorder_tasks=false
-permissions/restart_packages=false
-permissions/send_respond_via_message=false
-permissions/send_sms=false
-permissions/set_activity_watcher=false
-permissions/set_alarm=false
-permissions/set_always_finish=false
-permissions/set_animation_scale=false
-permissions/set_debug_app=false
-permissions/set_orientation=false
-permissions/set_pointer_speed=false
-permissions/set_preferred_applications=false
-permissions/set_process_limit=false
-permissions/set_time=false
-permissions/set_time_zone=false
-permissions/set_wallpaper=false
-permissions/set_wallpaper_hints=false
-permissions/signal_persistent_processes=false
-permissions/status_bar=false
-permissions/subscribed_feeds_read=false
-permissions/subscribed_feeds_write=false
-permissions/system_alert_window=false
-permissions/transmit_ir=false
-permissions/uninstall_shortcut=false
-permissions/update_device_stats=false
-permissions/use_credentials=false
-permissions/use_sip=false
-permissions/vibrate=false
-permissions/wake_lock=false
-permissions/write_apn_settings=false
-permissions/write_calendar=false
-permissions/write_call_log=false
-permissions/write_contacts=false
-permissions/write_external_storage=false
-permissions/write_gservices=false
-permissions/write_history_bookmarks=false
-permissions/write_profile=false
-permissions/write_secure_settings=false
-permissions/write_settings=false
-permissions/write_sms=false
-permissions/write_social_stream=false
-permissions/write_sync_settings=false
-permissions/write_user_dictionary=false
-screen/orientation=0
-screen/support_large=true
-screen/support_normal=true
-screen/support_small=true
-screen/support_xlarge=true
-user_permissions/0=""
-user_permissions/1=""
-user_permissions/10=""
-user_permissions/11=""
-user_permissions/12=""
-user_permissions/13=""
-user_permissions/14=""
-user_permissions/15=""
-user_permissions/16=""
-user_permissions/17=""
-user_permissions/18=""
-user_permissions/19=""
-user_permissions/2=""
-user_permissions/3=""
-user_permissions/4=""
-user_permissions/5=""
-user_permissions/6=""
-user_permissions/7=""
-user_permissions/8=""
-user_permissions/9=""
-version/code=1
-version/name="1.0"
-
-[platform:BlackBerry 10]
-
-package/category="core.games"
-package/custom_template=""
-package/description="Game made with Godot Engine"
-package/icon=""
-package/name=""
-package/unique_name="com.godot.noname"
-release/author="Cert. Name"
-release/author_id="Cert. ID"
-version/code=1
-version/name="1.0"
-
-[platform:HTML5]
-
-browser/enable_run=false
-custom_package/debug=""
-custom_package/release=""
-options/memory_size=3
-
-[platform:Linux X11]
-
-binary/64_bits=true
-custom_binary/debug=""
-custom_binary/release=""
-resources/pack_mode=1
-
-[platform:Mac OSX]
-
-application/64_bits=false
-application/copyright=""
-application/icon=""
-application/identifier="com.godot.macgame"
-application/info="This Game is Nice"
-application/name=""
-application/short_version="1.0"
-application/signature="godotmacgame"
-application/version="1.0"
-custom_package/debug=""
-custom_package/release=""
-display/high_res=false
-
-[platform:Windows Desktop]
-
-binary/64_bits=true
-custom_binary/debug=""
-custom_binary/release=""
-resources/pack_mode=1
-
-[script]
-
-action="compile"
-encrypt_key=""
diff --git a/demos/2d/light_mask/burano.png b/demos/2d/light_mask/burano.png
new file mode 100644
index 0000000000..6eec09d585
--- /dev/null
+++ b/demos/2d/light_mask/burano.png
Binary files differ
diff --git a/demos/2d/light_mask/engine.cfg b/demos/2d/light_mask/engine.cfg
new file mode 100644
index 0000000000..8b0ae6f61d
--- /dev/null
+++ b/demos/2d/light_mask/engine.cfg
@@ -0,0 +1,8 @@
+[application]
+
+name="Using Lights As Mask"
+main_scene="res://lightmask.scn"
+
+[rasterizer]
+
+shadow_filter=3
diff --git a/demos/2d/light_mask/lightmask.scn b/demos/2d/light_mask/lightmask.scn
new file mode 100644
index 0000000000..08805f44c6
--- /dev/null
+++ b/demos/2d/light_mask/lightmask.scn
Binary files differ
diff --git a/demos/2d/light_mask/splat.png b/demos/2d/light_mask/splat.png
new file mode 100644
index 0000000000..8c35f068a0
--- /dev/null
+++ b/demos/2d/light_mask/splat.png
Binary files differ
diff --git a/demos/2d/lights_shadows/light_shadows.scn b/demos/2d/lights_shadows/light_shadows.scn
index 34781b8049..a13e31376e 100644
--- a/demos/2d/lights_shadows/light_shadows.scn
+++ b/demos/2d/lights_shadows/light_shadows.scn
Binary files differ
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index 05c977f344..b40eccb239 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -1033,32 +1033,33 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu
int mipmaps= (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && img.get_mipmaps()>0) ? img.get_mipmaps() +1 : 1;
- int w=img.get_width();
- int h=img.get_height();
+ //int w=img.get_width();
+ //int h=img.get_height();
int tsize=0;
for(int i=0;i<mipmaps;i++) {
int size,ofs;
- img.get_mipmap_offset_and_size(i,ofs,size);
+ int mm_w,mm_h;
+ img.get_mipmap_offset_size_and_dimensions(i,ofs,size,mm_w,mm_h);
if (texture->compressed) {
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
- glCompressedTexImage2D( blit_target, i, format,w,h,0,size,&read[ofs] );
+ glCompressedTexImage2D( blit_target, i, format,mm_w,mm_h,0,size,&read[ofs] );
} else {
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
if (texture->flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) {
- glTexSubImage2D( blit_target, i, 0,0,w,h,format,GL_UNSIGNED_BYTE,&read[ofs] );
+ glTexSubImage2D( blit_target, i, 0,0,mm_w, mm_h,format,GL_UNSIGNED_BYTE,&read[ofs] );
} else {
- glTexImage2D(blit_target, i, internal_format, w, h, 0, format, GL_UNSIGNED_BYTE,&read[ofs]);
+ glTexImage2D(blit_target, i, internal_format, mm_w, mm_h, 0, format, GL_UNSIGNED_BYTE,&read[ofs]);
}
}
tsize+=size;
- w = MAX(1,w>>1);
- h = MAX(1,h>>1);
+ //w = MAX(Image::,w>>1);
+ //h = MAX(1,h>>1);
}
@@ -4611,6 +4612,9 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const {
if (fragment_flags.uses_texpixel_size) {
enablers.push_back("#define USE_TEXPIXEL_SIZE\n");
}
+ if (light_flags.uses_shadow_color) {
+ enablers.push_back("#define USE_LIGHT_SHADOW_COLOR\n");
+ }
if (vertex_flags.uses_worldvec) {
enablers.push_back("#define USE_WORLD_VEC\n");
@@ -8559,6 +8563,7 @@ RID RasterizerGLES2::canvas_light_shadow_buffer_create(int p_width) {
#ifdef GLEW_ENABLED
glDrawBuffer(GL_NONE);
#endif
+
} else {
// We'll use a RGBA texture into which we pack the depth info
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, cls->size, cls->height, 0,
@@ -8567,6 +8572,7 @@ RID RasterizerGLES2::canvas_light_shadow_buffer_create(int p_width) {
// Attach the RGBA texture to FBO color attachment point
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, cls->depth, 0);
+ cls->rgba=cls->depth;
// Allocate 16-bit depth buffer
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, cls->size, cls->height);
@@ -8845,10 +8851,14 @@ void RasterizerGLES2::canvas_debug_viewport_shadows(CanvasLight* p_lights_with_s
int h = 10;
int w = viewport.width;
int ofs = h;
+
+ //print_line(" debug lights ");
while(light) {
+ // print_line("debug light");
if (light->shadow_buffer.is_valid()) {
+ // print_line("sb is valid");
CanvasLightShadow * sb = canvas_light_shadow_owner.get(light->shadow_buffer);
if (sb) {
glActiveTexture(GL_TEXTURE0);
@@ -9129,6 +9139,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate);
canvas_shader.set_conditional(CanvasShaderGLES2::USE_DISTANCE_FIELD,false);
+
bool reset_modulate=false;
bool prev_distance_field=false;
@@ -9253,7 +9264,9 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
_canvas_item_setup_shader_uniforms(material,shader_cache);
}
- if (material && material->unshaded) {
+ bool unshaded = material && material->shading_mode==VS::CANVAS_ITEM_SHADING_UNSHADED;
+
+ if (unshaded) {
canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,Color(1,1,1,1));
reset_modulate=true;
} else if (reset_modulate) {
@@ -9310,13 +9323,15 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
canvas_opacity = ci->final_opacity;
- _canvas_item_render_commands<false>(ci,current_clip,reclip);
- if (canvas_blend_mode==VS::MATERIAL_BLEND_MODE_MIX && p_light && (!material || !material->unshaded)) {
+ if (unshaded || (p_modulate.a>0.001 && (!material || material->shading_mode!=VS::CANVAS_ITEM_SHADING_ONLY_LIGHT)))
+ _canvas_item_render_commands<false>(ci,current_clip,reclip);
+
+ if (canvas_blend_mode==VS::MATERIAL_BLEND_MODE_MIX && p_light && !unshaded) {
CanvasLight *light = p_light;
bool light_used=false;
- bool subtract=false;
+ VS::CanvasLightMode mode=VS::CANVAS_LIGHT_MODE_ADD;
while(light) {
@@ -9325,21 +9340,28 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
//intersects this light
- if (!light_used || subtract!=light->subtract) {
+ if (!light_used || mode!=light->mode) {
- subtract=light->subtract;
+ mode=light->mode;
- if (subtract) {
+ switch(mode) {
- glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
- glBlendFunc(GL_SRC_ALPHA,GL_ONE);
-
- } else {
+ case VS::CANVAS_LIGHT_MODE_ADD: {
+ glBlendEquation(GL_FUNC_ADD);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE);
- glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+ } break;
+ case VS::CANVAS_LIGHT_MODE_SUB: {
+ glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+ } break;
+ case VS::CANVAS_LIGHT_MODE_MIX: {
+ glBlendEquation(GL_FUNC_ADD);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ } break;
}
+
}
if (!light_used) {
@@ -9377,7 +9399,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_MATRIX,light->light_shader_xform);
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_POS,light->light_shader_pos);
- canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_COLOR,light->color);
+ canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_COLOR,Color(light->color.r*light->energy,light->color.g*light->energy,light->color.b*light->energy,light->color.a));
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_HEIGHT,light->height);
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_LOCAL_MATRIX,light->xform_cache.affine_inverse());
@@ -9857,9 +9879,9 @@ void RasterizerGLES2::free(const RID& p_rid) {
glDeleteFramebuffers(1,&cls->fbo);
glDeleteRenderbuffers(1,&cls->rbo);
glDeleteTextures(1,&cls->depth);
- if (!read_depth_supported) {
- glDeleteTextures(1,&cls->rgba);
- }
+ //if (!read_depth_supported) {
+ // glDeleteTextures(1,&cls->rgba);
+ //}
canvas_light_shadow_owner.free(p_rid);
memdelete(cls);
@@ -10365,6 +10387,62 @@ void RasterizerGLES2::_update_blur_buffer() {
}
#endif
+
+
+bool RasterizerGLES2::_test_depth_shadow_buffer() {
+
+
+ int size=16;
+
+ GLuint fbo;
+ GLuint rbo;
+ GLuint depth;
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glGenFramebuffers(1, &fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+ // Create a render buffer
+ glGenRenderbuffers(1, &rbo);
+ glBindRenderbuffer(GL_RENDERBUFFER, rbo);
+
+ // Create a texture for storing the depth
+ glGenTextures(1, &depth);
+ glBindTexture(GL_TEXTURE_2D, depth);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ // Remove artifact on the edges of the shadowmap
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+
+
+ // We'll use a depth texture to store the depths in the shadow map
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size, size, 0,
+ GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+
+#ifdef GLEW_ENABLED
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+#endif
+
+ // Attach the depth texture to FBO depth attachment point
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_TEXTURE_2D, depth, 0);
+
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+ glDeleteFramebuffers(1,&fbo);
+ glDeleteRenderbuffers(1,&rbo);
+ glDeleteTextures(1,&depth);
+
+ return status == GL_FRAMEBUFFER_COMPLETE;
+
+}
+
void RasterizerGLES2::init() {
#ifdef GLEW_ENABLED
@@ -10437,7 +10515,7 @@ void RasterizerGLES2::init() {
#ifdef GLEW_ENABLED
- read_depth_supported=true;
+
pvr_supported=false;
etc_supported=false;
use_depth24 =true;
@@ -10455,7 +10533,10 @@ void RasterizerGLES2::init() {
use_anisotropic_filter=true;
float_linear_supported=true;
float_supported=true;
- use_rgba_shadowmaps=false;
+
+ read_depth_supported=_test_depth_shadow_buffer();
+ use_rgba_shadowmaps=!read_depth_supported;
+ //print_line("read depth support? "+itos(read_depth_supported));
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT,&anisotropic_level);
anisotropic_level=MIN(anisotropic_level,float(GLOBAL_DEF("rasterizer/anisotropic_filter_level",4.0)));
@@ -10578,6 +10659,7 @@ void RasterizerGLES2::init() {
shadow_mat_ptr = material_owner.get(shadow_material);
overdraw_material = create_overdraw_debug_material();
copy_shader.set_conditional(CopyShaderGLES2::USE_8BIT_HDR,!use_fp16_fb);
+ canvas_shader.set_conditional(CanvasShaderGLES2::USE_DEPTH_SHADOWS,read_depth_supported);
canvas_shader.set_conditional(CanvasShaderGLES2::USE_PIXEL_SNAP,GLOBAL_DEF("rasterizer/use_pixel_snap",false));
diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h
index b7895ad82e..ad18c8e7a1 100644
--- a/drivers/gles2/rasterizer_gles2.h
+++ b/drivers/gles2/rasterizer_gles2.h
@@ -1288,6 +1288,7 @@ class RasterizerGLES2 : public Rasterizer {
void _copy_screen_quad();
void _copy_to_texscreen();
+ bool _test_depth_shadow_buffer();
Vector3 chunk_vertex;
Vector3 chunk_normal;
diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp
index 8d378ceec1..69bd269948 100644
--- a/drivers/gles2/shader_compiler_gles2.cpp
+++ b/drivers/gles2/shader_compiler_gles2.cpp
@@ -266,6 +266,9 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a
uses_normal=true;
}
+ if (vnode->name==vname_shadow) {
+ uses_shadow_color=true;
+ }
}
@@ -616,6 +619,7 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT
uses_texpixel_size=false;
uses_worldvec=false;
vertex_code_writes_vertex=false;
+ uses_shadow_color=false;
uniforms=r_uniforms;
flags=&r_flags;
r_flags.use_color_interp=false;
@@ -651,6 +655,7 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT
r_flags.uses_normal=uses_normal;
r_flags.uses_texpixel_size=uses_texpixel_size;
r_flags.uses_worldvec=uses_worldvec;
+ r_flags.uses_shadow_color=uses_shadow_color;
r_code_line=code;
r_globals_line=global_code;
@@ -827,7 +832,9 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
mode_replace_table[5]["LIGHT_VEC"]="light_vec";
mode_replace_table[5]["LIGHT_HEIGHT"]="light_height";
mode_replace_table[5]["LIGHT_COLOR"]="light";
+ mode_replace_table[5]["LIGHT_UV"]="light_uv";
mode_replace_table[5]["LIGHT"]="light_out";
+ mode_replace_table[5]["SHADOW"]="shadow_color";
mode_replace_table[5]["SCREEN_UV"]="screen_uv";
mode_replace_table[5]["POINT_COORD"]="gl_PointCoord";
mode_replace_table[5]["TIME"]="time";
@@ -857,5 +864,6 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
vname_normal="NORMAL";
vname_texpixel_size="TEXTURE_PIXEL_SIZE";
vname_world_vec="WORLD_VERTEX";
+ vname_shadow="SHADOW";
}
diff --git a/drivers/gles2/shader_compiler_gles2.h b/drivers/gles2/shader_compiler_gles2.h
index 87722602fd..87016fd968 100644
--- a/drivers/gles2/shader_compiler_gles2.h
+++ b/drivers/gles2/shader_compiler_gles2.h
@@ -55,6 +55,7 @@ private:
bool uses_texpixel_size;
bool uses_worldvec;
bool vertex_code_writes_vertex;
+ bool uses_shadow_color;
Flags *flags;
StringName vname_discard;
@@ -74,6 +75,7 @@ private:
StringName vname_normal;
StringName vname_texpixel_size;
StringName vname_world_vec;
+ StringName vname_shadow;
Map<StringName,ShaderLanguage::Uniform> *uniforms;
@@ -110,6 +112,7 @@ public:
bool uses_normal;
bool uses_texpixel_size;
bool uses_worldvec;
+ bool uses_shadow_color;
};
Error compile(const String& p_code, ShaderLanguage::ShaderType p_type, String& r_code_line, String& r_globals_line, Flags& r_flags, Map<StringName,ShaderLanguage::Uniform> *r_uniforms=NULL);
diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl
index e6d2569977..c4f0847870 100644
--- a/drivers/gles2/shaders/canvas.glsl
+++ b/drivers/gles2/shaders/canvas.glsl
@@ -36,7 +36,7 @@ uniform vec2 normal_flip;
#endif
#ifdef USE_SHADOWS
-highp varying vec2 pos;
+varying highp vec2 pos;
#endif
#endif
@@ -161,11 +161,11 @@ varying vec4 local_rot;
#ifdef USE_SHADOWS
-uniform sampler2D shadow_texture;
+uniform highp sampler2D shadow_texture;
uniform float shadow_attenuation;
uniform highp mat4 shadow_matrix;
-highp varying vec2 pos;
+varying highp vec2 pos;
uniform float shadowpixel_size;
#ifdef SHADOW_ESM
@@ -230,12 +230,16 @@ FRAGMENT_SHADER_CODE
float att=1.0;
- vec4 light = texture2D(light_texture,light_uv_interp.xy) * light_color;
+ vec2 light_uv = light_uv_interp.xy;
+ vec4 light = texture2D(light_texture,light_uv) * light_color;
+#if defined(USE_LIGHT_SHADOW_COLOR)
+ vec4 shadow_color=vec4(0.0,0.0,0.0,0.0);
+#endif
#if defined(USE_LIGHT_SHADER_CODE)
//light is written by the light shader
{
- vec4 light_out=vec4(0.0,0.0,0.0,0.0);
+ vec4 light_out=light*color;
LIGHT_SHADER_CODE
color=light_out;
}
@@ -292,39 +296,51 @@ LIGHT_SHADER_CODE
}
- vec4 s = shadow_matrix * vec4(point,0.0,1.0);
+ highp vec4 s = shadow_matrix * highp vec4(point,0.0,1.0);
s.xyz/=s.w;
su=s.x*0.5+0.5;
sz=s.z*0.5+0.5;
- float shadow_attenuation;
+ highp float shadow_attenuation=0.0;
+
+#ifdef USE_DEPTH_SHADOWS
+
+#define SHADOW_DEPTH(m_tex,m_uv) (texture2D((m_tex),(m_uv)).z)
+
+#else
+
+//#define SHADOW_DEPTH(m_tex,m_uv) dot(texture2D((m_tex),(m_uv)),highp vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1) )
+#define SHADOW_DEPTH(m_tex,m_uv) dot(texture2D((m_tex),(m_uv)),vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1) )
+
+#endif
+
+
#ifdef SHADOW_PCF5
- shadow_attenuation=0.0;
- shadow_attenuation += texture2D(shadow_texture,vec2(su,sh)).z<sz?0.0:1.0;
- shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size,sh)).z<sz?0.0:1.0;
- shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size*2.0,sh)).z<sz?0.0:1.0;
- shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size,sh)).z<sz?0.0:1.0;
- shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size*2.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su,sh))<sz?0.0:1.0;
+ shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size,sh))<sz?0.0:1.0;
+ shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size*2.0,sh))<sz?0.0:1.0;
+ shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size,sh))<sz?0.0:1.0;
+ shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size*2.0,sh))<sz?0.0:1.0;
shadow_attenuation/=5.0;
#endif
#ifdef SHADOW_PCF13
- shadow_attenuation += texture2D(shadow_texture,vec2(su,sh)).z<sz?0.0:1.0;
- shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size,sh)).z<sz?0.0:1.0;
- shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size*2.0,sh)).z<sz?0.0:1.0;
- shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size*3.0,sh)).z<sz?0.0:1.0;
- shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size*4.0,sh)).z<sz?0.0:1.0;
- shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size*5.0,sh)).z<sz?0.0:1.0;
- shadow_attenuation += texture2D(shadow_texture,vec2(su+shadowpixel_size*6.0,sh)).z<sz?0.0:1.0;
- shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size*2.0,sh)).z<sz?0.0:1.0;
- shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size*3.0,sh)).z<sz?0.0:1.0;
- shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size*4.0,sh)).z<sz?0.0:1.0;
- shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size*5.0,sh)).z<sz?0.0:1.0;
- shadow_attenuation += texture2D(shadow_texture,vec2(su-shadowpixel_size*6.0,sh)).z<sz?0.0:1.0;
+ shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su,sh))<sz?0.0:1.0;
+ shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size,sh))<sz?0.0:1.0;
+ shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size*2.0,sh))<sz?0.0:1.0;
+ shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size*3.0,sh))<sz?0.0:1.0;
+ shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size*4.0,sh))<sz?0.0:1.0;
+ shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size*5.0,sh))<sz?0.0:1.0;
+ shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size*6.0,sh))<sz?0.0:1.0;
+ shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size*2.0,sh))<sz?0.0:1.0;
+ shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size*3.0,sh))<sz?0.0:1.0;
+ shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size*4.0,sh))<sz?0.0:1.0;
+ shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size*5.0,sh))<sz?0.0:1.0;
+ shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size*6.0,sh))<sz?0.0:1.0;
shadow_attenuation/=13.0;
#endif
@@ -336,8 +352,8 @@ LIGHT_SHADER_CODE
float unnormalized = su/shadowpixel_size;
float fractional = fract(unnormalized);
unnormalized = floor(unnormalized);
- float zc = texture2D(shadow_texture,vec2((unnormalized-0.5)*shadowpixel_size,sh)).z;
- float zn = texture2D(shadow_texture,vec2((unnormalized+0.5)*shadowpixel_size,sh)).z;
+ float zc = SHADOW_DEPTH(shadow_texture,vec2((unnormalized-0.5)*shadowpixel_size,sh));
+ float zn = SHADOW_DEPTH(shadow_texture,vec2((unnormalized+0.5)*shadowpixel_size,sh));
float z = mix(zc,zn,fractional);
shadow_attenuation=clamp(exp(shadow_esm_multiplier* ( z - sz )),0.0,1.0);
}
@@ -346,11 +362,15 @@ LIGHT_SHADER_CODE
#if !defined(SHADOW_PCF5) && !defined(SHADOW_PCF13) && !defined(SHADOW_ESM)
- shadow_attenuation = texture2D(shadow_texture,vec2(su+shadowpixel_size,sh)).z<sz?0.0:1.0;
+ shadow_attenuation = SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size,sh))<sz?0.0:1.0;
#endif
- color.rgb*=shadow_attenuation;
+#if defined(USE_LIGHT_SHADOW_COLOR)
+ color=mix(shadow_color,color,shadow_attenuation);
+#else
+ color*=shadow_attenuation;
+#endif
//use shadows
#endif
}
diff --git a/drivers/pvr/AlphaBitmap.h b/drivers/pvr/AlphaBitmap.h
new file mode 100644
index 0000000000..57c6b026ea
--- /dev/null
+++ b/drivers/pvr/AlphaBitmap.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "Bitmap.h"
+
+namespace Javelin {
+
+class AlphaBitmap : public Bitmap {
+public:
+ AlphaBitmap(int w, int h)
+ : Bitmap(w, h, 1) {
+ }
+
+ const unsigned char *GetData() const { return data; }
+
+ unsigned char *GetData() { return data; }
+};
+
+}
diff --git a/drivers/pvr/BitScale.cpp b/drivers/pvr/BitScale.cpp
new file mode 100644
index 0000000000..97b3f0aa25
--- /dev/null
+++ b/drivers/pvr/BitScale.cpp
@@ -0,0 +1,184 @@
+#include "BitScale.h"
+
+
+const uint8_t Javelin::Data::BITSCALE_5_TO_8[32] = {
+ 0, 8, 16, 24, 32, 41, 49, 57, 65, 74,
+ 82, 90, 98, 106, 115, 123, 131, 139, 148, 156,
+ 164, 172, 180, 189, 197, 205, 213, 222, 230, 238,
+ 246, 255};
+
+const uint8_t Javelin::Data::BITSCALE_4_TO_8[16] = {
+ 0, 17, 34, 51, 68, 85, 102, 119, 136, 153,
+ 170, 187, 204, 221, 238, 255};
+
+const uint8_t Javelin::Data::BITSCALE_3_TO_8[8] = {
+ 0, 36, 72, 109, 145, 182, 218, 255};
+
+const uint8_t Javelin::Data::BITSCALE_8_TO_5_FLOOR[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
+ 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+ 3, 3, 3, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 7, 7,
+ 7, 7, 7, 7, 7, 7, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 9, 9, 9, 9, 9,
+ 9, 9, 9, 10, 10, 10, 10, 10, 10, 10,
+ 10, 11, 11, 11, 11, 11, 11, 11, 11, 12,
+ 12, 12, 12, 12, 12, 12, 12, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 14, 14, 14, 14,
+ 14, 14, 14, 14, 15, 15, 15, 15, 15, 15,
+ 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 18,
+ 18, 18, 18, 18, 18, 18, 18, 19, 19, 19,
+ 19, 19, 19, 19, 19, 20, 20, 20, 20, 20,
+ 20, 20, 20, 21, 21, 21, 21, 21, 21, 21,
+ 21, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 23, 23, 23, 23, 23, 23, 23, 23, 24, 24,
+ 24, 24, 24, 24, 24, 24, 25, 25, 25, 25,
+ 25, 25, 25, 25, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 27, 27, 27, 27, 27, 27, 27,
+ 27, 28, 28, 28, 28, 28, 28, 28, 28, 29,
+ 29, 29, 29, 29, 29, 29, 29, 30, 30, 30,
+ 30, 30, 30, 30, 30, 31};
+
+const uint8_t Javelin::Data::BITSCALE_8_TO_4_FLOOR[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 15};
+
+const uint8_t Javelin::Data::BITSCALE_8_TO_3_FLOOR[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 7};
+
+const uint8_t Javelin::Data::BITSCALE_8_TO_5_CEIL[256] = {
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 2, 2, 2, 2, 3, 3, 3,
+ 3, 3, 3, 3, 3, 4, 4, 4, 4, 4,
+ 4, 4, 4, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 6, 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 8, 8,
+ 8, 8, 8, 8, 8, 8, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 10, 10, 10, 10, 10,
+ 10, 10, 10, 11, 11, 11, 11, 11, 11, 11,
+ 11, 12, 12, 12, 12, 12, 12, 12, 12, 13,
+ 13, 13, 13, 13, 13, 13, 13, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 15, 15, 15, 15,
+ 15, 15, 15, 15, 16, 16, 16, 16, 16, 16,
+ 16, 16, 17, 17, 17, 17, 17, 17, 17, 17,
+ 18, 18, 18, 18, 18, 18, 18, 18, 18, 19,
+ 19, 19, 19, 19, 19, 19, 19, 20, 20, 20,
+ 20, 20, 20, 20, 20, 21, 21, 21, 21, 21,
+ 21, 21, 21, 22, 22, 22, 22, 22, 22, 22,
+ 22, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 24, 24, 24, 24, 24, 24, 24, 24, 25, 25,
+ 25, 25, 25, 25, 25, 25, 26, 26, 26, 26,
+ 26, 26, 26, 26, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 28, 28, 28, 28, 28, 28, 28,
+ 28, 29, 29, 29, 29, 29, 29, 29, 29, 30,
+ 30, 30, 30, 30, 30, 30, 30, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31};
+
+const uint8_t Javelin::Data::BITSCALE_8_TO_4_CEIL[256] = {
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15};
+
+const uint8_t Javelin::Data::BITSCALE_8_TO_3_CEIL[256] = {
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7};
+
diff --git a/drivers/pvr/BitScale.h b/drivers/pvr/BitScale.h
new file mode 100644
index 0000000000..36613aeeee
--- /dev/null
+++ b/drivers/pvr/BitScale.h
@@ -0,0 +1,28 @@
+//============================================================================
+
+#pragma once
+
+#include "typedefs.h"
+
+//============================================================================
+
+namespace Javelin
+{
+ namespace Data
+ {
+//============================================================================
+
+ extern const uint8_t BITSCALE_5_TO_8[32];
+ extern const uint8_t BITSCALE_4_TO_8[16];
+ extern const uint8_t BITSCALE_3_TO_8[8];
+ extern const uint8_t BITSCALE_8_TO_5_FLOOR[256];
+ extern const uint8_t BITSCALE_8_TO_4_FLOOR[256];
+ extern const uint8_t BITSCALE_8_TO_3_FLOOR[256];
+ extern const uint8_t BITSCALE_8_TO_5_CEIL[256];
+ extern const uint8_t BITSCALE_8_TO_4_CEIL[256];
+ extern const uint8_t BITSCALE_8_TO_3_CEIL[256];
+
+//============================================================================
+ } // namespace Data
+} // namespace Javelin
+//============================================================================
diff --git a/drivers/pvr/BitUtility.h b/drivers/pvr/BitUtility.h
new file mode 100644
index 0000000000..588ff3e892
--- /dev/null
+++ b/drivers/pvr/BitUtility.h
@@ -0,0 +1,19 @@
+#pragma once
+
+namespace Javelin {
+
+class BitUtility {
+public:
+ static bool IsPowerOf2(unsigned int x) {
+ return (x & (x - 1)) == 0;
+ }
+
+ static unsigned int RotateRight(unsigned int value, unsigned int shift) {
+ if ((shift &= sizeof(value) * 8 - 1) == 0) {
+ return value;
+ }
+ return (value >> shift) | (value << (sizeof(value) * 8 - shift));
+ }
+};
+
+}
diff --git a/drivers/pvr/Bitmap.h b/drivers/pvr/Bitmap.h
new file mode 100644
index 0000000000..508ed8cb75
--- /dev/null
+++ b/drivers/pvr/Bitmap.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include "Point2.h"
+
+namespace Javelin {
+
+class Bitmap {
+public:
+ int width;
+ int height;
+ unsigned char *data;
+
+ Bitmap(int w, int h, int bytesPerPixel)
+ : width(w)
+ , height(h)
+ , data(new unsigned char[width * height * bytesPerPixel]) {
+ }
+
+ virtual ~Bitmap() {
+ delete [] data;
+ }
+
+ Point2<int> GetSize() const { return Point2<int>(width, height); }
+
+ int GetArea() const { return width * height; }
+
+ int GetBitmapWidth() const { return width; }
+
+ int GetBitmapHeight() const { return height; }
+
+ const unsigned char *GetRawData() const { return data; }
+};
+
+}
diff --git a/drivers/pvr/ColorRgba.h b/drivers/pvr/ColorRgba.h
new file mode 100644
index 0000000000..6b46d65e3c
--- /dev/null
+++ b/drivers/pvr/ColorRgba.h
@@ -0,0 +1,152 @@
+#pragma once
+
+namespace Javelin {
+
+template<typename T>
+class ColorRgb {
+public:
+ T b;
+ T g;
+ T r;
+
+
+ ColorRgb()
+ : r(0)
+ , g(0)
+ , b(0) {
+ }
+
+ ColorRgb(T red, T green, T blue)
+ : r(red)
+ , g(green)
+ , b(blue) {
+ }
+
+ ColorRgb(const ColorRgb<T> &x)
+ : r(x.r)
+ , g(x.g)
+ , b(x.b) {
+ }
+
+ ColorRgb<int> operator *(int x) {
+ return ColorRgb<int>(r * x, g * x, b * x);
+ }
+
+ ColorRgb<int> operator +(const ColorRgb<T> &x) const {
+ return ColorRgb<int>(r + (int)x.r, g + (int)x.g, b + (int)x.b);
+ }
+
+ ColorRgb<int> operator -(const ColorRgb<T> &x) const {
+ return ColorRgb<int>(r - (int)x.r, g - (int)x.g, b - (int)x.b);
+ }
+
+ int operator %(const ColorRgb<T> &x) const {
+ return r * (int)x.r + g * (int)x.g + b * (int)x.b;
+ }
+
+ bool operator ==(const ColorRgb<T> &x) const {
+ return r == x.r && g == x.g && b == x.b;
+ }
+
+ bool operator !=(const ColorRgb<T> &x) const {
+ return r != x.r || g != x.g || b != x.b;
+ }
+
+ void SetMin(const ColorRgb<T> &x) {
+ if (x.r < r) {
+ r = x.r;
+ }
+ if (x.g < g) {
+ g = x.g;
+ }
+ if (x.b < b) {
+ b = x.b;
+ }
+ }
+
+ void SetMax(const ColorRgb<T> &x) {
+ if (x.r > r) {
+ r = x.r;
+ }
+ if (x.g > g) {
+ g = x.g;
+ }
+ if (x.b > b) {
+ b = x.b;
+ }
+ }
+};
+
+template<typename T>
+class ColorRgba : public ColorRgb<T> {
+public:
+ T a;
+
+ ColorRgba() :
+ a(0) {
+ }
+
+ ColorRgba(T red, T green, T blue, T alpha)
+ : ColorRgb<T>(red, green, blue)
+ , a(alpha) {
+ }
+
+ ColorRgba(const ColorRgba<T> &x)
+ : ColorRgb<T>(x.r, x.g, x.b)
+ , a(x.a) {
+ }
+
+ ColorRgba<int> operator *(int x) {
+ return ColorRgba<T>(ColorRgb<T>::r * x,
+ ColorRgb<T>::g * x,
+ ColorRgb<T>::b * x,
+ a * x);
+ }
+
+ ColorRgba<int> operator +(const ColorRgba<T> &x) {
+ return ColorRgba<T>(ColorRgb<T>::r + (int)x.r,
+ ColorRgb<T>::g + (int)x.g,
+ ColorRgb<T>::b + (int)x.b,
+ a + (int)x.a);
+ }
+
+ ColorRgba<int> operator -(const ColorRgba<T> &x) {
+ return ColorRgba<T>(ColorRgb<T>::r - (int)x.r,
+ ColorRgb<T>::g - (int)x.g,
+ ColorRgb<T>::b - (int)x.b,
+ a - (int)x.a);
+ }
+
+ int operator %(const ColorRgba<T> &x) {
+ return ColorRgb<T>::r * (int)x.r +
+ ColorRgb<T>::g * (int)x.g +
+ ColorRgb<T>::b * (int)x.b +
+ a * (int)x.a;
+ }
+
+ bool operator ==(const ColorRgba<T> &x) {
+ return ColorRgb<T>::r == x.r && ColorRgb<T>::g == x.g &&
+ ColorRgb<T>::b == x.b && a == x.a;
+ }
+
+ bool operator !=(const ColorRgba<T> &x) {
+ return ColorRgb<T>::r != x.r || ColorRgb<T>::g != x.g ||
+ ColorRgb<T>::b != x.b || a != x.a;
+ }
+
+ void SetMin(const ColorRgba<T> &x) {
+ ColorRgb<T>::SetMin(x);
+ if (x.a < a) {
+ a = x.a;
+ }
+ }
+
+ void SetMax(const ColorRgba<T> &x) {
+ ColorRgb<T>::SetMax(x);
+ if (x.a > a) {
+ a = x.a;
+ }
+ }
+};
+
+}
diff --git a/drivers/pvr/Interval.h b/drivers/pvr/Interval.h
new file mode 100644
index 0000000000..a7252e8375
--- /dev/null
+++ b/drivers/pvr/Interval.h
@@ -0,0 +1,21 @@
+#pragma once
+
+namespace Javelin {
+
+template<typename T>
+class Interval {
+public:
+ T min;
+ T max;
+
+ Interval() {
+ }
+
+ Interval<T> &operator|=(const T &x) {
+ min.SetMin(x);
+ max.SetMax(x);
+ return *this;
+ }
+};
+
+}
diff --git a/drivers/pvr/MortonTable.cpp b/drivers/pvr/MortonTable.cpp
new file mode 100644
index 0000000000..29a5af67f6
--- /dev/null
+++ b/drivers/pvr/MortonTable.cpp
@@ -0,0 +1,43 @@
+//============================================================================
+
+#include "MortonTable.h"
+
+//============================================================================
+
+const unsigned short Javelin::Data::MORTON_TABLE[256] =
+{
+ 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015,
+ 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055,
+ 0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115,
+ 0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155,
+ 0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415,
+ 0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455,
+ 0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515,
+ 0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555,
+ 0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015,
+ 0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055,
+ 0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115,
+ 0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155,
+ 0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415,
+ 0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455,
+ 0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515,
+ 0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555,
+ 0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015,
+ 0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055,
+ 0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115,
+ 0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155,
+ 0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415,
+ 0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455,
+ 0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515,
+ 0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555,
+ 0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015,
+ 0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055,
+ 0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115,
+ 0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155,
+ 0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415,
+ 0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455,
+ 0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515,
+ 0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555
+};
+
+//============================================================================
diff --git a/drivers/pvr/MortonTable.h b/drivers/pvr/MortonTable.h
new file mode 100644
index 0000000000..7a27e59544
--- /dev/null
+++ b/drivers/pvr/MortonTable.h
@@ -0,0 +1,18 @@
+//============================================================================
+
+#pragma once
+
+//============================================================================
+
+namespace Javelin
+{
+ namespace Data
+ {
+//============================================================================
+
+ extern const unsigned short MORTON_TABLE[256];
+
+//============================================================================
+ } // namespace Data
+} // namespace Javelin
+//============================================================================
diff --git a/drivers/pvr/Point2.h b/drivers/pvr/Point2.h
new file mode 100644
index 0000000000..89fa4b6322
--- /dev/null
+++ b/drivers/pvr/Point2.h
@@ -0,0 +1,17 @@
+#pragma once
+
+namespace Javelin {
+
+template<typename T>
+class Point2 {
+public:
+ T x;
+ T y;
+
+ Point2(int a, int b)
+ : x(a)
+ , y(b) {
+ }
+};
+
+}
diff --git a/drivers/pvr/PvrTcDecoder.cpp b/drivers/pvr/PvrTcDecoder.cpp
new file mode 100644
index 0000000000..d8a36b342c
--- /dev/null
+++ b/drivers/pvr/PvrTcDecoder.cpp
@@ -0,0 +1,144 @@
+//============================================================================
+
+#include "PvrTcDecoder.h"
+#include "PvrTcPacket.h"
+
+#include "MortonTable.h"
+#include <assert.h>
+
+//============================================================================
+
+using namespace Javelin;
+using Data::MORTON_TABLE;
+
+//============================================================================
+
+inline unsigned PvrTcDecoder::GetMortonNumber(int x, int y)
+{
+ return MORTON_TABLE[x >> 8] << 17 | MORTON_TABLE[y >> 8] << 16 | MORTON_TABLE[x & 0xFF] << 1 | MORTON_TABLE[y & 0xFF];
+}
+
+//============================================================================
+
+void PvrTcDecoder::DecodeRgb4Bpp(ColorRgb<unsigned char>* result, const Point2<int>& size, const void* data)
+{
+ assert(size.x == size.y);
+
+ const int blocks = size.x / 4;
+ const int blockMask = blocks-1;
+ const PvrTcPacket* packets = static_cast<const PvrTcPacket*>(data);
+
+ for(int y = 0; y < blocks; ++y)
+ {
+ for(int x = 0; x < blocks; ++x)
+ {
+ const PvrTcPacket* packet = packets + GetMortonNumber(x, y);
+
+ unsigned mod = packet->modulationData;
+ const unsigned char (*weights)[4] = PvrTcPacket::WEIGHTS + 4*packet->usePunchthroughAlpha;
+ const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS;
+
+ for(int py = 0; py < 4; ++py)
+ {
+ const int yOffset = (py < 2) ? -1 : 0;
+ const int y0 = (y + yOffset) & blockMask;
+ const int y1 = (y0+1) & blockMask;
+
+ for(int px = 0; px < 4; ++px)
+ {
+ const int xOffset = (px < 2) ? -1 : 0;
+ const int x0 = (x + xOffset) & blockMask;
+ const int x1 = (x0+1) & blockMask;
+
+ const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0);
+ const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0);
+ const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1);
+ const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1);
+
+ ColorRgb<int> ca = p0->GetColorRgbA() * (*factor)[0] +
+ p1->GetColorRgbA() * (*factor)[1] +
+ p2->GetColorRgbA() * (*factor)[2] +
+ p3->GetColorRgbA() * (*factor)[3];
+
+ ColorRgb<int> cb = p0->GetColorRgbB() * (*factor)[0] +
+ p1->GetColorRgbB() * (*factor)[1] +
+ p2->GetColorRgbB() * (*factor)[2] +
+ p3->GetColorRgbB() * (*factor)[3];
+
+ const unsigned char* w = weights[mod&3];
+ ColorRgb<unsigned char> c;
+ c.r = (ca.r * w[0] + cb.r * w[1]) >> 7;
+ c.g = (ca.g * w[0] + cb.g * w[1]) >> 7;
+ c.b = (ca.b * w[0] + cb.b * w[1]) >> 7;
+
+ result[(py+y*4)*size.x + (px+x*4)] = c;
+ mod >>= 2;
+ factor++;
+ }
+ }
+ }
+ }
+}
+
+void PvrTcDecoder::DecodeRgba4Bpp(ColorRgba<unsigned char>* result, const Point2<int>& size, const void* data)
+{
+ assert(size.x == size.y);
+
+ const int blocks = size.x / 4;
+ const int blockMask = blocks-1;
+ const PvrTcPacket* packets = static_cast<const PvrTcPacket*>(data);
+
+ for(int y = 0; y < blocks; ++y)
+ {
+ for(int x = 0; x < blocks; ++x)
+ {
+ const PvrTcPacket* packet = packets + GetMortonNumber(x, y);
+
+ unsigned mod = packet->modulationData;
+ const unsigned char (*weights)[4] = PvrTcPacket::WEIGHTS + 4*packet->usePunchthroughAlpha;
+ const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS;
+
+ for(int py = 0; py < 4; ++py)
+ {
+ const int yOffset = (py < 2) ? -1 : 0;
+ const int y0 = (y + yOffset) & blockMask;
+ const int y1 = (y0+1) & blockMask;
+
+ for(int px = 0; px < 4; ++px)
+ {
+ const int xOffset = (px < 2) ? -1 : 0;
+ const int x0 = (x + xOffset) & blockMask;
+ const int x1 = (x0+1) & blockMask;
+
+ const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0);
+ const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0);
+ const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1);
+ const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1);
+
+ ColorRgba<int> ca = p0->GetColorRgbaA() * (*factor)[0] +
+ p1->GetColorRgbaA() * (*factor)[1] +
+ p2->GetColorRgbaA() * (*factor)[2] +
+ p3->GetColorRgbaA() * (*factor)[3];
+
+ ColorRgba<int> cb = p0->GetColorRgbaB() * (*factor)[0] +
+ p1->GetColorRgbaB() * (*factor)[1] +
+ p2->GetColorRgbaB() * (*factor)[2] +
+ p3->GetColorRgbaB() * (*factor)[3];
+
+ const unsigned char* w = weights[mod&3];
+ ColorRgba<unsigned char> c;
+ c.r = (ca.r * w[0] + cb.r * w[1]) >> 7;
+ c.g = (ca.g * w[0] + cb.g * w[1]) >> 7;
+ c.b = (ca.b * w[0] + cb.b * w[1]) >> 7;
+ c.a = (ca.a * w[2] + cb.a * w[3]) >> 7;
+
+ result[(py+y*4)*size.x + (px+x*4)] = c;
+ mod >>= 2;
+ factor++;
+ }
+ }
+ }
+ }
+}
+
+//============================================================================
diff --git a/drivers/pvr/PvrTcDecoder.h b/drivers/pvr/PvrTcDecoder.h
new file mode 100644
index 0000000000..1b6fcf964c
--- /dev/null
+++ b/drivers/pvr/PvrTcDecoder.h
@@ -0,0 +1,25 @@
+//============================================================================
+
+#pragma once
+#include "Point2.h"
+#include "ColorRgba.h"
+
+//============================================================================
+
+namespace Javelin
+{
+//============================================================================
+
+ class PvrTcDecoder
+ {
+ public:
+ static void DecodeRgb4Bpp(ColorRgb<unsigned char>* result, const Point2<int>& size, const void* data);
+ static void DecodeRgba4Bpp(ColorRgba<unsigned char>* result, const Point2<int>& size, const void* data);
+
+ private:
+ static unsigned GetMortonNumber(int x, int y);
+ };
+
+//============================================================================
+}
+//============================================================================
diff --git a/drivers/pvr/PvrTcEncoder.cpp b/drivers/pvr/PvrTcEncoder.cpp
new file mode 100644
index 0000000000..587b1320f1
--- /dev/null
+++ b/drivers/pvr/PvrTcEncoder.cpp
@@ -0,0 +1,474 @@
+//============================================================================
+
+#include "PvrTcEncoder.h"
+#include "AlphaBitmap.h"
+#include "PvrTcPacket.h"
+#include "RgbBitmap.h"
+#include "RgbaBitmap.h"
+#include "MortonTable.h"
+#include "BitUtility.h"
+#include "Interval.h"
+#include <assert.h>
+#include <math.h>
+#include <stdint.h>
+
+//============================================================================
+
+using namespace Javelin;
+using Data::MORTON_TABLE;
+
+//============================================================================
+
+static const unsigned char MODULATION_LUT[16] =
+{
+ 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3
+};
+
+//============================================================================
+
+inline unsigned PvrTcEncoder::GetMortonNumber(int x, int y)
+{
+ return MORTON_TABLE[x >> 8] << 17 | MORTON_TABLE[y >> 8] << 16 | MORTON_TABLE[x & 0xFF] << 1 | MORTON_TABLE[y & 0xFF];
+}
+
+//============================================================================
+
+void PvrTcEncoder::EncodeAlpha2Bpp(void* result, const AlphaBitmap& bitmap)
+{
+ int size = bitmap.GetBitmapWidth();
+ assert(size == bitmap.GetBitmapHeight());
+ assert(BitUtility::IsPowerOf2(size));
+
+ // Blocks in each dimension.
+ int xBlocks = size/8;
+ int yBlocks = size/4;
+
+ const unsigned char* bitmapData = bitmap.GetRawData();
+
+ PvrTcPacket* packets = static_cast<PvrTcPacket*>(result);
+ for(int y = 0; y < yBlocks; ++y)
+ {
+ for(int x = 0; x < xBlocks; ++x)
+ {
+ PvrTcPacket* packet = packets + GetMortonNumber(x, y);
+ packet->usePunchthroughAlpha = 0;
+ packet->colorAIsOpaque = 0;
+ packet->colorA = 0x7ff; // White, with 0 alpha
+ packet->colorBIsOpaque = 1;
+ packet->colorB = 0x7fff; // White with full alpha
+
+ const unsigned char* blockBitmapData = &bitmapData[y*4*size + x*8];
+
+ uint32_t modulationData = 0;
+ for(int py = 0; py < 4; ++py)
+ {
+ const unsigned char* rowBitmapData = blockBitmapData;
+ for(int px = 0; px < 8; ++px)
+ {
+ unsigned char pixel = *rowBitmapData++;
+ modulationData = BitUtility::RotateRight(modulationData | (pixel >> 7), 1);
+ }
+ blockBitmapData += size;
+ }
+ packet->modulationData = modulationData;
+ }
+ }
+}
+
+void PvrTcEncoder::EncodeAlpha4Bpp(void* result, const AlphaBitmap& bitmap)
+{
+ int size = bitmap.GetBitmapWidth();
+ assert(size == bitmap.GetBitmapHeight());
+ assert(BitUtility::IsPowerOf2(size));
+
+ // Blocks in each dimension.
+ int blocks = size/4;
+
+ const unsigned char* bitmapData = bitmap.GetRawData();
+
+ PvrTcPacket* packets = static_cast<PvrTcPacket*>(result);
+ for(int y = 0; y < blocks; ++y)
+ {
+ for(int x = 0; x < blocks; ++x)
+ {
+ PvrTcPacket* packet = packets + GetMortonNumber(x, y);
+ packet->usePunchthroughAlpha = 0;
+ packet->colorAIsOpaque = 0;
+ packet->colorA = 0x7ff; // White, with 0 alpha
+ packet->colorBIsOpaque = 1;
+ packet->colorB = 0x7fff; // White with full alpha
+
+ const unsigned char* blockBitmapData = &bitmapData[(y*size + x)*4];
+
+ uint32_t modulationData = 0;
+ for(int py = 0; py < 4; ++py)
+ {
+ const unsigned char* rowBitmapData = blockBitmapData;
+ for(int px = 0; px < 4; ++px)
+ {
+ unsigned char pixel = *rowBitmapData++;
+ modulationData = BitUtility::RotateRight(modulationData | MODULATION_LUT[pixel>>4], 2);
+ }
+ blockBitmapData += size;
+ }
+ packet->modulationData = modulationData;
+ }
+ }
+}
+
+//============================================================================
+
+typedef Interval<ColorRgb<unsigned char> > ColorRgbBoundingBox;
+
+static void CalculateBoundingBox(ColorRgbBoundingBox& cbb, const RgbBitmap& bitmap, int blockX, int blockY)
+{
+ int size = bitmap.GetBitmapWidth();
+ const ColorRgb<unsigned char>* data = bitmap.GetData() + blockY * 4 * size + blockX * 4;
+
+ cbb.min = data[0];
+ cbb.max = data[0];
+ cbb |= data[1];
+ cbb |= data[2];
+ cbb |= data[3];
+
+ cbb |= data[size];
+ cbb |= data[size+1];
+ cbb |= data[size+2];
+ cbb |= data[size+3];
+
+ cbb |= data[2*size];
+ cbb |= data[2*size+1];
+ cbb |= data[2*size+2];
+ cbb |= data[2*size+3];
+
+ cbb |= data[3*size];
+ cbb |= data[3*size+1];
+ cbb |= data[3*size+2];
+ cbb |= data[3*size+3];
+}
+
+void PvrTcEncoder::EncodeRgb4Bpp(void* result, const RgbBitmap& bitmap)
+{
+ assert(bitmap.GetBitmapWidth() == bitmap.GetBitmapHeight());
+ assert(BitUtility::IsPowerOf2(bitmap.GetBitmapWidth()));
+ const int size = bitmap.GetBitmapWidth();
+ const int blocks = size / 4;
+ const int blockMask = blocks-1;
+
+ PvrTcPacket* packets = static_cast<PvrTcPacket*>(result);
+
+ for(int y = 0; y < blocks; ++y)
+ {
+ for(int x = 0; x < blocks; ++x)
+ {
+ ColorRgbBoundingBox cbb;
+ CalculateBoundingBox(cbb, bitmap, x, y);
+ PvrTcPacket* packet = packets + GetMortonNumber(x, y);
+ packet->usePunchthroughAlpha = 0;
+ packet->SetColorA(cbb.min);
+ packet->SetColorB(cbb.max);
+ }
+ }
+
+ for(int y = 0; y < blocks; ++y)
+ {
+ for(int x = 0; x < blocks; ++x)
+ {
+ const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS;
+ const ColorRgb<unsigned char>* data = bitmap.GetData() + y * 4 * size + x * 4;
+
+ uint32_t modulationData = 0;
+
+ for(int py = 0; py < 4; ++py)
+ {
+ const int yOffset = (py < 2) ? -1 : 0;
+ const int y0 = (y + yOffset) & blockMask;
+ const int y1 = (y0+1) & blockMask;
+
+ for(int px = 0; px < 4; ++px)
+ {
+ const int xOffset = (px < 2) ? -1 : 0;
+ const int x0 = (x + xOffset) & blockMask;
+ const int x1 = (x0+1) & blockMask;
+
+ const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0);
+ const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0);
+ const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1);
+ const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1);
+
+ ColorRgb<int> ca = p0->GetColorRgbA() * (*factor)[0] +
+ p1->GetColorRgbA() * (*factor)[1] +
+ p2->GetColorRgbA() * (*factor)[2] +
+ p3->GetColorRgbA() * (*factor)[3];
+
+ ColorRgb<int> cb = p0->GetColorRgbB() * (*factor)[0] +
+ p1->GetColorRgbB() * (*factor)[1] +
+ p2->GetColorRgbB() * (*factor)[2] +
+ p3->GetColorRgbB() * (*factor)[3];
+
+ const ColorRgb<unsigned char>& pixel = data[py*size + px];
+ ColorRgb<int> d = cb - ca;
+ ColorRgb<int> p;
+ p.r=pixel.r*16;
+ p.g=pixel.g*16;
+ p.b=pixel.b*16;
+ ColorRgb<int> v = p - ca;
+
+ // PVRTC uses weightings of 0, 3/8, 5/8 and 1
+ // The boundaries for these are 3/16, 1/2 (=8/16), 13/16
+ int projection = (v % d) * 16;
+ int lengthSquared = d % d;
+ if(projection > 3*lengthSquared) modulationData++;
+ if(projection > 8*lengthSquared) modulationData++;
+ if(projection > 13*lengthSquared) modulationData++;
+
+ modulationData = BitUtility::RotateRight(modulationData, 2);
+
+ factor++;
+ }
+ }
+
+ PvrTcPacket* packet = packets + GetMortonNumber(x, y);
+ packet->modulationData = modulationData;
+ }
+ }
+}
+
+//============================================================================
+
+static void CalculateBoundingBox(ColorRgbBoundingBox& cbb, const RgbaBitmap& bitmap, int blockX, int blockY)
+{
+ int size = bitmap.GetBitmapWidth();
+ const ColorRgba<unsigned char>* data = bitmap.GetData() + blockY * 4 * size + blockX * 4;
+
+ cbb.min = data[0];
+ cbb.max = data[0];
+
+ cbb |= data[1];
+ cbb |= data[2];
+ cbb |= data[3];
+
+ cbb |= data[size];
+ cbb |= data[size+1];
+ cbb |= data[size+2];
+ cbb |= data[size+3];
+
+ cbb |= data[2*size];
+ cbb |= data[2*size+1];
+ cbb |= data[2*size+2];
+ cbb |= data[2*size+3];
+
+ cbb |= data[3*size];
+ cbb |= data[3*size+1];
+ cbb |= data[3*size+2];
+ cbb |= data[3*size+3];
+}
+
+void PvrTcEncoder::EncodeRgb4Bpp(void* result, const RgbaBitmap& bitmap)
+{
+ assert(bitmap.GetBitmapWidth() == bitmap.GetBitmapHeight());
+ assert(BitUtility::IsPowerOf2(bitmap.GetBitmapWidth()));
+ const int size = bitmap.GetBitmapWidth();
+ const int blocks = size / 4;
+ const int blockMask = blocks-1;
+
+ PvrTcPacket* packets = static_cast<PvrTcPacket*>(result);
+
+ for(int y = 0; y < blocks; ++y)
+ {
+ for(int x = 0; x < blocks; ++x)
+ {
+ ColorRgbBoundingBox cbb;
+ CalculateBoundingBox(cbb, bitmap, x, y);
+ PvrTcPacket* packet = packets + GetMortonNumber(x, y);
+ packet->usePunchthroughAlpha = 0;
+ packet->SetColorA(cbb.min);
+ packet->SetColorB(cbb.max);
+ }
+ }
+
+ for(int y = 0; y < blocks; ++y)
+ {
+ for(int x = 0; x < blocks; ++x)
+ {
+ const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS;
+ const ColorRgba<unsigned char>* data = bitmap.GetData() + y * 4 * size + x * 4;
+
+ uint32_t modulationData = 0;
+
+ for(int py = 0; py < 4; ++py)
+ {
+ const int yOffset = (py < 2) ? -1 : 0;
+ const int y0 = (y + yOffset) & blockMask;
+ const int y1 = (y0+1) & blockMask;
+
+ for(int px = 0; px < 4; ++px)
+ {
+ const int xOffset = (px < 2) ? -1 : 0;
+ const int x0 = (x + xOffset) & blockMask;
+ const int x1 = (x0+1) & blockMask;
+
+ const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0);
+ const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0);
+ const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1);
+ const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1);
+
+ ColorRgb<int> ca = p0->GetColorRgbA() * (*factor)[0] +
+ p1->GetColorRgbA() * (*factor)[1] +
+ p2->GetColorRgbA() * (*factor)[2] +
+ p3->GetColorRgbA() * (*factor)[3];
+
+ ColorRgb<int> cb = p0->GetColorRgbB() * (*factor)[0] +
+ p1->GetColorRgbB() * (*factor)[1] +
+ p2->GetColorRgbB() * (*factor)[2] +
+ p3->GetColorRgbB() * (*factor)[3];
+
+ const ColorRgb<unsigned char>& pixel = data[py*size + px];
+ ColorRgb<int> d = cb - ca;
+ ColorRgb<int> p;
+ p.r=pixel.r*16;
+ p.g=pixel.g*16;
+ p.b=pixel.b*16;
+ ColorRgb<int> v = p - ca;
+
+ // PVRTC uses weightings of 0, 3/8, 5/8 and 1
+ // The boundaries for these are 3/16, 1/2 (=8/16), 13/16
+ int projection = (v % d) * 16;
+ int lengthSquared = d % d;
+ if(projection > 3*lengthSquared) modulationData++;
+ if(projection > 8*lengthSquared) modulationData++;
+ if(projection > 13*lengthSquared) modulationData++;
+
+ modulationData = BitUtility::RotateRight(modulationData, 2);
+
+ factor++;
+ }
+ }
+
+ PvrTcPacket* packet = packets + GetMortonNumber(x, y);
+ packet->modulationData = modulationData;
+ }
+ }
+}
+
+//============================================================================
+
+typedef Interval<ColorRgba<unsigned char> > ColorRgbaBoundingBox;
+
+static void CalculateBoundingBox(ColorRgbaBoundingBox& cbb, const RgbaBitmap& bitmap, int blockX, int blockY)
+{
+ int size = bitmap.GetBitmapWidth();
+ const ColorRgba<unsigned char>* data = bitmap.GetData() + blockY * 4 * size + blockX * 4;
+
+ cbb.min = data[0];
+ cbb.max = data[0];
+
+ cbb |= data[1];
+ cbb |= data[2];
+ cbb |= data[3];
+
+ cbb |= data[size];
+ cbb |= data[size+1];
+ cbb |= data[size+2];
+ cbb |= data[size+3];
+
+ cbb |= data[2*size];
+ cbb |= data[2*size+1];
+ cbb |= data[2*size+2];
+ cbb |= data[2*size+3];
+
+ cbb |= data[3*size];
+ cbb |= data[3*size+1];
+ cbb |= data[3*size+2];
+ cbb |= data[3*size+3];
+}
+
+void PvrTcEncoder::EncodeRgba4Bpp(void* result, const RgbaBitmap& bitmap)
+{
+ assert(bitmap.GetBitmapWidth() == bitmap.GetBitmapHeight());
+ assert(BitUtility::IsPowerOf2(bitmap.GetBitmapWidth()));
+ const int size = bitmap.GetBitmapWidth();
+ const int blocks = size / 4;
+ const int blockMask = blocks-1;
+
+ PvrTcPacket* packets = static_cast<PvrTcPacket*>(result);
+
+ for(int y = 0; y < blocks; ++y)
+ {
+ for(int x = 0; x < blocks; ++x)
+ {
+ ColorRgbaBoundingBox cbb;
+ CalculateBoundingBox(cbb, bitmap, x, y);
+ PvrTcPacket* packet = packets + GetMortonNumber(x, y);
+ packet->usePunchthroughAlpha = 0;
+ packet->SetColorA(cbb.min);
+ packet->SetColorB(cbb.max);
+ }
+ }
+
+ for(int y = 0; y < blocks; ++y)
+ {
+ for(int x = 0; x < blocks; ++x)
+ {
+ const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS;
+ const ColorRgba<unsigned char>* data = bitmap.GetData() + y * 4 * size + x * 4;
+
+ uint32_t modulationData = 0;
+
+ for(int py = 0; py < 4; ++py)
+ {
+ const int yOffset = (py < 2) ? -1 : 0;
+ const int y0 = (y + yOffset) & blockMask;
+ const int y1 = (y0+1) & blockMask;
+
+ for(int px = 0; px < 4; ++px)
+ {
+ const int xOffset = (px < 2) ? -1 : 0;
+ const int x0 = (x + xOffset) & blockMask;
+ const int x1 = (x0+1) & blockMask;
+
+ const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0);
+ const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0);
+ const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1);
+ const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1);
+
+ ColorRgba<int> ca = p0->GetColorRgbaA() * (*factor)[0] +
+ p1->GetColorRgbaA() * (*factor)[1] +
+ p2->GetColorRgbaA() * (*factor)[2] +
+ p3->GetColorRgbaA() * (*factor)[3];
+
+ ColorRgba<int> cb = p0->GetColorRgbaB() * (*factor)[0] +
+ p1->GetColorRgbaB() * (*factor)[1] +
+ p2->GetColorRgbaB() * (*factor)[2] +
+ p3->GetColorRgbaB() * (*factor)[3];
+
+ const ColorRgba<unsigned char>& pixel = data[py*size + px];
+ ColorRgba<int> d = cb - ca;
+ ColorRgba<int> p;
+ p.r=pixel.r*16;
+ p.g=pixel.g*16;
+ p.b=pixel.b*16;
+ p.a=pixel.a*16;
+ ColorRgba<int> v = p - ca;
+
+ // PVRTC uses weightings of 0, 3/8, 5/8 and 1
+ // The boundaries for these are 3/16, 1/2 (=8/16), 13/16
+ int projection = (v % d) * 16;
+ int lengthSquared = d % d;
+ if(projection > 3*lengthSquared) modulationData++;
+ if(projection > 8*lengthSquared) modulationData++;
+ if(projection > 13*lengthSquared) modulationData++;
+
+ modulationData = BitUtility::RotateRight(modulationData, 2);
+
+ factor++;
+ }
+ }
+
+ PvrTcPacket* packet = packets + GetMortonNumber(x, y);
+ packet->modulationData = modulationData;
+ }
+ }
+}
+
+//============================================================================
diff --git a/drivers/pvr/PvrTcEncoder.h b/drivers/pvr/PvrTcEncoder.h
new file mode 100644
index 0000000000..b9344367d9
--- /dev/null
+++ b/drivers/pvr/PvrTcEncoder.h
@@ -0,0 +1,40 @@
+//============================================================================
+
+#pragma once
+#include "ColorRgba.h"
+
+//============================================================================
+
+namespace Javelin
+{
+//============================================================================
+
+ class AlphaBitmap;
+ class RgbBitmap;
+ class RgbaBitmap;
+
+ class PvrTcEncoder
+ {
+ public:
+ // Result must be large enough for bitmap.GetArea()/4 bytes
+ static void EncodeAlpha2Bpp(void* result, const AlphaBitmap& bitmap);
+
+ // Result must be large enough for bitmap.GetArea()/2 bytes
+ static void EncodeAlpha4Bpp(void* result, const AlphaBitmap& bitmap);
+
+ // Result must be large enough for bitmap.GetArea()/2 bytes
+ static void EncodeRgb4Bpp(void* result, const RgbBitmap& bitmap);
+
+ // Result must be large enough for bitmap.GetArea()/2 bytes
+ static void EncodeRgb4Bpp(void* result, const RgbaBitmap& bitmap);
+
+ // Result must be large enough for bitmap.GetArea()/2 bytes
+ static void EncodeRgba4Bpp(void* result, const RgbaBitmap& bitmap);
+
+ private:
+ static unsigned GetMortonNumber(int x, int y);
+ };
+
+//============================================================================
+}
+//============================================================================
diff --git a/drivers/pvr/PvrTcPacket.cpp b/drivers/pvr/PvrTcPacket.cpp
new file mode 100644
index 0000000000..2e40d371e8
--- /dev/null
+++ b/drivers/pvr/PvrTcPacket.cpp
@@ -0,0 +1,209 @@
+//============================================================================
+
+#include "PvrTcPacket.h"
+#include "BitScale.h"
+
+//============================================================================
+
+using namespace Javelin;
+
+//============================================================================
+
+const unsigned char PvrTcPacket::BILINEAR_FACTORS[16][4] =
+{
+ { 4, 4, 4, 4 },
+ { 2, 6, 2, 6 },
+ { 8, 0, 8, 0 },
+ { 6, 2, 6, 2 },
+
+ { 2, 2, 6, 6 },
+ { 1, 3, 3, 9 },
+ { 4, 0, 12, 0 },
+ { 3, 1, 9, 3 },
+
+ { 8, 8, 0, 0 },
+ { 4, 12, 0, 0 },
+ { 16, 0, 0, 0 },
+ { 12, 4, 0, 0 },
+
+ { 6, 6, 2, 2 },
+ { 3, 9, 1, 3 },
+ { 12, 0, 4, 0 },
+ { 9, 3, 3, 1 },
+};
+
+// Weights are { colorA, colorB, alphaA, alphaB }
+const unsigned char PvrTcPacket::WEIGHTS[8][4] =
+{
+ // Weights for Mode=0
+ { 8, 0, 8, 0 },
+ { 5, 3, 5, 3 },
+ { 3, 5, 3, 5 },
+ { 0, 8, 0, 8 },
+
+ // Weights for Mode=1
+ { 8, 0, 8, 0 },
+ { 4, 4, 4, 4 },
+ { 4, 4, 0, 0 },
+ { 0, 8, 0, 8 },
+};
+
+//============================================================================
+
+ColorRgb<int> PvrTcPacket::GetColorRgbA() const
+{
+ if(colorAIsOpaque)
+ {
+ unsigned char r = colorA >> 9;
+ unsigned char g = colorA >> 4 & 0x1f;
+ unsigned char b = colorA & 0xf;
+ return ColorRgb<int>(Data::BITSCALE_5_TO_8[r],
+ Data::BITSCALE_5_TO_8[g],
+ Data::BITSCALE_4_TO_8[b]);
+ }
+ else
+ {
+ unsigned char r = (colorA >> 7) & 0xf;
+ unsigned char g = (colorA >> 3) & 0xf;
+ unsigned char b = colorA & 7;
+ return ColorRgb<int>(Data::BITSCALE_4_TO_8[r],
+ Data::BITSCALE_4_TO_8[g],
+ Data::BITSCALE_3_TO_8[b]);
+ }
+}
+
+ColorRgb<int> PvrTcPacket::GetColorRgbB() const
+{
+ if(colorBIsOpaque)
+ {
+ unsigned char r = colorB >> 10;
+ unsigned char g = colorB >> 5 & 0x1f;
+ unsigned char b = colorB & 0x1f;
+ return ColorRgb<int>(Data::BITSCALE_5_TO_8[r],
+ Data::BITSCALE_5_TO_8[g],
+ Data::BITSCALE_5_TO_8[b]);
+ }
+ else
+ {
+ unsigned char r = colorB >> 8 & 0xf;
+ unsigned char g = colorB >> 4 & 0xf;
+ unsigned char b = colorB & 0xf;
+ return ColorRgb<int>(Data::BITSCALE_4_TO_8[r],
+ Data::BITSCALE_4_TO_8[g],
+ Data::BITSCALE_4_TO_8[b]);
+ }
+}
+
+ColorRgba<int> PvrTcPacket::GetColorRgbaA() const
+{
+ if(colorAIsOpaque)
+ {
+ unsigned char r = colorA >> 9;
+ unsigned char g = colorA >> 4 & 0x1f;
+ unsigned char b = colorA & 0xf;
+ return ColorRgba<int>(Data::BITSCALE_5_TO_8[r],
+ Data::BITSCALE_5_TO_8[g],
+ Data::BITSCALE_4_TO_8[b],
+ 255);
+ }
+ else
+ {
+ unsigned char a = colorA >> 11 & 7;
+ unsigned char r = colorA >> 7 & 0xf;
+ unsigned char g = colorA >> 3 & 0xf;
+ unsigned char b = colorA & 7;
+ return ColorRgba<int>(Data::BITSCALE_4_TO_8[r],
+ Data::BITSCALE_4_TO_8[g],
+ Data::BITSCALE_3_TO_8[b],
+ Data::BITSCALE_3_TO_8[a]);
+ }
+}
+
+ColorRgba<int> PvrTcPacket::GetColorRgbaB() const
+{
+ if(colorBIsOpaque)
+ {
+ unsigned char r = colorB >> 10;
+ unsigned char g = colorB >> 5 & 0x1f;
+ unsigned char b = colorB & 0x1f;
+ return ColorRgba<int>(Data::BITSCALE_5_TO_8[r],
+ Data::BITSCALE_5_TO_8[g],
+ Data::BITSCALE_5_TO_8[b],
+ 255);
+ }
+ else
+ {
+ unsigned char a = colorB >> 12 & 7;
+ unsigned char r = colorB >> 8 & 0xf;
+ unsigned char g = colorB >> 4 & 0xf;
+ unsigned char b = colorB & 0xf;
+ return ColorRgba<int>(Data::BITSCALE_4_TO_8[r],
+ Data::BITSCALE_4_TO_8[g],
+ Data::BITSCALE_4_TO_8[b],
+ Data::BITSCALE_3_TO_8[a]);
+ }
+}
+
+//============================================================================
+
+void PvrTcPacket::SetColorA(const ColorRgb<unsigned char>& c)
+{
+ int r = Data::BITSCALE_8_TO_5_FLOOR[c.r];
+ int g = Data::BITSCALE_8_TO_5_FLOOR[c.g];
+ int b = Data::BITSCALE_8_TO_4_FLOOR[c.b];
+ colorA = r<<9 | g<<4 | b;
+ colorAIsOpaque = true;
+}
+
+void PvrTcPacket::SetColorB(const ColorRgb<unsigned char>& c)
+{
+ int r = Data::BITSCALE_8_TO_5_CEIL[c.r];
+ int g = Data::BITSCALE_8_TO_5_CEIL[c.g];
+ int b = Data::BITSCALE_8_TO_5_CEIL[c.b];
+ colorB = r<<10 | g<<5 | b;
+ colorBIsOpaque = true;
+}
+
+void PvrTcPacket::SetColorA(const ColorRgba<unsigned char>& c)
+{
+ int a = Data::BITSCALE_8_TO_3_FLOOR[c.a];
+ if(a == 7)
+ {
+ int r = Data::BITSCALE_8_TO_5_FLOOR[c.r];
+ int g = Data::BITSCALE_8_TO_5_FLOOR[c.g];
+ int b = Data::BITSCALE_8_TO_4_FLOOR[c.b];
+ colorA = r<<9 | g<<4 | b;
+ colorAIsOpaque = true;
+ }
+ else
+ {
+ int r = Data::BITSCALE_8_TO_4_FLOOR[c.r];
+ int g = Data::BITSCALE_8_TO_4_FLOOR[c.g];
+ int b = Data::BITSCALE_8_TO_3_FLOOR[c.b];
+ colorA = a<<11 | r<<7 | g<<3 | b;
+ colorAIsOpaque = false;
+ }
+}
+
+void PvrTcPacket::SetColorB(const ColorRgba<unsigned char>& c)
+{
+ int a = Data::BITSCALE_8_TO_3_CEIL[c.a];
+ if(a == 7)
+ {
+ int r = Data::BITSCALE_8_TO_5_CEIL[c.r];
+ int g = Data::BITSCALE_8_TO_5_CEIL[c.g];
+ int b = Data::BITSCALE_8_TO_5_CEIL[c.b];
+ colorB = r<<10 | g<<5 | b;
+ colorBIsOpaque = true;
+ }
+ else
+ {
+ int r = Data::BITSCALE_8_TO_4_CEIL[c.r];
+ int g = Data::BITSCALE_8_TO_4_CEIL[c.g];
+ int b = Data::BITSCALE_8_TO_4_CEIL[c.b];
+ colorB = a<<12 | r<<8 | g<<4 | b;
+ colorBIsOpaque = false;
+ }
+}
+
+//============================================================================
diff --git a/drivers/pvr/PvrTcPacket.h b/drivers/pvr/PvrTcPacket.h
new file mode 100644
index 0000000000..ac3b6a4dd1
--- /dev/null
+++ b/drivers/pvr/PvrTcPacket.h
@@ -0,0 +1,65 @@
+//============================================================================
+//
+// Modulation data specifies weightings of colorA to colorB for each pixel
+//
+// For mode = 0
+// 00: 0/8
+// 01: 3/8
+// 10: 5/8
+// 11: 8/8
+//
+// For mode = 1
+// 00: 0/8
+// 01: 4/8
+// 10: 4/8 with alpha punchthrough
+// 11: 8/8
+//
+// For colorIsOpaque=0
+// 3 bits A
+// 4 bits R
+// 4 bits G
+// 3/4 bits B
+//
+// For colorIsOpaque=1
+// 5 bits R
+// 5 bits G
+// 4/5 bits B
+//
+//============================================================================
+
+#pragma once
+#include "ColorRgba.h"
+
+//============================================================================
+
+namespace Javelin
+{
+//============================================================================
+
+ struct PvrTcPacket
+ {
+ unsigned int modulationData;
+ unsigned usePunchthroughAlpha : 1;
+ unsigned colorA : 14;
+ unsigned colorAIsOpaque : 1;
+ unsigned colorB : 15;
+ unsigned colorBIsOpaque : 1;
+
+ ColorRgb<int> GetColorRgbA() const;
+ ColorRgb<int> GetColorRgbB() const;
+ ColorRgba<int> GetColorRgbaA() const;
+ ColorRgba<int> GetColorRgbaB() const;
+
+ void SetColorA(const ColorRgb<unsigned char>& c);
+ void SetColorB(const ColorRgb<unsigned char>& c);
+
+ void SetColorA(const ColorRgba<unsigned char>& c);
+ void SetColorB(const ColorRgba<unsigned char>& c);
+
+ static const unsigned char BILINEAR_FACTORS[16][4];
+ static const unsigned char WEIGHTS[8][4];
+ };
+
+//============================================================================
+} // namespace Javelin
+//============================================================================
diff --git a/drivers/pvr/RgbBitmap.h b/drivers/pvr/RgbBitmap.h
new file mode 100644
index 0000000000..cf1d78667d
--- /dev/null
+++ b/drivers/pvr/RgbBitmap.h
@@ -0,0 +1,23 @@
+#pragma once
+
+#include "Bitmap.h"
+#include "ColorRgba.h"
+
+namespace Javelin {
+
+class RgbBitmap : public Bitmap {
+public:
+ RgbBitmap(int w, int h)
+ : Bitmap(w, h, 3) {
+ }
+
+ const ColorRgb<unsigned char> *GetData() const {
+ return reinterpret_cast<ColorRgb<unsigned char> *>(data);
+ }
+
+ ColorRgb<unsigned char> *GetData() {
+ return reinterpret_cast<ColorRgb<unsigned char> *>(data);
+ }
+};
+
+}
diff --git a/drivers/pvr/RgbaBitmap.h b/drivers/pvr/RgbaBitmap.h
new file mode 100644
index 0000000000..66b5542c1a
--- /dev/null
+++ b/drivers/pvr/RgbaBitmap.h
@@ -0,0 +1,23 @@
+#pragma once
+
+#include "ColorRgba.h"
+#include "Bitmap.h"
+
+namespace Javelin {
+
+class RgbaBitmap : public Bitmap {
+public:
+ RgbaBitmap(int w, int h)
+ : Bitmap(w, h, 4) {
+ }
+
+ const ColorRgba<unsigned char> *GetData() const {
+ return reinterpret_cast<ColorRgba<unsigned char> *>(data);
+ }
+
+ ColorRgba<unsigned char> *GetData() {
+ return reinterpret_cast<ColorRgba<unsigned char> *>(data);
+ }
+};
+
+}
diff --git a/drivers/pvr/SCsub b/drivers/pvr/SCsub
index bd4c6f3f88..44b8c3d6bb 100644
--- a/drivers/pvr/SCsub
+++ b/drivers/pvr/SCsub
@@ -2,10 +2,14 @@ Import('env')
pvr_sources = [
+ "pvr/BitScale.cpp",
+ "pvr/MortonTable.cpp",
+ "pvr/PvrTcDecoder.cpp",
+ "pvr/PvrTcEncoder.cpp",
+ "pvr/PvrTcPacket.cpp",
"pvr/texture_loader_pvr.cpp"
]
env.drivers_sources+=pvr_sources
#env.add_source_files(env.drivers_sources, pvr_sources)
-
diff --git a/drivers/pvr/texture_loader_pvr.cpp b/drivers/pvr/texture_loader_pvr.cpp
index b12e0c28b8..5268b953f4 100644
--- a/drivers/pvr/texture_loader_pvr.cpp
+++ b/drivers/pvr/texture_loader_pvr.cpp
@@ -1,6 +1,8 @@
#include "texture_loader_pvr.h"
#include "os/file_access.h"
#include <string.h>
+#include "PvrTcEncoder.h"
+#include "RgbaBitmap.h"
static void _pvrtc_decompress(Image* p_img);
@@ -154,10 +156,59 @@ String ResourceFormatPVR::get_resource_type(const String &p_path) const {
}
+
+static void _compress_pvrtc4(Image * p_img) {
+
+ Image img = *p_img;
+
+ bool make_mipmaps=false;
+ if (img.get_width()%8 || img.get_height()%8) {
+ make_mipmaps=img.get_mipmaps()>0;
+ img.resize(img.get_width()+(8-(img.get_width()%8)),img.get_height()+(8-(img.get_height()%8)));
+ }
+ img.convert(Image::FORMAT_RGBA);
+ if (img.get_mipmaps()==0 && make_mipmaps)
+ img.generate_mipmaps();
+
+ bool use_alpha=img.detect_alpha();
+
+ Image new_img;
+ new_img.create(img.get_width(),img.get_height(),true,use_alpha?Image::FORMAT_PVRTC4_ALPHA:Image::FORMAT_PVRTC4);
+ DVector<uint8_t> data=new_img.get_data();
+ {
+ DVector<uint8_t>::Write wr=data.write();
+ DVector<uint8_t>::Read r=img.get_data().read();
+
+
+ for(int i=0;i<=new_img.get_mipmaps();i++) {
+
+ int ofs,size,w,h;
+ img.get_mipmap_offset_size_and_dimensions(i,ofs,size,w,h);
+ Javelin::RgbaBitmap bm(w,h);
+ copymem(bm.GetData(),&r[ofs],size);
+ {
+ Javelin::ColorRgba<unsigned char> *dp = bm.GetData();
+ for(int j=0;j<size/4;j++) {
+ SWAP(dp[j].r,dp[j].b);
+ }
+ }
+
+ new_img.get_mipmap_offset_size_and_dimensions(i,ofs,size,w,h);
+ Javelin::PvrTcEncoder::EncodeRgba4Bpp(&wr[ofs],bm);
+ }
+
+ }
+
+ *p_img = Image(new_img.get_width(),new_img.get_height(),new_img.get_mipmaps(),new_img.get_format(),data);
+
+}
+
ResourceFormatPVR::ResourceFormatPVR() {
Image::_image_decompress_pvrtc=_pvrtc_decompress;
+ Image::_image_compress_pvrtc4_func=_compress_pvrtc4;
+ Image::_image_compress_pvrtc2_func=_compress_pvrtc4;
}
diff --git a/modules/gdscript/gd_functions.cpp b/modules/gdscript/gd_functions.cpp
index f37b2f645a..ce2cb14643 100644
--- a/modules/gdscript/gd_functions.cpp
+++ b/modules/gdscript/gd_functions.cpp
@@ -575,7 +575,7 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va
}
//str+="\n";
- OS::get_singleton()->print("%s\n",str.utf8().get_data());
+ OS::get_singleton()->print("%s",str.utf8().get_data());
r_ret=Variant();
} break;
diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp
index 06c746c4fb..f13b51c008 100644
--- a/modules/gdscript/gd_script.cpp
+++ b/modules/gdscript/gd_script.cpp
@@ -1689,7 +1689,7 @@ bool GDScript::_update_exports() {
}
- if (c->extends_used && String(c->extends_file)!="") {
+ if (c->extends_used && String(c->extends_file)!="" && String(c->extends_file) != get_path()) {
String path = c->extends_file;
if (path.is_rel_path()) {
diff --git a/platform/android/detect.py b/platform/android/detect.py
index 4cf12538db..5ef405f7b6 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -91,7 +91,7 @@ def configure(env):
gcc_path=gcc_path+"/darwin-x86_64/bin" #this may be wrong
env['SHLINKFLAGS'][1] = '-shared'
elif (os.name=="nt"):
- gcc_path=gcc_path+"/windows/bin" #this may be wrong
+ gcc_path=gcc_path+"/windows-x86_64/bin" #this may be wrong
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index 3e4ea8a4e0..8199e7c622 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -185,6 +185,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
bool _signed;
bool apk_expansion;
bool remove_prev;
+ bool use_32_fb;
String apk_expansion_salt;
String apk_expansion_pkey;
int orientation;
@@ -279,6 +280,8 @@ bool EditorExportPlatformAndroid::_set(const StringName& p_name, const Variant&
icon=p_value;
else if (n=="package/signed")
_signed=p_value;
+ else if (n=="screen/use_32_bits_view")
+ use_32_fb=p_value;
else if (n=="screen/orientation")
orientation=p_value;
else if (n=="screen/support_small")
@@ -344,6 +347,8 @@ bool EditorExportPlatformAndroid::_get(const StringName& p_name,Variant &r_ret)
r_ret=icon;
else if (n=="package/signed")
r_ret=_signed;
+ else if (n=="screen/use_32_bits_view")
+ r_ret=use_32_fb;
else if (n=="screen/orientation")
r_ret=orientation;
else if (n=="screen/support_small")
@@ -393,6 +398,7 @@ void EditorExportPlatformAndroid::_get_property_list( List<PropertyInfo> *p_list
p_list->push_back( PropertyInfo( Variant::STRING, "package/name") );
p_list->push_back( PropertyInfo( Variant::STRING, "package/icon",PROPERTY_HINT_FILE,"png") );
p_list->push_back( PropertyInfo( Variant::BOOL, "package/signed") );
+ p_list->push_back( PropertyInfo( Variant::BOOL, "screen/use_32_bits_view") );
p_list->push_back( PropertyInfo( Variant::INT, "screen/orientation",PROPERTY_HINT_ENUM,"Landscape,Portrait") );
p_list->push_back( PropertyInfo( Variant::BOOL, "screen/support_small") );
p_list->push_back( PropertyInfo( Variant::BOOL, "screen/support_normal") );
@@ -1158,8 +1164,14 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d
err = export_project_files(save_apk_file,&ed,false);
}
+
+
}
+ if (use_32_fb)
+ cl.push_back("-use_depth_32");
+
+
if (cl.size()) {
//add comandline
Vector<uint8_t> clf;
@@ -1534,6 +1546,7 @@ EditorExportPlatformAndroid::EditorExportPlatformAndroid() {
quit_request=false;
orientation=0;
remove_prev=true;
+ use_32_fb=true;
device_thread=Thread::create(_device_poll_thread,this);
devices_changed=true;
diff --git a/platform/android/java/src/com/android/godot/Godot.java b/platform/android/java/src/com/android/godot/Godot.java
index 1a7659a473..2abb4cec53 100644
--- a/platform/android/java/src/com/android/godot/Godot.java
+++ b/platform/android/java/src/com/android/godot/Godot.java
@@ -109,6 +109,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
private Button mPauseButton;
private Button mWiFiSettingsButton;
+ private boolean use_32_bits=false;
private boolean mStatePaused;
private int mState;
@@ -255,7 +256,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
// ...add to FrameLayout
layout.addView(edittext);
- mView = new GodotView(getApplication(),io,use_gl2, this);
+ mView = new GodotView(getApplication(),io,use_gl2,use_32_bits, this);
layout.addView(mView,new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
mView.setKeepScreenOn(true);
@@ -399,7 +400,9 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
for(int i=0;i<command_line.length;i++) {
boolean has_extra = i< command_line.length -1;
- if (command_line[i].equals("-use_apk_expansion")) {
+ if (command_line[i].equals("-use_depth_32")) {
+ use_32_bits=true;
+ } else if (command_line[i].equals("-use_apk_expansion")) {
use_apk_expansion=true;
} else if (has_extra && command_line[i].equals("-apk_expansion_md5")) {
main_pack_md5=command_line[i+1];
@@ -568,9 +571,24 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
}
@Override public void onSensorChanged(SensorEvent event) {
- float x = event.values[0];
- float y = event.values[1];
- float z = event.values[2];
+ Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
+ int displayRotation = display.getRotation();
+
+ float[] adjustedValues = new float[3];
+ final int axisSwap[][] = {
+ { 1, -1, 0, 1 }, // ROTATION_0
+ {-1, -1, 1, 0 }, // ROTATION_90
+ {-1, 1, 0, 1 }, // ROTATION_180
+ { 1, 1, 1, 0 } }; // ROTATION_270
+
+ final int[] as = axisSwap[displayRotation];
+ adjustedValues[0] = (float)as[0] * event.values[ as[2] ];
+ adjustedValues[1] = (float)as[1] * event.values[ as[3] ];
+ adjustedValues[2] = event.values[2];
+
+ float x = adjustedValues[0];
+ float y = adjustedValues[1];
+ float z = adjustedValues[2];
GodotLib.accelerometer(x,y,z);
}
diff --git a/platform/android/java/src/com/android/godot/GodotView.java b/platform/android/java/src/com/android/godot/GodotView.java
index f62431b94b..bd81b7f9af 100644
--- a/platform/android/java/src/com/android/godot/GodotView.java
+++ b/platform/android/java/src/com/android/godot/GodotView.java
@@ -71,14 +71,16 @@ public class GodotView extends GLSurfaceView {
private static GodotIO io;
private static boolean firsttime=true;
private static boolean use_gl2=false;
+ private static boolean use_32=false;
private Godot activity;
- public GodotView(Context context,GodotIO p_io,boolean p_use_gl2, Godot p_activity) {
+ public GodotView(Context context,GodotIO p_io,boolean p_use_gl2, boolean p_use_32_bits, Godot p_activity) {
super(context);
ctx=context;
io=p_io;
use_gl2=p_use_gl2;
+ use_32=p_use_32_bits;
activity = p_activity;
@@ -366,9 +368,17 @@ public class GodotView extends GLSurfaceView {
* custom config chooser. See ConfigChooser class definition
* below.
*/
- setEGLConfigChooser( translucent ?
- new ConfigChooser(8, 8, 8, 8, depth, stencil) :
- new ConfigChooser(5, 6, 5, 0, depth, stencil) );
+
+ if (use_32) {
+ setEGLConfigChooser( translucent ?
+ new ConfigChooser(8, 8, 8, 8, 24, stencil) :
+ new ConfigChooser(8, 8, 8, 8, 24, stencil) );
+
+ } else {
+ setEGLConfigChooser( translucent ?
+ new ConfigChooser(8, 8, 8, 8, 16, stencil) :
+ new ConfigChooser(5, 6, 5, 0, 16, stencil) );
+ }
/* Set the renderer responsible for frame rendering */
setRenderer(new Renderer());
diff --git a/platform/android/libs/downloader_library/gen/com/android/vending/expansion/downloader/BuildConfig.java b/platform/android/libs/downloader_library/gen/com/android/vending/expansion/downloader/BuildConfig.java
index 77ebb4b780..da9d06e63c 100644
--- a/platform/android/libs/downloader_library/gen/com/android/vending/expansion/downloader/BuildConfig.java
+++ b/platform/android/libs/downloader_library/gen/com/android/vending/expansion/downloader/BuildConfig.java
@@ -2,5 +2,5 @@
package com.android.vending.expansion.downloader;
public final class BuildConfig {
- public final static boolean DEBUG = true;
+ public final static boolean DEBUG = false;
} \ No newline at end of file
diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp
index 581df84925..4c8d8a4205 100644
--- a/platform/javascript/os_javascript.cpp
+++ b/platform/javascript/os_javascript.cpp
@@ -230,6 +230,12 @@ OS::VideoMode OS_JavaScript::get_video_mode(int p_screen) const {
return default_videomode;
}
+
+Size2 OS_JavaScript::get_window_size() const {
+
+ return Vector2(default_videomode.width,default_videomode.height);
+}
+
void OS_JavaScript::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) const {
p_list->push_back(default_videomode);
diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h
index dfc93d3ff0..2e9c8e14c2 100644
--- a/platform/javascript/os_javascript.h
+++ b/platform/javascript/os_javascript.h
@@ -127,6 +127,7 @@ public:
virtual VideoMode get_video_mode(int p_screen=0) const;
virtual void get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen=0) const;
+ virtual Size2 get_window_size() const;
virtual String get_name();
virtual MainLoop *get_main_loop() const;
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index 8f121b7dd5..9ffd4fc3f8 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -99,6 +99,13 @@ public:
CursorShape cursor_shape;
MouseMode mouse_mode;
+
+ bool minimized;
+ bool maximized;
+ bool zoomed;
+ Vector<Rect2> screens;
+ int current_screen;
+ Rect2 restore_rect;
protected:
virtual int get_video_driver_count() const;
@@ -112,16 +119,13 @@ protected:
virtual void set_main_loop( MainLoop * p_main_loop );
virtual void delete_main_loop();
-
public:
-
-
-
-
static OS_OSX* singleton;
+ void wm_minimized(bool p_minimized);
+
virtual String get_name();
virtual void set_cursor_shape(CursorShape p_shape);
@@ -162,6 +166,24 @@ public:
virtual void move_window_to_foreground();
+ virtual int get_screen_count() const;
+ virtual int get_current_screen() const;
+ virtual void set_current_screen(int p_screen);
+ virtual Point2 get_screen_position(int p_screen=0);
+ virtual Point2 get_window_position() const;
+ virtual void set_window_position(const Point2& p_position);
+ virtual void set_window_size(const Size2 p_size);
+ virtual void set_window_fullscreen(bool p_enabled);
+ virtual bool is_window_fullscreen() const;
+ virtual void set_window_resizable(bool p_enabled);
+ virtual bool is_window_resizable() const;
+ virtual void set_window_minimized(bool p_enabled);
+ virtual bool is_window_minimized() const;
+ virtual void set_window_maximized(bool p_enabled);
+ virtual bool is_window_maximized() const;
+ Size2 get_screen_size(int p_screen);
+
+
void run();
void set_mouse_mode(MouseMode p_mode);
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 55ef6c1516..a20263f9b2 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -227,19 +227,6 @@ static int button_mask=0;
// centerCursor(window);
}
-- (void)windowDidMiniaturize:(NSNotification *)notification
-{
- // _GodotInputWindowIconify(window, GL_TRUE);
-}
-
-- (void)windowDidDeminiaturize:(NSNotification *)notification
-{
- //if (window->monitor)
-// enterFullscreenMode(window);
-
- // _GodotInputWindowIconify(window, GL_FALSE);
-}
-
- (void)windowDidBecomeKey:(NSNotification *)notification
{
// _GodotInputWindowFocus(window, GL_TRUE);
@@ -256,6 +243,21 @@ static int button_mask=0;
OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
}
+- (void)windowDidMiniaturize:(NSNotification*)notification
+{
+ OS_OSX::singleton->wm_minimized(true);
+ if (OS_OSX::singleton->get_main_loop())
+ OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
+};
+
+- (void)windowDidDeminiaturize:(NSNotification*)notification
+{
+
+ OS_OSX::singleton->wm_minimized(false);
+ if (OS_OSX::singleton->get_main_loop())
+ OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);
+};
+
@end
@interface GodotContentView : NSView
@@ -903,7 +905,7 @@ void OS_OSX::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
unsigned int attributeCount = 0;
// OS X needs non-zero color size, so set resonable values
- int colorBits = 24;
+ int colorBits = 32;
// Fail if a robustness strategy was requested
@@ -1018,7 +1020,15 @@ void OS_OSX::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
_ensure_data_dir();
+ NSArray *screenArray = [NSScreen screens];
+ printf("nscreen count %i\n", (int)[screenArray count]);
+ for (int i=0; i<[screenArray count]; i++) {
+ NSRect nsrect = [[screenArray objectAtIndex: i] visibleFrame];
+ screens.push_back(Rect2(nsrect.origin.x, nsrect.origin.y, nsrect.size.width, nsrect.size.height));
+ printf("added screen %i\n", screens.size());
+ };
+ restore_rect = Rect2(get_window_position(), get_window_size());
}
void OS_OSX::finalize() {
@@ -1231,7 +1241,10 @@ void OS_OSX::swap_buffers() {
}
+void OS_OSX::wm_minimized(bool p_minimized) {
+ minimized = p_minimized;
+};
void OS_OSX::set_video_mode(const VideoMode& p_video_mode,int p_screen) {
@@ -1245,9 +1258,118 @@ void OS_OSX::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) cons
}
+
+int OS_OSX::get_screen_count() const {
+
+ return screens.size();
+};
+
+int OS_OSX::get_current_screen() const {
+
+ return current_screen;
+};
+
+void OS_OSX::set_current_screen(int p_screen) {
+
+ current_screen = p_screen;
+};
+
+Point2 OS_OSX::get_screen_position(int p_screen) {
+
+ ERR_FAIL_INDEX_V(p_screen, screens.size(), Point2());
+ return screens[p_screen].pos;
+};
+
+Size2 OS_OSX::get_screen_size(int p_screen) {
+
+ ERR_FAIL_INDEX_V(p_screen, screens.size(), Point2());
+ return screens[p_screen].size;
+};
+
+Point2 OS_OSX::get_window_position() const {
+
+ return Size2([window_object frame].origin.x, [window_object frame].origin.y);
+};
+
+
+void OS_OSX::set_window_position(const Point2& p_position) {
+
+ [window_object setFrame:NSMakeRect(p_position.x, p_position.y, [window_object frame].size.width, [window_object frame].size.height) display:YES];
+};
+
Size2 OS_OSX::get_window_size() const {
- return Vector2(current_videomode.width, current_videomode.height);
-}
+
+ return Size2([window_object frame].size.width, [window_object frame].size.height);
+};
+
+void OS_OSX::set_window_size(const Size2 p_size) {
+
+ NSRect frame = [window_object frame];
+ [window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y, p_size.x, p_size.y) display:YES];
+};
+
+void OS_OSX::set_window_fullscreen(bool p_enabled) {
+
+ [window_object performZoom:nil];
+ zoomed = p_enabled;
+};
+
+bool OS_OSX::is_window_fullscreen() const {
+
+ if ( [window_object respondsToSelector:@selector(isZoomed)] )
+ return [window_object isZoomed];
+
+ return zoomed;
+};
+
+void OS_OSX::set_window_resizable(bool p_enabled) {
+
+ if (p_enabled)
+ [window_object setStyleMask:[window_object styleMask] | NSResizableWindowMask ];
+ else
+ [window_object setStyleMask:[window_object styleMask] & ~NSResizableWindowMask ];
+};
+
+bool OS_OSX::is_window_resizable() const {
+
+ return [window_object styleMask] & NSResizableWindowMask;
+};
+
+void OS_OSX::set_window_minimized(bool p_enabled) {
+
+ if (p_enabled)
+ [window_object performMiniaturize:nil];
+ else
+ [window_object deminiaturize:nil];
+};
+
+bool OS_OSX::is_window_minimized() const {
+
+ if ( [window_object respondsToSelector:@selector(isMiniaturized)])
+ return [window_object isMiniaturized];
+
+ return minimized;
+};
+
+
+void OS_OSX::set_window_maximized(bool p_enabled) {
+
+ if (p_enabled) {
+ restore_rect = Rect2(get_window_position(), get_window_size());
+ [window_object setFrame:[[[NSScreen screens] objectAtIndex:current_screen] visibleFrame] display:YES];
+ } else {
+ set_window_size(restore_rect.size);
+ set_window_position(restore_rect.pos);
+ };
+ maximized = p_enabled;
+};
+
+bool OS_OSX::is_window_maximized() const {
+
+ // don't know
+ return maximized;
+};
+
void OS_OSX::move_window_to_foreground() {
@@ -1477,5 +1599,9 @@ OS_OSX::OS_OSX() {
last_id=1;
cursor_shape=CURSOR_ARROW;
+ current_screen = 0;
+ maximized = false;
+ minimized = false;
+ zoomed = false;
}
diff --git a/platform/server/os_server.cpp b/platform/server/os_server.cpp
index 7bc8f61744..1aabf5337b 100644
--- a/platform/server/os_server.cpp
+++ b/platform/server/os_server.cpp
@@ -56,7 +56,6 @@ void OS_Server::initialize(const VideoMode& p_desired,int p_video_driver,int p_a
args=OS::get_singleton()->get_cmdline_args();
current_videomode=p_desired;
main_loop=NULL;
-
rasterizer = memnew( RasterizerDummy );
@@ -163,6 +162,12 @@ OS::VideoMode OS_Server::get_video_mode(int p_screen) const {
return current_videomode;
}
+
+Size2 OS_Server::get_window_size() const {
+
+ return Vector2(current_videomode.width,current_videomode.height) ;
+}
+
void OS_Server::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) const {
diff --git a/platform/server/os_server.h b/platform/server/os_server.h
index fcf96253ad..f8d346ce48 100644
--- a/platform/server/os_server.h
+++ b/platform/server/os_server.h
@@ -109,6 +109,8 @@ public:
virtual VideoMode get_video_mode(int p_screen=0) const;
virtual void get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen=0) const;
+ virtual Size2 get_window_size() const;
+
virtual void move_window_to_foreground();
void run();
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index c3ff03d8f4..118ba33bc6 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -42,8 +42,8 @@ bool CanvasItemMaterial::_set(const StringName& p_name, const Variant& p_value)
if (p_name==SceneStringNames::get_singleton()->shader_shader) {
set_shader(p_value);
return true;
- } else if (p_name==SceneStringNames::get_singleton()->shader_unshaded) {
- set_unshaded(p_value);
+ } else if (p_name==SceneStringNames::get_singleton()->shading_mode) {
+ set_shading_mode(ShadingMode(p_value.operator int()));
return true;
} else {
@@ -74,10 +74,10 @@ bool CanvasItemMaterial::_get(const StringName& p_name,Variant &r_ret) const {
r_ret=get_shader();
return true;
- } else if (p_name==SceneStringNames::get_singleton()->shader_unshaded) {
+ } else if (p_name==SceneStringNames::get_singleton()->shading_mode) {
- r_ret=unshaded;
+ r_ret=shading_mode;
return true;
} else {
@@ -100,7 +100,7 @@ bool CanvasItemMaterial::_get(const StringName& p_name,Variant &r_ret) const {
void CanvasItemMaterial::_get_property_list( List<PropertyInfo> *p_list) const {
p_list->push_back( PropertyInfo( Variant::OBJECT, "shader/shader", PROPERTY_HINT_RESOURCE_TYPE,"CanvasItemShader,CanvasItemShaderGraph" ) );
- p_list->push_back( PropertyInfo( Variant::BOOL, "shader/unshaded") );
+ p_list->push_back( PropertyInfo( Variant::INT, "shader/shading_mode",PROPERTY_HINT_ENUM,"Normal,Unshaded,Light Only") );
if (!shader.is_null()) {
@@ -161,25 +161,30 @@ RID CanvasItemMaterial::get_rid() const {
return material;
}
-void CanvasItemMaterial::set_unshaded(bool p_unshaded) {
+void CanvasItemMaterial::set_shading_mode(ShadingMode p_mode) {
- unshaded=p_unshaded;
- VS::get_singleton()->canvas_item_material_set_unshaded(material,p_unshaded);
+ shading_mode=p_mode;
+ VS::get_singleton()->canvas_item_material_set_shading_mode(material,VS::CanvasItemShadingMode(p_mode));
}
-bool CanvasItemMaterial::is_unshaded() const{
-
- return unshaded;
+CanvasItemMaterial::ShadingMode CanvasItemMaterial::get_shading_mode() const {
+ return shading_mode;
}
+
void CanvasItemMaterial::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_shader","shader:Shader"),&CanvasItemMaterial::set_shader);
ObjectTypeDB::bind_method(_MD("get_shader:Shader"),&CanvasItemMaterial::get_shader);
ObjectTypeDB::bind_method(_MD("set_shader_param","param","value"),&CanvasItemMaterial::set_shader_param);
ObjectTypeDB::bind_method(_MD("get_shader_param","param"),&CanvasItemMaterial::get_shader_param);
- ObjectTypeDB::bind_method(_MD("set_unshaded","unshaded"),&CanvasItemMaterial::set_unshaded);
- ObjectTypeDB::bind_method(_MD("is_unshaded"),&CanvasItemMaterial::is_unshaded);
+ ObjectTypeDB::bind_method(_MD("set_shading_mode","mode"),&CanvasItemMaterial::set_shading_mode);
+ ObjectTypeDB::bind_method(_MD("get_shading_mode"),&CanvasItemMaterial::get_shading_mode);
+
+ BIND_CONSTANT( SHADING_NORMAL );
+ BIND_CONSTANT( SHADING_UNSHADED );
+ BIND_CONSTANT( SHADING_ONLY_LIGHT );
+
}
@@ -202,7 +207,7 @@ void CanvasItemMaterial::get_argument_options(const StringName& p_function,int p
CanvasItemMaterial::CanvasItemMaterial() {
material=VS::get_singleton()->canvas_item_material_create();
- unshaded=false;
+ shading_mode=SHADING_NORMAL;
}
CanvasItemMaterial::~CanvasItemMaterial(){
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index c43642a8ec..167f2b96f3 100644
--- a/scene/2d/canvas_item.h
+++ b/scene/2d/canvas_item.h
@@ -45,10 +45,17 @@ class CanvasItemMaterial : public Resource{
OBJ_TYPE(CanvasItemMaterial,Resource);
RID material;
Ref<Shader> shader;
- bool unshaded;
+public:
+ enum ShadingMode {
+ SHADING_NORMAL,
+ SHADING_UNSHADED,
+ SHADING_ONLY_LIGHT,
+ };
protected:
+ ShadingMode shading_mode;
+
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;
@@ -66,14 +73,16 @@ public:
void set_shader_param(const StringName& p_param,const Variant& p_value);
Variant get_shader_param(const StringName& p_param) const;
- void set_unshaded(bool p_unshaded);
- bool is_unshaded() const;
+ void set_shading_mode(ShadingMode p_mode);
+ ShadingMode get_shading_mode() const;
virtual RID get_rid() const;
CanvasItemMaterial();
~CanvasItemMaterial();
};
+VARIANT_ENUM_CAST( CanvasItemMaterial::ShadingMode );
+
class CanvasItem : public Node {
diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp
index 4abb7e5436..c0ab544d42 100644
--- a/scene/2d/light_2d.cpp
+++ b/scene/2d/light_2d.cpp
@@ -96,6 +96,21 @@ float Light2D::get_height() const {
return height;
}
+void Light2D::set_energy( float p_energy) {
+
+ energy=p_energy;
+ VS::get_singleton()->canvas_light_set_energy(canvas_light,energy);
+
+}
+
+
+float Light2D::get_energy() const {
+
+ return energy;
+}
+
+
+
void Light2D::set_texture_scale( float p_scale) {
_scale=p_scale;
@@ -178,15 +193,15 @@ int Light2D::get_item_shadow_mask() const {
return item_shadow_mask;
}
-void Light2D::set_subtract_mode( bool p_enable ) {
+void Light2D::set_mode( Mode p_mode ) {
- subtract_mode=p_enable;
- VS::get_singleton()->canvas_light_set_subtract_mode(canvas_light,p_enable);
+ mode=p_mode;
+ VS::get_singleton()->canvas_light_set_mode(canvas_light,VS::CanvasLightMode(p_mode));
}
-bool Light2D::get_subtract_mode() const {
+Light2D::Mode Light2D::get_mode() const {
- return subtract_mode;
+ return mode;
}
void Light2D::set_shadow_enabled( bool p_enabled) {
@@ -260,6 +275,9 @@ void Light2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_height","height"),&Light2D::set_height);
ObjectTypeDB::bind_method(_MD("get_height"),&Light2D::get_height);
+ ObjectTypeDB::bind_method(_MD("set_energy","energy"),&Light2D::set_energy);
+ ObjectTypeDB::bind_method(_MD("get_energy"),&Light2D::get_energy);
+
ObjectTypeDB::bind_method(_MD("set_texture_scale","texture_scale"),&Light2D::set_texture_scale);
ObjectTypeDB::bind_method(_MD("get_texture_scale"),&Light2D::get_texture_scale);
@@ -283,8 +301,8 @@ void Light2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_item_shadow_mask","item_shadow_mask"),&Light2D::set_item_shadow_mask);
ObjectTypeDB::bind_method(_MD("get_item_shadow_mask"),&Light2D::get_item_shadow_mask);
- ObjectTypeDB::bind_method(_MD("set_subtract_mode","enable"),&Light2D::set_subtract_mode);
- ObjectTypeDB::bind_method(_MD("get_subtract_mode"),&Light2D::get_subtract_mode);
+ ObjectTypeDB::bind_method(_MD("set_mode","mode"),&Light2D::set_mode);
+ ObjectTypeDB::bind_method(_MD("get_mode"),&Light2D::get_mode);
ObjectTypeDB::bind_method(_MD("set_shadow_enabled","enabled"),&Light2D::set_shadow_enabled);
ObjectTypeDB::bind_method(_MD("is_shadow_enabled"),&Light2D::is_shadow_enabled);
@@ -300,7 +318,8 @@ void Light2D::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"offset"),_SCS("set_texture_offset"),_SCS("get_texture_offset"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"scale",PROPERTY_HINT_RANGE,"0.01,4096,0.01"),_SCS("set_texture_scale"),_SCS("get_texture_scale"));
ADD_PROPERTY( PropertyInfo(Variant::COLOR,"color"),_SCS("set_color"),_SCS("get_color"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"subtract"),_SCS("set_subtract_mode"),_SCS("get_subtract_mode"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"energy"),_SCS("set_energy"),_SCS("get_energy"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Add,Sub,Mix"),_SCS("set_mode"),_SCS("get_mode"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"range/height"),_SCS("set_height"),_SCS("get_height"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"range/z_min",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_min"),_SCS("get_z_range_min"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"range/z_max",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_max"),_SCS("get_z_range_max"));
@@ -312,6 +331,10 @@ void Light2D::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::REAL,"shadow/esm_multiplier",PROPERTY_HINT_RANGE,"1,4096,0.1"),_SCS("set_shadow_esm_multiplier"),_SCS("get_shadow_esm_multiplier"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"shadow/item_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_item_shadow_mask"),_SCS("get_item_shadow_mask"));
+ BIND_CONSTANT( MODE_ADD );
+ BIND_CONSTANT( MODE_SUB );
+ BIND_CONSTANT( MODE_MIX );
+
}
@@ -329,9 +352,10 @@ Light2D::Light2D() {
layer_max=0;
item_mask=1;
item_shadow_mask=1;
- subtract_mode=false;
+ mode=MODE_ADD;
shadow_buffer_size=2048;
shadow_esm_multiplier=80;
+ energy=1.0;
}
diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h
index 6cfb055fa9..ef875aec2f 100644
--- a/scene/2d/light_2d.h
+++ b/scene/2d/light_2d.h
@@ -6,6 +6,13 @@
class Light2D : public Node2D {
OBJ_TYPE(Light2D,Node2D);
+public:
+ enum Mode {
+ MODE_ADD,
+ MODE_SUB,
+ MODE_MIX,
+ };
+
private:
RID canvas_light;
bool enabled;
@@ -13,6 +20,7 @@ private:
Color color;
float height;
float _scale;
+ float energy;
int z_min;
int z_max;
int layer_min;
@@ -21,7 +29,7 @@ private:
int item_shadow_mask;
int shadow_buffer_size;
float shadow_esm_multiplier;
- bool subtract_mode;
+ Mode mode;
Ref<Texture> texture;
Vector2 texture_offset;
@@ -51,6 +59,9 @@ public:
void set_height( float p_height);
float get_height() const;
+ void set_energy( float p_energy);
+ float get_energy() const;
+
void set_texture_scale( float p_scale);
float get_texture_scale() const;
@@ -72,8 +83,8 @@ public:
void set_item_shadow_mask( int p_mask);
int get_item_shadow_mask() const;
- void set_subtract_mode( bool p_enable );
- bool get_subtract_mode() const;
+ void set_mode( Mode p_mode );
+ Mode get_mode() const;
void set_shadow_enabled( bool p_enabled);
bool is_shadow_enabled() const;
@@ -90,5 +101,6 @@ public:
~Light2D();
};
+VARIANT_ENUM_CAST(Light2D::Mode);
#endif // LIGHT_2D_H
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 22dd0f01d0..5457182ea7 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -1198,7 +1198,7 @@ void KinematicBody2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("move","rel_vec"),&KinematicBody2D::move);
ObjectTypeDB::bind_method(_MD("move_to","position"),&KinematicBody2D::move_to);
- ObjectTypeDB::bind_method(_MD("can_move_to","position"),&KinematicBody2D::can_move_to);
+ ObjectTypeDB::bind_method(_MD("can_move_to","position","discrete"),&KinematicBody2D::can_move_to,DEFVAL(false));
ObjectTypeDB::bind_method(_MD("is_colliding"),&KinematicBody2D::is_colliding);
diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp
index cd3c788b65..abaaf3262a 100644
--- a/scene/2d/visibility_notifier_2d.cpp
+++ b/scene/2d/visibility_notifier_2d.cpp
@@ -65,8 +65,13 @@ void VisibilityNotifier2D::_exit_viewport(Viewport* p_viewport){
void VisibilityNotifier2D::set_rect(const Rect2& p_rect){
rect=p_rect;
- if (is_inside_tree())
+ if (is_inside_tree()) {
get_world_2d()->_update_notifier(this,get_global_transform().xform(rect));
+ if (get_tree()->is_editor_hint()) {
+ update();
+ item_rect_changed();
+ }
+ }
_change_notify("rect");
}
diff --git a/scene/3d/navigation.cpp b/scene/3d/navigation.cpp
index ce002fb44b..6612d6bf12 100644
--- a/scene/3d/navigation.cpp
+++ b/scene/3d/navigation.cpp
@@ -490,10 +490,10 @@ Vector<Vector3> Navigation::get_simple_path(const Vector3& p_start, const Vector
}
-Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vector3& p_to) {
+Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vector3& p_to,const bool& p_use_collision) {
- bool use_collision=false;
+ bool use_collision=p_use_collision;
Vector3 closest_point;
float closest_point_d=1e20;
NavMesh *closest_navmesh=NULL;
@@ -633,7 +633,7 @@ void Navigation::_bind_methods() {
ObjectTypeDB::bind_method(_MD("navmesh_remove","id"),&Navigation::navmesh_remove);
ObjectTypeDB::bind_method(_MD("get_simple_path","start","end","optimize"),&Navigation::get_simple_path,DEFVAL(true));
- ObjectTypeDB::bind_method(_MD("get_closest_point_to_segment","start","end"),&Navigation::get_closest_point_to_segment);
+ ObjectTypeDB::bind_method(_MD("get_closest_point_to_segment","start","end","use_collision"),&Navigation::get_closest_point_to_segment,DEFVAL(false));
ObjectTypeDB::bind_method(_MD("get_closest_point","to_point"),&Navigation::get_closest_point);
ObjectTypeDB::bind_method(_MD("get_closest_point_normal","to_point"),&Navigation::get_closest_point_normal);
diff --git a/scene/3d/navigation.h b/scene/3d/navigation.h
index 69d48531a7..19977c3110 100644
--- a/scene/3d/navigation.h
+++ b/scene/3d/navigation.h
@@ -135,7 +135,7 @@ public:
void navmesh_remove(int p_id);
Vector<Vector3> get_simple_path(const Vector3& p_start, const Vector3& p_end,bool p_optimize=true);
- Vector3 get_closest_point_to_segment(const Vector3& p_from,const Vector3& p_to);
+ Vector3 get_closest_point_to_segment(const Vector3& p_from,const Vector3& p_to,const bool& p_use_collision=false);
Vector3 get_closest_point(const Vector3& p_point);
Vector3 get_closest_point_normal(const Vector3& p_point);
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 86f442fd8c..c539dc3284 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -2869,7 +2869,7 @@ void Control::_bind_methods() {
BIND_CONSTANT( SIZE_EXPAND_FILL );
ADD_SIGNAL( MethodInfo("resized") );
- ADD_SIGNAL( MethodInfo("input_event") );
+ ADD_SIGNAL( MethodInfo("input_event",PropertyInfo(Variant::INPUT_EVENT,"ev")) );
ADD_SIGNAL( MethodInfo("mouse_enter") );
ADD_SIGNAL( MethodInfo("mouse_exit") );
ADD_SIGNAL( MethodInfo("focus_enter") );
diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp
index ed3e419359..8e2dc93288 100644
--- a/scene/main/scene_main_loop.cpp
+++ b/scene/main/scene_main_loop.cpp
@@ -850,6 +850,7 @@ void SceneTree::queue_delete(Object *p_object) {
_THREAD_SAFE_METHOD_
ERR_FAIL_NULL(p_object);
+ p_object->_is_queued_for_deletion = true;
delete_queue.push_back(p_object->get_instance_ID());
}
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index ee400ae6d5..f0c71da153 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -406,7 +406,7 @@ void Viewport::_notification(int p_what) {
int rc = ss2d->intersect_point(point,res,64,Set<RID>(),0xFFFFFFFF,0xFFFFFFFF);
for(int i=0;i<rc;i++) {
- if (res[i].collider) {
+ if (res[i].collider_id && res[i].collider) {
CollisionObject2D *co=res[i].collider->cast_to<CollisionObject2D>();
if (co) {
diff --git a/scene/resources/shader_graph.cpp b/scene/resources/shader_graph.cpp
index b0d9ceee0e..be54d649e2 100644
--- a/scene/resources/shader_graph.cpp
+++ b/scene/resources/shader_graph.cpp
@@ -1351,15 +1351,24 @@ const ShaderGraph::InOutParamInfo ShaderGraph::inout_param_info[]={
{MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Normal","NORMAL","",SLOT_TYPE_VEC,SLOT_OUT},
//canvas item light in
{MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"Color","COLOR.rgb","",SLOT_TYPE_VEC,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"Alpha","COLOR.a","",SLOT_TYPE_SCALAR,SLOT_IN},
{MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"Normal","NORMAL","",SLOT_TYPE_VEC,SLOT_IN},
- {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightDist","LIGHT_DISTANCE","",SLOT_TYPE_SCALAR,SLOT_IN},
- {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightDir","vec3(LIGHT_DIR,0)","",SLOT_TYPE_VEC,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"UV","vec3(UV,0)","",SLOT_TYPE_VEC,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightColor","LIGHT_COLOR.rgb","",SLOT_TYPE_VEC,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightAlpha","LIGHT_COLOR.a","",SLOT_TYPE_SCALAR,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightHeight","LIGHT_HEIGHT","",SLOT_TYPE_SCALAR,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"TexPixelSize","vec3(TEXTURE_PIXEL_SIZE,0)","",SLOT_TYPE_VEC,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"Var1","VAR1.rgb","",SLOT_TYPE_VEC,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"Var2","VAR2.rgb","",SLOT_TYPE_VEC,SLOT_IN},
{MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"PointCoord","POINT_COORD","",SLOT_TYPE_VEC,SLOT_IN},
//canvas item light out
- {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"Light","LIGHT","",SLOT_TYPE_VEC,SLOT_OUT},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightColor","LIGHT.rgb","",SLOT_TYPE_VEC,SLOT_OUT},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightAlpha","LIGHT.a","",SLOT_TYPE_SCALAR,SLOT_OUT},
//end
{MODE_MATERIAL,SHADER_TYPE_FRAGMENT,NULL,NULL,NULL,SLOT_TYPE_SCALAR,SLOT_OUT},
+
+
};
void ShaderGraph::get_input_output_node_slot_info(Mode p_mode, ShaderType p_type, List<SlotInfo> *r_slots) {
diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp
index d4159f0946..76cb5929cf 100644
--- a/scene/scene_string_names.cpp
+++ b/scene/scene_string_names.cpp
@@ -42,6 +42,7 @@ SceneStringNames::SceneStringNames() {
input_event=StaticCString::create("input_event");
shader_shader=StaticCString::create("shader/shader");
shader_unshaded=StaticCString::create("shader/unshaded");
+ shading_mode=StaticCString::create("shader/shading_mode");
enter_tree=StaticCString::create("enter_tree");
exit_tree=StaticCString::create("exit_tree");
item_rect_changed=StaticCString::create("item_rect_changed");
diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h
index aa29ef57dc..a69e8ba0b5 100644
--- a/scene/scene_string_names.h
+++ b/scene/scene_string_names.h
@@ -57,6 +57,7 @@ public:
StringName item_rect_changed;
StringName shader_shader;
StringName shader_unshaded;
+ StringName shading_mode;
StringName enter_tree;
StringName exit_tree;
StringName size_flags_changed;
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index ebc210fe3d..62563a0771 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -577,6 +577,7 @@ public:
Color color;
Matrix32 xform;
float height;
+ float energy;
float scale;
int z_min;
int z_max;
@@ -584,7 +585,7 @@ public:
int layer_max;
int item_mask;
int item_shadow_mask;
- bool subtract;
+ VS::CanvasLightMode mode;
RID texture;
Vector2 texture_offset;
RID canvas;
@@ -616,8 +617,9 @@ public:
layer_max=0;
item_mask=1;
scale=1.0;
+ energy=1.0;
item_shadow_mask=-1;
- subtract=false;
+ mode=VS::CANVAS_LIGHT_MODE_ADD;
texture_cache=NULL;
next_ptr=NULL;
filter_next_ptr=NULL;
@@ -635,9 +637,9 @@ public:
Map<StringName,Variant> shader_param;
uint32_t shader_version;
Set<CanvasItem*> owners;
- bool unshaded;
+ VS::CanvasItemShadingMode shading_mode;
- CanvasItemMaterial() {unshaded=false; shader_version=0; }
+ CanvasItemMaterial() {shading_mode=VS::CANVAS_ITEM_SHADING_NORMAL; shader_version=0; }
};
struct CanvasItem {
diff --git a/servers/visual/rasterizer_dummy.cpp b/servers/visual/rasterizer_dummy.cpp
index 7fb8eb02fc..45b29f5484 100644
--- a/servers/visual/rasterizer_dummy.cpp
+++ b/servers/visual/rasterizer_dummy.cpp
@@ -1545,9 +1545,36 @@ void RasterizerDummy::end_frame() {
}
+RID RasterizerDummy::canvas_light_occluder_create() {
+ return RID();
+}
+
+void RasterizerDummy::canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines) {
+
+
+}
+
+RID RasterizerDummy::canvas_light_shadow_buffer_create(int p_width) {
+
+ return RID();
+}
+
+void RasterizerDummy::canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache) {
+
+
+}
+
+void RasterizerDummy::canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow) {
+
+
+}
+
/* CANVAS API */
+void RasterizerDummy::begin_canvas_bg() {
+
+}
void RasterizerDummy::canvas_begin() {
@@ -1761,6 +1788,11 @@ bool RasterizerDummy::is_environment(const RID& p_rid) const {
return environment_owner.owns(p_rid);
}
+bool RasterizerDummy::is_canvas_light_occluder(const RID& p_rid) const {
+
+ return false;
+}
+
bool RasterizerDummy::is_shader(const RID& p_rid) const {
return false;
diff --git a/servers/visual/rasterizer_dummy.h b/servers/visual/rasterizer_dummy.h
index baa48951d6..99c76a1917 100644
--- a/servers/visual/rasterizer_dummy.h
+++ b/servers/visual/rasterizer_dummy.h
@@ -696,6 +696,7 @@ public:
/* CANVAS API */
+ virtual void begin_canvas_bg();
virtual void canvas_begin();
virtual void canvas_disable_blending();
virtual void canvas_set_opacity(float p_opacity);
@@ -712,6 +713,14 @@ public:
virtual void canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light);
+ virtual RID canvas_light_occluder_create();
+ virtual void canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines);
+
+ virtual RID canvas_light_shadow_buffer_create(int p_width);
+ virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache);
+
+ virtual void canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow);
+
/* ENVIRONMENT */
virtual RID environment_create();
@@ -747,6 +756,7 @@ public:
virtual bool is_particles_instance(const RID& p_rid) const;
virtual bool is_skeleton(const RID& p_rid) const;
virtual bool is_environment(const RID& p_rid) const;
+ virtual bool is_canvas_light_occluder(const RID& p_rid) const;
virtual bool is_shader(const RID& p_rid) const;
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index af65a7a639..4ad8aa6c71 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -1171,7 +1171,9 @@ const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_light_builtins_defs[]={
{ "LIGHT_VEC", TYPE_VEC2},
{ "LIGHT_HEIGHT", TYPE_FLOAT},
{ "LIGHT_COLOR", TYPE_VEC4},
+ { "LIGHT_UV", TYPE_VEC2},
{ "LIGHT", TYPE_VEC4},
+ { "SHADOW", TYPE_VEC4},
{ "POINT_COORD", TYPE_VEC2},
// { "SCREEN_POS", TYPE_VEC2},
// { "SCREEN_TEXEL_SIZE", TYPE_VEC2},
diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp
index 83bfbbc6c3..7a9db4ba11 100644
--- a/servers/visual/visual_server_raster.cpp
+++ b/servers/visual/visual_server_raster.cpp
@@ -3977,6 +3977,15 @@ void VisualServerRaster::canvas_light_set_height(RID p_light, float p_height){
clight->height=p_height;
}
+
+void VisualServerRaster::canvas_light_set_energy(RID p_light, float p_energy){
+
+ Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+ clight->energy=p_energy;
+
+}
+
void VisualServerRaster::canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z){
Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
@@ -4012,12 +4021,12 @@ void VisualServerRaster::canvas_light_set_item_shadow_mask(RID p_light, int p_ma
}
-void VisualServerRaster::canvas_light_set_subtract_mode(RID p_light, bool p_enable) {
+void VisualServerRaster::canvas_light_set_mode(RID p_light, CanvasLightMode p_mode) {
Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
- clight->subtract=p_enable;
+ clight->mode=p_mode;
}
void VisualServerRaster::canvas_light_set_shadow_enabled(RID p_light, bool p_enabled){
@@ -4267,12 +4276,12 @@ Variant VisualServerRaster::canvas_item_material_get_shader_param(RID p_material
return material->shader_param[p_param];
}
-void VisualServerRaster::canvas_item_material_set_unshaded(RID p_material, bool p_unshaded){
+void VisualServerRaster::canvas_item_material_set_shading_mode(RID p_material, CanvasItemShadingMode p_mode) {
VS_CHANGED;
Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material );
ERR_FAIL_COND(!material);
- material->unshaded=p_unshaded;
+ material->shading_mode=p_mode;
}
@@ -7155,7 +7164,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
}
- //rasterizer->canvas_debug_viewport_shadows(lights_with_shadow);
+// rasterizer->canvas_debug_viewport_shadows(lights_with_shadow);
}
//capture
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index 72af793278..a89a685e30 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -1170,12 +1170,13 @@ public:
virtual void canvas_light_set_texture_offset(RID p_light, const Vector2& p_offset);
virtual void canvas_light_set_color(RID p_light, const Color& p_color);
virtual void canvas_light_set_height(RID p_light, float p_height);
+ virtual void canvas_light_set_energy(RID p_light, float p_energy);
virtual void canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z);
virtual void canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer);
virtual void canvas_light_set_item_mask(RID p_light, int p_mask);
virtual void canvas_light_set_item_shadow_mask(RID p_light, int p_mask);
- virtual void canvas_light_set_subtract_mode(RID p_light, bool p_enable);
+ virtual void canvas_light_set_mode(RID p_light, CanvasLightMode p_mode);
virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled);
virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size);
virtual void canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier);
@@ -1204,8 +1205,9 @@ public:
virtual RID canvas_item_material_create();
virtual void canvas_item_material_set_shader(RID p_material, RID p_shader);
virtual void canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value);
- virtual Variant canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const;
- virtual void canvas_item_material_set_unshaded(RID p_material, bool p_unshaded);
+ virtual Variant canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const;
+ virtual void canvas_item_material_set_shading_mode(RID p_material, CanvasItemShadingMode p_mode);
+
/* CURSOR */
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index ded4c6fc00..6cd374aa08 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -1160,12 +1160,13 @@ public:
FUNC2(canvas_light_set_texture_offset,RID,const Vector2&);
FUNC2(canvas_light_set_color,RID,const Color&);
FUNC2(canvas_light_set_height,RID,float);
+ FUNC2(canvas_light_set_energy,RID,float);
FUNC3(canvas_light_set_layer_range,RID,int,int);
FUNC3(canvas_light_set_z_range,RID,int,int);
FUNC2(canvas_light_set_item_mask,RID,int);
FUNC2(canvas_light_set_item_shadow_mask,RID,int);
- FUNC2(canvas_light_set_subtract_mode,RID,bool);
+ FUNC2(canvas_light_set_mode,RID,CanvasLightMode);
FUNC2(canvas_light_set_shadow_enabled,RID,bool);
FUNC2(canvas_light_set_shadow_buffer_size,RID,int);
FUNC2(canvas_light_set_shadow_esm_multiplier,RID,float);
@@ -1191,8 +1192,8 @@ public:
FUNC0R(RID,canvas_item_material_create);
FUNC2(canvas_item_material_set_shader,RID,RID);
FUNC3(canvas_item_material_set_shader_param,RID,const StringName&,const Variant&);
- FUNC2RC(Variant,canvas_item_material_get_shader_param,RID,const StringName&);
- FUNC2(canvas_item_material_set_unshaded,RID,bool);
+ FUNC2RC(Variant,canvas_item_material_get_shader_param,RID,const StringName&);
+ FUNC2(canvas_item_material_set_shading_mode,RID,CanvasItemShadingMode);
/* CURSOR */
FUNC2(cursor_set_rotation,float , int ); // radians
diff --git a/servers/visual_server.h b/servers/visual_server.h
index b6d354454e..e9425afbab 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -1014,12 +1014,19 @@ public:
virtual void canvas_light_set_texture_offset(RID p_light, const Vector2& p_offset)=0;
virtual void canvas_light_set_color(RID p_light, const Color& p_color)=0;
virtual void canvas_light_set_height(RID p_light, float p_height)=0;
+ virtual void canvas_light_set_energy(RID p_light, float p_energy)=0;
virtual void canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z)=0;
virtual void canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer)=0;
virtual void canvas_light_set_item_mask(RID p_light, int p_mask)=0;
virtual void canvas_light_set_item_shadow_mask(RID p_light, int p_mask)=0;
- virtual void canvas_light_set_subtract_mode(RID p_light, bool p_enable)=0;
+ enum CanvasLightMode {
+ CANVAS_LIGHT_MODE_ADD,
+ CANVAS_LIGHT_MODE_SUB,
+ CANVAS_LIGHT_MODE_MIX,
+ };
+
+ virtual void canvas_light_set_mode(RID p_light, CanvasLightMode p_mode)=0;
virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled)=0;
virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size)=0;
virtual void canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier)=0;
@@ -1049,7 +1056,15 @@ public:
virtual void canvas_item_material_set_shader(RID p_material, RID p_shader)=0;
virtual void canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value)=0;
virtual Variant canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const=0;
- virtual void canvas_item_material_set_unshaded(RID p_material, bool p_unshaded)=0;
+
+
+ enum CanvasItemShadingMode {
+ CANVAS_ITEM_SHADING_NORMAL,
+ CANVAS_ITEM_SHADING_UNSHADED,
+ CANVAS_ITEM_SHADING_ONLY_LIGHT,
+ };
+
+ virtual void canvas_item_material_set_shading_mode(RID p_material, CanvasItemShadingMode p_mode)=0;
/* CURSOR */
virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0)=0; // radians
diff --git a/tools/editor/editor_help.cpp b/tools/editor/editor_help.cpp
index 2283a2df14..7deb136470 100644
--- a/tools/editor/editor_help.cpp
+++ b/tools/editor/editor_help.cpp
@@ -1390,7 +1390,9 @@ EditorHelp::EditorHelp(EditorNode *p_editor) {
{
PanelContainer *pc = memnew( PanelContainer );
- pc->add_style_override("panel",get_stylebox("normal","TextEdit"));
+ Ref<StyleBoxFlat> style( memnew( StyleBoxFlat ) );
+ style->set_bg_color( EditorSettings::get_singleton()->get("text_editor/background_color") );
+ pc->add_style_override("panel", style); //get_stylebox("normal","TextEdit"));
h_split->add_child(pc);
class_desc = memnew( RichTextLabel );
pc->add_child(class_desc);
diff --git a/tools/editor/plugins/mesh_editor_plugin.cpp b/tools/editor/plugins/mesh_editor_plugin.cpp
index a3884f9be4..f8c75e1cf5 100644
--- a/tools/editor/plugins/mesh_editor_plugin.cpp
+++ b/tools/editor/plugins/mesh_editor_plugin.cpp
@@ -33,7 +33,7 @@ void MeshInstanceEditor::_menu_option(int p_option) {
Ref<Mesh> mesh = node->get_mesh();
if (mesh.is_null()) {
err_dialog->set_text("Mesh is empty!");
- err_dialog->popup_centered(Size2(100,50));
+ err_dialog->popup_centered(Size2(100,80));
return;
}
@@ -240,6 +240,9 @@ MeshInstanceEditor::MeshInstanceEditor() {
add_child(outline_dialog);
outline_dialog->connect("confirmed",this,"_create_outline_mesh");
+ err_dialog = memnew( AcceptDialog );
+ add_child(err_dialog);
+
}
diff --git a/tools/editor/plugins/shader_graph_editor_plugin.cpp b/tools/editor/plugins/shader_graph_editor_plugin.cpp
index 508e8b4cba..e829c06e6f 100644
--- a/tools/editor/plugins/shader_graph_editor_plugin.cpp
+++ b/tools/editor/plugins/shader_graph_editor_plugin.cpp
@@ -376,7 +376,7 @@ void GraphCurveMapEdit::_input_event(const InputEvent& p_event) {
update();
}
- if (p_event.type==InputEvent::MOUSE_MOTION && grabbing) {
+ if (p_event.type==InputEvent::MOUSE_MOTION && grabbing && grabbed != -1) {
Point2 p = Vector2(p_event.mouse_button.x,p_event.mouse_button.y)/get_size();
p.y=1.0-p.y;
diff --git a/tools/editor/plugins/sprite_frames_editor_plugin.cpp b/tools/editor/plugins/sprite_frames_editor_plugin.cpp
index e04d9dfddb..9a9e8ee611 100644
--- a/tools/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/tools/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -229,6 +229,33 @@ void SpriteFramesEditor::_empty_pressed() {
}
+void SpriteFramesEditor::_empty2_pressed() {
+
+
+ int from=-1;
+
+ if (tree->get_selected()) {
+
+ from = tree->get_selected()->get_metadata(0);
+ sel=from;
+
+ } else {
+ from=frames->get_frame_count();
+ }
+
+
+
+ Ref<Texture> r;
+
+ undo_redo->create_action("Add Empty");
+ undo_redo->add_do_method(frames,"add_frame",r,from+1);
+ undo_redo->add_undo_method(frames,"remove_frame",from+1);
+ undo_redo->add_do_method(this,"_update_library");
+ undo_redo->add_undo_method(this,"_update_library");
+ undo_redo->commit_action();
+
+}
+
void SpriteFramesEditor::_up_pressed() {
if (!tree->get_selected())
@@ -322,6 +349,8 @@ void SpriteFramesEditor::_update_library() {
ti->set_text(0,"Frame "+itos(i));
ti->set_icon(0,frames->get_frame(i));
}
+ if (frames->get_frame(i).is_valid())
+ ti->set_tooltip(0,frames->get_frame(i)->get_path());
ti->set_metadata(0,i);
ti->set_icon_max_width(0,96);
if (sel==i)
@@ -355,6 +384,7 @@ void SpriteFramesEditor::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_input_event"),&SpriteFramesEditor::_input_event);
ObjectTypeDB::bind_method(_MD("_load_pressed"),&SpriteFramesEditor::_load_pressed);
ObjectTypeDB::bind_method(_MD("_empty_pressed"),&SpriteFramesEditor::_empty_pressed);
+ ObjectTypeDB::bind_method(_MD("_empty2_pressed"),&SpriteFramesEditor::_empty2_pressed);
ObjectTypeDB::bind_method(_MD("_item_edited"),&SpriteFramesEditor::_item_edited);
ObjectTypeDB::bind_method(_MD("_delete_pressed"),&SpriteFramesEditor::_delete_pressed);
ObjectTypeDB::bind_method(_MD("_paste_pressed"),&SpriteFramesEditor::_paste_pressed);
@@ -387,9 +417,13 @@ SpriteFramesEditor::SpriteFramesEditor() {
hbc->add_child(paste);
empty = memnew( Button );
- empty->set_text("Insert Empty");
+ empty->set_text("Insert Empty (Before)");
hbc->add_child(empty);
+ empty2 = memnew( Button );
+ empty2->set_text("Insert Empty (After)");
+ hbc->add_child(empty2);
+
move_up = memnew( Button );
move_up->set_text("Up");
hbc->add_child(move_up);
@@ -422,6 +456,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
_delete->connect("pressed", this,"_delete_pressed");
paste->connect("pressed", this,"_paste_pressed");
empty->connect("pressed", this,"_empty_pressed");
+ empty2->connect("pressed", this,"_empty2_pressed");
move_up->connect("pressed", this,"_up_pressed");
move_down->connect("pressed", this,"_down_pressed");
file->connect("files_selected", this,"_file_load_request");
diff --git a/tools/editor/plugins/sprite_frames_editor_plugin.h b/tools/editor/plugins/sprite_frames_editor_plugin.h
index 99c6ad486e..b0f2201b9e 100644
--- a/tools/editor/plugins/sprite_frames_editor_plugin.h
+++ b/tools/editor/plugins/sprite_frames_editor_plugin.h
@@ -46,6 +46,7 @@ class SpriteFramesEditor : public PanelContainer {
Button *_delete;
Button *paste;
Button *empty;
+ Button *empty2;
Button *move_up;
Button *move_down;
Tree *tree;
@@ -65,6 +66,7 @@ class SpriteFramesEditor : public PanelContainer {
void _file_load_request(const DVector<String>& p_path);
void _paste_pressed();
void _empty_pressed();
+ void _empty2_pressed();
void _delete_pressed();
void _delete_confirm_pressed();
void _up_pressed();
diff --git a/tools/editor/pvrtc_compress.cpp b/tools/editor/pvrtc_compress.cpp
index 9511d6a26d..777a05f272 100644
--- a/tools/editor/pvrtc_compress.cpp
+++ b/tools/editor/pvrtc_compress.cpp
@@ -32,11 +32,34 @@
#include "io/resource_saver.h"
#include "io/resource_loader.h"
#include "os/os.h"
-
+#include "os/file_access.h"
+static void (*_base_image_compress_pvrtc2_func)(Image *)=NULL;
+static void (*_base_image_compress_pvrtc4_func)(Image *)=NULL;
static void _compress_image(Image::CompressMode p_mode,Image *p_image) {
String ttpath = EditorSettings::get_singleton()->get("PVRTC/texture_tool");
+
+ if (ttpath.strip_edges()=="" || !FileAccess::exists(ttpath)) {
+ switch(p_mode) {
+
+ case Image::COMPRESS_PVRTC2:
+ if (_base_image_compress_pvrtc2_func)
+ _base_image_compress_pvrtc2_func(p_image);
+ else if (_base_image_compress_pvrtc4_func)
+ _base_image_compress_pvrtc4_func(p_image);
+
+ break;
+ case Image::COMPRESS_PVRTC4:
+ if (_base_image_compress_pvrtc4_func)
+ _base_image_compress_pvrtc4_func(p_image);
+
+ break;
+ default: ERR_FAIL();
+
+ }
+ return;
+ }
String spath = EditorSettings::get_singleton()->get_settings_path();
@@ -100,6 +123,9 @@ static void _compress_etc(Image *p_image) {
void _pvrtc_register_compressors() {
+ _base_image_compress_pvrtc2_func=Image::_image_compress_pvrtc2_func;
+ _base_image_compress_pvrtc4_func=Image::_image_compress_pvrtc4_func;
+
Image::_image_compress_pvrtc2_func=_compress_pvrtc2;
Image::_image_compress_pvrtc4_func=_compress_pvrtc4;
//Image::_image_compress_etc_func=_compress_etc; //use the built in one for ETC
diff --git a/tools/editor/scene_tree_dock.cpp b/tools/editor/scene_tree_dock.cpp
index 2012d96664..84b34cf130 100644
--- a/tools/editor/scene_tree_dock.cpp
+++ b/tools/editor/scene_tree_dock.cpp
@@ -1059,14 +1059,15 @@ void SceneTreeDock::_create() {
if (edited_scene) {
-
+ // If root exists in edited scene
parent = scene_tree->get_selected();
- ERR_FAIL_COND(!parent);
- } else {
+ if( !parent )
+ parent = edited_scene;
+ } else {
+ // If no root exist in edited scene
parent = scene_root;
ERR_FAIL_COND(!parent);
-
}
Object *c = create_dialog->instance_selected();
diff --git a/tools/export/blender25/io_scene_dae/export_dae.py b/tools/export/blender25/io_scene_dae/export_dae.py
index 5e5febfb1f..020ab6ca08 100644
--- a/tools/export/blender25/io_scene_dae/export_dae.py
+++ b/tools/export/blender25/io_scene_dae/export_dae.py
@@ -208,13 +208,16 @@ class DaeExporter:
imgid = self.new_id("image")
+
+ print("FOR: "+imgpath)
- if (not os.path.isfile(imgpath)):
- if imgpath.endswith((".bmp",".rgb",".png",".jpeg",".jpg",".jp2",".tga",".cin",".dpx",".exr",".hdr",".tif")):
- imgpath="images/"+os.path.basename(imgpath)
- else:
- imgpath="images/"+image.name+".png"
-
+# if (not os.path.isfile(imgpath)):
+# print("NOT FILE?")
+# if imgpath.endswith((".bmp",".rgb",".png",".jpeg",".jpg",".jp2",".tga",".cin",".dpx",".exr",".hdr",".tif")):
+# imgpath="images/"+os.path.basename(imgpath)
+# else:
+# imgpath="images/"+image.name+".png"
+
self.writel(S_IMGS,1,'<image id="'+imgid+'" name="'+image.name+'">')
self.writel(S_IMGS,2,'<init_from>'+imgpath+'</init_from>"/>')
self.writel(S_IMGS,1,'</image>')
@@ -529,8 +532,8 @@ class DaeExporter:
if (not (f.material_index in surface_indices)):
surface_indices[f.material_index]=[]
- print("Type: "+str(type(f.material_index)))
- print("IDX: "+str(f.material_index)+"/"+str(len(mesh.materials)))
+ #print("Type: "+str(type(f.material_index)))
+ #print("IDX: "+str(f.material_index)+"/"+str(len(mesh.materials)))
try:
#Bizarre blender behavior i don't understand, so catching exception
@@ -914,14 +917,14 @@ class DaeExporter:
if (node.data.shape_keys!=None):
sk = node.data.shape_keys
if (sk.animation_data):
- print("HAS ANIM")
- print("DRIVERS: "+str(len(sk.animation_data.drivers)))
+ #print("HAS ANIM")
+ #print("DRIVERS: "+str(len(sk.animation_data.drivers)))
for d in sk.animation_data.drivers:
if (d.driver):
for v in d.driver.variables:
for t in v.targets:
if (t.id!=None and t.id.name in self.scene.objects):
- print("LINKING "+str(node)+" WITH "+str(t.id.name))
+ #print("LINKING "+str(node)+" WITH "+str(t.id.name))
self.armature_for_morph[node]=self.scene.objects[t.id.name]
@@ -1234,7 +1237,7 @@ class DaeExporter:
il+=1
self.writel(S_NODES,il,'<matrix sid="transform">'+strmtx(node.matrix_local)+'</matrix>')
- print("NODE TYPE: "+node.type+" NAME: "+node.name)
+ #print("NODE TYPE: "+node.type+" NAME: "+node.name)
if (node.type=="MESH"):
self.export_mesh_node(node,il)
elif (node.type=="CURVE"):
@@ -1258,7 +1261,7 @@ class DaeExporter:
return False
if (self.config["use_active_layers"]):
valid=False
- print("NAME: "+node.name)
+ #print("NAME: "+node.name)
for i in range(20):
if (node.layers[i] and self.scene.layers[i]):
valid=True
@@ -1408,7 +1411,7 @@ class DaeExporter:
# Change frames first, export objects last
# This improves performance enormously
- print("anim from: "+str(start)+" to "+str(end)+" allowed: "+str(allowed))
+ #print("anim from: "+str(start)+" to "+str(end)+" allowed: "+str(allowed))
for t in range(start,end+1):
self.scene.frame_set(t)
key = t * frame_len - frame_sub
@@ -1462,7 +1465,7 @@ class DaeExporter:
bone_name=self.skeleton_info[node]["bone_ids"][bone]
if (not (bone_name in xform_cache)):
- print("has bone: "+bone_name)
+ #print("has bone: "+bone_name)
xform_cache[bone_name]=[]
posebone = node.pose.bones[bone.name]
@@ -1548,15 +1551,15 @@ class DaeExporter:
bone.matrix_basis = Matrix()
- print("allowed skeletons "+str(allowed_skeletons))
+ #print("allowed skeletons "+str(allowed_skeletons))
- print(str(x))
+ #print(str(x))
tcn = self.export_animation(int(x.frame_range[0]),int(x.frame_range[1]+0.5),allowed_skeletons)
framelen=(1.0/self.scene.render.fps)
start = x.frame_range[0]*framelen
end = x.frame_range[1]*framelen
- print("Export anim: "+x.name)
+ #print("Export anim: "+x.name)
self.writel(S_ANIM_CLIPS,1,'<animation_clip name="'+x.name+'" start="'+str(start)+'" end="'+str(end)+'">')
for z in tcn:
self.writel(S_ANIM_CLIPS,2,'<instance_animation url="#'+z+'"/>')
diff --git a/version.py b/version.py
index 86601a22f2..46490c48f4 100644
--- a/version.py
+++ b/version.py
@@ -1,7 +1,7 @@
short_name="godot"
name="Godot Engine"
major=1
-minor=0
-status="stable"
+minor=1
+status="beta1"