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--core/vector.h11
-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/bg.pngbin0 -> 294 bytes
-rw-r--r--demos/2d/lights_shadows/caster.pngbin0 -> 122 bytes
-rw-r--r--demos/2d/lights_shadows/engine.cfg8
-rw-r--r--demos/2d/lights_shadows/light.pngbin0 -> 243776 bytes
-rw-r--r--demos/2d/lights_shadows/light_shadows.scnbin0 -> 4293 bytes
-rw-r--r--demos/2d/lights_shadows/spot.pngbin0 -> 3699 bytes
-rw-r--r--demos/2d/normalmaps/diffuse.jpgbin0 -> 535660 bytes
-rw-r--r--demos/2d/normalmaps/diffuse.pngbin0 -> 2392221 bytes
-rw-r--r--demos/2d/normalmaps/engine.cfg4
-rw-r--r--demos/2d/normalmaps/light.pngbin0 -> 243776 bytes
-rw-r--r--demos/2d/normalmaps/normal.pngbin0 -> 2301245 bytes
-rw-r--r--demos/2d/normalmaps/normal_material.resbin0 -> 503 bytes
-rw-r--r--demos/2d/normalmaps/normalmap.scnbin0 -> 2450 bytes
-rw-r--r--demos/2d/texscreen/OpenCV_Chessboard.pngbin0 -> 44884 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.cpp36
-rw-r--r--modules/gdscript/gd_functions.h2
-rw-r--r--modules/gdscript/gd_script.cpp2
-rw-r--r--platform/android/detect.py2
-rw-r--r--platform/android/dir_access_jandroid.cpp5
-rw-r--r--platform/android/dir_access_jandroid.h1
-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/android/os_android.cpp5
-rw-r--r--platform/android/os_android.h2
-rw-r--r--platform/iphone/os_iphone.cpp5
-rw-r--r--platform/iphone/os_iphone.h2
-rw-r--r--platform/javascript/os_javascript.cpp6
-rw-r--r--platform/javascript/os_javascript.h1
-rw-r--r--platform/osx/os_osx.h34
-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--platform/windows/os_windows.cpp128
-rw-r--r--platform/windows/os_windows.h2
-rw-r--r--scene/2d/canvas_item.cpp33
-rw-r--r--scene/2d/canvas_item.h15
-rw-r--r--scene/2d/collision_polygon_2d.cpp12
-rw-r--r--scene/2d/collision_polygon_2d.h1
-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/light.cpp2
-rw-r--r--scene/3d/light.h2
-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/gui/file_dialog.cpp25
-rw-r--r--scene/gui/file_dialog.h9
-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/physics/body_sw.cpp32
-rw-r--r--servers/physics/body_sw.h9
-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/editor_node.cpp1
-rw-r--r--tools/editor/io_plugins/editor_import_collada.cpp1
-rw-r--r--tools/editor/plugins/canvas_item_editor_plugin.cpp486
-rw-r--r--tools/editor/plugins/canvas_item_editor_plugin.h29
-rw-r--r--tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp15
-rw-r--r--tools/editor/plugins/collision_polygon_2d_editor_plugin.h1
-rw-r--r--tools/editor/plugins/collision_polygon_editor_plugin.cpp17
-rw-r--r--tools/editor/plugins/collision_polygon_editor_plugin.h1
-rw-r--r--tools/editor/plugins/light_occluder_2d_editor_plugin.cpp15
-rw-r--r--tools/editor/plugins/mesh_editor_plugin.cpp5
-rw-r--r--tools/editor/plugins/navigation_polygon_editor_plugin.cpp15
-rw-r--r--tools/editor/plugins/navigation_polygon_editor_plugin.h1
-rw-r--r--tools/editor/plugins/path_2d_editor_plugin.cpp31
-rw-r--r--tools/editor/plugins/path_2d_editor_plugin.h1
-rw-r--r--tools/editor/plugins/polygon_2d_editor_plugin.cpp15
-rw-r--r--tools/editor/plugins/polygon_2d_editor_plugin.h1
-rw-r--r--tools/editor/plugins/sample_library_editor_plugin.cpp1
-rw-r--r--tools/editor/plugins/sample_player_editor_plugin.cpp1
-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/plugins/tile_map_editor_plugin.h1
-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
132 files changed, 2913 insertions, 838 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/core/vector.h b/core/vector.h
index 90a9bf715b..d6453a3b83 100644
--- a/core/vector.h
+++ b/core/vector.h
@@ -149,7 +149,16 @@ public:
sort_custom<_DefaultComparator<T> >();
}
-
+ void ordered_insert(const T& p_val) {
+ int i;
+ for (i=0; i<size(); i++) {
+
+ if (p_val < operator[](i)) {
+ break;
+ };
+ };
+ insert(i, p_val);
+ }
void operator=(const Vector& p_from);
Vector(const Vector& p_from);
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/bg.png b/demos/2d/lights_shadows/bg.png
new file mode 100644
index 0000000000..4a3376f484
--- /dev/null
+++ b/demos/2d/lights_shadows/bg.png
Binary files differ
diff --git a/demos/2d/lights_shadows/caster.png b/demos/2d/lights_shadows/caster.png
new file mode 100644
index 0000000000..bf53a4565b
--- /dev/null
+++ b/demos/2d/lights_shadows/caster.png
Binary files differ
diff --git a/demos/2d/lights_shadows/engine.cfg b/demos/2d/lights_shadows/engine.cfg
new file mode 100644
index 0000000000..bb9d1ef256
--- /dev/null
+++ b/demos/2d/lights_shadows/engine.cfg
@@ -0,0 +1,8 @@
+[application]
+
+name="2D Lighting"
+main_scene="res://light_shadows.scn"
+
+[rasterizer]
+
+shadow_filter=2
diff --git a/demos/2d/lights_shadows/light.png b/demos/2d/lights_shadows/light.png
new file mode 100644
index 0000000000..936860de52
--- /dev/null
+++ b/demos/2d/lights_shadows/light.png
Binary files differ
diff --git a/demos/2d/lights_shadows/light_shadows.scn b/demos/2d/lights_shadows/light_shadows.scn
new file mode 100644
index 0000000000..a13e31376e
--- /dev/null
+++ b/demos/2d/lights_shadows/light_shadows.scn
Binary files differ
diff --git a/demos/2d/lights_shadows/spot.png b/demos/2d/lights_shadows/spot.png
new file mode 100644
index 0000000000..9ab2d34963
--- /dev/null
+++ b/demos/2d/lights_shadows/spot.png
Binary files differ
diff --git a/demos/2d/normalmaps/diffuse.jpg b/demos/2d/normalmaps/diffuse.jpg
new file mode 100644
index 0000000000..87bc9cf158
--- /dev/null
+++ b/demos/2d/normalmaps/diffuse.jpg
Binary files differ
diff --git a/demos/2d/normalmaps/diffuse.png b/demos/2d/normalmaps/diffuse.png
new file mode 100644
index 0000000000..634d955f8d
--- /dev/null
+++ b/demos/2d/normalmaps/diffuse.png
Binary files differ
diff --git a/demos/2d/normalmaps/engine.cfg b/demos/2d/normalmaps/engine.cfg
new file mode 100644
index 0000000000..3fc2048716
--- /dev/null
+++ b/demos/2d/normalmaps/engine.cfg
@@ -0,0 +1,4 @@
+[application]
+
+name="2D Normal Mapping"
+main_scene="res://normalmap.scn"
diff --git a/demos/2d/normalmaps/light.png b/demos/2d/normalmaps/light.png
new file mode 100644
index 0000000000..9568298086
--- /dev/null
+++ b/demos/2d/normalmaps/light.png
Binary files differ
diff --git a/demos/2d/normalmaps/normal.png b/demos/2d/normalmaps/normal.png
new file mode 100644
index 0000000000..d5b3d53a24
--- /dev/null
+++ b/demos/2d/normalmaps/normal.png
Binary files differ
diff --git a/demos/2d/normalmaps/normal_material.res b/demos/2d/normalmaps/normal_material.res
new file mode 100644
index 0000000000..34129cccdc
--- /dev/null
+++ b/demos/2d/normalmaps/normal_material.res
Binary files differ
diff --git a/demos/2d/normalmaps/normalmap.scn b/demos/2d/normalmaps/normalmap.scn
new file mode 100644
index 0000000000..ab737e83f3
--- /dev/null
+++ b/demos/2d/normalmaps/normalmap.scn
Binary files differ
diff --git a/demos/2d/texscreen/OpenCV_Chessboard.png b/demos/2d/texscreen/OpenCV_Chessboard.png
new file mode 100644
index 0000000000..31b7f8ccd8
--- /dev/null
+++ b/demos/2d/texscreen/OpenCV_Chessboard.png
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..d4b8639c9b 100644
--- a/modules/gdscript/gd_functions.cpp
+++ b/modules/gdscript/gd_functions.cpp
@@ -71,6 +71,7 @@ const char *GDFunctions::get_func_name(Function p_func) {
"randi",
"randf",
"rand_range",
+ "seed",
"rand_seed",
"deg2rad",
"rad2deg",
@@ -97,6 +98,7 @@ const char *GDFunctions::get_func_name(Function p_func) {
"dict2inst",
"hash",
"print_stack",
+ "get_inst",
};
return _names[p_func];
@@ -328,6 +330,13 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va
VALIDATE_ARG_NUM(1);
r_ret=Math::random(*p_args[0],*p_args[1]);
} break;
+ case MATH_SEED: {
+ VALIDATE_ARG_COUNT(1);
+ VALIDATE_ARG_NUM(0);
+ uint32_t seed=*p_args[0];
+ Math::seed(seed);
+ r_ret=Variant();
+ } break;
case MATH_RANDSEED: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
@@ -575,7 +584,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;
@@ -895,6 +904,20 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va
};
} break;
+ case GET_INST: {
+
+ VALIDATE_ARG_COUNT(1);
+ if (p_args[0]->get_type()!=Variant::INT && p_args[0]->get_type()!=Variant::REAL) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument=0;
+ r_ret=Variant();
+ break;
+ }
+
+ uint32_t id=*p_args[0];
+ r_ret=ObjectDB::get_instance(id);
+
+ } break;
case FUNC_MAX: {
ERR_FAIL_V();
@@ -1130,6 +1153,11 @@ MethodInfo GDFunctions::get_info(Function p_func) {
mi.return_val.type=Variant::REAL;
return mi;
} break;
+ case MATH_SEED: {
+ MethodInfo mi("seed",PropertyInfo(Variant::REAL,"seed"));
+ mi.return_val.type=Variant::NIL;
+ return mi;
+ } break;
case MATH_RANDSEED: {
MethodInfo mi("rand_seed",PropertyInfo(Variant::REAL,"seed"));
mi.return_val.type=Variant::ARRAY;
@@ -1288,6 +1316,12 @@ MethodInfo GDFunctions::get_info(Function p_func) {
return mi;
} break;
+ case GET_INST: {
+ MethodInfo mi("get_info",PropertyInfo(Variant::INT,"instance_id"));
+ mi.return_val.type=Variant::OBJECT;
+ return mi;
+ } break;
+
case FUNC_MAX: {
ERR_FAIL_V(MethodInfo());
diff --git a/modules/gdscript/gd_functions.h b/modules/gdscript/gd_functions.h
index 05ff6a2e73..4fbfe99228 100644
--- a/modules/gdscript/gd_functions.h
+++ b/modules/gdscript/gd_functions.h
@@ -67,6 +67,7 @@ public:
MATH_RAND,
MATH_RANDF,
MATH_RANDOM,
+ MATH_SEED,
MATH_RANDSEED,
MATH_DEG2RAD,
MATH_RAD2DEG,
@@ -93,6 +94,7 @@ public:
DICT2INST,
HASH,
PRINT_STACK,
+ GET_INST,
FUNC_MAX
};
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/dir_access_jandroid.cpp b/platform/android/dir_access_jandroid.cpp
index fda4ca7357..98f20b2636 100644
--- a/platform/android/dir_access_jandroid.cpp
+++ b/platform/android/dir_access_jandroid.cpp
@@ -105,9 +105,12 @@ bool DirAccessJAndroid::current_is_dir() const{
return true;
}
-bool DirAccessAndroid::current_is_hidden() const{
+
+bool DirAccessJAndroid::current_is_hidden() const {
+
return current!="." && current!=".." && current.begins_with(".");
}
+
void DirAccessJAndroid::list_dir_end(){
if (id==0)
diff --git a/platform/android/dir_access_jandroid.h b/platform/android/dir_access_jandroid.h
index 958ea34891..0a696506e6 100644
--- a/platform/android/dir_access_jandroid.h
+++ b/platform/android/dir_access_jandroid.h
@@ -60,6 +60,7 @@ public:
virtual bool list_dir_begin(); ///< This starts dir listing
virtual String get_next();
virtual bool current_is_dir() const;
+ virtual bool current_is_hidden() const;
virtual void list_dir_end(); ///<
virtual int get_drive_count();
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/android/os_android.cpp b/platform/android/os_android.cpp
index 6b91c01dfc..f00e9c2d77 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -291,6 +291,11 @@ void OS_Android::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen)
p_list->push_back(default_videomode);
}
+Size2 OS_Android::get_window_size() const {
+
+ return Vector2(default_videomode.width,default_videomode.height);
+}
+
String OS_Android::get_name() {
return "Android";
diff --git a/platform/android/os_android.h b/platform/android/os_android.h
index 26dbf4a509..bea5371bbc 100644
--- a/platform/android/os_android.h
+++ b/platform/android/os_android.h
@@ -170,6 +170,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 String get_name();
virtual MainLoop *get_main_loop() const;
diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp
index aee5f76684..06b48318ec 100644
--- a/platform/iphone/os_iphone.cpp
+++ b/platform/iphone/os_iphone.cpp
@@ -474,6 +474,11 @@ String OSIPhone::get_name() {
return "iOS";
};
+Size2 OSIPhone::get_window_size() const {
+
+ return Vector2(video_mode.width, video_mode.height);
+}
+
bool OSIPhone::has_touchscreen_ui_hint() const {
return true;
diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h
index cb294d07eb..2585a26479 100644
--- a/platform/iphone/os_iphone.h
+++ b/platform/iphone/os_iphone.h
@@ -167,6 +167,8 @@ public:
virtual void hide_virtual_keyboard();
virtual void set_cursor_shape(CursorShape p_shape);
+
+ virtual Size2 get_window_size() const;
virtual bool has_touchscreen_ui_hint() const;
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 24f7115938..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);
@@ -133,6 +137,8 @@ public:
virtual Point2 get_mouse_pos() const;
virtual int get_mouse_button_state() const;
virtual void set_window_title(const String& p_title);
+
+ virtual Size2 get_window_size() const;
virtual void set_icon(const Image& p_icon);
@@ -160,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 1c0d1f9991..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,6 +1258,119 @@ 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 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() {
[window_object orderFrontRegardless];
@@ -1473,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/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index a8768ea9fd..93275b3d54 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -423,6 +423,7 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
case WM_RBUTTONUP:
case WM_MOUSEWHEEL:
case WM_LBUTTONDBLCLK:
+ case WM_RBUTTONDBLCLK:
/*case WM_XBUTTONDOWN:
case WM_XBUTTONUP: */{
@@ -476,6 +477,12 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
mb.button_index=1;
mb.doubleclick = true;
} break;
+ case WM_RBUTTONDBLCLK: {
+
+ mb.pressed=true;
+ mb.button_index=2;
+ mb.doubleclick = true;
+ } break;
case WM_MOUSEWHEEL: {
mb.pressed=true;
@@ -1067,6 +1074,7 @@ void OS_Windows::initialize(const VideoMode& p_desired,int p_video_driver,int p_
EnumDisplayMonitors(NULL,NULL,MonitorEnumProc,0);
print_line("DETECTED MONITORS: "+itos(monitor_info.size()));
+ pre_fs_valid=true;
if (video_mode.fullscreen) {
DEVMODE current;
@@ -1089,6 +1097,7 @@ void OS_Windows::initialize(const VideoMode& p_desired,int p_video_driver,int p_
video_mode.fullscreen=false;
}*/
+ pre_fs_valid=false;
}
DWORD dwExStyle;
@@ -1548,15 +1557,43 @@ void OS_Windows::set_window_position(const Point2& p_position){
Size2 OS_Windows::get_window_size() const{
RECT r;
- GetWindowRect(hWnd,&r);
+ GetClientRect(hWnd,&r);
return Vector2(r.right-r.left,r.bottom-r.top);
}
void OS_Windows::set_window_size(const Size2 p_size){
- RECT r;
- GetWindowRect(hWnd,&r);
- MoveWindow(hWnd,r.left,r.top,p_size.x,p_size.y,TRUE);
+ video_mode.width=p_size.width;
+ video_mode.height=p_size.height;
+
+ if (video_mode.fullscreen) {
+ return;
+ }
+
+
+ RECT crect;
+ GetClientRect(hWnd,&crect);
+
+ RECT rect;
+ GetWindowRect(hWnd,&rect);
+ int dx = (rect.right-rect.left)-(crect.right-crect.left);
+ int dy = (rect.bottom-rect.top)-(crect.bottom-crect.top);
+
+ rect.right=rect.left+p_size.width+dx;
+ rect.bottom=rect.top+p_size.height+dy;
+
+
+ //print_line("PRE: "+itos(rect.left)+","+itos(rect.top)+","+itos(rect.right-rect.left)+","+itos(rect.bottom-rect.top));
+
+ /*if (video_mode.resizable) {
+ AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
+ } else {
+ AdjustWindowRect(&rect, WS_CAPTION | WS_POPUPWINDOW, FALSE);
+ }*/
+
+ //print_line("POST: "+itos(rect.left)+","+itos(rect.top)+","+itos(rect.right-rect.left)+","+itos(rect.bottom-rect.top));
+
+ MoveWindow(hWnd,rect.left,rect.top,rect.right-rect.left,rect.bottom-rect.top,TRUE);
}
void OS_Windows::set_window_fullscreen(bool p_enabled){
@@ -1564,31 +1601,65 @@ void OS_Windows::set_window_fullscreen(bool p_enabled){
if (video_mode.fullscreen==p_enabled)
return;
+
+
if (p_enabled) {
- GetWindowRect(hWnd,&pre_fs_rect);
+
+ if (pre_fs_valid) {
+ GetWindowRect(hWnd,&pre_fs_rect);
+ //print_line("A: "+itos(pre_fs_rect.left)+","+itos(pre_fs_rect.top)+","+itos(pre_fs_rect.right-pre_fs_rect.left)+","+itos(pre_fs_rect.bottom-pre_fs_rect.top));
+ //MapWindowPoints(hWnd, GetParent(hWnd), (LPPOINT) &pre_fs_rect, 2);
+ //print_line("B: "+itos(pre_fs_rect.left)+","+itos(pre_fs_rect.top)+","+itos(pre_fs_rect.right-pre_fs_rect.left)+","+itos(pre_fs_rect.bottom-pre_fs_rect.top));
+ }
+
int cs = get_current_screen();
Point2 pos = get_screen_position(cs);
Size2 size = get_screen_size(cs);
- RECT WindowRect;
- WindowRect.left = pos.x;
- WindowRect.top = pos.y;
- WindowRect.bottom = pos.y+size.y;
- WindowRect.right = pos.x+size.x;
- DWORD dwExStyle=WS_EX_APPWINDOW;
- DWORD dwStyle=WS_POPUP;
-
- AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);
+ /* r.left = pos.x;
+ r.top = pos.y;
+ r.bottom = pos.y+size.y;
+ r.right = pos.x+size.x;
+*/
+ SetWindowLongPtr(hWnd, GWL_STYLE,
+ WS_SYSMENU | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE);
+ MoveWindow(hWnd, pos.x, pos.y, size.width, size.height, TRUE);
video_mode.fullscreen=true;
- video_mode.width=size.x;
- video_mode.height=size.y;
} else {
+ RECT rect;
+
+ if (pre_fs_valid) {
+ rect=pre_fs_rect;
+ } else {
+ rect.left=0;
+ rect.right=video_mode.width;
+ rect.top=0;
+ rect.bottom=video_mode.height;
+ }
+
+
+
+ if (video_mode.resizable) {
+
+ SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE);
+ //AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
+ MoveWindow(hWnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE);
+ } else {
+
+ SetWindowLongPtr(hWnd, GWL_STYLE, WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE);
+ //AdjustWindowRect(&rect, WS_CAPTION | WS_POPUPWINDOW, FALSE);
+ MoveWindow(hWnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE);
+ }
+
+ video_mode.fullscreen=false;
+ pre_fs_valid=true;
+/*
DWORD dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
DWORD dwStyle=WS_OVERLAPPEDWINDOW;
if (!video_mode.resizable) {
@@ -1599,9 +1670,11 @@ void OS_Windows::set_window_fullscreen(bool p_enabled){
video_mode.fullscreen=false;
video_mode.width=pre_fs_rect.right-pre_fs_rect.left;
video_mode.height=pre_fs_rect.bottom-pre_fs_rect.top;
-
+*/
}
+// MoveWindow(hWnd,r.left,r.top,p_size.x,p_size.y,TRUE);
+
}
bool OS_Windows::is_window_fullscreen() const{
@@ -1610,9 +1683,9 @@ bool OS_Windows::is_window_fullscreen() const{
}
void OS_Windows::set_window_resizable(bool p_enabled){
- if (video_mode.fullscreen || video_mode.resizable==p_enabled)
+ if (video_mode.resizable==p_enabled)
return;
-
+/*
GetWindowRect(hWnd,&pre_fs_rect);
DWORD dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
DWORD dwStyle=WS_OVERLAPPEDWINDOW;
@@ -1621,6 +1694,21 @@ void OS_Windows::set_window_resizable(bool p_enabled){
dwStyle &= ~WS_MAXIMIZEBOX;
}
AdjustWindowRectEx(&pre_fs_rect, dwStyle, FALSE, dwExStyle);
+ */
+
+ if (!video_mode.fullscreen) {
+ if (p_enabled) {
+ SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE);
+ } else {
+ SetWindowLongPtr(hWnd, GWL_STYLE, WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE);
+
+ }
+
+ RECT rect;
+ GetWindowRect(hWnd,&rect);
+ MoveWindow(hWnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE);
+ }
+
video_mode.resizable=p_enabled;
}
@@ -1964,7 +2052,7 @@ String OS_Windows::get_executable_path() const {
wchar_t bufname[4096];
GetModuleFileNameW(NULL,bufname,4096);
String s= bufname;
- print_line("EXEC PATHPó: "+s);
+ print_line("EXEC PATHP¨®: "+s);
return s;
}
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index c39b3c74a4..4995adc874 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -130,6 +130,7 @@ class OS_Windows : public OS {
int joystick_count;
Joystick joysticks[JOYSTICKS_MAX];
+ Size2 window_rect;
VideoMode video_mode;
MainLoop *main_loop;
@@ -204,6 +205,7 @@ protected:
};
+ bool pre_fs_valid;
RECT pre_fs_rect;
Vector<MonitorInfo> monitor_info;
bool maximized;
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/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp
index 1c0be60764..049017c0a5 100644
--- a/scene/2d/collision_polygon_2d.cpp
+++ b/scene/2d/collision_polygon_2d.cpp
@@ -33,6 +33,9 @@
void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) {
+ if (unparenting)
+ return;
+
CollisionObject2D *co = p_obj->cast_to<CollisionObject2D>();
ERR_FAIL_COND(!co);
@@ -96,6 +99,9 @@ void CollisionPolygon2D::_notification(int p_what) {
switch(p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ unparenting=false;
+ } break;
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
if (!is_inside_tree())
@@ -123,6 +129,11 @@ void CollisionPolygon2D::_notification(int p_what) {
}
#endif
} break;
+ case NOTIFICATION_UNPARENTED: {
+ unparenting = true;
+ _update_parent();
+ } break;
+
}
}
@@ -203,6 +214,7 @@ CollisionPolygon2D::CollisionPolygon2D() {
aabb=Rect2(-10,-10,20,20);
build_mode=BUILD_SOLIDS;
trigger=false;
+ unparenting=false;
}
diff --git a/scene/2d/collision_polygon_2d.h b/scene/2d/collision_polygon_2d.h
index b8e27b6fb4..735110efad 100644
--- a/scene/2d/collision_polygon_2d.h
+++ b/scene/2d/collision_polygon_2d.h
@@ -51,6 +51,7 @@ protected:
BuildMode build_mode;
Vector<Point2> polygon;
bool trigger;
+ bool unparenting;
void _add_to_collision_object(Object *p_obj);
void _update_parent();
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/light.cpp b/scene/3d/light.cpp
index 15e77e5378..037350f99a 100644
--- a/scene/3d/light.cpp
+++ b/scene/3d/light.cpp
@@ -669,7 +669,7 @@ void SpotLight::_bind_methods() {
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_ATTENUATION );
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/spot_angle", PROPERTY_HINT_RANGE, "0.01,89.9,0.01"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SPOT_ANGLE );
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/spot_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SPOT_ATTENUATION );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/spot_attenuation", PROPERTY_HINT_EXP_EASING, "spot_attenuation"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SPOT_ATTENUATION );
}
diff --git a/scene/3d/light.h b/scene/3d/light.h
index 6fb57a269b..5b10a4d816 100644
--- a/scene/3d/light.h
+++ b/scene/3d/light.h
@@ -49,7 +49,7 @@ public:
PARAM_ENERGY=VisualServer::LIGHT_PARAM_ENERGY,
PARAM_ATTENUATION=VisualServer::LIGHT_PARAM_ATTENUATION,
PARAM_SPOT_ANGLE=VisualServer::LIGHT_PARAM_SPOT_ANGLE,
- PARAM_SPOT_ATTENUATION=VisualServer::LIGHT_PARAM_ATTENUATION,
+ PARAM_SPOT_ATTENUATION=VisualServer::LIGHT_PARAM_SPOT_ATTENUATION,
PARAM_SHADOW_DARKENING=VisualServer::LIGHT_PARAM_SHADOW_DARKENING,
PARAM_SHADOW_Z_OFFSET=VisualServer::LIGHT_PARAM_SHADOW_Z_OFFSET,
PARAM_SHADOW_Z_SLOPE_SCALE=VisualServer::LIGHT_PARAM_SHADOW_Z_SLOPE_SCALE,
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/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 47f862a58d..2e8a84e39b 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -30,7 +30,7 @@
#include "scene/gui/label.h"
#include "print_string.h"
#include "os/keyboard.h"
-#include "tools/editor/editor_settings.h"
+
FileDialog::GetIconFunc FileDialog::get_icon_func=NULL;
@@ -281,7 +281,7 @@ void FileDialog::update_file_list() {
bool isdir;
bool ishidden;
- bool show_hidden = EditorSettings::get_singleton()->get("file_dialog/show_hidden_files");
+ bool show_hidden = show_hidden_files;
String item;
while ((item=dir_access->get_next(&isdir))!="") {
@@ -625,6 +625,9 @@ void FileDialog::_update_drives() {
}
}
+bool FileDialog::default_show_hidden_files=true;
+
+
void FileDialog::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_tree_selected"),&FileDialog::_tree_selected);
@@ -649,6 +652,8 @@ void FileDialog::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_vbox:VBoxContainer"),&FileDialog::get_vbox);
ObjectTypeDB::bind_method(_MD("set_access","access"),&FileDialog::set_access);
ObjectTypeDB::bind_method(_MD("get_access"),&FileDialog::get_access);
+ ObjectTypeDB::bind_method(_MD("set_show_hidden_files"),&FileDialog::set_show_hidden_files);
+ ObjectTypeDB::bind_method(_MD("is_showing_hidden_files"),&FileDialog::is_showing_hidden_files);
ObjectTypeDB::bind_method(_MD("_select_drive"),&FileDialog::_select_drive);
ObjectTypeDB::bind_method(_MD("_make_dir"),&FileDialog::_make_dir);
ObjectTypeDB::bind_method(_MD("_make_dir_confirm"),&FileDialog::_make_dir_confirm);
@@ -673,9 +678,23 @@ void FileDialog::_bind_methods() {
}
+void FileDialog::set_show_hidden_files(bool p_show) {
+ show_hidden_files=p_show;
+ invalidate();
+}
+
+bool FileDialog::is_showing_hidden_files() const {
+ return show_hidden_files;
+}
+
+void FileDialog::set_default_show_hidden_files(bool p_show) {
+ default_show_hidden_files=p_show;
+}
FileDialog::FileDialog() {
-
+
+ show_hidden_files=true;
+
VBoxContainer *vbc = memnew( VBoxContainer );
add_child(vbc);
set_child_rect(vbc);
diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h
index bda1797696..6b35035829 100644
--- a/scene/gui/file_dialog.h
+++ b/scene/gui/file_dialog.h
@@ -89,6 +89,10 @@ private:
Vector<String> filters;
+
+ static bool default_show_hidden_files;
+ bool show_hidden_files;
+
bool invalidated;
void update_dir();
@@ -141,6 +145,11 @@ public:
void set_access(Access p_access);
Access get_access() const;
+ void set_show_hidden_files(bool p_show);
+ bool is_showing_hidden_files() const;
+
+ static void set_default_show_hidden_files(bool p_show);
+
void invalidate();
FileDialog();
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/physics/body_sw.cpp b/servers/physics/body_sw.cpp
index c7c20a8bd1..5682ad8498 100644
--- a/servers/physics/body_sw.cpp
+++ b/servers/physics/body_sw.cpp
@@ -358,10 +358,10 @@ void BodySW::_compute_area_gravity(const AreaSW *p_area) {
if (p_area->is_gravity_point()) {
- gravity = (p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin()).normalized() * p_area->get_gravity();
+ gravity += (p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin()).normalized() * p_area->get_gravity();
} else {
- gravity = p_area->get_gravity_vector() * p_area->get_gravity();
+ gravity += p_area->get_gravity_vector() * p_area->get_gravity();
}
}
@@ -371,23 +371,29 @@ void BodySW::integrate_forces(real_t p_step) {
if (mode==PhysicsServer::BODY_MODE_STATIC)
return;
- AreaSW *current_area = get_space()->get_default_area();
- ERR_FAIL_COND(!current_area);
+ AreaSW *def_area = get_space()->get_default_area();
+ ERR_FAIL_COND(!def_area);
- int prio = current_area->get_priority();
int ac = areas.size();
+ bool replace = false;
+ gravity=Vector3(0,0,0);
if (ac) {
+ areas.sort();
const AreaCMP *aa = &areas[0];
- for(int i=0;i<ac;i++) {
- if (aa[i].area->get_priority() > prio) {
- current_area=aa[i].area;
- prio=current_area->get_priority();
+ density = aa[ac-1].area->get_density();
+ for(int i=ac-1;i>=0;i--) {
+ _compute_area_gravity(aa[i].area);
+ if (aa[i].area->get_space_override_mode() == PhysicsServer::AREA_SPACE_OVERRIDE_REPLACE) {
+ replace = true;
+ break;
}
}
+ } else {
+ density=def_area->get_density();
+ }
+ if( !replace ) {
+ _compute_area_gravity(def_area);
}
-
- _compute_area_gravity(current_area);
- density=current_area->get_density();
Vector3 motion;
bool do_motion=false;
@@ -455,7 +461,7 @@ void BodySW::integrate_forces(real_t p_step) {
}
- current_area=NULL; // clear the area, so it is set in the next frame
+ def_area=NULL; // clear the area, so it is set in the next frame
contact_count=0;
}
diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h
index ee3c76e455..021245fe50 100644
--- a/servers/physics/body_sw.h
+++ b/servers/physics/body_sw.h
@@ -84,13 +84,13 @@ class BodySW : public CollisionObjectSW {
struct AreaCMP {
AreaSW *area;
- _FORCE_INLINE_ bool operator<(const AreaCMP& p_cmp) const { return area->get_self() < p_cmp.area->get_self() ; }
+ _FORCE_INLINE_ bool operator==(const AreaCMP& p_cmp) const { return area->get_self() == p_cmp.area->get_self();}
+ _FORCE_INLINE_ bool operator<(const AreaCMP a) const { return area->get_priority() < a.area->get_priority();}
_FORCE_INLINE_ AreaCMP() {}
_FORCE_INLINE_ AreaCMP(AreaSW *p_area) { area=p_area;}
};
-
- VSet<AreaCMP> areas;
+ Vector<AreaCMP> areas;
struct Contact {
@@ -134,8 +134,7 @@ public:
void set_force_integration_callback(ObjectID p_id,const StringName& p_method,const Variant& p_udata=Variant());
-
- _FORCE_INLINE_ void add_area(AreaSW *p_area) { areas.insert(AreaCMP(p_area)); }
+ _FORCE_INLINE_ void add_area(AreaSW *p_area) { areas.ordered_insert(AreaCMP(p_area)); }
_FORCE_INLINE_ void remove_area(AreaSW *p_area) { areas.erase(AreaCMP(p_area)); }
_FORCE_INLINE_ void set_max_contacts_reported(int p_size) { contacts.resize(p_size); contact_count=0; if (mode==PhysicsServer::BODY_MODE_KINEMATIC && p_size) set_active(true);}
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/editor_node.cpp b/tools/editor/editor_node.cpp
index 5e571373ea..41545b887a 100644
--- a/tools/editor/editor_node.cpp
+++ b/tools/editor/editor_node.cpp
@@ -3287,6 +3287,7 @@ EditorNode::EditorNode() {
EditorSettings::create();
ResourceLoader::set_abort_on_missing_resources(false);
+ FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("file_dialog/show_hidden_files"));
ResourceLoader::set_error_notify_func(this,_load_error_notify);
ResourceLoader::set_timestamp_on_load(true);
diff --git a/tools/editor/io_plugins/editor_import_collada.cpp b/tools/editor/io_plugins/editor_import_collada.cpp
index f113bd3593..990e52be46 100644
--- a/tools/editor/io_plugins/editor_import_collada.cpp
+++ b/tools/editor/io_plugins/editor_import_collada.cpp
@@ -39,6 +39,7 @@
#include "scene/resources/packed_scene.h"
#include "os/os.h"
#include "tools/editor/editor_node.h"
+#include <iostream>
struct ColladaImport {
diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp
index fdec72332e..32d5641e68 100644
--- a/tools/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp
@@ -36,6 +36,110 @@
#include "globals.h"
#include "os/input.h"
#include "tools/editor/editor_settings.h"
+#include "scene/gui/grid_container.h"
+
+class SnapDialog : public ConfirmationDialog {
+
+ OBJ_TYPE(SnapDialog,ConfirmationDialog);
+
+protected:
+ friend class CanvasItemEditor;
+ SpinBox *grid_offset_x;
+ SpinBox *grid_offset_y;
+ SpinBox *grid_step_x;
+ SpinBox *grid_step_y;
+ SpinBox *rotation_offset;
+ SpinBox *rotation_step;
+
+public:
+ SnapDialog() : ConfirmationDialog() {
+ const int SPIN_BOX_GRID_RANGE = 256;
+ const int SPIN_BOX_ROTATION_RANGE = 360;
+ Label *label;
+ VBoxContainer *container;
+ GridContainer *child_container;
+
+ set_title("Configure Snap");
+ get_ok()->set_text("Close");
+ container = memnew(VBoxContainer);
+ add_child(container);
+
+ child_container = memnew(GridContainer);
+ child_container->set_columns(3);
+ container->add_child(child_container);
+
+ label = memnew(Label);
+ label->set_text("Grid Offset:");
+ child_container->add_child(label);
+ grid_offset_x=memnew(SpinBox);
+ grid_offset_x->set_min(-SPIN_BOX_GRID_RANGE);
+ grid_offset_x->set_max(SPIN_BOX_GRID_RANGE);
+ grid_offset_x->set_suffix("px");
+ child_container->add_child(grid_offset_x);
+ grid_offset_y=memnew(SpinBox);
+ grid_offset_y->set_min(-SPIN_BOX_GRID_RANGE);
+ grid_offset_y->set_max(SPIN_BOX_GRID_RANGE);
+ grid_offset_y->set_suffix("px");
+ child_container->add_child(grid_offset_y);
+
+ label = memnew(Label);
+ label->set_text("Grid Step:");
+ child_container->add_child(label);
+ grid_step_x=memnew(SpinBox);
+ grid_step_x->set_min(-SPIN_BOX_GRID_RANGE);
+ grid_step_x->set_max(SPIN_BOX_GRID_RANGE);
+ grid_step_x->set_suffix("px");
+ child_container->add_child(grid_step_x);
+ grid_step_y=memnew(SpinBox);
+ grid_step_y->set_min(-SPIN_BOX_GRID_RANGE);
+ grid_step_y->set_max(SPIN_BOX_GRID_RANGE);
+ grid_step_y->set_suffix("px");
+ child_container->add_child(grid_step_y);
+
+ container->add_child(memnew(HSeparator));
+
+ child_container = memnew(GridContainer);
+ child_container->set_columns(2);
+ container->add_child(child_container);
+
+ label = memnew(Label);
+ label->set_text("Rotation Offset:");
+ child_container->add_child(label);
+ rotation_offset=memnew(SpinBox);
+ rotation_offset->set_min(-SPIN_BOX_ROTATION_RANGE);
+ rotation_offset->set_max(SPIN_BOX_ROTATION_RANGE);
+ rotation_offset->set_suffix("deg");
+ child_container->add_child(rotation_offset);
+
+ label = memnew(Label);
+ label->set_text("Rotation Step:");
+ child_container->add_child(label);
+ rotation_step=memnew(SpinBox);
+ rotation_step->set_min(-SPIN_BOX_ROTATION_RANGE);
+ rotation_step->set_max(SPIN_BOX_ROTATION_RANGE);
+ rotation_step->set_suffix("deg");
+ child_container->add_child(rotation_step);
+ }
+
+ void set_fields(const Point2 p_grid_offset, const Size2 p_grid_step, const float p_rotation_offset, const float p_rotation_step) {
+ grid_offset_x->set_val(p_grid_offset.x);
+ grid_offset_y->set_val(p_grid_offset.y);
+ grid_step_x->set_val(p_grid_step.x);
+ grid_step_y->set_val(p_grid_step.y);
+ rotation_offset->set_val(p_rotation_offset * (180 / Math_PI));
+ rotation_step->set_val(p_rotation_step * (180 / Math_PI));
+ }
+
+ void get_fields(Point2 &p_grid_offset, Size2 &p_grid_step, float &p_rotation_offset, float &p_rotation_step) {
+ p_grid_offset.x = grid_offset_x->get_val();
+ p_grid_offset.y = grid_offset_y->get_val();
+ p_grid_step.x = grid_step_x->get_val();
+ p_grid_step.y = grid_step_y->get_val();
+ p_rotation_offset = rotation_offset->get_val() / (180 / Math_PI);
+ p_rotation_step = rotation_step->get_val() / (180 / Math_PI);
+ }
+};
+
void CanvasItemEditor::_unhandled_key_input(const InputEvent& p_ev) {
if (!is_visible())
@@ -75,9 +179,24 @@ Object *CanvasItemEditor::_get_editor_data(Object *p_what) {
return memnew( CanvasItemEditorSelectedItem );
}
-bool CanvasItemEditor::is_snap_active() const {
+inline float _snap_scalar(float p_offset, float p_step, bool p_snap_relative, float p_target, float p_start) {
+ float offset = p_snap_relative ? p_start : p_offset;
+ return p_step != 0 ? Math::stepify(p_target - offset, p_step) + offset : p_target;
+}
+
+Vector2 CanvasItemEditor::snap_point(Vector2 p_target, Vector2 p_start) const {
+ if (snap_grid) {
+ p_target.x = _snap_scalar(snap_offset.x, snap_step.x, snap_relative, p_target.x, p_start.x);
+ p_target.y = _snap_scalar(snap_offset.y, snap_step.y, snap_relative, p_target.y, p_start.y);
+ }
+ if (snap_pixel)
+ p_target = p_target.snapped(Size2(1, 1));
+
+ return p_target;
+}
- return edit_menu->get_popup()->is_item_checked(edit_menu->get_popup()->get_item_index(SNAP_USE));
+float CanvasItemEditor::snap_angle(float p_target, float p_start) const {
+ return snap_rotation ? _snap_scalar(snap_rotation_offset, snap_rotation_step, snap_relative, p_target, p_start) : p_target;
}
Dictionary CanvasItemEditor::get_state() const {
@@ -86,9 +205,15 @@ Dictionary CanvasItemEditor::get_state() const {
state["zoom"]=zoom;
state["ofs"]=Point2(h_scroll->get_val(),v_scroll->get_val());
// state["ofs"]=-transform.get_origin();
- state["use_snap"]=is_snap_active();
- state["snap_vec"]=Vector2(get_snap());
- state["pixel_snap"]=pixel_snap;
+ state["snap_offset"]=snap_offset;
+ state["snap_step"]=snap_step;
+ state["snap_rotation_offset"]=snap_rotation_offset;
+ state["snap_rotation_step"]=snap_rotation_step;
+ state["snap_grid"]=snap_grid;
+ state["snap_show_grid"]=snap_show_grid;
+ state["snap_rotation"]=snap_rotation;
+ state["snap_relative"]=snap_relative;
+ state["snap_pixel"]=snap_pixel;
return state;
}
void CanvasItemEditor::set_state(const Dictionary& p_state){
@@ -105,27 +230,50 @@ void CanvasItemEditor::set_state(const Dictionary& p_state){
v_scroll->set_val(ofs.y);
}
- if (state.has("use_snap")) {
+ if (state.has("snap_step")) {
+ snap_step=state["snap_step"];
+ }
+
+ if (state.has("snap_offset")) {
+ snap_offset=state["snap_offset"];
+ }
+
+ if (state.has("snap_rotation_step")) {
+ snap_rotation_step=state["snap_rotation_step"];
+ }
+
+ if (state.has("snap_rotation_offset")) {
+ snap_rotation_offset=state["snap_rotation_offset"];
+ }
+
+ if (state.has("snap_grid")) {
+ snap_grid=state["snap_grid"];
int idx = edit_menu->get_popup()->get_item_index(SNAP_USE);
- edit_menu->get_popup()->set_item_checked(idx,state["use_snap"]);
+ edit_menu->get_popup()->set_item_checked(idx,snap_grid);
}
- if (state.has("snap")) {
- snap_x->set_val(state["snap"]);
- snap_y->set_val(state["snap"]);
+ if (state.has("snap_show_grid")) {
+ snap_show_grid=state["snap_show_grid"];
+ int idx = edit_menu->get_popup()->get_item_index(SNAP_SHOW_GRID);
+ edit_menu->get_popup()->set_item_checked(idx,snap_show_grid);
}
- if (state.has("snap_vec")) {
- Vector2 sv = state["snap_vec"];
- snap_x->set_val(sv.x);
- snap_y->set_val(sv.y);
- viewport->update();
+ if (state.has("snap_rotation")) {
+ snap_rotation=state["snap_rotation"];
+ int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_ROTATION);
+ edit_menu->get_popup()->set_item_checked(idx,snap_rotation);
}
- if (state.has("pixel_snap")) {
- pixel_snap=state["pixel_snap"];
+ if (state.has("snap_relative")) {
+ snap_relative=state["snap_relative"];
+ int idx = edit_menu->get_popup()->get_item_index(SNAP_RELATIVE);
+ edit_menu->get_popup()->set_item_checked(idx,snap_relative);
+ }
+
+ if (state.has("snap_pixel")) {
+ snap_pixel=state["snap_pixel"];
int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_PIXEL);
- edit_menu->get_popup()->set_item_checked(idx,pixel_snap);
+ edit_menu->get_popup()->set_item_checked(idx,snap_pixel);
}
}
@@ -294,9 +442,7 @@ void CanvasItemEditor::_key_move(const Vector2& p_dir, bool p_snap, KeyMoveMODE
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item)
- continue;
- if (!canvas_item->is_visible())
+ if (!canvas_item || !canvas_item->is_visible())
continue;
CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
if (!se)
@@ -308,7 +454,7 @@ void CanvasItemEditor::_key_move(const Vector2& p_dir, bool p_snap, KeyMoveMODE
Vector2 drag = p_dir;
if (p_snap)
- drag*=get_snap();
+ drag*=snap_step;
undo_redo->add_undo_method(canvas_item,"edit_set_state",canvas_item->edit_get_state());
@@ -355,9 +501,7 @@ Point2 CanvasItemEditor::_find_topleftmost_point() {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item)
- continue;
- if (!canvas_item->is_visible())
+ if (!canvas_item || !canvas_item->is_visible())
continue;
@@ -385,9 +529,7 @@ int CanvasItemEditor::get_item_count() {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item)
- continue;
- if (!canvas_item->is_visible())
+ if (!canvas_item || !canvas_item->is_visible())
continue;
ic++;
@@ -406,9 +548,7 @@ CanvasItem *CanvasItemEditor::get_single_item() {
for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
- if (!canvas_item)
- continue;
- if (!canvas_item->is_visible())
+ if (!canvas_item || !canvas_item->is_visible())
continue;
if (single_item)
@@ -562,13 +702,11 @@ void CanvasItemEditor::_append_canvas_item(CanvasItem *c) {
}
-void CanvasItemEditor::_snap_changed(double) {
-
+void CanvasItemEditor::_snap_changed() {
+ ((SnapDialog *)snap_dialog)->get_fields(snap_offset, snap_step, snap_rotation_offset, snap_rotation_step);
viewport->update();
}
-
-
void CanvasItemEditor::_dialog_value_changed(double) {
if (updating_value_dialog)
@@ -576,11 +714,6 @@ void CanvasItemEditor::_dialog_value_changed(double) {
switch(last_option) {
- case SNAP_CONFIGURE: {
-
- // snap=dialog_val->get_val();
- viewport->update();
- } break;
case ZOOM_SET: {
zoom=dialog_val->get_val()/100.0;
@@ -676,9 +809,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item)
- continue;
- if (!canvas_item->is_visible())
+ if (!canvas_item || !canvas_item->is_visible())
continue;
CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
@@ -750,9 +881,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item)
- continue;
- if (!canvas_item->is_visible())
+ if (!canvas_item || !canvas_item->is_visible())
continue;
CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
if (!se)
@@ -958,9 +1087,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item)
- continue;
- if (!canvas_item->is_visible())
+ if (!canvas_item || !canvas_item->is_visible())
continue;
CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
if (!se)
@@ -1083,9 +1210,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item)
- continue;
- if (!canvas_item->is_visible())
+ if (!canvas_item || !canvas_item->is_visible())
continue;
CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
if (!se)
@@ -1141,9 +1266,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item)
- continue;
- if (!canvas_item->is_visible())
+ if (!canvas_item || !canvas_item->is_visible())
continue;
CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
if (!se)
@@ -1168,39 +1291,21 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
if (drag==DRAG_ROTATE) {
Vector2 center = canvas_item->get_global_transform_with_canvas().get_origin();
-
- Matrix32 rot;
- rot.elements[1] = (dfrom - center).normalized();
- rot.elements[0] = rot.elements[1].tangent();
- float ang = rot.xform_inv(dto-center).atan2();
- canvas_item->edit_rotate(ang);
- display_rotate_to = dto;
- display_rotate_from = center;
+ if (Node2D *node = canvas_item->cast_to<Node2D>()) {
+ Matrix32 rot;
+ rot.elements[1] = (dfrom - center).normalized();
+ rot.elements[0] = rot.elements[1].tangent();
+ node->set_rot(snap_angle(rot.xform_inv(dto-center).atan2(), node->get_rot()));
+ display_rotate_to = dto;
+ display_rotate_from = center;
+ viewport->update();
+ }
continue;
}
- if (pixel_snap || (is_snap_active() && get_snap().x>0 && get_snap().y>0)) {
-
- if (drag!=DRAG_ALL) {
- dfrom=drag_point_from;
- dto=snapify(dto);
- } else {
-
- Vector2 newpos = drag_point_from + (dto-dfrom);
- Vector2 disp;
- if (!is_snap_active() || get_snap().x<1 || get_snap().y<1) {
-
- disp.x = Math::fposmod(newpos.x,1);
- disp.y = Math::fposmod(newpos.y,1);
-
- } else {
- disp.x = Math::fposmod(newpos.x,get_snap().x);
- disp.y = Math::fposmod(newpos.y,get_snap().y);
- }
- dto-=disp;
- }
- }
+ dfrom = drag_point_from;
+ dto = snap_point(dto - (drag == DRAG_ALL ? drag_from - drag_point_from : Vector2(0, 0)), drag_point_from);
Vector2 drag_vector =
canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dto) -
@@ -1308,8 +1413,6 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
-
-
if (!dragging_bone) {
local_rect.pos=begin;
@@ -1492,32 +1595,32 @@ void CanvasItemEditor::_viewport_draw() {
_update_scrollbars();
RID ci=viewport->get_canvas_item();
- if (get_snap().x>0 && get_snap().y>0 && is_snap_active() && true ) {
-
+ if (snap_show_grid) {
Size2 s = viewport->get_size();
-
int last_cell;
Matrix32 xform = transform.affine_inverse();
- for(int i=0;i<s.width;i++) {
- int cell = Math::fast_ftoi(Math::floor(xform.xform(Vector2(i,0)).x/get_snap().x));
- if (i==0)
+ if (snap_step.x!=0) {
+ for(int i=0;i<s.width;i++) {
+ int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(i,0)).x-snap_offset.x)/snap_step.x));
+ if (i==0)
+ last_cell=cell;
+ if (last_cell!=cell)
+ viewport->draw_line(Point2(i,0),Point2(i,s.height),Color(0.3,0.7,1,0.3));
last_cell=cell;
- if (last_cell!=cell)
- viewport->draw_line(Point2(i,0),Point2(i,s.height),Color(0.3,0.7,1,0.3));
- last_cell=cell;
+ }
}
- for(int i=0;i<s.height;i++) {
-
- int cell = Math::fast_ftoi(Math::floor(xform.xform(Vector2(0,i)).y/get_snap().y));
- if (i==0)
+ if (snap_step.y!=0) {
+ for(int i=0;i<s.height;i++) {
+ int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(0,i)).y-snap_offset.y)/snap_step.y));
+ if (i==0)
+ last_cell=cell;
+ if (last_cell!=cell)
+ viewport->draw_line(Point2(0,i),Point2(s.width,i),Color(0.3,0.7,1,0.3));
last_cell=cell;
- if (last_cell!=cell)
- viewport->draw_line(Point2(0,i),Point2(s.width,i),Color(0.3,0.7,1,0.3));
- last_cell=cell;
+ }
}
-
}
if (viewport->has_focus()) {
@@ -1545,9 +1648,7 @@ void CanvasItemEditor::_viewport_draw() {
CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
- if (!canvas_item)
- continue;
- if (!canvas_item->is_visible())
+ if (!canvas_item || !canvas_item->is_visible())
continue;
CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
if (!se)
@@ -1764,9 +1865,7 @@ void CanvasItemEditor::_notification(int p_what) {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item)
- continue;
- if (!canvas_item->is_visible())
+ if (!canvas_item || !canvas_item->is_visible())
continue;
CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
@@ -1824,8 +1923,6 @@ void CanvasItemEditor::_notification(int p_what) {
group_button->set_icon(get_icon("Group","EditorIcons"));
ungroup_button->set_icon(get_icon("Ungroup","EditorIcons"));
key_insert_button->set_icon(get_icon("Key","EditorIcons"));
- snap_x->connect("value_changed",this,"_snap_changed");
- snap_y->connect("value_changed",this,"_snap_changed");
}
@@ -2013,90 +2110,40 @@ void CanvasItemEditor::_update_scroll(float) {
}
-Point2 CanvasItemEditor::snapify(const Point2& p_pos) const {
-
- bool active=is_snap_active();
-
- Vector2 pos = p_pos;
-
- if (!active || get_snap().x<1 || get_snap().y<1) {
-
- if (pixel_snap) {
-
- pos.x=Math::stepify(pos.x,1);
- pos.y=Math::stepify(pos.y,1);
- }
-
- return pos;
- }
-
-
- pos.x=Math::stepify(pos.x,get_snap().x);
- pos.y=Math::stepify(pos.y,get_snap().y);
- return pos;
-
-
-}
-
-
void CanvasItemEditor::_popup_callback(int p_op) {
last_option=MenuOption(p_op);
switch(p_op) {
case SNAP_USE: {
-
+ snap_grid = !snap_grid;
int idx = edit_menu->get_popup()->get_item_index(SNAP_USE);
- edit_menu->get_popup()->set_item_checked( idx,!edit_menu->get_popup()->is_item_checked(0));
+ edit_menu->get_popup()->set_item_checked(idx,snap_grid);
+ } break;
+ case SNAP_SHOW_GRID: {
+ snap_show_grid = !snap_show_grid;
+ int idx = edit_menu->get_popup()->get_item_index(SNAP_SHOW_GRID);
+ edit_menu->get_popup()->set_item_checked(idx,snap_show_grid);
viewport->update();
} break;
+ case SNAP_USE_ROTATION: {
+ snap_rotation = !snap_rotation;
+ int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_ROTATION);
+ edit_menu->get_popup()->set_item_checked(idx,snap_rotation);
+ } break;
+ case SNAP_RELATIVE: {
+ snap_relative = !snap_relative;
+ int idx = edit_menu->get_popup()->get_item_index(SNAP_RELATIVE);
+ edit_menu->get_popup()->set_item_checked(idx,snap_relative);
+ } break;
case SNAP_USE_PIXEL: {
- pixel_snap = ! pixel_snap;
+ snap_pixel = !snap_pixel;
int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_PIXEL);
- edit_menu->get_popup()->set_item_checked(idx,pixel_snap);
- } break;
- case SNAP_OBJECT_CENTERS: {
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- undo_redo->create_action("Snap Object Centers");
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item)
- continue;
- if (!canvas_item->is_visible())
- continue;
- Node2D* node = canvas_item->cast_to<Node2D>();
- if (!node)
- continue;
-
- Matrix32 gtrans = node->get_global_transform();
- gtrans.elements[2]=snapify(gtrans.elements[2]);
-
- undo_redo->add_do_method(node,"set_global_transform",gtrans);
- undo_redo->add_undo_method(node,"set_global_transform",node->get_global_transform());
- }
-
- undo_redo->add_do_method(viewport,"update");
- undo_redo->add_undo_method(viewport,"update");
- undo_redo->commit_action();
-
+ edit_menu->get_popup()->set_item_checked(idx,snap_pixel);
} break;
case SNAP_CONFIGURE: {
- updating_value_dialog=true;
-
- snap_dialog->popup_centered_minsize();
-/*
- dialog_label->set_text("Snap (Pixels):");
- dialog_val->set_min(1);
- dialog_val->set_step(1);
- dialog_val->set_max(4096);
- dialog_val->set_val(snap);
- value_dialog->popup_centered(Size2(200,85));
- */
- updating_value_dialog=false;
-
+ ((SnapDialog *)snap_dialog)->set_fields(snap_offset, snap_step, snap_rotation_offset, snap_rotation_step);
+ snap_dialog->popup_centered(Size2(200,160));
} break;
case ZOOM_IN: {
zoom=zoom*(1.0/0.5);
@@ -2140,9 +2187,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item)
- continue;
- if (!canvas_item->is_visible())
+ if (!canvas_item || !canvas_item->is_visible())
continue;
canvas_item->set_meta("_edit_lock_",true);
@@ -2157,9 +2202,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item)
- continue;
- if (!canvas_item->is_visible())
+ if (!canvas_item || !canvas_item->is_visible())
continue;
@@ -2177,9 +2220,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item)
- continue;
- if (!canvas_item->is_visible())
+ if (!canvas_item || !canvas_item->is_visible())
continue;
canvas_item->set_meta("_edit_group_",true);
@@ -2194,9 +2235,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item)
- continue;
- if (!canvas_item->is_visible())
+ if (!canvas_item || !canvas_item->is_visible())
continue;
canvas_item->set_meta("_edit_group_",Variant());
@@ -2214,9 +2253,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item)
- continue;
- if (!canvas_item->is_visible())
+ if (!canvas_item || !canvas_item->is_visible())
continue;
@@ -2284,9 +2321,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
- if (!canvas_item)
- continue;
- if (!canvas_item->is_visible())
+ if (!canvas_item || !canvas_item->is_visible())
continue;
if (canvas_item->cast_to<Node2D>()) {
@@ -2396,9 +2431,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
- if (!canvas_item)
- continue;
- if (!canvas_item->is_visible())
+ if (!canvas_item || !canvas_item->is_visible())
continue;
@@ -2448,9 +2481,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
- if (!canvas_item)
- continue;
- if (!canvas_item->is_visible())
+ if (!canvas_item || !canvas_item->is_visible())
continue;
if (canvas_item->cast_to<Node2D>()) {
@@ -2576,9 +2607,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item)
- continue;
- if (!canvas_item->is_visible())
+ if (!canvas_item || !canvas_item->is_visible())
continue;
@@ -2858,10 +2887,12 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
PopupMenu *p;
p = edit_menu->get_popup();
p->add_check_item("Use Snap",SNAP_USE);
+ p->add_check_item("Show Grid",SNAP_SHOW_GRID);
+ p->add_check_item("Use Rotation Snap",SNAP_USE_ROTATION);
+ p->add_check_item("Snap Relative",SNAP_RELATIVE);
p->add_item("Configure Snap..",SNAP_CONFIGURE);
p->add_separator();
p->add_check_item("Use Pixel Snap",SNAP_USE_PIXEL);
- p->add_item("Snap Selected Object Centers",SNAP_OBJECT_CENTERS);
p->add_separator();
p->add_item("Expand to Parent",EXPAND_TO_PARENT,KEY_MASK_CMD|KEY_P);
p->add_separator();
@@ -2949,6 +2980,10 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
p->add_item("Paste Pose",ANIM_PASTE_POSE);
p->add_item("Clear Pose",ANIM_CLEAR_POSE,KEY_MASK_SHIFT|KEY_K);
+ snap_dialog = memnew(SnapDialog);
+ snap_dialog->connect("confirmed",this,"_snap_changed");
+ add_child(snap_dialog);
+
value_dialog = memnew( AcceptDialog );
value_dialog->set_title("Set a Value");
value_dialog->get_ok()->set_text("Close");
@@ -2968,33 +3003,19 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
dialog_val->connect("value_changed",this,"_dialog_value_changed");
select_sb = Ref<StyleBoxTexture>( memnew( StyleBoxTexture) );
- snap_dialog = memnew( AcceptDialog );
- VBoxContainer *snap_vb = memnew( VBoxContainer );
- snap_dialog->add_child(snap_vb);
- snap_dialog->set_child_rect(snap_vb);
- snap_dialog->set_title("Snap Configuration");
- snap_x = memnew( SpinBox );
- snap_x->set_custom_minimum_size(Size2(250,0));
- snap_y = memnew( SpinBox );
- snap_x->set_min(1);
- snap_x->set_max(4096);
- snap_x->set_step(1);
- snap_x->set_val(10);
- snap_y->set_min(1);
- snap_y->set_max(4096);
- snap_y->set_step(1);
- snap_y->set_val(10);
- snap_vb->add_margin_child("Snap X",snap_x);
- snap_vb->add_margin_child("Snap Y",snap_y);
- add_child(snap_dialog);
-
-
key_pos=true;
key_rot=true;
key_scale=false;
zoom=1;
- //snap=10;
+ snap_offset=Vector2(0, 0);
+ snap_step=Vector2(10, 10);
+ snap_rotation_offset=0;
+ snap_rotation_step=15 / (180 / Math_PI);
+ snap_grid=false;
+ snap_show_grid=false;
+ snap_rotation=false;
+ snap_pixel=false;
updating_value_dialog=false;
box_selecting=false;
//zoom=0.5;
@@ -3002,7 +3023,6 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
editor->get_animation_editor()->connect("keying_changed",this,"_keying_changed");
set_process_unhandled_key_input(true);
can_move_pivot=false;
- pixel_snap=false;
drag=DRAG_NONE;
}
diff --git a/tools/editor/plugins/canvas_item_editor_plugin.h b/tools/editor/plugins/canvas_item_editor_plugin.h
index 9160742826..f25296abdc 100644
--- a/tools/editor/plugins/canvas_item_editor_plugin.h
+++ b/tools/editor/plugins/canvas_item_editor_plugin.h
@@ -75,9 +75,11 @@ class CanvasItemEditor : public VBoxContainer {
enum MenuOption {
SNAP_USE,
+ SNAP_SHOW_GRID,
+ SNAP_USE_ROTATION,
+ SNAP_RELATIVE,
SNAP_CONFIGURE,
SNAP_USE_PIXEL,
- SNAP_OBJECT_CENTERS,
ZOOM_IN,
ZOOM_OUT,
ZOOM_RESET,
@@ -144,7 +146,15 @@ class CanvasItemEditor : public VBoxContainer {
Matrix32 transform;
float zoom;
- bool pixel_snap;
+ Vector2 snap_offset;
+ Vector2 snap_step;
+ float snap_rotation_step;
+ float snap_rotation_offset;
+ bool snap_grid;
+ bool snap_show_grid;
+ bool snap_rotation;
+ bool snap_relative;
+ bool snap_pixel;
bool box_selecting;
Point2 box_selecting_to;
bool key_pos;
@@ -247,14 +257,12 @@ class CanvasItemEditor : public VBoxContainer {
CanvasItem* _select_canvas_item_at_pos(const Point2 &p_pos,Node* p_node,const Matrix32& p_parent_xform,const Matrix32& p_canvas_xform);
void _find_canvas_items_at_rect(const Rect2& p_rect,Node* p_node,const Matrix32& p_parent_xform,const Matrix32& p_canvas_xform,List<CanvasItem*> *r_items);
+ ConfirmationDialog *snap_dialog;
+
AcceptDialog *value_dialog;
Label *dialog_label;
SpinBox *dialog_val;
-
- AcceptDialog *snap_dialog;
- SpinBox *snap_x;
- SpinBox *snap_y;
-
+
CanvasItem *ref_item;
void _add_canvas_item(CanvasItem *p_canvas_item);
@@ -265,7 +273,6 @@ class CanvasItemEditor : public VBoxContainer {
DragType _find_drag_type(const Matrix32& p_xform, const Rect2& p_local_rect, const Point2& p_click, Vector2& r_point);
- Point2 snapify(const Point2& p_pos) const;
void _popup_callback(int p_op);
bool updating_scroll;
void _update_scroll(float);
@@ -275,6 +282,7 @@ class CanvasItemEditor : public VBoxContainer {
void _append_canvas_item(CanvasItem *p_item);
void _dialog_value_changed(double);
+ void _snap_changed();
UndoRedo *undo_redo;
Point2 _find_topleftmost_point();
@@ -293,7 +301,6 @@ class CanvasItemEditor : public VBoxContainer {
void _viewport_input_event(const InputEvent& p_event);
void _viewport_draw();
- void _snap_changed(double);
HSplitContainer *palette_split;
VSplitContainer *bottom_split;
@@ -339,8 +346,8 @@ protected:
static CanvasItemEditor *singleton;
public:
- bool is_snap_active() const;
- Size2i get_snap() const { return Size2i(snap_x->get_val(),snap_y->get_val()); }
+ Vector2 snap_point(Vector2 p_target, Vector2 p_start = Vector2(0, 0)) const;
+ float snap_angle(float p_target, float p_start = 0) const;
Matrix32 get_canvas_transform() const { return transform; }
diff --git a/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp b/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp
index 9a0d5b4066..a533c6aa1e 100644
--- a/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp
+++ b/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp
@@ -35,17 +35,6 @@ void CollisionPolygon2DEditor::_node_removed(Node *p_node) {
}
-Vector2 CollisionPolygon2DEditor::snap_point(const Vector2& p_point) const {
-
- if (canvas_item_editor->is_snap_active()) {
-
- return p_point.snapped(Vector2(1,1)*canvas_item_editor->get_snap());
-
- } else {
- return p_point;
- }
-}
-
void CollisionPolygon2DEditor::_menu_option(int p_option) {
switch(p_option) {
@@ -99,7 +88,7 @@ bool CollisionPolygon2DEditor::forward_input_event(const InputEvent& p_event) {
Vector2 gpoint = Point2(mb.x,mb.y);
Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint=snap_point(cpoint);
+ cpoint=canvas_item_editor->snap_point(cpoint);
cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
Vector<Vector2> poly = node->get_polygon();
@@ -302,7 +291,7 @@ bool CollisionPolygon2DEditor::forward_input_event(const InputEvent& p_event) {
Vector2 gpoint = Point2(mm.x,mm.y);
Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint=snap_point(cpoint);
+ cpoint=canvas_item_editor->snap_point(cpoint);
edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
canvas_item_editor->get_viewport_control()->update();
diff --git a/tools/editor/plugins/collision_polygon_2d_editor_plugin.h b/tools/editor/plugins/collision_polygon_2d_editor_plugin.h
index 052019b6c5..f34405b355 100644
--- a/tools/editor/plugins/collision_polygon_2d_editor_plugin.h
+++ b/tools/editor/plugins/collision_polygon_2d_editor_plugin.h
@@ -53,7 +53,6 @@ protected:
static void _bind_methods();
public:
- Vector2 snap_point(const Vector2& p_point) const;
bool forward_input_event(const InputEvent& p_event);
void edit(Node *p_collision_polygon);
CollisionPolygon2DEditor(EditorNode *p_editor);
diff --git a/tools/editor/plugins/collision_polygon_editor_plugin.cpp b/tools/editor/plugins/collision_polygon_editor_plugin.cpp
index a6f2085a19..126328bac3 100644
--- a/tools/editor/plugins/collision_polygon_editor_plugin.cpp
+++ b/tools/editor/plugins/collision_polygon_editor_plugin.cpp
@@ -70,19 +70,6 @@ void CollisionPolygonEditor::_node_removed(Node *p_node) {
}
-Vector2 CollisionPolygonEditor::snap_point(const Vector2& p_point) const {
-
- return p_point;
-
- if (CanvasItemEditor::get_singleton()->is_snap_active()) {
-
- return p_point.snapped(Vector2(1,1)*CanvasItemEditor::get_singleton()->get_snap());
-
- } else {
- return p_point;
- }
-}
-
void CollisionPolygonEditor::_menu_option(int p_option) {
switch(p_option) {
@@ -150,7 +137,7 @@ bool CollisionPolygonEditor::forward_spatial_input_event(Camera* p_camera,const
Vector2 cpoint(spoint.x,spoint.y);
- cpoint=snap_point(cpoint);
+ cpoint=CanvasItemEditor::get_singleton()->snap_point(cpoint);
Vector<Vector2> poly = node->get_polygon();
@@ -364,7 +351,7 @@ bool CollisionPolygonEditor::forward_spatial_input_event(Camera* p_camera,const
Vector2 cpoint(spoint.x,spoint.y);
- cpoint=snap_point(cpoint);
+ cpoint=CanvasItemEditor::get_singleton()->snap_point(cpoint);
edited_point_pos = cpoint;
_polygon_draw();
diff --git a/tools/editor/plugins/collision_polygon_editor_plugin.h b/tools/editor/plugins/collision_polygon_editor_plugin.h
index 54b0706149..1c12ee0041 100644
--- a/tools/editor/plugins/collision_polygon_editor_plugin.h
+++ b/tools/editor/plugins/collision_polygon_editor_plugin.h
@@ -90,7 +90,6 @@ protected:
static void _bind_methods();
public:
- Vector2 snap_point(const Vector2& p_point) const;
virtual bool forward_spatial_input_event(Camera* p_camera,const InputEvent& p_event);
void edit(Node *p_collision_polygon);
CollisionPolygonEditor(EditorNode *p_editor);
diff --git a/tools/editor/plugins/light_occluder_2d_editor_plugin.cpp b/tools/editor/plugins/light_occluder_2d_editor_plugin.cpp
index 5fa3d8ac8f..bf882857d9 100644
--- a/tools/editor/plugins/light_occluder_2d_editor_plugin.cpp
+++ b/tools/editor/plugins/light_occluder_2d_editor_plugin.cpp
@@ -35,17 +35,6 @@ void LightOccluder2DEditor::_node_removed(Node *p_node) {
}
-Vector2 LightOccluder2DEditor::snap_point(const Vector2& p_point) const {
-
- if (canvas_item_editor->is_snap_active()) {
-
- return p_point.snapped(Vector2(1,1)*canvas_item_editor->get_snap());
-
- } else {
- return p_point;
- }
-}
-
void LightOccluder2DEditor::_menu_option(int p_option) {
switch(p_option) {
@@ -109,7 +98,7 @@ bool LightOccluder2DEditor::forward_input_event(const InputEvent& p_event) {
Vector2 gpoint = Point2(mb.x,mb.y);
Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint=snap_point(cpoint);
+ cpoint=canvas_item_editor->snap_point(cpoint);
cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
Vector<Vector2> poly = Variant(node->get_occluder_polygon()->get_polygon());
@@ -317,7 +306,7 @@ bool LightOccluder2DEditor::forward_input_event(const InputEvent& p_event) {
Vector2 gpoint = Point2(mm.x,mm.y);
Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint=snap_point(cpoint);
+ cpoint=canvas_item_editor->snap_point(cpoint);
edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
canvas_item_editor->get_viewport_control()->update();
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/navigation_polygon_editor_plugin.cpp b/tools/editor/plugins/navigation_polygon_editor_plugin.cpp
index 163accfdd3..bc15741d0f 100644
--- a/tools/editor/plugins/navigation_polygon_editor_plugin.cpp
+++ b/tools/editor/plugins/navigation_polygon_editor_plugin.cpp
@@ -45,17 +45,6 @@ void NavigationPolygonEditor::_create_nav() {
undo_redo->commit_action();
}
-Vector2 NavigationPolygonEditor::snap_point(const Vector2& p_point) const {
-
- if (canvas_item_editor->is_snap_active()) {
-
- return p_point.snapped(Vector2(1,1)*canvas_item_editor->get_snap());
-
- } else {
- return p_point;
- }
-}
-
void NavigationPolygonEditor::_menu_option(int p_option) {
switch(p_option) {
@@ -125,7 +114,7 @@ bool NavigationPolygonEditor::forward_input_event(const InputEvent& p_event) {
Vector2 gpoint = Point2(mb.x,mb.y);
Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint=snap_point(cpoint);
+ cpoint=canvas_item_editor->snap_point(cpoint);
cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
@@ -373,7 +362,7 @@ bool NavigationPolygonEditor::forward_input_event(const InputEvent& p_event) {
Vector2 gpoint = Point2(mm.x,mm.y);
Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint=snap_point(cpoint);
+ cpoint=canvas_item_editor->snap_point(cpoint);
edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
canvas_item_editor->get_viewport_control()->update();
diff --git a/tools/editor/plugins/navigation_polygon_editor_plugin.h b/tools/editor/plugins/navigation_polygon_editor_plugin.h
index a86d28c8a8..f742cb011d 100644
--- a/tools/editor/plugins/navigation_polygon_editor_plugin.h
+++ b/tools/editor/plugins/navigation_polygon_editor_plugin.h
@@ -59,7 +59,6 @@ protected:
static void _bind_methods();
public:
- Vector2 snap_point(const Vector2& p_point) const;
bool forward_input_event(const InputEvent& p_event);
void edit(Node *p_collision_polygon);
NavigationPolygonEditor(EditorNode *p_editor);
diff --git a/tools/editor/plugins/path_2d_editor_plugin.cpp b/tools/editor/plugins/path_2d_editor_plugin.cpp
index 49239343a5..a38ec5bb7a 100644
--- a/tools/editor/plugins/path_2d_editor_plugin.cpp
+++ b/tools/editor/plugins/path_2d_editor_plugin.cpp
@@ -62,17 +62,6 @@ void Path2DEditor::_node_removed(Node *p_node) {
}
-Vector2 Path2DEditor::snap_point(const Vector2& p_point) const {
-
- if (canvas_item_editor->is_snap_active()) {
-
- return p_point.snapped(Vector2(1,1)*canvas_item_editor->get_snap());
-
- } else {
- return p_point;
- }
-}
-
bool Path2DEditor::forward_input_event(const InputEvent& p_event) {
if (!node)
@@ -93,8 +82,8 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) {
Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
Vector2 gpoint = Point2(mb.x,mb.y);
- Vector2 cpoint = !mb.mod.alt? snap_point(xform.affine_inverse().xform(gpoint))
- : node->get_global_transform().affine_inverse().xform( snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)) );
+ Vector2 cpoint = !mb.mod.alt? canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint))
+ : node->get_global_transform().affine_inverse().xform( canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)) );
//first check if a point is to be added (segment split)
real_t grab_treshold=EDITOR_DEF("poly_editor/point_grab_radius",8);
@@ -250,9 +239,9 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) {
if (!wip_active) {
wip.clear();
- wip.push_back( snap_point(cpoint) );
+ wip.push_back( canvas_item_editor->snap_point(cpoint) );
wip_active=true;
- edited_point_pos=snap_point(cpoint);
+ edited_point_pos=canvas_item_editor->snap_point(cpoint);
canvas_item_editor->update();
edited_point=1;
return true;
@@ -265,7 +254,7 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) {
return true;
} else {
- wip.push_back( snap_point(cpoint) );
+ wip.push_back( canvas_item_editor->snap_point(cpoint) );
edited_point=wip.size();
canvas_item_editor->update();
return true;
@@ -327,9 +316,9 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) {
if (closest_idx>=0) {
pre_move_edit=poly;
- poly.insert(closest_idx+1,snap_point(xform.affine_inverse().xform(closest_pos)));
+ poly.insert(closest_idx+1,canvas_item_editor->snap_point(xform.affine_inverse().xform(closest_pos)));
edited_point=closest_idx+1;
- edited_point_pos=snap_point(xform.affine_inverse().xform(closest_pos));
+ edited_point_pos=canvas_item_editor->snap_point(xform.affine_inverse().xform(closest_pos));
node->set_polygon(poly);
canvas_item_editor->update();
return true;
@@ -434,8 +423,8 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) {
Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
Vector2 gpoint = Point2(mm.x,mm.y);
- Vector2 cpoint = !mm.mod.alt? snap_point(xform.affine_inverse().xform(gpoint))
- : node->get_global_transform().affine_inverse().xform( snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)) );
+ Vector2 cpoint = !mm.mod.alt? canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint))
+ : node->get_global_transform().affine_inverse().xform( canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)) );
Ref<Curve2D> curve = node->get_curve();
@@ -471,7 +460,7 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) {
Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
Vector2 gpoint = Point2(mm.x,mm.y);
- edited_point_pos = snap_point(xform.affine_inverse().xform(gpoint));
+ edited_point_pos = canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint));
canvas_item_editor->update();
}
diff --git a/tools/editor/plugins/path_2d_editor_plugin.h b/tools/editor/plugins/path_2d_editor_plugin.h
index 73de2cc838..6ff69b96a2 100644
--- a/tools/editor/plugins/path_2d_editor_plugin.h
+++ b/tools/editor/plugins/path_2d_editor_plugin.h
@@ -94,7 +94,6 @@ protected:
static void _bind_methods();
public:
- Vector2 snap_point(const Vector2& p_point) const;
bool forward_input_event(const InputEvent& p_event);
void edit(Node *p_path2d);
Path2DEditor(EditorNode *p_editor);
diff --git a/tools/editor/plugins/polygon_2d_editor_plugin.cpp b/tools/editor/plugins/polygon_2d_editor_plugin.cpp
index 27e539d50b..3858bf2c68 100644
--- a/tools/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/tools/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -69,17 +69,6 @@ void Polygon2DEditor::_node_removed(Node *p_node) {
}
-Vector2 Polygon2DEditor::snap_point(const Vector2& p_point) const {
-
- if (canvas_item_editor->is_snap_active()) {
-
- return p_point.snapped(Vector2(1,1)*canvas_item_editor->get_snap());
-
- } else {
- return p_point;
- }
-}
-
void Polygon2DEditor::_menu_option(int p_option) {
switch(p_option) {
@@ -201,7 +190,7 @@ bool Polygon2DEditor::forward_input_event(const InputEvent& p_event) {
Vector2 gpoint = Point2(mb.x,mb.y);
Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint=snap_point(cpoint);
+ cpoint=canvas_item_editor->snap_point(cpoint);
cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
@@ -405,7 +394,7 @@ bool Polygon2DEditor::forward_input_event(const InputEvent& p_event) {
Vector2 gpoint = Point2(mm.x,mm.y);
Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint=snap_point(cpoint);
+ cpoint=canvas_item_editor->snap_point(cpoint);
edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
canvas_item_editor->get_viewport_control()->update();
diff --git a/tools/editor/plugins/polygon_2d_editor_plugin.h b/tools/editor/plugins/polygon_2d_editor_plugin.h
index 88d1c20493..8f807cb7e8 100644
--- a/tools/editor/plugins/polygon_2d_editor_plugin.h
+++ b/tools/editor/plugins/polygon_2d_editor_plugin.h
@@ -92,7 +92,6 @@ protected:
static void _bind_methods();
public:
- Vector2 snap_point(const Vector2& p_point) const;
bool forward_input_event(const InputEvent& p_event);
void edit(Node *p_collision_polygon);
Polygon2DEditor(EditorNode *p_editor);
diff --git a/tools/editor/plugins/sample_library_editor_plugin.cpp b/tools/editor/plugins/sample_library_editor_plugin.cpp
index 41c84f6e2c..96d72595ab 100644
--- a/tools/editor/plugins/sample_library_editor_plugin.cpp
+++ b/tools/editor/plugins/sample_library_editor_plugin.cpp
@@ -235,6 +235,7 @@ void SampleLibraryEditor::_update_library() {
List<StringName> names;
sample_library->get_sample_list(&names);
+ names.sort_custom<StringName::AlphCompare>();
for(List<StringName>::Element *E=names.front();E;E=E->next()) {
diff --git a/tools/editor/plugins/sample_player_editor_plugin.cpp b/tools/editor/plugins/sample_player_editor_plugin.cpp
index 405107889c..2e31467dc7 100644
--- a/tools/editor/plugins/sample_player_editor_plugin.cpp
+++ b/tools/editor/plugins/sample_player_editor_plugin.cpp
@@ -94,6 +94,7 @@ void SamplePlayerEditor::_update_sample_library() {
List<StringName> samplenames;
sl->get_sample_list(&samplenames);
+ samplenames.sort_custom<StringName::AlphCompare>();
for(List<StringName>::Element *E=samplenames.front();E;E=E->next()) {
samples->add_item(E->get());
}
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/plugins/tile_map_editor_plugin.h b/tools/editor/plugins/tile_map_editor_plugin.h
index 367e687d77..fe1295fe98 100644
--- a/tools/editor/plugins/tile_map_editor_plugin.h
+++ b/tools/editor/plugins/tile_map_editor_plugin.h
@@ -116,7 +116,6 @@ protected:
public:
HBoxContainer *get_canvas_item_editor_hb() const { return canvas_item_editor_hb; }
- Vector2 snap_point(const Vector2& p_point) const;
bool forward_input_event(const InputEvent& p_event);
void edit(Node *p_tile_map);
TileMapEditor(EditorNode *p_editor);
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"