diff options
Diffstat (limited to 'scene')
402 files changed, 21482 insertions, 19919 deletions
diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp index f10bd2f30..366c3a8bd 100644 --- a/scene/2d/animated_sprite.cpp +++ b/scene/2d/animated_sprite.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,7 +30,8 @@ #include "animated_sprite.h" #include "os/os.h" #include "scene/scene_string_names.h" -#include "scene/scene_string_names.h" + +#define NORMAL_SUFFIX "_normal" //////////////////////////// @@ -81,6 +83,7 @@ void SpriteFrames::add_animation(const StringName &p_anim) { ERR_FAIL_COND(animations.has(p_anim)); animations[p_anim] = Anim(); + animations[p_anim].normal_name = String(p_anim) + NORMAL_SUFFIX; } bool SpriteFrames::has_animation(const StringName &p_anim) const { @@ -100,6 +103,7 @@ void SpriteFrames::rename_animation(const StringName &p_prev, const StringName & Anim anim = animations[p_prev]; animations.erase(p_prev); animations[p_next] = anim; + animations[p_next].normal_name = String(p_next) + NORMAL_SUFFIX; } Vector<String> SpriteFrames::_get_animation_list() const { @@ -342,6 +346,7 @@ void AnimatedSprite::_notification(int p_what) { update(); _change_notify("frame"); + emit_signal(SceneStringNames::get_singleton()->frame_changed); } float to_process = MIN(timeout, remaining); @@ -373,6 +378,8 @@ void AnimatedSprite::_notification(int p_what) { return; } + Ref<Texture> normal = frames->get_normal_frame(animation, frame); + //print_line("DECIDED TO DRAW"); RID ci = get_canvas_item(); @@ -399,7 +406,7 @@ void AnimatedSprite::_notification(int p_what) { dst_rect.size.y = -dst_rect.size.y; //texture->draw_rect(ci,dst_rect,false,modulate); - texture->draw_rect_region(ci, dst_rect, Rect2(Vector2(), texture->get_size())); + texture->draw_rect_region(ci, dst_rect, Rect2(Vector2(), texture->get_size()), Color(1, 1, 1), false, normal); //VisualServer::get_singleton()->canvas_item_add_texture_rect_region(ci,dst_rect,texture->get_rid(),src_rect,modulate); } break; @@ -610,8 +617,8 @@ String AnimatedSprite::get_configuration_warning() const { void AnimatedSprite::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_sprite_frames", "sprite_frames:SpriteFrames"), &AnimatedSprite::set_sprite_frames); - ClassDB::bind_method(D_METHOD("get_sprite_frames:SpriteFrames"), &AnimatedSprite::get_sprite_frames); + ClassDB::bind_method(D_METHOD("set_sprite_frames", "sprite_frames"), &AnimatedSprite::set_sprite_frames); + ClassDB::bind_method(D_METHOD("get_sprite_frames"), &AnimatedSprite::get_sprite_frames); ClassDB::bind_method(D_METHOD("set_animation", "animation"), &AnimatedSprite::set_animation); ClassDB::bind_method(D_METHOD("get_animation"), &AnimatedSprite::get_animation); diff --git a/scene/2d/animated_sprite.h b/scene/2d/animated_sprite.h index bc0e85b0c..80defac07 100644 --- a/scene/2d/animated_sprite.h +++ b/scene/2d/animated_sprite.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -46,6 +47,8 @@ class SpriteFrames : public Resource { loop = true; speed = 5; } + + StringName normal_name; }; Map<StringName, Anim> animations; @@ -88,6 +91,20 @@ public: return E->get().frames[p_idx]; } + _FORCE_INLINE_ Ref<Texture> get_normal_frame(const StringName &p_anim, int p_idx) const { + + const Map<StringName, Anim>::Element *E = animations.find(p_anim); + ERR_FAIL_COND_V(!E, Ref<Texture>()); + ERR_FAIL_COND_V(p_idx < 0, Ref<Texture>()); + + const Map<StringName, Anim>::Element *EN = animations.find(E->get().normal_name); + + if (!EN || p_idx >= EN->get().frames.size()) + return Ref<Texture>(); + + return EN->get().frames[p_idx]; + } + void set_frame(const StringName &p_anim, int p_idx, const Ref<Texture> &p_frame) { Map<StringName, Anim>::Element *E = animations.find(p_anim); ERR_FAIL_COND(!E); diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp index 61e8ee16a..02a050944 100644 --- a/scene/2d/area_2d.cpp +++ b/scene/2d/area_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -28,7 +29,9 @@ /*************************************************************************/ #include "area_2d.h" #include "scene/scene_string_names.h" +#include "servers/audio_server.h" #include "servers/physics_2d_server.h" + void Area2D::set_space_override_mode(SpaceOverride p_mode) { space_override = p_mode; @@ -328,7 +331,10 @@ void Area2D::_clear_monitoring() { Object *obj = ObjectDB::get_instance(E->key()); Node *node = obj ? obj->cast_to<Node>() : NULL; - ERR_CONTINUE(!node); + + if (!node) //node may have been deleted in previous frame or at other legiminate point + continue; + //ERR_CONTINUE(!node); node->disconnect(SceneStringNames::get_singleton()->tree_entered, this, SceneStringNames::get_singleton()->_body_enter_tree); node->disconnect(SceneStringNames::get_singleton()->tree_exited, this, SceneStringNames::get_singleton()->_body_exit_tree); @@ -356,7 +362,7 @@ void Area2D::_clear_monitoring() { Object *obj = ObjectDB::get_instance(E->key()); Node *node = obj ? obj->cast_to<Node>() : NULL; - if (!node) //node may have been deleted in previous frame, this should not be an error + if (!node) //node may have been deleted in previous frame or at other legiminate point continue; //ERR_CONTINUE(!node); @@ -474,7 +480,7 @@ Array Area2D::get_overlapping_areas() const { bool Area2D::overlaps_area(Node *p_area) const { ERR_FAIL_NULL_V(p_area, false); - const Map<ObjectID, AreaState>::Element *E = area_map.find(p_area->get_instance_ID()); + const Map<ObjectID, AreaState>::Element *E = area_map.find(p_area->get_instance_id()); if (!E) return false; return E->get().in_tree; @@ -483,7 +489,7 @@ bool Area2D::overlaps_area(Node *p_area) const { bool Area2D::overlaps_body(Node *p_body) const { ERR_FAIL_NULL_V(p_body, false); - const Map<ObjectID, BodyState>::Element *E = body_map.find(p_body->get_instance_ID()); + const Map<ObjectID, BodyState>::Element *E = body_map.find(p_body->get_instance_id()); if (!E) return false; return E->get().in_tree; @@ -500,15 +506,15 @@ uint32_t Area2D::get_collision_mask() const { return collision_mask; } -void Area2D::set_layer_mask(uint32_t p_mask) { +void Area2D::set_collision_layer(uint32_t p_layer) { - layer_mask = p_mask; - Physics2DServer::get_singleton()->area_set_layer_mask(get_rid(), p_mask); + collision_layer = p_layer; + Physics2DServer::get_singleton()->area_set_collision_layer(get_rid(), p_layer); } -uint32_t Area2D::get_layer_mask() const { +uint32_t Area2D::get_collision_layer() const { - return layer_mask; + return collision_layer; } void Area2D::set_collision_mask_bit(int p_bit, bool p_value) { @@ -526,19 +532,60 @@ bool Area2D::get_collision_mask_bit(int p_bit) const { return get_collision_mask() & (1 << p_bit); } -void Area2D::set_layer_mask_bit(int p_bit, bool p_value) { +void Area2D::set_collision_layer_bit(int p_bit, bool p_value) { - uint32_t mask = get_layer_mask(); + uint32_t layer = get_collision_layer(); if (p_value) - mask |= 1 << p_bit; + layer |= 1 << p_bit; else - mask &= ~(1 << p_bit); - set_layer_mask(mask); + layer &= ~(1 << p_bit); + set_collision_layer(layer); +} + +bool Area2D::get_collision_layer_bit(int p_bit) const { + + return get_collision_layer() & (1 << p_bit); +} + +void Area2D::set_audio_bus_override(bool p_override) { + + audio_bus_override = p_override; +} + +bool Area2D::is_overriding_audio_bus() const { + + return audio_bus_override; } -bool Area2D::get_layer_mask_bit(int p_bit) const { +void Area2D::set_audio_bus(const StringName &p_audio_bus) { - return get_layer_mask() & (1 << p_bit); + audio_bus = p_audio_bus; +} + +StringName Area2D::get_audio_bus() const { + + for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { + if (AudioServer::get_singleton()->get_bus_name(i) == audio_bus) { + return audio_bus; + } + } + return "Master"; +} + +void Area2D::_validate_property(PropertyInfo &property) const { + + if (property.name == "audio_bus_name") { + + String options; + for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { + if (i > 0) + options += ","; + String name = AudioServer::get_singleton()->get_bus_name(i); + options += name; + } + + property.hint_string = options; + } } void Area2D::_bind_methods() { @@ -576,14 +623,14 @@ void Area2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &Area2D::set_collision_mask); ClassDB::bind_method(D_METHOD("get_collision_mask"), &Area2D::get_collision_mask); - ClassDB::bind_method(D_METHOD("set_layer_mask", "layer_mask"), &Area2D::set_layer_mask); - ClassDB::bind_method(D_METHOD("get_layer_mask"), &Area2D::get_layer_mask); + ClassDB::bind_method(D_METHOD("set_collision_layer", "collision_layer"), &Area2D::set_collision_layer); + ClassDB::bind_method(D_METHOD("get_collision_layer"), &Area2D::get_collision_layer); ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &Area2D::set_collision_mask_bit); ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &Area2D::get_collision_mask_bit); - ClassDB::bind_method(D_METHOD("set_layer_mask_bit", "bit", "value"), &Area2D::set_layer_mask_bit); - ClassDB::bind_method(D_METHOD("get_layer_mask_bit", "bit"), &Area2D::get_layer_mask_bit); + ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &Area2D::set_collision_layer_bit); + ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &Area2D::get_collision_layer_bit); ClassDB::bind_method(D_METHOD("set_monitoring", "enable"), &Area2D::set_monitoring); ClassDB::bind_method(D_METHOD("is_monitoring"), &Area2D::is_monitoring); @@ -597,6 +644,12 @@ void Area2D::_bind_methods() { ClassDB::bind_method(D_METHOD("overlaps_body", "body"), &Area2D::overlaps_body); ClassDB::bind_method(D_METHOD("overlaps_area", "area"), &Area2D::overlaps_area); + ClassDB::bind_method(D_METHOD("set_audio_bus", "name"), &Area2D::set_audio_bus); + ClassDB::bind_method(D_METHOD("get_audio_bus"), &Area2D::get_audio_bus); + + ClassDB::bind_method(D_METHOD("set_audio_bus_override", "enable"), &Area2D::set_audio_bus_override); + ClassDB::bind_method(D_METHOD("is_overriding_audio_bus"), &Area2D::is_overriding_audio_bus); + ClassDB::bind_method(D_METHOD("_body_inout"), &Area2D::_body_inout); ClassDB::bind_method(D_METHOD("_area_inout"), &Area2D::_area_inout); @@ -621,8 +674,12 @@ void Area2D::_bind_methods() { ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "monitoring"), "set_monitoring", "is_monitoring"); ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "monitorable"), "set_monitorable", "is_monitorable"); ADD_GROUP("Collision", "collision_"); - ADD_PROPERTYNO(PropertyInfo(Variant::INT, "collision_layers", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_layer_mask", "get_layer_mask"); + ADD_PROPERTYNO(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_layer", "get_collision_layer"); ADD_PROPERTYNO(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask"); + + ADD_GROUP("Audio Bus", "audio_bus_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_bus_override"), "set_audio_bus_override", "is_overriding_audio_bus"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "audio_bus_name", PROPERTY_HINT_ENUM, ""), "set_audio_bus", "get_audio_bus"); } Area2D::Area2D() @@ -640,7 +697,8 @@ Area2D::Area2D() monitoring = false; monitorable = false; collision_mask = 1; - layer_mask = 1; + collision_layer = 1; + audio_bus_override = false; set_monitoring(true); set_monitorable(true); } diff --git a/scene/2d/area_2d.h b/scene/2d/area_2d.h index 2402ff763..12d71f391 100644 --- a/scene/2d/area_2d.h +++ b/scene/2d/area_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -54,7 +55,7 @@ private: real_t linear_damp; real_t angular_damp; uint32_t collision_mask; - uint32_t layer_mask; + uint32_t collision_layer; int priority; bool monitoring; bool monitorable; @@ -125,9 +126,13 @@ private: Map<ObjectID, AreaState> area_map; void _clear_monitoring(); + bool audio_bus_override; + StringName audio_bus; + protected: void _notification(int p_what); static void _bind_methods(); + void _validate_property(PropertyInfo &property) const; public: void set_space_override_mode(SpaceOverride p_mode); @@ -163,14 +168,14 @@ public: void set_collision_mask(uint32_t p_mask); uint32_t get_collision_mask() const; - void set_layer_mask(uint32_t p_mask); - uint32_t get_layer_mask() const; + void set_collision_layer(uint32_t p_layer); + uint32_t get_collision_layer() const; void set_collision_mask_bit(int p_bit, bool p_value); bool get_collision_mask_bit(int p_bit) const; - void set_layer_mask_bit(int p_bit, bool p_value); - bool get_layer_mask_bit(int p_bit) const; + void set_collision_layer_bit(int p_bit, bool p_value); + bool get_collision_layer_bit(int p_bit) const; Array get_overlapping_bodies() const; //function for script Array get_overlapping_areas() const; //function for script @@ -178,6 +183,12 @@ public: bool overlaps_area(Node *p_area) const; bool overlaps_body(Node *p_body) const; + void set_audio_bus_override(bool p_override); + bool is_overriding_audio_bus() const; + + void set_audio_bus(const StringName &p_audio_bus); + StringName get_audio_bus() const; + Area2D(); ~Area2D(); }; diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp new file mode 100644 index 000000000..1423a804f --- /dev/null +++ b/scene/2d/audio_stream_player_2d.cpp @@ -0,0 +1,463 @@ + +#include "audio_stream_player_2d.h" +#include "scene/2d/area_2d.h" +#include "scene/main/viewport.h" +void AudioStreamPlayer2D::_mix_audio() { + + if (!stream_playback.is_valid()) { + return; + } + + if (!active) { + return; + } + + if (setseek >= 0.0) { + stream_playback->start(setseek); + setseek = -1.0; //reset seek + } + + //get data + AudioFrame *buffer = mix_buffer.ptr(); + int buffer_size = mix_buffer.size(); + + //mix + stream_playback->mix(buffer, 1.0, buffer_size); + + //write all outputs + for (int i = 0; i < output_count; i++) { + + Output current = outputs[i]; + + //see if current output exists, to keep volume ramp + bool found = false; + for (int j = i; j < prev_output_count; j++) { + if (prev_outputs[j].viewport == current.viewport) { + if (j != i) { + SWAP(prev_outputs[j], prev_outputs[i]); + } + found = true; + break; + } + } + + if (!found) { + //create new if was not used before + if (prev_output_count < MAX_OUTPUTS) { + prev_outputs[prev_output_count] = prev_outputs[i]; //may be owned by another viewport + prev_output_count++; + } + prev_outputs[i] = current; + } + + //mix! + AudioFrame vol_inc = (current.vol - prev_outputs[i].vol) / float(buffer_size); + AudioFrame vol = current.vol; + + switch (AudioServer::get_singleton()->get_speaker_mode()) { + + case AudioServer::SPEAKER_MODE_STEREO: { + AudioFrame *target = AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, 0); + + for (int j = 0; j < buffer_size; j++) { + + target[j] += buffer[j] * vol; + vol += vol_inc; + } + + } break; + case AudioServer::SPEAKER_SURROUND_51: { + + AudioFrame *targets[2] = { + AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, 1), + AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, 2), + }; + + for (int j = 0; j < buffer_size; j++) { + + AudioFrame frame = buffer[j] * vol; + targets[0][j] += frame; + targets[1][j] += frame; + vol += vol_inc; + } + + } break; + case AudioServer::SPEAKER_SURROUND_71: { + + AudioFrame *targets[3] = { + AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, 1), + AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, 2), + AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, 3) + }; + + for (int j = 0; j < buffer_size; j++) { + + AudioFrame frame = buffer[j] * vol; + targets[0][j] += frame; + targets[1][j] += frame; + targets[2][j] += frame; + vol += vol_inc; + } + + } break; + } + + prev_outputs[i] = current; + } + + prev_output_count = output_count; + + //stream is no longer active, disable this. + if (!stream_playback->is_playing()) { + active = false; + } + + output_ready = false; +} + +void AudioStreamPlayer2D::_notification(int p_what) { + + if (p_what == NOTIFICATION_ENTER_TREE) { + + AudioServer::get_singleton()->add_callback(_mix_audios, this); + if (autoplay && !get_tree()->is_editor_hint()) { + play(); + } + } + + if (p_what == NOTIFICATION_EXIT_TREE) { + + AudioServer::get_singleton()->remove_callback(_mix_audios, this); + } + + if (p_what == NOTIFICATION_INTERNAL_FIXED_PROCESS) { + + //update anything related to position first, if possible of course + + if (!output_ready) { + List<Viewport *> viewports; + Ref<World2D> world_2d = get_world_2d(); + ERR_FAIL_COND(world_2d.is_null()); + + int new_output_count = 0; + + Vector2 global_pos = get_global_position(); + + int bus_index = AudioServer::get_singleton()->thread_find_bus_index(bus); + + //check if any area is diverting sound into a bus + + Physics2DDirectSpaceState *space_state = Physics2DServer::get_singleton()->space_get_direct_state(world_2d->get_space()); + + Physics2DDirectSpaceState::ShapeResult sr[MAX_INTERSECT_AREAS]; + + int areas = space_state->intersect_point(global_pos, sr, MAX_INTERSECT_AREAS, Set<RID>(), area_mask, Physics2DDirectSpaceState::TYPE_MASK_AREA); + + for (int i = 0; i < areas; i++) { + if (!sr[i].collider) + continue; + + Area2D *area2d = sr[i].collider->cast_to<Area2D>(); + if (!area2d) + continue; + + if (!area2d->is_overriding_audio_bus()) + continue; + + StringName bus_name = area2d->get_audio_bus(); + bus_index = AudioServer::get_singleton()->thread_find_bus_index(bus_name); + break; + } + + world_2d->get_viewport_list(&viewports); + for (List<Viewport *>::Element *E = viewports.front(); E; E = E->next()) { + + Viewport *vp = E->get(); + if (vp->is_audio_listener_2d()) { + + //compute matrix to convert to screen + Transform2D to_screen = vp->get_global_canvas_transform() * vp->get_canvas_transform(); + Vector2 screen_size = vp->get_visible_rect().size; + + //screen in global is used for attenuation + Vector2 screen_in_global = to_screen.affine_inverse().xform(screen_size * 0.5); + + float dist = global_pos.distance_to(screen_in_global); //distance to screen center + + if (dist > max_distance) + continue; //cant hear this sound in this viewport + + float multiplier = Math::pow(1.0f - dist / max_distance, attenuation); + multiplier *= Math::db2linear(volume_db); //also apply player volume! + + //point in screen is used for panning + Vector2 point_in_screen = to_screen.xform(global_pos); + + float pan = CLAMP(point_in_screen.x / screen_size.width, 0.0, 1.0); + + float l = 1.0 - pan; + float r = pan; + + outputs[new_output_count].vol = AudioFrame(l, r) * multiplier; + outputs[new_output_count].bus_index = bus_index; + outputs[new_output_count].viewport = vp; //keep pointer only for reference + new_output_count++; + if (new_output_count == MAX_OUTPUTS) + break; + } + } + + output_count = new_output_count; + output_ready = true; + } + + //start playing if requested + if (setplay >= 0.0) { + setseek = setplay; + active = true; + setplay = -1; + _change_notify("playing"); //update property in editor + } + + //stop playing if no longer active + if (!active) { + set_fixed_process_internal(false); + _change_notify("playing"); //update property in editor + } + } +} + +void AudioStreamPlayer2D::set_stream(Ref<AudioStream> p_stream) { + + ERR_FAIL_COND(!p_stream.is_valid()); + AudioServer::get_singleton()->lock(); + + mix_buffer.resize(AudioServer::get_singleton()->thread_get_mix_buffer_size()); + + if (stream_playback.is_valid()) { + stream_playback.unref(); + stream.unref(); + active = false; + setseek = -1; + } + + stream = p_stream; + stream_playback = p_stream->instance_playback(); + + if (stream_playback.is_null()) { + stream.unref(); + ERR_FAIL_COND(stream_playback.is_null()); + } + + AudioServer::get_singleton()->unlock(); +} + +Ref<AudioStream> AudioStreamPlayer2D::get_stream() const { + + return stream; +} + +void AudioStreamPlayer2D::set_volume_db(float p_volume) { + + volume_db = p_volume; +} +float AudioStreamPlayer2D::get_volume_db() const { + + return volume_db; +} + +void AudioStreamPlayer2D::play(float p_from_pos) { + + if (stream_playback.is_valid()) { + setplay = p_from_pos; + output_ready = false; + set_fixed_process_internal(true); + } +} + +void AudioStreamPlayer2D::seek(float p_seconds) { + + if (stream_playback.is_valid()) { + setseek = p_seconds; + } +} + +void AudioStreamPlayer2D::stop() { + + if (stream_playback.is_valid()) { + active = false; + set_fixed_process_internal(false); + setplay = -1; + } +} + +bool AudioStreamPlayer2D::is_playing() const { + + if (stream_playback.is_valid()) { + return active; // && stream_playback->is_playing(); + } + + return false; +} + +float AudioStreamPlayer2D::get_pos() { + + if (stream_playback.is_valid()) { + return stream_playback->get_pos(); + } + + return 0; +} + +void AudioStreamPlayer2D::set_bus(const StringName &p_bus) { + + //if audio is active, must lock this + AudioServer::get_singleton()->lock(); + bus = p_bus; + AudioServer::get_singleton()->unlock(); +} +StringName AudioStreamPlayer2D::get_bus() const { + + for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { + if (AudioServer::get_singleton()->get_bus_name(i) == bus) { + return bus; + } + } + return "Master"; +} + +void AudioStreamPlayer2D::set_autoplay(bool p_enable) { + + autoplay = p_enable; +} +bool AudioStreamPlayer2D::is_autoplay_enabled() { + + return autoplay; +} + +void AudioStreamPlayer2D::_set_playing(bool p_enable) { + + if (p_enable) + play(); + else + stop(); +} +bool AudioStreamPlayer2D::_is_active() const { + + return active; +} + +void AudioStreamPlayer2D::_validate_property(PropertyInfo &property) const { + + if (property.name == "bus") { + + String options; + for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { + if (i > 0) + options += ","; + String name = AudioServer::get_singleton()->get_bus_name(i); + options += name; + } + + property.hint_string = options; + } +} + +void AudioStreamPlayer2D::_bus_layout_changed() { + + _change_notify(); +} + +void AudioStreamPlayer2D::set_max_distance(float p_pixels) { + + ERR_FAIL_COND(p_pixels <= 0.0); + max_distance = p_pixels; +} + +float AudioStreamPlayer2D::get_max_distance() const { + + return max_distance; +} + +void AudioStreamPlayer2D::set_attenuation(float p_curve) { + + attenuation = p_curve; +} +float AudioStreamPlayer2D::get_attenuation() const { + + return attenuation; +} + +void AudioStreamPlayer2D::set_area_mask(uint32_t p_mask) { + + area_mask = p_mask; +} + +uint32_t AudioStreamPlayer2D::get_area_mask() const { + + return area_mask; +} + +void AudioStreamPlayer2D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_stream", "stream"), &AudioStreamPlayer2D::set_stream); + ClassDB::bind_method(D_METHOD("get_stream"), &AudioStreamPlayer2D::get_stream); + + ClassDB::bind_method(D_METHOD("set_volume_db", "volume_db"), &AudioStreamPlayer2D::set_volume_db); + ClassDB::bind_method(D_METHOD("get_volume_db"), &AudioStreamPlayer2D::get_volume_db); + + ClassDB::bind_method(D_METHOD("play", "from_pos"), &AudioStreamPlayer2D::play, DEFVAL(0.0)); + ClassDB::bind_method(D_METHOD("seek", "to_pos"), &AudioStreamPlayer2D::seek); + ClassDB::bind_method(D_METHOD("stop"), &AudioStreamPlayer2D::stop); + + ClassDB::bind_method(D_METHOD("is_playing"), &AudioStreamPlayer2D::is_playing); + ClassDB::bind_method(D_METHOD("get_pos"), &AudioStreamPlayer2D::get_pos); + + ClassDB::bind_method(D_METHOD("set_bus", "bus"), &AudioStreamPlayer2D::set_bus); + ClassDB::bind_method(D_METHOD("get_bus"), &AudioStreamPlayer2D::get_bus); + + ClassDB::bind_method(D_METHOD("set_autoplay", "enable"), &AudioStreamPlayer2D::set_autoplay); + ClassDB::bind_method(D_METHOD("is_autoplay_enabled"), &AudioStreamPlayer2D::is_autoplay_enabled); + + ClassDB::bind_method(D_METHOD("_set_playing", "enable"), &AudioStreamPlayer2D::_set_playing); + ClassDB::bind_method(D_METHOD("_is_active"), &AudioStreamPlayer2D::_is_active); + + ClassDB::bind_method(D_METHOD("set_max_distance", "pixels"), &AudioStreamPlayer2D::set_max_distance); + ClassDB::bind_method(D_METHOD("get_max_distance"), &AudioStreamPlayer2D::get_max_distance); + + ClassDB::bind_method(D_METHOD("set_attenuation", "curve"), &AudioStreamPlayer2D::set_attenuation); + ClassDB::bind_method(D_METHOD("get_attenuation"), &AudioStreamPlayer2D::get_attenuation); + + ClassDB::bind_method(D_METHOD("set_area_mask", "mask"), &AudioStreamPlayer2D::set_area_mask); + ClassDB::bind_method(D_METHOD("get_area_mask"), &AudioStreamPlayer2D::get_area_mask); + + ClassDB::bind_method(D_METHOD("_bus_layout_changed"), &AudioStreamPlayer2D::_bus_layout_changed); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_stream", "get_stream"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "volume_db", PROPERTY_HINT_RANGE, "-80,24"), "set_volume_db", "get_volume_db"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_playing", "_is_active"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "is_autoplay_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_distance", PROPERTY_HINT_RANGE, "1,65536,1"), "set_max_distance", "get_max_distance"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "attenuation", PROPERTY_HINT_EXP_EASING), "set_attenuation", "get_attenuation"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "bus", PROPERTY_HINT_ENUM, ""), "set_bus", "get_bus"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "area_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_area_mask", "get_area_mask"); +} + +AudioStreamPlayer2D::AudioStreamPlayer2D() { + + volume_db = 0; + autoplay = false; + setseek = -1; + active = false; + output_count = 0; + prev_output_count = 0; + max_distance = 2000; + attenuation = 1; + setplay = -1; + output_ready = false; + area_mask = 1; + AudioServer::get_singleton()->connect("bus_layout_changed", this, "_bus_layout_changed"); +} + +AudioStreamPlayer2D::~AudioStreamPlayer2D() { +} diff --git a/scene/2d/audio_stream_player_2d.h b/scene/2d/audio_stream_player_2d.h new file mode 100644 index 000000000..25eff61b7 --- /dev/null +++ b/scene/2d/audio_stream_player_2d.h @@ -0,0 +1,96 @@ +#ifndef AUDIO_STREAM_PLAYER_2D_H +#define AUDIO_STREAM_PLAYER_2D_H + +#include "scene/2d/node_2d.h" +#include "servers/audio/audio_stream.h" +#include "servers/audio_server.h" + +class AudioStreamPlayer2D : public Node2D { + + GDCLASS(AudioStreamPlayer2D, Node2D) + +private: + enum { + MAX_OUTPUTS = 8, + MAX_INTERSECT_AREAS = 32 + + }; + + struct Output { + + AudioFrame vol; + int bus_index; + Viewport *viewport; //pointer only used for reference to previous mix + }; + + Output outputs[MAX_OUTPUTS]; + volatile int output_count; + volatile bool output_ready; + + //these are used by audio thread to have a reference of previous volumes (for ramping volume and avoiding clicks) + Output prev_outputs[MAX_OUTPUTS]; + int prev_output_count; + + Ref<AudioStreamPlayback> stream_playback; + Ref<AudioStream> stream; + Vector<AudioFrame> mix_buffer; + + volatile float setseek; + volatile bool active; + volatile float setplay; + + float volume_db; + bool autoplay; + StringName bus; + + void _mix_audio(); + static void _mix_audios(void *self) { reinterpret_cast<AudioStreamPlayer2D *>(self)->_mix_audio(); } + + void _set_playing(bool p_enable); + bool _is_active() const; + + void _bus_layout_changed(); + + uint32_t area_mask; + + float max_distance; + float attenuation; + +protected: + void _validate_property(PropertyInfo &property) const; + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_stream(Ref<AudioStream> p_stream); + Ref<AudioStream> get_stream() const; + + void set_volume_db(float p_volume); + float get_volume_db() const; + + void play(float p_from_pos = 0.0); + void seek(float p_seconds); + void stop(); + bool is_playing() const; + float get_pos(); + + void set_bus(const StringName &p_bus); + StringName get_bus() const; + + void set_autoplay(bool p_enable); + bool is_autoplay_enabled(); + + void set_max_distance(float p_pixels); + float get_max_distance() const; + + void set_attenuation(float p_curve); + float get_attenuation() const; + + void set_area_mask(uint32_t p_mask); + uint32_t get_area_mask() const; + + AudioStreamPlayer2D(); + ~AudioStreamPlayer2D(); +}; + +#endif diff --git a/scene/2d/back_buffer_copy.cpp b/scene/2d/back_buffer_copy.cpp index 5a79cee6d..748a527ca 100644 --- a/scene/2d/back_buffer_copy.cpp +++ b/scene/2d/back_buffer_copy.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/back_buffer_copy.h b/scene/2d/back_buffer_copy.h index b4f83e7db..4080f5069 100644 --- a/scene/2d/back_buffer_copy.h +++ b/scene/2d/back_buffer_copy.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index f8388cdcc..20571abdb 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -119,20 +120,20 @@ Transform2D Camera2D::get_camera_transform() { Rect2 screen_rect(-screen_offset + camera_pos, screen_size * zoom); if (offset != Vector2()) - screen_rect.pos += offset; + screen_rect.position += offset; if (limit_smoothing_enabled) { - if (screen_rect.pos.x < limit[MARGIN_LEFT]) - camera_pos.x -= screen_rect.pos.x - limit[MARGIN_LEFT]; + if (screen_rect.position.x < limit[MARGIN_LEFT]) + camera_pos.x -= screen_rect.position.x - limit[MARGIN_LEFT]; - if (screen_rect.pos.x + screen_rect.size.x > limit[MARGIN_RIGHT]) - camera_pos.x -= screen_rect.pos.x + screen_rect.size.x - limit[MARGIN_RIGHT]; + if (screen_rect.position.x + screen_rect.size.x > limit[MARGIN_RIGHT]) + camera_pos.x -= screen_rect.position.x + screen_rect.size.x - limit[MARGIN_RIGHT]; - if (screen_rect.pos.y + screen_rect.size.y > limit[MARGIN_BOTTOM]) - camera_pos.y -= screen_rect.pos.y + screen_rect.size.y - limit[MARGIN_BOTTOM]; + if (screen_rect.position.y + screen_rect.size.y > limit[MARGIN_BOTTOM]) + camera_pos.y -= screen_rect.position.y + screen_rect.size.y - limit[MARGIN_BOTTOM]; - if (screen_rect.pos.y < limit[MARGIN_TOP]) - camera_pos.y -= screen_rect.pos.y - limit[MARGIN_TOP]; + if (screen_rect.position.y < limit[MARGIN_TOP]) + camera_pos.y -= screen_rect.position.y - limit[MARGIN_TOP]; } if (smoothing_enabled && !get_tree()->is_editor_hint()) { @@ -159,49 +160,47 @@ Transform2D Camera2D::get_camera_transform() { } Rect2 screen_rect(-screen_offset + ret_camera_pos, screen_size * zoom); - if (screen_rect.pos.x < limit[MARGIN_LEFT]) - screen_rect.pos.x = limit[MARGIN_LEFT]; + if (screen_rect.position.x < limit[MARGIN_LEFT]) + screen_rect.position.x = limit[MARGIN_LEFT]; - if (screen_rect.pos.x + screen_rect.size.x > limit[MARGIN_RIGHT]) - screen_rect.pos.x = limit[MARGIN_RIGHT] - screen_rect.size.x; + if (screen_rect.position.x + screen_rect.size.x > limit[MARGIN_RIGHT]) + screen_rect.position.x = limit[MARGIN_RIGHT] - screen_rect.size.x; - if (screen_rect.pos.y + screen_rect.size.y > limit[MARGIN_BOTTOM]) - screen_rect.pos.y = limit[MARGIN_BOTTOM] - screen_rect.size.y; + if (screen_rect.position.y + screen_rect.size.y > limit[MARGIN_BOTTOM]) + screen_rect.position.y = limit[MARGIN_BOTTOM] - screen_rect.size.y; - if (screen_rect.pos.y < limit[MARGIN_TOP]) - screen_rect.pos.y = limit[MARGIN_TOP]; + if (screen_rect.position.y < limit[MARGIN_TOP]) + screen_rect.position.y = limit[MARGIN_TOP]; if (offset != Vector2()) { - screen_rect.pos += offset; - if (screen_rect.pos.x + screen_rect.size.x > limit[MARGIN_RIGHT]) - screen_rect.pos.x = limit[MARGIN_RIGHT] - screen_rect.size.x; + screen_rect.position += offset; + if (screen_rect.position.x + screen_rect.size.x > limit[MARGIN_RIGHT]) + screen_rect.position.x = limit[MARGIN_RIGHT] - screen_rect.size.x; - if (screen_rect.pos.y + screen_rect.size.y > limit[MARGIN_BOTTOM]) - screen_rect.pos.y = limit[MARGIN_BOTTOM] - screen_rect.size.y; + if (screen_rect.position.y + screen_rect.size.y > limit[MARGIN_BOTTOM]) + screen_rect.position.y = limit[MARGIN_BOTTOM] - screen_rect.size.y; - if (screen_rect.pos.x < limit[MARGIN_LEFT]) - screen_rect.pos.x = limit[MARGIN_LEFT]; + if (screen_rect.position.x < limit[MARGIN_LEFT]) + screen_rect.position.x = limit[MARGIN_LEFT]; - if (screen_rect.pos.y < limit[MARGIN_TOP]) - screen_rect.pos.y = limit[MARGIN_TOP]; + if (screen_rect.position.y < limit[MARGIN_TOP]) + screen_rect.position.y = limit[MARGIN_TOP]; } - camera_screen_center = screen_rect.pos + screen_rect.size * 0.5; + camera_screen_center = screen_rect.position + screen_rect.size * 0.5; Transform2D xform; if (rotating) { xform.set_rotation(angle); } xform.scale_basis(zoom); - xform.set_origin(screen_rect.pos /*.floor()*/); + xform.set_origin(screen_rect.position /*.floor()*/); /* if (0) { - xform = get_global_transform() * xform; } else { - xform.elements[2]+=get_global_transform().get_origin(); } */ @@ -266,25 +265,76 @@ void Camera2D::_notification(int p_what) { if (!is_inside_tree() || !get_tree()->is_editor_hint()) break; - Color area_axis_color(0.5, 0.42, 0.87, 0.63); - float area_axis_width = 1; - if (current) - area_axis_width = 3; + if (screen_drawing_enabled) { + Color area_axis_color(0.5, 0.42, 0.87, 0.63); + float area_axis_width = 1; + if (is_current()) { + area_axis_width = 3; + area_axis_color.a = 0.83; + } + + Transform2D inv_camera_transform = get_camera_transform().affine_inverse(); + Size2 screen_size = get_viewport_rect().size; + + Vector2 screen_endpoints[4] = { + inv_camera_transform.xform(Vector2(0, 0)), + inv_camera_transform.xform(Vector2(screen_size.width, 0)), + inv_camera_transform.xform(Vector2(screen_size.width, screen_size.height)), + inv_camera_transform.xform(Vector2(0, screen_size.height)) + }; + + Transform2D inv_transform = get_global_transform().affine_inverse(); // undo global space + + for (int i = 0; i < 4; i++) { + draw_line(inv_transform.xform(screen_endpoints[i]), inv_transform.xform(screen_endpoints[(i + 1) % 4]), area_axis_color, area_axis_width); + } + } + + if (limit_drawing_enabled) { + Color limit_drawing_color(1, 1, 0, 0.63); + float limit_drawing_width = 1; + if (is_current()) { + limit_drawing_color.a = 0.83; + limit_drawing_width = 3; + } - Transform2D inv_camera_transform = get_camera_transform().affine_inverse(); - Size2 screen_size = get_viewport_rect().size; + Vector2 camera_origin = get_global_transform().get_origin(); + Vector2 camera_scale = get_global_transform().get_scale().abs(); + Vector2 limit_points[4] = { + (Vector2(limit[MARGIN_LEFT], limit[MARGIN_TOP]) - camera_origin) / camera_scale, + (Vector2(limit[MARGIN_RIGHT], limit[MARGIN_TOP]) - camera_origin) / camera_scale, + (Vector2(limit[MARGIN_RIGHT], limit[MARGIN_BOTTOM]) - camera_origin) / camera_scale, + (Vector2(limit[MARGIN_LEFT], limit[MARGIN_BOTTOM]) - camera_origin) / camera_scale + }; - Vector2 screen_endpoints[4] = { - inv_camera_transform.xform(Vector2(0, 0)), - inv_camera_transform.xform(Vector2(screen_size.width, 0)), - inv_camera_transform.xform(Vector2(screen_size.width, screen_size.height)), - inv_camera_transform.xform(Vector2(0, screen_size.height)) - }; + for (int i = 0; i < 4; i++) { + draw_line(limit_points[i], limit_points[(i + 1) % 4], limit_drawing_color, limit_drawing_width); + } + } - Transform2D inv_transform = get_global_transform().affine_inverse(); // undo global space + if (margin_drawing_enabled) { + Color margin_drawing_color(0, 1, 1, 0.63); + float margin_drawing_width = 1; + if (is_current()) { + margin_drawing_width = 3; + margin_drawing_color.a = 0.83; + } - for (int i = 0; i < 4; i++) { - draw_line(inv_transform.xform(screen_endpoints[i]), inv_transform.xform(screen_endpoints[(i + 1) % 4]), area_axis_color, area_axis_width); + Transform2D inv_camera_transform = get_camera_transform().affine_inverse(); + Size2 screen_size = get_viewport_rect().size; + + Vector2 margin_endpoints[4] = { + inv_camera_transform.xform(Vector2((screen_size.width / 2) - ((screen_size.width / 2) * drag_margin[MARGIN_LEFT]), (screen_size.height / 2) - ((screen_size.height / 2) * drag_margin[MARGIN_TOP]))), + inv_camera_transform.xform(Vector2((screen_size.width / 2) + ((screen_size.width / 2) * drag_margin[MARGIN_RIGHT]), (screen_size.height / 2) - ((screen_size.height / 2) * drag_margin[MARGIN_TOP]))), + inv_camera_transform.xform(Vector2((screen_size.width / 2) + ((screen_size.width / 2) * drag_margin[MARGIN_RIGHT]), (screen_size.height / 2) + ((screen_size.height / 2) * drag_margin[MARGIN_BOTTOM]))), + inv_camera_transform.xform(Vector2((screen_size.width / 2) - ((screen_size.width / 2) * drag_margin[MARGIN_LEFT]), (screen_size.height / 2) + ((screen_size.height / 2) * drag_margin[MARGIN_BOTTOM]))) + }; + + Transform2D inv_transform = get_global_transform().affine_inverse(); // undo global space + + for (int i = 0; i < 4; i++) { + draw_line(inv_transform.xform(margin_endpoints[i]), inv_transform.xform(margin_endpoints[(i + 1) % 4]), margin_drawing_color, margin_drawing_width); + } } } break; @@ -329,7 +379,6 @@ void Camera2D::_make_current(Object *p_which) { if (p_which == this) { current = true; - _update_scroll(); } else { current = false; } @@ -341,6 +390,7 @@ void Camera2D::_set_current(bool p_current) { make_current(); current = p_current; + update(); } bool Camera2D::is_current() const { @@ -369,6 +419,7 @@ void Camera2D::set_limit(Margin p_margin, int p_limit) { ERR_FAIL_INDEX(p_margin, 4); limit[p_margin] = p_limit; + update(); } int Camera2D::get_limit(Margin p_margin) const { @@ -392,6 +443,7 @@ void Camera2D::set_drag_margin(Margin p_margin, float p_drag_margin) { ERR_FAIL_INDEX(p_margin, 4); drag_margin[p_margin] = p_drag_margin; + update(); } float Camera2D::get_drag_margin(Margin p_margin) const { @@ -500,11 +552,11 @@ float Camera2D::get_h_offset() const { return h_ofs; } -void Camera2D::_set_old_smoothing(float p_val) { +void Camera2D::_set_old_smoothing(float p_enable) { //compatibility - if (p_val > 0) { + if (p_enable > 0) { smoothing_enabled = true; - set_follow_smoothing(p_val); + set_follow_smoothing(p_enable); } } @@ -528,7 +580,7 @@ void Camera2D::set_custom_viewport(Node *p_viewport) { custom_viewport = p_viewport->cast_to<Viewport>(); if (custom_viewport) { - custom_viewport_id = custom_viewport->get_instance_ID(); + custom_viewport_id = custom_viewport->get_instance_id(); } else { custom_viewport_id = 0; } @@ -553,6 +605,33 @@ Node *Camera2D::get_custom_viewport() const { return custom_viewport; } +void Camera2D::set_screen_drawing_enabled(bool enable) { + screen_drawing_enabled = enable; + update(); +} + +bool Camera2D::is_screen_drawing_enabled() const { + return screen_drawing_enabled; +} + +void Camera2D::set_limit_drawing_enabled(bool enable) { + limit_drawing_enabled = enable; + update(); +} + +bool Camera2D::is_limit_drawing_enabled() const { + return limit_drawing_enabled; +} + +void Camera2D::set_margin_drawing_enabled(bool enable) { + margin_drawing_enabled = enable; + update(); +} + +bool Camera2D::is_margin_drawing_enabled() const { + return margin_drawing_enabled; +} + void Camera2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_offset", "offset"), &Camera2D::set_offset); @@ -600,8 +679,8 @@ void Camera2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_zoom", "zoom"), &Camera2D::set_zoom); ClassDB::bind_method(D_METHOD("get_zoom"), &Camera2D::get_zoom); - ClassDB::bind_method(D_METHOD("set_custom_viewport", "viewport:Viewport"), &Camera2D::set_custom_viewport); - ClassDB::bind_method(D_METHOD("get_custom_viewport:Viewport"), &Camera2D::get_custom_viewport); + ClassDB::bind_method(D_METHOD("set_custom_viewport", "viewport"), &Camera2D::set_custom_viewport); + ClassDB::bind_method(D_METHOD("get_custom_viewport"), &Camera2D::get_custom_viewport); ClassDB::bind_method(D_METHOD("set_follow_smoothing", "follow_smoothing"), &Camera2D::set_follow_smoothing); ClassDB::bind_method(D_METHOD("get_follow_smoothing"), &Camera2D::get_follow_smoothing); @@ -615,6 +694,15 @@ void Camera2D::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_old_smoothing", "follow_smoothing"), &Camera2D::_set_old_smoothing); + ClassDB::bind_method(D_METHOD("set_screen_drawing_enabled", "screen_drawing_enabled"), &Camera2D::set_screen_drawing_enabled); + ClassDB::bind_method(D_METHOD("is_screen_drawing_enabled"), &Camera2D::is_screen_drawing_enabled); + + ClassDB::bind_method(D_METHOD("set_limit_drawing_enabled", "limit_drawing_enabled"), &Camera2D::set_limit_drawing_enabled); + ClassDB::bind_method(D_METHOD("is_limit_drawing_enabled"), &Camera2D::is_limit_drawing_enabled); + + ClassDB::bind_method(D_METHOD("set_margin_drawing_enabled", "margin_drawing_enabled"), &Camera2D::set_margin_drawing_enabled); + ClassDB::bind_method(D_METHOD("is_margin_drawing_enabled"), &Camera2D::is_margin_drawing_enabled); + ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset"); ADD_PROPERTY(PropertyInfo(Variant::INT, "anchor_mode", PROPERTY_HINT_ENUM, "Fixed TopLeft,Drag Center"), "set_anchor_mode", "get_anchor_mode"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rotating"), "set_rotating", "is_rotating"); @@ -642,6 +730,11 @@ void Camera2D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::REAL, "drag_margin_right", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drag_margin", "get_drag_margin", MARGIN_RIGHT); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "drag_margin_bottom", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drag_margin", "get_drag_margin", MARGIN_BOTTOM); + ADD_GROUP("Editor", "editor_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_draw_screen"), "set_screen_drawing_enabled", "is_screen_drawing_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_draw_limits"), "set_limit_drawing_enabled", "is_limit_drawing_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_draw_drag_margin"), "set_margin_drawing_enabled", "is_margin_drawing_enabled"); + BIND_CONSTANT(ANCHOR_MODE_DRAG_CENTER); BIND_CONSTANT(ANCHOR_MODE_FIXED_TOP_LEFT); } @@ -670,6 +763,10 @@ Camera2D::Camera2D() { smoothing = 5.0; zoom = Vector2(1, 1); + screen_drawing_enabled = true; + limit_drawing_enabled = false; + margin_drawing_enabled = false; + h_drag_enabled = true; v_drag_enabled = true; h_ofs = 0; diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h index 44cdb5cd9..8d9e76be8 100644 --- a/scene/2d/camera_2d.h +++ b/scene/2d/camera_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -78,6 +79,10 @@ protected: void _set_old_smoothing(float p_enable); + bool screen_drawing_enabled; + bool limit_drawing_enabled; + bool margin_drawing_enabled; + protected: virtual Transform2D get_camera_transform(); void _notification(int p_what); @@ -137,6 +142,15 @@ public: void reset_smoothing(); void align(); + void set_screen_drawing_enabled(bool enable); + bool is_screen_drawing_enabled() const; + + void set_limit_drawing_enabled(bool enable); + bool is_limit_drawing_enabled() const; + + void set_margin_drawing_enabled(bool enable); + bool is_margin_drawing_enabled() const; + Camera2D(); }; diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index b52dd8d66..3d0b5047a 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -27,6 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "canvas_item.h" +#include "core/method_bind_ext.gen.inc" #include "message_queue.h" #include "os/input.h" #include "scene/main/canvas_layer.h" @@ -37,122 +39,194 @@ #include "scene/scene_string_names.h" #include "servers/visual_server.h" -bool CanvasItemMaterial::_set(const StringName &p_name, const Variant &p_value) { +Mutex *CanvasItemMaterial::material_mutex = NULL; +SelfList<CanvasItemMaterial>::List CanvasItemMaterial::dirty_materials; +Map<CanvasItemMaterial::MaterialKey, CanvasItemMaterial::ShaderData> CanvasItemMaterial::shader_map; - if (p_name == SceneStringNames::get_singleton()->shader_shader) { - set_shader(p_value); - return true; - } else { +void CanvasItemMaterial::init_shaders() { - if (shader.is_valid()) { +#ifndef NO_THREADS + material_mutex = Mutex::create(); +#endif +} - StringName pr = shader->remap_param(p_name); - if (!pr) { - String n = p_name; - if (n.find("param/") == 0) { //backwards compatibility - pr = n.substr(6, n.length()); - } - } - if (pr) { - VisualServer::get_singleton()->material_set_param(_get_material(), pr, p_value); - return true; - } - } - } +void CanvasItemMaterial::finish_shaders() { - return false; +#ifndef NO_THREADS + memdelete(material_mutex); +#endif } -bool CanvasItemMaterial::_get(const StringName &p_name, Variant &r_ret) const { +void CanvasItemMaterial::_update_shader() { - if (p_name == SceneStringNames::get_singleton()->shader_shader) { + dirty_materials.remove(&element); - r_ret = get_shader(); - return true; + MaterialKey mk = _compute_key(); + if (mk.key == current_key.key) + return; //no update required in the end - } else { + if (shader_map.has(current_key)) { + shader_map[current_key].users--; + if (shader_map[current_key].users == 0) { + //deallocate shader, as it's no longer in use + VS::get_singleton()->free(shader_map[current_key].shader); + shader_map.erase(current_key); + } + } - if (shader.is_valid()) { + current_key = mk; - StringName pr = shader->remap_param(p_name); - if (pr) { - r_ret = VisualServer::get_singleton()->material_get_param(_get_material(), pr); - return true; - } - } + if (shader_map.has(mk)) { + + VS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader); + shader_map[mk].users++; + return; } - return false; + //must create a shader! + + String code = "shader_type canvas_item;\nrender_mode "; + switch (blend_mode) { + case BLEND_MODE_MIX: code += "blend_mix"; break; + case BLEND_MODE_ADD: code += "blend_add"; break; + case BLEND_MODE_SUB: code += "blend_sub"; break; + case BLEND_MODE_MUL: code += "blend_mul"; break; + case BLEND_MODE_PREMULT_ALPHA: code += "blend_premul_alpha"; break; + } + + switch (light_mode) { + case LIGHT_MODE_NORMAL: break; + case LIGHT_MODE_UNSHADED: code += ",unshaded"; break; + case LIGHT_MODE_LIGHT_ONLY: code += ",light_only"; break; + } + code += ";\n"; //thats it. + + ShaderData shader_data; + shader_data.shader = VS::get_singleton()->shader_create(); + shader_data.users = 1; + + VS::get_singleton()->shader_set_code(shader_data.shader, code); + + shader_map[mk] = shader_data; + + VS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); } -void CanvasItemMaterial::_get_property_list(List<PropertyInfo> *p_list) const { +void CanvasItemMaterial::flush_changes() { - p_list->push_back(PropertyInfo(Variant::OBJECT, "shader/shader", PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemShader,CanvasItemShaderGraph")); + if (material_mutex) + material_mutex->lock(); - if (!shader.is_null()) { + while (dirty_materials.first()) { - shader->get_param_list(p_list); + dirty_materials.first()->self()->_update_shader(); } + + if (material_mutex) + material_mutex->unlock(); } -void CanvasItemMaterial::set_shader(const Ref<Shader> &p_shader) { +void CanvasItemMaterial::_queue_shader_change() { - ERR_FAIL_COND(p_shader.is_valid() && p_shader->get_mode() != Shader::MODE_CANVAS_ITEM); + if (material_mutex) + material_mutex->lock(); - shader = p_shader; + if (!element.in_list()) { + dirty_materials.add(&element); + } - RID rid; - if (shader.is_valid()) - rid = shader->get_rid(); + if (material_mutex) + material_mutex->unlock(); +} + +bool CanvasItemMaterial::_is_shader_dirty() const { + + bool dirty = false; + + if (material_mutex) + material_mutex->lock(); + + dirty = element.in_list(); - VS::get_singleton()->material_set_shader(_get_material(), rid); - _change_notify(); //properties for shader exposed - emit_changed(); + if (material_mutex) + material_mutex->unlock(); + + return dirty; } +void CanvasItemMaterial::set_blend_mode(BlendMode p_blend_mode) { -Ref<Shader> CanvasItemMaterial::get_shader() const { + blend_mode = p_blend_mode; + _queue_shader_change(); +} - return shader; +CanvasItemMaterial::BlendMode CanvasItemMaterial::get_blend_mode() const { + return blend_mode; } -void CanvasItemMaterial::set_shader_param(const StringName &p_param, const Variant &p_value) { +void CanvasItemMaterial::set_light_mode(LightMode p_light_mode) { - VS::get_singleton()->material_set_param(_get_material(), p_param, p_value); + light_mode = p_light_mode; + _queue_shader_change(); } -Variant CanvasItemMaterial::get_shader_param(const StringName &p_param) const { +CanvasItemMaterial::LightMode CanvasItemMaterial::get_light_mode() const { - return VS::get_singleton()->material_get_param(_get_material(), p_param); + return light_mode; +} + +void CanvasItemMaterial::_validate_property(PropertyInfo &property) const { } void CanvasItemMaterial::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_shader", "shader:Shader"), &CanvasItemMaterial::set_shader); - ClassDB::bind_method(D_METHOD("get_shader:Shader"), &CanvasItemMaterial::get_shader); - ClassDB::bind_method(D_METHOD("set_shader_param", "param", "value"), &CanvasItemMaterial::set_shader_param); - ClassDB::bind_method(D_METHOD("get_shader_param", "param"), &CanvasItemMaterial::get_shader_param); -} + ClassDB::bind_method(D_METHOD("set_blend_mode", "blend_mode"), &CanvasItemMaterial::set_blend_mode); + ClassDB::bind_method(D_METHOD("get_blend_mode"), &CanvasItemMaterial::get_blend_mode); -void CanvasItemMaterial::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { + ClassDB::bind_method(D_METHOD("set_light_mode", "light_mode"), &CanvasItemMaterial::set_light_mode); + ClassDB::bind_method(D_METHOD("get_light_mode"), &CanvasItemMaterial::get_light_mode); - String f = p_function.operator String(); - if ((f == "get_shader_param" || f == "set_shader_param") && p_idx == 0) { + ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul,Premult Alpha"), "set_blend_mode", "get_blend_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "light_mode", PROPERTY_HINT_ENUM, "Normal,Unshaded,Light Only"), "set_light_mode", "get_light_mode"); - if (shader.is_valid()) { - List<PropertyInfo> pl; - shader->get_param_list(&pl); - for (List<PropertyInfo>::Element *E = pl.front(); E; E = E->next()) { - r_options->push_back("\"" + E->get().name.replace_first("shader_param/", "") + "\""); - } - } - } - Resource::get_argument_options(p_function, p_idx, r_options); + BIND_CONSTANT(BLEND_MODE_MIX); + BIND_CONSTANT(BLEND_MODE_ADD); + BIND_CONSTANT(BLEND_MODE_SUB); + BIND_CONSTANT(BLEND_MODE_MUL); + BIND_CONSTANT(BLEND_MODE_PREMULT_ALPHA); + BIND_CONSTANT(LIGHT_MODE_NORMAL); + BIND_CONSTANT(LIGHT_MODE_UNSHADED); + BIND_CONSTANT(LIGHT_MODE_LIGHT_ONLY); } -CanvasItemMaterial::CanvasItemMaterial() { +CanvasItemMaterial::CanvasItemMaterial() + : element(this) { + + blend_mode = BLEND_MODE_MIX; + light_mode = LIGHT_MODE_NORMAL; + + current_key.key = 0; + current_key.invalid_key = 1; + _queue_shader_change(); } CanvasItemMaterial::~CanvasItemMaterial() { + + if (material_mutex) + material_mutex->lock(); + + if (shader_map.has(current_key)) { + shader_map[current_key].users--; + if (shader_map[current_key].users == 0) { + //deallocate shader, as it's no longer in use + VS::get_singleton()->free(shader_map[current_key].shader); + shader_map.erase(current_key); + } + + VS::get_singleton()->material_set_shader(_get_material(), RID()); + } + + if (material_mutex) + material_mutex->unlock(); } /////////////////////////////////////////////////////////////////// @@ -206,7 +280,7 @@ void CanvasItem::show() { return; _propagate_visibility_changed(true); - _change_notify("visibility/visible"); + _change_notify("visible"); } void CanvasItem::hide() { @@ -221,7 +295,7 @@ void CanvasItem::hide() { return; _propagate_visibility_changed(false); - _change_notify("visibility/visible"); + _change_notify("visible"); } Variant CanvasItem::edit_get_state() const { @@ -293,7 +367,9 @@ Transform2D CanvasItem::get_global_transform_with_canvas() const { } Transform2D CanvasItem::get_global_transform() const { - +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_V(!is_inside_tree(), get_transform()); +#endif if (global_invalid) { const CanvasItem *pi = get_parent_item(); @@ -533,14 +609,43 @@ void CanvasItem::draw_line(const Point2 &p_from, const Point2 &p_to, const Color VisualServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width, p_antialiased); } -void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color) { +void CanvasItem::draw_polyline(const Vector<Point2> &p_points, const Color &p_color, float p_width, bool p_antialiased) { + + if (!drawing) { + ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); + ERR_FAIL(); + } + + Vector<Color> colors; + colors.push_back(p_color); + VisualServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, colors, p_width, p_antialiased); +} + +void CanvasItem::draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) { if (!drawing) { ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL(); } - VisualServer::get_singleton()->canvas_item_add_rect(canvas_item, p_rect, p_color); + VisualServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, p_colors, p_width, p_antialiased); +} +void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled) { + + if (!drawing) { + ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); + ERR_FAIL(); + } + + if (p_filled) { + + VisualServer::get_singleton()->canvas_item_add_rect(canvas_item, p_rect, p_color); + } else { + VisualServer::get_singleton()->canvas_item_add_line(canvas_item, p_rect.position, p_rect.position + Size2(p_rect.size.width, 0), p_color); + VisualServer::get_singleton()->canvas_item_add_line(canvas_item, p_rect.position, p_rect.position + Size2(0, p_rect.size.height), p_color); + VisualServer::get_singleton()->canvas_item_add_line(canvas_item, p_rect.position + Point2(0, p_rect.size.height), p_rect.position + p_rect.size, p_color); + VisualServer::get_singleton()->canvas_item_add_line(canvas_item, p_rect.position + Point2(p_rect.size.width, 0), p_rect.position + p_rect.size, p_color); + } } void CanvasItem::draw_circle(const Point2 &p_pos, float p_radius, const Color &p_color) { @@ -553,7 +658,7 @@ void CanvasItem::draw_circle(const Point2 &p_pos, float p_radius, const Color &p VisualServer::get_singleton()->canvas_item_add_circle(canvas_item, p_pos, p_radius, p_color); } -void CanvasItem::draw_texture(const Ref<Texture> &p_texture, const Point2 &p_pos, const Color &p_modulate) { +void CanvasItem::draw_texture(const Ref<Texture> &p_texture, const Point2 &p_pos, const Color &p_modulate, const Ref<Texture> &p_normal_map) { if (!drawing) { ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); @@ -565,7 +670,7 @@ void CanvasItem::draw_texture(const Ref<Texture> &p_texture, const Point2 &p_pos p_texture->draw(canvas_item, p_pos, p_modulate); } -void CanvasItem::draw_texture_rect(const Ref<Texture> &p_texture, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) { +void CanvasItem::draw_texture_rect(const Ref<Texture> &p_texture, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) { if (!drawing) { ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); @@ -573,16 +678,16 @@ void CanvasItem::draw_texture_rect(const Ref<Texture> &p_texture, const Rect2 &p } ERR_FAIL_COND(p_texture.is_null()); - p_texture->draw_rect(canvas_item, p_rect, p_tile, p_modulate, p_transpose); + p_texture->draw_rect(canvas_item, p_rect, p_tile, p_modulate, p_transpose, p_normal_map); } -void CanvasItem::draw_texture_rect_region(const Ref<Texture> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose) { +void CanvasItem::draw_texture_rect_region(const Ref<Texture> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map, bool p_clip_uv) { if (!drawing) { ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL(); } ERR_FAIL_COND(p_texture.is_null()); - p_texture->draw_rect_region(canvas_item, p_rect, p_src_rect, p_modulate, p_transpose); + p_texture->draw_rect_region(canvas_item, p_rect, p_src_rect, p_modulate, p_transpose, p_normal_map, p_clip_uv); } void CanvasItem::draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p_rect) { @@ -595,7 +700,7 @@ void CanvasItem::draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p p_style_box->draw(canvas_item, p_rect); } -void CanvasItem::draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture> p_texture, float p_width) { +void CanvasItem::draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture> p_texture, float p_width, const Ref<Texture> &p_normal_map) { if (!drawing) { ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); @@ -603,8 +708,9 @@ void CanvasItem::draw_primitive(const Vector<Point2> &p_points, const Vector<Col } RID rid = p_texture.is_valid() ? p_texture->get_rid() : RID(); + RID rid_normal = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_primitive(canvas_item, p_points, p_colors, p_uvs, rid, p_width); + VisualServer::get_singleton()->canvas_item_add_primitive(canvas_item, p_points, p_colors, p_uvs, rid, p_width, rid_normal); } void CanvasItem::draw_set_transform(const Point2 &p_offset, float p_rot, const Size2 &p_scale) { @@ -628,7 +734,7 @@ void CanvasItem::draw_set_transform_matrix(const Transform2D &p_matrix) { VisualServer::get_singleton()->canvas_item_add_set_transform(canvas_item, p_matrix); } -void CanvasItem::draw_polygon(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture> p_texture) { +void CanvasItem::draw_polygon(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture> p_texture, const Ref<Texture> &p_normal_map) { if (!drawing) { ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); @@ -636,11 +742,12 @@ void CanvasItem::draw_polygon(const Vector<Point2> &p_points, const Vector<Color } RID rid = p_texture.is_valid() ? p_texture->get_rid() : RID(); + RID rid_normal = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_polygon(canvas_item, p_points, p_colors, p_uvs, rid); + VisualServer::get_singleton()->canvas_item_add_polygon(canvas_item, p_points, p_colors, p_uvs, rid, rid_normal); } -void CanvasItem::draw_colored_polygon(const Vector<Point2> &p_points, const Color &p_color, const Vector<Point2> &p_uvs, Ref<Texture> p_texture) { +void CanvasItem::draw_colored_polygon(const Vector<Point2> &p_points, const Color &p_color, const Vector<Point2> &p_uvs, Ref<Texture> p_texture, const Ref<Texture> &p_normal_map) { if (!drawing) { ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); @@ -650,8 +757,9 @@ void CanvasItem::draw_colored_polygon(const Vector<Point2> &p_points, const Colo Vector<Color> colors; colors.push_back(p_color); RID rid = p_texture.is_valid() ? p_texture->get_rid() : RID(); + RID rid_normal = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_polygon(canvas_item, p_points, colors, p_uvs, rid); + VisualServer::get_singleton()->canvas_item_add_polygon(canvas_item, p_points, colors, p_uvs, rid, rid_normal); } void CanvasItem::draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, const Color &p_modulate, int p_clip_w) { @@ -680,8 +788,9 @@ float CanvasItem::draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const void CanvasItem::_notify_transform(CanvasItem *p_node) { - if (/*p_node->xform_change.in_list() &&*/ p_node->global_invalid) + if (/*p_node->xform_change.in_list() &&*/ p_node->global_invalid) { return; //nothing to do + } p_node->global_invalid = true; @@ -770,7 +879,7 @@ bool CanvasItem::is_draw_behind_parent_enabled() const { return behind; } -void CanvasItem::set_material(const Ref<CanvasItemMaterial> &p_material) { +void CanvasItem::set_material(const Ref<Material> &p_material) { material = p_material; RID rid; @@ -791,7 +900,7 @@ bool CanvasItem::get_use_parent_material() const { return use_parent_material; } -Ref<CanvasItemMaterial> CanvasItem::get_material() const { +Ref<Material> CanvasItem::get_material() const { return material; } @@ -800,30 +909,28 @@ Vector2 CanvasItem::make_canvas_pos_local(const Vector2 &screen_point) const { ERR_FAIL_COND_V(!is_inside_tree(), screen_point); - Transform2D local_matrix = (get_canvas_transform() * - get_global_transform()) - .affine_inverse(); + Transform2D local_matrix = (get_canvas_transform() * get_global_transform()).affine_inverse(); return local_matrix.xform(screen_point); } -InputEvent CanvasItem::make_input_local(const InputEvent &p_event) const { +Ref<InputEvent> CanvasItem::make_input_local(const Ref<InputEvent> &p_event) const { ERR_FAIL_COND_V(!is_inside_tree(), p_event); - return p_event.xform_by((get_canvas_transform() * get_global_transform()).affine_inverse()); + return p_event->xformed_by((get_canvas_transform() * get_global_transform()).affine_inverse()); } -Vector2 CanvasItem::get_global_mouse_pos() const { +Vector2 CanvasItem::get_global_mouse_position() const { ERR_FAIL_COND_V(!get_viewport(), Vector2()); - return get_canvas_transform().affine_inverse().xform(get_viewport()->get_mouse_pos()); + return get_canvas_transform().affine_inverse().xform(get_viewport()->get_mouse_position()); } Vector2 CanvasItem::get_local_mouse_pos() const { ERR_FAIL_COND_V(!get_viewport(), Vector2()); - return get_global_transform().affine_inverse().xform(get_global_mouse_pos()); + return get_global_transform().affine_inverse().xform(get_global_mouse_position()); } void CanvasItem::_bind_methods() { @@ -832,7 +939,7 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("_update_callback"), &CanvasItem::_update_callback); ClassDB::bind_method(D_METHOD("edit_set_state", "state"), &CanvasItem::edit_set_state); - ClassDB::bind_method(D_METHOD("edit_get_state:Variant"), &CanvasItem::edit_get_state); + ClassDB::bind_method(D_METHOD("edit_get_state"), &CanvasItem::edit_get_state); ClassDB::bind_method(D_METHOD("edit_set_rect", "rect"), &CanvasItem::edit_set_rect); ClassDB::bind_method(D_METHOD("edit_rotate", "degrees"), &CanvasItem::edit_rotate); @@ -842,7 +949,7 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("get_canvas_item"), &CanvasItem::get_canvas_item); - ClassDB::bind_method(D_METHOD("set_visible"), &CanvasItem::set_visible); + ClassDB::bind_method(D_METHOD("set_visible", "visible"), &CanvasItem::set_visible); ClassDB::bind_method(D_METHOD("is_visible"), &CanvasItem::is_visible); ClassDB::bind_method(D_METHOD("is_visible_in_tree"), &CanvasItem::is_visible_in_tree); ClassDB::bind_method(D_METHOD("show"), &CanvasItem::show); @@ -869,17 +976,19 @@ void CanvasItem::_bind_methods() { //ClassDB::bind_method(D_METHOD("get_transform"),&CanvasItem::get_transform); ClassDB::bind_method(D_METHOD("draw_line", "from", "to", "color", "width", "antialiased"), &CanvasItem::draw_line, DEFVAL(1.0), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("draw_rect", "rect", "color"), &CanvasItem::draw_rect); + ClassDB::bind_method(D_METHOD("draw_polyline", "points", "color", "width", "antialiased"), &CanvasItem::draw_polyline, DEFVAL(1.0), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("draw_polyline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_polyline_colors, DEFVAL(1.0), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("draw_rect", "rect", "color", "filled"), &CanvasItem::draw_rect, DEFVAL(true)); ClassDB::bind_method(D_METHOD("draw_circle", "pos", "radius", "color"), &CanvasItem::draw_circle); - ClassDB::bind_method(D_METHOD("draw_texture", "texture:Texture", "pos", "modulate"), &CanvasItem::draw_texture, DEFVAL(Color(1, 1, 1, 1))); - ClassDB::bind_method(D_METHOD("draw_texture_rect", "texture:Texture", "rect", "tile", "modulate", "transpose"), &CanvasItem::draw_texture_rect, DEFVAL(Color(1, 1, 1)), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("draw_texture_rect_region", "texture:Texture", "rect", "src_rect", "modulate", "transpose"), &CanvasItem::draw_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("draw_style_box", "style_box:StyleBox", "rect"), &CanvasItem::draw_style_box); - ClassDB::bind_method(D_METHOD("draw_primitive", "points", "colors", "uvs", "texture:Texture", "width"), &CanvasItem::draw_primitive, DEFVAL(Variant()), DEFVAL(1.0)); - ClassDB::bind_method(D_METHOD("draw_polygon", "points", "colors", "uvs", "texture:Texture"), &CanvasItem::draw_polygon, DEFVAL(PoolVector2Array()), DEFVAL(Variant())); - ClassDB::bind_method(D_METHOD("draw_colored_polygon", "points", "color", "uvs", "texture:Texture"), &CanvasItem::draw_colored_polygon, DEFVAL(PoolVector2Array()), DEFVAL(Variant())); - ClassDB::bind_method(D_METHOD("draw_string", "font:Font", "pos", "text", "modulate", "clip_w"), &CanvasItem::draw_string, DEFVAL(Color(1, 1, 1)), DEFVAL(-1)); - ClassDB::bind_method(D_METHOD("draw_char", "font:Font", "pos", "char", "next", "modulate"), &CanvasItem::draw_char, DEFVAL(Color(1, 1, 1))); + ClassDB::bind_method(D_METHOD("draw_texture", "texture", "pos", "modulate", "normal_map"), &CanvasItem::draw_texture, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("draw_texture_rect", "texture", "rect", "tile", "modulate", "transpose", "normal_map"), &CanvasItem::draw_texture_rect, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("draw_texture_rect_region", "texture", "rect", "src_rect", "modulate", "transpose", "normal_map", "clip_uv"), &CanvasItem::draw_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("draw_style_box", "style_box", "rect"), &CanvasItem::draw_style_box); + ClassDB::bind_method(D_METHOD("draw_primitive", "points", "colors", "uvs", "texture", "width", "normal_map"), &CanvasItem::draw_primitive, DEFVAL(Variant()), DEFVAL(1.0), DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("draw_polygon", "points", "colors", "uvs", "texture", "normal_map"), &CanvasItem::draw_polygon, DEFVAL(PoolVector2Array()), DEFVAL(Variant()), DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("draw_colored_polygon", "points", "color", "uvs", "texture", "normal_map"), &CanvasItem::draw_colored_polygon, DEFVAL(PoolVector2Array()), DEFVAL(Variant()), DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("draw_string", "font", "pos", "text", "modulate", "clip_w"), &CanvasItem::draw_string, DEFVAL(Color(1, 1, 1)), DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("draw_char", "font", "pos", "char", "next", "modulate"), &CanvasItem::draw_char, DEFVAL(Color(1, 1, 1))); ClassDB::bind_method(D_METHOD("draw_set_transform", "pos", "rot", "scale"), &CanvasItem::draw_set_transform); ClassDB::bind_method(D_METHOD("draw_set_transform_matrix", "xform"), &CanvasItem::draw_set_transform_matrix); @@ -890,13 +999,13 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("get_viewport_rect"), &CanvasItem::get_viewport_rect); ClassDB::bind_method(D_METHOD("get_canvas_transform"), &CanvasItem::get_canvas_transform); ClassDB::bind_method(D_METHOD("get_local_mouse_pos"), &CanvasItem::get_local_mouse_pos); - ClassDB::bind_method(D_METHOD("get_global_mouse_pos"), &CanvasItem::get_global_mouse_pos); + ClassDB::bind_method(D_METHOD("get_global_mouse_position"), &CanvasItem::get_global_mouse_position); ClassDB::bind_method(D_METHOD("get_canvas"), &CanvasItem::get_canvas); ClassDB::bind_method(D_METHOD("get_world_2d"), &CanvasItem::get_world_2d); //ClassDB::bind_method(D_METHOD("get_viewport"),&CanvasItem::get_viewport); - ClassDB::bind_method(D_METHOD("set_material", "material:CanvasItemMaterial"), &CanvasItem::set_material); - ClassDB::bind_method(D_METHOD("get_material:CanvasItemMaterial"), &CanvasItem::get_material); + ClassDB::bind_method(D_METHOD("set_material", "material"), &CanvasItem::set_material); + ClassDB::bind_method(D_METHOD("get_material"), &CanvasItem::get_material); ClassDB::bind_method(D_METHOD("set_use_parent_material", "enable"), &CanvasItem::set_use_parent_material); ClassDB::bind_method(D_METHOD("get_use_parent_material"), &CanvasItem::get_use_parent_material); @@ -922,7 +1031,7 @@ void CanvasItem::_bind_methods() { ADD_PROPERTYNO(PropertyInfo(Variant::INT, "light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_light_mask", "get_light_mask"); ADD_GROUP("Material", ""); - ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial"), "set_material", "get_material"); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,CanvasItemMaterial"), "set_material", "get_material"); ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "use_parent_material"), "set_use_parent_material", "get_use_parent_material"); //exporting these two things doesn't really make much sense i think //ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transform/toplevel"), "set_as_toplevel","is_set_as_toplevel") ; @@ -984,7 +1093,15 @@ bool CanvasItem::is_local_transform_notification_enabled() const { } void CanvasItem::set_notify_transform(bool p_enable) { + if (notify_transform == p_enable) + return; + notify_transform = p_enable; + + if (notify_transform && is_inside_tree()) { + //this ensures that invalid globals get resolved, so notifications can be received + get_global_transform(); + } } bool CanvasItem::is_transform_notification_enabled() const { diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index a188ce495..660ddcf93 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +31,7 @@ #define CANVAS_ITEM_H #include "scene/main/node.h" -#include "scene/main/scene_main_loop.h" +#include "scene/main/scene_tree.h" #include "scene/resources/material.h" #include "scene/resources/shader.h" #include "scene/resources/texture.h" @@ -43,36 +44,90 @@ class StyleBox; class CanvasItemMaterial : public Material { - GDCLASS(CanvasItemMaterial, Material); - Ref<Shader> shader; + GDCLASS(CanvasItemMaterial, Material) public: - /*enum ShadingMode { - SHADING_NORMAL, - SHADING_UNSHADED, - SHADING_ONLY_LIGHT, - };*/ + enum BlendMode { + BLEND_MODE_MIX, + BLEND_MODE_ADD, + BLEND_MODE_SUB, + BLEND_MODE_MUL, + BLEND_MODE_PREMULT_ALPHA + }; -protected: - bool _set(const StringName &p_name, const Variant &p_value); - bool _get(const StringName &p_name, Variant &r_ret) const; - void _get_property_list(List<PropertyInfo> *p_list) const; + enum LightMode { + LIGHT_MODE_NORMAL, + LIGHT_MODE_UNSHADED, + LIGHT_MODE_LIGHT_ONLY + }; - static void _bind_methods(); +private: + union MaterialKey { + + struct { + uint32_t blend_mode : 4; + uint32_t light_mode : 4; + uint32_t invalid_key : 1; + }; + + uint32_t key; + + bool operator<(const MaterialKey &p_key) const { + return key < p_key.key; + } + }; - void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const; + struct ShaderData { + RID shader; + int users; + }; + + static Map<MaterialKey, ShaderData> shader_map; + + MaterialKey current_key; + + _FORCE_INLINE_ MaterialKey _compute_key() const { + + MaterialKey mk; + mk.key = 0; + mk.blend_mode = blend_mode; + mk.light_mode = light_mode; + return mk; + } + + static Mutex *material_mutex; + static SelfList<CanvasItemMaterial>::List dirty_materials; + SelfList<CanvasItemMaterial> element; + + void _update_shader(); + _FORCE_INLINE_ void _queue_shader_change(); + _FORCE_INLINE_ bool _is_shader_dirty() const; + + BlendMode blend_mode; + LightMode light_mode; + +protected: + static void _bind_methods(); + void _validate_property(PropertyInfo &property) const; public: - void set_shader(const Ref<Shader> &p_shader); - Ref<Shader> get_shader() const; + void set_blend_mode(BlendMode p_blend_mode); + BlendMode get_blend_mode() const; + + void set_light_mode(LightMode p_light_mode); + LightMode get_light_mode() const; - void set_shader_param(const StringName &p_param, const Variant &p_value); - Variant get_shader_param(const StringName &p_param) const; + static void init_shaders(); + static void finish_shaders(); + static void flush_changes(); CanvasItemMaterial(); - ~CanvasItemMaterial(); + virtual ~CanvasItemMaterial(); }; +VARIANT_ENUM_CAST(CanvasItemMaterial::BlendMode) +VARIANT_ENUM_CAST(CanvasItemMaterial::LightMode) + class CanvasItem : public Node { GDCLASS(CanvasItem, Node); @@ -114,7 +169,7 @@ private: bool notify_local_transform; bool notify_transform; - Ref<CanvasItemMaterial> material; + Ref<Material> material; mutable Transform2D global_transform; mutable bool global_invalid; @@ -187,15 +242,17 @@ public: /* DRAWING API */ void draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0, bool p_antialiased = false); - void draw_rect(const Rect2 &p_rect, const Color &p_color); + void draw_polyline(const Vector<Point2> &p_points, const Color &p_color, float p_width = 1.0, bool p_antialiased = false); + void draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false); + void draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled = true); void draw_circle(const Point2 &p_pos, float p_radius, const Color &p_color); - void draw_texture(const Ref<Texture> &p_texture, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1, 1)); - void draw_texture_rect(const Ref<Texture> &p_texture, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false); - void draw_texture_rect_region(const Ref<Texture> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false); + void draw_texture(const Ref<Texture> &p_texture, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1, 1), const Ref<Texture> &p_normal_map = Ref<Texture>()); + void draw_texture_rect(const Ref<Texture> &p_texture, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()); + void draw_texture_rect_region(const Ref<Texture> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = true); void draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p_rect); - void draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture> p_texture = Ref<Texture>(), float p_width = 1); - void draw_polygon(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture> p_texture = Ref<Texture>()); - void draw_colored_polygon(const Vector<Point2> &p_points, const Color &p_color, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture> p_texture = Ref<Texture>()); + void draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture> p_texture = Ref<Texture>(), float p_width = 1, const Ref<Texture> &p_normal_map = Ref<Texture>()); + void draw_polygon(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture> p_texture = Ref<Texture>(), const Ref<Texture> &p_normal_map = Ref<Texture>()); + void draw_colored_polygon(const Vector<Point2> &p_points, const Color &p_color, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture> p_texture = Ref<Texture>(), const Ref<Texture> &p_normal_map = Ref<Texture>()); void draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, const Color &p_modulate = Color(1, 1, 1), int p_clip_w = -1); float draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, const String &p_next = "", const Color &p_modulate = Color(1, 1, 1)); @@ -234,16 +291,16 @@ public: RID get_canvas() const; Ref<World2D> get_world_2d() const; - void set_material(const Ref<CanvasItemMaterial> &p_material); - Ref<CanvasItemMaterial> get_material() const; + void set_material(const Ref<Material> &p_material); + Ref<Material> get_material() const; void set_use_parent_material(bool p_use_parent_material); bool get_use_parent_material() const; - InputEvent make_input_local(const InputEvent &pevent) const; + Ref<InputEvent> make_input_local(const Ref<InputEvent> &p_event) const; Vector2 make_canvas_pos_local(const Vector2 &screen_point) const; - Vector2 get_global_mouse_pos() const; + Vector2 get_global_mouse_position() const; Vector2 get_local_mouse_pos() const; void set_notify_local_transform(bool p_enable); diff --git a/scene/2d/canvas_modulate.cpp b/scene/2d/canvas_modulate.cpp index a0e3061c8..a132c5e18 100644 --- a/scene/2d/canvas_modulate.cpp +++ b/scene/2d/canvas_modulate.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/canvas_modulate.h b/scene/2d/canvas_modulate.h index 8e62b5ccb..37d9d47ba 100644 --- a/scene/2d/canvas_modulate.h +++ b/scene/2d/canvas_modulate.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp index 1242599d4..d3bb5a8d4 100644 --- a/scene/2d/collision_object_2d.cpp +++ b/scene/2d/collision_object_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,18 +31,6 @@ #include "scene/scene_string_names.h" #include "servers/physics_2d_server.h" -void CollisionObject2D::_update_shapes_from_children() { - - shapes.clear(); - for (int i = 0; i < get_child_count(); i++) { - - Node *n = get_child(i); - n->call("_add_to_collision_object", this); - } - - _update_shapes(); -} - void CollisionObject2D::_notification(int p_what) { switch (p_what) { @@ -87,82 +76,207 @@ void CollisionObject2D::_notification(int p_what) { } } -void CollisionObject2D::_update_shapes() { +uint32_t CollisionObject2D::create_shape_owner(Object *p_owner) { - if (!rid.is_valid()) - return; + ShapeData sd; + uint32_t id; + + if (shapes.size() == 0) { + id = 1; + } else { + id = shapes.back()->key() + 1; + } + + sd.owner = p_owner; + + shapes[id] = sd; + + return id; +} + +void CollisionObject2D::remove_shape_owner(uint32_t owner) { + + ERR_FAIL_COND(!shapes.has(owner)); + + shape_owner_clear_shapes(owner); + + shapes.erase(owner); +} + +void CollisionObject2D::shape_owner_set_disabled(uint32_t p_owner, bool p_disabled) { + ERR_FAIL_COND(!shapes.has(p_owner)); + + ShapeData &sd = shapes[p_owner]; + sd.disabled = p_disabled; + for (int i = 0; i < sd.shapes.size(); i++) { + if (area) { + Physics2DServer::get_singleton()->area_set_shape_disabled(rid, sd.shapes[i].index, p_disabled); + } else { + Physics2DServer::get_singleton()->body_set_shape_disabled(rid, sd.shapes[i].index, p_disabled); + } + } +} + +bool CollisionObject2D::is_shape_owner_disabled(uint32_t p_owner) const { + + ERR_FAIL_COND_V(!shapes.has(p_owner), false); + + return shapes[p_owner].disabled; +} + +void CollisionObject2D::shape_owner_set_one_way_collision(uint32_t p_owner, bool p_enable) { if (area) - Physics2DServer::get_singleton()->area_clear_shapes(rid); - else - Physics2DServer::get_singleton()->body_clear_shapes(rid); + return; //not for areas - for (int i = 0; i < shapes.size(); i++) { + ERR_FAIL_COND(!shapes.has(p_owner)); - if (shapes[i].shape.is_null()) - continue; - if (area) - Physics2DServer::get_singleton()->area_add_shape(rid, shapes[i].shape->get_rid(), shapes[i].xform); - else { - Physics2DServer::get_singleton()->body_add_shape(rid, shapes[i].shape->get_rid(), shapes[i].xform); - if (shapes[i].trigger) - Physics2DServer::get_singleton()->body_set_shape_as_trigger(rid, i, shapes[i].trigger); + ShapeData &sd = shapes[p_owner]; + sd.one_way_collision = p_enable; + for (int i = 0; i < sd.shapes.size(); i++) { + Physics2DServer::get_singleton()->body_set_shape_as_one_way_collision(rid, sd.shapes[i].index, p_enable); + } +} + +bool CollisionObject2D::is_shape_owner_one_way_collision_enabled(uint32_t p_owner) const { + + ERR_FAIL_COND_V(!shapes.has(p_owner), false); + + return shapes[p_owner].one_way_collision; +} + +void CollisionObject2D::get_shape_owners(List<uint32_t> *r_owners) { + + for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) { + r_owners->push_back(E->key()); + } +} + +Array CollisionObject2D::_get_shape_owners() { + + Array ret; + for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) { + ret.push_back(E->key()); + } + + return ret; +} + +void CollisionObject2D::shape_owner_set_transform(uint32_t p_owner, const Transform2D &p_transform) { + + ERR_FAIL_COND(!shapes.has(p_owner)); + + ShapeData &sd = shapes[p_owner]; + sd.xform = p_transform; + for (int i = 0; i < sd.shapes.size(); i++) { + if (area) { + Physics2DServer::get_singleton()->area_set_shape_transform(rid, sd.shapes[i].index, p_transform); + } else { + Physics2DServer::get_singleton()->body_set_shape_transform(rid, sd.shapes[i].index, p_transform); } } } +Transform2D CollisionObject2D::shape_owner_get_transform(uint32_t p_owner) const { -bool CollisionObject2D::_set(const StringName &p_name, const Variant &p_value) { - String name = p_name; + ERR_FAIL_COND_V(!shapes.has(p_owner), Transform2D()); - if (name.begins_with("shapes/")) { + return shapes[p_owner].xform; +} - int idx = name.get_slicec('/', 1).to_int(); - String what = name.get_slicec('/', 2); - if (what == "shape") { - if (idx >= shapes.size()) - add_shape(RefPtr(p_value)); - else - set_shape(idx, RefPtr(p_value)); - } else if (what == "transform") - set_shape_transform(idx, p_value); - else if (what == "trigger") - set_shape_as_trigger(idx, p_value); - } else - return false; +Object *CollisionObject2D::shape_owner_get_owner(uint32_t p_owner) const { + + ERR_FAIL_COND_V(!shapes.has(p_owner), NULL); + + return shapes[p_owner].owner; +} + +void CollisionObject2D::shape_owner_add_shape(uint32_t p_owner, const Ref<Shape2D> &p_shape) { + + ERR_FAIL_COND(!shapes.has(p_owner)); + ERR_FAIL_COND(p_shape.is_null()); + + ShapeData &sd = shapes[p_owner]; + ShapeData::Shape s; + s.index = total_subshapes; + s.shape = p_shape; + if (area) { + Physics2DServer::get_singleton()->area_add_shape(rid, p_shape->get_rid(), sd.xform); + } else { + Physics2DServer::get_singleton()->body_add_shape(rid, p_shape->get_rid(), sd.xform); + } + sd.shapes.push_back(s); + + total_subshapes++; +} +int CollisionObject2D::shape_owner_get_shape_count(uint32_t p_owner) const { + + ERR_FAIL_COND_V(!shapes.has(p_owner), 0); + + return shapes[p_owner].shapes.size(); +} +Ref<Shape2D> CollisionObject2D::shape_owner_get_shape(uint32_t p_owner, int p_shape) const { + + ERR_FAIL_COND_V(!shapes.has(p_owner), Ref<Shape2D>()); + ERR_FAIL_INDEX_V(p_shape, shapes[p_owner].shapes.size(), Ref<Shape2D>()); + + return shapes[p_owner].shapes[p_shape].shape; +} +int CollisionObject2D::shape_owner_get_shape_index(uint32_t p_owner, int p_shape) const { - return true; + ERR_FAIL_COND_V(!shapes.has(p_owner), -1); + ERR_FAIL_INDEX_V(p_shape, shapes[p_owner].shapes.size(), -1); + + return shapes[p_owner].shapes[p_shape].index; } -bool CollisionObject2D::_get(const StringName &p_name, Variant &r_ret) const { +void CollisionObject2D::shape_owner_remove_shape(uint32_t p_owner, int p_shape) { + + ERR_FAIL_COND(!shapes.has(p_owner)); + ERR_FAIL_INDEX(p_shape, shapes[p_owner].shapes.size()); + + int index_to_remove = shapes[p_owner].shapes[p_shape].index; + if (area) { + Physics2DServer::get_singleton()->area_remove_shape(rid, index_to_remove); + } else { + Physics2DServer::get_singleton()->body_remove_shape(rid, index_to_remove); + } + + shapes[p_owner].shapes.remove(p_shape); + + for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) { + for (int i = 0; i < E->get().shapes.size(); i++) { + if (E->get().shapes[i].index > index_to_remove) { + E->get().shapes[i].index -= 1; + } + } + } - String name = p_name; + total_subshapes--; +} - if (name.begins_with("shapes/")) { +void CollisionObject2D::shape_owner_clear_shapes(uint32_t p_owner) { - int idx = name.get_slicec('/', 1).to_int(); - String what = name.get_slicec('/', 2); - if (what == "shape") - r_ret = get_shape(idx); - else if (what == "transform") - r_ret = get_shape_transform(idx); - else if (what == "trigger") - r_ret = is_shape_set_as_trigger(idx); - } else - return false; + ERR_FAIL_COND(!shapes.has(p_owner)); - return true; + while (shape_owner_get_shape_count(p_owner) > 0) { + shape_owner_remove_shape(p_owner, 0); + } } -void CollisionObject2D::_get_property_list(List<PropertyInfo> *p_list) const { +uint32_t CollisionObject2D::shape_find_owner(int p_shape_index) const { - //p_list->push_back( PropertyInfo(Variant::INT,"shape_count",PROPERTY_HINT_RANGE,"0,256,1",PROPERTY_USAGE_NOEDITOR|PROPERTY_USAGE_NO_INSTANCE_STATE) ); + ERR_FAIL_INDEX_V(p_shape_index, total_subshapes, 0); - for (int i = 0; i < shapes.size(); i++) { - String path = "shapes/" + itos(i) + "/"; - p_list->push_back(PropertyInfo(Variant::OBJECT, path + "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_NO_INSTANCE_STATE)); - p_list->push_back(PropertyInfo(Variant::TRANSFORM, path + "transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_NO_INSTANCE_STATE)); - p_list->push_back(PropertyInfo(Variant::BOOL, path + "trigger", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_NO_INSTANCE_STATE)); + for (const Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) { + for (int i = 0; i < E->get().shapes.size(); i++) { + if (E->get().shapes[i].index == p_shape_index) { + return E->key(); + } + } } + + //in theory it should be unreachable + return 0; } void CollisionObject2D::set_pickable(bool p_enabled) { @@ -179,7 +293,7 @@ bool CollisionObject2D::is_pickable() const { return pickable; } -void CollisionObject2D::_input_event(Node *p_viewport, const InputEvent &p_input_event, int p_shape) { +void CollisionObject2D::_input_event(Node *p_viewport, const Ref<InputEvent> &p_input_event, int p_shape) { if (get_script_instance()) { get_script_instance()->call(SceneStringNames::get_singleton()->_input_event, p_viewport, p_input_event, p_shape); @@ -215,24 +329,31 @@ void CollisionObject2D::_update_pickable() { void CollisionObject2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_shape", "shape:Shape2D", "transform"), &CollisionObject2D::add_shape, DEFVAL(Transform2D())); - ClassDB::bind_method(D_METHOD("get_shape_count"), &CollisionObject2D::get_shape_count); - ClassDB::bind_method(D_METHOD("set_shape", "shape_idx", "shape:Shape"), &CollisionObject2D::set_shape); - ClassDB::bind_method(D_METHOD("set_shape_transform", "shape_idx", "transform"), &CollisionObject2D::set_shape_transform); - ClassDB::bind_method(D_METHOD("set_shape_as_trigger", "shape_idx", "enable"), &CollisionObject2D::set_shape_as_trigger); - ClassDB::bind_method(D_METHOD("get_shape:Shape2D", "shape_idx"), &CollisionObject2D::get_shape); - ClassDB::bind_method(D_METHOD("get_shape_transform", "shape_idx"), &CollisionObject2D::get_shape_transform); - ClassDB::bind_method(D_METHOD("is_shape_set_as_trigger", "shape_idx"), &CollisionObject2D::is_shape_set_as_trigger); - ClassDB::bind_method(D_METHOD("remove_shape", "shape_idx"), &CollisionObject2D::remove_shape); - ClassDB::bind_method(D_METHOD("clear_shapes"), &CollisionObject2D::clear_shapes); ClassDB::bind_method(D_METHOD("get_rid"), &CollisionObject2D::get_rid); ClassDB::bind_method(D_METHOD("set_pickable", "enabled"), &CollisionObject2D::set_pickable); ClassDB::bind_method(D_METHOD("is_pickable"), &CollisionObject2D::is_pickable); + ClassDB::bind_method(D_METHOD("create_shape_owner", "owner"), &CollisionObject2D::create_shape_owner); + ClassDB::bind_method(D_METHOD("remove_shape_owner", "owner_id"), &CollisionObject2D::remove_shape_owner); + ClassDB::bind_method(D_METHOD("get_shape_owners"), &CollisionObject2D::_get_shape_owners); + ClassDB::bind_method(D_METHOD("shape_owner_set_transform", "owner_id", "transform"), &CollisionObject2D::shape_owner_set_transform); + ClassDB::bind_method(D_METHOD("shape_owner_get_transform", "owner_id"), &CollisionObject2D::shape_owner_get_transform); + ClassDB::bind_method(D_METHOD("shape_owner_get_owner", "owner_id"), &CollisionObject2D::shape_owner_get_owner); + ClassDB::bind_method(D_METHOD("shape_owner_set_disabled", "owner_id", "disabled"), &CollisionObject2D::shape_owner_set_disabled); + ClassDB::bind_method(D_METHOD("is_shape_owner_disabled", "owner_id"), &CollisionObject2D::is_shape_owner_disabled); + ClassDB::bind_method(D_METHOD("shape_owner_set_one_way_collision", "owner_id", "enable"), &CollisionObject2D::shape_owner_set_one_way_collision); + ClassDB::bind_method(D_METHOD("is_shape_owner_one_way_collision_enabled", "owner_id"), &CollisionObject2D::is_shape_owner_one_way_collision_enabled); + ClassDB::bind_method(D_METHOD("shape_owner_add_shape", "owner_id", "shape"), &CollisionObject2D::shape_owner_add_shape); + ClassDB::bind_method(D_METHOD("shape_owner_get_shape_count", "owner_id"), &CollisionObject2D::shape_owner_get_shape_count); + ClassDB::bind_method(D_METHOD("shape_owner_get_shape", "owner_id", "shape_id"), &CollisionObject2D::shape_owner_get_shape); + ClassDB::bind_method(D_METHOD("shape_owner_get_shape_index", "owner_id", "shape_id"), &CollisionObject2D::shape_owner_get_shape_index); + ClassDB::bind_method(D_METHOD("shape_owner_remove_shape", "owner_id", "shape_id"), &CollisionObject2D::shape_owner_remove_shape); + ClassDB::bind_method(D_METHOD("shape_owner_clear_shapes", "owner_id"), &CollisionObject2D::shape_owner_clear_shapes); + ClassDB::bind_method(D_METHOD("shape_find_owner", "shape_index"), &CollisionObject2D::shape_find_owner); - BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "viewport"), PropertyInfo(Variant::INPUT_EVENT, "event"), PropertyInfo(Variant::INT, "shape_idx"))); + BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "viewport"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::INT, "shape_idx"))); - ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "viewport"), PropertyInfo(Variant::INPUT_EVENT, "event"), PropertyInfo(Variant::INT, "shape_idx"))); + ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "viewport"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::INT, "shape_idx"))); ADD_SIGNAL(MethodInfo("mouse_entered")); ADD_SIGNAL(MethodInfo("mouse_exited")); @@ -241,112 +362,26 @@ void CollisionObject2D::_bind_methods() { ADD_GROUP("", ""); } -void CollisionObject2D::add_shape(const Ref<Shape2D> &p_shape, const Transform2D &p_transform) { - - ERR_FAIL_COND(p_shape.is_null()); - - ShapeData sdata; - sdata.shape = p_shape; - sdata.xform = p_transform; - sdata.trigger = false; - - if (area) - Physics2DServer::get_singleton()->area_add_shape(get_rid(), p_shape->get_rid(), p_transform); - else - Physics2DServer::get_singleton()->body_add_shape(get_rid(), p_shape->get_rid(), p_transform); - - shapes.push_back(sdata); -} -int CollisionObject2D::get_shape_count() const { - - return shapes.size(); -} -void CollisionObject2D::set_shape(int p_shape_idx, const Ref<Shape2D> &p_shape) { - - ERR_FAIL_INDEX(p_shape_idx, shapes.size()); - ERR_FAIL_COND(p_shape.is_null()); - - shapes[p_shape_idx].shape = p_shape; - if (area) - Physics2DServer::get_singleton()->area_set_shape(get_rid(), p_shape_idx, p_shape->get_rid()); - else - Physics2DServer::get_singleton()->body_set_shape(get_rid(), p_shape_idx, p_shape->get_rid()); - - //_update_shapes(); -} - -void CollisionObject2D::set_shape_transform(int p_shape_idx, const Transform2D &p_transform) { - - ERR_FAIL_INDEX(p_shape_idx, shapes.size()); - shapes[p_shape_idx].xform = p_transform; - - if (area) - Physics2DServer::get_singleton()->area_set_shape_transform(get_rid(), p_shape_idx, p_transform); - else - Physics2DServer::get_singleton()->body_set_shape_transform(get_rid(), p_shape_idx, p_transform); - - //_update_shapes(); -} - -Ref<Shape2D> CollisionObject2D::get_shape(int p_shape_idx) const { - - ERR_FAIL_INDEX_V(p_shape_idx, shapes.size(), Ref<Shape2D>()); - return shapes[p_shape_idx].shape; -} -Transform2D CollisionObject2D::get_shape_transform(int p_shape_idx) const { - - ERR_FAIL_INDEX_V(p_shape_idx, shapes.size(), Transform2D()); - return shapes[p_shape_idx].xform; -} -void CollisionObject2D::remove_shape(int p_shape_idx) { - - ERR_FAIL_INDEX(p_shape_idx, shapes.size()); - shapes.remove(p_shape_idx); - - _update_shapes(); -} - -void CollisionObject2D::set_shape_as_trigger(int p_shape_idx, bool p_trigger) { - - ERR_FAIL_INDEX(p_shape_idx, shapes.size()); - shapes[p_shape_idx].trigger = p_trigger; - if (!area && rid.is_valid()) { - - Physics2DServer::get_singleton()->body_set_shape_as_trigger(rid, p_shape_idx, p_trigger); - } -} - -bool CollisionObject2D::is_shape_set_as_trigger(int p_shape_idx) const { - - ERR_FAIL_INDEX_V(p_shape_idx, shapes.size(), false); - return shapes[p_shape_idx].trigger; -} - -void CollisionObject2D::clear_shapes() { - - shapes.clear(); - - _update_shapes(); -} - CollisionObject2D::CollisionObject2D(RID p_rid, bool p_area) { rid = p_rid; area = p_area; pickable = true; set_notify_transform(true); + total_subshapes = 0; if (p_area) { - Physics2DServer::get_singleton()->area_attach_object_instance_ID(rid, get_instance_ID()); + Physics2DServer::get_singleton()->area_attach_object_instance_id(rid, get_instance_id()); } else { - Physics2DServer::get_singleton()->body_attach_object_instance_ID(rid, get_instance_ID()); + Physics2DServer::get_singleton()->body_attach_object_instance_id(rid, get_instance_id()); } } CollisionObject2D::CollisionObject2D() { //owner= + set_notify_transform(true); } diff --git a/scene/2d/collision_object_2d.h b/scene/2d/collision_object_2d.h index e6ea0f42d..36bf39ff4 100644 --- a/scene/2d/collision_object_2d.h +++ b/scene/2d/collision_object_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -34,56 +35,73 @@ class CollisionObject2D : public Node2D { - GDCLASS(CollisionObject2D, Node2D); + GDCLASS(CollisionObject2D, Node2D) bool area; RID rid; bool pickable; struct ShapeData { + + Object *owner; Transform2D xform; - Ref<Shape2D> shape; - bool trigger; + struct Shape { + Ref<Shape2D> shape; + int index; + }; + + Vector<Shape> shapes; + bool disabled; + bool one_way_collision; ShapeData() { - trigger = false; + disabled = false; + one_way_collision = false; + owner = NULL; } }; - Vector<ShapeData> shapes; - - void _update_shapes(); + int total_subshapes; - friend class CollisionShape2D; - friend class CollisionPolygon2D; - void _update_shapes_from_children(); + Map<uint32_t, ShapeData> shapes; protected: CollisionObject2D(RID p_rid, bool p_area); void _notification(int p_what); - bool _set(const StringName &p_name, const Variant &p_value); - bool _get(const StringName &p_name, Variant &r_ret) const; - void _get_property_list(List<PropertyInfo> *p_list) const; static void _bind_methods(); void _update_pickable(); friend class Viewport; - void _input_event(Node *p_viewport, const InputEvent &p_input_event, int p_shape); + void _input_event(Node *p_viewport, const Ref<InputEvent> &p_input_event, int p_shape); void _mouse_enter(); void _mouse_exit(); public: - void add_shape(const Ref<Shape2D> &p_shape, const Transform2D &p_transform = Transform2D()); - int get_shape_count() const; - void set_shape(int p_shape_idx, const Ref<Shape2D> &p_shape); - void set_shape_transform(int p_shape_idx, const Transform2D &p_transform); - Ref<Shape2D> get_shape(int p_shape_idx) const; - Transform2D get_shape_transform(int p_shape_idx) const; - void set_shape_as_trigger(int p_shape_idx, bool p_trigger); - bool is_shape_set_as_trigger(int p_shape_idx) const; - void remove_shape(int p_shape_idx); - void clear_shapes(); + uint32_t create_shape_owner(Object *p_owner); + void remove_shape_owner(uint32_t owner); + void get_shape_owners(List<uint32_t> *r_owners); + Array _get_shape_owners(); + + void shape_owner_set_transform(uint32_t p_owner, const Transform2D &p_transform); + Transform2D shape_owner_get_transform(uint32_t p_owner) const; + Object *shape_owner_get_owner(uint32_t p_owner) const; + + void shape_owner_set_disabled(uint32_t p_owner, bool p_disabled); + bool is_shape_owner_disabled(uint32_t p_owner) const; + + void shape_owner_set_one_way_collision(uint32_t p_owner, bool p_enable); + bool is_shape_owner_one_way_collision_enabled(uint32_t p_owner) const; + + void shape_owner_add_shape(uint32_t p_owner, const Ref<Shape2D> &p_shape); + int shape_owner_get_shape_count(uint32_t p_owner) const; + Ref<Shape2D> shape_owner_get_shape(uint32_t p_owner, int p_shape) const; + int shape_owner_get_shape_index(uint32_t p_owner, int p_shape) const; + + void shape_owner_remove_shape(uint32_t p_owner, int p_shape); + void shape_owner_clear_shapes(uint32_t p_owner); + + uint32_t shape_find_owner(int p_shape_index) const; void set_pickable(bool p_enabled); bool is_pickable() const; diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp index abc044f10..bd669eb4c 100644 --- a/scene/2d/collision_polygon_2d.cpp +++ b/scene/2d/collision_polygon_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -27,17 +28,16 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "collision_polygon_2d.h" + #include "collision_object_2d.h" #include "scene/resources/concave_polygon_shape_2d.h" #include "scene/resources/convex_polygon_shape_2d.h" -#include "triangulator.h" -void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) { - if (unparenting || !can_update_body) - return; +#include "thirdparty/misc/triangulator.h" - CollisionObject2D *co = p_obj->cast_to<CollisionObject2D>(); - ERR_FAIL_COND(!co); +void CollisionPolygon2D::_build_polygon() { + + parent->shape_owner_clear_shapes(owner_id); if (polygon.size() == 0) return; @@ -49,18 +49,10 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) { //here comes the sun, lalalala //decompose concave into multiple convex polygons and add them Vector<Vector<Vector2> > decomp = _decompose_in_convex(); - shape_from = co->get_shape_count(); for (int i = 0; i < decomp.size(); i++) { Ref<ConvexPolygonShape2D> convex = memnew(ConvexPolygonShape2D); convex->set_points(decomp[i]); - co->add_shape(convex, get_transform()); - if (trigger) - co->set_shape_as_trigger(co->get_shape_count() - 1, true); - } - shape_to = co->get_shape_count() - 1; - if (shape_to < shape_from) { - shape_from = -1; - shape_to = -1; + parent->shape_owner_add_shape(owner_id, convex); } } else { @@ -79,28 +71,8 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) { w = PoolVector<Vector2>::Write(); concave->set_segments(segments); - co->add_shape(concave, get_transform()); - if (trigger) - co->set_shape_as_trigger(co->get_shape_count() - 1, true); - - shape_from = co->get_shape_count() - 1; - shape_to = co->get_shape_count() - 1; + parent->shape_owner_add_shape(owner_id, concave); } - - //co->add_shape(shape,get_transform()); -} - -void CollisionPolygon2D::_update_parent() { - - if (!can_update_body) - return; - Node *parent = get_parent(); - if (!parent) - return; - CollisionObject2D *co = parent->cast_to<CollisionObject2D>(); - if (!co) - return; - co->_update_shapes_from_children(); } Vector<Vector<Vector2> > CollisionPolygon2D::_decompose_in_convex() { @@ -151,33 +123,38 @@ Vector<Vector<Vector2> > CollisionPolygon2D::_decompose_in_convex() { void CollisionPolygon2D::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: { - unparenting = false; - can_update_body = get_tree()->is_editor_hint(); - if (!get_tree()->is_editor_hint()) { + case NOTIFICATION_PARENTED: { + + parent = get_parent()->cast_to<CollisionObject2D>(); + if (parent) { + owner_id = parent->create_shape_owner(this); + _build_polygon(); + parent->shape_owner_set_transform(owner_id, get_transform()); + parent->shape_owner_set_disabled(owner_id, disabled); + parent->shape_owner_set_one_way_collision(owner_id, one_way_collision); + } + + /*if (get_tree()->is_editor_hint()) { //display above all else set_z_as_relative(false); set_z(VS::CANVAS_ITEM_Z_MAX - 1); - } + }*/ } break; - case NOTIFICATION_EXIT_TREE: { - can_update_body = false; - } break; case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { - if (!is_inside_tree()) - break; - if (can_update_body) { - _update_parent(); - } else if (shape_from >= 0 && shape_to >= 0) { - CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>(); - for (int i = shape_from; i <= shape_to; i++) { - co->set_shape_transform(i, get_transform()); - } + if (parent) { + parent->shape_owner_set_transform(owner_id, get_transform()); } } break; + case NOTIFICATION_UNPARENTED: { + if (parent) { + parent->remove_shape_owner(owner_id); + } + owner_id = 0; + parent = NULL; + } break; case NOTIFICATION_DRAW: { @@ -206,10 +183,22 @@ void CollisionPolygon2D::_notification(int p_what) { draw_colored_polygon(polygon, get_tree()->get_debug_collisions_color()); #endif - } break; - case NOTIFICATION_UNPARENTED: { - unparenting = true; - _update_parent(); + if (one_way_collision) { + Color dcol = get_tree()->get_debug_collisions_color(); //0.9,0.2,0.2,0.4); + dcol.a = 1.0; + Vector2 line_to(0, 20); + draw_line(Vector2(), line_to, dcol, 3); + Vector<Vector2> pts; + float tsize = 8; + pts.push_back(line_to + (Vector2(0, tsize))); + pts.push_back(line_to + (Vector2(0.707 * tsize, 0))); + pts.push_back(line_to + (Vector2(-0.707 * tsize, 0))); + Vector<Color> cols; + for (int i = 0; i < 3; i++) + cols.push_back(dcol); + + draw_primitive(pts, cols, Vector<Vector2>()); //small arrow + } } break; } } @@ -218,7 +207,7 @@ void CollisionPolygon2D::set_polygon(const Vector<Point2> &p_polygon) { polygon = p_polygon; - if (can_update_body) { + { for (int i = 0; i < polygon.size(); i++) { if (i == 0) aabb = Rect2(polygon[i], Size2()); @@ -229,10 +218,13 @@ void CollisionPolygon2D::set_polygon(const Vector<Point2> &p_polygon) { aabb = Rect2(-10, -10, 20, 20); } else { - aabb.pos -= aabb.size * 0.3; + aabb.position -= aabb.size * 0.3; aabb.size += aabb.size * 0.6; } - _update_parent(); + } + + if (parent) { + _build_polygon(); } update(); update_configuration_warning(); @@ -247,7 +239,9 @@ void CollisionPolygon2D::set_build_mode(BuildMode p_mode) { ERR_FAIL_INDEX(p_mode, 2); build_mode = p_mode; - _update_parent(); + if (parent) { + _build_polygon(); + } } CollisionPolygon2D::BuildMode CollisionPolygon2D::get_build_mode() const { @@ -260,79 +254,69 @@ Rect2 CollisionPolygon2D::get_item_rect() const { return aabb; } -void CollisionPolygon2D::set_trigger(bool p_trigger) { +String CollisionPolygon2D::get_configuration_warning() const { - trigger = p_trigger; - _update_parent(); - if (!can_update_body && is_inside_tree() && shape_from >= 0 && shape_to >= 0) { - CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>(); - for (int i = shape_from; i <= shape_to; i++) { - co->set_shape_as_trigger(i, p_trigger); - } + if (!get_parent()->cast_to<CollisionObject2D>()) { + return TTR("CollisionPolygon2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape."); } -} -bool CollisionPolygon2D::is_trigger() const { + if (polygon.empty()) { + return TTR("An empty CollisionPolygon2D has no effect on collision."); + } - return trigger; + return String(); } -void CollisionPolygon2D::_set_shape_range(const Vector2 &p_range) { - - shape_from = p_range.x; - shape_to = p_range.y; +void CollisionPolygon2D::set_disabled(bool p_disabled) { + disabled = p_disabled; + update(); + if (parent) { + parent->shape_owner_set_disabled(owner_id, p_disabled); + } } -Vector2 CollisionPolygon2D::_get_shape_range() const { - - return Vector2(shape_from, shape_to); +bool CollisionPolygon2D::is_disabled() const { + return disabled; } -String CollisionPolygon2D::get_configuration_warning() const { - - if (!get_parent()->cast_to<CollisionObject2D>()) { - return TTR("CollisionPolygon2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape."); +void CollisionPolygon2D::set_one_way_collision(bool p_enable) { + one_way_collision = p_enable; + update(); + if (parent) { + parent->shape_owner_set_one_way_collision(owner_id, p_enable); } +} - if (polygon.empty()) { - return TTR("An empty CollisionPolygon2D has no effect on collision."); - } +bool CollisionPolygon2D::is_one_way_collision_enabled() const { - return String(); + return one_way_collision; } void CollisionPolygon2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("_add_to_collision_object"), &CollisionPolygon2D::_add_to_collision_object); ClassDB::bind_method(D_METHOD("set_polygon", "polygon"), &CollisionPolygon2D::set_polygon); ClassDB::bind_method(D_METHOD("get_polygon"), &CollisionPolygon2D::get_polygon); ClassDB::bind_method(D_METHOD("set_build_mode", "build_mode"), &CollisionPolygon2D::set_build_mode); ClassDB::bind_method(D_METHOD("get_build_mode"), &CollisionPolygon2D::get_build_mode); - - ClassDB::bind_method(D_METHOD("set_trigger", "trigger"), &CollisionPolygon2D::set_trigger); - ClassDB::bind_method(D_METHOD("is_trigger"), &CollisionPolygon2D::is_trigger); - - ClassDB::bind_method(D_METHOD("_set_shape_range", "shape_range"), &CollisionPolygon2D::_set_shape_range); - ClassDB::bind_method(D_METHOD("_get_shape_range"), &CollisionPolygon2D::_get_shape_range); - - ClassDB::bind_method(D_METHOD("get_collision_object_first_shape"), &CollisionPolygon2D::get_collision_object_first_shape); - ClassDB::bind_method(D_METHOD("get_collision_object_last_shape"), &CollisionPolygon2D::get_collision_object_last_shape); + ClassDB::bind_method(D_METHOD("set_disabled", "disabled"), &CollisionPolygon2D::set_disabled); + ClassDB::bind_method(D_METHOD("is_disabled"), &CollisionPolygon2D::is_disabled); + ClassDB::bind_method(D_METHOD("set_one_way_collision", "enabled"), &CollisionPolygon2D::set_one_way_collision); + ClassDB::bind_method(D_METHOD("is_one_way_collision_enabled"), &CollisionPolygon2D::is_one_way_collision_enabled); ADD_PROPERTY(PropertyInfo(Variant::INT, "build_mode", PROPERTY_HINT_ENUM, "Solids,Segments"), "set_build_mode", "get_build_mode"); ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "shape_range", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_shape_range", "_get_shape_range"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "trigger"), "set_trigger", "is_trigger"); + ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled"); + ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "one_way_collision"), "set_one_way_collision", "is_one_way_collision_enabled"); } CollisionPolygon2D::CollisionPolygon2D() { aabb = Rect2(-10, -10, 20, 20); build_mode = BUILD_SOLIDS; - trigger = false; - unparenting = false; - shape_from = -1; - shape_to = -1; - can_update_body = false; set_notify_local_transform(true); + parent = NULL; + owner_id = 0; + disabled = false; + one_way_collision = false; } diff --git a/scene/2d/collision_polygon_2d.h b/scene/2d/collision_polygon_2d.h index f1f31a285..f0666ba9d 100644 --- a/scene/2d/collision_polygon_2d.h +++ b/scene/2d/collision_polygon_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,6 +33,8 @@ #include "scene/2d/node_2d.h" #include "scene/resources/shape_2d.h" +class CollisionObject2D; + class CollisionPolygon2D : public Node2D { GDCLASS(CollisionPolygon2D, Node2D); @@ -46,29 +49,20 @@ protected: Rect2 aabb; BuildMode build_mode; Vector<Point2> polygon; - bool trigger; - bool unparenting; - - void _add_to_collision_object(Object *p_obj); - void _update_parent(); - - bool can_update_body; - int shape_from; - int shape_to; - - void _set_shape_range(const Vector2 &p_range); - Vector2 _get_shape_range() const; + uint32_t owner_id; + CollisionObject2D *parent; + bool disabled; + bool one_way_collision; Vector<Vector<Vector2> > _decompose_in_convex(); + void _build_polygon(); + protected: void _notification(int p_what); static void _bind_methods(); public: - void set_trigger(bool p_trigger); - bool is_trigger() const; - void set_build_mode(BuildMode p_mode); BuildMode get_build_mode() const; @@ -77,11 +71,14 @@ public: virtual Rect2 get_item_rect() const; - int get_collision_object_first_shape() const { return shape_from; } - int get_collision_object_last_shape() const { return shape_to; } - virtual String get_configuration_warning() const; + void set_disabled(bool p_disabled); + bool is_disabled() const; + + void set_one_way_collision(bool p_enable); + bool is_one_way_collision_enabled() const; + CollisionPolygon2D(); }; diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp index 39e0017e9..ff4aa245e 100644 --- a/scene/2d/collision_shape_2d.cpp +++ b/scene/2d/collision_shape_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -36,68 +37,48 @@ #include "scene/resources/segment_shape_2d.h" #include "scene/resources/shape_line_2d.h" -void CollisionShape2D::_add_to_collision_object(Object *p_obj) { - - if (unparenting) - return; - - CollisionObject2D *co = p_obj->cast_to<CollisionObject2D>(); - ERR_FAIL_COND(!co); - update_shape_index = co->get_shape_count(); - co->add_shape(shape, get_transform()); - if (trigger) - co->set_shape_as_trigger(co->get_shape_count() - 1, true); -} - void CollisionShape2D::_shape_changed() { update(); - _update_parent(); -} - -void CollisionShape2D::_update_parent() { - - Node *parent = get_parent(); - if (!parent) - return; - CollisionObject2D *co = parent->cast_to<CollisionObject2D>(); - if (!co) - return; - co->_update_shapes_from_children(); } void CollisionShape2D::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: { - unparenting = false; - can_update_body = get_tree()->is_editor_hint(); - if (!get_tree()->is_editor_hint()) { + case NOTIFICATION_PARENTED: { + + parent = get_parent()->cast_to<CollisionObject2D>(); + if (parent) { + owner_id = parent->create_shape_owner(this); + if (shape.is_valid()) { + parent->shape_owner_add_shape(owner_id, shape); + } + parent->shape_owner_set_transform(owner_id, get_transform()); + parent->shape_owner_set_disabled(owner_id, disabled); + parent->shape_owner_set_one_way_collision(owner_id, one_way_collision); + } + + /*if (get_tree()->is_editor_hint()) { //display above all else set_z_as_relative(false); set_z(VS::CANVAS_ITEM_Z_MAX - 1); - } + }*/ } break; case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { - if (!is_inside_tree()) - break; - if (can_update_body) { - _update_parent(); - } else if (update_shape_index >= 0) { - - CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>(); - if (co) { - co->set_shape_transform(update_shape_index, get_transform()); - } + if (parent) { + parent->shape_owner_set_transform(owner_id, get_transform()); } } break; - case NOTIFICATION_EXIT_TREE: { - can_update_body = false; - + case NOTIFICATION_UNPARENTED: { + if (parent) { + parent->remove_shape_owner(owner_id); + } + owner_id = 0; + parent = NULL; } break; /* case NOTIFICATION_TRANSFORM_CHANGED: { @@ -120,15 +101,33 @@ void CollisionShape2D::_notification(int p_what) { rect = Rect2(); Color draw_col = get_tree()->get_debug_collisions_color(); + if (disabled) { + float g = draw_col.gray(); + draw_col.r = g; + draw_col.g = g; + draw_col.b = g; + } shape->draw(get_canvas_item(), draw_col); rect = shape->get_rect(); rect = rect.grow(3); - } break; - case NOTIFICATION_UNPARENTED: { - unparenting = true; - _update_parent(); + if (one_way_collision) { + Color dcol = get_tree()->get_debug_collisions_color(); //0.9,0.2,0.2,0.4); + dcol.a = 1.0; + Vector2 line_to(0, 20); + draw_line(Vector2(), line_to, dcol, 3); + Vector<Vector2> pts; + float tsize = 8; + pts.push_back(line_to + (Vector2(0, tsize))); + pts.push_back(line_to + (Vector2(0.707 * tsize, 0))); + pts.push_back(line_to + (Vector2(-0.707 * tsize, 0))); + Vector<Color> cols; + for (int i = 0; i < 3; i++) + cols.push_back(dcol); + + draw_primitive(pts, cols, Vector<Vector2>()); //small arrow + } } break; } } @@ -139,14 +138,13 @@ void CollisionShape2D::set_shape(const Ref<Shape2D> &p_shape) { shape->disconnect("changed", this, "_shape_changed"); shape = p_shape; update(); - if (is_inside_tree() && can_update_body) - _update_parent(); - if (is_inside_tree() && !can_update_body && update_shape_index >= 0) { - CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>(); - if (co) { - co->set_shape(update_shape_index, p_shape); + if (parent) { + parent->shape_owner_clear_shapes(owner_id); + if (shape.is_valid()) { + parent->shape_owner_add_shape(owner_id, shape); } } + if (shape.is_valid()) shape->connect("changed", this, "_shape_changed"); @@ -163,72 +161,65 @@ Rect2 CollisionShape2D::get_item_rect() const { return rect; } -void CollisionShape2D::set_trigger(bool p_trigger) { +String CollisionShape2D::get_configuration_warning() const { - trigger = p_trigger; - if (can_update_body) { - _update_parent(); - } else if (is_inside_tree() && update_shape_index >= 0) { - CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>(); - if (co) { - co->set_shape_as_trigger(update_shape_index, p_trigger); - } + if (!get_parent()->cast_to<CollisionObject2D>()) { + return TTR("CollisionShape2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape."); } -} -bool CollisionShape2D::is_trigger() const { + if (!shape.is_valid()) { + return TTR("A shape must be provided for CollisionShape2D to function. Please create a shape resource for it!"); + } - return trigger; + return String(); } -void CollisionShape2D::_set_update_shape_index(int p_index) { - - update_shape_index = p_index; +void CollisionShape2D::set_disabled(bool p_disabled) { + disabled = p_disabled; + update(); + if (parent) { + parent->shape_owner_set_disabled(owner_id, p_disabled); + } } -int CollisionShape2D::_get_update_shape_index() const { - - return update_shape_index; +bool CollisionShape2D::is_disabled() const { + return disabled; } -String CollisionShape2D::get_configuration_warning() const { - - if (!get_parent()->cast_to<CollisionObject2D>()) { - return TTR("CollisionShape2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape."); +void CollisionShape2D::set_one_way_collision(bool p_enable) { + one_way_collision = p_enable; + update(); + if (parent) { + parent->shape_owner_set_one_way_collision(owner_id, p_enable); } +} - if (!shape.is_valid()) { - return TTR("A shape must be provided for CollisionShape2D to function. Please create a shape resource for it!"); - } +bool CollisionShape2D::is_one_way_collision_enabled() const { - return String(); + return one_way_collision; } void CollisionShape2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shape", "shape"), &CollisionShape2D::set_shape); ClassDB::bind_method(D_METHOD("get_shape"), &CollisionShape2D::get_shape); + ClassDB::bind_method(D_METHOD("set_disabled", "disabled"), &CollisionShape2D::set_disabled); + ClassDB::bind_method(D_METHOD("is_disabled"), &CollisionShape2D::is_disabled); + ClassDB::bind_method(D_METHOD("set_one_way_collision", "enabled"), &CollisionShape2D::set_one_way_collision); + ClassDB::bind_method(D_METHOD("is_one_way_collision_enabled"), &CollisionShape2D::is_one_way_collision_enabled); ClassDB::bind_method(D_METHOD("_shape_changed"), &CollisionShape2D::_shape_changed); - ClassDB::bind_method(D_METHOD("_add_to_collision_object"), &CollisionShape2D::_add_to_collision_object); - ClassDB::bind_method(D_METHOD("set_trigger", "enable"), &CollisionShape2D::set_trigger); - ClassDB::bind_method(D_METHOD("is_trigger"), &CollisionShape2D::is_trigger); - - ClassDB::bind_method(D_METHOD("_set_update_shape_index", "index"), &CollisionShape2D::_set_update_shape_index); - ClassDB::bind_method(D_METHOD("_get_update_shape_index"), &CollisionShape2D::_get_update_shape_index); - - ClassDB::bind_method(D_METHOD("get_collision_object_shape_index"), &CollisionShape2D::get_collision_object_shape_index); ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), "set_shape", "get_shape"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "trigger"), "set_trigger", "is_trigger"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "_update_shape_index", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_update_shape_index", "_get_update_shape_index"); + ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled"); + ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "one_way_collision"), "set_one_way_collision", "is_one_way_collision_enabled"); } CollisionShape2D::CollisionShape2D() { rect = Rect2(-Point2(10, 10), Point2(20, 20)); set_notify_local_transform(true); - trigger = false; - unparenting = false; - can_update_body = false; - update_shape_index = -1; + owner_id = 0; + parent = NULL; + disabled = false; + one_way_collision = false; } diff --git a/scene/2d/collision_shape_2d.h b/scene/2d/collision_shape_2d.h index a3395cdc1..1f2b96b91 100644 --- a/scene/2d/collision_shape_2d.h +++ b/scene/2d/collision_shape_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,35 +33,33 @@ #include "scene/2d/node_2d.h" #include "scene/resources/shape_2d.h" +class CollisionObject2D; + class CollisionShape2D : public Node2D { - GDCLASS(CollisionShape2D, Node2D); + GDCLASS(CollisionShape2D, Node2D) Ref<Shape2D> shape; Rect2 rect; - bool trigger; - bool unparenting; - bool can_update_body; + uint32_t owner_id; + CollisionObject2D *parent; void _shape_changed(); - int update_shape_index; - - void _set_update_shape_index(int p_index); - int _get_update_shape_index() const; + bool disabled; + bool one_way_collision; protected: - void _update_parent(); void _notification(int p_what); static void _bind_methods(); - void _add_to_collision_object(Object *p_obj); - public: void set_shape(const Ref<Shape2D> &p_shape); Ref<Shape2D> get_shape() const; virtual Rect2 get_item_rect() const; - void set_trigger(bool p_trigger); - bool is_trigger() const; - int get_collision_object_shape_index() const { return _get_update_shape_index(); } + void set_disabled(bool p_disabled); + bool is_disabled() const; + + void set_one_way_collision(bool p_enable); + bool is_one_way_collision_enabled() const; virtual String get_configuration_warning() const; diff --git a/scene/2d/joints_2d.cpp b/scene/2d/joints_2d.cpp index 96ef714f1..1bb40a28b 100644 --- a/scene/2d/joints_2d.cpp +++ b/scene/2d/joints_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/joints_2d.h b/scene/2d/joints_2d.h index c17262046..f854ce51e 100644 --- a/scene/2d/joints_2d.h +++ b/scene/2d/joints_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -80,7 +81,7 @@ protected: static void _bind_methods(); public: - void set_softness(real_t p_stiffness); + void set_softness(real_t p_softness); real_t get_softness() const; PinJoint2D(); diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp index 7cf98c8c0..ffe69fa93 100644 --- a/scene/2d/light_2d.cpp +++ b/scene/2d/light_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -335,6 +336,17 @@ String Light2D::get_configuration_warning() const { return String(); } +void Light2D::set_shadow_smooth(float p_amount) { + + shadow_smooth = p_amount; + VS::get_singleton()->canvas_light_set_shadow_smooth(canvas_light, shadow_smooth); +} + +float Light2D::get_shadow_smooth() const { + + return shadow_smooth; +} + void Light2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &Light2D::set_enabled); @@ -388,6 +400,9 @@ void Light2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shadow_buffer_size", "size"), &Light2D::set_shadow_buffer_size); ClassDB::bind_method(D_METHOD("get_shadow_buffer_size"), &Light2D::get_shadow_buffer_size); + ClassDB::bind_method(D_METHOD("set_shadow_smooth", "smooth"), &Light2D::set_shadow_smooth); + ClassDB::bind_method(D_METHOD("get_shadow_smooth"), &Light2D::get_shadow_smooth); + ClassDB::bind_method(D_METHOD("set_shadow_gradient_length", "multiplier"), &Light2D::set_shadow_gradient_length); ClassDB::bind_method(D_METHOD("get_shadow_gradient_length"), &Light2D::get_shadow_gradient_length); @@ -401,7 +416,7 @@ void Light2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_only"), "set_editor_only", "is_editor_only"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_texture_offset", "get_texture_offset"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "scale", PROPERTY_HINT_RANGE, "0.01,50,0.01"), "set_texture_scale", "get_texture_scale"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "texture_scale", PROPERTY_HINT_RANGE, "0.01,50,0.01"), "set_texture_scale", "get_texture_scale"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "energy", PROPERTY_HINT_RANGE, "0.01,100,0.01"), "set_energy", "get_energy"); ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Add,Sub,Mix,Mask"), "set_mode", "get_mode"); @@ -419,6 +434,7 @@ void Light2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_buffer_size", PROPERTY_HINT_RANGE, "32,16384,1"), "set_shadow_buffer_size", "get_shadow_buffer_size"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "shadow_gradient_length", PROPERTY_HINT_RANGE, "1,4096,0.1"), "set_shadow_gradient_length", "get_shadow_gradient_length"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "shadow_filter", PROPERTY_HINT_ENUM, "None,PCF3,PCF5,PCF9,PCF13"), "set_shadow_filter", "get_shadow_filter"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "shadow_filter_smooth", PROPERTY_HINT_RANGE, "0,64,0.1"), "set_shadow_smooth", "get_shadow_smooth"); ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_item_cull_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_item_shadow_cull_mask", "get_item_shadow_cull_mask"); BIND_CONSTANT(MODE_ADD); @@ -448,6 +464,7 @@ Light2D::Light2D() { energy = 1.0; shadow_color = Color(0, 0, 0, 0); shadow_filter = SHADOW_FILTER_NONE; + shadow_smooth = 0; set_notify_transform(true); } diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h index e9f0e069d..90e55aeda 100644 --- a/scene/2d/light_2d.h +++ b/scene/2d/light_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -68,6 +69,7 @@ private: int item_mask; int item_shadow_mask; int shadow_buffer_size; + float shadow_smooth; float shadow_gradient_length; Mode mode; Ref<Texture> texture; @@ -145,6 +147,9 @@ public: void set_shadow_color(const Color &p_shadow_color); Color get_shadow_color() const; + void set_shadow_smooth(float p_amount); + float get_shadow_smooth() const; + virtual Rect2 get_item_rect() const; String get_configuration_warning() const; diff --git a/scene/2d/light_occluder_2d.cpp b/scene/2d/light_occluder_2d.cpp index 401bbcedb..a1a8e7d9c 100644 --- a/scene/2d/light_occluder_2d.cpp +++ b/scene/2d/light_occluder_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -211,8 +212,8 @@ String LightOccluder2D::get_configuration_warning() const { void LightOccluder2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_occluder_polygon", "polygon:OccluderPolygon2D"), &LightOccluder2D::set_occluder_polygon); - ClassDB::bind_method(D_METHOD("get_occluder_polygon:OccluderPolygon2D"), &LightOccluder2D::get_occluder_polygon); + ClassDB::bind_method(D_METHOD("set_occluder_polygon", "polygon"), &LightOccluder2D::set_occluder_polygon); + ClassDB::bind_method(D_METHOD("get_occluder_polygon"), &LightOccluder2D::get_occluder_polygon); ClassDB::bind_method(D_METHOD("set_occluder_light_mask", "mask"), &LightOccluder2D::set_occluder_light_mask); ClassDB::bind_method(D_METHOD("get_occluder_light_mask"), &LightOccluder2D::get_occluder_light_mask); diff --git a/scene/2d/light_occluder_2d.h b/scene/2d/light_occluder_2d.h index 26135334f..30c30b1a4 100644 --- a/scene/2d/light_occluder_2d.h +++ b/scene/2d/light_occluder_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp index cd9b8e8cb..5438557d0 100644 --- a/scene/2d/line_2d.cpp +++ b/scene/2d/line_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -98,7 +99,7 @@ Color Line2D::get_default_color() const { return _default_color; } -void Line2D::set_gradient(const Ref<ColorRamp> &gradient) { +void Line2D::set_gradient(const Ref<Gradient> &gradient) { // Cleanup previous connection if any if (_gradient.is_valid()) { @@ -115,7 +116,7 @@ void Line2D::set_gradient(const Ref<ColorRamp> &gradient) { update(); } -Ref<ColorRamp> Line2D::get_gradient() const { +Ref<Gradient> Line2D::get_gradient() const { return _gradient; } @@ -309,12 +310,15 @@ void Line2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "points"), "set_points", "get_points"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "width"), "set_width", "get_width"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "default_color"), "set_default_color", "get_default_color"); - ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "gradient", PROPERTY_HINT_RESOURCE_TYPE, "ColorRamp"), "set_gradient", "get_gradient"); + ADD_GROUP("Fill", ""); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "gradient", PROPERTY_HINT_RESOURCE_TYPE, "Gradient"), "set_gradient", "get_gradient"); ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture"); ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "texture_mode", PROPERTY_HINT_ENUM, "None,Tile"), "set_texture_mode", "get_texture_mode"); + ADD_GROUP("Capping", ""); ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "joint_mode", PROPERTY_HINT_ENUM, "Sharp,Bevel,Round"), "set_joint_mode", "get_joint_mode"); ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "begin_cap_mode", PROPERTY_HINT_ENUM, "None,Box,Round"), "set_begin_cap_mode", "get_begin_cap_mode"); ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "end_cap_mode", PROPERTY_HINT_ENUM, "None,Box,Round"), "set_end_cap_mode", "get_end_cap_mode"); + ADD_GROUP("Border", ""); ADD_PROPERTY(PropertyInfo(Variant::REAL, "sharp_limit"), "set_sharp_limit", "get_sharp_limit"); ADD_PROPERTY(PropertyInfo(Variant::INT, "round_precision"), "set_round_precision", "get_round_precision"); diff --git a/scene/2d/line_2d.h b/scene/2d/line_2d.h index 2cd71e972..e8ca5e6e7 100644 --- a/scene/2d/line_2d.h +++ b/scene/2d/line_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -56,8 +57,8 @@ public: void set_default_color(Color color); Color get_default_color() const; - void set_gradient(const Ref<ColorRamp> &gradient); - Ref<ColorRamp> get_gradient() const; + void set_gradient(const Ref<Gradient> &gradient); + Ref<Gradient> get_gradient() const; void set_texture(const Ref<Texture> &texture); Ref<Texture> get_texture() const; @@ -96,7 +97,7 @@ private: LineCapMode _end_cap_mode; float _width; Color _default_color; - Ref<ColorRamp> _gradient; + Ref<Gradient> _gradient; Ref<Texture> _texture; LineTextureMode _texture_mode; float _sharp_limit; diff --git a/scene/2d/line_builder.cpp b/scene/2d/line_builder.cpp index 024c0b89e..3c1410edb 100644 --- a/scene/2d/line_builder.cpp +++ b/scene/2d/line_builder.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -82,8 +83,8 @@ static inline Vector2 rotate90(const Vector2 &v) { static inline Vector2 interpolate(const Rect2 &r, const Vector2 &v) { return Vector2( - Math::lerp(r.get_pos().x, r.get_pos().x + r.get_size().x, v.x), - Math::lerp(r.get_pos().y, r.get_pos().y + r.get_size().y, v.y)); + Math::lerp(r.position.x, r.position.x + r.get_size().x, v.x), + Math::lerp(r.position.y, r.position.y + r.get_size().y, v.y)); } //---------------------------------------------------------------------------- @@ -336,7 +337,7 @@ void LineBuilder::build() { } else if (current_joint_mode == LINE_JOINT_ROUND) { Vector2 vbegin = cbegin - pos1; Vector2 vend = cend - pos1; - strip_add_arc(pos1, vend.angle_to(vbegin), orientation); + strip_add_arc(pos1, vbegin.angle_to(vend), orientation); } if (intersection_result != SEGMENT_INTERSECT) @@ -497,7 +498,7 @@ void LineBuilder::strip_add_arc(Vector2 center, float angle_delta, Orientation o if (angle_delta < 0.f) angle_step = -angle_step; - float t = vbegin.angle_to(Vector2(1, 0)); + float t = Vector2(1, 0).angle_to(vbegin); float end_angle = t + angle_delta; Vector2 rpos(0, 0); @@ -524,7 +525,7 @@ void LineBuilder::new_arc(Vector2 center, Vector2 vbegin, float angle_delta, Col if (angle_delta < 0.f) angle_step = -angle_step; - float t = vbegin.angle_to(Vector2(1, 0)); + float t = Vector2(1, 0).angle_to(vbegin); float end_angle = t + angle_delta; Vector2 rpos(0, 0); float tt_begin = -Math_PI / 2.f; diff --git a/scene/2d/line_builder.h b/scene/2d/line_builder.h index 43fd281d9..0e1a2aaf5 100644 --- a/scene/2d/line_builder.h +++ b/scene/2d/line_builder.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -61,7 +62,7 @@ public: LineCapMode end_cap_mode; float width; Color default_color; - ColorRamp *gradient; + Gradient *gradient; LineTextureMode texture_mode; float sharp_limit; int round_precision; diff --git a/scene/2d/navigation2d.cpp b/scene/2d/navigation2d.cpp index f0280a2f8..383236b4c 100644 --- a/scene/2d/navigation2d.cpp +++ b/scene/2d/navigation2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -645,7 +646,8 @@ debug path break; } - path.push_back(begin_point); + if (path[path.size() - 1].distance_to(begin_point) > CMP_EPSILON) + path.push_back(begin_point); path.invert(); } @@ -762,7 +764,7 @@ Object *Navigation2D::get_closest_point_owner(const Vector2 &p_point) { void Navigation2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("navpoly_create", "mesh:NavigationPolygon", "xform", "owner"), &Navigation2D::navpoly_create, DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("navpoly_create", "mesh", "xform", "owner"), &Navigation2D::navpoly_create, DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("navpoly_set_transform", "id", "xform"), &Navigation2D::navpoly_set_transform); ClassDB::bind_method(D_METHOD("navpoly_remove", "id"), &Navigation2D::navpoly_remove); diff --git a/scene/2d/navigation2d.h b/scene/2d/navigation2d.h index afa565518..54e89de9e 100644 --- a/scene/2d/navigation2d.h +++ b/scene/2d/navigation2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -56,9 +57,9 @@ class Navigation2D : public Node2D { return (a.key == p_key.a.key) ? (b.key < p_key.b.key) : (a.key < p_key.a.key); }; - EdgeKey(const Point &p_a = Point(), const Point &p_b = Point()) { - a = p_a; - b = p_b; + EdgeKey(const Point &p_a = Point(), const Point &p_b = Point()) + : a(p_a), + b(p_b) { if (a.key > b.key) { SWAP(a, b); } diff --git a/scene/2d/navigation_polygon.cpp b/scene/2d/navigation_polygon.cpp index 570bd00a5..779751c1c 100644 --- a/scene/2d/navigation_polygon.cpp +++ b/scene/2d/navigation_polygon.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -27,9 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "navigation_polygon.h" + #include "core_string_names.h" #include "navigation2d.h" -#include "triangulator.h" + +#include "thirdparty/misc/triangulator.h" void NavigationPolygon::set_vertices(const PoolVector<Vector2> &p_vertices) { @@ -456,8 +459,8 @@ String NavigationPolygonInstance::get_configuration_warning() const { void NavigationPolygonInstance::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_navigation_polygon", "navpoly:NavigationPolygon"), &NavigationPolygonInstance::set_navigation_polygon); - ClassDB::bind_method(D_METHOD("get_navigation_polygon:NavigationPolygon"), &NavigationPolygonInstance::get_navigation_polygon); + ClassDB::bind_method(D_METHOD("set_navigation_polygon", "navpoly"), &NavigationPolygonInstance::set_navigation_polygon); + ClassDB::bind_method(D_METHOD("get_navigation_polygon"), &NavigationPolygonInstance::get_navigation_polygon); ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationPolygonInstance::set_enabled); ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationPolygonInstance::is_enabled); diff --git a/scene/2d/navigation_polygon.h b/scene/2d/navigation_polygon.h index 6bc3b903c..f6e6ed210 100644 --- a/scene/2d/navigation_polygon.h +++ b/scene/2d/navigation_polygon.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index 1ba6ec46c..98d6a467b 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -63,9 +64,10 @@ void Node2D::edit_set_state(const Variant &p_state) { angle = state[1]; _scale = state[2]; _update_transform(); - _change_notify("transform/rot"); - _change_notify("transform/scale"); - _change_notify("transform/pos"); + _change_notify("rotation"); + _change_notify("rotation_deg"); + _change_notify("scale"); + _change_notify("position"); } void Node2D::edit_set_rect(const Rect2 &p_edit_rect) { @@ -74,9 +76,9 @@ void Node2D::edit_set_rect(const Rect2 &p_edit_rect) { Vector2 zero_offset; if (r.size.x != 0) - zero_offset.x = -r.pos.x / r.size.x; + zero_offset.x = -r.position.x / r.size.x; if (r.size.y != 0) - zero_offset.y = -r.pos.y / r.size.y; + zero_offset.y = -r.position.y / r.size.y; Size2 new_scale(1, 1); @@ -85,7 +87,7 @@ void Node2D::edit_set_rect(const Rect2 &p_edit_rect) { if (r.size.y != 0) new_scale.y = p_edit_rect.size.y / r.size.y; - Point2 new_pos = p_edit_rect.pos + p_edit_rect.size * zero_offset; //p_edit_rect.pos - r.pos; + Point2 new_pos = p_edit_rect.position + p_edit_rect.size * zero_offset; //p_edit_rect.pos - r.pos; Transform2D postxf; postxf.set_rotation_and_scale(angle, _scale); @@ -95,15 +97,16 @@ void Node2D::edit_set_rect(const Rect2 &p_edit_rect) { _scale *= new_scale; _update_transform(); - _change_notify("transform/scale"); - _change_notify("transform/pos"); + _change_notify("scale"); + _change_notify("position"); } void Node2D::edit_rotate(float p_rot) { angle += p_rot; _update_transform(); - _change_notify("transform/rot"); + _change_notify("rotation"); + _change_notify("rotation_deg"); } void Node2D::_update_xform_values() { @@ -134,7 +137,7 @@ void Node2D::set_position(const Point2 &p_pos) { ((Node2D *)this)->_update_xform_values(); pos = p_pos; _update_transform(); - _change_notify("transform/pos"); + _change_notify("position"); } void Node2D::set_rotation(float p_radians) { @@ -143,7 +146,8 @@ void Node2D::set_rotation(float p_radians) { ((Node2D *)this)->_update_xform_values(); angle = p_radians; _update_transform(); - _change_notify("transform/rot"); + _change_notify("rotation"); + _change_notify("rotation_deg"); } void Node2D::set_rotation_in_degrees(float p_degrees) { @@ -169,7 +173,7 @@ void Node2D::set_scale(const Size2 &p_scale) { if (_scale.y == 0) _scale.y = CMP_EPSILON; _update_transform(); - _change_notify("transform/scale"); + _change_notify("scale"); } Point2 Node2D::get_position() const { @@ -239,7 +243,7 @@ void Node2D::global_translate(const Vector2 &p_amount) { set_global_position(get_global_position() + p_amount); } -void Node2D::scale(const Size2 &p_amount) { +void Node2D::apply_scale(const Size2 &p_amount) { set_scale(get_scale() * p_amount); } @@ -315,7 +319,7 @@ void Node2D::set_global_scale(const Size2 &p_scale) { CanvasItem *pi = get_parent_item(); if (pi) { const Size2 parent_global_scale = pi->get_global_transform().get_scale(); - set_scale(p_scale - parent_global_scale); + set_scale(p_scale / parent_global_scale); } else { set_scale(p_scale); } @@ -349,6 +353,7 @@ void Node2D::set_z(int p_z) { ERR_FAIL_COND(p_z > VS::CANVAS_ITEM_Z_MAX); z = p_z; VS::get_singleton()->canvas_item_set_z(get_canvas_item(), z); + _change_notify("z"); } void Node2D::set_z_as_relative(bool p_enabled) { @@ -393,6 +398,16 @@ float Node2D::get_angle_to(const Vector2 &p_pos) const { return (get_global_transform().affine_inverse().xform(p_pos)).angle(); } +Point2 Node2D::to_local(Point2 p_global) const { + + return get_global_transform().affine_inverse().xform(p_global); +} + +Point2 Node2D::to_global(Point2 p_local) const { + + return get_global_transform().xform(p_local); +} + void Node2D::_bind_methods() { // TODO: Obsolete those two methods (old name) properly (GH-4397) @@ -414,7 +429,7 @@ void Node2D::_bind_methods() { ClassDB::bind_method(D_METHOD("move_local_y", "delta", "scaled"), &Node2D::move_y, DEFVAL(false)); ClassDB::bind_method(D_METHOD("translate", "offset"), &Node2D::translate); ClassDB::bind_method(D_METHOD("global_translate", "offset"), &Node2D::global_translate); - ClassDB::bind_method(D_METHOD("scale", "ratio"), &Node2D::scale); + ClassDB::bind_method(D_METHOD("apply_scale", "ratio"), &Node2D::apply_scale); ClassDB::bind_method(D_METHOD("set_global_position", "pos"), &Node2D::set_global_position); ClassDB::bind_method(D_METHOD("get_global_position"), &Node2D::get_global_position); @@ -431,6 +446,9 @@ void Node2D::_bind_methods() { ClassDB::bind_method(D_METHOD("look_at", "point"), &Node2D::look_at); ClassDB::bind_method(D_METHOD("get_angle_to", "point"), &Node2D::get_angle_to); + ClassDB::bind_method(D_METHOD("to_local", "global_point"), &Node2D::to_local); + ClassDB::bind_method(D_METHOD("to_global", "local_point"), &Node2D::to_global); + ClassDB::bind_method(D_METHOD("set_z", "z"), &Node2D::set_z); ClassDB::bind_method(D_METHOD("get_z"), &Node2D::get_z); diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h index b9c689433..a6009851c 100644 --- a/scene/2d/node_2d.h +++ b/scene/2d/node_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -48,7 +49,7 @@ class Node2D : public CanvasItem { void _update_transform(); // Deprecated, should be removed in a future version. - void _set_rotd(float p_angle); + void _set_rotd(float p_degrees); float _get_rotd() const; void _update_xform_values(); @@ -77,7 +78,7 @@ public: void move_y(float p_delta, bool p_scaled = false); void translate(const Vector2 &p_amount); void global_translate(const Vector2 &p_amount); - void scale(const Size2 &p_amount); + void apply_scale(const Size2 &p_amount); Point2 get_position() const; float get_rotation() const; @@ -103,6 +104,9 @@ public: void look_at(const Vector2 &p_pos); float get_angle_to(const Vector2 &p_pos) const; + Point2 to_local(Point2 p_global) const; + Point2 to_global(Point2 p_local) const; + void set_z_as_relative(bool p_enabled); bool is_z_relative() const; diff --git a/scene/2d/parallax_background.cpp b/scene/2d/parallax_background.cpp index 17bc26aa7..433ab5ff8 100644 --- a/scene/2d/parallax_background.cpp +++ b/scene/2d/parallax_background.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/parallax_background.h b/scene/2d/parallax_background.h index 5914c21c9..fce1bbd92 100644 --- a/scene/2d/parallax_background.h +++ b/scene/2d/parallax_background.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -59,7 +60,7 @@ public: void set_scroll_offset(const Point2 &p_ofs); Point2 get_scroll_offset() const; - void set_scroll_scale(float p_ofs); + void set_scroll_scale(float p_scale); float get_scroll_scale() const; void set_scroll_base_offset(const Point2 &p_ofs); diff --git a/scene/2d/parallax_layer.cpp b/scene/2d/parallax_layer.cpp index 238723460..0e83b9aaa 100644 --- a/scene/2d/parallax_layer.cpp +++ b/scene/2d/parallax_layer.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/parallax_layer.h b/scene/2d/parallax_layer.h index 01293e85a..f2d005334 100644 --- a/scene/2d/parallax_layer.h +++ b/scene/2d/parallax_layer.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -47,7 +48,7 @@ protected: static void _bind_methods(); public: - void set_motion_offset(const Size2 &p_scale); + void set_motion_offset(const Size2 &p_offset); Size2 get_motion_offset() const; void set_motion_scale(const Size2 &p_scale); @@ -56,7 +57,7 @@ public: void set_mirroring(const Size2 &p_mirroring); Size2 get_mirroring() const; - void set_base_offset_and_scale(const Point2 &p_offsetf, float p_scale); + void set_base_offset_and_scale(const Point2 &p_offset, float p_scale); virtual String get_configuration_warning() const; ParallaxLayer(); diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp index c9d5bebe5..a2ec33f40 100644 --- a/scene/2d/particles_2d.cpp +++ b/scene/2d/particles_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -27,903 +28,248 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "particles_2d.h" -#include "scene/scene_string_names.h" - -void ParticleAttractor2D::_notification(int p_what) { - - switch (p_what) { - - case NOTIFICATION_ENTER_TREE: { - - _update_owner(); - } break; - case NOTIFICATION_DRAW: { - - if (!get_tree()->is_editor_hint()) - return; - - Vector2 pv; - float dr = MIN(disable_radius, radius); - for (int i = 0; i <= 32; i++) { - Vector2 v(Math::sin(i / 32.0 * Math_PI * 2), Math::cos(i / 32.0 * Math_PI * 2)); - if (i > 0) { - draw_line(pv * radius, v * radius, Color(0, 0, 0.5, 0.9)); - if (dr > 0) { - draw_line(pv * dr, v * dr, Color(0.5, 0, 0.0, 0.9)); - } - } - pv = v; - } - - } break; - case NOTIFICATION_EXIT_TREE: { - if (owner) { - _set_owner(NULL); - } - - } break; - } -} +#include "scene/3d/particles.h" +#include "scene/scene_string_names.h" -void ParticleAttractor2D::_owner_exited() { +void Particles2D::set_emitting(bool p_emitting) { - ERR_FAIL_COND(!owner); - owner->attractors.erase(this); - owner = NULL; + emitting = p_emitting; + VS::get_singleton()->particles_set_emitting(particles, emitting); } -void ParticleAttractor2D::_update_owner() { - - if (!is_inside_tree() || !has_node(path)) { - _set_owner(NULL); - return; - } - - Node *n = get_node(path); - ERR_FAIL_COND(!n); - Particles2D *pn = n->cast_to<Particles2D>(); - if (!pn) { - _set_owner(NULL); - return; - } +void Particles2D::set_amount(int p_amount) { - _set_owner(pn); + ERR_FAIL_COND(p_amount < 1); + amount = p_amount; + VS::get_singleton()->particles_set_amount(particles, amount); } +void Particles2D::set_lifetime(float p_lifetime) { -void ParticleAttractor2D::_set_owner(Particles2D *p_owner) { - - if (owner == p_owner) - return; - - if (owner) { - owner->disconnect("tree_exited", this, "_owner_exited"); - owner->attractors.erase(this); - owner = NULL; - } - owner = p_owner; - - if (owner) { - - owner->connect("tree_exited", this, "_owner_exited", varray(), CONNECT_ONESHOT); - owner->attractors.insert(this); - } + ERR_FAIL_COND(p_lifetime <= 0); + lifetime = p_lifetime; + VS::get_singleton()->particles_set_lifetime(particles, lifetime); } -void ParticleAttractor2D::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &ParticleAttractor2D::set_enabled); - ClassDB::bind_method(D_METHOD("is_enabled"), &ParticleAttractor2D::is_enabled); - - ClassDB::bind_method(D_METHOD("set_radius", "radius"), &ParticleAttractor2D::set_radius); - ClassDB::bind_method(D_METHOD("get_radius"), &ParticleAttractor2D::get_radius); - - ClassDB::bind_method(D_METHOD("set_disable_radius", "radius"), &ParticleAttractor2D::set_disable_radius); - ClassDB::bind_method(D_METHOD("get_disable_radius"), &ParticleAttractor2D::get_disable_radius); +void Particles2D::set_one_shot(bool p_enable) { - ClassDB::bind_method(D_METHOD("set_gravity", "gravity"), &ParticleAttractor2D::set_gravity); - ClassDB::bind_method(D_METHOD("get_gravity"), &ParticleAttractor2D::get_gravity); - - ClassDB::bind_method(D_METHOD("set_absorption", "absorption"), &ParticleAttractor2D::set_absorption); - ClassDB::bind_method(D_METHOD("get_absorption"), &ParticleAttractor2D::get_absorption); - - ClassDB::bind_method(D_METHOD("set_particles_path", "path"), &ParticleAttractor2D::set_particles_path); - ClassDB::bind_method(D_METHOD("get_particles_path"), &ParticleAttractor2D::get_particles_path); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0.1,16000,0.1"), "set_radius", "get_radius"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "disable_radius", PROPERTY_HINT_RANGE, "0.1,16000,0.1"), "set_disable_radius", "get_disable_radius"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "gravity", PROPERTY_HINT_RANGE, "-512,512,0.01"), "set_gravity", "get_gravity"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "absorption", PROPERTY_HINT_RANGE, "0,512,0.01"), "set_absorption", "get_absorption"); - ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "particles_path", PROPERTY_HINT_RESOURCE_TYPE, "Particles2D"), "set_particles_path", "get_particles_path"); + one_shot = p_enable; + VS::get_singleton()->particles_set_one_shot(particles, one_shot); + if (!one_shot && emitting) + VisualServer::get_singleton()->particles_restart(particles); } +void Particles2D::set_pre_process_time(float p_time) { -void ParticleAttractor2D::set_enabled(bool p_enabled) { - - enabled = p_enabled; + pre_process_time = p_time; + VS::get_singleton()->particles_set_pre_process_time(particles, pre_process_time); } +void Particles2D::set_explosiveness_ratio(float p_ratio) { -bool ParticleAttractor2D::is_enabled() const { - - return enabled; + explosiveness_ratio = p_ratio; + VS::get_singleton()->particles_set_explosiveness_ratio(particles, explosiveness_ratio); } +void Particles2D::set_randomness_ratio(float p_ratio) { -void ParticleAttractor2D::set_radius(float p_radius) { - - radius = p_radius; - update(); + randomness_ratio = p_ratio; + VS::get_singleton()->particles_set_randomness_ratio(particles, randomness_ratio); } +void Particles2D::set_visibility_rect(const Rect2 &p_aabb) { -float ParticleAttractor2D::get_radius() const { + visibility_rect = p_aabb; + Rect3 aabb; + aabb.position.x = p_aabb.position.x; + aabb.position.y = p_aabb.position.y; + aabb.size.x = p_aabb.size.x; + aabb.size.y = p_aabb.size.y; - return radius; -} + VS::get_singleton()->particles_set_custom_aabb(particles, aabb); -void ParticleAttractor2D::set_disable_radius(float p_disable_radius) { - - disable_radius = p_disable_radius; + _change_notify("visibility_rect"); update(); } -float ParticleAttractor2D::get_disable_radius() const { +void Particles2D::set_use_local_coordinates(bool p_enable) { - return disable_radius; -} - -void ParticleAttractor2D::set_gravity(float p_gravity) { - - gravity = p_gravity; -} -float ParticleAttractor2D::get_gravity() const { - - return gravity; -} - -void ParticleAttractor2D::set_absorption(float p_absorption) { - - absorption = p_absorption; -} -float ParticleAttractor2D::get_absorption() const { - - return absorption; -} - -void ParticleAttractor2D::set_particles_path(NodePath p_path) { - - path = p_path; - _update_owner(); - update_configuration_warning(); -} -NodePath ParticleAttractor2D::get_particles_path() const { - - return path; -} - -String ParticleAttractor2D::get_configuration_warning() const { - - if (!has_node(path) || !get_node(path) || !get_node(path)->cast_to<Particles2D>()) { - return TTR("Path property must point to a valid Particles2D node to work."); + local_coords = p_enable; + VS::get_singleton()->particles_set_use_local_coordinates(particles, local_coords); + set_notify_transform(!p_enable); + if (!p_enable && is_inside_tree()) { + _update_particle_emission_transform(); } - - return String(); } -ParticleAttractor2D::ParticleAttractor2D() { +void Particles2D::_update_particle_emission_transform() { - owner = NULL; - radius = 50; - disable_radius = 0; - gravity = 100; - absorption = 0; - path = String(".."); - enabled = true; -} + Transform2D xf2d = get_global_transform(); + Transform xf; + xf.basis.set_axis(0, Vector3(xf2d.get_axis(0).x, xf2d.get_axis(0).y, 0)); + xf.basis.set_axis(1, Vector3(xf2d.get_axis(1).x, xf2d.get_axis(1).y, 0)); + xf.set_origin(Vector3(xf2d.get_origin().x, xf2d.get_origin().y, 0)); -/****************************************/ - -_FORCE_INLINE_ static float _rand_from_seed(uint64_t *seed) { - - uint32_t r = Math::rand_from_seed(seed); - return 2.0f * (float)r / (float)Math::RANDOM_MAX - 1.0f; + VS::get_singleton()->particles_set_emission_transform(particles, xf); } -void Particles2D::_process_particles(float p_delta) { - - if (particles.size() == 0 || lifetime == 0) - return; - - p_delta *= time_scale; - - float frame_time = p_delta; - - if (emit_timeout > 0) { - time_to_live -= frame_time; - if (time_to_live < 0) { - - emitting = false; - _change_notify("config/emitting"); - }; - }; - - float next_time = time + frame_time; - - if (next_time > lifetime) - next_time = Math::fmod(next_time, lifetime); - - Particle *pdata = &particles[0]; - int particle_count = particles.size(); - Transform2D xform; - if (!local_space) - xform = get_global_transform(); - - active_count = 0; - - PoolVector<Point2>::Read r; - int emission_point_count = 0; - if (emission_points.size()) { - - emission_point_count = emission_points.size(); - r = emission_points.read(); - } - - int attractor_count = 0; - AttractorCache *attractor_ptr = NULL; - - if (attractors.size()) { - if (attractors.size() != attractor_cache.size()) { - attractor_cache.resize(attractors.size()); - } - - int idx = 0; - Transform2D m; - if (local_space) { - m = get_global_transform().affine_inverse(); - } - for (Set<ParticleAttractor2D *>::Element *E = attractors.front(); E; E = E->next()) { - - attractor_cache[idx].pos = m.xform(E->get()->get_global_position()); - attractor_cache[idx].attractor = E->get(); - idx++; - } - - attractor_ptr = attractor_cache.ptr(); - attractor_count = attractor_cache.size(); - } - - for (int i = 0; i < particle_count; i++) { - - Particle &p = pdata[i]; - - float restart_time = (i * lifetime / particle_count) * explosiveness; - - bool restart = false; - - if (next_time < time) { - - if (restart_time > time || restart_time < next_time) - restart = true; - - } else if (restart_time > time && restart_time < next_time) { - restart = true; - } - - if (restart) { - - if (emitting) { - - p.pos = emissor_offset; - if (emission_point_count) { - - Vector2 ep = r[Math::rand() % emission_point_count]; - if (!local_space) { - p.pos = xform.xform(p.pos + ep * extents); - } else { - p.pos += ep * extents; - } - } else { - if (!local_space) { - p.pos = xform.xform(p.pos + Vector2(Math::random(-extents.x, extents.x), Math::random(-extents.y, extents.y))); - } else { - p.pos += Vector2(Math::random(-extents.x, extents.x), Math::random(-extents.y, extents.y)); - } - } - p.seed = Math::rand() % 12345678; - uint64_t rand_seed = p.seed * (i + 1); - - float angle = Math::deg2rad(param[PARAM_DIRECTION] + _rand_from_seed(&rand_seed) * param[PARAM_SPREAD]); - - p.velocity = Vector2(Math::sin(angle), Math::cos(angle)); - if (!local_space) { - - p.velocity = xform.basis_xform(p.velocity).normalized(); - } - - p.velocity *= param[PARAM_LINEAR_VELOCITY] + param[PARAM_LINEAR_VELOCITY] * _rand_from_seed(&rand_seed) * randomness[PARAM_LINEAR_VELOCITY]; - p.velocity += initial_velocity; - p.active = true; - p.rot = Math::deg2rad(param[PARAM_INITIAL_ANGLE] + param[PARAM_INITIAL_ANGLE] * randomness[PARAM_INITIAL_ANGLE] * _rand_from_seed(&rand_seed)); - active_count++; +void Particles2D::set_process_material(const Ref<Material> &p_material) { - p.frame = Math::fmod(param[PARAM_ANIM_INITIAL_POS] + randomness[PARAM_ANIM_INITIAL_POS] * _rand_from_seed(&rand_seed), 1.0f); - - } else { - - p.active = false; - } - - } else { - - if (!p.active) - continue; - - uint64_t rand_seed = p.seed * (i + 1); - - Vector2 force; - - //apply gravity - float gravity_dir = Math::deg2rad(param[PARAM_GRAVITY_DIRECTION] + 180 * randomness[PARAM_GRAVITY_DIRECTION] * _rand_from_seed(&rand_seed)); - force += Vector2(Math::sin(gravity_dir), Math::cos(gravity_dir)) * (param[PARAM_GRAVITY_STRENGTH] + param[PARAM_GRAVITY_STRENGTH] * randomness[PARAM_GRAVITY_STRENGTH] * _rand_from_seed(&rand_seed)); - //apply radial - Vector2 rvec = (p.pos - emissor_offset).normalized(); - force += rvec * (param[PARAM_RADIAL_ACCEL] + param[PARAM_RADIAL_ACCEL] * randomness[PARAM_RADIAL_ACCEL] * _rand_from_seed(&rand_seed)); - //apply orbit - float orbitvel = (param[PARAM_ORBIT_VELOCITY] + param[PARAM_ORBIT_VELOCITY] * randomness[PARAM_ORBIT_VELOCITY] * _rand_from_seed(&rand_seed)); - if (orbitvel != 0) { - Vector2 rel = p.pos - xform.elements[2]; - Transform2D rot(orbitvel * frame_time, Vector2()); - p.pos = rot.xform(rel) + xform.elements[2]; - } - - Vector2 tvec = rvec.tangent(); - force += tvec * (param[PARAM_TANGENTIAL_ACCEL] + param[PARAM_TANGENTIAL_ACCEL] * randomness[PARAM_TANGENTIAL_ACCEL] * _rand_from_seed(&rand_seed)); - - for (int j = 0; j < attractor_count; j++) { - - Vector2 vec = (attractor_ptr[j].pos - p.pos); - float vl = vec.length(); - - if (!attractor_ptr[j].attractor->enabled || vl == 0 || vl > attractor_ptr[j].attractor->radius) - continue; - - force += vec * attractor_ptr[j].attractor->gravity; - float fvl = p.velocity.length(); - if (fvl && attractor_ptr[j].attractor->absorption) { - Vector2 target = vec.normalized(); - p.velocity = p.velocity.normalized().linear_interpolate(target, MIN(frame_time * attractor_ptr[j].attractor->absorption, 1)) * fvl; - } - - if (attractor_ptr[j].attractor->disable_radius && vl < attractor_ptr[j].attractor->disable_radius) { - p.active = false; - } - } - - p.velocity += force * frame_time; - - if (param[PARAM_DAMPING]) { - float dmp = param[PARAM_DAMPING] + param[PARAM_DAMPING] * randomness[PARAM_DAMPING] * _rand_from_seed(&rand_seed); - float v = p.velocity.length(); - v -= dmp * frame_time; - if (v <= 0) { - p.velocity = Vector2(); - } else { - p.velocity = p.velocity.normalized() * v; - } - } - - p.pos += p.velocity * frame_time; - p.rot += Math::lerp(param[PARAM_SPIN_VELOCITY], param[PARAM_SPIN_VELOCITY] * randomness[PARAM_SPIN_VELOCITY] * _rand_from_seed(&rand_seed), randomness[PARAM_SPIN_VELOCITY]) * frame_time; - float anim_spd = param[PARAM_ANIM_SPEED_SCALE] + param[PARAM_ANIM_SPEED_SCALE] * randomness[PARAM_ANIM_SPEED_SCALE] * _rand_from_seed(&rand_seed); - p.frame = Math::fposmod(p.frame + (frame_time / lifetime) * anim_spd, 1.0f); - - active_count++; - } + process_material = p_material; + Ref<ParticlesMaterial> pm = p_material; + if (pm.is_valid() && !pm->get_flag(ParticlesMaterial::FLAG_DISABLE_Z) && pm->get_gravity() == Vector3(0, -9.8, 0)) { + //likely a new material, modify it! + pm->set_flag(ParticlesMaterial::FLAG_DISABLE_Z, true); + pm->set_gravity(Vector3(0, 98, 0)); } + RID material_rid; + if (process_material.is_valid()) + material_rid = process_material->get_rid(); + VS::get_singleton()->particles_set_process_material(particles, material_rid); - time = Math::fmod(time + frame_time, lifetime); - if (!emitting && active_count == 0) { - emit_signal(SceneStringNames::get_singleton()->emission_finished); - set_process(false); - set_fixed_process(false); - } - - update(); -} - -void Particles2D::_notification(int p_what) { - - switch (p_what) { - - case NOTIFICATION_PROCESS: { - - _process_particles(get_process_delta_time()); - } break; - - case NOTIFICATION_FIXED_PROCESS: { - - _process_particles(get_fixed_process_delta_time()); - } break; - - case NOTIFICATION_ENTER_TREE: { - - float ppt = preprocess; - while (ppt > 0) { - _process_particles(0.1); - ppt -= 0.1; - } - } break; - case NOTIFICATION_DRAW: { - - if (particles.size() == 0 || lifetime == 0) - return; - - RID ci = get_canvas_item(); - Size2 size(1, 1); - Point2 center; - int total_frames = 1; - - if (!texture.is_null()) { - size = texture->get_size(); - size.x /= h_frames; - size.y /= v_frames; - total_frames = h_frames * v_frames; - } - - float time_pos = (time / lifetime); - - Particle *pdata = &particles[0]; - int particle_count = particles.size(); - - RID texrid; - - if (texture.is_valid()) - texrid = texture->get_rid(); - - Transform2D invxform; - if (!local_space) - invxform = get_global_transform().affine_inverse(); - - int start_particle = (int)(time * (float)particle_count / lifetime); - - for (int id = 0; id < particle_count; ++id) { - int i = start_particle + id; - if (i >= particle_count) { - i -= particle_count; - } - - Particle &p = pdata[i]; - if (!p.active) - continue; - - float ptime = ((float)i / particle_count) * explosiveness; - - if (ptime < time_pos) - ptime = time_pos - ptime; - else - ptime = (1.0 - ptime) + time_pos; - - uint64_t rand_seed = p.seed * (i + 1); - - Color color; - - if (color_ramp.is_valid()) { - color = color_ramp->get_color_at_offset(ptime); - } else { - color = default_color; - } - - { - float huerand = _rand_from_seed(&rand_seed); - float huerot = param[PARAM_HUE_VARIATION] + randomness[PARAM_HUE_VARIATION] * huerand; - - if (Math::abs(huerot) > CMP_EPSILON) { - - float h = color.get_h(); - float s = color.get_s(); - float v = color.get_v(); - float a = color.a; - //float preh=h; - h += huerot; - h = Math::abs(Math::fposmod(h, 1.0f)); - //print_line("rand: "+rtos(randomness[PARAM_HUE_VARIATION])+" rand: "+rtos(huerand)); - //print_line(itos(i)+":hue: "+rtos(preh)+" + "+rtos(huerot)+" = "+rtos(h)); - color.set_hsv(h, s, v); - color.a = a; - } - } - - float initial_size = param[PARAM_INITIAL_SIZE] + param[PARAM_INITIAL_SIZE] * _rand_from_seed(&rand_seed) * randomness[PARAM_INITIAL_SIZE]; - float final_size = param[PARAM_FINAL_SIZE] + param[PARAM_FINAL_SIZE] * _rand_from_seed(&rand_seed) * randomness[PARAM_FINAL_SIZE]; - - float size_mult = initial_size * (1.0 - ptime) + final_size * ptime; - - //Size2 rectsize=size * size_mult; - //rectsize=rectsize.floor(); - - //Rect2 r = Rect2(Vecto,rectsize); - - Transform2D xform; - - if (p.rot) { - - xform.set_rotation(p.rot); - xform.translate(-size * size_mult / 2.0); - xform.elements[2] += p.pos; - } else { - xform.elements[2] = -size * size_mult / 2.0; - xform.elements[2] += p.pos; - } - - if (!local_space) { - xform = invxform * xform; - } - - xform.scale_basis(Size2(size_mult, size_mult)); - - VisualServer::get_singleton()->canvas_item_add_set_transform(ci, xform); - - if (texrid.is_valid()) { - - Rect2 src_rect; - src_rect.size = size; - - if (total_frames > 1) { - int frame = Math::fast_ftoi(Math::floor(p.frame * total_frames)) % total_frames; - src_rect.pos.x = size.x * (frame % h_frames); - src_rect.pos.y = size.y * (frame / h_frames); - } - - if (flip_h) - src_rect.size.x = -src_rect.size.x; - if (flip_v) - src_rect.size.y = -src_rect.size.y; - - texture->draw_rect_region(ci, Rect2(Point2(), size), src_rect, color); - //VisualServer::get_singleton()->canvas_item_add_texture_rect(ci,r,texrid,false,color); - } else { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(), size), color); - } - } - - } break; - } + update_configuration_warning(); } -static const char *_particlesframe_property_names[Particles2D::PARAM_MAX] = { - "params/direction", - "params/spread", - "params/linear_velocity", - "params/spin_velocity", - "params/orbit_velocity", - "params/gravity_direction", - "params/gravity_strength", - "params/radial_accel", - "params/tangential_accel", - "params/damping", - "params/initial_angle", - "params/initial_size", - "params/final_size", - "params/hue_variation", - "params/anim_speed_scale", - "params/anim_initial_pos", -}; +void Particles2D::set_speed_scale(float p_scale) { -static const char *_particlesframe_property_rnames[Particles2D::PARAM_MAX] = { - "randomness/direction", - "randomness/spread", - "randomness/linear_velocity", - "randomness/spin_velocity", - "randomness/orbit_velocity", - "randomness/gravity_direction", - "randomness/gravity_strength", - "randomness/radial_accel", - "randomness/tangential_accel", - "randomness/damping", - "randomness/initial_angle", - "randomness/initial_size", - "randomness/final_size", - "randomness/hue_variation", - "randomness/anim_speed_scale", - "randomness/anim_initial_pos", -}; - -static const char *_particlesframe_property_ranges[Particles2D::PARAM_MAX] = { - "0,360,0.01", - "0,180,0.01", - "-1024,1024,0.01", - "-1024,1024,0.01", - "-1024,1024,0.01", - "0,360,0.01", - "0,1024,0.01", - "-128,128,0.01", - "-128,128,0.01", - "0,1024,0.001", - "0,360,0.01", - "0,1024,0.01", - "0,1024,0.01", - "0,1,0.01", - "0,128,0.01", - "0,1,0.01", -}; - -void Particles2D::set_emitting(bool p_emitting) { - - if (emitting == p_emitting) - return; - - if (p_emitting) { - - if (active_count == 0) - time = 0; - set_process(process_mode == PROCESS_IDLE); - set_fixed_process(process_mode == PROCESS_FIXED); - time_to_live = emit_timeout; - }; - emitting = p_emitting; - _change_notify("config/emitting"); + speed_scale = p_scale; + VS::get_singleton()->particles_set_speed_scale(particles, p_scale); } bool Particles2D::is_emitting() const { return emitting; } - -void Particles2D::set_process_mode(ProcessMode p_mode) { - - process_mode = p_mode; - const bool should_process = emitting || active_count != 0; - set_process(should_process && process_mode == PROCESS_IDLE); - set_fixed_process(should_process && process_mode == PROCESS_FIXED); -} - -Particles2D::ProcessMode Particles2D::get_process_mode() const { - - return process_mode; -} - -void Particles2D::set_amount(int p_amount) { - - ERR_FAIL_INDEX(p_amount, 1024 + 1); - - particles.resize(p_amount); -} int Particles2D::get_amount() const { - return particles.size(); -} - -void Particles2D::set_emit_timeout(float p_timeout) { - - emit_timeout = p_timeout; - time_to_live = p_timeout; -}; - -float Particles2D::get_emit_timeout() const { - - return emit_timeout; -}; - -void Particles2D::set_lifetime(float p_lifetime) { - - ERR_FAIL_INDEX(p_lifetime, 3600 + 1); - - lifetime = p_lifetime; + return amount; } float Particles2D::get_lifetime() const { return lifetime; } -void Particles2D::set_time_scale(float p_time_scale) { - - time_scale = p_time_scale; -} -float Particles2D::get_time_scale() const { +bool Particles2D::get_one_shot() const { - return time_scale; + return one_shot; } - -void Particles2D::set_pre_process_time(float p_pre_process_time) { - - preprocess = p_pre_process_time; -} - float Particles2D::get_pre_process_time() const { - return preprocess; -} - -void Particles2D::set_param(Parameter p_param, float p_value) { - - ERR_FAIL_INDEX(p_param, PARAM_MAX); - param[p_param] = p_value; + return pre_process_time; } -float Particles2D::get_param(Parameter p_param) const { +float Particles2D::get_explosiveness_ratio() const { - ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); - return param[p_param]; + return explosiveness_ratio; } +float Particles2D::get_randomness_ratio() const { -void Particles2D::set_randomness(Parameter p_param, float p_value) { - - ERR_FAIL_INDEX(p_param, PARAM_MAX); - randomness[p_param] = p_value; + return randomness_ratio; } -float Particles2D::get_randomness(Parameter p_param) const { +Rect2 Particles2D::get_visibility_rect() const { - ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); - return randomness[p_param]; + return visibility_rect; } +bool Particles2D::get_use_local_coordinates() const { -void Particles2D::set_texture(const Ref<Texture> &p_texture) { - - texture = p_texture; + return local_coords; } +Ref<Material> Particles2D::get_process_material() const { -Ref<Texture> Particles2D::get_texture() const { - - return texture; + return process_material; } -void Particles2D::set_color(const Color &p_color) { +float Particles2D::get_speed_scale() const { - default_color = p_color; + return speed_scale; } -Color Particles2D::get_color() const { +void Particles2D::set_draw_order(DrawOrder p_order) { - return default_color; + draw_order = p_order; + VS::get_singleton()->particles_set_draw_order(particles, VS::ParticlesDrawOrder(p_order)); } -void Particles2D::set_color_ramp(const Ref<ColorRamp> &p_color_ramp) { +Particles2D::DrawOrder Particles2D::get_draw_order() const { - color_ramp = p_color_ramp; + return draw_order; } -Ref<ColorRamp> Particles2D::get_color_ramp() const { - - return color_ramp; +void Particles2D::set_fixed_fps(int p_count) { + fixed_fps = p_count; + VS::get_singleton()->particles_set_fixed_fps(particles, p_count); } -void Particles2D::set_emissor_offset(const Point2 &p_offset) { - - emissor_offset = p_offset; +int Particles2D::get_fixed_fps() const { + return fixed_fps; } -Point2 Particles2D::get_emissor_offset() const { - - return emissor_offset; +void Particles2D::set_fractional_delta(bool p_enable) { + fractional_delta = p_enable; + VS::get_singleton()->particles_set_fractional_delta(particles, p_enable); } -void Particles2D::set_use_local_space(bool p_use) { - - local_space = p_use; +bool Particles2D::get_fractional_delta() const { + return fractional_delta; } -bool Particles2D::is_using_local_space() const { - - return local_space; -} - -//Deprecated. Converts color phases to color ramp -void Particles2D::set_color_phases(int p_phases) { - - //Create color ramp if we have 2 or more phases. - //Otherwise first phase phase will be assigned to default color. - if (p_phases > 1 && color_ramp.is_null()) { - color_ramp = Ref<ColorRamp>(memnew(ColorRamp())); - } - if (color_ramp.is_valid()) { - color_ramp->get_points().resize(p_phases); - } -} - -//Deprecated. -int Particles2D::get_color_phases() const { - - if (color_ramp.is_valid()) { - return color_ramp->get_points_count(); - } - return 0; -} - -//Deprecated. Converts color phases to color ramp -void Particles2D::set_color_phase_color(int p_phase, const Color &p_color) { - - ERR_FAIL_INDEX(p_phase, MAX_COLOR_PHASES); - if (color_ramp.is_valid()) { - if (color_ramp->get_points_count() > p_phase) - color_ramp->set_color(p_phase, p_color); - } else { - if (p_phase == 0) - default_color = p_color; - } -} - -//Deprecated. -Color Particles2D::get_color_phase_color(int p_phase) const { - - ERR_FAIL_INDEX_V(p_phase, MAX_COLOR_PHASES, Color()); - if (color_ramp.is_valid()) { - return color_ramp->get_color(p_phase); - } - return Color(0, 0, 0, 1); -} - -//Deprecated. Converts color phases to color ramp -void Particles2D::set_color_phase_pos(int p_phase, float p_pos) { - ERR_FAIL_INDEX(p_phase, MAX_COLOR_PHASES); - ERR_FAIL_COND(p_pos < 0.0 || p_pos > 1.0); - if (color_ramp.is_valid() && color_ramp->get_points_count() > p_phase) { - return color_ramp->set_offset(p_phase, p_pos); - } -} +String Particles2D::get_configuration_warning() const { -//Deprecated. -float Particles2D::get_color_phase_pos(int p_phase) const { + String warnings; - ERR_FAIL_INDEX_V(p_phase, MAX_COLOR_PHASES, 0); - if (color_ramp.is_valid()) { - return color_ramp->get_offset(p_phase); + if (process_material.is_null()) { + if (warnings != String()) + warnings += "\n"; + warnings += "- " + TTR("A material to process the particles is not assigned, so no behavior is imprinted."); } - return 0; -} - -void Particles2D::set_emission_half_extents(const Vector2 &p_extents) { - - extents = p_extents; -} -Vector2 Particles2D::get_emission_half_extents() const { - - return extents; + return warnings; } -void Particles2D::set_initial_velocity(const Vector2 &p_velocity) { +Rect2 Particles2D::capture_rect() const { - initial_velocity = p_velocity; + Rect3 aabb = VS::get_singleton()->particles_get_current_aabb(particles); + Rect2 r; + r.position.x = aabb.position.x; + r.position.y = aabb.position.y; + r.size.x = aabb.size.x; + r.size.y = aabb.size.y; + return r; } -Vector2 Particles2D::get_initial_velocity() const { - return initial_velocity; +void Particles2D::set_texture(const Ref<Texture> &p_texture) { + texture = p_texture; + update(); } -void Particles2D::pre_process(float p_delta) { - - _process_particles(p_delta); +Ref<Texture> Particles2D::get_texture() const { + return texture; } -void Particles2D::set_explosiveness(float p_value) { +void Particles2D::set_normal_map(const Ref<Texture> &p_normal_map) { - explosiveness = p_value; + normal_map = p_normal_map; + update(); } -float Particles2D::get_explosiveness() const { - - return explosiveness; +Ref<Texture> Particles2D::get_normal_map() const { + return normal_map; } -void Particles2D::set_flip_h(bool p_flip) { - - flip_h = p_flip; +void Particles2D::_validate_property(PropertyInfo &property) const { } -bool Particles2D::is_flipped_h() const { +void Particles2D::set_v_frames(int p_count) { - return flip_h; + ERR_FAIL_COND(p_count < 1); + v_frames = p_count; + update(); } -void Particles2D::set_flip_v(bool p_flip) { - - flip_v = p_flip; -} -bool Particles2D::is_flipped_v() const { +int Particles2D::get_v_frames() const { - return flip_v; + return v_frames; } -void Particles2D::set_h_frames(int p_frames) { +void Particles2D::set_h_frames(int p_count) { - ERR_FAIL_COND(p_frames < 1); - h_frames = p_frames; + ERR_FAIL_COND(p_count < 1); + h_frames = p_count; + update(); } int Particles2D::get_h_frames() const { @@ -931,215 +277,143 @@ int Particles2D::get_h_frames() const { return h_frames; } -void Particles2D::set_v_frames(int p_frames) { - - ERR_FAIL_COND(p_frames < 1); - v_frames = p_frames; +void Particles2D::restart() { + VS::get_singleton()->particles_restart(particles); } -int Particles2D::get_v_frames() const { - return v_frames; -} +void Particles2D::_notification(int p_what) { -void Particles2D::set_emission_points(const PoolVector<Vector2> &p_points) { + if (p_what == NOTIFICATION_DRAW) { - emission_points = p_points; -} + RID texture_rid; + if (texture.is_valid()) + texture_rid = texture->get_rid(); + RID normal_rid; + if (normal_map.is_valid()) + normal_rid = texture->get_rid(); -PoolVector<Vector2> Particles2D::get_emission_points() const { + VS::get_singleton()->canvas_item_add_particles(get_canvas_item(), particles, texture_rid, normal_rid, h_frames, v_frames); - return emission_points; -} +#ifdef TOOLS_ENABLED + if (get_tree()->is_editor_hint() && (this == get_tree()->get_edited_scene_root() || get_tree()->get_edited_scene_root()->is_a_parent_of(this))) { + + draw_rect(visibility_rect, Color(0, 0.7, 0.9, 0.4), false); + } +#endif + } + + if (p_what == NOTIFICATION_PAUSED || p_what == NOTIFICATION_UNPAUSED) { + if (can_process()) { + VS::get_singleton()->particles_set_speed_scale(particles, speed_scale); + } else { -void Particles2D::reset() { + VS::get_singleton()->particles_set_speed_scale(particles, 0); + } + } - for (int i = 0; i < particles.size(); i++) { - particles[i].active = false; + if (p_what == NOTIFICATION_TRANSFORM_CHANGED) { + _update_particle_emission_transform(); } - time = 0; - active_count = 0; } void Particles2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_emitting", "active"), &Particles2D::set_emitting); - ClassDB::bind_method(D_METHOD("is_emitting"), &Particles2D::is_emitting); - - ClassDB::bind_method(D_METHOD("set_process_mode", "mode"), &Particles2D::set_process_mode); - ClassDB::bind_method(D_METHOD("get_process_mode"), &Particles2D::get_process_mode); - + ClassDB::bind_method(D_METHOD("set_emitting", "emitting"), &Particles2D::set_emitting); ClassDB::bind_method(D_METHOD("set_amount", "amount"), &Particles2D::set_amount); - ClassDB::bind_method(D_METHOD("get_amount"), &Particles2D::get_amount); + ClassDB::bind_method(D_METHOD("set_lifetime", "secs"), &Particles2D::set_lifetime); + ClassDB::bind_method(D_METHOD("set_one_shot", "secs"), &Particles2D::set_one_shot); + ClassDB::bind_method(D_METHOD("set_pre_process_time", "secs"), &Particles2D::set_pre_process_time); + ClassDB::bind_method(D_METHOD("set_explosiveness_ratio", "ratio"), &Particles2D::set_explosiveness_ratio); + ClassDB::bind_method(D_METHOD("set_randomness_ratio", "ratio"), &Particles2D::set_randomness_ratio); + ClassDB::bind_method(D_METHOD("set_visibility_rect", "aabb"), &Particles2D::set_visibility_rect); + ClassDB::bind_method(D_METHOD("set_use_local_coordinates", "enable"), &Particles2D::set_use_local_coordinates); + ClassDB::bind_method(D_METHOD("set_fixed_fps", "fps"), &Particles2D::set_fixed_fps); + ClassDB::bind_method(D_METHOD("set_fractional_delta", "enable"), &Particles2D::set_fractional_delta); + ClassDB::bind_method(D_METHOD("set_process_material", "material"), &Particles2D::set_process_material); + ClassDB::bind_method(D_METHOD("set_speed_scale", "scale"), &Particles2D::set_speed_scale); - ClassDB::bind_method(D_METHOD("set_lifetime", "lifetime"), &Particles2D::set_lifetime); + ClassDB::bind_method(D_METHOD("is_emitting"), &Particles2D::is_emitting); + ClassDB::bind_method(D_METHOD("get_amount"), &Particles2D::get_amount); ClassDB::bind_method(D_METHOD("get_lifetime"), &Particles2D::get_lifetime); - - ClassDB::bind_method(D_METHOD("set_time_scale", "time_scale"), &Particles2D::set_time_scale); - ClassDB::bind_method(D_METHOD("get_time_scale"), &Particles2D::get_time_scale); - - ClassDB::bind_method(D_METHOD("set_pre_process_time", "time"), &Particles2D::set_pre_process_time); + ClassDB::bind_method(D_METHOD("get_one_shot"), &Particles2D::get_one_shot); ClassDB::bind_method(D_METHOD("get_pre_process_time"), &Particles2D::get_pre_process_time); + ClassDB::bind_method(D_METHOD("get_explosiveness_ratio"), &Particles2D::get_explosiveness_ratio); + ClassDB::bind_method(D_METHOD("get_randomness_ratio"), &Particles2D::get_randomness_ratio); + ClassDB::bind_method(D_METHOD("get_visibility_rect"), &Particles2D::get_visibility_rect); + ClassDB::bind_method(D_METHOD("get_use_local_coordinates"), &Particles2D::get_use_local_coordinates); + ClassDB::bind_method(D_METHOD("get_fixed_fps"), &Particles2D::get_fixed_fps); + ClassDB::bind_method(D_METHOD("get_fractional_delta"), &Particles2D::get_fractional_delta); + ClassDB::bind_method(D_METHOD("get_process_material"), &Particles2D::get_process_material); + ClassDB::bind_method(D_METHOD("get_speed_scale"), &Particles2D::get_speed_scale); - ClassDB::bind_method(D_METHOD("set_emit_timeout", "value"), &Particles2D::set_emit_timeout); - ClassDB::bind_method(D_METHOD("get_emit_timeout"), &Particles2D::get_emit_timeout); - - ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &Particles2D::set_param); - ClassDB::bind_method(D_METHOD("get_param", "param"), &Particles2D::get_param); - - ClassDB::bind_method(D_METHOD("set_randomness", "param", "value"), &Particles2D::set_randomness); - ClassDB::bind_method(D_METHOD("get_randomness", "param"), &Particles2D::get_randomness); + ClassDB::bind_method(D_METHOD("set_draw_order", "order"), &Particles2D::set_draw_order); + ClassDB::bind_method(D_METHOD("get_draw_order"), &Particles2D::get_draw_order); - ClassDB::bind_method(D_METHOD("set_texture:Texture", "texture"), &Particles2D::set_texture); - ClassDB::bind_method(D_METHOD("get_texture:Texture"), &Particles2D::get_texture); + ClassDB::bind_method(D_METHOD("set_texture", "texture"), &Particles2D::set_texture); + ClassDB::bind_method(D_METHOD("get_texture"), &Particles2D::get_texture); - ClassDB::bind_method(D_METHOD("set_color", "color"), &Particles2D::set_color); - ClassDB::bind_method(D_METHOD("get_color"), &Particles2D::get_color); + ClassDB::bind_method(D_METHOD("set_normal_map", "texture"), &Particles2D::set_normal_map); + ClassDB::bind_method(D_METHOD("get_normal_map"), &Particles2D::get_normal_map); - ClassDB::bind_method(D_METHOD("set_color_ramp:ColorRamp", "color_ramp"), &Particles2D::set_color_ramp); - ClassDB::bind_method(D_METHOD("get_color_ramp:ColorRamp"), &Particles2D::get_color_ramp); - - ClassDB::bind_method(D_METHOD("set_emissor_offset", "offset"), &Particles2D::set_emissor_offset); - ClassDB::bind_method(D_METHOD("get_emissor_offset"), &Particles2D::get_emissor_offset); - - ClassDB::bind_method(D_METHOD("set_flip_h", "enable"), &Particles2D::set_flip_h); - ClassDB::bind_method(D_METHOD("is_flipped_h"), &Particles2D::is_flipped_h); - - ClassDB::bind_method(D_METHOD("set_flip_v", "enable"), &Particles2D::set_flip_v); - ClassDB::bind_method(D_METHOD("is_flipped_v"), &Particles2D::is_flipped_v); - - ClassDB::bind_method(D_METHOD("set_h_frames", "enable"), &Particles2D::set_h_frames); - ClassDB::bind_method(D_METHOD("get_h_frames"), &Particles2D::get_h_frames); + ClassDB::bind_method(D_METHOD("capture_rect"), &Particles2D::capture_rect); - ClassDB::bind_method(D_METHOD("set_v_frames", "enable"), &Particles2D::set_v_frames); + ClassDB::bind_method(D_METHOD("set_v_frames", "frames"), &Particles2D::set_v_frames); ClassDB::bind_method(D_METHOD("get_v_frames"), &Particles2D::get_v_frames); - ClassDB::bind_method(D_METHOD("set_emission_half_extents", "extents"), &Particles2D::set_emission_half_extents); - ClassDB::bind_method(D_METHOD("get_emission_half_extents"), &Particles2D::get_emission_half_extents); - - ClassDB::bind_method(D_METHOD("set_color_phases", "phases"), &Particles2D::set_color_phases); - ClassDB::bind_method(D_METHOD("get_color_phases"), &Particles2D::get_color_phases); - - ClassDB::bind_method(D_METHOD("set_color_phase_color", "phase", "color"), &Particles2D::set_color_phase_color); - ClassDB::bind_method(D_METHOD("get_color_phase_color", "phase"), &Particles2D::get_color_phase_color); - - ClassDB::bind_method(D_METHOD("set_color_phase_pos", "phase", "pos"), &Particles2D::set_color_phase_pos); - ClassDB::bind_method(D_METHOD("get_color_phase_pos", "phase"), &Particles2D::get_color_phase_pos); - - ClassDB::bind_method(D_METHOD("pre_process", "time"), &Particles2D::pre_process); - ClassDB::bind_method(D_METHOD("reset"), &Particles2D::reset); - - ClassDB::bind_method(D_METHOD("set_use_local_space", "enable"), &Particles2D::set_use_local_space); - ClassDB::bind_method(D_METHOD("is_using_local_space"), &Particles2D::is_using_local_space); - - ClassDB::bind_method(D_METHOD("set_initial_velocity", "velocity"), &Particles2D::set_initial_velocity); - ClassDB::bind_method(D_METHOD("get_initial_velocity"), &Particles2D::get_initial_velocity); - - ClassDB::bind_method(D_METHOD("set_explosiveness", "amount"), &Particles2D::set_explosiveness); - ClassDB::bind_method(D_METHOD("get_explosiveness"), &Particles2D::get_explosiveness); - - ClassDB::bind_method(D_METHOD("set_emission_points", "points"), &Particles2D::set_emission_points); - ClassDB::bind_method(D_METHOD("get_emission_points"), &Particles2D::get_emission_points); - - ADD_SIGNAL(MethodInfo("emission_finished")); - - ADD_PROPERTY(PropertyInfo(Variant::INT, "config/amount", PROPERTY_HINT_EXP_RANGE, "1,1024"), "set_amount", "get_amount"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "config/lifetime", PROPERTY_HINT_EXP_RANGE, "0.1,3600,0.1"), "set_lifetime", "get_lifetime"); - ADD_PROPERTYNO(PropertyInfo(Variant::REAL, "config/time_scale", PROPERTY_HINT_EXP_RANGE, "0.01,128,0.01"), "set_time_scale", "get_time_scale"); - ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "config/preprocess", PROPERTY_HINT_EXP_RANGE, "0.1,3600,0.1"), "set_pre_process_time", "get_pre_process_time"); - ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "config/emit_timeout", PROPERTY_HINT_RANGE, "0,3600,0.1"), "set_emit_timeout", "get_emit_timeout"); - ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "config/emitting"), "set_emitting", "is_emitting"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "config/process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), "set_process_mode", "get_process_mode"); - ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "config/offset"), "set_emissor_offset", "get_emissor_offset"); - ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "config/half_extents"), "set_emission_half_extents", "get_emission_half_extents"); - ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "config/local_space"), "set_use_local_space", "is_using_local_space"); - ADD_PROPERTYNO(PropertyInfo(Variant::REAL, "config/explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness", "get_explosiveness"); - ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "config/flip_h"), "set_flip_h", "is_flipped_h"); - ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "config/flip_v"), "set_flip_v", "is_flipped_v"); - ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "config/texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture"); - ADD_PROPERTYNO(PropertyInfo(Variant::INT, "config/h_frames", PROPERTY_HINT_RANGE, "1,512,1"), "set_h_frames", "get_h_frames"); - ADD_PROPERTYNO(PropertyInfo(Variant::INT, "config/v_frames", PROPERTY_HINT_RANGE, "1,512,1"), "set_v_frames", "get_v_frames"); - - for (int i = 0; i < PARAM_MAX; i++) { - ADD_PROPERTYI(PropertyInfo(Variant::REAL, _particlesframe_property_names[i], PROPERTY_HINT_RANGE, _particlesframe_property_ranges[i]), "set_param", "get_param", i); - } - - for (int i = 0; i < PARAM_MAX; i++) { - ADD_PROPERTYINZ(PropertyInfo(Variant::REAL, _particlesframe_property_rnames[i], PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_randomness", "get_randomness", i); - } - - ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "color_phases/count", PROPERTY_HINT_RANGE, "0,4,1", 0), "set_color_phases", "get_color_phases"); - - //Backward compatibility. They will be converted to color ramp - for (int i = 0; i < MAX_COLOR_PHASES; i++) { - String phase = "phase_" + itos(i) + "/"; - ADD_PROPERTYI(PropertyInfo(Variant::REAL, phase + "pos", PROPERTY_HINT_RANGE, "0,1,0.01", 0), "set_color_phase_pos", "get_color_phase_pos", i); - ADD_PROPERTYI(PropertyInfo(Variant::COLOR, phase + "color", PROPERTY_HINT_NONE, "", 0), "set_color_phase_color", "get_color_phase_color", i); - } - - ADD_PROPERTYNO(PropertyInfo(Variant::COLOR, "color/color"), "set_color", "get_color"); - ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "color/color_ramp", PROPERTY_HINT_RESOURCE_TYPE, "ColorRamp"), "set_color_ramp", "get_color_ramp"); + ClassDB::bind_method(D_METHOD("set_h_frames", "frames"), &Particles2D::set_h_frames); + ClassDB::bind_method(D_METHOD("get_h_frames"), &Particles2D::get_h_frames); - ADD_PROPERTYNZ(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "emission_points", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_emission_points", "get_emission_points"); + ClassDB::bind_method(D_METHOD("restart"), &Particles2D::restart); - BIND_CONSTANT(PARAM_DIRECTION); - BIND_CONSTANT(PARAM_SPREAD); - BIND_CONSTANT(PARAM_LINEAR_VELOCITY); - BIND_CONSTANT(PARAM_SPIN_VELOCITY); - BIND_CONSTANT(PARAM_ORBIT_VELOCITY); - BIND_CONSTANT(PARAM_GRAVITY_DIRECTION); - BIND_CONSTANT(PARAM_GRAVITY_STRENGTH); - BIND_CONSTANT(PARAM_RADIAL_ACCEL); - BIND_CONSTANT(PARAM_TANGENTIAL_ACCEL); - BIND_CONSTANT(PARAM_DAMPING); - BIND_CONSTANT(PARAM_INITIAL_ANGLE); - BIND_CONSTANT(PARAM_INITIAL_SIZE); - BIND_CONSTANT(PARAM_FINAL_SIZE); - BIND_CONSTANT(PARAM_HUE_VARIATION); - BIND_CONSTANT(PARAM_ANIM_SPEED_SCALE); - BIND_CONSTANT(PARAM_ANIM_INITIAL_POS); - BIND_CONSTANT(PARAM_MAX); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,100000,1"), "set_amount", "get_amount"); + ADD_GROUP("Time", ""); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01"), "set_lifetime", "get_lifetime"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "preprocess", PROPERTY_HINT_RANGE, "0.00,600.0,0.01"), "set_pre_process_time", "get_pre_process_time"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "speed_scale", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_speed_scale", "get_speed_scale"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1"), "set_fixed_fps", "get_fixed_fps"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta"); + ADD_GROUP("Drawing", ""); + ADD_PROPERTY(PropertyInfo(Variant::RECT3, "visibility_rect"), "set_visibility_rect", "get_visibility_rect"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), "set_use_local_coordinates", "get_use_local_coordinates"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_order", PROPERTY_HINT_ENUM, "Index,Lifetime"), "set_draw_order", "get_draw_order"); + ADD_GROUP("Process Material", "process_"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,ParticlesMaterial"), "set_process_material", "get_process_material"); + ADD_GROUP("Textures", ""); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_normal_map", "get_normal_map"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "h_frames", PROPERTY_HINT_RANGE, "1,1024,1"), "set_h_frames", "get_h_frames"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "v_frames", PROPERTY_HINT_RANGE, "1,1024,1"), "set_v_frames", "get_v_frames"); - BIND_CONSTANT(MAX_COLOR_PHASES); + BIND_CONSTANT(DRAW_ORDER_INDEX); + BIND_CONSTANT(DRAW_ORDER_LIFETIME); } Particles2D::Particles2D() { - for (int i = 0; i < PARAM_MAX; i++) { + particles = VS::get_singleton()->particles_create(); - param[i] = 0; - randomness[i] = 0; - } - - set_param(PARAM_SPREAD, 10); - set_param(PARAM_LINEAR_VELOCITY, 20); - set_param(PARAM_GRAVITY_STRENGTH, 9.8); - set_param(PARAM_RADIAL_ACCEL, 0); - set_param(PARAM_TANGENTIAL_ACCEL, 0); - set_param(PARAM_INITIAL_ANGLE, 0.0); - set_param(PARAM_INITIAL_SIZE, 1.0); - set_param(PARAM_FINAL_SIZE, 1.0); - set_param(PARAM_ANIM_SPEED_SCALE, 1.0); - - set_color(Color(1, 1, 1, 1)); - - time = 0; - lifetime = 2; - emitting = false; - particles.resize(32); - active_count = -1; set_emitting(true); - process_mode = PROCESS_IDLE; - local_space = true; - preprocess = 0; - time_scale = 1.0; - - flip_h = false; - flip_v = false; - - v_frames = 1; + set_one_shot(false); + set_amount(8); + set_lifetime(1); + set_fixed_fps(0); + set_fractional_delta(true); + set_pre_process_time(0); + set_explosiveness_ratio(0); + set_randomness_ratio(0); + set_visibility_rect(Rect2(Vector2(-100, -100), Vector2(200, 200))); + set_use_local_coordinates(true); + set_draw_order(DRAW_ORDER_INDEX); + set_speed_scale(1); h_frames = 1; + v_frames = 1; +} + +Particles2D::~Particles2D() { - emit_timeout = 0; - time_to_live = 0; - explosiveness = 1.0; + VS::get_singleton()->free(particles); } diff --git a/scene/2d/particles_2d.h b/scene/2d/particles_2d.h index 0cf4063ce..a6ac0c37d 100644 --- a/scene/2d/particles_2d.h +++ b/scene/2d/particles_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,235 +34,102 @@ #include "scene/resources/color_ramp.h" #include "scene/resources/texture.h" -class Particles2D; -class ParticleAttractor2D : public Node2D { - - GDCLASS(ParticleAttractor2D, Node2D); - - friend class Particles2D; - bool enabled; - float radius; - float disable_radius; - float gravity; - float absorption; - NodePath path; - - Particles2D *owner; - - void _update_owner(); - void _owner_exited(); - void _set_owner(Particles2D *p_owner); - - void _notification(int p_what); - static void _bind_methods(); - -public: - void set_enabled(bool p_enabled); - bool is_enabled() const; - - void set_radius(float p_radius); - float get_radius() const; - - void set_disable_radius(float p_disable_radius); - float get_disable_radius() const; - - void set_gravity(float p_gravity); - float get_gravity() const; - - void set_absorption(float p_absorption); - float get_absorption() const; - - void set_particles_path(NodePath p_path); - NodePath get_particles_path() const; - - virtual String get_configuration_warning() const; - - ParticleAttractor2D(); -}; - class Particles2D : public Node2D { - - GDCLASS(Particles2D, Node2D); +private: + GDCLASS(Particles2D, Node2D) public: - enum Parameter { - PARAM_DIRECTION, - PARAM_SPREAD, - PARAM_LINEAR_VELOCITY, - PARAM_SPIN_VELOCITY, - PARAM_ORBIT_VELOCITY, - PARAM_GRAVITY_DIRECTION, - PARAM_GRAVITY_STRENGTH, - PARAM_RADIAL_ACCEL, - PARAM_TANGENTIAL_ACCEL, - PARAM_DAMPING, - PARAM_INITIAL_ANGLE, - PARAM_INITIAL_SIZE, - PARAM_FINAL_SIZE, - PARAM_HUE_VARIATION, - PARAM_ANIM_SPEED_SCALE, - PARAM_ANIM_INITIAL_POS, - PARAM_MAX - }; - - enum { - MAX_COLOR_PHASES = 4 - }; - - enum ProcessMode { - PROCESS_FIXED, - PROCESS_IDLE, + enum DrawOrder { + DRAW_ORDER_INDEX, + DRAW_ORDER_LIFETIME, }; private: - float param[PARAM_MAX]; - float randomness[PARAM_MAX]; + RID particles; - struct Particle { - bool active; - Point2 pos; - Vector2 velocity; - float rot; - float frame; - uint64_t seed; - Particle() { - active = false; - seed = 123465789; - rot = 0; - frame = 0; - } - }; - - Vector<Particle> particles; - - struct AttractorCache { - - Vector2 pos; - ParticleAttractor2D *attractor; - }; - - Vector<AttractorCache> attractor_cache; - - float explosiveness; - float preprocess; - float lifetime; bool emitting; - bool local_space; - float emit_timeout; - float time_to_live; - float time_scale; - bool flip_h; - bool flip_v; - int h_frames; + bool one_shot; + int amount; + float lifetime; + float pre_process_time; + float explosiveness_ratio; + float randomness_ratio; + float speed_scale; + Rect2 visibility_rect; + bool local_coords; + int fixed_fps; + bool fractional_delta; int v_frames; - Point2 emissor_offset; - Vector2 initial_velocity; - Vector2 extents; - PoolVector<Vector2> emission_points; + int h_frames; - ProcessMode process_mode; + Ref<Material> process_material; - float time; - int active_count; + DrawOrder draw_order; Ref<Texture> texture; + Ref<Texture> normal_map; - //If no color ramp is set then default color is used. Created as simple alternative to color_ramp. - Color default_color; - Ref<ColorRamp> color_ramp; - - void _process_particles(float p_delta); - friend class ParticleAttractor2D; - - Set<ParticleAttractor2D *> attractors; + void _update_particle_emission_transform(); protected: - void _notification(int p_what); static void _bind_methods(); + virtual void _validate_property(PropertyInfo &property) const; + void _notification(int p_what); public: void set_emitting(bool p_emitting); - bool is_emitting() const; - - void set_process_mode(ProcessMode p_mode); - ProcessMode get_process_mode() const; - void set_amount(int p_amount); - int get_amount() const; - void set_lifetime(float p_lifetime); - float get_lifetime() const; - - void set_time_scale(float p_time_scale); - float get_time_scale() const; + void set_one_shot(bool p_enable); + void set_pre_process_time(float p_time); + void set_explosiveness_ratio(float p_ratio); + void set_randomness_ratio(float p_ratio); + void set_visibility_rect(const Rect2 &p_aabb); + void set_use_local_coordinates(bool p_enable); + void set_process_material(const Ref<Material> &p_material); + void set_speed_scale(float p_scale); - void set_pre_process_time(float p_pre_process_time); + bool is_emitting() const; + int get_amount() const; + float get_lifetime() const; + bool get_one_shot() const; float get_pre_process_time() const; + float get_explosiveness_ratio() const; + float get_randomness_ratio() const; + Rect2 get_visibility_rect() const; + bool get_use_local_coordinates() const; + Ref<Material> get_process_material() const; + float get_speed_scale() const; - void set_emit_timeout(float p_timeout); - float get_emit_timeout() const; - - void set_emission_half_extents(const Vector2 &p_extents); - Vector2 get_emission_half_extents() const; + void set_fixed_fps(int p_count); + int get_fixed_fps() const; - void set_param(Parameter p_param, float p_value); - float get_param(Parameter p_param) const; + void set_fractional_delta(bool p_enable); + bool get_fractional_delta() const; - void set_randomness(Parameter p_randomness, float p_value); - float get_randomness(Parameter p_randomness) const; - - void set_explosiveness(float p_value); - float get_explosiveness() const; - - void set_flip_h(bool p_flip); - bool is_flipped_h() const; - - void set_flip_v(bool p_flip); - bool is_flipped_v() const; - - void set_h_frames(int p_frames); - int get_h_frames() const; - - void set_v_frames(int p_frames); - int get_v_frames() const; - - void set_color_phases(int p_phases); - int get_color_phases() const; - - void set_color_phase_color(int p_phase, const Color &p_color); - Color get_color_phase_color(int p_phase) const; - - void set_color_phase_pos(int p_phase, float p_pos); - float get_color_phase_pos(int p_phase) const; + void set_draw_order(DrawOrder p_order); + DrawOrder get_draw_order() const; void set_texture(const Ref<Texture> &p_texture); Ref<Texture> get_texture() const; - void set_color(const Color &p_color); - Color get_color() const; - - void set_color_ramp(const Ref<ColorRamp> &p_texture); - Ref<ColorRamp> get_color_ramp() const; - - void set_emissor_offset(const Point2 &p_offset); - Point2 get_emissor_offset() const; + void set_normal_map(const Ref<Texture> &p_normal_map); + Ref<Texture> get_normal_map() const; - void set_use_local_space(bool p_use); - bool is_using_local_space() const; - - void set_initial_velocity(const Vector2 &p_velocity); - Vector2 get_initial_velocity() const; + virtual String get_configuration_warning() const; - void set_emission_points(const PoolVector<Vector2> &p_points); - PoolVector<Vector2> get_emission_points() const; + void set_v_frames(int p_count); + int get_v_frames() const; - void pre_process(float p_delta); - void reset(); + void set_h_frames(int p_count); + int get_h_frames() const; + void restart(); + Rect2 capture_rect() const; Particles2D(); + ~Particles2D(); }; -VARIANT_ENUM_CAST(Particles2D::ProcessMode); -VARIANT_ENUM_CAST(Particles2D::Parameter); +VARIANT_ENUM_CAST(Particles2D::DrawOrder) #endif // PARTICLES_FRAME_H diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp index 9e8be7fa1..6b30e97de 100644 --- a/scene/2d/path_2d.cpp +++ b/scene/2d/path_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -81,8 +82,8 @@ Ref<Curve2D> Path2D::get_curve() const { void Path2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_curve", "curve:Curve2D"), &Path2D::set_curve); - ClassDB::bind_method(D_METHOD("get_curve:Curve2D", "curve"), &Path2D::get_curve); + ClassDB::bind_method(D_METHOD("set_curve", "curve"), &Path2D::set_curve); + ClassDB::bind_method(D_METHOD("get_curve"), &Path2D::get_curve); ClassDB::bind_method(D_METHOD("_curve_changed"), &Path2D::_curve_changed); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve2D"), "set_curve", "get_curve"); diff --git a/scene/2d/path_2d.h b/scene/2d/path_2d.h index 7357b6810..e80817cd3 100644 --- a/scene/2d/path_2d.h +++ b/scene/2d/path_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -95,7 +96,7 @@ public: void set_loop(bool p_loop); bool has_loop() const; - void set_rotate(bool p_enabled); + void set_rotate(bool p_rotate); bool is_rotating() const; void set_cubic_interpolation(bool p_enable); diff --git a/scene/2d/path_texture.cpp b/scene/2d/path_texture.cpp index 60efccec3..e06c79dab 100644 --- a/scene/2d/path_texture.cpp +++ b/scene/2d/path_texture.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/path_texture.h b/scene/2d/path_texture.h index 8d5adc49c..163e914e4 100644 --- a/scene/2d/path_texture.h +++ b/scene/2d/path_texture.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 88845a729..6ec164213 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -43,28 +44,6 @@ void PhysicsBody2D::_notification(int p_what) { */ } -void PhysicsBody2D::set_one_way_collision_direction(const Vector2 &p_dir) { - - one_way_collision_direction = p_dir; - Physics2DServer::get_singleton()->body_set_one_way_collision_direction(get_rid(), p_dir); -} - -Vector2 PhysicsBody2D::get_one_way_collision_direction() const { - - return one_way_collision_direction; -} - -void PhysicsBody2D::set_one_way_collision_max_depth(float p_depth) { - - one_way_collision_max_depth = p_depth; - Physics2DServer::get_singleton()->body_set_one_way_collision_max_depth(get_rid(), p_depth); -} - -float PhysicsBody2D::get_one_way_collision_max_depth() const { - - return one_way_collision_max_depth; -} - void PhysicsBody2D::_set_layers(uint32_t p_mask) { set_collision_layer(p_mask); @@ -78,7 +57,7 @@ uint32_t PhysicsBody2D::_get_layers() const { void PhysicsBody2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_collision_layer", "mask"), &PhysicsBody2D::set_collision_layer); + ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &PhysicsBody2D::set_collision_layer); ClassDB::bind_method(D_METHOD("get_collision_layer"), &PhysicsBody2D::get_collision_layer); ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &PhysicsBody2D::set_collision_mask); ClassDB::bind_method(D_METHOD("get_collision_mask"), &PhysicsBody2D::get_collision_mask); @@ -91,31 +70,24 @@ void PhysicsBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_layers", "mask"), &PhysicsBody2D::_set_layers); ClassDB::bind_method(D_METHOD("_get_layers"), &PhysicsBody2D::_get_layers); - ClassDB::bind_method(D_METHOD("set_one_way_collision_direction", "dir"), &PhysicsBody2D::set_one_way_collision_direction); - ClassDB::bind_method(D_METHOD("get_one_way_collision_direction"), &PhysicsBody2D::get_one_way_collision_direction); - ClassDB::bind_method(D_METHOD("set_one_way_collision_max_depth", "depth"), &PhysicsBody2D::set_one_way_collision_max_depth); - ClassDB::bind_method(D_METHOD("get_one_way_collision_max_depth"), &PhysicsBody2D::get_one_way_collision_max_depth); - ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body:PhysicsBody2D"), &PhysicsBody2D::add_collision_exception_with); - ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body:PhysicsBody2D"), &PhysicsBody2D::remove_collision_exception_with); + ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &PhysicsBody2D::add_collision_exception_with); + ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &PhysicsBody2D::remove_collision_exception_with); ADD_PROPERTY(PropertyInfo(Variant::INT, "layers", PROPERTY_HINT_LAYERS_2D_PHYSICS, "", 0), "_set_layers", "_get_layers"); //for backwards compat ADD_GROUP("Collision", "collision_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_layer", "get_collision_layer"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask"); - ADD_GROUP("", ""); - ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "one_way_collision/direction"), "set_one_way_collision_direction", "get_one_way_collision_direction"); - ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "one_way_collision/max_depth"), "set_one_way_collision_max_depth", "get_one_way_collision_max_depth"); } -void PhysicsBody2D::set_collision_layer(uint32_t p_mask) { +void PhysicsBody2D::set_collision_layer(uint32_t p_layer) { - mask = p_mask; - Physics2DServer::get_singleton()->body_set_layer_mask(get_rid(), p_mask); + collision_layer = p_layer; + Physics2DServer::get_singleton()->body_set_collision_layer(get_rid(), p_layer); } uint32_t PhysicsBody2D::get_collision_layer() const { - return mask; + return collision_layer; } void PhysicsBody2D::set_collision_mask(uint32_t p_mask) { @@ -145,12 +117,12 @@ bool PhysicsBody2D::get_collision_mask_bit(int p_bit) const { void PhysicsBody2D::set_collision_layer_bit(int p_bit, bool p_value) { - uint32_t mask = get_collision_layer(); + uint32_t collision_layer = get_collision_layer(); if (p_value) - mask |= 1 << p_bit; + collision_layer |= 1 << p_bit; else - mask &= ~(1 << p_bit); - set_collision_layer(mask); + collision_layer &= ~(1 << p_bit); + set_collision_layer(collision_layer); } bool PhysicsBody2D::get_collision_layer_bit(int p_bit) const { @@ -161,9 +133,8 @@ bool PhysicsBody2D::get_collision_layer_bit(int p_bit) const { PhysicsBody2D::PhysicsBody2D(Physics2DServer::BodyMode p_mode) : CollisionObject2D(Physics2DServer::get_singleton()->body_create(p_mode), false) { - mask = 1; + collision_layer = 1; collision_mask = 1; - set_one_way_collision_max_depth(0); set_pickable(false); } @@ -583,11 +554,12 @@ real_t RigidBody2D::get_inertia() const { void RigidBody2D::set_weight(real_t p_weight) { - set_mass(p_weight / 9.8); + set_mass(p_weight / real_t(GLOBAL_DEF("physics/2d/default_gravity", 98)) / 10); } + real_t RigidBody2D::get_weight() const { - return mass * 9.8; + return mass * real_t(GLOBAL_DEF("physics/2d/default_gravity", 98)) / 10; } void RigidBody2D::set_friction(real_t p_friction) { @@ -826,6 +798,40 @@ bool RigidBody2D::is_contact_monitor_enabled() const { return contact_monitor != NULL; } +void RigidBody2D::_notification(int p_what) { + +#ifdef TOOLS_ENABLED + if (p_what == NOTIFICATION_ENTER_TREE) { + if (get_tree()->is_editor_hint()) { + set_notify_local_transform(true); //used for warnings and only in editor + } + } + + if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) { + if (get_tree()->is_editor_hint()) { + update_configuration_warning(); + } + } + +#endif +} + +String RigidBody2D::get_configuration_warning() const { + + Transform2D t = get_transform(); + + String warning = CollisionObject2D::get_configuration_warning(); + + if ((get_mode() == MODE_RIGID || get_mode() == MODE_CHARACTER) && (ABS(t.elements[0].length() - 1.0) > 0.05 || ABS(t.elements[1].length() - 1.0) > 0.05)) { + if (warning != String()) { + warning += "\n"; + } + warning += TTR("Size changes to RigidBody2D (in character or rigid modes) will be overriden by the physics engine when running.\nChange the size in children collision shapes instead."); + } + + return warning; +} + void RigidBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_mode", "mode"), &RigidBody2D::set_mode); @@ -890,7 +896,7 @@ void RigidBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &RigidBody2D::set_can_sleep); ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &RigidBody2D::is_able_to_sleep); - ClassDB::bind_method(D_METHOD("test_motion", "motion", "margin", "result:Physics2DTestMotionResult"), &RigidBody2D::_test_motion, DEFVAL(0.08), DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("test_motion", "motion", "margin", "result"), &RigidBody2D::_test_motion, DEFVAL(0.08), DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("_direct_state_changed"), &RigidBody2D::_direct_state_changed); ClassDB::bind_method(D_METHOD("_body_enter_tree"), &RigidBody2D::_body_enter_tree); @@ -970,247 +976,106 @@ RigidBody2D::~RigidBody2D() { ////////////////////////// -Variant KinematicBody2D::_get_collider() const { - - ObjectID oid = get_collider(); - if (oid == 0) - return Variant(); - Object *obj = ObjectDB::get_instance(oid); - if (!obj) - return Variant(); - - Reference *ref = obj->cast_to<Reference>(); - if (ref) { - return Ref<Reference>(ref); - } - - return obj; -} +Dictionary KinematicBody2D::_move(const Vector2 &p_motion) { -void KinematicBody2D::revert_motion() { + Collision col; + if (move(p_motion, col)) { + Dictionary d; + d["position"] = col.collision; + d["normal"] = col.normal; + d["local_shape"] = col.local_shape; + d["travel"] = col.travel; + d["remainder"] = col.remainder; + d["collider_id"] = col.collider; + d["collider_velocity"] = col.collider_vel; + if (col.collider) { + d["collider"] = ObjectDB::get_instance(col.collider); + } else { + d["collider"] = Variant(); + } - Transform2D gt = get_global_transform(); - gt.elements[2] -= travel; - travel = Vector2(); - set_global_transform(gt); -} + d["collider_shape_index"] = col.collider_shape; + d["collider_metadata"] = col.collider_metadata; -Vector2 KinematicBody2D::get_travel() const { + return d; - return travel; + } else { + return Dictionary(); + } } -Vector2 KinematicBody2D::move(const Vector2 &p_motion) { - -#if 1 +bool KinematicBody2D::move(const Vector2 &p_motion, Collision &r_collision) { Transform2D gt = get_global_transform(); Physics2DServer::MotionResult result; - colliding = Physics2DServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, margin, &result); - - collider_metadata = result.collider_metadata; - collider_shape = result.collider_shape; - collider_vel = result.collider_velocity; - collision = result.collision_point; - normal = result.collision_normal; - collider = result.collider_id; - - gt.elements[2] += result.motion; - set_global_transform(gt); - travel = result.motion; - - return result.remainder; - -#else - //give me back regular physics engine logic - //this is madness - //and most people using this function will think - //what it does is simpler than using physics - //this took about a week to get right.. - //but is it right? who knows at this point.. - - colliding = false; - ERR_FAIL_COND_V(!is_inside_tree(), Vector2()); - Physics2DDirectSpaceState *dss = Physics2DServer::get_singleton()->space_get_direct_state(get_world_2d()->get_space()); - ERR_FAIL_COND_V(!dss, Vector2()); - const int max_shapes = 32; - Vector2 sr[max_shapes * 2]; - int res_shapes; - - Set<RID> exclude; - exclude.insert(get_rid()); - - //recover first - int recover_attempts = 4; - - bool collided = false; - uint32_t mask = 0; - if (true) - mask |= Physics2DDirectSpaceState::TYPE_MASK_STATIC_BODY; - if (true) - mask |= Physics2DDirectSpaceState::TYPE_MASK_KINEMATIC_BODY; - if (true) - mask |= Physics2DDirectSpaceState::TYPE_MASK_RIGID_BODY; - if (true) - mask |= Physics2DDirectSpaceState::TYPE_MASK_CHARACTER_BODY; - - //print_line("margin: "+rtos(margin)); - do { - - //motion recover - for (int i = 0; i < get_shape_count(); i++) { - - if (is_shape_set_as_trigger(i)) - continue; - if (dss->collide_shape(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i), Vector2(), margin, sr, max_shapes, res_shapes, exclude, get_layer_mask(), mask)) - collided = true; - } - - if (!collided) - break; - - Vector2 recover_motion; - - for (int i = 0; i < res_shapes; i++) { - - Vector2 a = sr[i * 2 + 0]; - Vector2 b = sr[i * 2 + 1]; - - float d = a.distance_to(b); - - /* - if (d<margin) - continue; - */ - recover_motion += (b - a) * 0.4; - } - - if (recover_motion == Vector2()) { - collided = false; - break; - } - - Transform2D gt = get_global_transform(); - gt.elements[2] += recover_motion; - set_global_transform(gt); - - recover_attempts--; - - } while (recover_attempts); - - //move second - float safe = 1.0; - float unsafe = 1.0; - int best_shape = -1; - - for (int i = 0; i < get_shape_count(); i++) { + bool colliding = Physics2DServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, margin, &result); - if (is_shape_set_as_trigger(i)) - continue; - - float lsafe, lunsafe; - bool valid = dss->cast_motion(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i), p_motion, 0, lsafe, lunsafe, exclude, get_layer_mask(), mask); - //print_line("shape: "+itos(i)+" travel:"+rtos(ltravel)); - if (!valid) { - - safe = 0; - unsafe = 0; - best_shape = i; //sadly it's the best - break; - } - if (lsafe == 1.0) { - continue; - } - if (lsafe < safe) { - - safe = lsafe; - unsafe = lunsafe; - best_shape = i; - } + if (colliding) { + r_collision.collider_metadata = result.collider_metadata; + r_collision.collider_shape = result.collider_shape; + r_collision.collider_vel = result.collider_velocity; + r_collision.collision = result.collision_point; + r_collision.normal = result.collision_normal; + r_collision.collider = result.collider_id; + r_collision.travel = result.motion; + r_collision.remainder = result.remainder; + r_collision.local_shape = result.collision_local_shape; } - //print_line("best shape: "+itos(best_shape)+" motion "+p_motion); - - if (safe >= 1) { - //not collided - colliding = false; - - } else { - - //it collided, let's get the rest info in unsafe advance - Transform2D ugt = get_global_transform(); - ugt.elements[2] += p_motion * unsafe; - Physics2DDirectSpaceState::ShapeRestInfo rest_info; - bool c2 = dss->rest_info(get_shape(best_shape)->get_rid(), ugt * get_shape_transform(best_shape), Vector2(), margin, &rest_info, exclude, get_layer_mask(), mask); - if (!c2) { - //should not happen, but floating point precision is so weird.. - - colliding = false; - } else { - - //print_line("Travel: "+rtos(travel)); - colliding = true; - collision = rest_info.point; - normal = rest_info.normal; - collider = rest_info.collider_id; - collider_vel = rest_info.linear_velocity; - collider_shape = rest_info.shape; - collider_metadata = rest_info.metadata; - } - } - - Vector2 motion = p_motion * safe; - Transform2D gt = get_global_transform(); - gt.elements[2] += motion; + gt.elements[2] += result.motion; set_global_transform(gt); - return p_motion - motion; -#endif + return colliding; } -Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction, float p_slope_stop_min_velocity, int p_max_bounces) { +Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction, float p_slope_stop_min_velocity, int p_max_bounces, float p_floor_max_angle) { - Vector2 motion = (move_and_slide_floor_velocity + p_linear_velocity) * get_fixed_process_delta_time(); + Vector2 motion = (floor_velocity + p_linear_velocity) * get_fixed_process_delta_time(); Vector2 lv = p_linear_velocity; - move_and_slide_on_floor = false; - move_and_slide_on_ceiling = false; - move_and_slide_on_wall = false; - move_and_slide_colliders.clear(); - move_and_slide_floor_velocity = Vector2(); + on_floor = false; + on_ceiling = false; + on_wall = false; + colliders.clear(); + floor_velocity = Vector2(); while (p_max_bounces) { - motion = move(motion); + Collision collision; + + bool collided = move(motion, collision); - if (is_colliding()) { + if (collided) { + + motion = collision.remainder; if (p_floor_direction == Vector2()) { //all is a wall - move_and_slide_on_wall = true; + on_wall = true; } else { - if (get_collision_normal().dot(p_floor_direction) > Math::cos(Math::deg2rad((float)45))) { //floor + if (collision.normal.dot(p_floor_direction) >= Math::cos(p_floor_max_angle)) { //floor - move_and_slide_on_floor = true; - move_and_slide_floor_velocity = get_collider_velocity(); + on_floor = true; + floor_velocity = collision.collider_vel; - if (get_travel().length() < 1 && ABS((lv.x - move_and_slide_floor_velocity.x)) < p_slope_stop_min_velocity) { - revert_motion(); + if (collision.travel.length() < 1 && ABS((lv.x - floor_velocity.x)) < p_slope_stop_min_velocity) { + Transform2D gt = get_global_transform(); + gt.elements[2] -= collision.travel; + set_global_transform(gt); return Vector2(); } - } else if (get_collision_normal().dot(p_floor_direction) < Math::cos(Math::deg2rad((float)45))) { //ceiling - move_and_slide_on_ceiling = true; + } else if (collision.normal.dot(-p_floor_direction) >= Math::cos(p_floor_max_angle)) { //ceiling + on_ceiling = true; } else { - move_and_slide_on_wall = true; + on_wall = true; } } - motion = get_collision_normal().slide(motion); - lv = get_collision_normal().slide(lv); - Variant collider = _get_collider(); - if (collider.get_type() != Variant::NIL) { - move_and_slide_colliders.push_back(collider); - } + Vector2 n = collision.normal; + motion = motion.slide(n); + lv = lv.slide(n); + + colliders.push_back(collision); } else { break; @@ -1224,26 +1089,22 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const return lv; } -bool KinematicBody2D::is_move_and_slide_on_floor() const { - - return move_and_slide_on_floor; -} -bool KinematicBody2D::is_move_and_slide_on_wall() const { +bool KinematicBody2D::is_on_floor() const { - return move_and_slide_on_wall; + return on_floor; } -bool KinematicBody2D::is_move_and_slide_on_ceiling() const { +bool KinematicBody2D::is_on_wall() const { - return move_and_slide_on_ceiling; + return on_wall; } -Array KinematicBody2D::get_move_and_slide_colliders() const { +bool KinematicBody2D::is_on_ceiling() const { - return move_and_slide_colliders; + return on_ceiling; } -Vector2 KinematicBody2D::move_to(const Vector2 &p_position) { +Vector2 KinematicBody2D::get_floor_velocity() const { - return move(p_position - get_global_position()); + return floor_velocity; } bool KinematicBody2D::test_move(const Transform2D &p_from, const Vector2 &p_motion) { @@ -1253,98 +1114,123 @@ bool KinematicBody2D::test_move(const Transform2D &p_from, const Vector2 &p_moti return Physics2DServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, margin); } -Vector2 KinematicBody2D::get_collision_pos() const { +void KinematicBody2D::set_safe_margin(float p_margin) { - ERR_FAIL_COND_V(!colliding, Vector2()); - return collision; + margin = p_margin; } -Vector2 KinematicBody2D::get_collision_normal() const { +float KinematicBody2D::get_safe_margin() const { - ERR_FAIL_COND_V(!colliding, Vector2()); - return normal; + return margin; } -Vector2 KinematicBody2D::get_collider_velocity() const { +int KinematicBody2D::get_collision_count() const { - return collider_vel; + return colliders.size(); } +Vector2 KinematicBody2D::get_collision_position(int p_collision) const { -ObjectID KinematicBody2D::get_collider() const { + ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector2()); - ERR_FAIL_COND_V(!colliding, 0); - return collider; + return colliders[p_collision].collision; } - -int KinematicBody2D::get_collider_shape() const { - - ERR_FAIL_COND_V(!colliding, 0); - return collider_shape; +Vector2 KinematicBody2D::get_collision_normal(int p_collision) const { + ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector2()); + return colliders[p_collision].normal; } -Variant KinematicBody2D::get_collider_metadata() const { - - ERR_FAIL_COND_V(!colliding, 0); - return collider_metadata; +Vector2 KinematicBody2D::get_collision_travel(int p_collision) const { + ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector2()); + return colliders[p_collision].travel; } - -bool KinematicBody2D::is_colliding() const { - - return colliding; +Vector2 KinematicBody2D::get_collision_remainder(int p_collision) const { + ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector2()); + return colliders[p_collision].remainder; +} +Object *KinematicBody2D::get_collision_local_shape(int p_collision) const { + ERR_FAIL_INDEX_V(p_collision, colliders.size(), NULL); + uint32_t owner = shape_find_owner(colliders[p_collision].local_shape); + return shape_owner_get_owner(owner); } +Object *KinematicBody2D::get_collision_collider(int p_collision) const { + ERR_FAIL_INDEX_V(p_collision, colliders.size(), NULL); -void KinematicBody2D::set_collision_margin(float p_margin) { + if (colliders[p_collision].collider) { + return ObjectDB::get_instance(colliders[p_collision].collider); + } - margin = p_margin; + return NULL; } +ObjectID KinematicBody2D::get_collision_collider_id(int p_collision) const { + ERR_FAIL_INDEX_V(p_collision, colliders.size(), 0); -float KinematicBody2D::get_collision_margin() const { + return colliders[p_collision].collider; +} +Object *KinematicBody2D::get_collision_collider_shape(int p_collision) const { + ERR_FAIL_INDEX_V(p_collision, colliders.size(), NULL); + Object *collider = get_collision_collider(p_collision); + if (collider) { + CollisionObject2D *obj2d = collider->cast_to<CollisionObject2D>(); + if (obj2d) { + uint32_t owner = shape_find_owner(colliders[p_collision].collider_shape); + return obj2d->shape_owner_get_owner(owner); + } + } - return margin; + return NULL; +} +int KinematicBody2D::get_collision_collider_shape_index(int p_collision) const { + ERR_FAIL_INDEX_V(p_collision, colliders.size(), -1); + return colliders[p_collision].collider_shape; +} +Vector2 KinematicBody2D::get_collision_collider_velocity(int p_collision) const { + ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector2()); + return colliders[p_collision].collider_vel; +} +Variant KinematicBody2D::get_collision_collider_metadata(int p_collision) const { + ERR_FAIL_INDEX_V(p_collision, colliders.size(), Variant()); + return colliders[p_collision].collider_metadata; } void KinematicBody2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("move", "rel_vec"), &KinematicBody2D::move); - ClassDB::bind_method(D_METHOD("move_to", "position"), &KinematicBody2D::move_to); - ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "slope_stop_min_velocity", "max_bounces"), &KinematicBody2D::move_and_slide, DEFVAL(Vector2(0, 0)), DEFVAL(5), DEFVAL(4)); + ClassDB::bind_method(D_METHOD("move", "rel_vec"), &KinematicBody2D::_move); + ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "slope_stop_min_velocity", "max_bounces", "floor_max_angle"), &KinematicBody2D::move_and_slide, DEFVAL(Vector2(0, 0)), DEFVAL(5), DEFVAL(4), DEFVAL(Math::deg2rad((float)45))); ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec"), &KinematicBody2D::test_move); - ClassDB::bind_method(D_METHOD("get_travel"), &KinematicBody2D::get_travel); - ClassDB::bind_method(D_METHOD("revert_motion"), &KinematicBody2D::revert_motion); - ClassDB::bind_method(D_METHOD("is_colliding"), &KinematicBody2D::is_colliding); + ClassDB::bind_method(D_METHOD("is_on_floor"), &KinematicBody2D::is_on_floor); + ClassDB::bind_method(D_METHOD("is_on_ceiling"), &KinematicBody2D::is_on_ceiling); + ClassDB::bind_method(D_METHOD("is_on_wall"), &KinematicBody2D::is_on_wall); + ClassDB::bind_method(D_METHOD("get_floor_velocity"), &KinematicBody2D::get_floor_velocity); - ClassDB::bind_method(D_METHOD("get_collision_pos"), &KinematicBody2D::get_collision_pos); - ClassDB::bind_method(D_METHOD("get_collision_normal"), &KinematicBody2D::get_collision_normal); - ClassDB::bind_method(D_METHOD("get_collider_velocity"), &KinematicBody2D::get_collider_velocity); - ClassDB::bind_method(D_METHOD("get_collider:Variant"), &KinematicBody2D::_get_collider); - ClassDB::bind_method(D_METHOD("get_collider_shape"), &KinematicBody2D::get_collider_shape); - ClassDB::bind_method(D_METHOD("get_collider_metadata:Variant"), &KinematicBody2D::get_collider_metadata); - ClassDB::bind_method(D_METHOD("get_move_and_slide_colliders"), &KinematicBody2D::get_move_and_slide_colliders); - ClassDB::bind_method(D_METHOD("is_move_and_slide_on_floor"), &KinematicBody2D::is_move_and_slide_on_floor); - ClassDB::bind_method(D_METHOD("is_move_and_slide_on_ceiling"), &KinematicBody2D::is_move_and_slide_on_ceiling); - ClassDB::bind_method(D_METHOD("is_move_and_slide_on_wall"), &KinematicBody2D::is_move_and_slide_on_wall); + ClassDB::bind_method(D_METHOD("set_safe_margin", "pixels"), &KinematicBody2D::set_safe_margin); + ClassDB::bind_method(D_METHOD("get_safe_margin"), &KinematicBody2D::get_safe_margin); - ClassDB::bind_method(D_METHOD("set_collision_margin", "pixels"), &KinematicBody2D::set_collision_margin); - ClassDB::bind_method(D_METHOD("get_collision_margin", "pixels"), &KinematicBody2D::get_collision_margin); + ClassDB::bind_method(D_METHOD("get_collision_count"), &KinematicBody2D::get_collision_count); + ClassDB::bind_method(D_METHOD("get_collision_position", "collision"), &KinematicBody2D::get_collision_position); + ClassDB::bind_method(D_METHOD("get_collision_normal", "collision"), &KinematicBody2D::get_collision_normal); + ClassDB::bind_method(D_METHOD("get_collision_travel", "collision"), &KinematicBody2D::get_collision_travel); + ClassDB::bind_method(D_METHOD("get_collision_remainder", "collision"), &KinematicBody2D::get_collision_remainder); + ClassDB::bind_method(D_METHOD("get_collision_local_shape", "collision"), &KinematicBody2D::get_collision_local_shape); + ClassDB::bind_method(D_METHOD("get_collision_collider", "collision"), &KinematicBody2D::get_collision_collider); + ClassDB::bind_method(D_METHOD("get_collision_collider_id", "collision"), &KinematicBody2D::get_collision_collider_id); + ClassDB::bind_method(D_METHOD("get_collision_collider_shape", "collision"), &KinematicBody2D::get_collision_collider_shape); + ClassDB::bind_method(D_METHOD("get_collision_collider_shape_index", "collision"), &KinematicBody2D::get_collision_collider_shape_index); + ClassDB::bind_method(D_METHOD("get_collision_collider_velocity", "collision"), &KinematicBody2D::get_collision_collider_velocity); + ClassDB::bind_method(D_METHOD("get_collision_collider_metadata", "collision"), &KinematicBody2D::get_collision_collider_metadata); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "collision/margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_collision_margin", "get_collision_margin"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin"); } KinematicBody2D::KinematicBody2D() : PhysicsBody2D(Physics2DServer::BODY_MODE_KINEMATIC) { - colliding = false; - collider = 0; - - collider_shape = 0; - margin = 0.08; - move_and_slide_on_floor = false; - move_and_slide_on_ceiling = false; - move_and_slide_on_wall = false; + on_floor = false; + on_ceiling = false; + on_wall = false; } KinematicBody2D::~KinematicBody2D() { } diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index e51b51230..54bd263b1 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -37,10 +38,8 @@ class PhysicsBody2D : public CollisionObject2D { GDCLASS(PhysicsBody2D, CollisionObject2D); - uint32_t mask; + uint32_t collision_layer; uint32_t collision_mask; - Vector2 one_way_collision_direction; - float one_way_collision_max_depth; void _set_layers(uint32_t p_mask); uint32_t _get_layers() const; @@ -52,7 +51,7 @@ protected: static void _bind_methods(); public: - void set_collision_layer(uint32_t p_mask); + void set_collision_layer(uint32_t p_layer); uint32_t get_collision_layer() const; void set_collision_mask(uint32_t p_mask); @@ -67,12 +66,6 @@ public: void add_collision_exception_with(Node *p_node); //must be physicsbody void remove_collision_exception_with(Node *p_node); - void set_one_way_collision_direction(const Vector2 &p_dir); - Vector2 get_one_way_collision_direction() const; - - void set_one_way_collision_max_depth(float p_dir); - float get_one_way_collision_max_depth() const; - PhysicsBody2D(); }; @@ -192,6 +185,7 @@ private: bool _test_motion(const Vector2 &p_motion, float p_margin = 0.08, const Ref<Physics2DTestMotionResult> &p_result = Ref<Physics2DTestMotionResult>()); protected: + void _notification(int p_what); static void _bind_methods(); public: @@ -260,6 +254,8 @@ public: Array get_colliding_bodies() const; //function for script + virtual String get_configuration_warning() const; + RigidBody2D(); ~RigidBody2D(); }; @@ -271,54 +267,60 @@ class KinematicBody2D : public PhysicsBody2D { GDCLASS(KinematicBody2D, PhysicsBody2D); - float margin; - bool colliding; - Vector2 collision; - Vector2 normal; - Vector2 collider_vel; - ObjectID collider; - int collider_shape; - Variant collider_metadata; - Vector2 travel; +public: + struct Collision { + Vector2 collision; + Vector2 normal; + Vector2 collider_vel; + ObjectID collider; + int collider_shape; + Variant collider_metadata; + Vector2 remainder; + Vector2 travel; + int local_shape; + }; - Vector2 move_and_slide_floor_velocity; - bool move_and_slide_on_floor; - bool move_and_slide_on_ceiling; - bool move_and_slide_on_wall; - Array move_and_slide_colliders; +private: + float margin; - Variant _get_collider() const; + Vector2 floor_velocity; + bool on_floor; + bool on_ceiling; + bool on_wall; + Vector<Collision> colliders; _FORCE_INLINE_ bool _ignores_mode(Physics2DServer::BodyMode) const; + Dictionary _move(const Vector2 &p_motion); + protected: static void _bind_methods(); public: - Vector2 move(const Vector2 &p_motion); - Vector2 move_to(const Vector2 &p_position); - + bool move(const Vector2 &p_motion, Collision &r_collision); bool test_move(const Transform2D &p_from, const Vector2 &p_motion); - bool is_colliding() const; - - Vector2 get_travel() const; - void revert_motion(); - Vector2 get_collision_pos() const; - Vector2 get_collision_normal() const; - Vector2 get_collider_velocity() const; - ObjectID get_collider() const; - int get_collider_shape() const; - Variant get_collider_metadata() const; + void set_safe_margin(float p_margin); + float get_safe_margin() const; - void set_collision_margin(float p_margin); - float get_collision_margin() const; + Vector2 move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction = Vector2(0, 0), float p_slope_stop_min_velocity = 5, int p_max_bounces = 4, float p_floor_max_angle = Math::deg2rad((float)45)); + bool is_on_floor() const; + bool is_on_wall() const; + bool is_on_ceiling() const; + Vector2 get_floor_velocity() const; - Vector2 move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction = Vector2(0, 0), float p_slope_stop_min_velocity = 5, int p_max_bounces = 4); - bool is_move_and_slide_on_floor() const; - bool is_move_and_slide_on_wall() const; - bool is_move_and_slide_on_ceiling() const; - Array get_move_and_slide_colliders() const; + int get_collision_count() const; + Vector2 get_collision_position(int p_collision) const; + Vector2 get_collision_normal(int p_collision) const; + Vector2 get_collision_travel(int p_collision) const; + Vector2 get_collision_remainder(int p_collision) const; + Object *get_collision_local_shape(int p_collision) const; + Object *get_collision_collider(int p_collision) const; + ObjectID get_collision_collider_id(int p_collision) const; + Object *get_collision_collider_shape(int p_collision) const; + int get_collision_collider_shape_index(int p_collision) const; + Vector2 get_collision_collider_velocity(int p_collision) const; + Variant get_collision_collider_metadata(int p_collision) const; KinematicBody2D(); ~KinematicBody2D(); diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp index 1d54fd153..5c1c953a3 100644 --- a/scene/2d/polygon_2d.cpp +++ b/scene/2d/polygon_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -37,7 +38,7 @@ Rect2 Polygon2D::get_item_rect() const { for (int i = 0; i < l; i++) { Vector2 pos = r[i] + offset; if (i == 0) - item_rect.pos = pos; + item_rect.position = pos; else item_rect.expand_to(pos); } @@ -94,7 +95,7 @@ void Polygon2D::_notification(int p_what) { for (int i = 0; i < len; i++) { if (i == 0) - bounds.pos = points[i]; + bounds.position = points[i]; else bounds.expand_to(points[i]); if (points[i].y > highest_y) { @@ -109,10 +110,10 @@ void Polygon2D::_notification(int p_what) { Vector2 ep[7] = { Vector2(points[highest_idx].x, points[highest_idx].y + invert_border), - Vector2(bounds.pos + bounds.size), - Vector2(bounds.pos + Vector2(bounds.size.x, 0)), - Vector2(bounds.pos), - Vector2(bounds.pos + Vector2(0, bounds.size.y)), + Vector2(bounds.position + bounds.size), + Vector2(bounds.position + Vector2(bounds.size.x, 0)), + Vector2(bounds.position), + Vector2(bounds.position + Vector2(0, bounds.size.y)), Vector2(points[highest_idx].x - CMP_EPSILON, points[highest_idx].y + invert_border), Vector2(points[highest_idx].x - CMP_EPSILON, points[highest_idx].y), }; diff --git a/scene/2d/polygon_2d.h b/scene/2d/polygon_2d.h index 50968f3de..3cc9db28b 100644 --- a/scene/2d/polygon_2d.h +++ b/scene/2d/polygon_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -83,10 +84,10 @@ public: void set_texture_scale(const Size2 &p_scale); Size2 get_texture_scale() const; - void set_invert(bool p_rot); + void set_invert(bool p_invert); bool get_invert() const; - void set_invert_border(float p_border); + void set_invert_border(float p_invert_border); float get_invert_border() const; void set_offset(const Vector2 &p_offset); diff --git a/scene/2d/position_2d.cpp b/scene/2d/position_2d.cpp index 39fc6352e..74ad9c17e 100644 --- a/scene/2d/position_2d.cpp +++ b/scene/2d/position_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/position_2d.h b/scene/2d/position_2d.h index a9ead3d87..67ff2c610 100644 --- a/scene/2d/position_2d.h +++ b/scene/2d/position_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp index 83a0717ac..cfb405971 100644 --- a/scene/2d/ray_cast_2d.cpp +++ b/scene/2d/ray_cast_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -43,14 +44,14 @@ Vector2 RayCast2D::get_cast_to() const { return cast_to; } -void RayCast2D::set_layer_mask(uint32_t p_mask) { +void RayCast2D::set_collision_layer(uint32_t p_layer) { - layer_mask = p_mask; + collision_layer = p_layer; } -uint32_t RayCast2D::get_layer_mask() const { +uint32_t RayCast2D::get_collision_layer() const { - return layer_mask; + return collision_layer; } void RayCast2D::set_type_mask(uint32_t p_mask) { @@ -156,16 +157,16 @@ void RayCast2D::_notification(int p_what) { break; Transform2D xf; xf.rotate(cast_to.angle()); - xf.translate(Vector2(0, cast_to.length())); + xf.translate(Vector2(cast_to.length(), 0)); //Vector2 tip = Vector2(0,s->get_length()); Color dcol = get_tree()->get_debug_collisions_color(); //0.9,0.2,0.2,0.4); draw_line(Vector2(), cast_to, dcol, 3); Vector<Vector2> pts; float tsize = 4; - pts.push_back(xf.xform(Vector2(0, tsize))); - pts.push_back(xf.xform(Vector2(0.707 * tsize, 0))); - pts.push_back(xf.xform(Vector2(-0.707 * tsize, 0))); + pts.push_back(xf.xform(Vector2(tsize, 0))); + pts.push_back(xf.xform(Vector2(0, 0.707 * tsize))); + pts.push_back(xf.xform(Vector2(0, -0.707 * tsize))); Vector<Color> cols; for (int i = 0; i < 3; i++) cols.push_back(dcol); @@ -200,7 +201,7 @@ void RayCast2D::_update_raycast_state() { Physics2DDirectSpaceState::RayResult rr; - if (dss->intersect_ray(gt.get_origin(), gt.xform(to), rr, exclude, layer_mask, type_mask)) { + if (dss->intersect_ray(gt.get_origin(), gt.xform(to), rr, exclude, collision_layer, type_mask)) { collided = true; against = rr.collider_id; @@ -273,8 +274,8 @@ void RayCast2D::_bind_methods() { ClassDB::bind_method(D_METHOD("clear_exceptions"), &RayCast2D::clear_exceptions); - ClassDB::bind_method(D_METHOD("set_layer_mask", "mask"), &RayCast2D::set_layer_mask); - ClassDB::bind_method(D_METHOD("get_layer_mask"), &RayCast2D::get_layer_mask); + ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &RayCast2D::set_collision_layer); + ClassDB::bind_method(D_METHOD("get_collision_layer"), &RayCast2D::get_collision_layer); ClassDB::bind_method(D_METHOD("set_type_mask", "mask"), &RayCast2D::set_type_mask); ClassDB::bind_method(D_METHOD("get_type_mask"), &RayCast2D::get_type_mask); @@ -285,7 +286,7 @@ void RayCast2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclude_parent"), "set_exclude_parent_body", "get_exclude_parent_body"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "cast_to"), "set_cast_to", "get_cast_to"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "layer_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_layer_mask", "get_layer_mask"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_layer", "get_collision_layer"); ADD_PROPERTY(PropertyInfo(Variant::INT, "type_mask", PROPERTY_HINT_FLAGS, "Static,Kinematic,Rigid,Character,Area"), "set_type_mask", "get_type_mask"); } @@ -295,7 +296,7 @@ RayCast2D::RayCast2D() { against = 0; collided = false; against_shape = 0; - layer_mask = 1; + collision_layer = 1; type_mask = Physics2DDirectSpaceState::TYPE_MASK_COLLISION; cast_to = Vector2(0, 50); exclude_parent_body = true; diff --git a/scene/2d/ray_cast_2d.h b/scene/2d/ray_cast_2d.h index 6a59ef963..244f4302a 100644 --- a/scene/2d/ray_cast_2d.h +++ b/scene/2d/ray_cast_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -42,7 +43,7 @@ class RayCast2D : public Node2D { Vector2 collision_point; Vector2 collision_normal; Set<RID> exclude; - uint32_t layer_mask; + uint32_t collision_layer; uint32_t type_mask; bool exclude_parent_body; @@ -60,8 +61,8 @@ public: void set_cast_to(const Vector2 &p_point); Vector2 get_cast_to() const; - void set_layer_mask(uint32_t p_mask); - uint32_t get_layer_mask() const; + void set_collision_layer(uint32_t p_layer); + uint32_t get_collision_layer() const; void set_type_mask(uint32_t p_mask); uint32_t get_type_mask() const; diff --git a/scene/2d/remote_transform_2d.cpp b/scene/2d/remote_transform_2d.cpp index 210f64ae2..cbd7ac06f 100644 --- a/scene/2d/remote_transform_2d.cpp +++ b/scene/2d/remote_transform_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -38,7 +39,7 @@ void RemoteTransform2D::_update_cache() { return; } - cache = node->get_instance_ID(); + cache = node->get_instance_id(); } } @@ -62,7 +63,50 @@ void RemoteTransform2D::_update_remote() { return; //todo make faster - n->set_global_transform(get_global_transform()); + if (use_global_coordinates) { + + if (update_remote_position && update_remote_rotation && update_remote_scale) { + n->set_global_transform(get_global_transform()); + } else { + Transform2D n_trans = n->get_global_transform(); + Transform2D our_trans = get_global_transform(); + Vector2 n_scale = n->get_global_scale(); + + if (!update_remote_position) + our_trans.set_origin(n_trans.get_origin()); + if (!update_remote_rotation) + our_trans.set_rotation(n_trans.get_rotation()); + + n->set_global_transform(our_trans); + + if (update_remote_scale) + n->set_scale(get_global_scale()); + else + n->set_scale(n_scale); + } + + } else { + + if (update_remote_position && update_remote_rotation && update_remote_scale) { + n->set_transform(get_transform()); + } else { + Transform2D n_trans = n->get_transform(); + Transform2D our_trans = get_transform(); + Vector2 n_scale = n->get_scale(); + + if (!update_remote_position) + our_trans.set_origin(n_trans.get_origin()); + if (!update_remote_rotation) + our_trans.set_rotation(n_trans.get_rotation()); + + n->set_transform(our_trans); + + if (update_remote_scale) + n->set_scale(get_scale()); + else + n->set_scale(n_scale); + } + } } void RemoteTransform2D::_notification(int p_what) { @@ -101,6 +145,41 @@ NodePath RemoteTransform2D::get_remote_node() const { return remote_node; } +void RemoteTransform2D::set_use_global_coordinates(const bool p_enable) { + use_global_coordinates = p_enable; +} + +bool RemoteTransform2D::get_use_global_coordinates() const { + return use_global_coordinates; +} + +void RemoteTransform2D::set_update_position(const bool p_update) { + update_remote_position = p_update; + _update_remote(); +} + +bool RemoteTransform2D::get_update_position() const { + return update_remote_position; +} + +void RemoteTransform2D::set_update_rotation(const bool p_update) { + update_remote_rotation = p_update; + _update_remote(); +} + +bool RemoteTransform2D::get_update_rotation() const { + return update_remote_rotation; +} + +void RemoteTransform2D::set_update_scale(const bool p_update) { + update_remote_scale = p_update; + _update_remote(); +} + +bool RemoteTransform2D::get_update_scale() const { + return update_remote_scale; +} + String RemoteTransform2D::get_configuration_warning() const { if (!has_node(remote_node) || !get_node(remote_node) || !get_node(remote_node)->cast_to<Node2D>()) { @@ -115,11 +194,32 @@ void RemoteTransform2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_remote_node", "path"), &RemoteTransform2D::set_remote_node); ClassDB::bind_method(D_METHOD("get_remote_node"), &RemoteTransform2D::get_remote_node); + ClassDB::bind_method(D_METHOD("set_use_global_coordinates", "use_global_coordinates"), &RemoteTransform2D::set_use_global_coordinates); + ClassDB::bind_method(D_METHOD("get_use_global_coordinates"), &RemoteTransform2D::get_use_global_coordinates); + + ClassDB::bind_method(D_METHOD("set_update_position", "update_remote_position"), &RemoteTransform2D::set_update_position); + ClassDB::bind_method(D_METHOD("get_update_position"), &RemoteTransform2D::get_update_position); + ClassDB::bind_method(D_METHOD("set_update_rotation", "update_remote_rotation"), &RemoteTransform2D::set_update_rotation); + ClassDB::bind_method(D_METHOD("get_update_rotation"), &RemoteTransform2D::get_update_rotation); + ClassDB::bind_method(D_METHOD("set_update_scale", "update_remote_scale"), &RemoteTransform2D::set_update_scale); + ClassDB::bind_method(D_METHOD("get_update_scale"), &RemoteTransform2D::get_update_scale); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "remote_path"), "set_remote_node", "get_remote_node"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_global_coordinates"), "set_use_global_coordinates", "get_use_global_coordinates"); + + ADD_GROUP("Update", "update_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_position"), "set_update_position", "get_update_position"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_rotation"), "set_update_rotation", "get_update_rotation"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_scale"), "set_update_scale", "get_update_scale"); } RemoteTransform2D::RemoteTransform2D() { + use_global_coordinates = true; + update_remote_position = true; + update_remote_rotation = true; + update_remote_scale = true; + cache = 0; set_notify_transform(true); } diff --git a/scene/2d/remote_transform_2d.h b/scene/2d/remote_transform_2d.h index aa1b21431..d58ec14a9 100644 --- a/scene/2d/remote_transform_2d.h +++ b/scene/2d/remote_transform_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -36,6 +37,11 @@ class RemoteTransform2D : public Node2D { ObjectID cache; + bool use_global_coordinates; + bool update_remote_position; + bool update_remote_rotation; + bool update_remote_scale; + void _update_remote(); void _update_cache(); //void _node_exited_scene(); @@ -47,6 +53,18 @@ public: void set_remote_node(const NodePath &p_remote_node); NodePath get_remote_node() const; + void set_use_global_coordinates(const bool p_enable); + bool get_use_global_coordinates() const; + + void set_update_position(const bool p_update); + bool get_update_position() const; + + void set_update_rotation(const bool p_update); + bool get_update_rotation() const; + + void set_update_scale(const bool p_update); + bool get_update_scale() const; + virtual String get_configuration_warning() const; RemoteTransform2D(); diff --git a/scene/2d/screen_button.cpp b/scene/2d/screen_button.cpp index db822ed30..37139b2b9 100644 --- a/scene/2d/screen_button.cpp +++ b/scene/2d/screen_button.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -65,12 +66,14 @@ Ref<BitMap> TouchScreenButton::get_bitmask() const { void TouchScreenButton::set_shape(const Ref<Shape2D> &p_shape) { + if (shape.is_valid()) + shape->disconnect("changed", this, "update"); + shape = p_shape; - if (!is_inside_tree()) - return; - if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) - return; + if (shape.is_valid()) + shape->connect("changed", this, "update"); + update(); } @@ -82,11 +85,17 @@ Ref<Shape2D> TouchScreenButton::get_shape() const { void TouchScreenButton::set_shape_centered(bool p_shape_centered) { shape_centered = p_shape_centered; + update(); +} - if (!is_inside_tree()) - return; - if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) - return; +bool TouchScreenButton::is_shape_visible() const { + + return shape_visible; +} + +void TouchScreenButton::set_shape_visible(bool p_shape_visible) { + + shape_visible = p_shape_visible; update(); } @@ -118,6 +127,8 @@ void TouchScreenButton::_notification(int p_what) { draw_texture(texture, Point2()); } + if (!shape_visible) + return; if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) return; if (shape.is_valid()) { @@ -137,11 +148,6 @@ void TouchScreenButton::_notification(int p_what) { if (!get_tree()->is_editor_hint()) set_process_input(is_visible_in_tree()); - if (action.operator String() != "" && InputMap::get_singleton()->has_action(action)) { - action_id = InputMap::get_singleton()->get_action_id(action); - } else { - action_id = -1; - } } break; case NOTIFICATION_EXIT_TREE: { if (is_pressed()) @@ -173,11 +179,6 @@ bool TouchScreenButton::is_pressed() const { void TouchScreenButton::set_action(const String &p_action) { action = p_action; - if (action.operator String() != "" && InputMap::get_singleton()->has_action(action)) { - action_id = InputMap::get_singleton()->get_action_id(action); - } else { - action_id = -1; - } } String TouchScreenButton::get_action() const { @@ -185,44 +186,37 @@ String TouchScreenButton::get_action() const { return action; } -void TouchScreenButton::_input(const InputEvent &p_event) { +void TouchScreenButton::_input(const Ref<InputEvent> &p_event) { if (!get_tree()) return; - if (p_event.device != 0) + if (p_event->get_device() != 0) return; - if (passby_press) { + ERR_FAIL_COND(!is_visible_in_tree()); - if (p_event.type == InputEvent::SCREEN_TOUCH && !p_event.screen_touch.pressed && finger_pressed == p_event.screen_touch.index) { + const InputEventScreenTouch *st = p_event->cast_to<InputEventScreenTouch>(); - _release(); - } - - if ((p_event.type == InputEvent::SCREEN_TOUCH && p_event.screen_touch.pressed) || p_event.type == InputEvent::SCREEN_DRAG) { + if (passby_press) { - if (finger_pressed == -1 || p_event.screen_touch.index == finger_pressed) { + const InputEventScreenDrag *sd = p_event->cast_to<InputEventScreenDrag>(); - Point2 coord = (get_global_transform_with_canvas()).affine_inverse().xform(Point2(p_event.screen_touch.x, p_event.screen_touch.y)); + if (st && !st->is_pressed() && finger_pressed == st->get_index()) { - bool touched = false; - if (bitmask.is_valid()) { + _release(); + } - if (Rect2(Point2(), bitmask->get_size()).has_point(coord)) { + if ((st && st->is_pressed()) || sd) { - if (bitmask->get_bit(coord)) - touched = true; - } - } else { + int index = st ? st->get_index() : sd->get_index(); + Point2 coord = st ? st->get_position() : sd->get_position(); - if (texture.is_valid()) - touched = Rect2(Point2(), texture->get_size()).has_point(coord); - } + if (finger_pressed == -1 || index == finger_pressed) { - if (touched) { + if (_is_point_inside(coord)) { if (finger_pressed == -1) { - _press(p_event.screen_touch.index); + _press(index); } } else { if (finger_pressed != -1) { @@ -234,69 +228,71 @@ void TouchScreenButton::_input(const InputEvent &p_event) { } else { - if (p_event.type == InputEvent::SCREEN_TOUCH) { - - if (p_event.screen_touch.pressed) { + if (st) { - if (!is_visible_in_tree()) - return; + if (st->is_pressed()) { const bool can_press = finger_pressed == -1; if (!can_press) return; //already fingering - Point2 coord = (get_global_transform_with_canvas()).affine_inverse().xform(Point2(p_event.screen_touch.x, p_event.screen_touch.y)); - Rect2 item_rect = get_item_rect(); + if (_is_point_inside(st->get_position())) { + _press(st->get_index()); + } + } else { + if (st->get_index() == finger_pressed) { + _release(); + } + } + } + } +} - bool touched = false; - bool check_rect = true; - if (shape.is_valid()) { +bool TouchScreenButton::_is_point_inside(const Point2 &p_point) { - check_rect = false; - Transform2D xform = shape_centered ? Transform2D().translated(get_item_rect().size * 0.5f) : Transform2D(); - touched = shape->collide(xform, unit_rect, Transform2D(0, coord + Vector2(0.5, 0.5))); - } + Point2 coord = (get_global_transform_with_canvas()).affine_inverse().xform(p_point); + Rect2 item_rect = get_item_rect(); - if (bitmask.is_valid()) { + bool touched = false; + bool check_rect = true; - check_rect = false; - if (!touched && Rect2(Point2(), bitmask->get_size()).has_point(coord)) { + if (shape.is_valid()) { - if (bitmask->get_bit(coord)) - touched = true; - } - } + check_rect = false; + Transform2D xform = shape_centered ? Transform2D().translated(item_rect.size * 0.5f) : Transform2D(); + touched = shape->collide(xform, unit_rect, Transform2D(0, coord + Vector2(0.5, 0.5))); + } - if (!touched && check_rect) { - if (!texture.is_null()) - touched = item_rect.has_point(coord); - } + if (bitmask.is_valid()) { - if (touched) { - _press(p_event.screen_touch.index); - } - } else { - if (p_event.screen_touch.index == finger_pressed) { - _release(); - } - } + check_rect = false; + if (!touched && Rect2(Point2(), bitmask->get_size()).has_point(coord)) { + + if (bitmask->get_bit(coord)) + touched = true; } } + + if (!touched && check_rect) { + if (texture.is_valid()) + touched = item_rect.has_point(coord); + } + + return touched; } void TouchScreenButton::_press(int p_finger_pressed) { finger_pressed = p_finger_pressed; - if (action_id != -1) { + if (action != StringName()) { Input::get_singleton()->action_press(action); - InputEvent ie; - ie.type = InputEvent::ACTION; - ie.ID = 0; - ie.action.action = action_id; - ie.action.pressed = true; - get_tree()->input_event(ie); + Ref<InputEventAction> iea; + iea.instance(); + iea->set_action(action); + iea->set_pressed(true); + get_tree()->input_event(iea); } emit_signal("pressed"); @@ -307,16 +303,16 @@ void TouchScreenButton::_release(bool p_exiting_tree) { finger_pressed = -1; - if (action_id != -1) { + if (action != StringName()) { Input::get_singleton()->action_release(action); if (!p_exiting_tree) { - InputEvent ie; - ie.type = InputEvent::ACTION; - ie.ID = 0; - ie.action.action = action_id; - ie.action.pressed = false; - get_tree()->input_event(ie); + + Ref<InputEventAction> iea; + iea.instance(); + iea->set_action(action); + iea->set_pressed(false); + get_tree()->input_event(iea); } } @@ -375,6 +371,9 @@ void TouchScreenButton::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shape_centered", "bool"), &TouchScreenButton::set_shape_centered); ClassDB::bind_method(D_METHOD("is_shape_centered"), &TouchScreenButton::is_shape_centered); + ClassDB::bind_method(D_METHOD("set_shape_visible", "bool"), &TouchScreenButton::set_shape_visible); + ClassDB::bind_method(D_METHOD("is_shape_visible"), &TouchScreenButton::is_shape_visible); + ClassDB::bind_method(D_METHOD("set_action", "action"), &TouchScreenButton::set_action); ClassDB::bind_method(D_METHOD("get_action"), &TouchScreenButton::get_action); @@ -393,6 +392,7 @@ void TouchScreenButton::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "bitmask", PROPERTY_HINT_RESOURCE_TYPE, "BitMap"), "set_bitmask", "get_bitmask"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), "set_shape", "get_shape"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shape_centered"), "set_shape_centered", "is_shape_centered"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shape_visible"), "set_shape_visible", "is_shape_visible"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "passby_press"), "set_passby_press", "is_passby_press_enabled"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "action"), "set_action", "get_action"); ADD_PROPERTY(PropertyInfo(Variant::INT, "visibility_mode", PROPERTY_HINT_ENUM, "Always,TouchScreen Only"), "set_visibility_mode", "get_visibility_mode"); @@ -404,10 +404,10 @@ void TouchScreenButton::_bind_methods() { TouchScreenButton::TouchScreenButton() { finger_pressed = -1; - action_id = -1; passby_press = false; visibility = VISIBILITY_ALWAYS; shape_centered = true; + shape_visible = true; unit_rect = Ref<RectangleShape2D>(memnew(RectangleShape2D)); unit_rect->set_extents(Vector2(0.5, 0.5)); } diff --git a/scene/2d/screen_button.h b/scene/2d/screen_button.h index 201d908bf..2a5935aaf 100644 --- a/scene/2d/screen_button.h +++ b/scene/2d/screen_button.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -50,17 +51,19 @@ private: Ref<BitMap> bitmask; Ref<Shape2D> shape; bool shape_centered; + bool shape_visible; Ref<RectangleShape2D> unit_rect; StringName action; bool passby_press; int finger_pressed; - int action_id; VisibilityMode visibility; - void _input(const InputEvent &p_Event); + void _input(const Ref<InputEvent> &p_event); + + bool _is_point_inside(const Point2 &p_point); void _press(int p_finger_pressed); void _release(bool p_exiting_tree = false); @@ -85,6 +88,9 @@ public: void set_shape_centered(bool p_shape_centered); bool is_shape_centered() const; + void set_shape_visible(bool p_shape_visible); + bool is_shape_visible() const; + void set_action(const String &p_action); String get_action() const; diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp index 41ea6a39e..2ec529a16 100644 --- a/scene/2d/sprite.cpp +++ b/scene/2d/sprite.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -64,18 +65,20 @@ void Sprite::_notification(int p_what) { Size2 s; Rect2 src_rect; + bool filter_clip = false; if (region) { s = region_rect.size; src_rect = region_rect; + filter_clip = region_filter_clip; } else { s = Size2(texture->get_size()); s = s / Size2(hframes, vframes); src_rect.size = s; - src_rect.pos.x += float(frame % hframes) * s.x; - src_rect.pos.y += float(frame / hframes) * s.y; + src_rect.position.x += float(frame % hframes) * s.x; + src_rect.position.y += float(frame / hframes) * s.y; } Point2 ofs = offset; @@ -92,7 +95,7 @@ void Sprite::_notification(int p_what) { if (vflip) dst_rect.size.y = -dst_rect.size.y; - texture->draw_rect_region(ci, dst_rect, src_rect); + texture->draw_rect_region(ci, dst_rect, src_rect, Color(1, 1, 1), false, normal_map, filter_clip); } break; } @@ -102,21 +105,22 @@ void Sprite::set_texture(const Ref<Texture> &p_texture) { if (p_texture == texture) return; -#ifdef DEBUG_ENABLED - if (texture.is_valid()) { - texture->disconnect(CoreStringNames::get_singleton()->changed, this, SceneStringNames::get_singleton()->update); - } -#endif texture = p_texture; -#ifdef DEBUG_ENABLED - if (texture.is_valid()) { - texture->set_flags(texture->get_flags()); //remove repeat from texture, it looks bad in sprites - texture->connect(CoreStringNames::get_singleton()->changed, this, SceneStringNames::get_singleton()->update); - } -#endif update(); emit_signal("texture_changed"); item_rect_changed(); + _change_notify("texture"); +} + +void Sprite::set_normal_map(const Ref<Texture> &p_texture) { + + normal_map = p_texture; + update(); +} + +Ref<Texture> Sprite::get_normal_map() const { + + return normal_map; } Ref<Texture> Sprite::get_texture() const { @@ -200,6 +204,15 @@ Rect2 Sprite::get_region_rect() const { return region_rect; } +void Sprite::set_region_filter_clip(bool p_enable) { + region_filter_clip = p_enable; + update(); +} + +bool Sprite::is_region_filter_clip_enabled() const { + return region_filter_clip; +} + void Sprite::set_frame(int p_frame) { ERR_FAIL_INDEX(p_frame, vframes * hframes); @@ -224,7 +237,7 @@ void Sprite::set_vframes(int p_amount) { vframes = p_amount; update(); item_rect_changed(); - _change_notify("frame"); + _change_notify(); } int Sprite::get_vframes() const { @@ -237,7 +250,7 @@ void Sprite::set_hframes(int p_amount) { hframes = p_amount; update(); item_rect_changed(); - _change_notify("frame"); + _change_notify(); } int Sprite::get_hframes() const { @@ -285,8 +298,11 @@ void Sprite::_validate_property(PropertyInfo &property) const { void Sprite::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_texture", "texture:Texture"), &Sprite::set_texture); - ClassDB::bind_method(D_METHOD("get_texture:Texture"), &Sprite::get_texture); + ClassDB::bind_method(D_METHOD("set_texture", "texture"), &Sprite::set_texture); + ClassDB::bind_method(D_METHOD("get_texture"), &Sprite::get_texture); + + ClassDB::bind_method(D_METHOD("set_normal_map", "normal_map"), &Sprite::set_normal_map); + ClassDB::bind_method(D_METHOD("get_normal_map"), &Sprite::get_normal_map); ClassDB::bind_method(D_METHOD("set_centered", "centered"), &Sprite::set_centered); ClassDB::bind_method(D_METHOD("is_centered"), &Sprite::is_centered); @@ -306,6 +322,9 @@ void Sprite::_bind_methods() { ClassDB::bind_method(D_METHOD("set_region_rect", "rect"), &Sprite::set_region_rect); ClassDB::bind_method(D_METHOD("get_region_rect"), &Sprite::get_region_rect); + ClassDB::bind_method(D_METHOD("set_region_filter_clip", "enabled"), &Sprite::set_region_filter_clip); + ClassDB::bind_method(D_METHOD("is_region_filter_clip_enabled"), &Sprite::is_region_filter_clip_enabled); + ClassDB::bind_method(D_METHOD("set_frame", "frame"), &Sprite::set_frame); ClassDB::bind_method(D_METHOD("get_frame"), &Sprite::get_frame); @@ -319,15 +338,21 @@ void Sprite::_bind_methods() { ADD_SIGNAL(MethodInfo("texture_changed")); ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture"); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_normal_map", "get_normal_map"); + ADD_GROUP("Offset", ""); ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "centered"), "set_centered", "is_centered"); ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset"); ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "flip_h"), "set_flip_h", "is_flipped_h"); ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "flip_v"), "set_flip_v", "is_flipped_v"); + ADD_GROUP("Animation", ""); ADD_PROPERTYNO(PropertyInfo(Variant::INT, "vframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_vframes", "get_vframes"); ADD_PROPERTYNO(PropertyInfo(Variant::INT, "hframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_hframes", "get_hframes"); ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "frame", PROPERTY_HINT_SPRITE_FRAME), "set_frame", "get_frame"); - ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "region"), "set_region", "is_region"); + + ADD_GROUP("Region", "region_"); + ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region", "is_region"); ADD_PROPERTYNZ(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect"); + ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "region_filter_clip"), "set_region_filter_clip", "is_region_filter_clip_enabled"); } Sprite::Sprite() { @@ -336,6 +361,7 @@ Sprite::Sprite() { hflip = false; vflip = false; region = false; + region_filter_clip = false; frame = 0; diff --git a/scene/2d/sprite.h b/scene/2d/sprite.h index c4bc80064..d3f9a5f03 100644 --- a/scene/2d/sprite.h +++ b/scene/2d/sprite.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -37,6 +38,7 @@ class Sprite : public Node2D { GDCLASS(Sprite, Node2D); Ref<Texture> texture; + Ref<Texture> normal_map; bool centered; Point2 offset; @@ -45,6 +47,7 @@ class Sprite : public Node2D { bool vflip; bool region; Rect2 region_rect; + bool region_filter_clip; int frame; @@ -66,6 +69,9 @@ public: void set_texture(const Ref<Texture> &p_texture); Ref<Texture> get_texture() const; + void set_normal_map(const Ref<Texture> &p_texture); + Ref<Texture> get_normal_map() const; + void set_centered(bool p_center); bool is_centered() const; @@ -81,6 +87,9 @@ public: void set_region(bool p_region); bool is_region() const; + void set_region_filter_clip(bool p_enable); + bool is_region_filter_clip_enabled() const; + void set_region_rect(const Rect2 &p_region_rect); Rect2 get_region_rect() const; diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 02b41fbd0..68b026b1b 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -28,7 +29,7 @@ /*************************************************************************/ #include "tile_map.h" #include "io/marshalls.h" -#include "method_bind_ext.inc" +#include "method_bind_ext.gen.inc" #include "os/os.h" #include "servers/physics_2d_server.h" @@ -304,7 +305,7 @@ void TileMap::_update_dirty_quadrants() { VS::get_singleton()->free(E->get().id); } q.occluder_instances.clear(); - Ref<CanvasItemMaterial> prev_material; + Ref<ShaderMaterial> prev_material; RID prev_canvas_item; RID prev_debug_canvas_item; @@ -324,7 +325,7 @@ void TileMap::_update_dirty_quadrants() { if (!tex.is_valid()) continue; - Ref<CanvasItemMaterial> mat = tile_set->tile_get_material(c.id); + Ref<ShaderMaterial> mat = tile_set->tile_get_material(c.id); RID canvas_item; RID debug_canvas_item; @@ -369,14 +370,14 @@ void TileMap::_update_dirty_quadrants() { s = tex->get_size(); else { s = r.size; - r.pos.x += fp_adjust; - r.pos.y += fp_adjust; + r.position.x += fp_adjust; + r.position.y += fp_adjust; r.size.x -= fp_adjust * 2.0; r.size.y -= fp_adjust * 2.0; } Rect2 rect; - rect.pos = offset.floor(); + rect.position = offset.floor(); rect.size = s; if (rect.size.y > rect.size.x) { @@ -405,70 +406,73 @@ void TileMap::_update_dirty_quadrants() { Vector2 center_ofs; if (tile_origin == TILE_ORIGIN_TOP_LEFT) { - rect.pos += tile_ofs; + rect.position += tile_ofs; } else if (tile_origin == TILE_ORIGIN_BOTTOM_LEFT) { - rect.pos += tile_ofs; + rect.position += tile_ofs; if (c.transpose) { if (c.flip_h) - rect.pos.x -= cell_size.x; + rect.position.x -= cell_size.x; else - rect.pos.x += cell_size.x; + rect.position.x += cell_size.x; } else { if (c.flip_v) - rect.pos.y -= cell_size.y; + rect.position.y -= cell_size.y; else - rect.pos.y += cell_size.y; + rect.position.y += cell_size.y; } } else if (tile_origin == TILE_ORIGIN_CENTER) { - rect.pos += tcenter; + rect.position += tcenter; Vector2 center = (s / 2) - tile_ofs; center_ofs = tcenter - (s / 2); if (c.flip_h) - rect.pos.x -= s.x - center.x; + rect.position.x -= s.x - center.x; else - rect.pos.x -= center.x; + rect.position.x -= center.x; if (c.flip_v) - rect.pos.y -= s.y - center.y; + rect.position.y -= s.y - center.y; else - rect.pos.y -= center.y; + rect.position.y -= center.y; } + Ref<Texture> normal_map = tile_set->tile_get_normal_map(c.id); Color modulate = tile_set->tile_get_modulate(c.id); Color self_modulate = get_self_modulate(); modulate = Color(modulate.r * self_modulate.r, modulate.g * self_modulate.g, modulate.b * self_modulate.b, modulate.a * self_modulate.a); if (r == Rect2()) { - tex->draw_rect(canvas_item, rect, false, modulate, c.transpose); + tex->draw_rect(canvas_item, rect, false, modulate, c.transpose, normal_map); } else { - tex->draw_rect_region(canvas_item, rect, r, modulate, c.transpose); + tex->draw_rect_region(canvas_item, rect, r, modulate, c.transpose, normal_map); } - Vector<Ref<Shape2D> > shapes = tile_set->tile_get_shapes(c.id); + Vector<TileSet::ShapeData> shapes = tile_set->tile_get_shapes(c.id); for (int i = 0; i < shapes.size(); i++) { - Ref<Shape2D> shape = shapes[i]; + Ref<Shape2D> shape = shapes[i].shape; if (shape.is_valid()) { - - Vector2 shape_ofs = tile_set->tile_get_shape_offset(c.id); Transform2D xform; xform.set_origin(offset.floor()); - _fix_cell_transform(xform, c, shape_ofs + center_ofs, s); + _fix_cell_transform(xform, c, center_ofs, s); + + xform *= shapes[i].shape_transform; if (debug_canvas_item.is_valid()) { vs->canvas_item_add_set_transform(debug_canvas_item, xform); shape->draw(debug_canvas_item, debug_collision_color); } ps->body_add_shape(q.body, shape->get_rid(), xform); - ps->body_set_shape_metadata(q.body, shape_idx++, Vector2(E->key().x, E->key().y)); + ps->body_set_shape_metadata(q.body, shape_idx, Vector2(E->key().x, E->key().y)); + ps->body_set_shape_as_one_way_collision(q.body, shape_idx, shapes[i].one_way_collision); + shape_idx++; } } @@ -548,7 +552,7 @@ void TileMap::_recompute_rect_cache() { for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) { Rect2 r; - r.pos = _map_to_world(E->key().x * _get_quadrant_size(), E->key().y * _get_quadrant_size()); + r.position = _map_to_world(E->key().x * _get_quadrant_size(), E->key().y * _get_quadrant_size()); r.expand_to(_map_to_world(E->key().x * _get_quadrant_size() + _get_quadrant_size(), E->key().y * _get_quadrant_size())); r.expand_to(_map_to_world(E->key().x * _get_quadrant_size() + _get_quadrant_size(), E->key().y * _get_quadrant_size() + _get_quadrant_size())); r.expand_to(_map_to_world(E->key().x * _get_quadrant_size(), E->key().y * _get_quadrant_size() + _get_quadrant_size())); @@ -585,8 +589,8 @@ Map<TileMap::PosKey, TileMap::Quadrant>::Element *TileMap::_create_quadrant(cons xform.set_origin(q.pos); //q.canvas_item = VisualServer::get_singleton()->canvas_item_create(); q.body = Physics2DServer::get_singleton()->body_create(use_kinematic ? Physics2DServer::BODY_MODE_KINEMATIC : Physics2DServer::BODY_MODE_STATIC); - Physics2DServer::get_singleton()->body_attach_object_instance_ID(q.body, get_instance_ID()); - Physics2DServer::get_singleton()->body_set_layer_mask(q.body, collision_layer); + Physics2DServer::get_singleton()->body_attach_object_instance_id(q.body, get_instance_id()); + Physics2DServer::get_singleton()->body_set_collision_layer(q.body, collision_layer); Physics2DServer::get_singleton()->body_set_collision_mask(q.body, collision_mask); Physics2DServer::get_singleton()->body_set_param(q.body, Physics2DServer::BODY_PARAM_FRICTION, friction); Physics2DServer::get_singleton()->body_set_param(q.body, Physics2DServer::BODY_PARAM_BOUNCE, bounce); @@ -862,7 +866,7 @@ void TileMap::set_collision_layer(uint32_t p_layer) { for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) { Quadrant &q = E->get(); - Physics2DServer::get_singleton()->body_set_layer_mask(q.body, collision_layer); + Physics2DServer::get_singleton()->body_set_collision_layer(q.body, collision_layer); } } @@ -876,6 +880,26 @@ void TileMap::set_collision_mask(uint32_t p_mask) { } } +void TileMap::set_collision_layer_bit(int p_bit, bool p_value) { + + uint32_t layer = get_collision_layer(); + if (p_value) + layer |= 1 << p_bit; + else + layer &= ~(1 << p_bit); + set_collision_layer(layer); +} + +void TileMap::set_collision_mask_bit(int p_bit, bool p_value) { + + uint32_t mask = get_collision_mask(); + if (p_value) + mask |= 1 << p_bit; + else + mask &= ~(1 << p_bit); + set_collision_mask(mask); +} + bool TileMap::get_collision_use_kinematic() const { return use_kinematic; @@ -927,6 +951,16 @@ uint32_t TileMap::get_collision_mask() const { return collision_mask; } +bool TileMap::get_collision_layer_bit(int p_bit) const { + + return get_collision_layer() & (1 << p_bit); +} + +bool TileMap::get_collision_mask_bit(int p_bit) const { + + return get_collision_mask() & (1 << p_bit); +} + void TileMap::set_mode(Mode p_mode) { _clear_quadrants(); @@ -1034,20 +1068,20 @@ Transform2D TileMap::get_custom_transform() const { return custom_transform; } -Vector2 TileMap::_map_to_world(int x, int y, bool p_ignore_ofs) const { +Vector2 TileMap::_map_to_world(int p_x, int p_y, bool p_ignore_ofs) const { - Vector2 ret = get_cell_transform().xform(Vector2(x, y)); + Vector2 ret = get_cell_transform().xform(Vector2(p_x, p_y)); if (!p_ignore_ofs) { switch (half_offset) { case HALF_OFFSET_X: { - if (ABS(y) & 1) { + if (ABS(p_y) & 1) { ret += get_cell_transform()[0] * 0.5; } } break; case HALF_OFFSET_Y: { - if (ABS(x) & 1) { + if (ABS(p_x) & 1) { ret += get_cell_transform()[1] * 0.5; } } break; @@ -1110,6 +1144,20 @@ Array TileMap::get_used_cells() const { return a; } +Array TileMap::get_used_cells_by_id(int p_id) const { + + Array a; + for (Map<PosKey, Cell>::Element *E = tile_map.front(); E; E = E->next()) { + + if (E->value().id == p_id) { + Vector2 p(E->key().x, E->key().y); + a.push_back(p); + } + } + + return a; +} + Rect2 TileMap::get_used_rect() { // Not const because of cache if (used_size_cache_dirty) { @@ -1160,8 +1208,8 @@ void TileMap::set_light_mask(int p_light_mask) { void TileMap::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_tileset", "tileset:TileSet"), &TileMap::set_tileset); - ClassDB::bind_method(D_METHOD("get_tileset:TileSet"), &TileMap::get_tileset); + ClassDB::bind_method(D_METHOD("set_tileset", "tileset"), &TileMap::set_tileset); + ClassDB::bind_method(D_METHOD("get_tileset"), &TileMap::get_tileset); ClassDB::bind_method(D_METHOD("set_mode", "mode"), &TileMap::set_mode); ClassDB::bind_method(D_METHOD("get_mode"), &TileMap::get_mode); @@ -1196,12 +1244,18 @@ void TileMap::_bind_methods() { ClassDB::bind_method(D_METHOD("set_collision_use_kinematic", "use_kinematic"), &TileMap::set_collision_use_kinematic); ClassDB::bind_method(D_METHOD("get_collision_use_kinematic"), &TileMap::get_collision_use_kinematic); - ClassDB::bind_method(D_METHOD("set_collision_layer", "mask"), &TileMap::set_collision_layer); + ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &TileMap::set_collision_layer); ClassDB::bind_method(D_METHOD("get_collision_layer"), &TileMap::get_collision_layer); ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &TileMap::set_collision_mask); ClassDB::bind_method(D_METHOD("get_collision_mask"), &TileMap::get_collision_mask); + ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &TileMap::set_collision_layer_bit); + ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &TileMap::get_collision_layer_bit); + + ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &TileMap::set_collision_mask_bit); + ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &TileMap::get_collision_mask_bit); + ClassDB::bind_method(D_METHOD("set_collision_friction", "value"), &TileMap::set_collision_friction); ClassDB::bind_method(D_METHOD("get_collision_friction"), &TileMap::get_collision_friction); @@ -1222,6 +1276,7 @@ void TileMap::_bind_methods() { ClassDB::bind_method(D_METHOD("clear"), &TileMap::clear); ClassDB::bind_method(D_METHOD("get_used_cells"), &TileMap::get_used_cells); + ClassDB::bind_method(D_METHOD("get_used_cells_by_id", "id"), &TileMap::get_used_cells_by_id); ClassDB::bind_method(D_METHOD("get_used_rect"), &TileMap::get_used_rect); ClassDB::bind_method(D_METHOD("map_to_world", "mappos", "ignore_half_ofs"), &TileMap::map_to_world, DEFVAL(false)); @@ -1249,7 +1304,7 @@ void TileMap::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collision_use_kinematic", PROPERTY_HINT_NONE, ""), "set_collision_use_kinematic", "get_collision_use_kinematic"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "collision_friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_collision_friction", "get_collision_friction"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "collision_bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_collision_bounce", "get_collision_bounce"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layers", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_layer", "get_collision_layer"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_layer", "get_collision_layer"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask"); ADD_GROUP("Occluder", "occluder_"); diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index f52adcd51..082e9d101 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -232,6 +233,12 @@ public: void set_collision_mask(uint32_t p_mask); uint32_t get_collision_mask() const; + void set_collision_layer_bit(int p_bit, bool p_value); + bool get_collision_layer_bit(int p_bit) const; + + void set_collision_mask_bit(int p_bit, bool p_value); + bool get_collision_mask_bit(int p_bit) const; + void set_collision_use_kinematic(bool p_use_kinematic); bool get_collision_use_kinematic() const; @@ -263,6 +270,7 @@ public: bool is_y_sort_mode_enabled() const; Array get_used_cells() const; + Array get_used_cells_by_id(int p_id) const; Rect2 get_used_rect(); // Not const because of cache void set_occluder_light_mask(int p_mask); diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp index f20a995d5..fb71b61d4 100644 --- a/scene/2d/visibility_notifier_2d.cpp +++ b/scene/2d/visibility_notifier_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,6 +33,7 @@ #include "scene/2d/animated_sprite.h" #include "scene/2d/physics_body_2d.h" #include "scene/animation/animation_player.h" +#include "scene/main/viewport.h" #include "scene/scene_string_names.h" #include "scene/scene_string_names.h" diff --git a/scene/2d/visibility_notifier_2d.h b/scene/2d/visibility_notifier_2d.h index aa4949740..38da69fae 100644 --- a/scene/2d/visibility_notifier_2d.h +++ b/scene/2d/visibility_notifier_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/y_sort.cpp b/scene/2d/y_sort.cpp index 760139287..f258b7e2e 100644 --- a/scene/2d/y_sort.cpp +++ b/scene/2d/y_sort.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/2d/y_sort.h b/scene/2d/y_sort.h index c91978849..3564cfc15 100644 --- a/scene/2d/y_sort.h +++ b/scene/2d/y_sort.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp index c42ca2f3f..c64b807e4 100644 --- a/scene/3d/area.cpp +++ b/scene/3d/area.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -28,7 +29,9 @@ /*************************************************************************/ #include "area.h" #include "scene/scene_string_names.h" +#include "servers/audio_server.h" #include "servers/physics_server.h" + void Area::set_space_override_mode(SpaceOverride p_mode) { space_override = p_mode; @@ -226,7 +229,11 @@ void Area::_clear_monitoring() { Object *obj = ObjectDB::get_instance(E->key()); Node *node = obj ? obj->cast_to<Node>() : NULL; - ERR_CONTINUE(!node); + + if (!node) //node may have been deleted in previous frame or at other legiminate point + continue; + //ERR_CONTINUE(!node); + if (!E->get().in_tree) continue; @@ -252,7 +259,11 @@ void Area::_clear_monitoring() { Object *obj = ObjectDB::get_instance(E->key()); Node *node = obj ? obj->cast_to<Node>() : NULL; - ERR_CONTINUE(!node); + + if (!node) //node may have been deleted in previous frame or at other legiminate point + continue; + //ERR_CONTINUE(!node); + if (!E->get().in_tree) continue; @@ -464,7 +475,7 @@ Array Area::get_overlapping_areas() const { bool Area::overlaps_area(Node *p_area) const { ERR_FAIL_NULL_V(p_area, false); - const Map<ObjectID, AreaState>::Element *E = area_map.find(p_area->get_instance_ID()); + const Map<ObjectID, AreaState>::Element *E = area_map.find(p_area->get_instance_id()); if (!E) return false; return E->get().in_tree; @@ -473,7 +484,7 @@ bool Area::overlaps_area(Node *p_area) const { bool Area::overlaps_body(Node *p_body) const { ERR_FAIL_NULL_V(p_body, false); - const Map<ObjectID, BodyState>::Element *E = body_map.find(p_body->get_instance_ID()); + const Map<ObjectID, BodyState>::Element *E = body_map.find(p_body->get_instance_id()); if (!E) return false; return E->get().in_tree; @@ -488,15 +499,15 @@ uint32_t Area::get_collision_mask() const { return collision_mask; } -void Area::set_layer_mask(uint32_t p_mask) { +void Area::set_collision_layer(uint32_t p_layer) { - layer_mask = p_mask; - PhysicsServer::get_singleton()->area_set_layer_mask(get_rid(), p_mask); + collision_layer = p_layer; + PhysicsServer::get_singleton()->area_set_collision_layer(get_rid(), p_layer); } -uint32_t Area::get_layer_mask() const { +uint32_t Area::get_collision_layer() const { - return layer_mask; + return collision_layer; } void Area::set_collision_mask_bit(int p_bit, bool p_value) { @@ -514,19 +525,100 @@ bool Area::get_collision_mask_bit(int p_bit) const { return get_collision_mask() & (1 << p_bit); } -void Area::set_layer_mask_bit(int p_bit, bool p_value) { +void Area::set_collision_layer_bit(int p_bit, bool p_value) { - uint32_t mask = get_layer_mask(); + uint32_t layer = get_collision_layer(); if (p_value) - mask |= 1 << p_bit; + layer |= 1 << p_bit; else - mask &= ~(1 << p_bit); - set_layer_mask(mask); + layer &= ~(1 << p_bit); + set_collision_layer(layer); +} + +bool Area::get_collision_layer_bit(int p_bit) const { + + return get_collision_layer() & (1 << p_bit); +} + +void Area::set_audio_bus_override(bool p_override) { + + audio_bus_override = p_override; +} + +bool Area::is_overriding_audio_bus() const { + + return audio_bus_override; +} + +void Area::set_audio_bus(const StringName &p_audio_bus) { + + audio_bus = p_audio_bus; +} +StringName Area::get_audio_bus() const { + + for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { + if (AudioServer::get_singleton()->get_bus_name(i) == audio_bus) { + return audio_bus; + } + } + return "Master"; +} + +void Area::set_use_reverb_bus(bool p_enable) { + + use_reverb_bus = p_enable; +} +bool Area::is_using_reverb_bus() const { + + return use_reverb_bus; } -bool Area::get_layer_mask_bit(int p_bit) const { +void Area::set_reverb_bus(const StringName &p_audio_bus) { - return get_layer_mask() & (1 << p_bit); + reverb_bus = p_audio_bus; +} +StringName Area::get_reverb_bus() const { + + for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { + if (AudioServer::get_singleton()->get_bus_name(i) == reverb_bus) { + return reverb_bus; + } + } + return "Master"; +} + +void Area::set_reverb_amount(float p_amount) { + + reverb_amount = p_amount; +} +float Area::get_reverb_amount() const { + + return reverb_amount; +} + +void Area::set_reverb_uniformity(float p_uniformity) { + + reverb_uniformity = p_uniformity; +} +float Area::get_reverb_uniformity() const { + + return reverb_uniformity; +} + +void Area::_validate_property(PropertyInfo &property) const { + + if (property.name == "audio_bus_name" || property.name == "reverb_bus_name") { + + String options; + for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { + if (i > 0) + options += ","; + String name = AudioServer::get_singleton()->get_bus_name(i); + options += name; + } + + property.hint_string = options; + } } void Area::_bind_methods() { @@ -564,14 +656,14 @@ void Area::_bind_methods() { ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &Area::set_collision_mask); ClassDB::bind_method(D_METHOD("get_collision_mask"), &Area::get_collision_mask); - ClassDB::bind_method(D_METHOD("set_layer_mask", "layer_mask"), &Area::set_layer_mask); - ClassDB::bind_method(D_METHOD("get_layer_mask"), &Area::get_layer_mask); + ClassDB::bind_method(D_METHOD("set_collision_layer", "collision_layer"), &Area::set_collision_layer); + ClassDB::bind_method(D_METHOD("get_collision_layer"), &Area::get_collision_layer); ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &Area::set_collision_mask_bit); ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &Area::get_collision_mask_bit); - ClassDB::bind_method(D_METHOD("set_layer_mask_bit", "bit", "value"), &Area::set_layer_mask_bit); - ClassDB::bind_method(D_METHOD("get_layer_mask_bit", "bit"), &Area::get_layer_mask_bit); + ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &Area::set_collision_layer_bit); + ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &Area::get_collision_layer_bit); ClassDB::bind_method(D_METHOD("set_monitorable", "enable"), &Area::set_monitorable); ClassDB::bind_method(D_METHOD("is_monitorable"), &Area::is_monitorable); @@ -588,6 +680,24 @@ void Area::_bind_methods() { ClassDB::bind_method(D_METHOD("_body_inout"), &Area::_body_inout); ClassDB::bind_method(D_METHOD("_area_inout"), &Area::_area_inout); + ClassDB::bind_method(D_METHOD("set_audio_bus_override", "enable"), &Area::set_audio_bus_override); + ClassDB::bind_method(D_METHOD("is_overriding_audio_bus"), &Area::is_overriding_audio_bus); + + ClassDB::bind_method(D_METHOD("set_audio_bus", "name"), &Area::set_audio_bus); + ClassDB::bind_method(D_METHOD("get_audio_bus"), &Area::get_audio_bus); + + ClassDB::bind_method(D_METHOD("set_use_reverb_bus", "enable"), &Area::set_use_reverb_bus); + ClassDB::bind_method(D_METHOD("is_using_reverb_bus"), &Area::is_using_reverb_bus); + + ClassDB::bind_method(D_METHOD("set_reverb_bus", "name"), &Area::set_reverb_bus); + ClassDB::bind_method(D_METHOD("get_reverb_bus"), &Area::get_reverb_bus); + + ClassDB::bind_method(D_METHOD("set_reverb_amount", "amount"), &Area::set_reverb_amount); + ClassDB::bind_method(D_METHOD("get_reverb_amount"), &Area::get_reverb_amount); + + ClassDB::bind_method(D_METHOD("set_reverb_uniformity", "amount"), &Area::set_reverb_uniformity); + ClassDB::bind_method(D_METHOD("get_reverb_uniformity"), &Area::get_reverb_uniformity); + ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "area_shape"))); ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "area_shape"))); ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body"))); @@ -609,8 +719,16 @@ void Area::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "monitoring"), "set_monitoring", "is_monitoring"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "monitorable"), "set_monitorable", "is_monitorable"); ADD_GROUP("Collision", "collision_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layers", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_layer_mask", "get_layer_mask"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); + ADD_GROUP("Audio Bus", "audio_bus_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_bus_override"), "set_audio_bus_override", "is_overriding_audio_bus"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "audio_bus_name", PROPERTY_HINT_ENUM, ""), "set_audio_bus", "get_audio_bus"); + ADD_GROUP("Reverb Bus", "reverb_bus_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "reverb_bus_enable"), "set_use_reverb_bus", "is_using_reverb_bus"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "reverb_bus_name", PROPERTY_HINT_ENUM, ""), "set_reverb_bus", "get_reverb_bus"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "reverb_bus_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_reverb_amount", "get_reverb_amount"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "reverb_bus_uniformity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_reverb_uniformity", "get_reverb_uniformity"); } Area::Area() @@ -627,10 +745,18 @@ Area::Area() priority = 0; monitoring = false; collision_mask = 1; - layer_mask = 1; + collision_layer = 1; set_ray_pickable(false); set_monitoring(true); set_monitorable(true); + + audio_bus_override = false; + audio_bus = "Master"; + + use_reverb_bus = false; + reverb_bus = "Master"; + reverb_amount = 0.0; + reverb_uniformity = 0.0; } Area::~Area() { diff --git a/scene/3d/area.h b/scene/3d/area.h index a50f101ec..5df308fc4 100644 --- a/scene/3d/area.h +++ b/scene/3d/area.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -54,7 +55,7 @@ private: real_t angular_damp; real_t linear_damp; uint32_t collision_mask; - uint32_t layer_mask; + uint32_t collision_layer; int priority; bool monitoring; bool monitorable; @@ -125,6 +126,16 @@ private: Map<ObjectID, AreaState> area_map; void _clear_monitoring(); + bool audio_bus_override; + StringName audio_bus; + + bool use_reverb_bus; + StringName reverb_bus; + float reverb_amount; + float reverb_uniformity; + + void _validate_property(PropertyInfo &property) const; + protected: void _notification(int p_what); static void _bind_methods(); @@ -163,14 +174,14 @@ public: void set_collision_mask(uint32_t p_mask); uint32_t get_collision_mask() const; - void set_layer_mask(uint32_t p_mask); - uint32_t get_layer_mask() const; + void set_collision_layer(uint32_t p_layer); + uint32_t get_collision_layer() const; void set_collision_mask_bit(int p_bit, bool p_value); bool get_collision_mask_bit(int p_bit) const; - void set_layer_mask_bit(int p_bit, bool p_value); - bool get_layer_mask_bit(int p_bit) const; + void set_collision_layer_bit(int p_bit, bool p_value); + bool get_collision_layer_bit(int p_bit) const; Array get_overlapping_bodies() const; Array get_overlapping_areas() const; //function for script @@ -178,6 +189,24 @@ public: bool overlaps_area(Node *p_area) const; bool overlaps_body(Node *p_body) const; + void set_audio_bus_override(bool p_override); + bool is_overriding_audio_bus() const; + + void set_audio_bus(const StringName &p_audio_bus); + StringName get_audio_bus() const; + + void set_use_reverb_bus(bool p_enable); + bool is_using_reverb_bus() const; + + void set_reverb_bus(const StringName &p_audio_bus); + StringName get_reverb_bus() const; + + void set_reverb_amount(float p_amount); + float get_reverb_amount() const; + + void set_reverb_uniformity(float p_uniformity); + float get_reverb_uniformity() const; + Area(); ~Area(); }; diff --git a/scene/3d/arvr_nodes.cpp b/scene/3d/arvr_nodes.cpp new file mode 100644 index 000000000..3c99f7fb3 --- /dev/null +++ b/scene/3d/arvr_nodes.cpp @@ -0,0 +1,426 @@ +/*************************************************************************/ +/* arvr_nodes.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "arvr_nodes.h" +#include "core/os/input.h" +#include "servers/arvr/arvr_interface.h" +#include "servers/arvr/arvr_positional_tracker.h" +#include "servers/arvr_server.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void ARVRCamera::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + // need to find our ARVROrigin parent and let it know we're it's camera! + ARVROrigin *origin = get_parent()->cast_to<ARVROrigin>(); + if (origin != NULL) { + origin->set_tracked_camera(this); + } + }; break; + case NOTIFICATION_EXIT_TREE: { + // need to find our ARVROrigin parent and let it know we're no longer it's camera! + ARVROrigin *origin = get_parent()->cast_to<ARVROrigin>(); + if (origin != NULL) { + origin->clear_tracked_camera_if(this); + } + }; break; + }; +}; + +String ARVRCamera::get_configuration_warning() const { + if (!is_visible() || !is_inside_tree()) + return String(); + + // must be child node of ARVROrigin! + ARVROrigin *origin = get_parent()->cast_to<ARVROrigin>(); + if (origin == NULL) { + return TTR("ARVRCamera must have an ARVROrigin node as its parent"); + }; + + return String(); +}; + +ARVRCamera::ARVRCamera(){ + // nothing to do here yet for now.. +}; + +ARVRCamera::~ARVRCamera(){ + // nothing to do here yet for now.. +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void ARVRController::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + set_process_internal(true); + }; break; + case NOTIFICATION_EXIT_TREE: { + set_process_internal(false); + }; break; + case NOTIFICATION_INTERNAL_PROCESS: { + // get our ARVRServer + ARVRServer *arvr_server = ARVRServer::get_singleton(); + ERR_FAIL_NULL(arvr_server); + + // find the tracker for our controller + ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, controller_id); + if (tracker == NULL) { + // this controller is currently turned off + is_active = false; + button_states = 0; + } else { + is_active = true; + set_transform(tracker->get_transform(true)); + + int joy_id = tracker->get_joy_id(); + if (joy_id >= 0) { + int mask = 1; + // check button states + for (int i = 0; i < 16; i++) { + bool was_pressed = (button_states && mask) == mask; + bool is_pressed = Input::get_singleton()->is_joy_button_pressed(joy_id, i); + + if (!was_pressed && is_pressed) { + emit_signal("button_pressed", i); + button_states += mask; + } else if (was_pressed && !is_pressed) { + emit_signal("button_release", i); + button_states -= mask; + }; + + mask = mask << 1; + }; + + } else { + button_states = 0; + }; + }; + }; break; + default: + break; + }; +}; + +void ARVRController::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_controller_id", "controller_id"), &ARVRController::set_controller_id); + ClassDB::bind_method(D_METHOD("get_controller_id"), &ARVRController::get_controller_id); + ADD_PROPERTY(PropertyInfo(Variant::INT, "controller_id"), "set_controller_id", "get_controller_id"); + ClassDB::bind_method(D_METHOD("get_controller_name"), &ARVRController::get_controller_name); + + // passthroughs to information about our related joystick + ClassDB::bind_method(D_METHOD("get_joystick_id"), &ARVRController::get_joystick_id); + ClassDB::bind_method(D_METHOD("is_button_pressed", "button"), &ARVRController::is_button_pressed); + ClassDB::bind_method(D_METHOD("get_joystick_axis", "axis"), &ARVRController::get_joystick_axis); + + ClassDB::bind_method(D_METHOD("get_is_active"), &ARVRController::get_is_active); + + ADD_SIGNAL(MethodInfo("button_pressed", PropertyInfo(Variant::INT, "button"))); + ADD_SIGNAL(MethodInfo("button_release", PropertyInfo(Variant::INT, "button"))); +}; + +void ARVRController::set_controller_id(int p_controller_id) { + // we don't check any bounds here, this controller may not yet be active and just be a place holder until it is. + controller_id = p_controller_id; +}; + +int ARVRController::get_controller_id(void) const { + return controller_id; +}; + +String ARVRController::get_controller_name(void) const { + // get our ARVRServer + ARVRServer *arvr_server = ARVRServer::get_singleton(); + ERR_FAIL_NULL_V(arvr_server, String()); + + ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, controller_id); + if (tracker == NULL) { + return String("Not connected"); + }; + + return tracker->get_name(); +}; + +int ARVRController::get_joystick_id() const { + // get our ARVRServer + ARVRServer *arvr_server = ARVRServer::get_singleton(); + ERR_FAIL_NULL_V(arvr_server, 0); + + ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, controller_id); + if (tracker == NULL) { + return 0; + }; + + return tracker->get_joy_id(); +}; + +int ARVRController::is_button_pressed(int p_button) const { + int joy_id = get_joystick_id(); + if (joy_id == 0) { + return false; + }; + + return Input::get_singleton()->is_joy_button_pressed(joy_id, p_button); +}; + +float ARVRController::get_joystick_axis(int p_axis) const { + int joy_id = get_joystick_id(); + if (joy_id == 0) { + return 0.0; + }; + + return Input::get_singleton()->get_joy_axis(joy_id, p_axis); +}; + +bool ARVRController::get_is_active() const { + return is_active; +}; + +String ARVRController::get_configuration_warning() const { + if (!is_visible() || !is_inside_tree()) + return String(); + + // must be child node of ARVROrigin! + ARVROrigin *origin = get_parent()->cast_to<ARVROrigin>(); + if (origin == NULL) { + return TTR("ARVRController must have an ARVROrigin node as its parent"); + }; + + if (controller_id == 0) { + return TTR("The controller id must not be 0 or this controller will not be bound to an actual controller"); + }; + + return String(); +}; + +ARVRController::ARVRController() { + controller_id = 0; + is_active = true; +}; + +ARVRController::~ARVRController(){ + // nothing to do here yet for now.. +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void ARVRAnchor::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + set_process_internal(true); + }; break; + case NOTIFICATION_EXIT_TREE: { + set_process_internal(false); + }; break; + case NOTIFICATION_INTERNAL_PROCESS: { + // get our ARVRServer + ARVRServer *arvr_server = ARVRServer::get_singleton(); + ERR_FAIL_NULL(arvr_server); + + // find the tracker for our anchor + ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_ANCHOR, anchor_id); + if (tracker == NULL) { + // this anchor is currently not available + is_active = false; + } else { + is_active = true; + Transform transform; + + // we'll need our world_scale + real_t world_scale = arvr_server->get_world_scale(); + + // get our info from our tracker + transform.basis = tracker->get_orientation(); + transform.origin = tracker->get_position(); // <-- already adjusted to world scale + + // our basis is scaled to the size of the plane the anchor is tracking + // extract the size from our basis and reset the scale + size = transform.basis.get_scale() * world_scale; + transform.basis.set_scale(Vector3(1.0, 1.0, 1.0)); + + // apply our reference frame and set our transform + set_transform(arvr_server->get_reference_frame() * transform); + }; + }; break; + default: + break; + }; +}; + +void ARVRAnchor::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_anchor_id", "anchor_id"), &ARVRAnchor::set_anchor_id); + ClassDB::bind_method(D_METHOD("get_anchor_id"), &ARVRAnchor::get_anchor_id); + ADD_PROPERTY(PropertyInfo(Variant::INT, "anchor_id"), "set_anchor_id", "get_anchor_id"); + ClassDB::bind_method(D_METHOD("get_anchor_name"), &ARVRAnchor::get_anchor_name); + + ClassDB::bind_method(D_METHOD("get_is_active"), &ARVRAnchor::get_is_active); + ClassDB::bind_method(D_METHOD("get_size"), &ARVRAnchor::get_size); +}; + +void ARVRAnchor::set_anchor_id(int p_anchor_id) { + // we don't check any bounds here, this anchor may not yet be active and just be a place holder until it is. + anchor_id = p_anchor_id; +}; + +int ARVRAnchor::get_anchor_id(void) const { + return anchor_id; +}; + +Vector3 ARVRAnchor::get_size() const { + return size; +}; + +String ARVRAnchor::get_anchor_name(void) const { + // get our ARVRServer + ARVRServer *arvr_server = ARVRServer::get_singleton(); + ERR_FAIL_NULL_V(arvr_server, String()); + + ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_ANCHOR, anchor_id); + if (tracker == NULL) { + return String("Not connected"); + }; + + return tracker->get_name(); +}; + +bool ARVRAnchor::get_is_active() const { + return is_active; +}; + +String ARVRAnchor::get_configuration_warning() const { + if (!is_visible() || !is_inside_tree()) + return String(); + + // must be child node of ARVROrigin! + ARVROrigin *origin = get_parent()->cast_to<ARVROrigin>(); + if (origin == NULL) { + return TTR("ARVRAnchor must have an ARVROrigin node as its parent"); + }; + + if (anchor_id == 0) { + return TTR("The anchor id must not be 0 or this anchor will not be bound to an actual anchor"); + }; + + return String(); +}; + +ARVRAnchor::ARVRAnchor() { + anchor_id = 0; + is_active = true; +}; + +ARVRAnchor::~ARVRAnchor(){ + // nothing to do here yet for now.. +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +String ARVROrigin::get_configuration_warning() const { + if (!is_visible() || !is_inside_tree()) + return String(); + + if (tracked_camera == NULL) + return TTR("ARVROrigin requires an ARVRCamera child node"); + + return String(); +}; + +void ARVROrigin::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_world_scale", "world_scale"), &ARVROrigin::set_world_scale); + ClassDB::bind_method(D_METHOD("get_world_scale"), &ARVROrigin::get_world_scale); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "world_scale"), "set_world_scale", "get_world_scale"); +}; + +void ARVROrigin::set_tracked_camera(ARVRCamera *p_tracked_camera) { + tracked_camera = p_tracked_camera; +}; + +void ARVROrigin::clear_tracked_camera_if(ARVRCamera *p_tracked_camera) { + if (tracked_camera == p_tracked_camera) { + tracked_camera = NULL; + }; +}; + +float ARVROrigin::get_world_scale() const { + // get our ARVRServer + ARVRServer *arvr_server = ARVRServer::get_singleton(); + ERR_FAIL_NULL_V(arvr_server, 1.0); + + return arvr_server->get_world_scale(); +}; + +void ARVROrigin::set_world_scale(float p_world_scale) { + // get our ARVRServer + ARVRServer *arvr_server = ARVRServer::get_singleton(); + ERR_FAIL_NULL(arvr_server); + + arvr_server->set_world_scale(p_world_scale); +}; + +void ARVROrigin::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + set_process_internal(true); + }; break; + case NOTIFICATION_EXIT_TREE: { + set_process_internal(false); + }; break; + case NOTIFICATION_INTERNAL_PROCESS: { + // get our ARVRServer + ARVRServer *arvr_server = ARVRServer::get_singleton(); + ERR_FAIL_NULL(arvr_server); + + // set our world origin to our node transform + arvr_server->set_world_origin(get_global_transform()); + + // check if we have a primary interface + Ref<ARVRInterface> arvr_interface = arvr_server->get_primary_interface(); + if (arvr_interface.is_valid() && tracked_camera != NULL) { + // get our positioning transform for our headset + Transform t = arvr_interface->get_transform_for_eye(ARVRInterface::EYE_MONO, Transform()); + + // now apply this to our camera + tracked_camera->set_transform(t); + }; + }; break; + default: + break; + }; +}; + +ARVROrigin::ARVROrigin() { + tracked_camera = NULL; +}; + +ARVROrigin::~ARVROrigin(){ + // nothing to do here yet for now.. +}; diff --git a/scene/3d/arvr_nodes.h b/scene/3d/arvr_nodes.h new file mode 100644 index 000000000..936519126 --- /dev/null +++ b/scene/3d/arvr_nodes.h @@ -0,0 +1,157 @@ +/*************************************************************************/ +/* arvr_nodes.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef ARVR_NODES_H +#define ARVR_NODES_H + +#include "scene/3d/camera.h" +#include "scene/3d/spatial.h" + +/** + @author Bastiaan Olij <mux213@gmail.com> +**/ + +/* + ARVRCamera is a subclass of camera which will register itself with its parent ARVROrigin and as a result is automatically positioned +*/ +class ARVRCamera : public Camera { + + GDCLASS(ARVRCamera, Camera); + +protected: + void _notification(int p_what); + +public: + String get_configuration_warning() const; + + ARVRCamera(); + ~ARVRCamera(); +}; + +/* + ARVRController is a helper node that automatically updates it's position based on tracker data. + + It must be a child node of our ARVROrigin node +*/ + +class ARVRController : public Spatial { + + GDCLASS(ARVRController, Spatial); + +private: + int controller_id; + bool is_active; + int button_states; + +protected: + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_controller_id(int p_controller_id); + int get_controller_id(void) const; + String get_controller_name(void) const; + + int get_joystick_id() const; + int is_button_pressed(int p_button) const; + float get_joystick_axis(int p_axis) const; + + bool get_is_active() const; + + String get_configuration_warning() const; + + ARVRController(); + ~ARVRController(); +}; + +/* + ARVRAnchor is a helper node that automatically updates it's position based on anchor data, it represents a real world location. + It must be a child node of our ARVROrigin node +*/ + +class ARVRAnchor : public Spatial { + GDCLASS(ARVRAnchor, Spatial); + +private: + int anchor_id; + bool is_active; + Vector3 size; + +protected: + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_anchor_id(int p_anchor_id); + int get_anchor_id(void) const; + String get_anchor_name(void) const; + + bool get_is_active() const; + Vector3 get_size() const; + + String get_configuration_warning() const; + + ARVRAnchor(); + ~ARVRAnchor(); +}; + +/* + ARVROrigin is special spatial node that acts as our origin point mapping our real world center of our tracking volume into our virtual world. + + It is this point that you will move around the world as the player 'moves while standing still', i.e. the player moves through teleporting or controller inputs as opposed to physically moving. + + Our camera and controllers will always be child nodes and thus place relative to this origin point. + This node will automatically locate any camera child nodes and update its position while our ARVRController node will handle tracked controllers. +*/ +class ARVROrigin : public Spatial { + + GDCLASS(ARVROrigin, Spatial); + +private: + ARVRCamera *tracked_camera; + +protected: + void _notification(int p_what); + static void _bind_methods(); + +public: + String get_configuration_warning() const; + + void set_tracked_camera(ARVRCamera *p_tracked_camera); + void clear_tracked_camera_if(ARVRCamera *p_tracked_camera); + + float get_world_scale() const; + void set_world_scale(float p_world_scale); + + ARVROrigin(); + ~ARVROrigin(); +}; + +#endif /* ARVR_NODES_H */ diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp new file mode 100644 index 000000000..6abc2caac --- /dev/null +++ b/scene/3d/audio_stream_player_3d.cpp @@ -0,0 +1,930 @@ +#include "audio_stream_player_3d.h" +#include "engine.h" +#include "scene/3d/area.h" +#include "scene/3d/camera.h" +#include "scene/main/viewport.h" +void AudioStreamPlayer3D::_mix_audio() { + + if (!stream_playback.is_valid()) { + return; + } + + if (!active) { + return; + } + + bool started = false; + if (setseek >= 0.0) { + stream_playback->start(setseek); + setseek = -1.0; //reset seek + started = true; + } + + //get data + AudioFrame *buffer = mix_buffer.ptr(); + int buffer_size = mix_buffer.size(); + + //mix + if (output_count > 0 || out_of_range_mode == OUT_OF_RANGE_MIX) { + + float pitch_scale = 0.0; + if (output_count) { + //used for doppler, not realistic but good enough + for (int i = 0; i < output_count; i++) { + pitch_scale += outputs[i].pitch_scale; + } + pitch_scale /= float(output_count); + } else { + pitch_scale = 1.0; + } + + stream_playback->mix(buffer, pitch_scale, buffer_size); + } + + //write all outputs + for (int i = 0; i < output_count; i++) { + + Output current = outputs[i]; + + //see if current output exists, to keep volume ramp + bool found = false; + for (int j = i; j < prev_output_count; j++) { + if (prev_outputs[j].viewport == current.viewport) { + if (j != i) { + SWAP(prev_outputs[j], prev_outputs[i]); + } + found = true; + break; + } + } + + bool interpolate_filter = !started; + ; + if (!found) { + //create new if was not used before + if (prev_output_count < MAX_OUTPUTS) { + prev_outputs[prev_output_count] = prev_outputs[i]; //may be owned by another viewport + prev_output_count++; + } + prev_outputs[i] = current; + interpolate_filter = false; + } + + //mix! + + int buffers = 0; + int first = 0; + + switch (AudioServer::get_singleton()->get_speaker_mode()) { + + case AudioServer::SPEAKER_MODE_STEREO: { + buffers = 1; + first = 0; + + } break; + case AudioServer::SPEAKER_SURROUND_51: { + buffers = 2; + first = 1; + + } break; + case AudioServer::SPEAKER_SURROUND_71: { + + buffers = 3; + first = 1; + + } break; + } + + for (int k = 0; k < buffers; k++) { + AudioFrame vol_inc = (current.vol[k] - prev_outputs[i].vol[k]) / float(buffer_size); + AudioFrame vol = current.vol[k]; + + AudioFrame *target = AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, first + k); + + current.filter.set_mode(AudioFilterSW::HIGHSHELF); + current.filter.set_sampling_rate(AudioServer::get_singleton()->get_mix_rate()); + current.filter.set_cutoff(attenuation_filter_cutoff_hz); + current.filter.set_resonance(1); + current.filter.set_stages(1); + current.filter.set_gain(current.filter_gain); + + if (interpolate_filter) { + + current.filter_process[k * 2 + 0] = prev_outputs[i].filter_process[k * 2 + 0]; + current.filter_process[k * 2 + 1] = prev_outputs[i].filter_process[k * 2 + 1]; + + current.filter_process[k * 2 + 0].set_filter(¤t.filter, false); + current.filter_process[k * 2 + 1].set_filter(¤t.filter, false); + + current.filter_process[k * 2 + 0].update_coeffs(buffer_size); + current.filter_process[k * 2 + 1].update_coeffs(buffer_size); + for (int j = 0; j < buffer_size; j++) { + + AudioFrame f = buffer[j] * vol; + current.filter_process[k * 2 + 0].process_one_interp(f.l); + current.filter_process[k * 2 + 1].process_one_interp(f.r); + + target[j] += f; + vol += vol_inc; + } + } else { + current.filter_process[k * 2 + 0].set_filter(¤t.filter); + current.filter_process[k * 2 + 1].set_filter(¤t.filter); + + current.filter_process[k * 2 + 0].update_coeffs(); + current.filter_process[k * 2 + 1].update_coeffs(); + for (int j = 0; j < buffer_size; j++) { + + AudioFrame f = buffer[j] * vol; + current.filter_process[k * 2 + 0].process_one(f.l); + current.filter_process[k * 2 + 1].process_one(f.r); + + target[j] += f; + vol += vol_inc; + } + } + + if (current.reverb_bus_index >= 0) { + + AudioFrame *rtarget = AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.reverb_bus_index, first + k); + + if (current.reverb_bus_index == prev_outputs[i].reverb_bus_index) { + AudioFrame rvol_inc = (current.reverb_vol[k] - prev_outputs[i].reverb_vol[k]) / float(buffer_size); + AudioFrame rvol = prev_outputs[i].reverb_vol[k]; + + for (int j = 0; j < buffer_size; j++) { + + rtarget[j] += buffer[j] * rvol; + rvol += rvol_inc; + } + } else { + + AudioFrame rvol = current.reverb_vol[k]; + for (int j = 0; j < buffer_size; j++) { + + rtarget[j] += buffer[j] * rvol; + } + } + } + } + + prev_outputs[i] = current; + } + + prev_output_count = output_count; + + //stream is no longer active, disable this. + if (!stream_playback->is_playing()) { + active = false; + } + + output_ready = false; +} + +float AudioStreamPlayer3D::_get_attenuation_db(float p_distance) const { + + float att; + switch (attenuation_model) { + case ATTENUATION_INVERSE_DISTANCE: { + att = Math::linear2db(1.0 / ((p_distance / unit_size) + 000001)); + } break; + case ATTENUATION_INVERSE_SQUARE_DISTANCE: { + float d = (p_distance / unit_size); + d *= d; + att = Math::linear2db(1.0 / (d + 0.00001)); + } break; + case ATTENUATION_LOGARITHMIC: { + att = -20 * Math::log(p_distance / unit_size + 000001); + } break; + } + + att += unit_db; + if (att > max_db) { + att = max_db; + } + + return att; +} + +void _update_sound() { +} + +void AudioStreamPlayer3D::_notification(int p_what) { + + if (p_what == NOTIFICATION_ENTER_TREE) { + + velocity_tracker->reset(get_global_transform().origin); + AudioServer::get_singleton()->add_callback(_mix_audios, this); + if (autoplay && !get_tree()->is_editor_hint()) { + play(); + } + } + + if (p_what == NOTIFICATION_EXIT_TREE) { + + AudioServer::get_singleton()->remove_callback(_mix_audios, this); + } + if (p_what == NOTIFICATION_TRANSFORM_CHANGED) { + + if (doppler_tracking != DOPPLER_TRACKING_DISABLED) { + velocity_tracker->update_position(get_global_transform().origin); + } + } + + if (p_what == NOTIFICATION_INTERNAL_FIXED_PROCESS) { + + //update anything related to position first, if possible of course + + if (!output_ready) { + + Vector3 linear_velocity; + + //compute linear velocity for doppler + if (doppler_tracking != DOPPLER_TRACKING_DISABLED) { + linear_velocity = velocity_tracker->get_tracked_linear_velocity(); + } + + Ref<World> world = get_world(); + ERR_FAIL_COND(world.is_null()); + + int new_output_count = 0; + + Vector3 global_pos = get_global_transform().origin; + + int bus_index = AudioServer::get_singleton()->thread_find_bus_index(bus); + + //check if any area is diverting sound into a bus + + PhysicsDirectSpaceState *space_state = PhysicsServer::get_singleton()->space_get_direct_state(world->get_space()); + + PhysicsDirectSpaceState::ShapeResult sr[MAX_INTERSECT_AREAS]; + + int areas = space_state->intersect_point(global_pos, sr, MAX_INTERSECT_AREAS, Set<RID>(), area_mask, PhysicsDirectSpaceState::TYPE_MASK_AREA); + Area *area = NULL; + + for (int i = 0; i < areas; i++) { + if (!sr[i].collider) + continue; + + Area *tarea = sr[i].collider->cast_to<Area>(); + if (!tarea) + continue; + + if (!tarea->is_overriding_audio_bus() && !tarea->is_using_reverb_bus()) + continue; + + area = tarea; + break; + } + + List<Camera *> cameras; + world->get_camera_list(&cameras); + + for (List<Camera *>::Element *E = cameras.front(); E; E = E->next()) { + + Camera *camera = E->get(); + Viewport *vp = camera->get_viewport(); + if (!vp->is_audio_listener()) + continue; + + Vector3 local_pos = camera->get_global_transform().orthonormalized().affine_inverse().xform(global_pos); + + float dist = local_pos.length(); + + Vector3 area_sound_pos; + Vector3 cam_area_pos; + + if (area && area->is_using_reverb_bus() && area->get_reverb_uniformity() > 0) { + area_sound_pos = space_state->get_closest_point_to_object_volume(area->get_rid(), camera->get_global_transform().origin); + cam_area_pos = camera->get_global_transform().affine_inverse().xform(area_sound_pos); + } + + if (max_distance > 0) { + + float total_max = max_distance; + + if (area && area->is_using_reverb_bus() && area->get_reverb_uniformity() > 0) { + total_max = MAX(total_max, cam_area_pos.length()); + } + if (total_max > max_distance) { + continue; //cant hear this sound in this camera + } + } + + float multiplier = Math::db2linear(_get_attenuation_db(dist)); + if (max_distance > 0) { + multiplier *= MAX(0, 1.0 - (dist / max_distance)); + } + + Output output; + output.bus_index = bus_index; + output.reverb_bus_index = -1; //no reverb by default + output.viewport = vp; + + float db_att = (1.0 - MIN(1.0, multiplier)) * attenuation_filter_db; + + if (emission_angle_enabled) { + Vector3 camtopos = global_pos - camera->get_global_transform().origin; + float c = camtopos.normalized().dot(get_global_transform().basis.get_axis(2).normalized()); //it's z negative + float angle = Math::rad2deg(Math::acos(c)); + if (angle > emission_angle) + db_att -= -emission_angle_filter_attenuation_db; + } + + output.filter_gain = Math::db2linear(db_att); + + Vector3 flat_pos = local_pos; + flat_pos.y = 0; + flat_pos.normalize(); + + switch (AudioServer::get_singleton()->get_speaker_mode()) { + + case AudioServer::SPEAKER_MODE_STEREO: { + + float c = flat_pos.x * 0.5 + 0.5; + output.vol[0].l = 1.0 - c; + output.vol[0].r = c; + + output.vol[0] *= multiplier; + + } break; + case AudioServer::SPEAKER_SURROUND_51: { + + float xl = Vector3(-1, 0, -1).normalized().dot(flat_pos) * 0.5 + 0.5; + float xr = Vector3(1, 0, -1).normalized().dot(flat_pos) * 0.5 + 0.5; + + output.vol[0].l = xl; + output.vol[1].r = 1.0 - xl; + output.vol[0].r = xr; + output.vol[1].l = 1.0 - xr; + + output.vol[0] *= multiplier; + output.vol[1] *= multiplier; + } break; + case AudioServer::SPEAKER_SURROUND_71: { + + float xl = Vector3(-1, 0, -1).normalized().dot(flat_pos) * 0.5 + 0.5; + float xr = Vector3(1, 0, -1).normalized().dot(flat_pos) * 0.5 + 0.5; + + output.vol[0].l = xl; + output.vol[1].r = 1.0 - xl; + output.vol[0].r = xr; + output.vol[1].l = 1.0 - xr; + + float c = flat_pos.x * 0.5 + 0.5; + output.vol[2].l = 1.0 - c; + output.vol[2].r = c; + + output.vol[0] *= multiplier; + output.vol[1] *= multiplier; + output.vol[2] *= multiplier; + + } break; + } + + bool filled_reverb = false; + int vol_index_max = AudioServer::get_singleton()->get_speaker_mode() + 1; + + if (area) { + + if (area->is_overriding_audio_bus()) { + //override audio bus + StringName bus_name = area->get_audio_bus(); + output.bus_index = AudioServer::get_singleton()->thread_find_bus_index(bus_name); + } + + if (area->is_using_reverb_bus()) { + + filled_reverb = true; + StringName bus_name = area->get_reverb_bus(); + output.reverb_bus_index = AudioServer::get_singleton()->thread_find_bus_index(bus_name); + + float uniformity = area->get_reverb_uniformity(); + float area_send = area->get_reverb_amount(); + + if (uniformity > 0.0) { + + float distance = cam_area_pos.length(); + float attenuation = Math::db2linear(_get_attenuation_db(distance)); + + //float dist_att_db = -20 * Math::log(dist + 0.00001); //logarithmic attenuation, like in real life + + float center_val[3] = { 0.5, 0.25, 0.16666 }; + AudioFrame center_frame(center_val[vol_index_max - 1], center_val[vol_index_max - 1]); + + if (attenuation < 1.0) { + //pan the uniform sound + Vector3 rev_pos = cam_area_pos; + rev_pos.y = 0; + rev_pos.normalize(); + + switch (AudioServer::get_singleton()->get_speaker_mode()) { + + case AudioServer::SPEAKER_MODE_STEREO: { + + float c = rev_pos.x * 0.5 + 0.5; + output.reverb_vol[0].l = 1.0 - c; + output.reverb_vol[0].r = c; + + } break; + case AudioServer::SPEAKER_SURROUND_51: { + + float xl = Vector3(-1, 0, -1).normalized().dot(rev_pos) * 0.5 + 0.5; + float xr = Vector3(1, 0, -1).normalized().dot(rev_pos) * 0.5 + 0.5; + + output.reverb_vol[0].l = xl; + output.reverb_vol[1].r = 1.0 - xl; + output.reverb_vol[0].r = xr; + output.reverb_vol[1].l = 1.0 - xr; + + } break; + case AudioServer::SPEAKER_SURROUND_71: { + + float xl = Vector3(-1, 0, -1).normalized().dot(rev_pos) * 0.5 + 0.5; + float xr = Vector3(1, 0, -1).normalized().dot(rev_pos) * 0.5 + 0.5; + + output.reverb_vol[0].l = xl; + output.reverb_vol[1].r = 1.0 - xl; + output.reverb_vol[0].r = xr; + output.reverb_vol[1].l = 1.0 - xr; + + float c = rev_pos.x * 0.5 + 0.5; + output.reverb_vol[2].l = 1.0 - c; + output.reverb_vol[2].r = c; + + } break; + } + + for (int i = 0; i < vol_index_max; i++) { + + output.reverb_vol[i] = output.reverb_vol[i].linear_interpolate(center_frame, attenuation); + } + } else { + for (int i = 0; i < vol_index_max; i++) { + + output.reverb_vol[i] = center_frame; + } + } + + for (int i = 0; i < vol_index_max; i++) { + + output.reverb_vol[i] = output.vol[i].linear_interpolate(output.reverb_vol[i] * attenuation, uniformity); + output.reverb_vol[i] *= area_send; + } + + } else { + + for (int i = 0; i < vol_index_max; i++) { + + output.reverb_vol[i] = output.vol[i] * area_send; + } + } + } + } + + if (doppler_tracking != DOPPLER_TRACKING_DISABLED) { + + Vector3 camera_velocity = camera->get_doppler_tracked_velocity(); + + Vector3 local_velocity = camera->get_global_transform().orthonormalized().basis.xform_inv(linear_velocity - camera_velocity); + + if (local_velocity == Vector3()) { + output.pitch_scale = 1.0; + } else { + float approaching = local_pos.normalized().dot(local_velocity.normalized()); + float velocity = local_velocity.length(); + float speed_of_sound = 343.0; + + output.pitch_scale = speed_of_sound / (speed_of_sound + velocity * approaching); + output.pitch_scale = CLAMP(output.pitch_scale, (1 / 8.0), 8.0); //avoid crazy stuff + } + + } else { + output.pitch_scale = 1.0; + } + + if (!filled_reverb) { + + for (int i = 0; i < vol_index_max; i++) { + + output.reverb_vol[i] = AudioFrame(0, 0); + } + } + + outputs[new_output_count] = output; + new_output_count++; + if (new_output_count == MAX_OUTPUTS) + break; + } + + output_count = new_output_count; + output_ready = true; + } + + //start playing if requested + if (setplay >= 0.0) { + setseek = setplay; + active = true; + setplay = -1; + _change_notify("playing"); //update property in editor + } + + //stop playing if no longer active + if (!active) { + set_fixed_process_internal(false); + _change_notify("playing"); //update property in editor + } + } +} + +void AudioStreamPlayer3D::set_stream(Ref<AudioStream> p_stream) { + + ERR_FAIL_COND(!p_stream.is_valid()); + AudioServer::get_singleton()->lock(); + + mix_buffer.resize(AudioServer::get_singleton()->thread_get_mix_buffer_size()); + + if (stream_playback.is_valid()) { + stream_playback.unref(); + stream.unref(); + active = false; + setseek = -1; + } + + stream = p_stream; + stream_playback = p_stream->instance_playback(); + + if (stream_playback.is_null()) { + stream.unref(); + ERR_FAIL_COND(stream_playback.is_null()); + } + + AudioServer::get_singleton()->unlock(); +} + +Ref<AudioStream> AudioStreamPlayer3D::get_stream() const { + + return stream; +} + +void AudioStreamPlayer3D::set_unit_db(float p_volume) { + + unit_db = p_volume; +} +float AudioStreamPlayer3D::get_unit_db() const { + + return unit_db; +} + +void AudioStreamPlayer3D::set_unit_size(float p_volume) { + + unit_size = p_volume; +} +float AudioStreamPlayer3D::get_unit_size() const { + + return unit_size; +} + +void AudioStreamPlayer3D::set_max_db(float p_boost) { + + max_db = p_boost; +} +float AudioStreamPlayer3D::get_max_db() const { + + return max_db; +} + +void AudioStreamPlayer3D::play(float p_from_pos) { + + if (stream_playback.is_valid()) { + setplay = p_from_pos; + output_ready = false; + set_fixed_process_internal(true); + } +} + +void AudioStreamPlayer3D::seek(float p_seconds) { + + if (stream_playback.is_valid()) { + setseek = p_seconds; + } +} + +void AudioStreamPlayer3D::stop() { + + if (stream_playback.is_valid()) { + active = false; + set_fixed_process_internal(false); + setplay = -1; + } +} + +bool AudioStreamPlayer3D::is_playing() const { + + if (stream_playback.is_valid()) { + return active; // && stream_playback->is_playing(); + } + + return false; +} + +float AudioStreamPlayer3D::get_pos() { + + if (stream_playback.is_valid()) { + return stream_playback->get_pos(); + } + + return 0; +} + +void AudioStreamPlayer3D::set_bus(const StringName &p_bus) { + + //if audio is active, must lock this + AudioServer::get_singleton()->lock(); + bus = p_bus; + AudioServer::get_singleton()->unlock(); +} +StringName AudioStreamPlayer3D::get_bus() const { + + for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { + if (AudioServer::get_singleton()->get_bus_name(i) == bus) { + return bus; + } + } + return "Master"; +} + +void AudioStreamPlayer3D::set_autoplay(bool p_enable) { + + autoplay = p_enable; +} +bool AudioStreamPlayer3D::is_autoplay_enabled() { + + return autoplay; +} + +void AudioStreamPlayer3D::_set_playing(bool p_enable) { + + if (p_enable) + play(); + else + stop(); +} +bool AudioStreamPlayer3D::_is_active() const { + + return active; +} + +void AudioStreamPlayer3D::_validate_property(PropertyInfo &property) const { + + if (property.name == "bus") { + + String options; + for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { + if (i > 0) + options += ","; + String name = AudioServer::get_singleton()->get_bus_name(i); + options += name; + } + + property.hint_string = options; + } +} + +void AudioStreamPlayer3D::_bus_layout_changed() { + + _change_notify(); +} + +void AudioStreamPlayer3D::set_max_distance(float p_metres) { + + ERR_FAIL_COND(p_metres < 0.0); + max_distance = p_metres; +} + +float AudioStreamPlayer3D::get_max_distance() const { + + return max_distance; +} + +void AudioStreamPlayer3D::set_area_mask(uint32_t p_mask) { + + area_mask = p_mask; +} + +uint32_t AudioStreamPlayer3D::get_area_mask() const { + + return area_mask; +} + +void AudioStreamPlayer3D::set_emission_angle_enabled(bool p_enable) { + emission_angle_enabled = p_enable; + update_gizmo(); +} + +bool AudioStreamPlayer3D::is_emission_angle_enabled() const { + return emission_angle_enabled; +} + +void AudioStreamPlayer3D::set_emission_angle(float p_angle) { + ERR_FAIL_COND(p_angle < 0 || p_angle > 90); + emission_angle = p_angle; + update_gizmo(); +} + +float AudioStreamPlayer3D::get_emission_angle() const { + return emission_angle; +} + +void AudioStreamPlayer3D::set_emission_angle_filter_attenuation_db(float p_angle_attenuation_db) { + + emission_angle_filter_attenuation_db = p_angle_attenuation_db; +} + +float AudioStreamPlayer3D::get_emission_angle_filter_attenuation_db() const { + + return emission_angle_filter_attenuation_db; +} + +void AudioStreamPlayer3D::set_attenuation_filter_cutoff_hz(float p_hz) { + + attenuation_filter_cutoff_hz = p_hz; +} +float AudioStreamPlayer3D::get_attenuation_filter_cutoff_hz() const { + + return attenuation_filter_cutoff_hz; +} + +void AudioStreamPlayer3D::set_attenuation_filter_db(float p_db) { + + attenuation_filter_db = p_db; +} +float AudioStreamPlayer3D::get_attenuation_filter_db() const { + + return attenuation_filter_db; +} + +void AudioStreamPlayer3D::set_attenuation_model(AttenuationModel p_model) { + ERR_FAIL_INDEX(p_model, 3); + attenuation_model = p_model; +} + +AudioStreamPlayer3D::AttenuationModel AudioStreamPlayer3D::get_attenuation_model() const { + return attenuation_model; +} + +void AudioStreamPlayer3D::set_out_of_range_mode(OutOfRangeMode p_mode) { + + ERR_FAIL_INDEX(p_mode, 2); + out_of_range_mode = p_mode; +} + +AudioStreamPlayer3D::OutOfRangeMode AudioStreamPlayer3D::get_out_of_range_mode() const { + + return out_of_range_mode; +} + +void AudioStreamPlayer3D::set_doppler_tracking(DopplerTracking p_tracking) { + + if (doppler_tracking == p_tracking) + return; + + doppler_tracking = p_tracking; + + if (doppler_tracking != DOPPLER_TRACKING_DISABLED) { + set_notify_transform(true); + velocity_tracker->set_track_fixed_step(doppler_tracking == DOPPLER_TRACKING_FIXED_STEP); + velocity_tracker->reset(get_global_transform().origin); + } else { + set_notify_transform(false); + } +} + +AudioStreamPlayer3D::DopplerTracking AudioStreamPlayer3D::get_doppler_tracking() const { + + return doppler_tracking; +} + +void AudioStreamPlayer3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_stream", "stream"), &AudioStreamPlayer3D::set_stream); + ClassDB::bind_method(D_METHOD("get_stream"), &AudioStreamPlayer3D::get_stream); + + ClassDB::bind_method(D_METHOD("set_unit_db", "unit_db"), &AudioStreamPlayer3D::set_unit_db); + ClassDB::bind_method(D_METHOD("get_unit_db"), &AudioStreamPlayer3D::get_unit_db); + + ClassDB::bind_method(D_METHOD("set_unit_size", "unit_size"), &AudioStreamPlayer3D::set_unit_size); + ClassDB::bind_method(D_METHOD("get_unit_size"), &AudioStreamPlayer3D::get_unit_size); + + ClassDB::bind_method(D_METHOD("set_max_db", "max_db"), &AudioStreamPlayer3D::set_max_db); + ClassDB::bind_method(D_METHOD("get_max_db"), &AudioStreamPlayer3D::get_max_db); + + ClassDB::bind_method(D_METHOD("play", "from_pos"), &AudioStreamPlayer3D::play, DEFVAL(0.0)); + ClassDB::bind_method(D_METHOD("seek", "to_pos"), &AudioStreamPlayer3D::seek); + ClassDB::bind_method(D_METHOD("stop"), &AudioStreamPlayer3D::stop); + + ClassDB::bind_method(D_METHOD("is_playing"), &AudioStreamPlayer3D::is_playing); + ClassDB::bind_method(D_METHOD("get_pos"), &AudioStreamPlayer3D::get_pos); + + ClassDB::bind_method(D_METHOD("set_bus", "bus"), &AudioStreamPlayer3D::set_bus); + ClassDB::bind_method(D_METHOD("get_bus"), &AudioStreamPlayer3D::get_bus); + + ClassDB::bind_method(D_METHOD("set_autoplay", "enable"), &AudioStreamPlayer3D::set_autoplay); + ClassDB::bind_method(D_METHOD("is_autoplay_enabled"), &AudioStreamPlayer3D::is_autoplay_enabled); + + ClassDB::bind_method(D_METHOD("_set_playing", "enable"), &AudioStreamPlayer3D::_set_playing); + ClassDB::bind_method(D_METHOD("_is_active"), &AudioStreamPlayer3D::_is_active); + + ClassDB::bind_method(D_METHOD("set_max_distance", "metres"), &AudioStreamPlayer3D::set_max_distance); + ClassDB::bind_method(D_METHOD("get_max_distance"), &AudioStreamPlayer3D::get_max_distance); + + ClassDB::bind_method(D_METHOD("set_area_mask", "mask"), &AudioStreamPlayer3D::set_area_mask); + ClassDB::bind_method(D_METHOD("get_area_mask"), &AudioStreamPlayer3D::get_area_mask); + + ClassDB::bind_method(D_METHOD("set_emission_angle", "degrees"), &AudioStreamPlayer3D::set_emission_angle); + ClassDB::bind_method(D_METHOD("get_emission_angle"), &AudioStreamPlayer3D::get_emission_angle); + + ClassDB::bind_method(D_METHOD("set_emission_angle_enabled", "enabled"), &AudioStreamPlayer3D::set_emission_angle_enabled); + ClassDB::bind_method(D_METHOD("is_emission_angle_enabled"), &AudioStreamPlayer3D::is_emission_angle_enabled); + + ClassDB::bind_method(D_METHOD("set_emission_angle_filter_attenuation_db", "db"), &AudioStreamPlayer3D::set_emission_angle_filter_attenuation_db); + ClassDB::bind_method(D_METHOD("get_emission_angle_filter_attenuation_db"), &AudioStreamPlayer3D::get_emission_angle_filter_attenuation_db); + + ClassDB::bind_method(D_METHOD("set_attenuation_filter_cutoff_hz", "degrees"), &AudioStreamPlayer3D::set_attenuation_filter_cutoff_hz); + ClassDB::bind_method(D_METHOD("get_attenuation_filter_cutoff_hz"), &AudioStreamPlayer3D::get_attenuation_filter_cutoff_hz); + + ClassDB::bind_method(D_METHOD("set_attenuation_filter_db", "db"), &AudioStreamPlayer3D::set_attenuation_filter_db); + ClassDB::bind_method(D_METHOD("get_attenuation_filter_db"), &AudioStreamPlayer3D::get_attenuation_filter_db); + + ClassDB::bind_method(D_METHOD("set_attenuation_model", "model"), &AudioStreamPlayer3D::set_attenuation_model); + ClassDB::bind_method(D_METHOD("get_attenuation_model"), &AudioStreamPlayer3D::get_attenuation_model); + + ClassDB::bind_method(D_METHOD("set_out_of_range_mode", "mode"), &AudioStreamPlayer3D::set_out_of_range_mode); + ClassDB::bind_method(D_METHOD("get_out_of_range_mode"), &AudioStreamPlayer3D::get_out_of_range_mode); + + ClassDB::bind_method(D_METHOD("set_doppler_tracking", "mode"), &AudioStreamPlayer3D::set_doppler_tracking); + ClassDB::bind_method(D_METHOD("get_doppler_tracking"), &AudioStreamPlayer3D::get_doppler_tracking); + + ClassDB::bind_method(D_METHOD("_bus_layout_changed"), &AudioStreamPlayer3D::_bus_layout_changed); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_stream", "get_stream"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "attenuation_model", PROPERTY_HINT_ENUM, "Inverse,InverseSquare,Log"), "set_attenuation_model", "get_attenuation_model"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_db", PROPERTY_HINT_RANGE, "-80,80"), "set_unit_db", "get_unit_db"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_size", PROPERTY_HINT_RANGE, "0.1,100,0.1"), "set_unit_size", "get_unit_size"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_db", PROPERTY_HINT_RANGE, "-24,6"), "set_max_db", "get_max_db"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_playing", "_is_active"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "is_autoplay_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_distance", PROPERTY_HINT_RANGE, "0,65536,1"), "set_max_distance", "get_max_distance"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "out_of_range_mode", PROPERTY_HINT_ENUM, "Mix,Pause"), "set_out_of_range_mode", "get_out_of_range_mode"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "bus", PROPERTY_HINT_ENUM, ""), "set_bus", "get_bus"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "area_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_area_mask", "get_area_mask"); + ADD_GROUP("Emission Angle", "emission_angle"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emission_angle_enabled"), "set_emission_angle_enabled", "is_emission_angle_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_angle_degrees", PROPERTY_HINT_RANGE, "0.1,90,0.1"), "set_emission_angle", "get_emission_angle"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_angle_filter_attenuation_db", PROPERTY_HINT_RANGE, "-80,0,0.1"), "set_emission_angle_filter_attenuation_db", "get_emission_angle_filter_attenuation_db"); + ADD_GROUP("Attenuation Filter", "attenuation_filter_"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "attenuation_filter_cutoff_hz", PROPERTY_HINT_RANGE, "50,50000,1"), "set_attenuation_filter_cutoff_hz", "get_attenuation_filter_cutoff_hz"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "attenuation_filter_db", PROPERTY_HINT_RANGE, "-80,0,0.1"), "set_attenuation_filter_db", "get_attenuation_filter_db"); + ADD_GROUP("Doppler", "doppler_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "doppler_tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Fixed"), "set_doppler_tracking", "get_doppler_tracking"); + + BIND_CONSTANT(ATTENUATION_INVERSE_DISTANCE); + BIND_CONSTANT(ATTENUATION_INVERSE_SQUARE_DISTANCE); + BIND_CONSTANT(ATTENUATION_LOGARITHMIC); + + BIND_CONSTANT(OUT_OF_RANGE_MIX); + BIND_CONSTANT(OUT_OF_RANGE_PAUSE); + + BIND_CONSTANT(DOPPLER_TRACKING_DISABLED); + BIND_CONSTANT(DOPPLER_TRACKING_IDLE_STEP); + BIND_CONSTANT(DOPPLER_TRACKING_FIXED_STEP); +} + +AudioStreamPlayer3D::AudioStreamPlayer3D() { + + unit_db = 0; + unit_size = 1; + attenuation_model = ATTENUATION_INVERSE_DISTANCE; + max_db = 3; + autoplay = false; + setseek = -1; + active = false; + output_count = 0; + prev_output_count = 0; + max_distance = 0; + setplay = -1; + output_ready = false; + area_mask = 1; + emission_angle = 45; + emission_angle_enabled = false; + emission_angle_filter_attenuation_db = -12; + attenuation_filter_cutoff_hz = 5000; + attenuation_filter_db = -24; + out_of_range_mode = OUT_OF_RANGE_MIX; + doppler_tracking = DOPPLER_TRACKING_DISABLED; + + velocity_tracker.instance(); + AudioServer::get_singleton()->connect("bus_layout_changed", this, "_bus_layout_changed"); +} +AudioStreamPlayer3D::~AudioStreamPlayer3D() { +} diff --git a/scene/3d/audio_stream_player_3d.h b/scene/3d/audio_stream_player_3d.h new file mode 100644 index 000000000..8603cab5a --- /dev/null +++ b/scene/3d/audio_stream_player_3d.h @@ -0,0 +1,175 @@ +#ifndef AUDIO_STREAM_PLAYER_3D_H +#define AUDIO_STREAM_PLAYER_3D_H + +#include "scene/3d/spatial.h" +#include "scene/3d/spatial_velocity_tracker.h" +#include "servers/audio/audio_filter_sw.h" +#include "servers/audio/audio_stream.h" +#include "servers/audio_server.h" + +class Camera; +class AudioStreamPlayer3D : public Spatial { + + GDCLASS(AudioStreamPlayer3D, Spatial) +public: + enum AttenuationModel { + ATTENUATION_INVERSE_DISTANCE, + ATTENUATION_INVERSE_SQUARE_DISTANCE, + ATTENUATION_LOGARITHMIC, + }; + + enum OutOfRangeMode { + OUT_OF_RANGE_MIX, + OUT_OF_RANGE_PAUSE, + }; + + enum DopplerTracking { + DOPPLER_TRACKING_DISABLED, + DOPPLER_TRACKING_IDLE_STEP, + DOPPLER_TRACKING_FIXED_STEP + }; + +private: + enum { + MAX_OUTPUTS = 8, + MAX_INTERSECT_AREAS = 32 + + }; + + struct Output { + + AudioFilterSW filter; + AudioFilterSW::Processor filter_process[6]; + AudioFrame vol[3]; + float filter_gain; + float pitch_scale; + int bus_index; + int reverb_bus_index; + AudioFrame reverb_vol[3]; + Viewport *viewport; //pointer only used for reference to previous mix + + Output() { + filter_gain = 0; + viewport = NULL; + reverb_bus_index = -1; + bus_index = -1; + } + }; + + Output outputs[MAX_OUTPUTS]; + volatile int output_count; + volatile bool output_ready; + + //these are used by audio thread to have a reference of previous volumes (for ramping volume and avoiding clicks) + Output prev_outputs[MAX_OUTPUTS]; + int prev_output_count; + + Ref<AudioStreamPlayback> stream_playback; + Ref<AudioStream> stream; + Vector<AudioFrame> mix_buffer; + + volatile float setseek; + volatile bool active; + volatile float setplay; + + AttenuationModel attenuation_model; + float unit_db; + float unit_size; + float max_db; + bool autoplay; + StringName bus; + + void _mix_audio(); + static void _mix_audios(void *self) { reinterpret_cast<AudioStreamPlayer3D *>(self)->_mix_audio(); } + + void _set_playing(bool p_enable); + bool _is_active() const; + + void _bus_layout_changed(); + + uint32_t area_mask; + + bool emission_angle_enabled; + float emission_angle; + float emission_angle_filter_attenuation_db; + float attenuation_filter_cutoff_hz; + float attenuation_filter_db; + + float max_distance; + + Ref<SpatialVelocityTracker> velocity_tracker; + + DopplerTracking doppler_tracking; + + OutOfRangeMode out_of_range_mode; + + float _get_attenuation_db(float p_distance) const; + +protected: + void _validate_property(PropertyInfo &property) const; + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_stream(Ref<AudioStream> p_stream); + Ref<AudioStream> get_stream() const; + + void set_unit_db(float p_volume); + float get_unit_db() const; + + void set_unit_size(float p_volume); + float get_unit_size() const; + + void set_max_db(float p_boost); + float get_max_db() const; + + void play(float p_from_pos = 0.0); + void seek(float p_seconds); + void stop(); + bool is_playing() const; + float get_pos(); + + void set_bus(const StringName &p_bus); + StringName get_bus() const; + + void set_autoplay(bool p_enable); + bool is_autoplay_enabled(); + + void set_max_distance(float p_metres); + float get_max_distance() const; + + void set_area_mask(uint32_t p_mask); + uint32_t get_area_mask() const; + + void set_emission_angle_enabled(bool p_enable); + bool is_emission_angle_enabled() const; + + void set_emission_angle(float p_angle); + float get_emission_angle() const; + + void set_emission_angle_filter_attenuation_db(float p_angle_attenuation_db); + float get_emission_angle_filter_attenuation_db() const; + + void set_attenuation_filter_cutoff_hz(float p_hz); + float get_attenuation_filter_cutoff_hz() const; + + void set_attenuation_filter_db(float p_db); + float get_attenuation_filter_db() const; + + void set_attenuation_model(AttenuationModel p_model); + AttenuationModel get_attenuation_model() const; + + void set_out_of_range_mode(OutOfRangeMode p_mode); + OutOfRangeMode get_out_of_range_mode() const; + + void set_doppler_tracking(DopplerTracking p_tracking); + DopplerTracking get_doppler_tracking() const; + + AudioStreamPlayer3D(); + ~AudioStreamPlayer3D(); +}; + +VARIANT_ENUM_CAST(AudioStreamPlayer3D::AttenuationModel) +VARIANT_ENUM_CAST(AudioStreamPlayer3D::OutOfRangeMode) +VARIANT_ENUM_CAST(AudioStreamPlayer3D::DopplerTracking) +#endif // AUDIO_STREAM_PLAYER_3D_H diff --git a/scene/3d/baked_light_instance.cpp b/scene/3d/baked_light_instance.cpp deleted file mode 100644 index ac424475e..000000000 --- a/scene/3d/baked_light_instance.cpp +++ /dev/null @@ -1,1753 +0,0 @@ -/*************************************************************************/ -/* baked_light_instance.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "baked_light_instance.h" -#include "light.h" -#include "math.h" -#include "mesh_instance.h" -#include "scene/scene_string_names.h" - -#define FINDMINMAX(x0, x1, x2, min, max) \ - min = max = x0; \ - if (x1 < min) min = x1; \ - if (x1 > max) max = x1; \ - if (x2 < min) min = x2; \ - if (x2 > max) max = x2; - -static bool planeBoxOverlap(Vector3 normal, float d, Vector3 maxbox) { - int q; - Vector3 vmin, vmax; - for (q = 0; q <= 2; q++) { - if (normal[q] > 0.0f) { - vmin[q] = -maxbox[q]; - vmax[q] = maxbox[q]; - } else { - vmin[q] = maxbox[q]; - vmax[q] = -maxbox[q]; - } - } - if (normal.dot(vmin) + d > 0.0f) return false; - if (normal.dot(vmax) + d >= 0.0f) return true; - - return false; -} - -/*======================== X-tests ========================*/ -#define AXISTEST_X01(a, b, fa, fb) \ - p0 = a * v0.y - b * v0.z; \ - p2 = a * v2.y - b * v2.z; \ - if (p0 < p2) { \ - min = p0; \ - max = p2; \ - } else { \ - min = p2; \ - max = p0; \ - } \ - rad = fa * boxhalfsize.y + fb * boxhalfsize.z; \ - if (min > rad || max < -rad) return false; - -#define AXISTEST_X2(a, b, fa, fb) \ - p0 = a * v0.y - b * v0.z; \ - p1 = a * v1.y - b * v1.z; \ - if (p0 < p1) { \ - min = p0; \ - max = p1; \ - } else { \ - min = p1; \ - max = p0; \ - } \ - rad = fa * boxhalfsize.y + fb * boxhalfsize.z; \ - if (min > rad || max < -rad) return false; - -/*======================== Y-tests ========================*/ -#define AXISTEST_Y02(a, b, fa, fb) \ - p0 = -a * v0.x + b * v0.z; \ - p2 = -a * v2.x + b * v2.z; \ - if (p0 < p2) { \ - min = p0; \ - max = p2; \ - } else { \ - min = p2; \ - max = p0; \ - } \ - rad = fa * boxhalfsize.x + fb * boxhalfsize.z; \ - if (min > rad || max < -rad) return false; - -#define AXISTEST_Y1(a, b, fa, fb) \ - p0 = -a * v0.x + b * v0.z; \ - p1 = -a * v1.x + b * v1.z; \ - if (p0 < p1) { \ - min = p0; \ - max = p1; \ - } else { \ - min = p1; \ - max = p0; \ - } \ - rad = fa * boxhalfsize.x + fb * boxhalfsize.z; \ - if (min > rad || max < -rad) return false; - -/*======================== Z-tests ========================*/ - -#define AXISTEST_Z12(a, b, fa, fb) \ - p1 = a * v1.x - b * v1.y; \ - p2 = a * v2.x - b * v2.y; \ - if (p2 < p1) { \ - min = p2; \ - max = p1; \ - } else { \ - min = p1; \ - max = p2; \ - } \ - rad = fa * boxhalfsize.x + fb * boxhalfsize.y; \ - if (min > rad || max < -rad) return false; - -#define AXISTEST_Z0(a, b, fa, fb) \ - p0 = a * v0.x - b * v0.y; \ - p1 = a * v1.x - b * v1.y; \ - if (p0 < p1) { \ - min = p0; \ - max = p1; \ - } else { \ - min = p1; \ - max = p0; \ - } \ - rad = fa * boxhalfsize.x + fb * boxhalfsize.y; \ - if (min > rad || max < -rad) return false; - -static bool fast_tri_box_overlap(const Vector3 &boxcenter, const Vector3 boxhalfsize, const Vector3 *triverts) { - - /* use separating axis theorem to test overlap between triangle and box */ - /* need to test for overlap in these directions: */ - /* 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle */ - /* we do not even need to test these) */ - /* 2) normal of the triangle */ - /* 3) crossproduct(edge from tri, {x,y,z}-directin) */ - /* this gives 3x3=9 more tests */ - Vector3 v0, v1, v2; - float min, max, d, p0, p1, p2, rad, fex, fey, fez; - Vector3 normal, e0, e1, e2; - - /* This is the fastest branch on Sun */ - /* move everything so that the boxcenter is in (0,0,0) */ - - v0 = triverts[0] - boxcenter; - v1 = triverts[1] - boxcenter; - v2 = triverts[2] - boxcenter; - - /* compute triangle edges */ - e0 = v1 - v0; /* tri edge 0 */ - e1 = v2 - v1; /* tri edge 1 */ - e2 = v0 - v2; /* tri edge 2 */ - - /* Bullet 3: */ - /* test the 9 tests first (this was faster) */ - fex = Math::abs(e0.x); - fey = Math::abs(e0.y); - fez = Math::abs(e0.z); - AXISTEST_X01(e0.z, e0.y, fez, fey); - AXISTEST_Y02(e0.z, e0.x, fez, fex); - AXISTEST_Z12(e0.y, e0.x, fey, fex); - - fex = Math::abs(e1.x); - fey = Math::abs(e1.y); - fez = Math::abs(e1.z); - AXISTEST_X01(e1.z, e1.y, fez, fey); - AXISTEST_Y02(e1.z, e1.x, fez, fex); - AXISTEST_Z0(e1.y, e1.x, fey, fex); - - fex = Math::abs(e2.x); - fey = Math::abs(e2.y); - fez = Math::abs(e2.z); - AXISTEST_X2(e2.z, e2.y, fez, fey); - AXISTEST_Y1(e2.z, e2.x, fez, fex); - AXISTEST_Z12(e2.y, e2.x, fey, fex); - - /* Bullet 1: */ - /* first test overlap in the {x,y,z}-directions */ - /* find min, max of the triangle each direction, and test for overlap in */ - /* that direction -- this is equivalent to testing a minimal AABB around */ - /* the triangle against the AABB */ - - /* test in X-direction */ - FINDMINMAX(v0.x, v1.x, v2.x, min, max); - if (min > boxhalfsize.x || max < -boxhalfsize.x) return false; - - /* test in Y-direction */ - FINDMINMAX(v0.y, v1.y, v2.y, min, max); - if (min > boxhalfsize.y || max < -boxhalfsize.y) return false; - - /* test in Z-direction */ - FINDMINMAX(v0.z, v1.z, v2.z, min, max); - if (min > boxhalfsize.z || max < -boxhalfsize.z) return false; - - /* Bullet 2: */ - /* test if the box intersects the plane of the triangle */ - /* compute plane equation of triangle: normal*x+d=0 */ - normal = e0.cross(e1); - d = -normal.dot(v0); /* plane eq: normal.x+d=0 */ - if (!planeBoxOverlap(normal, d, boxhalfsize)) return false; - - return true; /* box and triangle overlaps */ -} - -Vector<Color> BakedLight::_get_bake_texture(Image &p_image, const Color &p_color) { - - Vector<Color> ret; - - if (p_image.empty()) { - - ret.resize(bake_texture_size * bake_texture_size); - for (int i = 0; i < bake_texture_size * bake_texture_size; i++) { - ret[i] = p_color; - } - - return ret; - } - - p_image.convert(Image::FORMAT_RGBA8); - p_image.resize(bake_texture_size, bake_texture_size, Image::INTERPOLATE_CUBIC); - - PoolVector<uint8_t>::Read r = p_image.get_data().read(); - ret.resize(bake_texture_size * bake_texture_size); - - for (int i = 0; i < bake_texture_size * bake_texture_size; i++) { - Color c; - c.r = r[i * 4 + 0] / 255.0; - c.g = r[i * 4 + 1] / 255.0; - c.b = r[i * 4 + 2] / 255.0; - c.a = r[i * 4 + 3] / 255.0; - ret[i] = c; - } - - return ret; -} - -BakedLight::MaterialCache BakedLight::_get_material_cache(Ref<Material> p_material) { - - //this way of obtaining materials is inaccurate and also does not support some compressed formats very well - Ref<FixedSpatialMaterial> mat = p_material; - - Ref<Material> material = mat; //hack for now - - if (material_cache.has(material)) { - return material_cache[material]; - } - - MaterialCache mc; - - if (mat.is_valid()) { - - Ref<ImageTexture> albedo_tex = mat->get_texture(FixedSpatialMaterial::TEXTURE_ALBEDO); - - Image img_albedo; - if (albedo_tex.is_valid()) { - - img_albedo = albedo_tex->get_data(); - } - - mc.albedo = _get_bake_texture(img_albedo, mat->get_albedo()); - - Ref<ImageTexture> emission_tex = mat->get_texture(FixedSpatialMaterial::TEXTURE_EMISSION); - - Color emission_col = mat->get_emission(); - emission_col.r *= mat->get_emission_energy(); - emission_col.g *= mat->get_emission_energy(); - emission_col.b *= mat->get_emission_energy(); - - Image img_emission; - - if (emission_tex.is_valid()) { - - img_emission = emission_tex->get_data(); - } - - mc.emission = _get_bake_texture(img_emission, emission_col); - - } else { - Image empty; - - mc.albedo = _get_bake_texture(empty, Color(0.7, 0.7, 0.7)); - mc.emission = _get_bake_texture(empty, Color(0, 0, 0)); - } - - material_cache[p_material] = mc; - return mc; -} - -static _FORCE_INLINE_ Vector2 get_uv(const Vector3 &p_pos, const Vector3 *p_vtx, const Vector2 *p_uv) { - - if (p_pos.distance_squared_to(p_vtx[0]) < CMP_EPSILON2) - return p_uv[0]; - if (p_pos.distance_squared_to(p_vtx[1]) < CMP_EPSILON2) - return p_uv[1]; - if (p_pos.distance_squared_to(p_vtx[2]) < CMP_EPSILON2) - return p_uv[2]; - - Vector3 v0 = p_vtx[1] - p_vtx[0]; - Vector3 v1 = p_vtx[2] - p_vtx[0]; - Vector3 v2 = p_pos - p_vtx[0]; - - float d00 = v0.dot(v0); - float d01 = v0.dot(v1); - float d11 = v1.dot(v1); - float d20 = v2.dot(v0); - float d21 = v2.dot(v1); - float denom = (d00 * d11 - d01 * d01); - if (denom == 0) - return p_uv[0]; - float v = (d11 * d20 - d01 * d21) / denom; - float w = (d00 * d21 - d01 * d20) / denom; - float u = 1.0f - v - w; - - return p_uv[0] * u + p_uv[1] * v + p_uv[2] * w; -} - -void BakedLight::_plot_face(int p_idx, int p_level, const Vector3 *p_vtx, const Vector2 *p_uv, const MaterialCache &p_material, const Rect3 &p_aabb) { - - if (p_level == cell_subdiv - 1) { - //plot the face by guessing it's albedo and emission value - - //find best axis to map to, for scanning values - int closest_axis; - float closest_dot; - - Vector3 normal = Plane(p_vtx[0], p_vtx[1], p_vtx[2]).normal; - - for (int i = 0; i < 3; i++) { - - Vector3 axis; - axis[i] = 1.0; - float dot = ABS(normal.dot(axis)); - if (i == 0 || dot > closest_dot) { - closest_axis = i; - closest_dot = dot; - } - } - - Vector3 axis; - axis[closest_axis] = 1.0; - Vector3 t1; - t1[(closest_axis + 1) % 3] = 1.0; - Vector3 t2; - t2[(closest_axis + 2) % 3] = 1.0; - - t1 *= p_aabb.size[(closest_axis + 1) % 3] / float(color_scan_cell_width); - t2 *= p_aabb.size[(closest_axis + 2) % 3] / float(color_scan_cell_width); - - Color albedo_accum; - Color emission_accum; - float alpha = 0.0; - - //map to a grid average in the best axis for this face - for (int i = 0; i < color_scan_cell_width; i++) { - - Vector3 ofs_i = float(i) * t1; - - for (int j = 0; j < color_scan_cell_width; j++) { - - Vector3 ofs_j = float(j) * t2; - - Vector3 from = p_aabb.pos + ofs_i + ofs_j; - Vector3 to = from + t1 + t2 + axis * p_aabb.size[closest_axis]; - Vector3 half = (to - from) * 0.5; - - //is in this cell? - if (!fast_tri_box_overlap(from + half, half, p_vtx)) { - continue; //face does not span this cell - } - - //go from -size to +size*2 to avoid skipping collisions - Vector3 ray_from = from + (t1 + t2) * 0.5 - axis * p_aabb.size[closest_axis]; - Vector3 ray_to = ray_from + axis * p_aabb.size[closest_axis] * 2; - - Vector3 intersection; - - if (!Geometry::ray_intersects_triangle(ray_from, ray_to, p_vtx[0], p_vtx[1], p_vtx[2], &intersection)) { - //no intersect? look in edges - - float closest_dist = 1e20; - for (int j = 0; j < 3; j++) { - Vector3 c; - Vector3 inters; - Geometry::get_closest_points_between_segments(p_vtx[j], p_vtx[(j + 1) % 3], ray_from, ray_to, inters, c); - float d = c.distance_to(intersection); - if (j == 0 || d < closest_dist) { - closest_dist = d; - intersection = inters; - } - } - } - - Vector2 uv = get_uv(intersection, p_vtx, p_uv); - - int uv_x = CLAMP(Math::fposmod(uv.x, 1.0f) * bake_texture_size, 0, bake_texture_size - 1); - int uv_y = CLAMP(Math::fposmod(uv.y, 1.0f) * bake_texture_size, 0, bake_texture_size - 1); - - int ofs = uv_y * bake_texture_size + uv_x; - albedo_accum.r += p_material.albedo[ofs].r; - albedo_accum.g += p_material.albedo[ofs].g; - albedo_accum.b += p_material.albedo[ofs].b; - albedo_accum.a += p_material.albedo[ofs].a; - - emission_accum.r += p_material.emission[ofs].r; - emission_accum.g += p_material.emission[ofs].g; - emission_accum.b += p_material.emission[ofs].b; - alpha += 1.0; - } - } - - if (alpha == 0) { - //could not in any way get texture information.. so use closest point to center - - Face3 f(p_vtx[0], p_vtx[1], p_vtx[2]); - Vector3 inters = f.get_closest_point_to(p_aabb.pos + p_aabb.size * 0.5); - - Vector2 uv = get_uv(inters, p_vtx, p_uv); - - int uv_x = CLAMP(Math::fposmod(uv.x, 1.0f) * bake_texture_size, 0, bake_texture_size - 1); - int uv_y = CLAMP(Math::fposmod(uv.y, 1.0f) * bake_texture_size, 0, bake_texture_size - 1); - - int ofs = uv_y * bake_texture_size + uv_x; - - alpha = 1.0 / (color_scan_cell_width * color_scan_cell_width); - - albedo_accum.r = p_material.albedo[ofs].r * alpha; - albedo_accum.g = p_material.albedo[ofs].g * alpha; - albedo_accum.b = p_material.albedo[ofs].b * alpha; - albedo_accum.a = p_material.albedo[ofs].a * alpha; - - emission_accum.r = p_material.emission[ofs].r * alpha; - emission_accum.g = p_material.emission[ofs].g * alpha; - emission_accum.b = p_material.emission[ofs].b * alpha; - - zero_alphas++; - } else { - - float accdiv = 1.0 / (color_scan_cell_width * color_scan_cell_width); - alpha *= accdiv; - - albedo_accum.r *= accdiv; - albedo_accum.g *= accdiv; - albedo_accum.b *= accdiv; - albedo_accum.a *= accdiv; - - emission_accum.r *= accdiv; - emission_accum.g *= accdiv; - emission_accum.b *= accdiv; - } - - //put this temporarily here, corrected in a later step - bake_cells_write[p_idx].albedo[0] += albedo_accum.r; - bake_cells_write[p_idx].albedo[1] += albedo_accum.g; - bake_cells_write[p_idx].albedo[2] += albedo_accum.b; - bake_cells_write[p_idx].light[0] += emission_accum.r; - bake_cells_write[p_idx].light[1] += emission_accum.g; - bake_cells_write[p_idx].light[2] += emission_accum.b; - bake_cells_write[p_idx].alpha += alpha; - - static const Vector3 side_normals[6] = { - Vector3(-1, 0, 0), - Vector3(1, 0, 0), - Vector3(0, -1, 0), - Vector3(0, 1, 0), - Vector3(0, 0, -1), - Vector3(0, 0, 1), - }; - - for (int i = 0; i < 6; i++) { - if (normal.dot(side_normals[i]) > CMP_EPSILON) { - bake_cells_write[p_idx].used_sides |= (1 << i); - } - } - - } else { - //go down - for (int i = 0; i < 8; i++) { - - Rect3 aabb = p_aabb; - aabb.size *= 0.5; - - if (i & 1) - aabb.pos.x += aabb.size.x; - if (i & 2) - aabb.pos.y += aabb.size.y; - if (i & 4) - aabb.pos.z += aabb.size.z; - - { - Rect3 test_aabb = aabb; - //test_aabb.grow_by(test_aabb.get_longest_axis_size()*0.05); //grow a bit to avoid numerical error in real-time - Vector3 qsize = test_aabb.size * 0.5; //quarter size, for fast aabb test - - if (!fast_tri_box_overlap(test_aabb.pos + qsize, qsize, p_vtx)) { - //if (!Face3(p_vtx[0],p_vtx[1],p_vtx[2]).intersects_aabb2(aabb)) { - //does not fit in child, go on - continue; - } - } - - if (bake_cells_write[p_idx].childs[i] == CHILD_EMPTY) { - //sub cell must be created - - if (bake_cells_used == (1 << bake_cells_alloc)) { - //exhausted cells, creating more space - bake_cells_alloc++; - bake_cells_write = PoolVector<BakeCell>::Write(); - bake_cells.resize(1 << bake_cells_alloc); - bake_cells_write = bake_cells.write(); - } - - bake_cells_write[p_idx].childs[i] = bake_cells_used; - bake_cells_level_used[p_level + 1]++; - bake_cells_used++; - } - - _plot_face(bake_cells_write[p_idx].childs[i], p_level + 1, p_vtx, p_uv, p_material, aabb); - } - } -} - -void BakedLight::_fixup_plot(int p_idx, int p_level, int p_x, int p_y, int p_z) { - - if (p_level == cell_subdiv - 1) { - - float alpha = bake_cells_write[p_idx].alpha; - - bake_cells_write[p_idx].albedo[0] /= alpha; - bake_cells_write[p_idx].albedo[1] /= alpha; - bake_cells_write[p_idx].albedo[2] /= alpha; - - //transfer emission to light - bake_cells_write[p_idx].light[0] /= alpha; - bake_cells_write[p_idx].light[1] /= alpha; - bake_cells_write[p_idx].light[2] /= alpha; - - bake_cells_write[p_idx].alpha = 1.0; - - //remove neighbours from used sides - - for (int n = 0; n < 6; n++) { - - int ofs[3] = { 0, 0, 0 }; - - ofs[n / 2] = (n & 1) ? 1 : -1; - - //convert to x,y,z on this level - int x = p_x; - int y = p_y; - int z = p_z; - - x += ofs[0]; - y += ofs[1]; - z += ofs[2]; - - int ofs_x = 0; - int ofs_y = 0; - int ofs_z = 0; - int size = 1 << p_level; - int half = size / 2; - - if (x < 0 || x >= size || y < 0 || y >= size || z < 0 || z >= size) { - //neighbour is out, can't use it - bake_cells_write[p_idx].used_sides &= ~(1 << uint32_t(n)); - continue; - } - - uint32_t neighbour = 0; - - for (int i = 0; i < cell_subdiv - 1; i++) { - - BakeCell *bc = &bake_cells_write[neighbour]; - - int child = 0; - if (x >= ofs_x + half) { - child |= 1; - ofs_x += half; - } - if (y >= ofs_y + half) { - child |= 2; - ofs_y += half; - } - if (z >= ofs_z + half) { - child |= 4; - ofs_z += half; - } - - neighbour = bc->childs[child]; - if (neighbour == CHILD_EMPTY) { - break; - } - - half >>= 1; - } - - if (neighbour != CHILD_EMPTY) { - bake_cells_write[p_idx].used_sides &= ~(1 << uint32_t(n)); - } - } - } else { - - //go down - - float alpha_average = 0; - int half = cells_per_axis >> (p_level + 1); - for (int i = 0; i < 8; i++) { - - uint32_t child = bake_cells_write[p_idx].childs[i]; - - if (child == CHILD_EMPTY) - continue; - - int nx = p_x; - int ny = p_y; - int nz = p_z; - - if (i & 1) - nx += half; - if (i & 2) - ny += half; - if (i & 4) - nz += half; - - _fixup_plot(child, p_level + 1, nx, ny, nz); - alpha_average += bake_cells_write[child].alpha; - } - - bake_cells_write[p_idx].alpha = alpha_average / 8.0; - bake_cells_write[p_idx].light[0] = 0; - bake_cells_write[p_idx].light[1] = 0; - bake_cells_write[p_idx].light[2] = 0; - bake_cells_write[p_idx].albedo[0] = 0; - bake_cells_write[p_idx].albedo[1] = 0; - bake_cells_write[p_idx].albedo[2] = 0; - } - - //clean up light - bake_cells_write[p_idx].light_pass = 0; - //find neighbours -} - -void BakedLight::_bake_add_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh) { - - for (int i = 0; i < p_mesh->get_surface_count(); i++) { - - if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) - continue; //only triangles - - MaterialCache material = _get_material_cache(p_mesh->surface_get_material(i)); - - Array a = p_mesh->surface_get_arrays(i); - - PoolVector<Vector3> vertices = a[Mesh::ARRAY_VERTEX]; - PoolVector<Vector3>::Read vr = vertices.read(); - PoolVector<Vector2> uv = a[Mesh::ARRAY_TEX_UV]; - PoolVector<Vector2>::Read uvr; - PoolVector<int> index = a[Mesh::ARRAY_INDEX]; - - bool read_uv = false; - - if (uv.size()) { - - uvr = uv.read(); - read_uv = true; - } - - if (index.size()) { - - int facecount = index.size() / 3; - PoolVector<int>::Read ir = index.read(); - - for (int j = 0; j < facecount; j++) { - - Vector3 vtxs[3]; - Vector2 uvs[3]; - - for (int k = 0; k < 3; k++) { - vtxs[k] = p_xform.xform(vr[ir[j * 3 + k]]); - } - - if (read_uv) { - for (int k = 0; k < 3; k++) { - uvs[k] = uvr[ir[j * 3 + k]]; - } - } - - //plot face - _plot_face(0, 0, vtxs, uvs, material, bounds); - } - - } else { - - int facecount = vertices.size() / 3; - - for (int j = 0; j < facecount; j++) { - - Vector3 vtxs[3]; - Vector2 uvs[3]; - - for (int k = 0; k < 3; k++) { - vtxs[k] = p_xform.xform(vr[j * 3 + k]); - } - - if (read_uv) { - for (int k = 0; k < 3; k++) { - uvs[k] = uvr[j * 3 + k]; - } - } - - //plot face - _plot_face(0, 0, vtxs, uvs, material, bounds); - } - } - } -} - -void BakedLight::_bake_add_to_aabb(const Transform &p_xform, Ref<Mesh> &p_mesh, bool &first) { - - for (int i = 0; i < p_mesh->get_surface_count(); i++) { - - if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) - continue; //only triangles - - Array a = p_mesh->surface_get_arrays(i); - PoolVector<Vector3> vertices = a[Mesh::ARRAY_VERTEX]; - int vc = vertices.size(); - PoolVector<Vector3>::Read vr = vertices.read(); - - if (first) { - bounds.pos = p_xform.xform(vr[0]); - first = false; - } - - for (int j = 0; j < vc; j++) { - bounds.expand_to(p_xform.xform(vr[j])); - } - } -} - -void BakedLight::bake() { - - bake_cells_alloc = 16; - bake_cells.resize(1 << bake_cells_alloc); - bake_cells_used = 1; - cells_per_axis = (1 << (cell_subdiv - 1)); - zero_alphas = 0; - - bool aabb_first = true; - print_line("Generating AABB"); - - bake_cells_level_used.resize(cell_subdiv); - for (int i = 0; i < cell_subdiv; i++) { - bake_cells_level_used[i] = 0; - } - - int count = 0; - for (Set<GeometryInstance *>::Element *E = geometries.front(); E; E = E->next()) { - - print_line("aabb geom " + itos(count) + "/" + itos(geometries.size())); - - GeometryInstance *geom = E->get(); - - if (geom->cast_to<MeshInstance>()) { - - MeshInstance *mesh_instance = geom->cast_to<MeshInstance>(); - Ref<Mesh> mesh = mesh_instance->get_mesh(); - if (mesh.is_valid()) { - - _bake_add_to_aabb(geom->get_relative_transform(this), mesh, aabb_first); - } - } - count++; - } - - print_line("AABB: " + bounds); - ERR_FAIL_COND(aabb_first); - - bake_cells_write = bake_cells.write(); - count = 0; - - for (Set<GeometryInstance *>::Element *E = geometries.front(); E; E = E->next()) { - - GeometryInstance *geom = E->get(); - print_line("plot geom " + itos(count) + "/" + itos(geometries.size())); - - if (geom->cast_to<MeshInstance>()) { - - MeshInstance *mesh_instance = geom->cast_to<MeshInstance>(); - Ref<Mesh> mesh = mesh_instance->get_mesh(); - if (mesh.is_valid()) { - - _bake_add_mesh(geom->get_relative_transform(this), mesh); - } - } - - count++; - } - - _fixup_plot(0, 0, 0, 0, 0); - - bake_cells_write = PoolVector<BakeCell>::Write(); - - bake_cells.resize(bake_cells_used); - - print_line("total bake cells used: " + itos(bake_cells_used)); - for (int i = 0; i < cell_subdiv; i++) { - print_line("level " + itos(i) + ": " + itos(bake_cells_level_used[i])); - } - print_line("zero alphas: " + itos(zero_alphas)); -} - -void BakedLight::_bake_directional(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 &p_dir, const Color &p_color, int p_sign) { - - if (p_level == cell_subdiv - 1) { - - Vector3 end; - end.x = float(p_x + 0.5) / cells_per_axis; - end.y = float(p_y + 0.5) / cells_per_axis; - end.z = float(p_z + 0.5) / cells_per_axis; - - end = bounds.pos + bounds.size * end; - - float max_ray_len = (bounds.size).length() * 1.2; - - Vector3 begin = end + max_ray_len * -p_dir; - - //clip begin - - for (int i = 0; i < 3; i++) { - - if (ABS(p_dir[i]) < CMP_EPSILON) { - continue; // parallel to axis, don't clip - } - - Plane p; - p.normal[i] = 1.0; - p.d = bounds.pos[i]; - if (p_dir[i] < 0) { - p.d += bounds.size[i]; - } - - Vector3 inters; - if (p.intersects_segment(end, begin, &inters)) { - begin = inters; - } - } - - int idx = _plot_ray(begin, end); - - if (idx >= 0 && light_pass != bake_cells_write[idx].light_pass) { - //hit something, add or remove light to it - - Color albedo = Color(bake_cells_write[idx].albedo[0], bake_cells_write[idx].albedo[1], bake_cells_write[idx].albedo[2]); - bake_cells_write[idx].light[0] += albedo.r * p_color.r * p_sign; - bake_cells_write[idx].light[1] += albedo.g * p_color.g * p_sign; - bake_cells_write[idx].light[2] += albedo.b * p_color.b * p_sign; - bake_cells_write[idx].light_pass = light_pass; - } - - } else { - - int half = cells_per_axis >> (p_level + 1); - - //go down - for (int i = 0; i < 8; i++) { - - uint32_t child = bake_cells_write[p_idx].childs[i]; - - if (child == CHILD_EMPTY) - continue; - - int nx = p_x; - int ny = p_y; - int nz = p_z; - - if (i & 1) - nx += half; - if (i & 2) - ny += half; - if (i & 4) - nz += half; - - _bake_directional(child, p_level + 1, nx, ny, nz, p_dir, p_color, p_sign); - } - } -} - -void BakedLight::_bake_light(Light *p_light) { - - if (p_light->cast_to<DirectionalLight>()) { - - DirectionalLight *dl = p_light->cast_to<DirectionalLight>(); - - Transform rel_xf = dl->get_relative_transform(this); - - Vector3 light_dir = -rel_xf.basis.get_axis(2); - - Color color = dl->get_color(); - float nrg = dl->get_param(Light::PARAM_ENERGY); - color.r *= nrg; - color.g *= nrg; - color.b *= nrg; - - light_pass++; - _bake_directional(0, 0, 0, 0, 0, light_dir, color, 1); - } -} - -void BakedLight::_upscale_light(int p_idx, int p_level) { - - //go down - - float light_accum[3] = { 0, 0, 0 }; - float alpha_accum = 0; - - bool check_children = p_level < (cell_subdiv - 2); - - for (int i = 0; i < 8; i++) { - - uint32_t child = bake_cells_write[p_idx].childs[i]; - - if (child == CHILD_EMPTY) - continue; - - if (check_children) { - _upscale_light(child, p_level + 1); - } - - light_accum[0] += bake_cells_write[child].light[0]; - light_accum[1] += bake_cells_write[child].light[1]; - light_accum[2] += bake_cells_write[child].light[2]; - alpha_accum += bake_cells_write[child].alpha; - } - - bake_cells_write[p_idx].light[0] = light_accum[0] / 8.0; - bake_cells_write[p_idx].light[1] = light_accum[1] / 8.0; - bake_cells_write[p_idx].light[2] = light_accum[2] / 8.0; - bake_cells_write[p_idx].alpha = alpha_accum / 8.0; -} - -void BakedLight::bake_lights() { - - ERR_FAIL_COND(bake_cells.size() == 0); - - bake_cells_write = bake_cells.write(); - - for (Set<Light *>::Element *E = lights.front(); E; E = E->next()) { - - _bake_light(E->get()); - } - - _upscale_light(0, 0); - - bake_cells_write = PoolVector<BakeCell>::Write(); -} - -Color BakedLight::_cone_trace(const Vector3 &p_from, const Vector3 &p_dir, float p_half_angle) { - - Color color(0, 0, 0, 0); - float tha = Math::tan(p_half_angle); //tan half angle - Vector3 from = (p_from - bounds.pos) / bounds.size; //convert to 0..1 - from /= cells_per_axis; //convert to voxels of size 1 - Vector3 dir = (p_dir / bounds.size).normalized(); - - float max_dist = Vector3(cells_per_axis, cells_per_axis, cells_per_axis).length(); - - float dist = 1.0; - // self occlusion in flat surfaces - - float alpha = 0; - - while (dist < max_dist && alpha < 0.95) { - -#if 0 - // smallest sample diameter possible is the voxel size - float diameter = MAX(1.0, 2.0 * tha * dist); - float lod = log2(diameter); - - Vector3 sample_pos = from + dist * dir; - - - Color samples_base[2][8]={{Color(0,0,0,0),Color(0,0,0,0),Color(0,0,0,0),Color(0,0,0,0),Color(0,0,0,0),Color(0,0,0,0),Color(0,0,0,0),Color(0,0,0,0)}, - {Color(0,0,0,0),Color(0,0,0,0),Color(0,0,0,0),Color(0,0,0,0),Color(0,0,0,0),Color(0,0,0,0),Color(0,0,0,0),Color(0,0,0,0)}}; - - float levelf = Math::fposmod(lod,1.0); - float fx = Math::fposmod(sample_pos.x,1.0); - float fy = Math::fposmod(sample_pos.y,1.0); - float fz = Math::fposmod(sample_pos.z,1.0); - - for(int l=0;l<2;l++){ - - int bx = Math::floor(sample_pos.x); - int by = Math::floor(sample_pos.y); - int bz = Math::floor(sample_pos.z); - - int lodn=int(Math::floor(lod))-l; - - bx>>=lodn; - by>>=lodn; - bz>>=lodn; - - int limit = MAX(0,cell_subdiv-lodn-1); - - for(int c=0;c<8;c++) { - - int x = bx; - int y = by; - int z = bz; - - if (c&1) { - x+=1; - } - if (c&2) { - y+=1; - } - if (c&4) { - z+=1; - } - - int ofs_x=0; - int ofs_y=0; - int ofs_z=0; - int size = cells_per_axis>>lodn; - int half=size/2; - - bool outside=x<0 || x>=size || y<0 || y>=size || z<0 || z>=size; - - if (outside) - continue; - - - uint32_t cell=0; - - for(int i=0;i<limit;i++) { - - BakeCell *bc = &bake_cells_write[cell]; - - int child = 0; - if (x >= ofs_x + half) { - child|=1; - ofs_x+=half; - } - if (y >= ofs_y + half) { - child|=2; - ofs_y+=half; - } - if (z >= ofs_z + half) { - child|=4; - ofs_z+=half; - } - - cell = bc->childs[child]; - if (cell==CHILD_EMPTY) - break; - - half>>=1; - } - - if (cell!=CHILD_EMPTY) { - - samples_base[l][c].r=bake_cells_write[cell].light[0]; - samples_base[l][c].g=bake_cells_write[cell].light[1]; - samples_base[l][c].b=bake_cells_write[cell].light[2]; - samples_base[l][c].a=bake_cells_write[cell].alpha; - } - - } - - - } - - Color m0x0 = samples_base[0][0].linear_interpolate(samples_base[0][1],fx); - Color m0x1 = samples_base[0][2].linear_interpolate(samples_base[0][3],fx); - Color m0y0 = m0x0.linear_interpolate(m0x1,fy); - m0x0 = samples_base[0][4].linear_interpolate(samples_base[0][5],fx); - m0x1 = samples_base[0][6].linear_interpolate(samples_base[0][7],fx); - Color m0y1 = m0x0.linear_interpolate(m0x1,fy); - Color m0z = m0y0.linear_interpolate(m0y1,fz); - - Color m1x0 = samples_base[1][0].linear_interpolate(samples_base[1][1],fx); - Color m1x1 = samples_base[1][2].linear_interpolate(samples_base[1][3],fx); - Color m1y0 = m1x0.linear_interpolate(m1x1,fy); - m1x0 = samples_base[1][4].linear_interpolate(samples_base[1][5],fx); - m1x1 = samples_base[1][6].linear_interpolate(samples_base[1][7],fx); - Color m1y1 = m1x0.linear_interpolate(m1x1,fy); - Color m1z = m1y0.linear_interpolate(m1y1,fz); - - Color m = m0z.linear_interpolate(m1z,levelf); -#else - float diameter = 1.0; - Vector3 sample_pos = from + dist * dir; - - Color m(0, 0, 0, 0); - { - int x = Math::floor(sample_pos.x); - int y = Math::floor(sample_pos.y); - int z = Math::floor(sample_pos.z); - - int ofs_x = 0; - int ofs_y = 0; - int ofs_z = 0; - int size = cells_per_axis; - int half = size / 2; - - bool outside = x < 0 || x >= size || y < 0 || y >= size || z < 0 || z >= size; - - if (!outside) { - - uint32_t cell = 0; - - for (int i = 0; i < cell_subdiv - 1; i++) { - - BakeCell *bc = &bake_cells_write[cell]; - - int child = 0; - if (x >= ofs_x + half) { - child |= 1; - ofs_x += half; - } - if (y >= ofs_y + half) { - child |= 2; - ofs_y += half; - } - if (z >= ofs_z + half) { - child |= 4; - ofs_z += half; - } - - cell = bc->childs[child]; - if (cell == CHILD_EMPTY) - break; - - half >>= 1; - } - - if (cell != CHILD_EMPTY) { - - m.r = bake_cells_write[cell].light[0]; - m.g = bake_cells_write[cell].light[1]; - m.b = bake_cells_write[cell].light[2]; - m.a = bake_cells_write[cell].alpha; - } - } - } - -#endif - // front-to-back compositing - float a = (1.0 - alpha); - color.r += a * m.r; - color.g += a * m.g; - color.b += a * m.b; - alpha += a * m.a; - //occlusion += a * voxelColor.a; - //occlusion += (a * voxelColor.a) / (1.0 + 0.03 * diameter); - dist += diameter * 0.5; // smoother - //dist += diameter; // faster but misses more voxels - } - - return color; -} - -void BakedLight::_bake_radiance(int p_idx, int p_level, int p_x, int p_y, int p_z) { - - if (p_level == cell_subdiv - 1) { - - const int NUM_CONES = 6; - Vector3 cone_directions[6] = { - Vector3(1, 0, 0), - Vector3(0.5, 0.866025, 0), - Vector3(0.5, 0.267617, 0.823639), - Vector3(0.5, -0.700629, 0.509037), - Vector3(0.5, -0.700629, -0.509037), - Vector3(0.5, 0.267617, -0.823639) - }; - float coneWeights[6] = { 0.25, 0.15, 0.15, 0.15, 0.15, 0.15 }; - - Vector3 pos = (Vector3(p_x, p_y, p_z) / float(cells_per_axis)) * bounds.size + bounds.pos; - Vector3 voxel_size = bounds.size / float(cells_per_axis); - pos += voxel_size * 0.5; - - Color accum; - - bake_cells_write[p_idx].light[0] = 0; - bake_cells_write[p_idx].light[1] = 0; - bake_cells_write[p_idx].light[2] = 0; - - int freepix = 0; - for (int i = 0; i < 6; i++) { - - if (!(bake_cells_write[p_idx].used_sides & (1 << i))) - continue; - - if ((i & 1) == 0) - bake_cells_write[p_idx].light[i / 2] = 1.0; - freepix++; - continue; - - int ofs = i / 2; - - Vector3 dir; - if ((i & 1) == 0) - dir[ofs] = 1.0; - else - dir[ofs] = -1.0; - - for (int j = 0; j < 1; j++) { - - Vector3 cone_dir; - cone_dir.x = cone_directions[j][(ofs + 0) % 3]; - cone_dir.y = cone_directions[j][(ofs + 1) % 3]; - cone_dir.z = cone_directions[j][(ofs + 2) % 3]; - - cone_dir[ofs] *= dir[ofs]; - - Color res = _cone_trace(pos + dir * voxel_size, cone_dir, Math::deg2rad(29.9849)); - accum.r += res.r; //*coneWeights[j]; - accum.g += res.g; //*coneWeights[j]; - accum.b += res.b; //*coneWeights[j]; - } - } -#if 0 - if (freepix==0) { - bake_cells_write[p_idx].light[0]=0; - bake_cells_write[p_idx].light[1]=0; - bake_cells_write[p_idx].light[2]=0; - } - - if (freepix==1) { - bake_cells_write[p_idx].light[0]=1; - bake_cells_write[p_idx].light[1]=0; - bake_cells_write[p_idx].light[2]=0; - } - - if (freepix==2) { - bake_cells_write[p_idx].light[0]=0; - bake_cells_write[p_idx].light[1]=1; - bake_cells_write[p_idx].light[2]=0; - } - - if (freepix==3) { - bake_cells_write[p_idx].light[0]=1; - bake_cells_write[p_idx].light[1]=1; - bake_cells_write[p_idx].light[2]=0; - } - - if (freepix==4) { - bake_cells_write[p_idx].light[0]=0; - bake_cells_write[p_idx].light[1]=0; - bake_cells_write[p_idx].light[2]=1; - } - - if (freepix==5) { - bake_cells_write[p_idx].light[0]=1; - bake_cells_write[p_idx].light[1]=0; - bake_cells_write[p_idx].light[2]=1; - } - - if (freepix==6) { - bake_cells_write[p_idx].light[0]=0; - bake_cells_write[p_idx].light[0]=1; - bake_cells_write[p_idx].light[0]=1; - } -#endif - //bake_cells_write[p_idx].radiance[0]=accum.r; - //bake_cells_write[p_idx].radiance[1]=accum.g; - //bake_cells_write[p_idx].radiance[2]=accum.b; - - } else { - - int half = cells_per_axis >> (p_level + 1); - - //go down - for (int i = 0; i < 8; i++) { - - uint32_t child = bake_cells_write[p_idx].childs[i]; - - if (child == CHILD_EMPTY) - continue; - - int nx = p_x; - int ny = p_y; - int nz = p_z; - - if (i & 1) - nx += half; - if (i & 2) - ny += half; - if (i & 4) - nz += half; - - _bake_radiance(child, p_level + 1, nx, ny, nz); - } - } -} - -void BakedLight::bake_radiance() { - - ERR_FAIL_COND(bake_cells.size() == 0); - - bake_cells_write = bake_cells.write(); - - _bake_radiance(0, 0, 0, 0, 0); - - bake_cells_write = PoolVector<BakeCell>::Write(); -} -int BakedLight::_find_cell(int x, int y, int z) { - - uint32_t cell = 0; - - int ofs_x = 0; - int ofs_y = 0; - int ofs_z = 0; - int size = cells_per_axis; - int half = size / 2; - - if (x < 0 || x >= size) - return -1; - if (y < 0 || y >= size) - return -1; - if (z < 0 || z >= size) - return -1; - - for (int i = 0; i < cell_subdiv - 1; i++) { - - BakeCell *bc = &bake_cells_write[cell]; - - int child = 0; - if (x >= ofs_x + half) { - child |= 1; - ofs_x += half; - } - if (y >= ofs_y + half) { - child |= 2; - ofs_y += half; - } - if (z >= ofs_z + half) { - child |= 4; - ofs_z += half; - } - - cell = bc->childs[child]; - if (cell == CHILD_EMPTY) - return -1; - - half >>= 1; - } - - return cell; -} - -int BakedLight::_plot_ray(const Vector3 &p_from, const Vector3 &p_to) { - - Vector3 from = (p_from - bounds.pos) / bounds.size; - Vector3 to = (p_to - bounds.pos) / bounds.size; - - int x1 = Math::floor(from.x * cells_per_axis); - int y1 = Math::floor(from.y * cells_per_axis); - int z1 = Math::floor(from.z * cells_per_axis); - - int x2 = Math::floor(to.x * cells_per_axis); - int y2 = Math::floor(to.y * cells_per_axis); - int z2 = Math::floor(to.z * cells_per_axis); - - int i, dx, dy, dz, l, m, n, x_inc, y_inc, z_inc, err_1, err_2, dx2, dy2, dz2; - int point[3]; - - point[0] = x1; - point[1] = y1; - point[2] = z1; - dx = x2 - x1; - dy = y2 - y1; - dz = z2 - z1; - x_inc = (dx < 0) ? -1 : 1; - l = ABS(dx); - y_inc = (dy < 0) ? -1 : 1; - m = ABS(dy); - z_inc = (dz < 0) ? -1 : 1; - n = ABS(dz); - dx2 = l << 1; - dy2 = m << 1; - dz2 = n << 1; - - if ((l >= m) && (l >= n)) { - err_1 = dy2 - l; - err_2 = dz2 - l; - for (i = 0; i < l; i++) { - int cell = _find_cell(point[0], point[1], point[2]); - if (cell >= 0) - return cell; - - if (err_1 > 0) { - point[1] += y_inc; - err_1 -= dx2; - } - if (err_2 > 0) { - point[2] += z_inc; - err_2 -= dx2; - } - err_1 += dy2; - err_2 += dz2; - point[0] += x_inc; - } - } else if ((m >= l) && (m >= n)) { - err_1 = dx2 - m; - err_2 = dz2 - m; - for (i = 0; i < m; i++) { - int cell = _find_cell(point[0], point[1], point[2]); - if (cell >= 0) - return cell; - if (err_1 > 0) { - point[0] += x_inc; - err_1 -= dy2; - } - if (err_2 > 0) { - point[2] += z_inc; - err_2 -= dy2; - } - err_1 += dx2; - err_2 += dz2; - point[1] += y_inc; - } - } else { - err_1 = dy2 - n; - err_2 = dx2 - n; - for (i = 0; i < n; i++) { - int cell = _find_cell(point[0], point[1], point[2]); - if (cell >= 0) - return cell; - - if (err_1 > 0) { - point[1] += y_inc; - err_1 -= dz2; - } - if (err_2 > 0) { - point[0] += x_inc; - err_2 -= dz2; - } - err_1 += dy2; - err_2 += dx2; - point[2] += z_inc; - } - } - return _find_cell(point[0], point[1], point[2]); -} - -void BakedLight::set_cell_subdiv(int p_subdiv) { - - cell_subdiv = p_subdiv; - - //VS::get_singleton()->baked_light_set_subdivision(baked_light,p_subdiv); -} - -int BakedLight::get_cell_subdiv() const { - - return cell_subdiv; -} - -Rect3 BakedLight::get_aabb() const { - - return Rect3(Vector3(0, 0, 0), Vector3(1, 1, 1)); -} -PoolVector<Face3> BakedLight::get_faces(uint32_t p_usage_flags) const { - - return PoolVector<Face3>(); -} - -String BakedLight::get_configuration_warning() const { - return String(); -} - -void BakedLight::_debug_mesh(int p_idx, int p_level, const Rect3 &p_aabb, DebugMode p_mode, Ref<MultiMesh> &p_multimesh, int &idx) { - - if (p_level == cell_subdiv - 1) { - - Vector3 center = p_aabb.pos + p_aabb.size * 0.5; - Transform xform; - xform.origin = center; - xform.basis.scale(p_aabb.size * 0.5); - p_multimesh->set_instance_transform(idx, xform); - Color col; - switch (p_mode) { - case DEBUG_ALBEDO: { - col = Color(bake_cells_write[p_idx].albedo[0], bake_cells_write[p_idx].albedo[1], bake_cells_write[p_idx].albedo[2]); - } break; - case DEBUG_LIGHT: { - col = Color(bake_cells_write[p_idx].light[0], bake_cells_write[p_idx].light[1], bake_cells_write[p_idx].light[2]); - Color colr = Color(bake_cells_write[p_idx].radiance[0], bake_cells_write[p_idx].radiance[1], bake_cells_write[p_idx].radiance[2]); - col.r += colr.r; - col.g += colr.g; - col.b += colr.b; - } break; - } - p_multimesh->set_instance_color(idx, col); - - idx++; - - } else { - - for (int i = 0; i < 8; i++) { - - if (bake_cells_write[p_idx].childs[i] == CHILD_EMPTY) - continue; - - Rect3 aabb = p_aabb; - aabb.size *= 0.5; - - if (i & 1) - aabb.pos.x += aabb.size.x; - if (i & 2) - aabb.pos.y += aabb.size.y; - if (i & 4) - aabb.pos.z += aabb.size.z; - - _debug_mesh(bake_cells_write[p_idx].childs[i], p_level + 1, aabb, p_mode, p_multimesh, idx); - } - } -} - -void BakedLight::create_debug_mesh(DebugMode p_mode) { - - Ref<MultiMesh> mm; - mm.instance(); - - mm->set_transform_format(MultiMesh::TRANSFORM_3D); - mm->set_color_format(MultiMesh::COLOR_8BIT); - mm->set_instance_count(bake_cells_level_used[cell_subdiv - 1]); - - Ref<Mesh> mesh; - mesh.instance(); - - { - Array arr; - arr.resize(Mesh::ARRAY_MAX); - - PoolVector<Vector3> vertices; - PoolVector<Color> colors; - - int vtx_idx = 0; -#define ADD_VTX(m_idx) \ - ; \ - vertices.push_back(face_points[m_idx]); \ - colors.push_back(Color(1, 1, 1, 1)); \ - vtx_idx++; - - for (int i = 0; i < 6; i++) { - - Vector3 face_points[4]; - - for (int j = 0; j < 4; j++) { - - float v[3]; - v[0] = 1.0; - v[1] = 1 - 2 * ((j >> 1) & 1); - v[2] = v[1] * (1 - 2 * (j & 1)); - - for (int k = 0; k < 3; k++) { - - if (i < 3) - face_points[j][(i + k) % 3] = v[k] * (i >= 3 ? -1 : 1); - else - face_points[3 - j][(i + k) % 3] = v[k] * (i >= 3 ? -1 : 1); - } - } - - //tri 1 - ADD_VTX(0); - ADD_VTX(1); - ADD_VTX(2); - //tri 2 - ADD_VTX(2); - ADD_VTX(3); - ADD_VTX(0); - } - - arr[Mesh::ARRAY_VERTEX] = vertices; - arr[Mesh::ARRAY_COLOR] = colors; - mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, arr); - } - - { - Ref<FixedSpatialMaterial> fsm; - fsm.instance(); - fsm->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - fsm->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - fsm->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); - fsm->set_albedo(Color(1, 1, 1, 1)); - - mesh->surface_set_material(0, fsm); - } - - mm->set_mesh(mesh); - - bake_cells_write = bake_cells.write(); - - int idx = 0; - _debug_mesh(0, 0, bounds, p_mode, mm, idx); - - print_line("written: " + itos(idx) + " total: " + itos(bake_cells_level_used[cell_subdiv - 1])); - - MultiMeshInstance *mmi = memnew(MultiMeshInstance); - mmi->set_multimesh(mm); - add_child(mmi); -#ifdef TOOLS_ENABLED - if (get_tree()->get_edited_scene_root() == this) { - mmi->set_owner(this); - } else { - mmi->set_owner(get_owner()); - } -#else - mmi->set_owner(get_owner()); -#endif -} - -void BakedLight::_debug_mesh_albedo() { - create_debug_mesh(DEBUG_ALBEDO); -} - -void BakedLight::_debug_mesh_light() { - create_debug_mesh(DEBUG_LIGHT); -} - -void BakedLight::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_cell_subdiv", "steps"), &BakedLight::set_cell_subdiv); - ClassDB::bind_method(D_METHOD("get_cell_subdiv"), &BakedLight::get_cell_subdiv); - - ClassDB::bind_method(D_METHOD("bake"), &BakedLight::bake); - ClassDB::set_method_flags(get_class_static(), _scs_create("bake"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); - - ClassDB::bind_method(D_METHOD("bake_lights"), &BakedLight::bake_lights); - ClassDB::set_method_flags(get_class_static(), _scs_create("bake_lights"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); - - ClassDB::bind_method(D_METHOD("bake_radiance"), &BakedLight::bake_radiance); - ClassDB::set_method_flags(get_class_static(), _scs_create("bake_radiance"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); - - ClassDB::bind_method(D_METHOD("debug_mesh_albedo"), &BakedLight::_debug_mesh_albedo); - ClassDB::set_method_flags(get_class_static(), _scs_create("debug_mesh_albedo"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); - - ClassDB::bind_method(D_METHOD("debug_mesh_light"), &BakedLight::_debug_mesh_light); - ClassDB::set_method_flags(get_class_static(), _scs_create("debug_mesh_light"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); - - ADD_PROPERTY(PropertyInfo(Variant::INT, "cell_subdiv"), "set_cell_subdiv", "get_cell_subdiv"); - ADD_SIGNAL(MethodInfo("baked_light_changed")); -} - -BakedLight::BakedLight() { - - //baked_light=VisualServer::get_singleton()->baked_light_create(); - VS::get_singleton()->instance_set_base(get_instance(), baked_light); - - cell_subdiv = 8; - bake_texture_size = 128; - color_scan_cell_width = 8; - light_pass = 0; -} - -BakedLight::~BakedLight() { - - VS::get_singleton()->free(baked_light); -} - -///////////////////////// - -#if 0 -void BakedLightSampler::set_param(Param p_param,float p_value) { - ERR_FAIL_INDEX(p_param,PARAM_MAX); - params[p_param]=p_value; - VS::get_singleton()->baked_light_sampler_set_param(base,VS::BakedLightSamplerParam(p_param),p_value); -} - -float BakedLightSampler::get_param(Param p_param) const{ - - ERR_FAIL_INDEX_V(p_param,PARAM_MAX,0); - return params[p_param]; - -} - -void BakedLightSampler::set_resolution(int p_resolution){ - - ERR_FAIL_COND(p_resolution<4 || p_resolution>32); - resolution=p_resolution; - VS::get_singleton()->baked_light_sampler_set_resolution(base,resolution); -} -int BakedLightSampler::get_resolution() const { - - return resolution; -} - -AABB BakedLightSampler::get_aabb() const { - - float r = get_param(PARAM_RADIUS); - return AABB( Vector3(-r,-r,-r),Vector3(r*2,r*2,r*2)); -} -DVector<Face3> BakedLightSampler::get_faces(uint32_t p_usage_flags) const { - return DVector<Face3>(); -} - -void BakedLightSampler::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_param","param","value"),&BakedLightSampler::set_param); - ClassDB::bind_method(D_METHOD("get_param","param"),&BakedLightSampler::get_param); - - ClassDB::bind_method(D_METHOD("set_resolution","resolution"),&BakedLightSampler::set_resolution); - ClassDB::bind_method(D_METHOD("get_resolution"),&BakedLightSampler::get_resolution); - - - BIND_CONSTANT( PARAM_RADIUS ); - BIND_CONSTANT( PARAM_STRENGTH ); - BIND_CONSTANT( PARAM_ATTENUATION ); - BIND_CONSTANT( PARAM_DETAIL_RATIO ); - BIND_CONSTANT( PARAM_MAX ); - - ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/radius",PROPERTY_HINT_RANGE,"0.01,1024,0.01"),"set_param","get_param",PARAM_RADIUS); - ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/strength",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_param","get_param",PARAM_STRENGTH); - ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/attenuation",PROPERTY_HINT_EXP_EASING),"set_param","get_param",PARAM_ATTENUATION); - ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/detail_ratio",PROPERTY_HINT_RANGE,"0.01,1.0,0.01"),"set_param","get_param",PARAM_DETAIL_RATIO); - //ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/detail_ratio",PROPERTY_HINT_RANGE,"0,20,1"),"set_param","get_param",PARAM_DETAIL_RATIO); - ADD_PROPERTY( PropertyInfo(Variant::REAL,"params/resolution",PROPERTY_HINT_RANGE,"4,32,1"),"set_resolution","get_resolution"); - -} - -BakedLightSampler::BakedLightSampler() { - - base = VS::get_singleton()->baked_light_sampler_create(); - set_base(base); - - params[PARAM_RADIUS]=1.0; - params[PARAM_STRENGTH]=1.0; - params[PARAM_ATTENUATION]=1.0; - params[PARAM_DETAIL_RATIO]=0.1; - resolution=16; - - -} - -BakedLightSampler::~BakedLightSampler(){ - - VS::get_singleton()->free(base); -} -#endif diff --git a/scene/3d/baked_light_instance.h b/scene/3d/baked_light_instance.h deleted file mode 100644 index 2180f8b17..000000000 --- a/scene/3d/baked_light_instance.h +++ /dev/null @@ -1,198 +0,0 @@ -/*************************************************************************/ -/* baked_light_instance.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef BAKED_LIGHT_INSTANCE_H -#define BAKED_LIGHT_INSTANCE_H - -#include "scene/3d/multimesh_instance.h" -#include "scene/3d/visual_instance.h" -#include "scene/resources/baked_light.h" - -class BakedLightBaker; -class Light; - -class BakedLight : public VisualInstance { - GDCLASS(BakedLight, VisualInstance); - -public: - enum DebugMode { - DEBUG_ALBEDO, - DEBUG_LIGHT - }; - -private: - RID baked_light; - int cell_subdiv; - Rect3 bounds; - int cells_per_axis; - - enum { - CHILD_EMPTY = 0xFFFFFFFF, - }; - - /* BAKE DATA */ - - struct BakeCell { - - uint32_t childs[8]; - float albedo[3]; //albedo in RGB24 - float light[3]; //accumulated light in 16:16 fixed point (needs to be integer for moving lights fast) - float radiance[3]; //accumulated light in 16:16 fixed point (needs to be integer for moving lights fast) - uint32_t used_sides; - float alpha; //used for upsampling - uint32_t light_pass; //used for baking light - - BakeCell() { - for (int i = 0; i < 8; i++) { - childs[i] = 0xFFFFFFFF; - } - - for (int i = 0; i < 3; i++) { - light[i] = 0; - albedo[i] = 0; - radiance[i] = 0; - } - alpha = 0; - light_pass = 0; - used_sides = 0; - } - }; - - int bake_texture_size; - int color_scan_cell_width; - - struct MaterialCache { - //128x128 textures - Vector<Color> albedo; - Vector<Color> emission; - }; - - Vector<Color> _get_bake_texture(Image &p_image, const Color &p_color); - - Map<Ref<Material>, MaterialCache> material_cache; - MaterialCache _get_material_cache(Ref<Material> p_material); - - int bake_cells_alloc; - int bake_cells_used; - int zero_alphas; - Vector<int> bake_cells_level_used; - PoolVector<BakeCell> bake_cells; - PoolVector<BakeCell>::Write bake_cells_write; - - void _plot_face(int p_idx, int p_level, const Vector3 *p_vtx, const Vector2 *p_uv, const MaterialCache &p_material, const Rect3 &p_aabb); - void _fixup_plot(int p_idx, int p_level, int p_x, int p_y, int p_z); - void _bake_add_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh); - void _bake_add_to_aabb(const Transform &p_xform, Ref<Mesh> &p_mesh, bool &first); - - void _debug_mesh(int p_idx, int p_level, const Rect3 &p_aabb, DebugMode p_mode, Ref<MultiMesh> &p_multimesh, int &idx); - void _debug_mesh_albedo(); - void _debug_mesh_light(); - - _FORCE_INLINE_ int _find_cell(int x, int y, int z); - int _plot_ray(const Vector3 &p_from, const Vector3 &p_to); - - uint32_t light_pass; - - void _bake_directional(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 &p_dir, const Color &p_color, int p_sign); - void _upscale_light(int p_idx, int p_level); - void _bake_light(Light *p_light); - - Color _cone_trace(const Vector3 &p_from, const Vector3 &p_dir, float p_half_angle); - void _bake_radiance(int p_idx, int p_level, int p_x, int p_y, int p_z); - - friend class GeometryInstance; - - Set<GeometryInstance *> geometries; - friend class Light; - - Set<Light *> lights; - -protected: - static void _bind_methods(); - -public: - void set_cell_subdiv(int p_subdiv); - int get_cell_subdiv() const; - - void bake(); - void bake_lights(); - void bake_radiance(); - - void create_debug_mesh(DebugMode p_mode); - - virtual Rect3 get_aabb() const; - virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const; - - String get_configuration_warning() const; - - BakedLight(); - ~BakedLight(); -}; - -#if 0 -class BakedLightSampler : public VisualInstance { - GDCLASS(BakedLightSampler,VisualInstance); - - -public: - - enum Param { - PARAM_RADIUS=VS::BAKED_LIGHT_SAMPLER_RADIUS, - PARAM_STRENGTH=VS::BAKED_LIGHT_SAMPLER_STRENGTH, - PARAM_ATTENUATION=VS::BAKED_LIGHT_SAMPLER_ATTENUATION, - PARAM_DETAIL_RATIO=VS::BAKED_LIGHT_SAMPLER_DETAIL_RATIO, - PARAM_MAX=VS::BAKED_LIGHT_SAMPLER_MAX - }; - - - -protected: - - RID base; - float params[PARAM_MAX]; - int resolution; - static void _bind_methods(); -public: - - virtual AABB get_aabb() const; - virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const; - - void set_param(Param p_param,float p_value); - float get_param(Param p_param) const; - - void set_resolution(int p_resolution); - int get_resolution() const; - - BakedLightSampler(); - ~BakedLightSampler(); -}; - -VARIANT_ENUM_CAST( BakedLightSampler::Param ); - -#endif -#endif // BAKED_LIGHT_H diff --git a/scene/3d/body_shape.cpp b/scene/3d/body_shape.cpp deleted file mode 100644 index 840380657..000000000 --- a/scene/3d/body_shape.cpp +++ /dev/null @@ -1,919 +0,0 @@ -/*************************************************************************/ -/* body_shape.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "body_shape.h" -#include "scene/resources/box_shape.h" -#include "scene/resources/capsule_shape.h" -#include "scene/resources/concave_polygon_shape.h" -#include "scene/resources/convex_polygon_shape.h" -#include "scene/resources/plane_shape.h" -#include "scene/resources/ray_shape.h" -#include "scene/resources/sphere_shape.h" -#include "servers/visual_server.h" -//TODO: Implement CylinderShape and HeightMapShape? -#include "mesh_instance.h" -#include "physics_body.h" -#include "quick_hull.h" - -void CollisionShape::_update_body() { - - if (!is_inside_tree() || !can_update_body) - return; - if (!get_tree()->is_editor_hint()) - return; - if (get_parent() && get_parent()->cast_to<CollisionObject>()) - get_parent()->cast_to<CollisionObject>()->_update_shapes_from_children(); -} - -void CollisionShape::make_convex_from_brothers() { - - Node *p = get_parent(); - if (!p) - return; - - for (int i = 0; i < p->get_child_count(); i++) { - - Node *n = p->get_child(i); - if (n->cast_to<MeshInstance>()) { - - MeshInstance *mi = n->cast_to<MeshInstance>(); - Ref<Mesh> m = mi->get_mesh(); - if (m.is_valid()) { - - Ref<Shape> s = m->create_convex_shape(); - set_shape(s); - } - } - } -} -/* - -void CollisionShape::_update_indicator() { - - while (VisualServer::get_singleton()->mesh_get_surface_count(indicator)) - VisualServer::get_singleton()->mesh_remove_surface(indicator,0); - - if (shape.is_null()) - return; - - PoolVector<Vector3> points; - PoolVector<Vector3> normals; - - VS::PrimitiveType pt = VS::PRIMITIVE_TRIANGLES; - - if (shape->cast_to<RayShape>()) { - - RayShape *rs = shape->cast_to<RayShape>(); - points.push_back(Vector3()); - points.push_back(Vector3(0,0,rs->get_length())); - pt = VS::PRIMITIVE_LINES; - } else if (shape->cast_to<SphereShape>()) { - - //VisualServer *vs=VisualServer::get_singleton(); - SphereShape *shapeptr=shape->cast_to<SphereShape>(); - - - Color col(0.4,1.0,1.0,0.5); - - int lats=6; - int lons=12; - float size=shapeptr->get_radius(); - - - for(int i = 1; i <= lats; i++) { - double lat0 = Math_PI * (-0.5 + (double) (i - 1) / lats); - double z0 = Math::sin(lat0); - double zr0 = Math::cos(lat0); - - double lat1 = Math_PI * (-0.5 + (double) i / lats); - double z1 = Math::sin(lat1); - double zr1 = Math::cos(lat1); - - for(int j = lons; j >= 1; j--) { - - double lng0 = 2 * Math_PI * (double) (j - 1) / lons; - double x0 = Math::cos(lng0); - double y0 = Math::sin(lng0); - - double lng1 = 2 * Math_PI * (double) (j) / lons; - double x1 = Math::cos(lng1); - double y1 = Math::sin(lng1); - - Vector3 v4=Vector3(x0 * zr0, z0, y0 *zr0)*size; - Vector3 v3=Vector3(x0 * zr1, z1, y0 *zr1)*size; - Vector3 v2=Vector3(x1 * zr1, z1, y1 *zr1)*size; - Vector3 v1=Vector3(x1 * zr0, z0, y1 *zr0)*size; - - Vector<Vector3> line; - line.push_back(v1); - line.push_back(v2); - line.push_back(v3); - line.push_back(v4); - - - points.push_back(v1); - points.push_back(v2); - points.push_back(v3); - - points.push_back(v1); - points.push_back(v3); - points.push_back(v4); - - normals.push_back(v1.normalized()); - normals.push_back(v2.normalized()); - normals.push_back(v3.normalized()); - - normals.push_back(v1.normalized()); - normals.push_back(v3.normalized()); - normals.push_back(v4.normalized()); - - } - } - } else if (shape->cast_to<BoxShape>()) { - - BoxShape *shapeptr=shape->cast_to<BoxShape>(); - - for (int i=0;i<6;i++) { - - - Vector3 face_points[4]; - - - for (int j=0;j<4;j++) { - - float v[3]; - v[0]=1.0; - v[1]=1-2*((j>>1)&1); - v[2]=v[1]*(1-2*(j&1)); - - for (int k=0;k<3;k++) { - - if (i<3) - face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1); - else - face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1); - } - } - Vector3 normal; - normal[i%3]=(i>=3?-1:1); - - for(int j=0;j<4;j++) - face_points[j]*=shapeptr->get_extents(); - - points.push_back(face_points[0]); - points.push_back(face_points[1]); - points.push_back(face_points[2]); - - points.push_back(face_points[0]); - points.push_back(face_points[2]); - points.push_back(face_points[3]); - - for(int n=0;n<6;n++) - normals.push_back(normal); - - } - - } else if (shape->cast_to<ConvexPolygonShape>()) { - - ConvexPolygonShape *shapeptr=shape->cast_to<ConvexPolygonShape>(); - - Geometry::MeshData md; - QuickHull::build(Variant(shapeptr->get_points()),md); - - for(int i=0;i<md.faces.size();i++) { - - for(int j=2;j<md.faces[i].indices.size();j++) { - points.push_back(md.vertices[md.faces[i].indices[0]]); - points.push_back(md.vertices[md.faces[i].indices[j-1]]); - points.push_back(md.vertices[md.faces[i].indices[j]]); - normals.push_back(md.faces[i].plane.normal); - normals.push_back(md.faces[i].plane.normal); - normals.push_back(md.faces[i].plane.normal); - } - } - } else if (shape->cast_to<ConcavePolygonShape>()) { - - ConcavePolygonShape *shapeptr=shape->cast_to<ConcavePolygonShape>(); - - points = shapeptr->get_faces(); - for(int i=0;i<points.size()/3;i++) { - - Vector3 n = Plane( points[i*3+0],points[i*3+1],points[i*3+2] ).normal; - normals.push_back(n); - normals.push_back(n); - normals.push_back(n); - } - - } else if (shape->cast_to<CapsuleShape>()) { - - CapsuleShape *shapeptr=shape->cast_to<CapsuleShape>(); - - PoolVector<Plane> planes = Geometry::build_capsule_planes(shapeptr->get_radius(), shapeptr->get_height()/2.0, 12, Vector3::AXIS_Z); - Geometry::MeshData md = Geometry::build_convex_mesh(planes); - - for(int i=0;i<md.faces.size();i++) { - - for(int j=2;j<md.faces[i].indices.size();j++) { - points.push_back(md.vertices[md.faces[i].indices[0]]); - points.push_back(md.vertices[md.faces[i].indices[j-1]]); - points.push_back(md.vertices[md.faces[i].indices[j]]); - normals.push_back(md.faces[i].plane.normal); - normals.push_back(md.faces[i].plane.normal); - normals.push_back(md.faces[i].plane.normal); - - } - } - - } else if (shape->cast_to<PlaneShape>()) { - - PlaneShape *shapeptr=shape->cast_to<PlaneShape>(); - - Plane p = shapeptr->get_plane(); - Vector3 n1 = p.get_any_perpendicular_normal(); - Vector3 n2 = p.normal.cross(n1).normalized(); - - Vector3 pface[4]={ - p.normal*p.d+n1*100.0+n2*100.0, - p.normal*p.d+n1*100.0+n2*-100.0, - p.normal*p.d+n1*-100.0+n2*-100.0, - p.normal*p.d+n1*-100.0+n2*100.0, - }; - - points.push_back(pface[0]); - points.push_back(pface[1]); - points.push_back(pface[2]); - - points.push_back(pface[0]); - points.push_back(pface[2]); - points.push_back(pface[3]); - - normals.push_back(p.normal); - normals.push_back(p.normal); - normals.push_back(p.normal); - normals.push_back(p.normal); - normals.push_back(p.normal); - normals.push_back(p.normal); - - } - - if (!points.size()) - return; - RID material = VisualServer::get_singleton()->fixed_material_create(); - VisualServer::get_singleton()->fixed_material_set_param(material,VS::FIXED_MATERIAL_PARAM_DIFFUSE,Color(0,0.6,0.7,0.3)); - VisualServer::get_singleton()->fixed_material_set_param(material,VS::FIXED_MATERIAL_PARAM_EMISSION,0.7); - if (normals.size()==0) - VisualServer::get_singleton()->material_set_flag(material,VS::MATERIAL_FLAG_UNSHADED,true); - VisualServer::get_singleton()->material_set_flag(material,VS::MATERIAL_FLAG_DOUBLE_SIDED,true); - Array d; - d.resize(VS::ARRAY_MAX); - d[VS::ARRAY_VERTEX]=points; - if (normals.size()) - d[VS::ARRAY_NORMAL]=normals; - VisualServer::get_singleton()->mesh_add_surface(indicator,pt,d); - VisualServer::get_singleton()->mesh_surface_set_material(indicator,0,material,true); - -} - -*/ -void CollisionShape::_add_to_collision_object(Object *p_cshape) { - - if (unparenting) - return; - - CollisionObject *co = p_cshape->cast_to<CollisionObject>(); - ERR_FAIL_COND(!co); - - if (shape.is_valid()) { - - update_shape_index = co->get_shape_count(); - co->add_shape(shape, get_transform()); - if (trigger) - co->set_shape_as_trigger(co->get_shape_count() - 1, true); - } else { - update_shape_index = -1; - } -} - -void CollisionShape::_notification(int p_what) { - - switch (p_what) { - - case NOTIFICATION_ENTER_TREE: { - unparenting = false; - can_update_body = get_tree()->is_editor_hint(); - set_notify_local_transform(!can_update_body); - - if (get_tree()->is_debugging_collisions_hint()) { - _create_debug_shape(); - } - - //indicator_instance = VisualServer::get_singleton()->instance_create2(indicator,get_world()->get_scenario()); - } break; - case NOTIFICATION_TRANSFORM_CHANGED: { - //VisualServer::get_singleton()->instance_set_transform(indicator_instance,get_global_transform()); - if (can_update_body && updating_body) { - _update_body(); - } - } break; - case NOTIFICATION_EXIT_TREE: { - /* if (indicator_instance.is_valid()) { - VisualServer::get_singleton()->free(indicator_instance); - indicator_instance=RID(); - }*/ - can_update_body = false; - set_notify_local_transform(false); - if (debug_shape) { - debug_shape->queue_delete(); - debug_shape = NULL; - } - } break; - case NOTIFICATION_UNPARENTED: { - unparenting = true; - if (can_update_body && updating_body) - _update_body(); - } break; - case NOTIFICATION_PARENTED: { - if (can_update_body && updating_body) - _update_body(); - } break; - case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { - - if (!can_update_body && update_shape_index >= 0) { - - CollisionObject *co = get_parent()->cast_to<CollisionObject>(); - if (co) { - co->set_shape_transform(update_shape_index, get_transform()); - } - } - - } break; - } -} - -void CollisionShape::resource_changed(RES res) { - - update_gizmo(); -} - -void CollisionShape::_set_update_shape_index(int p_index) { - - update_shape_index = p_index; -} - -int CollisionShape::_get_update_shape_index() const { - - return update_shape_index; -} - -String CollisionShape::get_configuration_warning() const { - - if (!get_parent()->cast_to<CollisionObject>()) { - return TTR("CollisionShape only serves to provide a collision shape to a CollisionObject derived node. Please only use it as a child of Area, StaticBody, RigidBody, KinematicBody, etc. to give them a shape."); - } - - if (!shape.is_valid()) { - return TTR("A shape must be provided for CollisionShape to function. Please create a shape resource for it!"); - } - - return String(); -} - -void CollisionShape::_bind_methods() { - - //not sure if this should do anything - ClassDB::bind_method(D_METHOD("resource_changed", "resource"), &CollisionShape::resource_changed); - ClassDB::bind_method(D_METHOD("set_shape", "shape"), &CollisionShape::set_shape); - ClassDB::bind_method(D_METHOD("get_shape"), &CollisionShape::get_shape); - ClassDB::bind_method(D_METHOD("_add_to_collision_object"), &CollisionShape::_add_to_collision_object); - ClassDB::bind_method(D_METHOD("set_trigger", "enable"), &CollisionShape::set_trigger); - ClassDB::bind_method(D_METHOD("is_trigger"), &CollisionShape::is_trigger); - ClassDB::bind_method(D_METHOD("make_convex_from_brothers"), &CollisionShape::make_convex_from_brothers); - ClassDB::set_method_flags("CollisionShape", "make_convex_from_brothers", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); - ClassDB::bind_method(D_METHOD("_set_update_shape_index", "index"), &CollisionShape::_set_update_shape_index); - ClassDB::bind_method(D_METHOD("_get_update_shape_index"), &CollisionShape::_get_update_shape_index); - - ClassDB::bind_method(D_METHOD("get_collision_object_shape_index"), &CollisionShape::get_collision_object_shape_index); - - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape"), "set_shape", "get_shape"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "trigger"), "set_trigger", "is_trigger"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "_update_shape_index", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_update_shape_index", "_get_update_shape_index"); -} - -void CollisionShape::set_shape(const Ref<Shape> &p_shape) { - - if (!shape.is_null()) - shape->unregister_owner(this); - shape = p_shape; - if (!shape.is_null()) - shape->register_owner(this); - update_gizmo(); - if (updating_body) { - _update_body(); - } else if (can_update_body && update_shape_index >= 0 && is_inside_tree()) { - CollisionObject *co = get_parent()->cast_to<CollisionObject>(); - if (co) { - co->set_shape(update_shape_index, p_shape); - } - } -} - -Ref<Shape> CollisionShape::get_shape() const { - - return shape; -} - -void CollisionShape::set_updating_body(bool p_update) { - updating_body = p_update; -} - -bool CollisionShape::is_updating_body() const { - - return updating_body; -} - -void CollisionShape::set_trigger(bool p_trigger) { - - trigger = p_trigger; - if (updating_body) { - _update_body(); - } else if (can_update_body && update_shape_index >= 0 && is_inside_tree()) { - CollisionObject *co = get_parent()->cast_to<CollisionObject>(); - if (co) { - co->set_shape_as_trigger(update_shape_index, p_trigger); - } - } -} - -bool CollisionShape::is_trigger() const { - - return trigger; -} - -CollisionShape::CollisionShape() { - - //indicator = VisualServer::get_singleton()->mesh_create(); - updating_body = true; - unparenting = false; - update_shape_index = -1; - trigger = false; - can_update_body = false; - debug_shape = NULL; -} - -CollisionShape::~CollisionShape() { - if (!shape.is_null()) - shape->unregister_owner(this); - //VisualServer::get_singleton()->free(indicator); -} - -void CollisionShape::_create_debug_shape() { - - if (debug_shape) { - debug_shape->queue_delete(); - debug_shape = NULL; - } - - Ref<Shape> s = get_shape(); - - if (s.is_null()) - return; - - Ref<Mesh> mesh = s->get_debug_mesh(); - - MeshInstance *mi = memnew(MeshInstance); - mi->set_mesh(mesh); - - add_child(mi); - debug_shape = mi; -} - -#if 0 -#include "body_volume.h" - -#include "geometry.h" -#include "scene/3d/physics_body.h" - -#define ADD_TRIANGLE(m_a, m_b, m_c, m_color) \ - { \ - Vector<Vector3> points; \ - points.resize(3); \ - points[0] = m_a; \ - points[1] = m_b; \ - points[2] = m_c; \ - Vector<Color> colors; \ - colors.resize(3); \ - colors[0] = m_color; \ - colors[1] = m_color; \ - colors[2] = m_color; \ - vs->poly_add_primitive(p_indicator, points, Vector<Vector3>(), colors, Vector<Vector3>()); \ - } - - -void CollisionShape::_notification(int p_what) { - - switch (p_what) { - case NOTIFICATION_ENTER_SCENE: { - - - if (get_root_node()->get_editor() && !indicator.is_valid()) { - - indicator=VisualServer::get_singleton()->poly_create(); - RID mat=VisualServer::get_singleton()->fixed_material_create(); - VisualServer::get_singleton()->material_set_flag( mat, VisualServer::MATERIAL_FLAG_UNSHADED, true ); - VisualServer::get_singleton()->material_set_flag( mat, VisualServer::MATERIAL_FLAG_WIREFRAME, true ); - VisualServer::get_singleton()->material_set_flag( mat, VisualServer::MATERIAL_FLAG_DOUBLE_SIDED, true ); - VisualServer::get_singleton()->material_set_line_width( mat, 3 ); - - VisualServer::get_singleton()->poly_set_material(indicator,mat,true); - - update_indicator(indicator); - } - - if (indicator.is_valid()) { - - indicator_instance=VisualServer::get_singleton()->instance_create2(indicator,get_world()->get_scenario()); - VisualServer::get_singleton()->instance_attach_object_instance_ID(indicator_instance,get_instance_ID()); - } - volume_changed(); - } break; - case NOTIFICATION_EXIT_SCENE: { - - if (indicator_instance.is_valid()) { - - VisualServer::get_singleton()->free(indicator_instance); - } - volume_changed(); - } break; - case NOTIFICATION_TRANSFORM_CHANGED: { - - if (indicator_instance.is_valid()) { - - VisualServer::get_singleton()->instance_set_transform(indicator_instance,get_global_transform()); - } - volume_changed(); - } break; - default: {} - } -} - -void CollisionShape::volume_changed() { - - if (indicator.is_valid()) - update_indicator(indicator); - - Object *parent=get_parent(); - if (!parent) - return; - PhysicsBody *physics_body=parent->cast_to<PhysicsBody>(); - - ERR_EXPLAIN("CollisionShape parent is not of type PhysicsBody"); - ERR_FAIL_COND(!physics_body); - - physics_body->recompute_child_volumes(); - -} - -RID CollisionShape::_get_visual_instance_rid() const { - - return indicator_instance; - -} - -void CollisionShape::_bind_methods() { - - ClassDB::bind_method("_get_visual_instance_rid",&CollisionShape::_get_visual_instance_rid); -} - -CollisionShape::CollisionShape() { - -} - -CollisionShape::~CollisionShape() { - - if (indicator.is_valid()) { - - VisualServer::get_singleton()->free(indicator); - } - -} - -void CollisionShapeSphere::_set(const String& p_name, const Variant& p_value) { - - if (p_name=="radius") { - radius=p_value; - volume_changed(); - } - -} - -Variant CollisionShapeSphere::_get(const String& p_name) const { - - if (p_name=="radius") { - return radius; - } - - return Variant(); -} - -void CollisionShapeSphere::_get_property_list( List<PropertyInfo> *p_list) const { - - p_list->push_back( PropertyInfo(Variant::REAL,"radius",PROPERTY_HINT_RANGE,"0.01,16384,0.01") ); -} - -void CollisionShapeSphere::update_indicator(RID p_indicator) { - - VisualServer *vs=VisualServer::get_singleton(); - - vs->poly_clear(p_indicator); - Color col(0.4,1.0,1.0,0.5); - - int lats=6; - int lons=12; - float size=radius; - - for(int i = 1; i <= lats; i++) { - double lat0 = Math_PI * (-0.5 + (double) (i - 1) / lats); - double z0 = Math::sin(lat0); - double zr0 = Math::cos(lat0); - - double lat1 = Math_PI * (-0.5 + (double) i / lats); - double z1 = Math::sin(lat1); - double zr1 = Math::cos(lat1); - - for(int j = lons; j >= 1; j--) { - - double lng0 = 2 * Math_PI * (double) (j - 1) / lons; - double x0 = Math::cos(lng0); - double y0 = Math::sin(lng0); - - double lng1 = 2 * Math_PI * (double) (j) / lons; - double x1 = Math::cos(lng1); - double y1 = Math::sin(lng1); - - Vector3 v4=Vector3(x0 * zr0, z0, y0 *zr0)*size; - Vector3 v3=Vector3(x0 * zr1, z1, y0 *zr1)*size; - Vector3 v2=Vector3(x1 * zr1, z1, y1 *zr1)*size; - Vector3 v1=Vector3(x1 * zr0, z0, y1 *zr0)*size; - - Vector<Vector3> line; - line.push_back(v1); - line.push_back(v2); - line.push_back(v3); - line.push_back(v4); - - Vector<Color> cols; - cols.push_back(col); - cols.push_back(col); - cols.push_back(col); - cols.push_back(col); - - - VisualServer::get_singleton()->poly_add_primitive(p_indicator,line,Vector<Vector3>(),cols,Vector<Vector3>()); - } - } -} - -void CollisionShapeSphere::append_to_volume(Ref<Shape> p_volume) { - - p_volume->add_sphere_shape(radius,get_transform()); -} - - -CollisionShapeSphere::CollisionShapeSphere() { - - radius=1.0; -} - -/* BOX */ - - -void CollisionShapeBox::_set(const String& p_name, const Variant& p_value) { - - if (p_name=="half_extents") { - half_extents=p_value; - volume_changed(); - } - -} - -Variant CollisionShapeBox::_get(const String& p_name) const { - - if (p_name=="half_extents") { - return half_extents; - } - - return Variant(); -} - -void CollisionShapeBox::_get_property_list( List<PropertyInfo> *p_list) const { - - p_list->push_back( PropertyInfo(Variant::VECTOR3,"half_extents" ) ); -} - - -void CollisionShapeBox::update_indicator(RID p_indicator) { - - VisualServer *vs=VisualServer::get_singleton(); - - vs->poly_clear(p_indicator); - Color col(0.4,1.0,1.0,0.5); - - - for (int i=0;i<6;i++) { - - - Vector3 face_points[4]; - - for (int j=0;j<4;j++) { - - float v[3]; - v[0]=1.0; - v[1]=1-2*((j>>1)&1); - v[2]=v[1]*(1-2*(j&1)); - - for (int k=0;k<3;k++) { - - if (i<3) - face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1); - else - face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1); - } - } - - for(int j=0;j<4;j++) - face_points[i]*=half_extents; - - ADD_TRIANGLE(face_points[0],face_points[1],face_points[2],col); - ADD_TRIANGLE(face_points[2],face_points[3],face_points[0],col); - - } -} - -void CollisionShapeBox::append_to_volume(Ref<Shape> p_volume) { - - p_volume->add_box_shape(half_extents,get_transform()); -} - - -CollisionShapeBox::CollisionShapeBox() { - - half_extents=Vector3(1,1,1); -} - -/* CYLINDER */ - - -void CollisionShapeCylinder::_set(const String& p_name, const Variant& p_value) { - - if (p_name=="radius") { - radius=p_value; - volume_changed(); - } - if (p_name=="height") { - height=p_value; - volume_changed(); - } - -} - -Variant CollisionShapeCylinder::_get(const String& p_name) const { - - if (p_name=="radius") { - return radius; - } - if (p_name=="height") { - return height; - } - return Variant(); -} - -void CollisionShapeCylinder::_get_property_list( List<PropertyInfo> *p_list) const { - - p_list->push_back( PropertyInfo(Variant::REAL,"radius",PROPERTY_HINT_RANGE,"0.01,16384,0.01") ); - p_list->push_back( PropertyInfo(Variant::REAL,"height",PROPERTY_HINT_RANGE,"0.01,16384,0.01") ); -} - - -void CollisionShapeCylinder::update_indicator(RID p_indicator) { - - VisualServer *vs=VisualServer::get_singleton(); - - vs->poly_clear(p_indicator); - Color col(0.4,1.0,1.0,0.5); - - PoolVector<Plane> planes = Geometry::build_cylinder_planes(radius, height, 12, Vector3::AXIS_Z); - Geometry::MeshData md = Geometry::build_convex_mesh(planes); - - for(int i=0;i<md.faces.size();i++) { - - for(int j=2;j<md.faces[i].indices.size();j++) { - ADD_TRIANGLE(md.vertices[md.faces[i].indices[0]],md.vertices[md.faces[i].indices[j-1]],md.vertices[md.faces[i].indices[j]],col); - } - } - -} - -void CollisionShapeCylinder::append_to_volume(Ref<Shape> p_volume) { - - p_volume->add_cylinder_shape(radius,height*2.0,get_transform()); -} - - -CollisionShapeCylinder::CollisionShapeCylinder() { - - height=1; - radius=1; -} - -/* CAPSULE */ - - -void CollisionShapeCapsule::_set(const String& p_name, const Variant& p_value) { - - if (p_name=="radius") { - radius=p_value; - volume_changed(); - } - - if (p_name=="height") { - height=p_value; - volume_changed(); - } - -} - -Variant CollisionShapeCapsule::_get(const String& p_name) const { - - if (p_name=="radius") { - return radius; - } - if (p_name=="height") { - return height; - } - return Variant(); -} - -void CollisionShapeCapsule::_get_property_list( List<PropertyInfo> *p_list) const { - - p_list->push_back( PropertyInfo(Variant::REAL,"radius",PROPERTY_HINT_RANGE,"0.01,16384,0.01") ); - p_list->push_back( PropertyInfo(Variant::REAL,"height",PROPERTY_HINT_RANGE,"0.01,16384,0.01") ); -} - - -void CollisionShapeCapsule::update_indicator(RID p_indicator) { - - VisualServer *vs=VisualServer::get_singleton(); - - vs->poly_clear(p_indicator); - Color col(0.4,1.0,1.0,0.5); - - PoolVector<Plane> planes = Geometry::build_capsule_planes(radius, height, 12, 3, Vector3::AXIS_Z); - Geometry::MeshData md = Geometry::build_convex_mesh(planes); - - for(int i=0;i<md.faces.size();i++) { - - for(int j=2;j<md.faces[i].indices.size();j++) { - ADD_TRIANGLE(md.vertices[md.faces[i].indices[0]],md.vertices[md.faces[i].indices[j-1]],md.vertices[md.faces[i].indices[j]],col); - } - } - -} - -void CollisionShapeCapsule::append_to_volume(Ref<Shape> p_volume) { - - - p_volume->add_capsule_shape(radius,height,get_transform()); -} - - -CollisionShapeCapsule::CollisionShapeCapsule() { - - height=1; - radius=1; -} -#endif diff --git a/scene/3d/bone_attachment.cpp b/scene/3d/bone_attachment.cpp index d8cb2dfda..b55b788b5 100644 --- a/scene/3d/bone_attachment.cpp +++ b/scene/3d/bone_attachment.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/bone_attachment.h b/scene/3d/bone_attachment.h index 194d6b4f9..65908d98a 100644 --- a/scene/3d/bone_attachment.h +++ b/scene/3d/bone_attachment.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp index 540edd8a2..3c5eb21d3 100644 --- a/scene/3d/camera.cpp +++ b/scene/3d/camera.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -93,6 +94,8 @@ bool Camera::_set(const StringName &p_name, const Variant &p_value) { set_cull_mask(p_value); } else if (p_name == "environment") { set_environment(p_value); + } else if (p_name == "doppler/tracking") { + set_doppler_tracking(DopplerTracking(int(p_value))); } else return false; @@ -130,6 +133,8 @@ bool Camera::_get(const StringName &p_name, Variant &r_ret) const { r_ret = get_v_offset(); } else if (p_name == "environment") { r_ret = get_environment(); + } else if (p_name == "doppler/tracking") { + r_ret = get_doppler_tracking(); } else return false; @@ -170,6 +175,7 @@ void Camera::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment")); p_list->push_back(PropertyInfo(Variant::REAL, "h_offset")); p_list->push_back(PropertyInfo(Variant::REAL, "v_offset")); + p_list->push_back(PropertyInfo(Variant::INT, "doppler/tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Fixed")); } void Camera::_update_camera() { @@ -208,6 +214,9 @@ void Camera::_notification(int p_what) { case NOTIFICATION_TRANSFORM_CHANGED: { _request_camera_update(); + if (doppler_tracking != DOPPLER_TRACKING_DISABLED) { + velocity_tracker->update_position(get_global_transform().origin); + } } break; case NOTIFICATION_EXIT_WORLD: { @@ -506,6 +515,22 @@ Camera::KeepAspect Camera::get_keep_aspect_mode() const { return keep_aspect; } +void Camera::set_doppler_tracking(DopplerTracking p_tracking) { + + if (doppler_tracking == p_tracking) + return; + + doppler_tracking = p_tracking; + if (p_tracking != DOPPLER_TRACKING_DISABLED) { + velocity_tracker->set_track_fixed_step(doppler_tracking == DOPPLER_TRACKING_FIXED_STEP); + velocity_tracker->reset(get_global_transform().origin); + } +} + +Camera::DopplerTracking Camera::get_doppler_tracking() const { + return doppler_tracking; +} + void Camera::_bind_methods() { ClassDB::bind_method(D_METHOD("project_ray_normal", "screen_point"), &Camera::project_ray_normal); @@ -531,10 +556,12 @@ void Camera::_bind_methods() { ClassDB::bind_method(D_METHOD("get_v_offset"), &Camera::get_v_offset); ClassDB::bind_method(D_METHOD("set_cull_mask", "mask"), &Camera::set_cull_mask); ClassDB::bind_method(D_METHOD("get_cull_mask"), &Camera::get_cull_mask); - ClassDB::bind_method(D_METHOD("set_environment", "env:Environment"), &Camera::set_environment); - ClassDB::bind_method(D_METHOD("get_environment:Environment"), &Camera::get_environment); + ClassDB::bind_method(D_METHOD("set_environment", "env"), &Camera::set_environment); + ClassDB::bind_method(D_METHOD("get_environment"), &Camera::get_environment); ClassDB::bind_method(D_METHOD("set_keep_aspect_mode", "mode"), &Camera::set_keep_aspect_mode); ClassDB::bind_method(D_METHOD("get_keep_aspect_mode"), &Camera::get_keep_aspect_mode); + ClassDB::bind_method(D_METHOD("set_doppler_tracking", "mode"), &Camera::set_doppler_tracking); + ClassDB::bind_method(D_METHOD("get_doppler_tracking"), &Camera::get_doppler_tracking); //ClassDB::bind_method(D_METHOD("_camera_make_current"),&Camera::_camera_make_current ); BIND_CONSTANT(PROJECTION_PERSPECTIVE); @@ -542,6 +569,10 @@ void Camera::_bind_methods() { BIND_CONSTANT(KEEP_WIDTH); BIND_CONSTANT(KEEP_HEIGHT); + + BIND_CONSTANT(DOPPLER_TRACKING_DISABLED) + BIND_CONSTANT(DOPPLER_TRACKING_IDLE_STEP) + BIND_CONSTANT(DOPPLER_TRACKING_FIXED_STEP) } float Camera::get_fov() const { @@ -615,6 +646,14 @@ float Camera::get_h_offset() const { return h_offset; } +Vector3 Camera::get_doppler_tracked_velocity() const { + + if (doppler_tracking != DOPPLER_TRACKING_DISABLED) { + return velocity_tracker->get_tracked_linear_velocity(); + } else { + return Vector3(); + } +} Camera::Camera() { camera = VisualServer::get_singleton()->camera_create(); @@ -625,13 +664,15 @@ Camera::Camera() { current = false; force_change = false; mode = PROJECTION_PERSPECTIVE; - set_perspective(60.0, 0.1, 100.0); + set_perspective(65.0, 0.1, 100.0); keep_aspect = KEEP_HEIGHT; layers = 0xfffff; v_offset = 0; h_offset = 0; VisualServer::get_singleton()->camera_set_cull_mask(camera, layers); //active=false; + velocity_tracker.instance(); + doppler_tracking = DOPPLER_TRACKING_DISABLED; set_notify_transform(true); } diff --git a/scene/3d/camera.h b/scene/3d/camera.h index 3c31b6bee..70849791e 100644 --- a/scene/3d/camera.h +++ b/scene/3d/camera.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,6 +31,7 @@ #define CAMERA_H #include "scene/3d/spatial.h" +#include "scene/3d/spatial_velocity_tracker.h" #include "scene/main/viewport.h" #include "scene/resources/environment.h" /** @@ -51,6 +53,12 @@ public: KEEP_HEIGHT }; + enum DopplerTracking { + DOPPLER_TRACKING_DISABLED, + DOPPLER_TRACKING_IDLE_STEP, + DOPPLER_TRACKING_FIXED_STEP + }; + private: bool force_change; bool current; @@ -79,6 +87,9 @@ private: friend class Viewport; void _update_audio_listener_state(); + DopplerTracking doppler_tracking; + Ref<SpatialVelocityTracker> velocity_tracker; + protected: void _update_camera(); virtual void _request_camera_update(); @@ -115,9 +126,9 @@ public: virtual Transform get_camera_transform() const; - Vector3 project_ray_normal(const Point2 &p_point) const; - Vector3 project_ray_origin(const Point2 &p_point) const; - Vector3 project_local_ray_normal(const Point2 &p_point) const; + Vector3 project_ray_normal(const Point2 &p_pos) const; + Vector3 project_ray_origin(const Point2 &p_pos) const; + Vector3 project_local_ray_normal(const Point2 &p_pos) const; Point2 unproject_position(const Vector3 &p_pos) const; bool is_position_behind(const Vector3 &p_pos) const; Vector3 project_position(const Point2 &p_point) const; @@ -139,11 +150,17 @@ public: void set_h_offset(float p_offset); float get_h_offset() const; + void set_doppler_tracking(DopplerTracking p_tracking); + DopplerTracking get_doppler_tracking() const; + + Vector3 get_doppler_tracked_velocity() const; + Camera(); ~Camera(); }; VARIANT_ENUM_CAST(Camera::Projection); VARIANT_ENUM_CAST(Camera::KeepAspect); +VARIANT_ENUM_CAST(Camera::DopplerTracking); #endif diff --git a/scene/3d/character_camera.cpp b/scene/3d/character_camera.cpp index edd97eaa6..065e21fcc 100644 --- a/scene/3d/character_camera.cpp +++ b/scene/3d/character_camera.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/character_camera.h b/scene/3d/character_camera.h index 464fa5c23..c3a1c70d5 100644 --- a/scene/3d/character_camera.h +++ b/scene/3d/character_camera.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/collision_object.cpp b/scene/3d/collision_object.cpp index c3e19c4b8..1aba26673 100644 --- a/scene/3d/collision_object.cpp +++ b/scene/3d/collision_object.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,17 +30,6 @@ #include "collision_object.h" #include "scene/scene_string_names.h" #include "servers/physics_server.h" -void CollisionObject::_update_shapes_from_children() { - - shapes.clear(); - for (int i = 0; i < get_child_count(); i++) { - - Node *n = get_child(i); - n->call("_add_to_collision_object", this); - } - - _update_shapes(); -} void CollisionObject::_notification(int p_what) { @@ -86,92 +76,7 @@ void CollisionObject::_notification(int p_what) { } } -void CollisionObject::_update_shapes() { - - if (!rid.is_valid()) - return; - - if (area) - PhysicsServer::get_singleton()->area_clear_shapes(rid); - else - PhysicsServer::get_singleton()->body_clear_shapes(rid); - - for (int i = 0; i < shapes.size(); i++) { - - if (shapes[i].shape.is_null()) - continue; - if (area) - PhysicsServer::get_singleton()->area_add_shape(rid, shapes[i].shape->get_rid(), shapes[i].xform); - else { - PhysicsServer::get_singleton()->body_add_shape(rid, shapes[i].shape->get_rid(), shapes[i].xform); - if (shapes[i].trigger) - PhysicsServer::get_singleton()->body_set_shape_as_trigger(rid, i, shapes[i].trigger); - } - } -} - -bool CollisionObject::_set(const StringName &p_name, const Variant &p_value) { - String name = p_name; - - if (name == "shape_count") { - - shapes.resize(p_value); - _update_shapes(); - _change_notify(); - - } else if (name.begins_with("shapes/")) { - - int idx = name.get_slicec('/', 1).to_int(); - String what = name.get_slicec('/', 2); - if (what == "shape") - set_shape(idx, RefPtr(p_value)); - else if (what == "transform") - set_shape_transform(idx, p_value); - else if (what == "trigger") - set_shape_as_trigger(idx, p_value); - - } else - return false; - - return true; -} - -bool CollisionObject::_get(const StringName &p_name, Variant &r_ret) const { - - String name = p_name; - - if (name == "shape_count") { - r_ret = shapes.size(); - } else if (name.begins_with("shapes/")) { - - int idx = name.get_slicec('/', 1).to_int(); - String what = name.get_slicec('/', 2); - if (what == "shape") - r_ret = get_shape(idx); - else if (what == "transform") - r_ret = get_shape_transform(idx); - else if (what == "trigger") - r_ret = is_shape_set_as_trigger(idx); - - } else - return false; - - return true; -} - -void CollisionObject::_get_property_list(List<PropertyInfo> *p_list) const { - - p_list->push_back(PropertyInfo(Variant::INT, "shape_count", PROPERTY_HINT_RANGE, "0,256,1", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_NO_INSTANCE_STATE)); - - for (int i = 0; i < shapes.size(); i++) { - String path = "shapes/" + itos(i) + "/"; - p_list->push_back(PropertyInfo(Variant::OBJECT, path + "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_NO_INSTANCE_STATE)); - p_list->push_back(PropertyInfo(Variant::TRANSFORM, path + "transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_NO_INSTANCE_STATE)); - p_list->push_back(PropertyInfo(Variant::BOOL, path + "trigger", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_NO_INSTANCE_STATE)); - } -} - -void CollisionObject::_input_event(Node *p_camera, const InputEvent &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape) { +void CollisionObject::_input_event(Node *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape) { if (get_script_instance()) { get_script_instance()->call(SceneStringNames::get_singleton()->_input_event, p_camera, p_input_event, p_pos, p_normal, p_shape); @@ -218,25 +123,30 @@ bool CollisionObject::is_ray_pickable() const { void CollisionObject::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_shape", "shape:Shape", "transform"), &CollisionObject::add_shape, DEFVAL(Transform())); - ClassDB::bind_method(D_METHOD("get_shape_count"), &CollisionObject::get_shape_count); - ClassDB::bind_method(D_METHOD("set_shape", "shape_idx", "shape:Shape"), &CollisionObject::set_shape); - ClassDB::bind_method(D_METHOD("set_shape_transform", "shape_idx", "transform"), &CollisionObject::set_shape_transform); - // ClassDB::bind_method(D_METHOD("set_shape_transform","shape_idx","transform"),&CollisionObject::set_shape_transform); - ClassDB::bind_method(D_METHOD("set_shape_as_trigger", "shape_idx", "enable"), &CollisionObject::set_shape_as_trigger); - ClassDB::bind_method(D_METHOD("is_shape_set_as_trigger", "shape_idx"), &CollisionObject::is_shape_set_as_trigger); - ClassDB::bind_method(D_METHOD("get_shape:Shape", "shape_idx"), &CollisionObject::get_shape); - ClassDB::bind_method(D_METHOD("get_shape_transform", "shape_idx"), &CollisionObject::get_shape_transform); - ClassDB::bind_method(D_METHOD("remove_shape", "shape_idx"), &CollisionObject::remove_shape); - ClassDB::bind_method(D_METHOD("clear_shapes"), &CollisionObject::clear_shapes); ClassDB::bind_method(D_METHOD("set_ray_pickable", "ray_pickable"), &CollisionObject::set_ray_pickable); ClassDB::bind_method(D_METHOD("is_ray_pickable"), &CollisionObject::is_ray_pickable); ClassDB::bind_method(D_METHOD("set_capture_input_on_drag", "enable"), &CollisionObject::set_capture_input_on_drag); ClassDB::bind_method(D_METHOD("get_capture_input_on_drag"), &CollisionObject::get_capture_input_on_drag); ClassDB::bind_method(D_METHOD("get_rid"), &CollisionObject::get_rid); - BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "camera"), PropertyInfo(Variant::INPUT_EVENT, "event"), PropertyInfo(Variant::VECTOR3, "click_pos"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx"))); + ClassDB::bind_method(D_METHOD("create_shape_owner", "owner"), &CollisionObject::create_shape_owner); + ClassDB::bind_method(D_METHOD("remove_shape_owner", "owner_id"), &CollisionObject::remove_shape_owner); + ClassDB::bind_method(D_METHOD("get_shape_owners"), &CollisionObject::_get_shape_owners); + ClassDB::bind_method(D_METHOD("shape_owner_set_transform", "owner_id", "transform"), &CollisionObject::shape_owner_set_transform); + ClassDB::bind_method(D_METHOD("shape_owner_get_transform", "owner_id"), &CollisionObject::shape_owner_get_transform); + ClassDB::bind_method(D_METHOD("shape_owner_get_owner", "owner_id"), &CollisionObject::shape_owner_get_owner); + ClassDB::bind_method(D_METHOD("shape_owner_set_disabled", "owner_id", "disabled"), &CollisionObject::shape_owner_set_disabled); + ClassDB::bind_method(D_METHOD("is_shape_owner_disabled", "owner_id"), &CollisionObject::is_shape_owner_disabled); + ClassDB::bind_method(D_METHOD("shape_owner_add_shape", "owner_id", "shape"), &CollisionObject::shape_owner_add_shape); + ClassDB::bind_method(D_METHOD("shape_owner_get_shape_count", "owner_id"), &CollisionObject::shape_owner_get_shape_count); + ClassDB::bind_method(D_METHOD("shape_owner_get_shape", "owner_id", "shape_id"), &CollisionObject::shape_owner_get_shape); + ClassDB::bind_method(D_METHOD("shape_owner_get_shape_index", "owner_id", "shape_id"), &CollisionObject::shape_owner_get_shape_index); + ClassDB::bind_method(D_METHOD("shape_owner_remove_shape", "owner_id", "shape_id"), &CollisionObject::shape_owner_remove_shape); + ClassDB::bind_method(D_METHOD("shape_owner_clear_shapes", "owner_id"), &CollisionObject::shape_owner_clear_shapes); + ClassDB::bind_method(D_METHOD("shape_find_owner", "shape_index"), &CollisionObject::shape_find_owner); + + BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_pos"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx"))); - ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "camera"), PropertyInfo(Variant::INPUT_EVENT, "event"), PropertyInfo(Variant::VECTOR3, "click_pos"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx"))); + ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_pos"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx"))); ADD_SIGNAL(MethodInfo("mouse_entered")); ADD_SIGNAL(MethodInfo("mouse_exited")); @@ -244,72 +154,186 @@ void CollisionObject::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "input_capture_on_drag"), "set_capture_input_on_drag", "get_capture_input_on_drag"); } -void CollisionObject::add_shape(const Ref<Shape> &p_shape, const Transform &p_transform) { +uint32_t CollisionObject::create_shape_owner(Object *p_owner) { + + ShapeData sd; + uint32_t id; + + if (shapes.size() == 0) { + id = 1; + } else { + id = shapes.back()->key() + 1; + } - ShapeData sdata; - sdata.shape = p_shape; - sdata.xform = p_transform; - shapes.push_back(sdata); - _update_shapes(); + sd.owner = p_owner; + + shapes[id] = sd; + + return id; } -int CollisionObject::get_shape_count() const { - return shapes.size(); +void CollisionObject::remove_shape_owner(uint32_t owner) { + + ERR_FAIL_COND(!shapes.has(owner)); + + shape_owner_clear_shapes(owner); + + shapes.erase(owner); } -void CollisionObject::set_shape(int p_shape_idx, const Ref<Shape> &p_shape) { - ERR_FAIL_INDEX(p_shape_idx, shapes.size()); - shapes[p_shape_idx].shape = p_shape; - _update_shapes(); +void CollisionObject::shape_owner_set_disabled(uint32_t p_owner, bool p_disabled) { + ERR_FAIL_COND(!shapes.has(p_owner)); + + ShapeData &sd = shapes[p_owner]; + sd.disabled = p_disabled; + for (int i = 0; i < sd.shapes.size(); i++) { + if (area) { + PhysicsServer::get_singleton()->area_set_shape_disabled(rid, sd.shapes[i].index, p_disabled); + } else { + PhysicsServer::get_singleton()->body_set_shape_disabled(rid, sd.shapes[i].index, p_disabled); + } + } } -void CollisionObject::set_shape_transform(int p_shape_idx, const Transform &p_transform) { +bool CollisionObject::is_shape_owner_disabled(uint32_t p_owner) const { - ERR_FAIL_INDEX(p_shape_idx, shapes.size()); - shapes[p_shape_idx].xform = p_transform; + ERR_FAIL_COND_V(!shapes.has(p_owner), false); - _update_shapes(); + return shapes[p_owner].disabled; } -Ref<Shape> CollisionObject::get_shape(int p_shape_idx) const { +void CollisionObject::get_shape_owners(List<uint32_t> *r_owners) { - ERR_FAIL_INDEX_V(p_shape_idx, shapes.size(), Ref<Shape>()); - return shapes[p_shape_idx].shape; + for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) { + r_owners->push_back(E->key()); + } } -Transform CollisionObject::get_shape_transform(int p_shape_idx) const { - ERR_FAIL_INDEX_V(p_shape_idx, shapes.size(), Transform()); - return shapes[p_shape_idx].xform; +Array CollisionObject::_get_shape_owners() { + + Array ret; + for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) { + ret.push_back(E->key()); + } + + return ret; } -void CollisionObject::remove_shape(int p_shape_idx) { - ERR_FAIL_INDEX(p_shape_idx, shapes.size()); - shapes.remove(p_shape_idx); +void CollisionObject::shape_owner_set_transform(uint32_t p_owner, const Transform &p_transform) { + + ERR_FAIL_COND(!shapes.has(p_owner)); - _update_shapes(); + ShapeData &sd = shapes[p_owner]; + sd.xform = p_transform; + for (int i = 0; i < sd.shapes.size(); i++) { + if (area) { + PhysicsServer::get_singleton()->area_set_shape_transform(rid, sd.shapes[i].index, p_transform); + } else { + PhysicsServer::get_singleton()->body_set_shape_transform(rid, sd.shapes[i].index, p_transform); + } + } } +Transform CollisionObject::shape_owner_get_transform(uint32_t p_owner) const { + + ERR_FAIL_COND_V(!shapes.has(p_owner), Transform()); -void CollisionObject::clear_shapes() { + return shapes[p_owner].xform; +} - shapes.clear(); +Object *CollisionObject::shape_owner_get_owner(uint32_t p_owner) const { - _update_shapes(); + ERR_FAIL_COND_V(!shapes.has(p_owner), NULL); + + return shapes[p_owner].owner; } -void CollisionObject::set_shape_as_trigger(int p_shape_idx, bool p_trigger) { +void CollisionObject::shape_owner_add_shape(uint32_t p_owner, const Ref<Shape> &p_shape) { - ERR_FAIL_INDEX(p_shape_idx, shapes.size()); - shapes[p_shape_idx].trigger = p_trigger; - if (!area && rid.is_valid()) { + ERR_FAIL_COND(!shapes.has(p_owner)); + ERR_FAIL_COND(p_shape.is_null()); - PhysicsServer::get_singleton()->body_set_shape_as_trigger(rid, p_shape_idx, p_trigger); + ShapeData &sd = shapes[p_owner]; + ShapeData::ShapeBase s; + s.index = total_subshapes; + s.shape = p_shape; + if (area) { + PhysicsServer::get_singleton()->area_add_shape(rid, p_shape->get_rid(), sd.xform); + } else { + PhysicsServer::get_singleton()->body_add_shape(rid, p_shape->get_rid(), sd.xform); } + sd.shapes.push_back(s); + + total_subshapes++; +} +int CollisionObject::shape_owner_get_shape_count(uint32_t p_owner) const { + + ERR_FAIL_COND_V(!shapes.has(p_owner), 0); + + return shapes[p_owner].shapes.size(); } +Ref<Shape> CollisionObject::shape_owner_get_shape(uint32_t p_owner, int p_shape) const { -bool CollisionObject::is_shape_set_as_trigger(int p_shape_idx) const { + ERR_FAIL_COND_V(!shapes.has(p_owner), Ref<Shape>()); + ERR_FAIL_INDEX_V(p_shape, shapes[p_owner].shapes.size(), Ref<Shape>()); - ERR_FAIL_INDEX_V(p_shape_idx, shapes.size(), false); - return shapes[p_shape_idx].trigger; + return shapes[p_owner].shapes[p_shape].shape; +} +int CollisionObject::shape_owner_get_shape_index(uint32_t p_owner, int p_shape) const { + + ERR_FAIL_COND_V(!shapes.has(p_owner), -1); + ERR_FAIL_INDEX_V(p_shape, shapes[p_owner].shapes.size(), -1); + + return shapes[p_owner].shapes[p_shape].index; +} + +void CollisionObject::shape_owner_remove_shape(uint32_t p_owner, int p_shape) { + + ERR_FAIL_COND(!shapes.has(p_owner)); + ERR_FAIL_INDEX(p_shape, shapes[p_owner].shapes.size()); + + int index_to_remove = shapes[p_owner].shapes[p_shape].index; + if (area) { + PhysicsServer::get_singleton()->area_remove_shape(rid, index_to_remove); + } else { + PhysicsServer::get_singleton()->body_remove_shape(rid, index_to_remove); + } + + shapes[p_owner].shapes.remove(p_shape); + + for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) { + for (int i = 0; i < E->get().shapes.size(); i++) { + if (E->get().shapes[i].index > index_to_remove) { + E->get().shapes[i].index -= 1; + } + } + } + + total_subshapes--; +} + +void CollisionObject::shape_owner_clear_shapes(uint32_t p_owner) { + + ERR_FAIL_COND(!shapes.has(p_owner)); + + while (shape_owner_get_shape_count(p_owner) > 0) { + shape_owner_remove_shape(p_owner, 0); + } +} + +uint32_t CollisionObject::shape_find_owner(int p_shape_index) const { + + ERR_FAIL_INDEX_V(p_shape_index, total_subshapes, 0); + + for (const Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) { + for (int i = 0; i < E->get().shapes.size(); i++) { + if (E->get().shapes[i].index == p_shape_index) { + return E->key(); + } + } + } + + //in theory it should be unreachable + return 0; } CollisionObject::CollisionObject(RID p_rid, bool p_area) { @@ -319,10 +343,12 @@ CollisionObject::CollisionObject(RID p_rid, bool p_area) { capture_input_on_drag = false; ray_pickable = true; set_notify_transform(true); + total_subshapes = 0; + if (p_area) { - PhysicsServer::get_singleton()->area_attach_object_instance_ID(rid, get_instance_ID()); + PhysicsServer::get_singleton()->area_attach_object_instance_id(rid, get_instance_id()); } else { - PhysicsServer::get_singleton()->body_attach_object_instance_ID(rid, get_instance_ID()); + PhysicsServer::get_singleton()->body_attach_object_instance_id(rid, get_instance_id()); } //set_transform_notify(true); } diff --git a/scene/3d/collision_object.h b/scene/3d/collision_object.h index 9b124cf27..6c13e5d50 100644 --- a/scene/3d/collision_object.h +++ b/scene/3d/collision_object.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -40,50 +41,64 @@ class CollisionObject : public Spatial { RID rid; struct ShapeData { + + Object *owner; Transform xform; - Ref<Shape> shape; - bool trigger; + struct ShapeBase { + Ref<Shape> shape; + int index; + }; + + Vector<ShapeBase> shapes; + bool disabled; ShapeData() { - trigger = false; + disabled = false; + owner = NULL; } }; + int total_subshapes; + + Map<uint32_t, ShapeData> shapes; + bool capture_input_on_drag; bool ray_pickable; - Vector<ShapeData> shapes; void _update_pickable(); - void _update_shapes(); - - friend class CollisionShape; - friend class CollisionPolygon; - void _update_shapes_from_children(); protected: CollisionObject(RID p_rid, bool p_area); void _notification(int p_what); - bool _set(const StringName &p_name, const Variant &p_value); - bool _get(const StringName &p_name, Variant &r_ret) const; - void _get_property_list(List<PropertyInfo> *p_list) const; static void _bind_methods(); friend class Viewport; - virtual void _input_event(Node *p_camera, const InputEvent &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape); + virtual void _input_event(Node *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape); virtual void _mouse_enter(); virtual void _mouse_exit(); public: - void add_shape(const Ref<Shape> &p_shape, const Transform &p_transform = Transform()); - int get_shape_count() const; - void set_shape(int p_shape_idx, const Ref<Shape> &p_shape); - void set_shape_transform(int p_shape_idx, const Transform &p_transform); - Ref<Shape> get_shape(int p_shape_idx) const; - Transform get_shape_transform(int p_shape_idx) const; - void remove_shape(int p_shape_idx); - void clear_shapes(); - void set_shape_as_trigger(int p_shape_idx, bool p_trigger); - bool is_shape_set_as_trigger(int p_shape_idx) const; + uint32_t create_shape_owner(Object *p_owner); + void remove_shape_owner(uint32_t owner); + void get_shape_owners(List<uint32_t> *r_owners); + Array _get_shape_owners(); + + void shape_owner_set_transform(uint32_t p_owner, const Transform &p_transform); + Transform shape_owner_get_transform(uint32_t p_owner) const; + Object *shape_owner_get_owner(uint32_t p_owner) const; + + void shape_owner_set_disabled(uint32_t p_owner, bool p_disabled); + bool is_shape_owner_disabled(uint32_t p_owner) const; + + void shape_owner_add_shape(uint32_t p_owner, const Ref<Shape> &p_shape); + int shape_owner_get_shape_count(uint32_t p_owner) const; + Ref<Shape> shape_owner_get_shape(uint32_t p_owner, int p_shape) const; + int shape_owner_get_shape_index(uint32_t p_owner, int p_shape) const; + + void shape_owner_remove_shape(uint32_t p_owner, int p_shape); + void shape_owner_clear_shapes(uint32_t p_owner); + + uint32_t shape_find_owner(int p_shape_index) const; void set_ray_pickable(bool p_ray_pickable); bool is_ray_pickable() const; diff --git a/scene/3d/collision_polygon.cpp b/scene/3d/collision_polygon.cpp index 12dab067d..0c61c96d0 100644 --- a/scene/3d/collision_polygon.cpp +++ b/scene/3d/collision_polygon.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,186 +33,82 @@ #include "scene/resources/concave_polygon_shape.h" #include "scene/resources/convex_polygon_shape.h" -void CollisionPolygon::_add_to_collision_object(Object *p_obj) { +void CollisionPolygon::_build_polygon() { - if (!can_update_body) + if (!parent) return; - CollisionObject *co = p_obj->cast_to<CollisionObject>(); - ERR_FAIL_COND(!co); + parent->shape_owner_clear_shapes(owner_id); if (polygon.size() == 0) return; - bool solids = build_mode == BUILD_SOLIDS; - Vector<Vector<Vector2> > decomp = Geometry::decompose_polygon(polygon); if (decomp.size() == 0) return; - if (true || solids) { + //here comes the sun, lalalala + //decompose concave into multiple convex polygons and add them - //here comes the sun, lalalala - //decompose concave into multiple convex polygons and add them - shape_from = co->get_shape_count(); - for (int i = 0; i < decomp.size(); i++) { - Ref<ConvexPolygonShape> convex = memnew(ConvexPolygonShape); - PoolVector<Vector3> cp; - int cs = decomp[i].size(); - cp.resize(cs * 2); - { - PoolVector<Vector3>::Write w = cp.write(); - int idx = 0; - for (int j = 0; j < cs; j++) { + for (int i = 0; i < decomp.size(); i++) { + Ref<ConvexPolygonShape> convex = memnew(ConvexPolygonShape); + PoolVector<Vector3> cp; + int cs = decomp[i].size(); + cp.resize(cs * 2); + { + PoolVector<Vector3>::Write w = cp.write(); + int idx = 0; + for (int j = 0; j < cs; j++) { - Vector2 d = decomp[i][j]; - w[idx++] = Vector3(d.x, d.y, depth * 0.5); - w[idx++] = Vector3(d.x, d.y, -depth * 0.5); - } + Vector2 d = decomp[i][j]; + w[idx++] = Vector3(d.x, d.y, depth * 0.5); + w[idx++] = Vector3(d.x, d.y, -depth * 0.5); } - - convex->set_points(cp); - co->add_shape(convex, get_transform()); - } - shape_to = co->get_shape_count() - 1; - if (shape_to < shape_from) { - shape_from = -1; - shape_to = -1; - } - - } else { -#if 0 - Ref<ConcavePolygonShape> concave = memnew( ConcavePolygonShape ); - - PoolVector<Vector2> segments; - segments.resize(polygon.size()*2); - PoolVector<Vector2>::Write w=segments.write(); - - for(int i=0;i<polygon.size();i++) { - w[(i<<1)+0]=polygon[i]; - w[(i<<1)+1]=polygon[(i+1)%polygon.size()]; } - w=PoolVector<Vector2>::Write(); - concave->set_segments(segments); - - co->add_shape(concave,get_transform()); -#endif + convex->set_points(cp); + parent->shape_owner_add_shape(owner_id, convex); + parent->shape_owner_set_disabled(owner_id, disabled); } - - //co->add_shape(shape,get_transform()); -} - -void CollisionPolygon::_update_parent() { - - if (!can_update_body) - return; - - Node *parent = get_parent(); - if (!parent) - return; - CollisionObject *co = parent->cast_to<CollisionObject>(); - if (!co) - return; - co->_update_shapes_from_children(); -} - -void CollisionPolygon::_set_shape_range(const Vector2 &p_range) { - - shape_from = p_range.x; - shape_to = p_range.y; -} - -Vector2 CollisionPolygon::_get_shape_range() const { - - return Vector2(shape_from, shape_to); } void CollisionPolygon::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: { - can_update_body = get_tree()->is_editor_hint(); - set_notify_local_transform(!can_update_body); - //indicator_instance = VisualServer::get_singleton()->instance_create2(indicator,get_world()->get_scenario()); - } break; - case NOTIFICATION_EXIT_TREE: { - can_update_body = false; - set_notify_local_transform(false); - } break; - case NOTIFICATION_TRANSFORM_CHANGED: { - - if (!is_inside_tree()) - break; - if (can_update_body) { - _update_parent(); + case NOTIFICATION_PARENTED: { + parent = get_parent()->cast_to<CollisionObject>(); + if (parent) { + owner_id = parent->create_shape_owner(this); + _build_polygon(); + parent->shape_owner_set_transform(owner_id, get_transform()); + parent->shape_owner_set_disabled(owner_id, disabled); } - } break; case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { - if (!can_update_body && shape_from >= 0 && shape_to >= 0) { - CollisionObject *co = get_parent()->cast_to<CollisionObject>(); - if (co) { - for (int i = shape_from; i <= shape_to; i++) { - co->set_shape_transform(i, get_transform()); - } - } + if (parent) { + parent->shape_owner_set_transform(owner_id, get_transform()); } } break; -#if 0 - case NOTIFICATION_DRAW: { - for(int i=0;i<polygon.size();i++) { - - Vector2 p = polygon[i]; - Vector2 n = polygon[(i+1)%polygon.size()]; - draw_line(p,n,Color(0,0.6,0.7,0.5),3); + case NOTIFICATION_UNPARENTED: { + if (parent) { + parent->remove_shape_owner(owner_id); } - - Vector< Vector<Vector2> > decomp = Geometry::decompose_polygon(polygon); -#define DEBUG_DECOMPOSE -#ifdef DEBUG_DECOMPOSE - Color c(0.4,0.9,0.1); - for(int i=0;i<decomp.size();i++) { - - c.set_hsv( Math::fmod(c.get_h() + 0.738,1),c.get_s(),c.get_v(),0.5); - draw_colored_polygon(decomp[i],c); - } -#endif - + owner_id = 0; + parent = NULL; } break; -#endif } } void CollisionPolygon::set_polygon(const Vector<Point2> &p_polygon) { polygon = p_polygon; - if (can_update_body) { - - for (int i = 0; i < polygon.size(); i++) { - - Vector3 p1(polygon[i].x, polygon[i].y, depth * 0.5); - - if (i == 0) - aabb = Rect3(p1, Vector3()); - else - aabb.expand_to(p1); - - Vector3 p2(polygon[i].x, polygon[i].y, -depth * 0.5); - aabb.expand_to(p2); - } - if (aabb == Rect3()) { - - aabb = Rect3(Vector3(-1, -1, -1), Vector3(2, 2, 2)); - } else { - aabb.pos -= aabb.size * 0.3; - aabb.size += aabb.size * 0.6; - } - _update_parent(); + if (parent) { + _build_polygon(); } + update_configuration_warning(); update_gizmo(); } @@ -220,20 +117,6 @@ Vector<Point2> CollisionPolygon::get_polygon() const { return polygon; } -void CollisionPolygon::set_build_mode(BuildMode p_mode) { - - ERR_FAIL_INDEX(p_mode, 2); - build_mode = p_mode; - if (!can_update_body) - return; - _update_parent(); -} - -CollisionPolygon::BuildMode CollisionPolygon::get_build_mode() const { - - return build_mode; -} - Rect3 CollisionPolygon::get_item_rect() const { return aabb; @@ -242,9 +125,7 @@ Rect3 CollisionPolygon::get_item_rect() const { void CollisionPolygon::set_depth(float p_depth) { depth = p_depth; - if (!can_update_body) - return; - _update_parent(); + _build_polygon(); update_gizmo(); } @@ -253,6 +134,17 @@ float CollisionPolygon::get_depth() const { return depth; } +void CollisionPolygon::set_disabled(bool p_disabled) { + disabled = p_disabled; + if (parent) { + parent->shape_owner_set_disabled(owner_id, p_disabled); + } +} + +bool CollisionPolygon::is_disabled() const { + return disabled; +} + String CollisionPolygon::get_configuration_warning() const { if (!get_parent()->cast_to<CollisionObject>()) { @@ -268,36 +160,26 @@ String CollisionPolygon::get_configuration_warning() const { void CollisionPolygon::_bind_methods() { - ClassDB::bind_method(D_METHOD("_add_to_collision_object"), &CollisionPolygon::_add_to_collision_object); - - ClassDB::bind_method(D_METHOD("set_build_mode", "build_mode"), &CollisionPolygon::set_build_mode); - ClassDB::bind_method(D_METHOD("get_build_mode"), &CollisionPolygon::get_build_mode); - ClassDB::bind_method(D_METHOD("set_depth", "depth"), &CollisionPolygon::set_depth); ClassDB::bind_method(D_METHOD("get_depth"), &CollisionPolygon::get_depth); ClassDB::bind_method(D_METHOD("set_polygon", "polygon"), &CollisionPolygon::set_polygon); ClassDB::bind_method(D_METHOD("get_polygon"), &CollisionPolygon::get_polygon); - ClassDB::bind_method(D_METHOD("_set_shape_range", "shape_range"), &CollisionPolygon::_set_shape_range); - ClassDB::bind_method(D_METHOD("_get_shape_range"), &CollisionPolygon::_get_shape_range); - - ClassDB::bind_method(D_METHOD("get_collision_object_first_shape"), &CollisionPolygon::get_collision_object_first_shape); - ClassDB::bind_method(D_METHOD("get_collision_object_last_shape"), &CollisionPolygon::get_collision_object_last_shape); + ClassDB::bind_method(D_METHOD("set_disabled", "disabled"), &CollisionPolygon::set_disabled); + ClassDB::bind_method(D_METHOD("is_disabled"), &CollisionPolygon::is_disabled); - ADD_PROPERTY(PropertyInfo(Variant::INT, "build_mode", PROPERTY_HINT_ENUM, "Solids,Triangles"), "set_build_mode", "get_build_mode"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "depth"), "set_depth", "get_depth"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled"); ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "shape_range", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_shape_range", "_get_shape_range"); } CollisionPolygon::CollisionPolygon() { - shape_from = -1; - shape_to = -1; - can_update_body = false; - aabb = Rect3(Vector3(-1, -1, -1), Vector3(2, 2, 2)); - build_mode = BUILD_SOLIDS; depth = 1.0; + set_notify_local_transform(true); + parent = NULL; + owner_id = 0; + disabled = false; } diff --git a/scene/3d/collision_polygon.h b/scene/3d/collision_polygon.h index fee146a87..beefae182 100644 --- a/scene/3d/collision_polygon.h +++ b/scene/3d/collision_polygon.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,55 +33,42 @@ #include "scene/3d/spatial.h" #include "scene/resources/shape.h" +class CollisionObject; class CollisionPolygon : public Spatial { GDCLASS(CollisionPolygon, Spatial); -public: - enum BuildMode { - BUILD_SOLIDS, - BUILD_TRIANGLES, - }; - protected: float depth; Rect3 aabb; - BuildMode build_mode; Vector<Point2> polygon; - void _add_to_collision_object(Object *p_obj); - void _update_parent(); + uint32_t owner_id; + CollisionObject *parent; - bool can_update_body; - int shape_from; - int shape_to; + bool disabled; - void _set_shape_range(const Vector2 &p_range); - Vector2 _get_shape_range() const; + void _build_polygon(); protected: void _notification(int p_what); static void _bind_methods(); public: - void set_build_mode(BuildMode p_mode); - BuildMode get_build_mode() const; - void set_depth(float p_depth); float get_depth() const; void set_polygon(const Vector<Point2> &p_polygon); Vector<Point2> get_polygon() const; - virtual Rect3 get_item_rect() const; + void set_disabled(bool p_disabled); + bool is_disabled() const; - int get_collision_object_first_shape() const { return shape_from; } - int get_collision_object_last_shape() const { return shape_to; } + virtual Rect3 get_item_rect() const; String get_configuration_warning() const; CollisionPolygon(); }; -VARIANT_ENUM_CAST(CollisionPolygon::BuildMode); #endif // COLLISION_POLYGON_H diff --git a/scene/3d/collision_shape.cpp b/scene/3d/collision_shape.cpp new file mode 100644 index 000000000..2aa6a9571 --- /dev/null +++ b/scene/3d/collision_shape.cpp @@ -0,0 +1,207 @@ +/*************************************************************************/ +/* body_shape.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "collision_shape.h" +#include "scene/resources/box_shape.h" +#include "scene/resources/capsule_shape.h" +#include "scene/resources/concave_polygon_shape.h" +#include "scene/resources/convex_polygon_shape.h" +#include "scene/resources/plane_shape.h" +#include "scene/resources/ray_shape.h" +#include "scene/resources/sphere_shape.h" +#include "servers/visual_server.h" +//TODO: Implement CylinderShape and HeightMapShape? +#include "mesh_instance.h" +#include "physics_body.h" +#include "quick_hull.h" + +void CollisionShape::make_convex_from_brothers() { + + Node *p = get_parent(); + if (!p) + return; + + for (int i = 0; i < p->get_child_count(); i++) { + + Node *n = p->get_child(i); + if (n->cast_to<MeshInstance>()) { + + MeshInstance *mi = n->cast_to<MeshInstance>(); + Ref<Mesh> m = mi->get_mesh(); + if (m.is_valid()) { + + Ref<Shape> s = m->create_convex_shape(); + set_shape(s); + } + } + } +} + +void CollisionShape::_notification(int p_what) { + + switch (p_what) { + + case NOTIFICATION_PARENTED: { + parent = get_parent()->cast_to<CollisionObject>(); + if (parent) { + owner_id = parent->create_shape_owner(this); + if (shape.is_valid()) { + parent->shape_owner_add_shape(owner_id, shape); + } + parent->shape_owner_set_transform(owner_id, get_transform()); + parent->shape_owner_set_disabled(owner_id, disabled); + } + } break; + case NOTIFICATION_ENTER_TREE: { + if (get_tree()->is_debugging_collisions_hint()) { + _create_debug_shape(); + } + + } break; + case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { + if (parent) { + parent->shape_owner_set_transform(owner_id, get_transform()); + } + } break; + case NOTIFICATION_UNPARENTED: { + if (parent) { + parent->remove_shape_owner(owner_id); + } + owner_id = 0; + parent = NULL; + } break; + } +} + +void CollisionShape::resource_changed(RES res) { + + update_gizmo(); +} + +String CollisionShape::get_configuration_warning() const { + + if (!get_parent()->cast_to<CollisionObject>()) { + return TTR("CollisionShape only serves to provide a collision shape to a CollisionObject derived node. Please only use it as a child of Area, StaticBody, RigidBody, KinematicBody, etc. to give them a shape."); + } + + if (!shape.is_valid()) { + return TTR("A shape must be provided for CollisionShape to function. Please create a shape resource for it!"); + } + + return String(); +} + +void CollisionShape::_bind_methods() { + + //not sure if this should do anything + ClassDB::bind_method(D_METHOD("resource_changed", "resource"), &CollisionShape::resource_changed); + ClassDB::bind_method(D_METHOD("set_shape", "shape"), &CollisionShape::set_shape); + ClassDB::bind_method(D_METHOD("get_shape"), &CollisionShape::get_shape); + ClassDB::bind_method(D_METHOD("set_disabled", "enable"), &CollisionShape::set_disabled); + ClassDB::bind_method(D_METHOD("is_disabled"), &CollisionShape::is_disabled); + ClassDB::bind_method(D_METHOD("make_convex_from_brothers"), &CollisionShape::make_convex_from_brothers); + ClassDB::set_method_flags("CollisionShape", "make_convex_from_brothers", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape"), "set_shape", "get_shape"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled"); +} + +void CollisionShape::set_shape(const Ref<Shape> &p_shape) { + + if (!shape.is_null()) + shape->unregister_owner(this); + shape = p_shape; + if (!shape.is_null()) + shape->register_owner(this); + update_gizmo(); + if (parent) { + parent->shape_owner_clear_shapes(owner_id); + if (shape.is_valid()) { + parent->shape_owner_add_shape(owner_id, shape); + } + } + + update_configuration_warning(); +} + +Ref<Shape> CollisionShape::get_shape() const { + + return shape; +} + +void CollisionShape::set_disabled(bool p_disabled) { + + disabled = p_disabled; + update_gizmo(); + if (parent) { + parent->shape_owner_set_disabled(owner_id, p_disabled); + } +} + +bool CollisionShape::is_disabled() const { + + return disabled; +} + +CollisionShape::CollisionShape() { + + //indicator = VisualServer::get_singleton()->mesh_create(); + disabled = false; + debug_shape = NULL; + parent = NULL; + owner_id = 0; + set_notify_local_transform(true); +} + +CollisionShape::~CollisionShape() { + if (!shape.is_null()) + shape->unregister_owner(this); + //VisualServer::get_singleton()->free(indicator); +} + +void CollisionShape::_create_debug_shape() { + + if (debug_shape) { + debug_shape->queue_delete(); + debug_shape = NULL; + } + + Ref<Shape> s = get_shape(); + + if (s.is_null()) + return; + + Ref<Mesh> mesh = s->get_debug_mesh(); + + MeshInstance *mi = memnew(MeshInstance); + mi->set_mesh(mesh); + + add_child(mi); + debug_shape = mi; +} diff --git a/scene/3d/body_shape.h b/scene/3d/collision_shape.h index 137a6cd9f..277e0dfa7 100644 --- a/scene/3d/body_shape.h +++ b/scene/3d/collision_shape.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +32,7 @@ #include "scene/3d/spatial.h" #include "scene/resources/shape.h" - +class CollisionObject; class CollisionShape : public Spatial { GDCLASS(CollisionShape, Spatial); @@ -39,34 +40,13 @@ class CollisionShape : public Spatial { Ref<Shape> shape; - /* - RID _get_visual_instance_rid() const; - - - void _update_indicator(); - - RID material; - RID indicator; - RID indicator_instance; - */ + uint32_t owner_id; + CollisionObject *parent; Node *debug_shape; void resource_changed(RES res); - - bool updating_body; - bool unparenting; - bool trigger; - - bool can_update_body; - - int update_shape_index; - - void _update_body(); - void _add_to_collision_object(Object *p_cshape); - - void _set_update_shape_index(int p_index); - int _get_update_shape_index() const; + bool disabled; void _create_debug_shape(); @@ -80,13 +60,8 @@ public: void set_shape(const Ref<Shape> &p_shape); Ref<Shape> get_shape() const; - void set_updating_body(bool p_update); - bool is_updating_body() const; - - void set_trigger(bool p_trigger); - bool is_trigger() const; - - int get_collision_object_shape_index() const { return _get_update_shape_index(); } + void set_disabled(bool p_disabled); + bool is_disabled() const; String get_configuration_warning() const; diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp index cb1292a9d..2174f924a 100644 --- a/scene/3d/gi_probe.cpp +++ b/scene/3d/gi_probe.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -94,6 +95,16 @@ float GIProbeData::get_bias() const { return VS::get_singleton()->gi_probe_get_bias(probe); } +void GIProbeData::set_normal_bias(float p_range) { + + VS::get_singleton()->gi_probe_set_normal_bias(probe, p_range); +} + +float GIProbeData::get_normal_bias() const { + + return VS::get_singleton()->gi_probe_get_normal_bias(probe); +} + void GIProbeData::set_propagation(float p_range) { VS::get_singleton()->gi_probe_set_propagation(probe, p_range); @@ -157,6 +168,9 @@ void GIProbeData::_bind_methods() { ClassDB::bind_method(D_METHOD("set_bias", "bias"), &GIProbeData::set_bias); ClassDB::bind_method(D_METHOD("get_bias"), &GIProbeData::get_bias); + ClassDB::bind_method(D_METHOD("set_normal_bias", "bias"), &GIProbeData::set_normal_bias); + ClassDB::bind_method(D_METHOD("get_normal_bias"), &GIProbeData::get_normal_bias); + ClassDB::bind_method(D_METHOD("set_propagation", "propagation"), &GIProbeData::set_propagation); ClassDB::bind_method(D_METHOD("get_propagation"), &GIProbeData::get_propagation); @@ -174,6 +188,7 @@ void GIProbeData::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "dynamic_range", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_dynamic_range", "get_dynamic_range"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "energy", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_energy", "get_energy"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "bias", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_bias", "get_bias"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "normal_bias", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_normal_bias", "get_normal_bias"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "propagation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_propagation", "get_propagation"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_interior", "is_interior"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "compress", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_compress", "is_compressed"); @@ -264,6 +279,18 @@ float GIProbe::get_bias() const { return bias; } +void GIProbe::set_normal_bias(float p_normal_bias) { + + normal_bias = p_normal_bias; + if (probe_data.is_valid()) { + probe_data->set_normal_bias(normal_bias); + } +} +float GIProbe::get_normal_bias() const { + + return normal_bias; +} + void GIProbe::set_propagation(float p_propagation) { propagation = p_propagation; @@ -563,7 +590,7 @@ void GIProbe::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, cons Vector3 ofs_j = float(j) * t2; - Vector3 from = p_aabb.pos + ofs_i + ofs_j; + Vector3 from = p_aabb.position + ofs_i + ofs_j; Vector3 to = from + t1 + t2 + axis * p_aabb.size[closest_axis]; Vector3 half = (to - from) * 0.5; @@ -618,7 +645,7 @@ void GIProbe::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, cons //could not in any way get texture information.. so use closest point to center Face3 f(p_vtx[0], p_vtx[1], p_vtx[2]); - Vector3 inters = f.get_closest_point_to(p_aabb.pos + p_aabb.size * 0.5); + Vector3 inters = f.get_closest_point_to(p_aabb.position + p_aabb.size * 0.5); Vector2 uv = get_uv(inters, p_vtx, p_uv); @@ -699,15 +726,15 @@ void GIProbe::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, cons int nz = p_z; if (i & 1) { - aabb.pos.x += aabb.size.x; + aabb.position.x += aabb.size.x; nx += half; } if (i & 2) { - aabb.pos.y += aabb.size.y; + aabb.position.y += aabb.size.y; ny += half; } if (i & 4) { - aabb.pos.z += aabb.size.z; + aabb.position.z += aabb.size.z; nz += half; } //make sure to not plot beyond limits @@ -719,7 +746,7 @@ void GIProbe::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, cons //test_aabb.grow_by(test_aabb.get_longest_axis_size()*0.05); //grow a bit to avoid numerical error in real-time Vector3 qsize = test_aabb.size * 0.5; //quarter size, for fast aabb test - if (!fast_tri_box_overlap(test_aabb.pos + qsize, qsize, p_vtx)) { + if (!fast_tri_box_overlap(test_aabb.position + qsize, qsize, p_vtx)) { //if (!Face3(p_vtx[0],p_vtx[1],p_vtx[2]).intersects_aabb2(aabb)) { //does not fit in child, go on continue; @@ -880,11 +907,11 @@ void GIProbe::_fixup_plot(int p_idx, int p_level, int p_x, int p_y, int p_z, Bak } } -Vector<Color> GIProbe::_get_bake_texture(Image &p_image, const Color &p_color) { +Vector<Color> GIProbe::_get_bake_texture(Ref<Image> p_image, const Color &p_color) { Vector<Color> ret; - if (p_image.empty()) { + if (p_image.is_null() || p_image->empty()) { ret.resize(bake_texture_size * bake_texture_size); for (int i = 0; i < bake_texture_size * bake_texture_size; i++) { @@ -893,23 +920,26 @@ Vector<Color> GIProbe::_get_bake_texture(Image &p_image, const Color &p_color) { return ret; } + p_image = p_image->duplicate(); - if (p_image.is_compressed()) { + if (p_image->is_compressed()) { print_line("DECOMPRESSING!!!!"); - p_image.decompress(); + + p_image->decompress(); } - p_image.convert(Image::FORMAT_RGBA8); - p_image.resize(bake_texture_size, bake_texture_size, Image::INTERPOLATE_CUBIC); + p_image->convert(Image::FORMAT_RGBA8); + p_image->resize(bake_texture_size, bake_texture_size, Image::INTERPOLATE_CUBIC); - PoolVector<uint8_t>::Read r = p_image.get_data().read(); + PoolVector<uint8_t>::Read r = p_image->get_data().read(); ret.resize(bake_texture_size * bake_texture_size); for (int i = 0; i < bake_texture_size * bake_texture_size; i++) { Color c; - c.r = r[i * 4 + 0] / 255.0; - c.g = r[i * 4 + 1] / 255.0; - c.b = r[i * 4 + 2] / 255.0; + c.r = (r[i * 4 + 0] / 255.0) * p_color.r; + c.g = (r[i * 4 + 1] / 255.0) * p_color.g; + c.b = (r[i * 4 + 2] / 255.0) * p_color.b; c.a = r[i * 4 + 3] / 255.0; + ret[i] = c; } @@ -919,7 +949,7 @@ Vector<Color> GIProbe::_get_bake_texture(Image &p_image, const Color &p_color) { GIProbe::Baker::MaterialCache GIProbe::_get_material_cache(Ref<Material> p_material, Baker *p_baker) { //this way of obtaining materials is inaccurate and also does not support some compressed formats very well - Ref<FixedSpatialMaterial> mat = p_material; + Ref<SpatialMaterial> mat = p_material; Ref<Material> material = mat; //hack for now @@ -931,9 +961,9 @@ GIProbe::Baker::MaterialCache GIProbe::_get_material_cache(Ref<Material> p_mater if (mat.is_valid()) { - Ref<Texture> albedo_tex = mat->get_texture(FixedSpatialMaterial::TEXTURE_ALBEDO); + Ref<Texture> albedo_tex = mat->get_texture(SpatialMaterial::TEXTURE_ALBEDO); - Image img_albedo; + Ref<Image> img_albedo; if (albedo_tex.is_valid()) { img_albedo = albedo_tex->get_data(); @@ -942,14 +972,14 @@ GIProbe::Baker::MaterialCache GIProbe::_get_material_cache(Ref<Material> p_mater mc.albedo = _get_bake_texture(img_albedo, mat->get_albedo()); - Ref<ImageTexture> emission_tex = mat->get_texture(FixedSpatialMaterial::TEXTURE_EMISSION); + Ref<ImageTexture> emission_tex = mat->get_texture(SpatialMaterial::TEXTURE_EMISSION); Color emission_col = mat->get_emission(); emission_col.r *= mat->get_emission_energy(); emission_col.g *= mat->get_emission_energy(); emission_col.b *= mat->get_emission_energy(); - Image img_emission; + Ref<Image> img_emission; if (emission_tex.is_valid()) { @@ -959,7 +989,7 @@ GIProbe::Baker::MaterialCache GIProbe::_get_material_cache(Ref<Material> p_mater mc.emission = _get_bake_texture(img_emission, emission_col); } else { - Image empty; + Ref<Image> empty; mc.albedo = _get_bake_texture(empty, Color(0.7, 0.7, 0.7)); mc.emission = _get_bake_texture(empty, Color(0, 0, 0)); @@ -1151,7 +1181,7 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) { Transform to_bounds; to_bounds.basis.scale(Vector3(baker.po2_bounds.size[longest_axis], baker.po2_bounds.size[longest_axis], baker.po2_bounds.size[longest_axis])); - to_bounds.origin = baker.po2_bounds.pos; + to_bounds.origin = baker.po2_bounds.position; Transform to_grid; to_grid.basis.scale(Vector3(baker.axis_cell_size[longest_axis], baker.axis_cell_size[longest_axis], baker.axis_cell_size[longest_axis])); @@ -1257,6 +1287,7 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) { probe_data->set_dynamic_range(dynamic_range); probe_data->set_energy(energy); probe_data->set_bias(bias); + probe_data->set_normal_bias(normal_bias); probe_data->set_propagation(propagation); probe_data->set_interior(interior); probe_data->set_compress(compress); @@ -1270,12 +1301,13 @@ void GIProbe::_debug_mesh(int p_idx, int p_level, const Rect3 &p_aabb, Ref<Multi if (p_level == p_baker->cell_subdiv - 1) { - Vector3 center = p_aabb.pos + p_aabb.size * 0.5; + Vector3 center = p_aabb.position + p_aabb.size * 0.5; Transform xform; xform.origin = center; xform.basis.scale(p_aabb.size * 0.5); p_multimesh->set_instance_transform(idx, xform); Color col = Color(p_baker->bake_cells[p_idx].albedo[0], p_baker->bake_cells[p_idx].albedo[1], p_baker->bake_cells[p_idx].albedo[2]); + //Color col = Color(p_baker->bake_cells[p_idx].emission[0], p_baker->bake_cells[p_idx].emission[1], p_baker->bake_cells[p_idx].emission[2]); p_multimesh->set_instance_color(idx, col); idx++; @@ -1291,11 +1323,11 @@ void GIProbe::_debug_mesh(int p_idx, int p_level, const Rect3 &p_aabb, Ref<Multi aabb.size *= 0.5; if (i & 1) - aabb.pos.x += aabb.size.x; + aabb.position.x += aabb.size.x; if (i & 2) - aabb.pos.y += aabb.size.y; + aabb.position.y += aabb.size.y; if (i & 4) - aabb.pos.z += aabb.size.z; + aabb.position.z += aabb.size.z; _debug_mesh(p_baker->bake_cells[p_idx].childs[i], p_level + 1, aabb, p_multimesh, idx, p_baker); } @@ -1312,7 +1344,7 @@ void GIProbe::_create_debug_mesh(Baker *p_baker) { print_line("leaf voxels: " + itos(p_baker->leaf_voxel_count)); mm->set_instance_count(p_baker->leaf_voxel_count); - Ref<Mesh> mesh; + Ref<ArrayMesh> mesh; mesh.instance(); { @@ -1365,11 +1397,11 @@ void GIProbe::_create_debug_mesh(Baker *p_baker) { } { - Ref<FixedSpatialMaterial> fsm; + Ref<SpatialMaterial> fsm; fsm.instance(); - fsm->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - fsm->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - fsm->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); + fsm->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); + fsm->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + fsm->set_flag(SpatialMaterial::FLAG_UNSHADED, true); fsm->set_albedo(Color(1, 1, 1, 1)); mesh->surface_set_material(0, fsm); @@ -1429,6 +1461,9 @@ void GIProbe::_bind_methods() { ClassDB::bind_method(D_METHOD("set_bias", "max"), &GIProbe::set_bias); ClassDB::bind_method(D_METHOD("get_bias"), &GIProbe::get_bias); + ClassDB::bind_method(D_METHOD("set_normal_bias", "max"), &GIProbe::set_normal_bias); + ClassDB::bind_method(D_METHOD("get_normal_bias"), &GIProbe::get_normal_bias); + ClassDB::bind_method(D_METHOD("set_propagation", "max"), &GIProbe::set_propagation); ClassDB::bind_method(D_METHOD("get_propagation"), &GIProbe::get_propagation); @@ -1448,6 +1483,7 @@ void GIProbe::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_energy", "get_energy"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "propagation", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_propagation", "get_propagation"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "bias", PROPERTY_HINT_RANGE, "0,4,0.001"), "set_bias", "get_bias"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "normal_bias", PROPERTY_HINT_RANGE, "0,4,0.001"), "set_normal_bias", "get_normal_bias"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "compress"), "set_compress", "is_compressed"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "data", PROPERTY_HINT_RESOURCE_TYPE, "GIProbeData"), "set_probe_data", "get_probe_data"); @@ -1463,7 +1499,8 @@ GIProbe::GIProbe() { subdiv = SUBDIV_128; dynamic_range = 4; energy = 1.0; - bias = 0.4; + bias = 0.0; + normal_bias = 0.8; propagation = 1.0; extents = Vector3(10, 10, 10); color_scan_cell_width = 4; diff --git a/scene/3d/gi_probe.h b/scene/3d/gi_probe.h index 675b41cef..8346437eb 100644 --- a/scene/3d/gi_probe.h +++ b/scene/3d/gi_probe.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -66,6 +67,9 @@ public: void set_bias(float p_range); float get_bias() const; + void set_normal_bias(float p_range); + float get_normal_bias() const; + void set_interior(bool p_enable); bool is_interior() const; @@ -133,7 +137,7 @@ private: Vector<Color> emission; }; - Vector<Color> _get_bake_texture(Image &p_image, const Color &p_color); + Vector<Color> _get_bake_texture(Ref<Image> p_image, const Color &p_color); Map<Ref<Material>, MaterialCache> material_cache; MaterialCache _get_material_cache(Ref<Material> p_material); int leaf_voxel_count; @@ -162,6 +166,7 @@ private: int dynamic_range; float energy; float bias; + float normal_bias; float propagation; bool interior; bool compress; @@ -169,7 +174,7 @@ private: int color_scan_cell_width; int bake_texture_size; - Vector<Color> _get_bake_texture(Image &p_image, const Color &p_color); + Vector<Color> _get_bake_texture(Ref<Image> p_image, const Color &p_color); Baker::MaterialCache _get_material_cache(Ref<Material> p_material, Baker *p_baker); void _plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 *p_vtx, const Vector2 *p_uv, const Baker::MaterialCache &p_material, const Rect3 &p_aabb, Baker *p_baker); void _plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, Baker *p_baker, const Vector<Ref<Material> > &p_materials, const Ref<Material> &p_override_material); @@ -203,6 +208,9 @@ public: void set_bias(float p_bias); float get_bias() const; + void set_normal_bias(float p_normal_bias); + float get_normal_bias() const; + void set_propagation(float p_propagation); float get_propagation() const; diff --git a/scene/3d/immediate_geometry.cpp b/scene/3d/immediate_geometry.cpp index adcc16722..060e08875 100644 --- a/scene/3d/immediate_geometry.cpp +++ b/scene/3d/immediate_geometry.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -64,7 +65,7 @@ void ImmediateGeometry::add_vertex(const Vector3 &p_vertex) { VS::get_singleton()->immediate_vertex(im, p_vertex); if (empty) { - aabb.pos = p_vertex; + aabb.position = p_vertex; aabb.size = Vector3(); empty = false; } else { @@ -142,7 +143,7 @@ void ImmediateGeometry::add_sphere(int p_lats, int p_lons, float p_radius, bool void ImmediateGeometry::_bind_methods() { - ClassDB::bind_method(D_METHOD("begin", "primitive", "texture:Texture"), &ImmediateGeometry::begin, DEFVAL(Ref<Texture>())); + ClassDB::bind_method(D_METHOD("begin", "primitive", "texture"), &ImmediateGeometry::begin, DEFVAL(Ref<Texture>())); ClassDB::bind_method(D_METHOD("set_normal", "normal"), &ImmediateGeometry::set_normal); ClassDB::bind_method(D_METHOD("set_tangent", "tangent"), &ImmediateGeometry::set_tangent); ClassDB::bind_method(D_METHOD("set_color", "color"), &ImmediateGeometry::set_color); diff --git a/scene/3d/immediate_geometry.h b/scene/3d/immediate_geometry.h index 6e0123992..bc8452c7e 100644 --- a/scene/3d/immediate_geometry.h +++ b/scene/3d/immediate_geometry.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -51,8 +52,8 @@ public: void set_normal(const Vector3 &p_normal); void set_tangent(const Plane &p_tangent); void set_color(const Color &p_color); - void set_uv(const Vector2 &tex_uv); - void set_uv2(const Vector2 &tex_uv); + void set_uv(const Vector2 &p_uv); + void set_uv2(const Vector2 &p_uv2); void add_vertex(const Vector3 &p_vertex); diff --git a/scene/3d/interpolated_camera.cpp b/scene/3d/interpolated_camera.cpp index 9723a686c..36a6660bf 100644 --- a/scene/3d/interpolated_camera.cpp +++ b/scene/3d/interpolated_camera.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -131,7 +132,7 @@ void InterpolatedCamera::_bind_methods() { ClassDB::bind_method(D_METHOD("set_target_path", "target_path"), &InterpolatedCamera::set_target_path); ClassDB::bind_method(D_METHOD("get_target_path"), &InterpolatedCamera::get_target_path); - ClassDB::bind_method(D_METHOD("set_target", "target:Camera"), &InterpolatedCamera::_set_target); + ClassDB::bind_method(D_METHOD("set_target", "target"), &InterpolatedCamera::_set_target); ClassDB::bind_method(D_METHOD("set_speed", "speed"), &InterpolatedCamera::set_speed); ClassDB::bind_method(D_METHOD("get_speed"), &InterpolatedCamera::get_speed); diff --git a/scene/3d/interpolated_camera.h b/scene/3d/interpolated_camera.h index ebadf3994..c302c32fc 100644 --- a/scene/3d/interpolated_camera.h +++ b/scene/3d/interpolated_camera.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp index 7d0123051..977f1f81a 100644 --- a/scene/3d/light.cpp +++ b/scene/3d/light.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -28,8 +29,7 @@ /*************************************************************************/ #include "light.h" -#include "baked_light_instance.h" -#include "global_config.h" +#include "project_settings.h" #include "scene/resources/surface_tool.h" bool Light::_can_gizmo_scale() const { @@ -165,26 +165,9 @@ void Light::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { _update_visibility(); - - Node *node = this; - - while (node) { - - baked_light = node->cast_to<BakedLight>(); - if (baked_light) { - baked_light->lights.insert(this); - break; - } - - node = node->get_parent(); - } } if (p_what == NOTIFICATION_EXIT_TREE) { - - if (baked_light) { - baked_light->lights.erase(this); - } } } @@ -251,7 +234,7 @@ void Light::_bind_methods() { BIND_CONSTANT(PARAM_SHADOW_SPLIT_3_OFFSET); BIND_CONSTANT(PARAM_SHADOW_NORMAL_BIAS); BIND_CONSTANT(PARAM_SHADOW_BIAS); - BIND_CONSTANT(PARAM_SHADOW_BIAS_SPLIT_SCALE); + BIND_CONSTANT(PARAM_MAX); } @@ -261,8 +244,6 @@ Light::Light(VisualServer::LightType p_type) { light = VisualServer::get_singleton()->light_create(p_type); VS::get_singleton()->instance_set_base(get_instance(), light); - baked_light = NULL; - editor_only = false; set_color(Color(1, 1, 1, 1)); set_shadow(false); @@ -280,9 +261,8 @@ Light::Light(VisualServer::LightType p_type) { set_param(PARAM_SHADOW_SPLIT_1_OFFSET, 0.1); set_param(PARAM_SHADOW_SPLIT_2_OFFSET, 0.2); set_param(PARAM_SHADOW_SPLIT_3_OFFSET, 0.5); - set_param(PARAM_SHADOW_NORMAL_BIAS, 0.1); - set_param(PARAM_SHADOW_BIAS, 0.1); - set_param(PARAM_SHADOW_BIAS_SPLIT_SCALE, 0.1); + set_param(PARAM_SHADOW_NORMAL_BIAS, 0.0); + set_param(PARAM_SHADOW_BIAS, 0.15); } Light::Light() { @@ -337,7 +317,6 @@ void DirectionalLight::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_split_3", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_3_OFFSET); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "directional_shadow_blend_splits"), "set_blend_splits", "is_blend_splits_enabled"); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_normal_bias", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_param", "get_param", PARAM_SHADOW_NORMAL_BIAS); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_bias_split_scale", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_param", "get_param", PARAM_SHADOW_BIAS_SPLIT_SCALE); BIND_CONSTANT(SHADOW_ORTHOGONAL); BIND_CONSTANT(SHADOW_PARALLEL_2_SPLITS); @@ -347,7 +326,11 @@ void DirectionalLight::_bind_methods() { DirectionalLight::DirectionalLight() : Light(VisualServer::LIGHT_DIRECTIONAL) { + set_param(PARAM_SHADOW_NORMAL_BIAS, 0.2); + set_param(PARAM_SHADOW_BIAS, 1.0); + set_param(PARAM_SHADOW_MAX_DISTANCE, 200); set_shadow_mode(SHADOW_PARALLEL_4_SPLITS); + blend_splits = false; } @@ -390,7 +373,7 @@ void OmniLight::_bind_methods() { OmniLight::OmniLight() : Light(VisualServer::LIGHT_OMNI) { - set_shadow_mode(SHADOW_DUAL_PARABOLOID); + set_shadow_mode(SHADOW_CUBE); set_shadow_detail(SHADOW_DETAIL_HORIZONTAL); } diff --git a/scene/3d/light.h b/scene/3d/light.h index fd50f0fcc..22ff5c076 100644 --- a/scene/3d/light.h +++ b/scene/3d/light.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -59,7 +60,6 @@ public: PARAM_SHADOW_SPLIT_3_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET, PARAM_SHADOW_NORMAL_BIAS = VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS, PARAM_SHADOW_BIAS = VS::LIGHT_PARAM_SHADOW_BIAS, - PARAM_SHADOW_BIAS_SPLIT_SCALE = VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE, PARAM_MAX = VS::LIGHT_PARAM_MAX }; @@ -74,7 +74,6 @@ private: bool editor_only; void _update_visibility(); - BakedLight *baked_light; // bind helpers protected: diff --git a/scene/3d/listener.cpp b/scene/3d/listener.cpp index fc9326b57..c7d3bac2f 100644 --- a/scene/3d/listener.cpp +++ b/scene/3d/listener.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -151,7 +152,7 @@ bool Listener::_can_gizmo_scale() const { } RES Listener::_get_gizmo_geometry() const { - Ref<Mesh> mesh = memnew(Mesh); + Ref<ArrayMesh> mesh = memnew(ArrayMesh); return mesh; } diff --git a/scene/3d/listener.h b/scene/3d/listener.h index 4fb2aea07..b66fc7fc3 100644 --- a/scene/3d/listener.h +++ b/scene/3d/listener.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp index b61232dbf..da25afbf5 100644 --- a/scene/3d/mesh_instance.cpp +++ b/scene/3d/mesh_instance.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -28,9 +29,10 @@ /*************************************************************************/ #include "mesh_instance.h" -#include "body_shape.h" +#include "collision_shape.h" #include "core_string_names.h" #include "physics_body.h" +#include "scene/resources/material.h" #include "scene/scene_string_names.h" #include "skeleton.h" bool MeshInstance::_set(const StringName &p_name, const Variant &p_value) { @@ -97,7 +99,7 @@ void MeshInstance::_get_property_list(List<PropertyInfo> *p_list) const { if (mesh.is_valid()) { for (int i = 0; i < mesh->get_surface_count(); i++) { - p_list->push_back(PropertyInfo(Variant::OBJECT, "material/" + itos(i), PROPERTY_HINT_RESOURCE_TYPE, "Material")); + p_list->push_back(PropertyInfo(Variant::OBJECT, "material/" + itos(i), PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,SpatialMaterial")); } } } @@ -192,7 +194,9 @@ Node *MeshInstance::create_trimesh_collision_node() { return NULL; StaticBody *static_body = memnew(StaticBody); - static_body->add_shape(shape); + CollisionShape *cshape = memnew(CollisionShape); + cshape->set_shape(shape); + static_body->add_child(cshape); return static_body; } @@ -203,13 +207,11 @@ void MeshInstance::create_trimesh_collision() { static_body->set_name(String(get_name()) + "_col"); add_child(static_body); - if (get_owner()) + if (get_owner()) { + CollisionShape *cshape = static_body->get_child(0)->cast_to<CollisionShape>(); static_body->set_owner(get_owner()); - CollisionShape *cshape = memnew(CollisionShape); - cshape->set_shape(static_body->get_shape(0)); - static_body->add_child(cshape); - if (get_owner()) cshape->set_owner(get_owner()); + } } Node *MeshInstance::create_convex_collision_node() { @@ -222,7 +224,9 @@ Node *MeshInstance::create_convex_collision_node() { return NULL; StaticBody *static_body = memnew(StaticBody); - static_body->add_shape(shape); + CollisionShape *cshape = memnew(CollisionShape); + cshape->set_shape(shape); + static_body->add_child(cshape); return static_body; } @@ -233,13 +237,11 @@ void MeshInstance::create_convex_collision() { static_body->set_name(String(get_name()) + "_col"); add_child(static_body); - if (get_owner()) + if (get_owner()) { + CollisionShape *cshape = static_body->get_child(0)->cast_to<CollisionShape>(); static_body->set_owner(get_owner()); - CollisionShape *cshape = memnew(CollisionShape); - cshape->set_shape(static_body->get_shape(0)); - static_body->add_child(cshape); - if (get_owner()) cshape->set_owner(get_owner()); + } } void MeshInstance::_notification(int p_what) { @@ -273,12 +275,90 @@ void MeshInstance::_mesh_changed() { materials.resize(mesh->get_surface_count()); } +void MeshInstance::create_debug_tangents() { + + Vector<Vector3> lines; + Vector<Color> colors; + + Ref<Mesh> mesh = get_mesh(); + if (!mesh.is_valid()) + return; + + for (int i = 0; i < mesh->get_surface_count(); i++) { + Array arrays = mesh->surface_get_arrays(i); + Vector<Vector3> verts = arrays[Mesh::ARRAY_VERTEX]; + Vector<Vector3> norms = arrays[Mesh::ARRAY_NORMAL]; + if (norms.size() == 0) + continue; + Vector<float> tangents = arrays[Mesh::ARRAY_TANGENT]; + if (tangents.size() == 0) + continue; + + for (int j = 0; j < verts.size(); j++) { + Vector3 v = verts[j]; + Vector3 n = norms[j]; + Vector3 t = Vector3(tangents[j * 4 + 0], tangents[j * 4 + 1], tangents[j * 4 + 2]); + Vector3 b = (n.cross(t)).normalized() * tangents[j * 4 + 3]; + + lines.push_back(v); //normal + colors.push_back(Color(0, 0, 1)); //color + lines.push_back(v + n * 0.04); //normal + colors.push_back(Color(0, 0, 1)); //color + + lines.push_back(v); //tangent + colors.push_back(Color(1, 0, 0)); //color + lines.push_back(v + t * 0.04); //tangent + colors.push_back(Color(1, 0, 0)); //color + + lines.push_back(v); //binormal + colors.push_back(Color(0, 1, 0)); //color + lines.push_back(v + b * 0.04); //binormal + colors.push_back(Color(0, 1, 0)); //color + } + } + + if (lines.size()) { + + Ref<SpatialMaterial> sm; + sm.instance(); + + sm->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + sm->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); + sm->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + + Ref<ArrayMesh> am; + am.instance(); + Array a; + a.resize(Mesh::ARRAY_MAX); + a[Mesh::ARRAY_VERTEX] = lines; + a[Mesh::ARRAY_COLOR] = colors; + + am->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a); + am->surface_set_material(0, sm); + + MeshInstance *mi = memnew(MeshInstance); + mi->set_mesh(am); + mi->set_name("DebugTangents"); + add_child(mi); +#ifdef TOOLS_ENABLED + + if (this == get_tree()->get_edited_scene_root()) + mi->set_owner(this); + else + mi->set_owner(get_owner()); +#endif + } +} + void MeshInstance::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_mesh", "mesh:Mesh"), &MeshInstance::set_mesh); - ClassDB::bind_method(D_METHOD("get_mesh:Mesh"), &MeshInstance::get_mesh); - ClassDB::bind_method(D_METHOD("set_skeleton_path", "skeleton_path:NodePath"), &MeshInstance::set_skeleton_path); - ClassDB::bind_method(D_METHOD("get_skeleton_path:NodePath"), &MeshInstance::get_skeleton_path); + ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &MeshInstance::set_mesh); + ClassDB::bind_method(D_METHOD("get_mesh"), &MeshInstance::get_mesh); + ClassDB::bind_method(D_METHOD("set_skeleton_path", "skeleton_path"), &MeshInstance::set_skeleton_path); + ClassDB::bind_method(D_METHOD("get_skeleton_path"), &MeshInstance::get_skeleton_path); + + ClassDB::bind_method(D_METHOD("set_surface_material", "surface", "material"), &MeshInstance::set_surface_material); + ClassDB::bind_method(D_METHOD("get_surface_material", "surface"), &MeshInstance::get_surface_material); ClassDB::bind_method(D_METHOD("create_trimesh_collision"), &MeshInstance::create_trimesh_collision); ClassDB::set_method_flags("MeshInstance", "create_trimesh_collision", METHOD_FLAGS_DEFAULT); @@ -286,6 +366,9 @@ void MeshInstance::_bind_methods() { ClassDB::set_method_flags("MeshInstance", "create_convex_collision", METHOD_FLAGS_DEFAULT); ClassDB::bind_method(D_METHOD("_mesh_changed"), &MeshInstance::_mesh_changed); + ClassDB::bind_method(D_METHOD("create_debug_tangents"), &MeshInstance::create_debug_tangents); + ClassDB::set_method_flags("MeshInstance", "create_debug_tangents", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh"); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton"), "set_skeleton_path", "get_skeleton_path"); } diff --git a/scene/3d/mesh_instance.h b/scene/3d/mesh_instance.h index 543f407ca..1bb2c97d1 100644 --- a/scene/3d/mesh_instance.h +++ b/scene/3d/mesh_instance.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -82,6 +83,8 @@ public: Node *create_convex_collision_node(); void create_convex_collision(); + void create_debug_tangents(); + virtual Rect3 get_aabb() const; virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const; diff --git a/scene/3d/multimesh_instance.cpp b/scene/3d/multimesh_instance.cpp index 18a747a5b..b51953f27 100644 --- a/scene/3d/multimesh_instance.cpp +++ b/scene/3d/multimesh_instance.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/multimesh_instance.h b/scene/3d/multimesh_instance.h index 4a0edb563..7e14d567a 100644 --- a/scene/3d/multimesh_instance.h +++ b/scene/3d/multimesh_instance.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/navigation.cpp b/scene/3d/navigation.cpp index 093d217cb..a1183326d 100644 --- a/scene/3d/navigation.cpp +++ b/scene/3d/navigation.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -689,7 +690,7 @@ Vector3 Navigation::get_up_vector() const { void Navigation::_bind_methods() { - ClassDB::bind_method(D_METHOD("navmesh_create", "mesh:NavigationMesh", "xform", "owner"), &Navigation::navmesh_create, DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("navmesh_create", "mesh", "xform", "owner"), &Navigation::navmesh_create, DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("navmesh_set_transform", "id", "xform"), &Navigation::navmesh_set_transform); ClassDB::bind_method(D_METHOD("navmesh_remove", "id"), &Navigation::navmesh_remove); diff --git a/scene/3d/navigation.h b/scene/3d/navigation.h index 6222d2bad..80699fce7 100644 --- a/scene/3d/navigation.h +++ b/scene/3d/navigation.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -57,9 +58,9 @@ class Navigation : public Spatial { return (a.key == p_key.a.key) ? (b.key < p_key.b.key) : (a.key < p_key.a.key); }; - EdgeKey(const Point &p_a = Point(), const Point &p_b = Point()) { - a = p_a; - b = p_b; + EdgeKey(const Point &p_a = Point(), const Point &p_b = Point()) + : a(p_a), + b(p_b) { if (a.key > b.key) { SWAP(a, b); } diff --git a/scene/3d/navigation_mesh.cpp b/scene/3d/navigation_mesh.cpp index 1059a9b97..5d4568f5d 100644 --- a/scene/3d/navigation_mesh.cpp +++ b/scene/3d/navigation_mesh.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -148,8 +149,8 @@ Ref<Mesh> NavigationMesh::get_debug_mesh() { tw[tidx++] = f.vertex[j]; _EdgeKey ek; - ek.from = f.vertex[j].snapped(CMP_EPSILON); - ek.to = f.vertex[(j + 1) % 3].snapped(CMP_EPSILON); + ek.from = f.vertex[j].snapped(Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON)); + ek.to = f.vertex[(j + 1) % 3].snapped(Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON)); if (ek.from < ek.to) SWAP(ek.from, ek.to); @@ -186,7 +187,7 @@ Ref<Mesh> NavigationMesh::get_debug_mesh() { } } - debug_mesh = Ref<Mesh>(memnew(Mesh)); + debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); Array arr; arr.resize(Mesh::ARRAY_MAX); @@ -207,6 +208,8 @@ void NavigationMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("get_polygon", "idx"), &NavigationMesh::get_polygon); ClassDB::bind_method(D_METHOD("clear_polygons"), &NavigationMesh::clear_polygons); + ClassDB::bind_method(D_METHOD("create_from_mesh", "mesh"), &NavigationMesh::create_from_mesh); + ClassDB::bind_method(D_METHOD("_set_polygons", "polygons"), &NavigationMesh::_set_polygons); ClassDB::bind_method(D_METHOD("_get_polygons"), &NavigationMesh::_get_polygons); diff --git a/scene/3d/navigation_mesh.h b/scene/3d/navigation_mesh.h index fda892378..e5a3dc7b4 100644 --- a/scene/3d/navigation_mesh.h +++ b/scene/3d/navigation_mesh.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -43,7 +44,7 @@ class NavigationMesh : public Resource { Vector<int> indices; }; Vector<Polygon> polygons; - Ref<Mesh> debug_mesh; + Ref<ArrayMesh> debug_mesh; struct _EdgeKey { diff --git a/scene/3d/particles.cpp b/scene/3d/particles.cpp index ea61253ac..e88a52c76 100644 --- a/scene/3d/particles.cpp +++ b/scene/3d/particles.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,532 +31,1525 @@ #include "scene/resources/surface_tool.h" #include "servers/visual_server.h" -#if 0 -/* -static const char* _var_names[Particles::VAR_MAX]={ - "vars/lifetime", - "vars/spread", - "vars/gravity", - "vars/linear_vel", - "vars/angular_vel", - "vars/linear_accel", - "vars/radial_accel", - "vars/tan_accel", - "vars/initial_size", - "vars/final_size", - "vars/initial_angle", - "vars/height", - "vars/height_speed_scale", -}; -*/ -static const char* _rand_names[Particles::VAR_MAX]={ - "rand/lifetime", - "rand/spread", - "rand/gravity", - "rand/linear_vel", - "rand/angular_vel", - "rand/linear_accel", - "rand/radial_accel", - "rand/tan_accel", - "rand/damping", - "rand/initial_size", - "rand/final_size", - "rand/initial_angle", - "rand/height", - "rand/height_speed_scale", -}; +Rect3 Particles::get_aabb() const { -static const Particles::Variable _var_indices[Particles::VAR_MAX]={ - Particles::VAR_LIFETIME, - Particles::VAR_SPREAD, - Particles::VAR_GRAVITY, - Particles::VAR_LINEAR_VELOCITY, - Particles::VAR_ANGULAR_VELOCITY, - Particles::VAR_LINEAR_ACCELERATION, - Particles::VAR_DRAG, - Particles::VAR_TANGENTIAL_ACCELERATION, - Particles::VAR_DAMPING, - Particles::VAR_INITIAL_SIZE, - Particles::VAR_FINAL_SIZE, - Particles::VAR_INITIAL_ANGLE, - Particles::VAR_HEIGHT, - Particles::VAR_HEIGHT_SPEED_SCALE, -}; + return Rect3(); +} +PoolVector<Face3> Particles::get_faces(uint32_t p_usage_flags) const { + return PoolVector<Face3>(); +} +void Particles::set_emitting(bool p_emitting) { -AABB Particles::get_aabb() const { + emitting = p_emitting; + VS::get_singleton()->particles_set_emitting(particles, emitting); +} + +void Particles::set_amount(int p_amount) { - return AABB( Vector3(-1,-1,-1), Vector3(2, 2, 2 ) ); + ERR_FAIL_COND(p_amount < 1); + amount = p_amount; + VS::get_singleton()->particles_set_amount(particles, amount); } -PoolVector<Face3> Particles::get_faces(uint32_t p_usage_flags) const { +void Particles::set_lifetime(float p_lifetime) { - return PoolVector<Face3>(); + ERR_FAIL_COND(p_lifetime <= 0); + lifetime = p_lifetime; + VS::get_singleton()->particles_set_lifetime(particles, lifetime); } +void Particles::set_one_shot(bool p_one_shot) { -void Particles::set_amount(int p_amount) { + one_shot = p_one_shot; + VS::get_singleton()->particles_set_one_shot(particles, one_shot); + if (!one_shot && emitting) + VisualServer::get_singleton()->particles_restart(particles); +} - ERR_FAIL_INDEX(p_amount,1024); - amount=p_amount; - VisualServer::get_singleton()->particles_set_amount(particles,p_amount); +void Particles::set_pre_process_time(float p_time) { + + pre_process_time = p_time; + VS::get_singleton()->particles_set_pre_process_time(particles, pre_process_time); } -int Particles::get_amount() const { +void Particles::set_explosiveness_ratio(float p_ratio) { - return amount; + explosiveness_ratio = p_ratio; + VS::get_singleton()->particles_set_explosiveness_ratio(particles, explosiveness_ratio); } +void Particles::set_randomness_ratio(float p_ratio) { -void Particles::set_emitting(bool p_emitting) { + randomness_ratio = p_ratio; + VS::get_singleton()->particles_set_randomness_ratio(particles, randomness_ratio); +} +void Particles::set_visibility_aabb(const Rect3 &p_aabb) { + + visibility_aabb = p_aabb; + VS::get_singleton()->particles_set_custom_aabb(particles, visibility_aabb); + update_gizmo(); + _change_notify("visibility_aabb"); +} +void Particles::set_use_local_coordinates(bool p_enable) { - emitting=p_emitting; - VisualServer::get_singleton()->particles_set_emitting(particles,p_emitting); + local_coords = p_enable; + VS::get_singleton()->particles_set_use_local_coordinates(particles, local_coords); +} +void Particles::set_process_material(const Ref<Material> &p_material) { - setup_timer(); + process_material = p_material; + RID material_rid; + if (process_material.is_valid()) + material_rid = process_material->get_rid(); + VS::get_singleton()->particles_set_process_material(particles, material_rid); + + update_configuration_warning(); } + +void Particles::set_speed_scale(float p_scale) { + + speed_scale = p_scale; + VS::get_singleton()->particles_set_speed_scale(particles, p_scale); +} + bool Particles::is_emitting() const { return emitting; } +int Particles::get_amount() const { + + return amount; +} +float Particles::get_lifetime() const { -void Particles::set_visibility_aabb(const AABB& p_aabb) { + return lifetime; +} +bool Particles::get_one_shot() const { - visibility_aabb=p_aabb; - VisualServer::get_singleton()->particles_set_visibility_aabb(particles,p_aabb); - update_gizmo(); + return one_shot; +} + +float Particles::get_pre_process_time() const { + + return pre_process_time; +} +float Particles::get_explosiveness_ratio() const { + return explosiveness_ratio; } -AABB Particles::get_visibility_aabb() const { +float Particles::get_randomness_ratio() const { + + return randomness_ratio; +} +Rect3 Particles::get_visibility_aabb() const { return visibility_aabb; } +bool Particles::get_use_local_coordinates() const { + return local_coords; +} +Ref<Material> Particles::get_process_material() const { + + return process_material; +} -void Particles::set_emission_points(const PoolVector<Vector3>& p_points) { +float Particles::get_speed_scale() const { - using_points = p_points.size(); - VisualServer::get_singleton()->particles_set_emission_points(particles,p_points); + return speed_scale; } -PoolVector<Vector3> Particles::get_emission_points() const { +void Particles::set_draw_order(DrawOrder p_order) { - if (!using_points) - return PoolVector<Vector3>(); + draw_order = p_order; + VS::get_singleton()->particles_set_draw_order(particles, VS::ParticlesDrawOrder(p_order)); +} - return VisualServer::get_singleton()->particles_get_emission_points(particles); +Particles::DrawOrder Particles::get_draw_order() const { + return draw_order; } -void Particles::set_emission_half_extents(const Vector3& p_half_extents) { +void Particles::set_draw_passes(int p_count) { - emission_half_extents=p_half_extents; - VisualServer::get_singleton()->particles_set_emission_half_extents(particles,p_half_extents); + ERR_FAIL_COND(p_count < 1); + draw_passes.resize(p_count); + VS::get_singleton()->particles_set_draw_passes(particles, p_count); + _change_notify(); +} +int Particles::get_draw_passes() const { + return draw_passes.size(); } -Vector3 Particles::get_emission_half_extents() const { +void Particles::set_draw_pass_mesh(int p_pass, const Ref<Mesh> &p_mesh) { + + ERR_FAIL_INDEX(p_pass, draw_passes.size()); + + draw_passes[p_pass] = p_mesh; - return emission_half_extents; + RID mesh_rid; + if (p_mesh.is_valid()) + mesh_rid = p_mesh->get_rid(); + + VS::get_singleton()->particles_set_draw_pass_mesh(particles, p_pass, mesh_rid); + + update_configuration_warning(); } -void Particles::set_emission_base_velocity(const Vector3& p_base_velocity) { +Ref<Mesh> Particles::get_draw_pass_mesh(int p_pass) const { - emission_base_velocity=p_base_velocity; - VisualServer::get_singleton()->particles_set_emission_base_velocity(particles,p_base_velocity); + ERR_FAIL_INDEX_V(p_pass, draw_passes.size(), Ref<Mesh>()); + return draw_passes[p_pass]; } -Vector3 Particles::get_emission_base_velocity() const { +void Particles::set_fixed_fps(int p_count) { + fixed_fps = p_count; + VS::get_singleton()->particles_set_fixed_fps(particles, p_count); +} - return emission_base_velocity; +int Particles::get_fixed_fps() const { + return fixed_fps; } -void Particles::set_gravity_normal(const Vector3& p_normal) { +void Particles::set_fractional_delta(bool p_enable) { + fractional_delta = p_enable; + VS::get_singleton()->particles_set_fractional_delta(particles, p_enable); +} - gravity_normal=p_normal; - VisualServer::get_singleton()->particles_set_gravity_normal(particles,p_normal); +bool Particles::get_fractional_delta() const { + return fractional_delta; } -Vector3 Particles::get_gravity_normal() const { +String Particles::get_configuration_warning() const { + + String warnings; + + bool meshes_found = false; + + for (int i = 0; i < draw_passes.size(); i++) { + if (draw_passes[i].is_valid()) { + meshes_found = true; + break; + } + } + + if (!meshes_found) { + warnings += "- " + TTR("Nothing is visible because meshes have not been assigned to draw passes."); + } - return gravity_normal; + if (process_material.is_null()) { + if (warnings != String()) + warnings += "\n"; + warnings += "- " + TTR("A material to process the particles is not assigned, so no behavior is imprinted."); + } + return warnings; } -void Particles::set_variable(Variable p_variable,float p_value) { +void Particles::restart() { - ERR_FAIL_INDEX(p_variable,VAR_MAX); - var[p_variable]=p_value; - VisualServer::get_singleton()->particles_set_variable(particles,(VS::ParticleVariable)p_variable,p_value); - if (p_variable==VAR_SPREAD) - update_gizmo(); + VisualServer::get_singleton()->particles_restart(particles); } -float Particles::get_variable(Variable p_variable) const { +Rect3 Particles::capture_aabb() const { + + return VS::get_singleton()->particles_get_current_aabb(particles); +} - ERR_FAIL_INDEX_V(p_variable,VAR_MAX,-1); - return var[p_variable]; +void Particles::_validate_property(PropertyInfo &property) const { + if (property.name.begins_with("draw_pass_")) { + int index = property.name.get_slicec('_', 2).to_int() - 1; + if (index >= draw_passes.size()) { + property.usage = 0; + return; + } + } } -void Particles::set_randomness(Variable p_variable,float p_randomness) { +void Particles::_notification(int p_what) { - ERR_FAIL_INDEX(p_variable,VAR_MAX); - var_random[p_variable]=p_randomness; - VisualServer::get_singleton()->particles_set_randomness(particles,(VS::ParticleVariable)p_variable,p_randomness); + if (p_what == NOTIFICATION_PAUSED || p_what == NOTIFICATION_UNPAUSED) { + if (can_process()) { + VS::get_singleton()->particles_set_speed_scale(particles, speed_scale); + } else { + VS::get_singleton()->particles_set_speed_scale(particles, 0); + } + } } -float Particles::get_randomness(Variable p_variable) const { - ERR_FAIL_INDEX_V(p_variable,VAR_MAX,-1); - return var_random[p_variable]; +void Particles::_bind_methods() { -} + ClassDB::bind_method(D_METHOD("set_emitting", "emitting"), &Particles::set_emitting); + ClassDB::bind_method(D_METHOD("set_amount", "amount"), &Particles::set_amount); + ClassDB::bind_method(D_METHOD("set_lifetime", "secs"), &Particles::set_lifetime); + ClassDB::bind_method(D_METHOD("set_one_shot", "enable"), &Particles::set_one_shot); + ClassDB::bind_method(D_METHOD("set_pre_process_time", "secs"), &Particles::set_pre_process_time); + ClassDB::bind_method(D_METHOD("set_explosiveness_ratio", "ratio"), &Particles::set_explosiveness_ratio); + ClassDB::bind_method(D_METHOD("set_randomness_ratio", "ratio"), &Particles::set_randomness_ratio); + ClassDB::bind_method(D_METHOD("set_visibility_aabb", "aabb"), &Particles::set_visibility_aabb); + ClassDB::bind_method(D_METHOD("set_use_local_coordinates", "enable"), &Particles::set_use_local_coordinates); + ClassDB::bind_method(D_METHOD("set_fixed_fps", "fps"), &Particles::set_fixed_fps); + ClassDB::bind_method(D_METHOD("set_fractional_delta", "enable"), &Particles::set_fractional_delta); + ClassDB::bind_method(D_METHOD("set_process_material", "material"), &Particles::set_process_material); + ClassDB::bind_method(D_METHOD("set_speed_scale", "scale"), &Particles::set_speed_scale); + + ClassDB::bind_method(D_METHOD("is_emitting"), &Particles::is_emitting); + ClassDB::bind_method(D_METHOD("get_amount"), &Particles::get_amount); + ClassDB::bind_method(D_METHOD("get_lifetime"), &Particles::get_lifetime); + ClassDB::bind_method(D_METHOD("get_one_shot"), &Particles::get_one_shot); + ClassDB::bind_method(D_METHOD("get_pre_process_time"), &Particles::get_pre_process_time); + ClassDB::bind_method(D_METHOD("get_explosiveness_ratio"), &Particles::get_explosiveness_ratio); + ClassDB::bind_method(D_METHOD("get_randomness_ratio"), &Particles::get_randomness_ratio); + ClassDB::bind_method(D_METHOD("get_visibility_aabb"), &Particles::get_visibility_aabb); + ClassDB::bind_method(D_METHOD("get_use_local_coordinates"), &Particles::get_use_local_coordinates); + ClassDB::bind_method(D_METHOD("get_fixed_fps"), &Particles::get_fixed_fps); + ClassDB::bind_method(D_METHOD("get_fractional_delta"), &Particles::get_fractional_delta); + ClassDB::bind_method(D_METHOD("get_process_material"), &Particles::get_process_material); + ClassDB::bind_method(D_METHOD("get_speed_scale"), &Particles::get_speed_scale); + + ClassDB::bind_method(D_METHOD("set_draw_order", "order"), &Particles::set_draw_order); + + ClassDB::bind_method(D_METHOD("get_draw_order"), &Particles::get_draw_order); + + ClassDB::bind_method(D_METHOD("set_draw_passes", "passes"), &Particles::set_draw_passes); + ClassDB::bind_method(D_METHOD("set_draw_pass_mesh", "pass", "mesh"), &Particles::set_draw_pass_mesh); + + ClassDB::bind_method(D_METHOD("get_draw_passes"), &Particles::get_draw_passes); + ClassDB::bind_method(D_METHOD("get_draw_pass_mesh", "pass"), &Particles::get_draw_pass_mesh); + + ClassDB::bind_method(D_METHOD("restart"), &Particles::restart); + ClassDB::bind_method(D_METHOD("capture_aabb"), &Particles::capture_aabb); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,100000,1"), "set_amount", "get_amount"); + ADD_GROUP("Time", ""); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01"), "set_lifetime", "get_lifetime"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "preprocess", PROPERTY_HINT_RANGE, "0.00,600.0,0.01"), "set_pre_process_time", "get_pre_process_time"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "speed_scale", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_speed_scale", "get_speed_scale"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1"), "set_fixed_fps", "get_fixed_fps"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta"); + ADD_GROUP("Drawing", ""); + ADD_PROPERTY(PropertyInfo(Variant::RECT3, "visibility_aabb"), "set_visibility_aabb", "get_visibility_aabb"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), "set_use_local_coordinates", "get_use_local_coordinates"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_order", PROPERTY_HINT_ENUM, "Index,Lifetime,View Depth"), "set_draw_order", "get_draw_order"); + ADD_GROUP("Process Material", ""); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,ParticlesMaterial"), "set_process_material", "get_process_material"); + ADD_GROUP("Draw Passes", "draw_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_passes", PROPERTY_HINT_RANGE, "0," + itos(MAX_DRAW_PASSES) + ",1"), "set_draw_passes", "get_draw_passes"); + for (int i = 0; i < MAX_DRAW_PASSES; i++) { -void Particles::set_color_phase_pos(int p_phase, float p_pos) { + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "draw_pass_" + itos(i + 1), PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_draw_pass_mesh", "get_draw_pass_mesh", i); + } - ERR_FAIL_INDEX(p_phase,VS::MAX_PARTICLE_COLOR_PHASES); - color_phase[p_phase].pos=p_pos; - VisualServer::get_singleton()->particles_set_color_phase_pos(particles,p_phase,p_pos); + BIND_CONSTANT(DRAW_ORDER_INDEX); + BIND_CONSTANT(DRAW_ORDER_LIFETIME); + BIND_CONSTANT(DRAW_ORDER_VIEW_DEPTH); + BIND_CONSTANT(MAX_DRAW_PASSES); +} +Particles::Particles() { + + particles = VS::get_singleton()->particles_create(); + set_base(particles); + set_emitting(true); + set_one_shot(false); + set_amount(8); + set_lifetime(1); + set_fixed_fps(0); + set_fractional_delta(true); + set_pre_process_time(0); + set_explosiveness_ratio(0); + set_randomness_ratio(0); + set_visibility_aabb(Rect3(Vector3(-4, -4, -4), Vector3(8, 8, 8))); + set_use_local_coordinates(true); + set_draw_passes(1); + set_draw_order(DRAW_ORDER_INDEX); + set_speed_scale(1); } -float Particles::get_color_phase_pos(int p_phase) const { - ERR_FAIL_INDEX_V(p_phase,VS::MAX_PARTICLE_COLOR_PHASES,-1); - return color_phase[p_phase].pos; +Particles::~Particles() { + + VS::get_singleton()->free(particles); } -void Particles::set_color_phase_color(int p_phase, const Color& p_color) { +////////////////////////////////////// + +Mutex *ParticlesMaterial::material_mutex = NULL; +SelfList<ParticlesMaterial>::List ParticlesMaterial::dirty_materials; +Map<ParticlesMaterial::MaterialKey, ParticlesMaterial::ShaderData> ParticlesMaterial::shader_map; +ParticlesMaterial::ShaderNames *ParticlesMaterial::shader_names = NULL; + +void ParticlesMaterial::init_shaders() { + +#ifndef NO_THREADS + material_mutex = Mutex::create(); +#endif + + shader_names = memnew(ShaderNames); + + shader_names->spread = "spread"; + shader_names->flatness = "flatness"; + shader_names->initial_linear_velocity = "initial_linear_velocity"; + shader_names->initial_angle = "initial_angle"; + shader_names->angular_velocity = "angular_velocity"; + shader_names->orbit_velocity = "orbit_velocity"; + shader_names->linear_accel = "linear_accel"; + shader_names->radial_accel = "radial_accel"; + shader_names->tangent_accel = "tangent_accel"; + shader_names->damping = "damping"; + shader_names->scale = "scale"; + shader_names->hue_variation = "hue_variation"; + shader_names->anim_speed = "anim_speed"; + shader_names->anim_offset = "anim_offset"; + + shader_names->initial_linear_velocity_random = "initial_linear_velocity_random"; + shader_names->initial_angle_random = "initial_angle_random"; + shader_names->angular_velocity_random = "angular_velocity_random"; + shader_names->orbit_velocity_random = "orbit_velocity_random"; + shader_names->linear_accel_random = "linear_accel_random"; + shader_names->radial_accel_random = "radial_accel_random"; + shader_names->tangent_accel_random = "tangent_accel_random"; + shader_names->damping_random = "damping_random"; + shader_names->scale_random = "scale_random"; + shader_names->hue_variation_random = "hue_variation_random"; + shader_names->anim_speed_random = "anim_speed_random"; + shader_names->anim_offset_random = "anim_offset_random"; + + shader_names->angle_texture = "angle_texture"; + shader_names->angular_velocity_texture = "angular_velocity_texture"; + shader_names->orbit_velocity_texture = "orbit_velocity_texture"; + shader_names->linear_accel_texture = "linear_accel_texture"; + shader_names->radial_accel_texture = "radial_accel_texture"; + shader_names->tangent_accel_texture = "tangent_accel_texture"; + shader_names->damping_texture = "damping_texture"; + shader_names->scale_texture = "scale_texture"; + shader_names->hue_variation_texture = "hue_variation_texture"; + shader_names->anim_speed_texture = "anim_speed_texture"; + shader_names->anim_offset_texture = "anim_offset_texture"; + + shader_names->color = "color_value"; + shader_names->color_ramp = "color_ramp"; + + shader_names->emission_sphere_radius = "emission_sphere_radius"; + shader_names->emission_box_extents = "emission_box_extents"; + shader_names->emission_texture_point_count = "emission_texture_point_count"; + shader_names->emission_texture_points = "emission_texture_points"; + shader_names->emission_texture_normal = "emission_texture_normal"; + shader_names->emission_texture_color = "emission_texture_color"; - ERR_FAIL_INDEX(p_phase,VS::MAX_PARTICLE_COLOR_PHASES); - color_phase[p_phase].color=p_color; - VisualServer::get_singleton()->particles_set_color_phase_color(particles,p_phase,p_color); + shader_names->trail_divisor = "trail_divisor"; + shader_names->trail_size_modifier = "trail_size_modifier"; + shader_names->trail_color_modifier = "trail_color_modifier"; + shader_names->gravity = "gravity"; } -Color Particles::get_color_phase_color(int p_phase) const { - ERR_FAIL_INDEX_V(p_phase,VS::MAX_PARTICLE_COLOR_PHASES,Color()); - return color_phase[p_phase].color; +void ParticlesMaterial::finish_shaders() { +#ifndef NO_THREADS + memdelete(material_mutex); +#endif + + memdelete(shader_names); } -void Particles::set_material(const Ref<Material>& p_material) { +void ParticlesMaterial::_update_shader() { + + print_line("updating shader"); + + dirty_materials.remove(&element); + + MaterialKey mk = _compute_key(); + if (mk.key == current_key.key) + return; //no update required in the end + + if (shader_map.has(current_key)) { + shader_map[current_key].users--; + if (shader_map[current_key].users == 0) { + //deallocate shader, as it's no longer in use + VS::get_singleton()->free(shader_map[current_key].shader); + shader_map.erase(current_key); + } + } + + current_key = mk; + + if (shader_map.has(mk)) { + + VS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader); + shader_map[mk].users++; + return; + } + + //must create a shader! + + String code = "shader_type particles;\n"; + + code += "uniform float spread;\n"; + code += "uniform float flatness;\n"; + code += "uniform float initial_linear_velocity;\n"; + code += "uniform float initial_angle;\n"; + code += "uniform float angular_velocity;\n"; + code += "uniform float orbit_velocity;\n"; + code += "uniform float linear_accel;\n"; + code += "uniform float radial_accel;\n"; + code += "uniform float tangent_accel;\n"; + code += "uniform float damping;\n"; + code += "uniform float scale;\n"; + code += "uniform float hue_variation;\n"; + code += "uniform float anim_speed;\n"; + code += "uniform float anim_offset;\n"; + + code += "uniform float initial_linear_velocity_random;\n"; + code += "uniform float initial_angle_random;\n"; + code += "uniform float angular_velocity_random;\n"; + code += "uniform float orbit_velocity_random;\n"; + code += "uniform float linear_accel_random;\n"; + code += "uniform float radial_accel_random;\n"; + code += "uniform float tangent_accel_random;\n"; + code += "uniform float damping_random;\n"; + code += "uniform float scale_random;\n"; + code += "uniform float hue_variation_random;\n"; + code += "uniform float anim_speed_random;\n"; + code += "uniform float anim_offset_random;\n"; + + switch (emission_shape) { + case EMISSION_SHAPE_POINT: { + //do none + } break; + case EMISSION_SHAPE_SPHERE: { + code += "uniform float emission_sphere_radius;\n"; + } break; + case EMISSION_SHAPE_BOX: { + code += "uniform vec3 emission_box_extents;\n"; + } break; + case EMISSION_SHAPE_DIRECTED_POINTS: { + code += "uniform sampler2D emission_texture_normal : hint_black;\n"; + } //fallthrough + case EMISSION_SHAPE_POINTS: { + code += "uniform sampler2D emission_texture_points : hint_black;\n"; + code += "uniform int emission_texture_point_count;\n"; + if (emission_color_texture.is_valid()) { + code += "uniform sampler2D emission_texture_color : hint_white;\n"; + } + } break; + } + + code += "uniform vec4 color_value : hint_color;\n"; + + code += "uniform int trail_divisor;\n"; + + code += "uniform vec3 gravity;\n"; + + if (color_ramp.is_valid()) + code += "uniform sampler2D color_ramp;\n"; + + if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) + code += "uniform sampler2D linear_velocity_texture;\n"; + if (tex_parameters[PARAM_ORBIT_VELOCITY].is_valid()) + code += "uniform sampler2D orbit_velocity_texture;\n"; + if (tex_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) + code += "uniform sampler2D angular_velocity_texture;\n"; + if (tex_parameters[PARAM_LINEAR_ACCEL].is_valid()) + code += "uniform sampler2D linear_accel_texture;\n"; + if (tex_parameters[PARAM_RADIAL_ACCEL].is_valid()) + code += "uniform sampler2D radial_accel_texture;\n"; + if (tex_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) + code += "uniform sampler2D tangent_accel_texture;\n"; + if (tex_parameters[PARAM_DAMPING].is_valid()) + code += "uniform sampler2D damping_texture;\n"; + if (tex_parameters[PARAM_ANGLE].is_valid()) + code += "uniform sampler2D angle_texture;\n"; + if (tex_parameters[PARAM_SCALE].is_valid()) + code += "uniform sampler2D scale_texture;\n"; + if (tex_parameters[PARAM_HUE_VARIATION].is_valid()) + code += "uniform sampler2D hue_variation_texture;\n"; + if (tex_parameters[PARAM_ANIM_SPEED].is_valid()) + code += "uniform sampler2D anim_speed_texture;\n"; + if (tex_parameters[PARAM_ANIM_OFFSET].is_valid()) + code += "uniform sampler2D anim_offset_texture;\n"; + + if (trail_size_modifier.is_valid()) { + code += "uniform sampler2D trail_size_modifier;\n"; + } + + if (trail_color_modifier.is_valid()) { + code += "uniform sampler2D trail_color_modifier;\n"; + } + + //need a random function + code += "\n\n"; + code += "float rand_from_seed(inout uint seed) {\n"; + code += " int k;\n"; + code += " int s = int(seed);\n"; + code += " if (s == 0)\n"; + code += " s = 305420679;\n"; + code += " k = s / 127773;\n"; + code += " s = 16807 * (s - k * 127773) - 2836 * k;\n"; + code += " if (s < 0)\n"; + code += " s += 2147483647;\n"; + code += " seed = uint(s);\n"; + code += " return float(seed % uint(65536))/65535.0;\n"; + code += "}\n"; + //improve seed quality + code += "uint hash(uint x) {\n"; + code += " x = ((x >> uint(16)) ^ x) * uint(73244475);\n"; + code += " x = ((x >> uint(16)) ^ x) * uint(73244475);\n"; + code += " x = (x >> uint(16)) ^ x;\n"; + code += " return x;\n"; + code += "}\n"; + code += "void vertex() {\n\n"; + code += "\n"; + + code += " uint base_number=NUMBER/uint(trail_divisor);\n"; + code += " uint alt_seed=hash(base_number+uint(1)+RANDOM_SEED);\n"; + code += " float angle_rand=rand_from_seed(alt_seed);\n"; + code += " float scale_rand=rand_from_seed(alt_seed);\n"; + code += " float hue_rot_rand=rand_from_seed(alt_seed);\n"; + code += " float anim_offset_rand=rand_from_seed(alt_seed);\n"; + code += "\n"; + code += "\n"; + code += "\n"; + code += "\n"; + if (emission_shape >= EMISSION_SHAPE_POINTS) { + code += " int point = min(emission_texture_point_count-1,int(rand_from_seed(alt_seed) * float(emission_texture_point_count)));\n"; + code += " ivec2 emission_tex_size = textureSize( emission_texture_points, 0 );\n"; + code += " ivec2 emission_tex_ofs = ivec2( point % emission_tex_size.x, point / emission_tex_size.x );\n"; + } + code += " if (RESTART) {\n"; + + if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) + code += " float tex_linear_velocity = textureLod(linear_velocity_texture,vec2(0.0,0.0),0.0).r;\n"; + else + code += " float tex_linear_velocity = 0.0;\n"; + + if (tex_parameters[PARAM_ANGLE].is_valid()) + code += " float tex_angle = textureLod(angle_texture,vec2(0.0,0.0),0.0).r;\n"; + else + code += " float tex_angle = 0.0;\n"; + + if (tex_parameters[PARAM_ANIM_OFFSET].is_valid()) + code += " float tex_anim_offset = textureLod(anim_offset_texture,vec2(0.0,0.0),0.0).r;\n"; + else + code += " float tex_anim_offset = 0.0;\n"; + + if (flags[FLAG_DISABLE_Z]) { + + code += " float angle1 = (rand_from_seed(alt_seed)*2.0-1.0)*spread/180.0*3.1416;\n"; + code += " vec3 rot=vec3( cos(angle1), sin(angle1),0.0 );\n"; + code += " VELOCITY=(rot*initial_linear_velocity+rot*initial_linear_velocity_random*rand_from_seed(alt_seed));\n"; - material=p_material; - if(material.is_null()) { - VisualServer::get_singleton()->particles_set_material(particles,RID()); } else { - VisualServer::get_singleton()->particles_set_material(particles,material->get_rid()); + //initiate velocity spread in 3D + code += " float angle1 = rand_from_seed(alt_seed)*spread*3.1416;\n"; + code += " float angle2 = rand_from_seed(alt_seed)*20.0*3.1416; // make it more random like\n"; + code += " vec3 rot_xz=vec3( sin(angle1), 0.0, cos(angle1) );\n"; + code += " vec3 rot = vec3( cos(angle2)*rot_xz.x,sin(angle2)*rot_xz.x, rot_xz.z);\n"; + code += " VELOCITY=(rot*initial_linear_velocity+rot*initial_linear_velocity_random*rand_from_seed(alt_seed));\n"; } -} + code += " float base_angle=(initial_angle+tex_angle)*mix(1.0,angle_rand,initial_angle_random);\n"; + code += " CUSTOM.x=base_angle*3.1416/180.0;\n"; //angle + code += " CUSTOM.y=0.0;\n"; //phase + code += " CUSTOM.z=(anim_offset+tex_anim_offset)*mix(1.0,anim_offset_rand,anim_offset_random);\n"; //animation offset (0-1) + switch (emission_shape) { + case EMISSION_SHAPE_POINT: { + //do none + } break; + case EMISSION_SHAPE_SPHERE: { + code += " TRANSFORM[3].xyz = normalize(vec3(rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0-1.0, rand_from_seed(alt_seed) * 2.0-1.0 ))*emission_sphere_radius;\n"; + } break; + case EMISSION_SHAPE_BOX: { + code += " TRANSFORM[3].xyz = vec3(rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0-1.0, rand_from_seed(alt_seed) * 2.0-1.0)*emission_box_extents;\n"; + } break; + case EMISSION_SHAPE_POINTS: + case EMISSION_SHAPE_DIRECTED_POINTS: { + code += " TRANSFORM[3].xyz = texelFetch(emission_texture_points, emission_tex_ofs,0).xyz;\n"; -void Particles::setup_timer() { + if (emission_shape == EMISSION_SHAPE_DIRECTED_POINTS) { + if (flags[FLAG_DISABLE_Z]) { - if (emitting && emit_timeout > 0) { + code += " mat2 rotm;"; + code += " rotm[0]=texelFetch(emission_texture_normal, emission_tex_ofs,0).xy;\n"; + code += " rotm[1]=rotm[0].yx * vec2(1.0,-1.0);\n"; + code += " VELOCITY.xy = rotm * VELOCITY.xy;\n"; + } else { + code += " vec3 normal = texelFetch(emission_texture_normal, emission_tex_ofs,0).xyz;\n"; + code += " vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0, 1.0, 0.0);\n"; + code += " vec3 tangent = normalize(cross(v0, normal));\n"; + code += " vec3 bitangent = normalize(cross(tangent, normal));\n"; + code += " VELOCITY = mat3(tangent,bitangent,normal) * VELOCITY;\n"; + } + } + } break; + } + code += " VELOCITY = (EMISSION_TRANSFORM * vec4(VELOCITY,0.0)).xyz;\n"; + code += " TRANSFORM = EMISSION_TRANSFORM * TRANSFORM;\n"; + if (flags[FLAG_DISABLE_Z]) { + code += " VELOCITY.z=0.0;\n"; + code += " TRANSFORM[3].z=0.0;\n"; + } - timer->set_wait_time(emit_timeout); - timer->start(); - timer->set_one_shot(true); - }; -}; + code += " } else {\n"; -void Particles::set_emit_timeout(float p_timeout) { + code += " CUSTOM.y+=DELTA/LIFETIME;\n"; + if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) + code += " float tex_linear_velocity = textureLod(linear_velocity_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; + else + code += " float tex_linear_velocity = 0.0;\n"; - emit_timeout = p_timeout; - setup_timer(); -}; + if (tex_parameters[PARAM_ORBIT_VELOCITY].is_valid()) + code += " float tex_orbit_velocity = textureLod(orbit_velocity_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; + else + code += " float tex_orbit_velocity = 0.0;\n"; -float Particles::get_emit_timeout() const { + if (tex_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) + code += " float tex_angular_velocity = textureLod(angular_velocity_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; + else + code += " float tex_angular_velocity = 0.0;\n"; - return emit_timeout; -}; + if (tex_parameters[PARAM_LINEAR_ACCEL].is_valid()) + code += " float tex_linear_accel = textureLod(linear_accel_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; + else + code += " float tex_linear_accel = 0.0;\n"; + if (tex_parameters[PARAM_RADIAL_ACCEL].is_valid()) + code += " float tex_radial_accel = textureLod(radial_accel_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; + else + code += " float tex_radial_accel = 0.0;\n"; -Ref<Material> Particles::get_material() const { + if (tex_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) + code += " float tex_tangent_accel = textureLod(tangent_accel_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; + else + code += " float tex_tangent_accel = 0.0;\n"; - return material; -} + if (tex_parameters[PARAM_DAMPING].is_valid()) + code += " float tex_damping = textureLod(damping_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; + else + code += " float tex_damping = 0.0;\n"; + + if (tex_parameters[PARAM_ANGLE].is_valid()) + code += " float tex_angle = textureLod(angle_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; + else + code += " float tex_angle = 0.0;\n"; + + if (tex_parameters[PARAM_ANIM_SPEED].is_valid()) + code += " float tex_anim_speed = textureLod(anim_speed_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; + else + code += " float tex_anim_speed = 0.0;\n"; + + if (tex_parameters[PARAM_ANIM_OFFSET].is_valid()) + code += " float tex_anim_offset = textureLod(anim_offset_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; + else + code += " float tex_anim_offset = 0.0;\n"; + + code += " vec3 force = gravity; \n"; + code += " vec3 pos = TRANSFORM[3].xyz; \n"; + if (flags[FLAG_DISABLE_Z]) { + code += " pos.z=0.0; \n"; + } + code += " //apply linear acceleration\n"; + code += " force+= length(VELOCITY) > 0.0 ? normalize(VELOCITY) * (linear_accel+tex_linear_accel)*mix(1.0,rand_from_seed(alt_seed),linear_accel_random) : vec3(0.0);\n"; + code += " //apply radial acceleration\n"; + code += " vec3 org = vec3(0.0);\n"; + code += " // if (!p_system->local_coordinates)\n"; + code += " //org=p_transform.origin;\n"; + code += " vec3 diff = pos-org;\n"; + code += " force+=length(diff) > 0.0 ? normalize(diff) * (radial_accel+tex_radial_accel)*mix(1.0,rand_from_seed(alt_seed),radial_accel_random) : vec3(0.0);\n"; + code += " //apply tangential acceleration;\n"; + if (flags[FLAG_DISABLE_Z]) { + code += " force+=length(diff.yx) > 0.0 ? vec3(normalize(diff.yx * vec2(-1.0,1.0)),0.0) * ((tangent_accel+tex_tangent_accel)*mix(1.0,rand_from_seed(alt_seed),radial_accel_random)) : vec3(0.0);\n"; + + } else { + code += " vec3 crossDiff = cross(normalize(diff),normalize(gravity));\n"; + code += " force+=length(crossDiff) > 0.0 ? normalize(crossDiff) * ((tangent_accel+tex_tangent_accel)*mix(1.0,rand_from_seed(alt_seed),radial_accel_random)) : vec3(0.0);\n"; + } + code += " //apply attractor forces\n"; + code += " VELOCITY+=force * DELTA;\n"; + if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { + code += " VELOCITY=normalize(VELOCITY)*tex_linear_velocity;\n"; + } + code += " if (damping+tex_damping>0.0) {\n"; + code += " \n"; + code += " float v = length(VELOCITY);\n"; + code += " float damp = (damping+tex_damping)*mix(1.0,rand_from_seed(alt_seed),damping_random);\n"; + code += " v -= damp * DELTA;\n"; + code += " if (v<0.0) {\n"; + code += " VELOCITY=vec3(0.0);\n"; + code += " } else {\n"; + code += " VELOCITY=normalize(VELOCITY) * v;\n"; + code += " }\n"; + code += " }\n"; + code += " float base_angle=(initial_angle+tex_angle)*mix(1.0,angle_rand,initial_angle_random);\n"; + code += " base_angle+=CUSTOM.y*LIFETIME*(angular_velocity+tex_angular_velocity)*mix(1.0,rand_from_seed(alt_seed)*2.0-1.0,angular_velocity_random);\n"; + code += " CUSTOM.x=base_angle*3.1416/180.0;\n"; //angle + code += " CUSTOM.z=(anim_offset+tex_anim_offset)*mix(1.0,anim_offset_rand,anim_offset_random)+CUSTOM.y*(anim_speed+tex_anim_speed)*mix(1.0,rand_from_seed(alt_seed),anim_speed_random);\n"; //angle + if (flags[FLAG_ANIM_LOOP]) { + code += " CUSTOM.z=mod(CUSTOM.z,1.0);\n"; //loop + + } else { + code += " CUSTOM.z=clamp(CUSTOM.z,0.0,1.0);\n"; //0 to 1 only + } + code += " }\n"; + //apply color + //apply hue rotation + if (tex_parameters[PARAM_SCALE].is_valid()) + code += " float tex_scale = textureLod(scale_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; + else + code += " float tex_scale = 1.0;\n"; + + if (tex_parameters[PARAM_HUE_VARIATION].is_valid()) + code += " float tex_hue_variation = textureLod(hue_variation_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; + else + code += " float tex_hue_variation = 0.0;\n"; -void Particles::set_height_from_velocity(bool p_enable) { + code += " float hue_rot_angle = (hue_variation+tex_hue_variation)*3.1416*2.0*mix(1.0,hue_rot_rand*2.0-1.0,hue_variation_random);\n"; + code += " float hue_rot_c = cos(hue_rot_angle);\n"; + code += " float hue_rot_s = sin(hue_rot_angle);\n"; + code += " mat4 hue_rot_mat = mat4( vec4(0.299, 0.587, 0.114, 0.0),\n"; + code += " vec4(0.299, 0.587, 0.114, 0.0),\n"; + code += " vec4(0.299, 0.587, 0.114, 0.0),\n"; + code += " vec4(0.000, 0.000, 0.000, 1.0)) +\n"; + code += " \n"; + code += " mat4( vec4(0.701, -0.587, -0.114, 0.0),\n"; + code += " vec4(-0.299, 0.413, -0.114, 0.0),\n"; + code += " vec4(-0.300, -0.588, 0.886, 0.0),\n"; + code += " vec4(0.000, 0.000, 0.000, 0.0)) * hue_rot_c +\n"; + code += "\n"; + code += " mat4( vec4(0.168, 0.330, -0.497, 0.0),\n"; + code += " vec4(-0.328, 0.035, 0.292, 0.0),\n"; + code += " vec4(1.250, -1.050, -0.203, 0.0),\n"; + code += " vec4(0.000, 0.000, 0.000, 0.0)) * hue_rot_s;\n"; + if (color_ramp.is_valid()) { + code += " COLOR = textureLod(color_ramp,vec2(CUSTOM.y,0.0),0.0) * hue_rot_mat;\n"; + } else { + code += " COLOR = color_value * hue_rot_mat;\n"; + } + if (emission_color_texture.is_valid() && emission_shape >= EMISSION_SHAPE_POINTS) { + code += " COLOR*= texelFetch(emission_texture_color,emission_tex_ofs,0);\n"; + } + if (trail_color_modifier.is_valid()) { + code += "if (trail_divisor>1) { COLOR*=textureLod(trail_color_modifier,vec2(float(int(NUMBER)%trail_divisor)/float(trail_divisor-1),0.0),0.0); }\n"; + } + code += "\n"; + + if (flags[FLAG_DISABLE_Z]) { + + code += " TRANSFORM[0]=vec4(cos(CUSTOM.x),-sin(CUSTOM.x),0.0,0.0);\n"; + code += " TRANSFORM[1]=vec4(sin(CUSTOM.x),cos(CUSTOM.x),0.0,0.0);\n"; + code += " TRANSFORM[2]=vec4(0.0,0.0,1.0,0.0);\n"; + + } else { + //orient particle Y towards velocity + if (flags[FLAG_ALIGN_Y_TO_VELOCITY]) { + code += " if (length(VELOCITY)>0.0) {TRANSFORM[1].xyz=normalize(VELOCITY);} else {TRANSFORM[1].xyz=normalize(TRANSFORM[1].xyz);}\n"; + code += " if (TRANSFORM[1].xyz==normalize(TRANSFORM[0].xyz)) {\n"; + code += "\tTRANSFORM[0].xyz=normalize(cross(normalize(TRANSFORM[1].xyz),normalize(TRANSFORM[2].xyz)));\n"; + code += "\tTRANSFORM[2].xyz=normalize(cross(normalize(TRANSFORM[0].xyz),normalize(TRANSFORM[1].xyz)));\n"; + code += " } else {\n"; + code += "\tTRANSFORM[2].xyz=normalize(cross(normalize(TRANSFORM[0].xyz),normalize(TRANSFORM[1].xyz)));\n"; + code += "\tTRANSFORM[0].xyz=normalize(cross(normalize(TRANSFORM[1].xyz),normalize(TRANSFORM[2].xyz)));\n"; + code += " }\n"; + } else { + code += "\tTRANSFORM[0].xyz=normalize(TRANSFORM[0].xyz);\n"; + code += "\tTRANSFORM[1].xyz=normalize(TRANSFORM[1].xyz);\n"; + code += "\tTRANSFORM[2].xyz=normalize(TRANSFORM[2].xyz);\n"; + } + //turn particle by rotation in Y + if (flags[FLAG_ROTATE_Y]) { + code += "\tTRANSFORM = TRANSFORM * mat4( vec4(cos(CUSTOM.x),0.0,-sin(CUSTOM.x),0.0), vec4(0.0,1.0,0.0,0.0),vec4(sin(CUSTOM.x),0.0,cos(CUSTOM.x),0.0),vec4(0.0,0.0,0.0,1.0));\n"; + } + } + //scale by scale + code += " float base_scale=mix(scale*tex_scale,1.0,scale_random*scale_rand);\n"; + if (trail_size_modifier.is_valid()) { + code += "if (trail_divisor>1) { base_scale*=textureLod(trail_size_modifier,vec2(float(int(NUMBER)%trail_divisor)/float(trail_divisor-1),0.0),0.0).r; } \n"; + } + + code += " TRANSFORM[0].xyz*=base_scale;\n"; + code += " TRANSFORM[1].xyz*=base_scale;\n"; + code += " TRANSFORM[2].xyz*=base_scale;\n"; + if (flags[FLAG_DISABLE_Z]) { + code += " VELOCITY.z=0.0;\n"; + code += " TRANSFORM[3].z=0.0;\n"; + } + code += "}\n"; + code += "\n"; - height_from_velocity=p_enable; - VisualServer::get_singleton()->particles_set_height_from_velocity(particles,height_from_velocity); + ShaderData shader_data; + shader_data.shader = VS::get_singleton()->shader_create(); + shader_data.users = 1; + + VS::get_singleton()->shader_set_code(shader_data.shader, code); + + shader_map[mk] = shader_data; + + VS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); } -bool Particles::has_height_from_velocity() const { +void ParticlesMaterial::flush_changes() { + + if (material_mutex) + material_mutex->lock(); - return height_from_velocity; + while (dirty_materials.first()) { + + dirty_materials.first()->self()->_update_shader(); + } + + if (material_mutex) + material_mutex->unlock(); } -void Particles::set_color_phases(int p_phases) { +void ParticlesMaterial::_queue_shader_change() { - color_phase_count=p_phases; - VisualServer::get_singleton()->particles_set_color_phases(particles,p_phases); + if (material_mutex) + material_mutex->lock(); + + print_line("queuing change"); + if (!element.in_list()) { + print_line("not in list, adding"); + dirty_materials.add(&element); + } + + if (material_mutex) + material_mutex->unlock(); } -int Particles::get_color_phases() const{ +bool ParticlesMaterial::_is_shader_dirty() const { + + bool dirty = false; + + if (material_mutex) + material_mutex->lock(); + + dirty = element.in_list(); - return color_phase_count; + if (material_mutex) + material_mutex->unlock(); + + return dirty; } -bool Particles::_can_gizmo_scale() const { +void ParticlesMaterial::set_spread(float p_spread) { - return false; + spread = p_spread; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->spread, p_spread); } -void Particles::set_use_local_coordinates(bool p_use) { +float ParticlesMaterial::get_spread() const { - local_coordinates=p_use; - VisualServer::get_singleton()->particles_set_use_local_coordinates(particles,local_coordinates); + return spread; } -bool Particles::is_using_local_coordinates() const{ +void ParticlesMaterial::set_flatness(float p_flatness) { - return local_coordinates; + flatness = p_flatness; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->flatness, p_flatness); } +float ParticlesMaterial::get_flatness() const { + return flatness; +} -RES Particles::_get_gizmo_geometry() const { +void ParticlesMaterial::set_param(Parameter p_param, float p_value) { - Ref<SurfaceTool> surface_tool( memnew( SurfaceTool )); + ERR_FAIL_INDEX(p_param, PARAM_MAX); - Ref<FixedSpatialMaterial> mat( memnew( FixedSpatialMaterial )); + parameters[p_param] = p_value; - mat->set_parameter( FixedSpatialMaterial::PARAM_DIFFUSE,Color(0.0,0.6,0.7,0.2) ); - mat->set_parameter( FixedSpatialMaterial::PARAM_EMISSION,Color(0.5,0.7,0.8) ); - mat->set_blend_mode( Material::BLEND_MODE_ADD ); - mat->set_flag(Material::FLAG_DOUBLE_SIDED,true); - //mat->set_hint(Material::HINT_NO_DEPTH_DRAW,true); + switch (p_param) { + case PARAM_INITIAL_LINEAR_VELOCITY: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_linear_velocity, p_value); + } break; + case PARAM_ANGULAR_VELOCITY: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity, p_value); + } break; + case PARAM_ORBIT_VELOCITY: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity, p_value); + } break; + case PARAM_LINEAR_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel, p_value); + } break; + case PARAM_RADIAL_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel, p_value); + } break; + case PARAM_TANGENTIAL_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel, p_value); + } break; + case PARAM_DAMPING: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->damping, p_value); + } break; + case PARAM_ANGLE: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_angle, p_value); + } break; + case PARAM_SCALE: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->scale, p_value); + } break; + case PARAM_HUE_VARIATION: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation, p_value); + } break; + case PARAM_ANIM_SPEED: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed, p_value); + } break; + case PARAM_ANIM_OFFSET: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset, p_value); + } break; + case PARAM_MAX: { + }; + } +} +float ParticlesMaterial::get_param(Parameter p_param) const { + ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); - surface_tool->begin(Mesh::PRIMITIVE_TRIANGLES); - surface_tool->set_material(mat); + return parameters[p_param]; +} - int sides=16; - int sections=24; +void ParticlesMaterial::set_param_randomness(Parameter p_param, float p_value) { + + ERR_FAIL_INDEX(p_param, PARAM_MAX); + + randomness[p_param] = p_value; + + switch (p_param) { + case PARAM_INITIAL_LINEAR_VELOCITY: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_linear_velocity_random, p_value); + } break; + case PARAM_ANGULAR_VELOCITY: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity_random, p_value); + } break; + case PARAM_ORBIT_VELOCITY: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity_random, p_value); + } break; + case PARAM_LINEAR_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel_random, p_value); + } break; + case PARAM_RADIAL_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel_random, p_value); + } break; + case PARAM_TANGENTIAL_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel_random, p_value); + } break; + case PARAM_DAMPING: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->damping_random, p_value); + } break; + case PARAM_ANGLE: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_angle_random, p_value); + } break; + case PARAM_SCALE: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->scale_random, p_value); + } break; + case PARAM_HUE_VARIATION: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation_random, p_value); + } break; + case PARAM_ANIM_SPEED: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed_random, p_value); + } break; + case PARAM_ANIM_OFFSET: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_random, p_value); + } break; + case PARAM_MAX: { + }; + } +} +float ParticlesMaterial::get_param_randomness(Parameter p_param) const { - //float len=1; - float deg=Math::deg2rad(var[VAR_SPREAD]*180); - if (deg==180) - deg=179.5; + ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); - Vector3 to=Vector3(0,0,-1); + return randomness[p_param]; +} - for(int j=0;j<sections;j++) { +static void _adjust_curve_range(const Ref<Texture> &p_texture, float p_min, float p_max) { - Vector3 p1=Matrix3(Vector3(1,0,0),deg*j/sections).xform(to); - Vector3 p2=Matrix3(Vector3(1,0,0),deg*(j+1)/sections).xform(to); + Ref<CurveTexture> curve_tex = p_texture; + if (!curve_tex.is_valid()) + return; - for(int i=0;i<sides;i++) { + curve_tex->ensure_default_setup(p_min, p_max); +} - Vector3 p1r = Matrix3(Vector3(0,0,1),Math_PI*2*float(i)/sides).xform(p1); - Vector3 p1s = Matrix3(Vector3(0,0,1),Math_PI*2*float(i+1)/sides).xform(p1); - Vector3 p2s = Matrix3(Vector3(0,0,1),Math_PI*2*float(i+1)/sides).xform(p2); - Vector3 p2r = Matrix3(Vector3(0,0,1),Math_PI*2*float(i)/sides).xform(p2); +void ParticlesMaterial::set_param_texture(Parameter p_param, const Ref<Texture> &p_texture) { - surface_tool->add_normal(p1r.normalized()); - surface_tool->add_vertex(p1r); - surface_tool->add_normal(p1s.normalized()); - surface_tool->add_vertex(p1s); - surface_tool->add_normal(p2s.normalized()); - surface_tool->add_vertex(p2s); + ERR_FAIL_INDEX(p_param, PARAM_MAX); - surface_tool->add_normal(p1r.normalized()); - surface_tool->add_vertex(p1r); - surface_tool->add_normal(p2s.normalized()); - surface_tool->add_vertex(p2s); - surface_tool->add_normal(p2r.normalized()); - surface_tool->add_vertex(p2r); + tex_parameters[p_param] = p_texture; - if (j==sections-1) { + switch (p_param) { + case PARAM_INITIAL_LINEAR_VELOCITY: { + //do none for this one + } break; + case PARAM_ANGULAR_VELOCITY: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity_texture, p_texture); + _adjust_curve_range(p_texture, -360, 360); + } break; + case PARAM_ORBIT_VELOCITY: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity_texture, p_texture); + _adjust_curve_range(p_texture, -500, 500); + } break; + case PARAM_LINEAR_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel_texture, p_texture); + _adjust_curve_range(p_texture, -200, 200); + } break; + case PARAM_RADIAL_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel_texture, p_texture); + _adjust_curve_range(p_texture, -200, 200); + } break; + case PARAM_TANGENTIAL_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel_texture, p_texture); + _adjust_curve_range(p_texture, -200, 200); + } break; + case PARAM_DAMPING: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->damping_texture, p_texture); + _adjust_curve_range(p_texture, 0, 100); + } break; + case PARAM_ANGLE: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->angle_texture, p_texture); + _adjust_curve_range(p_texture, -360, 360); + } break; + case PARAM_SCALE: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->scale_texture, p_texture); - surface_tool->add_normal(p2r.normalized()); - surface_tool->add_vertex(p2r); - surface_tool->add_normal(p2s.normalized()); - surface_tool->add_vertex(p2s); - surface_tool->add_normal(Vector3(0,0,1)); - surface_tool->add_vertex(Vector3()); + Ref<CurveTexture> curve_tex = p_texture; + if (curve_tex.is_valid()) { + curve_tex->ensure_default_setup(); } - } + + } break; + case PARAM_HUE_VARIATION: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation_texture, p_texture); + _adjust_curve_range(p_texture, -1, 1); + } break; + case PARAM_ANIM_SPEED: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed_texture, p_texture); + _adjust_curve_range(p_texture, 0, 200); + } break; + case PARAM_ANIM_OFFSET: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_texture, p_texture); + } break; + case PARAM_MAX: { + }; } + _queue_shader_change(); +} +Ref<Texture> ParticlesMaterial::get_param_texture(Parameter p_param) const { - Ref<Mesh> mesh = surface_tool->commit(); + ERR_FAIL_INDEX_V(p_param, PARAM_MAX, Ref<Texture>()); - Ref<FixedSpatialMaterial> mat_aabb( memnew( FixedSpatialMaterial )); + return tex_parameters[p_param]; +} - mat_aabb->set_parameter( FixedSpatialMaterial::PARAM_DIFFUSE,Color(0.8,0.8,0.9,0.7) ); - mat_aabb->set_line_width(3); - mat_aabb->set_flag( Material::FLAG_UNSHADED, true ); +void ParticlesMaterial::set_color(const Color &p_color) { - surface_tool->begin(Mesh::PRIMITIVE_LINES); - surface_tool->set_material(mat_aabb); + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->color, p_color); + color = p_color; +} - for(int i=0;i<12;i++) { +Color ParticlesMaterial::get_color() const { - Vector3 f,t; - visibility_aabb.get_edge(i,f,t); - surface_tool->add_vertex(f); - surface_tool->add_vertex(t); - } + return color; +} - return surface_tool->commit(mesh); +void ParticlesMaterial::set_color_ramp(const Ref<Texture> &p_texture) { + color_ramp = p_texture; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->color_ramp, p_texture); + _queue_shader_change(); + _change_notify(); } +Ref<Texture> ParticlesMaterial::get_color_ramp() const { -void Particles::_bind_methods() { + return color_ramp; +} + +void ParticlesMaterial::set_flag(Flags p_flag, bool p_enable) { + ERR_FAIL_INDEX(p_flag, FLAG_MAX); + flags[p_flag] = p_enable; + _queue_shader_change(); +} + +bool ParticlesMaterial::get_flag(Flags p_flag) const { + ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); + return flags[p_flag]; +} + +void ParticlesMaterial::set_emission_shape(EmissionShape p_shape) { + + emission_shape = p_shape; + _change_notify(); + _queue_shader_change(); +} + +void ParticlesMaterial::set_emission_sphere_radius(float p_radius) { + + emission_sphere_radius = p_radius; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_sphere_radius, p_radius); +} + +void ParticlesMaterial::set_emission_box_extents(Vector3 p_extents) { + + emission_box_extents = p_extents; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_box_extents, p_extents); +} + +void ParticlesMaterial::set_emission_point_texture(const Ref<Texture> &p_points) { + + emission_point_texture = p_points; + RID texture; + if (p_points.is_valid()) + texture = p_points->get_rid(); + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_points, texture); +} + +void ParticlesMaterial::set_emission_normal_texture(const Ref<Texture> &p_normals) { + + emission_normal_texture = p_normals; + RID texture; + if (p_normals.is_valid()) + texture = p_normals->get_rid(); + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_normal, texture); +} + +void ParticlesMaterial::set_emission_color_texture(const Ref<Texture> &p_colors) { + + emission_color_texture = p_colors; + RID texture; + if (p_colors.is_valid()) + texture = p_colors->get_rid(); + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_color, texture); + _queue_shader_change(); +} + +void ParticlesMaterial::set_emission_point_count(int p_count) { + + emission_point_count = p_count; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_point_count, p_count); +} + +ParticlesMaterial::EmissionShape ParticlesMaterial::get_emission_shape() const { + + return emission_shape; +} + +float ParticlesMaterial::get_emission_sphere_radius() const { + + return emission_sphere_radius; +} +Vector3 ParticlesMaterial::get_emission_box_extents() const { + + return emission_box_extents; +} +Ref<Texture> ParticlesMaterial::get_emission_point_texture() const { - ClassDB::bind_method(D_METHOD("set_amount","amount"),&Particles::set_amount); - ClassDB::bind_method(D_METHOD("get_amount"),&Particles::get_amount); - ClassDB::bind_method(D_METHOD("set_emitting","enabled"),&Particles::set_emitting); - ClassDB::bind_method(D_METHOD("is_emitting"),&Particles::is_emitting); - ClassDB::bind_method(D_METHOD("set_visibility_aabb","aabb"),&Particles::set_visibility_aabb); - ClassDB::bind_method(D_METHOD("get_visibility_aabb"),&Particles::get_visibility_aabb); - ClassDB::bind_method(D_METHOD("set_emission_half_extents","half_extents"),&Particles::set_emission_half_extents); - ClassDB::bind_method(D_METHOD("get_emission_half_extents"),&Particles::get_emission_half_extents); - ClassDB::bind_method(D_METHOD("set_emission_base_velocity","base_velocity"),&Particles::set_emission_base_velocity); - ClassDB::bind_method(D_METHOD("get_emission_base_velocity"),&Particles::get_emission_base_velocity); - ClassDB::bind_method(D_METHOD("set_emission_points","points"),&Particles::set_emission_points); - ClassDB::bind_method(D_METHOD("get_emission_points"),&Particles::get_emission_points); - ClassDB::bind_method(D_METHOD("set_gravity_normal","normal"),&Particles::set_gravity_normal); - ClassDB::bind_method(D_METHOD("get_gravity_normal"),&Particles::get_gravity_normal); - ClassDB::bind_method(D_METHOD("set_variable","variable","value"),&Particles::set_variable); - ClassDB::bind_method(D_METHOD("get_variable","variable"),&Particles::get_variable); - ClassDB::bind_method(D_METHOD("set_randomness","variable","randomness"),&Particles::set_randomness); - ClassDB::bind_method(D_METHOD("get_randomness","variable"),&Particles::get_randomness); - ClassDB::bind_method(D_METHOD("set_color_phase_pos","phase","pos"),&Particles::set_color_phase_pos); - ClassDB::bind_method(D_METHOD("get_color_phase_pos","phase"),&Particles::get_color_phase_pos); - ClassDB::bind_method(D_METHOD("set_color_phase_color","phase","color"),&Particles::set_color_phase_color); - ClassDB::bind_method(D_METHOD("get_color_phase_color","phase"),&Particles::get_color_phase_color); - ClassDB::bind_method(D_METHOD("set_material","material:Material"),&Particles::set_material); - ClassDB::bind_method(D_METHOD("get_material:Material"),&Particles::get_material); - ClassDB::bind_method(D_METHOD("set_emit_timeout","timeout"),&Particles::set_emit_timeout); - ClassDB::bind_method(D_METHOD("get_emit_timeout"),&Particles::get_emit_timeout); - ClassDB::bind_method(D_METHOD("set_height_from_velocity","enable"),&Particles::set_height_from_velocity); - ClassDB::bind_method(D_METHOD("has_height_from_velocity"),&Particles::has_height_from_velocity); - ClassDB::bind_method(D_METHOD("set_use_local_coordinates","enable"),&Particles::set_use_local_coordinates); - ClassDB::bind_method(D_METHOD("is_using_local_coordinates"),&Particles::is_using_local_coordinates); + return emission_point_texture; +} +Ref<Texture> ParticlesMaterial::get_emission_normal_texture() const { - ClassDB::bind_method(D_METHOD("set_color_phases","count"),&Particles::set_color_phases); - ClassDB::bind_method(D_METHOD("get_color_phases"),&Particles::get_color_phases); + return emission_normal_texture; +} - ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "Material" ), "set_material", "get_material") ; +Ref<Texture> ParticlesMaterial::get_emission_color_texture() const { - ADD_PROPERTY( PropertyInfo( Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1024,1" ), "set_amount", "get_amount") ; - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "emitting" ), "set_emitting", "is_emitting") ; - ADD_PROPERTY( PropertyInfo( Variant::_AABB, "visibility" ), "set_visibility_aabb", "get_visibility_aabb") ; - ADD_PROPERTY( PropertyInfo( Variant::VECTOR3, "emission_extents" ), "set_emission_half_extents", "get_emission_half_extents") ; - ADD_PROPERTY( PropertyInfo( Variant::VECTOR3, "emission_base_velocity" ), "set_emission_base_velocity", "get_emission_base_velocity") ; - ADD_PROPERTY( PropertyInfo( Variant::VECTOR3_ARRAY, "emission_points" ), "set_emission_points", "get_emission_points") ; - ADD_PROPERTY( PropertyInfo( Variant::VECTOR3, "gravity_normal" ), "set_gravity_normal", "get_gravity_normal") ; - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "local_coords" ), "set_use_local_coordinates", "is_using_local_coordinates") ; - ADD_PROPERTY( PropertyInfo( Variant::REAL, "emit_timeout",PROPERTY_HINT_RANGE,"0,256,0.01"), "set_emit_timeout", "get_emit_timeout") ; + return emission_color_texture; +} +int ParticlesMaterial::get_emission_point_count() const { + + return emission_point_count; +} - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/lifetime", PROPERTY_HINT_RANGE,"0.1,60,0.01"), "set_variable", "get_variable", VAR_LIFETIME ); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/spread", PROPERTY_HINT_RANGE,"0,1,0.01"), "set_variable", "get_variable", VAR_SPREAD ); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/gravity", PROPERTY_HINT_RANGE,"-48,48,0.01"), "set_variable", "get_variable", VAR_GRAVITY ); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/linear_vel", PROPERTY_HINT_RANGE,"-100,100,0.01"), "set_variable", "get_variable", VAR_LINEAR_VELOCITY ); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/angular_vel", PROPERTY_HINT_RANGE,"-100,100,0.01"), "set_variable", "get_variable", VAR_ANGULAR_VELOCITY ); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/linear_accel", PROPERTY_HINT_RANGE,"-100,100,0.01"), "set_variable", "get_variable", VAR_LINEAR_ACCELERATION ); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/radial_accel", PROPERTY_HINT_RANGE,"-100,100,0.01"), "set_variable", "get_variable", VAR_DRAG ); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/tan_accel", PROPERTY_HINT_RANGE,"-100,100,0.01"), "set_variable", "get_variable", VAR_TANGENTIAL_ACCELERATION ); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/damping", PROPERTY_HINT_RANGE,"0,128,0.01"), "set_variable", "get_variable", VAR_DAMPING ); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/initial_size", PROPERTY_HINT_RANGE,"0,100,0.01"), "set_variable", "get_variable", VAR_INITIAL_SIZE ); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/final_size", PROPERTY_HINT_RANGE,"0,100,0.01"), "set_variable", "get_variable", VAR_FINAL_SIZE ); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/initial_angle",PROPERTY_HINT_RANGE,"0,1,0.01"), "set_variable", "get_variable", VAR_INITIAL_ANGLE ); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "vars/height_from_velocity"), "set_height_from_velocity", "has_height_from_velocity") ; - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/height",PROPERTY_HINT_RANGE,"0,4096,0.01"), "set_variable", "get_variable", VAR_HEIGHT); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/height_speed_scale",PROPERTY_HINT_RANGE,"0,4096,0.01"), "set_variable", "get_variable", VAR_HEIGHT_SPEED_SCALE ); +void ParticlesMaterial::set_trail_divisor(int p_divisor) { - for(int i=0;i<VAR_MAX;i++) - ADD_PROPERTYI( PropertyInfo( Variant::REAL, _rand_names[i], PROPERTY_HINT_RANGE,"-16.0,16.0,0.01"),"set_randomness", "get_randomness",_var_indices[i] ); + trail_divisor = p_divisor; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_divisor, p_divisor); +} + +int ParticlesMaterial::get_trail_divisor() const { + + return trail_divisor; +} +void ParticlesMaterial::set_trail_size_modifier(const Ref<CurveTexture> &p_trail_size_modifier) { - ADD_PROPERTY( PropertyInfo( Variant::INT, "color_phases/count",PROPERTY_HINT_RANGE,"0,4,1"), "set_color_phases", "get_color_phases"); + trail_size_modifier = p_trail_size_modifier; - for(int i=0;i<VS::MAX_PARTICLE_COLOR_PHASES;i++) { - String phase="phase_"+itos(i)+"/"; - ADD_PROPERTYI( PropertyInfo( Variant::REAL, phase+"pos", PROPERTY_HINT_RANGE,"0,1,0.01"),"set_color_phase_pos","get_color_phase_pos",i ); - ADD_PROPERTYI( PropertyInfo( Variant::COLOR, phase+"color"),"set_color_phase_color","get_color_phase_color",i ); + Ref<CurveTexture> curve = trail_size_modifier; + if (curve.is_valid()) { + curve->ensure_default_setup(); } - BIND_CONSTANT( VAR_LIFETIME ); - BIND_CONSTANT( VAR_SPREAD ); - BIND_CONSTANT( VAR_GRAVITY ); - BIND_CONSTANT( VAR_LINEAR_VELOCITY ); - BIND_CONSTANT( VAR_ANGULAR_VELOCITY ); - BIND_CONSTANT( VAR_LINEAR_ACCELERATION ); - BIND_CONSTANT( VAR_DRAG ); - BIND_CONSTANT( VAR_TANGENTIAL_ACCELERATION ); - BIND_CONSTANT( VAR_INITIAL_SIZE ); - BIND_CONSTANT( VAR_FINAL_SIZE ); - BIND_CONSTANT( VAR_INITIAL_ANGLE ); - BIND_CONSTANT( VAR_HEIGHT ); - BIND_CONSTANT( VAR_HEIGHT_SPEED_SCALE ); - BIND_CONSTANT( VAR_MAX ); + RID texture; + if (p_trail_size_modifier.is_valid()) + texture = p_trail_size_modifier->get_rid(); + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_size_modifier, texture); + _queue_shader_change(); +} + +Ref<CurveTexture> ParticlesMaterial::get_trail_size_modifier() const { + return trail_size_modifier; } -Particles::Particles() { +void ParticlesMaterial::set_trail_color_modifier(const Ref<GradientTexture> &p_trail_color_modifier) { - particles = VisualServer::get_singleton()->particles_create(); - timer = memnew(Timer); - add_child(timer); - emit_timeout = 0; + trail_color_modifier = p_trail_color_modifier; + RID texture; + if (p_trail_color_modifier.is_valid()) + texture = p_trail_color_modifier->get_rid(); + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_color_modifier, texture); + _queue_shader_change(); +} - set_amount(64); - set_emitting(true); - set_visibility_aabb(AABB( Vector3(-4,-4,-4), Vector3(8,8,8) ) ); +Ref<GradientTexture> ParticlesMaterial::get_trail_color_modifier() const { - for (int i=0;i<VAR_MAX;i++) { - set_randomness((Variable)i,0.0); + return trail_color_modifier; +} + +void ParticlesMaterial::set_gravity(const Vector3 &p_gravity) { + + gravity = p_gravity; + Vector3 gset = gravity; + if (gset == Vector3()) { + gset = Vector3(0, -0.000001, 0); //as gravity is used as upvector in some calculations } + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->gravity, gset); +} - set_variable( VAR_LIFETIME, 5.0); - set_variable( VAR_SPREAD, 0.2); - set_variable( VAR_GRAVITY, 9.8); - set_variable( VAR_LINEAR_VELOCITY, 0.2); - set_variable( VAR_ANGULAR_VELOCITY, 0.0); - set_variable( VAR_LINEAR_ACCELERATION, 0.0); - set_variable( VAR_DRAG, 0.0); - set_variable( VAR_TANGENTIAL_ACCELERATION, 0.0); - set_variable( VAR_DAMPING, 0.0); - set_variable( VAR_INITIAL_SIZE, 1.0); - set_variable( VAR_FINAL_SIZE, 1.0); - set_variable( VAR_INITIAL_ANGLE, 0.0); - set_variable( VAR_HEIGHT, 1.0); - set_variable( VAR_HEIGHT_SPEED_SCALE, 0.0); +Vector3 ParticlesMaterial::get_gravity() const { - color_phase_count=0; + return gravity; +} - set_color_phase_pos(0,0.0); - set_color_phase_pos(1,1.0); - set_color_phase_pos(2,1.0); - set_color_phase_pos(3,1.0); +void ParticlesMaterial::_validate_property(PropertyInfo &property) const { - set_color_phase_color(0,Color(1,1,1)); - set_color_phase_color(1,Color(0,0,0)); - set_color_phase_color(2,Color(0,0,0)); - set_color_phase_color(3,Color(0,0,0)); + if (property.name == "color" && color_ramp.is_valid()) { + property.usage = 0; + } - set_gravity_normal(Vector3(0,-1.0,0)); - set_emission_half_extents(Vector3(0.1,0.1,0.1)); + if (property.name == "emission_sphere_radius" && emission_shape != EMISSION_SHAPE_SPHERE) { + property.usage = 0; + } - height_from_velocity=false; + if (property.name == "emission_box_extents" && emission_shape != EMISSION_SHAPE_BOX) { + property.usage = 0; + } - Vector<Variant> pars; - pars.push_back(false); - timer->connect("timeout", this, "set_emitting", pars); - set_base(particles); - local_coordinates=false; + if ((property.name == "emission_point_texture" || property.name == "emission_color_texture") && (emission_shape < EMISSION_SHAPE_POINTS)) { + property.usage = 0; + } + + if (property.name == "emission_normal_texture" && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS) { + property.usage = 0; + } + + if (property.name == "emission_point_count" && (emission_shape != EMISSION_SHAPE_POINTS && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS)) { + property.usage = 0; + } } +void ParticlesMaterial::_bind_methods() { -Particles::~Particles() { + ClassDB::bind_method(D_METHOD("set_spread", "degrees"), &ParticlesMaterial::set_spread); + ClassDB::bind_method(D_METHOD("get_spread"), &ParticlesMaterial::get_spread); + + ClassDB::bind_method(D_METHOD("set_flatness", "amount"), &ParticlesMaterial::set_flatness); + ClassDB::bind_method(D_METHOD("get_flatness"), &ParticlesMaterial::get_flatness); + + ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &ParticlesMaterial::set_param); + ClassDB::bind_method(D_METHOD("get_param", "param"), &ParticlesMaterial::get_param); + + ClassDB::bind_method(D_METHOD("set_param_randomness", "param", "randomness"), &ParticlesMaterial::set_param_randomness); + ClassDB::bind_method(D_METHOD("get_param_randomness", "param"), &ParticlesMaterial::get_param_randomness); + + ClassDB::bind_method(D_METHOD("set_param_texture", "param", "texture"), &ParticlesMaterial::set_param_texture); + ClassDB::bind_method(D_METHOD("get_param_texture", "param"), &ParticlesMaterial::get_param_texture); + + ClassDB::bind_method(D_METHOD("set_color", "color"), &ParticlesMaterial::set_color); + ClassDB::bind_method(D_METHOD("get_color"), &ParticlesMaterial::get_color); + + ClassDB::bind_method(D_METHOD("set_color_ramp", "ramp"), &ParticlesMaterial::set_color_ramp); + ClassDB::bind_method(D_METHOD("get_color_ramp"), &ParticlesMaterial::get_color_ramp); + + ClassDB::bind_method(D_METHOD("set_flag", "flag", "enable"), &ParticlesMaterial::set_flag); + ClassDB::bind_method(D_METHOD("get_flag", "flag"), &ParticlesMaterial::get_flag); + + ClassDB::bind_method(D_METHOD("set_emission_shape", "shape"), &ParticlesMaterial::set_emission_shape); + ClassDB::bind_method(D_METHOD("get_emission_shape"), &ParticlesMaterial::get_emission_shape); + + ClassDB::bind_method(D_METHOD("set_emission_sphere_radius", "radius"), &ParticlesMaterial::set_emission_sphere_radius); + ClassDB::bind_method(D_METHOD("get_emission_sphere_radius"), &ParticlesMaterial::get_emission_sphere_radius); + + ClassDB::bind_method(D_METHOD("set_emission_box_extents", "extents"), &ParticlesMaterial::set_emission_box_extents); + ClassDB::bind_method(D_METHOD("get_emission_box_extents"), &ParticlesMaterial::get_emission_box_extents); + + ClassDB::bind_method(D_METHOD("set_emission_point_texture", "texture"), &ParticlesMaterial::set_emission_point_texture); + ClassDB::bind_method(D_METHOD("get_emission_point_texture"), &ParticlesMaterial::get_emission_point_texture); + + ClassDB::bind_method(D_METHOD("set_emission_normal_texture", "texture"), &ParticlesMaterial::set_emission_normal_texture); + ClassDB::bind_method(D_METHOD("get_emission_normal_texture"), &ParticlesMaterial::get_emission_normal_texture); + + ClassDB::bind_method(D_METHOD("set_emission_color_texture", "texture"), &ParticlesMaterial::set_emission_color_texture); + ClassDB::bind_method(D_METHOD("get_emission_color_texture"), &ParticlesMaterial::get_emission_color_texture); + + ClassDB::bind_method(D_METHOD("set_emission_point_count", "point_count"), &ParticlesMaterial::set_emission_point_count); + ClassDB::bind_method(D_METHOD("get_emission_point_count"), &ParticlesMaterial::get_emission_point_count); + + ClassDB::bind_method(D_METHOD("set_trail_divisor", "divisor"), &ParticlesMaterial::set_trail_divisor); + ClassDB::bind_method(D_METHOD("get_trail_divisor"), &ParticlesMaterial::get_trail_divisor); + + ClassDB::bind_method(D_METHOD("set_trail_size_modifier", "texture"), &ParticlesMaterial::set_trail_size_modifier); + ClassDB::bind_method(D_METHOD("get_trail_size_modifier"), &ParticlesMaterial::get_trail_size_modifier); - VisualServer::get_singleton()->free(particles); + ClassDB::bind_method(D_METHOD("set_trail_color_modifier", "texture"), &ParticlesMaterial::set_trail_color_modifier); + ClassDB::bind_method(D_METHOD("get_trail_color_modifier"), &ParticlesMaterial::get_trail_color_modifier); + + ClassDB::bind_method(D_METHOD("get_gravity"), &ParticlesMaterial::get_gravity); + ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &ParticlesMaterial::set_gravity); + + ADD_GROUP("Trail", "trail_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "trail_divisor", PROPERTY_HINT_RANGE, "1,1000000,1"), "set_trail_divisor", "get_trail_divisor"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "trail_size_modifier", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_trail_size_modifier", "get_trail_size_modifier"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "trail_color_modifier", PROPERTY_HINT_RESOURCE_TYPE, "GradientTexture"), "set_trail_color_modifier", "get_trail_color_modifier"); + ADD_GROUP("Emission Shape", "emission_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points"), "set_emission_shape", "get_emission_shape"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01"), "set_emission_sphere_radius", "get_emission_sphere_radius"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "emission_box_extents"), "set_emission_box_extents", "get_emission_box_extents"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "emission_point_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_emission_point_texture", "get_emission_point_texture"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "emission_normal_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_emission_normal_texture", "get_emission_normal_texture"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "emission_color_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_emission_color_texture", "get_emission_color_texture"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_point_count", PROPERTY_HINT_RANGE, "0,1000000,1"), "set_emission_point_count", "get_emission_point_count"); + ADD_GROUP("Flags", "flag_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_align_y"), "set_flag", "get_flag", FLAG_ALIGN_Y_TO_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_rotate_y"), "set_flag", "get_flag", FLAG_ROTATE_Y); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_disable_z"), "set_flag", "get_flag", FLAG_DISABLE_Z); + ADD_GROUP("Spread", ""); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "spread", PROPERTY_HINT_RANGE, "0,180,0.01"), "set_spread", "get_spread"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "flatness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_flatness", "get_flatness"); + ADD_GROUP("Gravity", ""); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity"), "set_gravity", "get_gravity"); + ADD_GROUP("Initial Velocity", "initial_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "initial_velocity", PROPERTY_HINT_RANGE, "0,1000,0.01"), "set_param", "get_param", PARAM_INITIAL_LINEAR_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "initial_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_INITIAL_LINEAR_VELOCITY); + ADD_GROUP("Angular Velocity", "angular_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_velocity", PROPERTY_HINT_RANGE, "-360,360,0.01"), "set_param", "get_param", PARAM_ANGULAR_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGULAR_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "angular_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANGULAR_VELOCITY); + ADD_GROUP("Orbit Velocity", "orbit_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "orbit_velocity", PROPERTY_HINT_RANGE, "-1000,1000,0.01"), "set_param", "get_param", PARAM_ORBIT_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "orbit_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ORBIT_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "orbit_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ORBIT_VELOCITY); + ADD_GROUP("Linear Accel", "linear_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_accel", PROPERTY_HINT_RANGE, "-100,100,0.01"), "set_param", "get_param", PARAM_LINEAR_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_LINEAR_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "linear_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_LINEAR_ACCEL); + ADD_GROUP("Radial Accel", "radial_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "radial_accel", PROPERTY_HINT_RANGE, "-100,100,0.01"), "set_param", "get_param", PARAM_RADIAL_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "radial_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_RADIAL_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "radial_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_RADIAL_ACCEL); + ADD_GROUP("Tangential Accel", "tangential_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "tangential_accel", PROPERTY_HINT_RANGE, "-100,100,0.01"), "set_param", "get_param", PARAM_TANGENTIAL_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "tangential_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_TANGENTIAL_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "tangential_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_TANGENTIAL_ACCEL); + ADD_GROUP("Damping", ""); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "damping", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_param", "get_param", PARAM_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "damping_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_DAMPING); + ADD_GROUP("Angle", ""); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angle", PROPERTY_HINT_RANGE, "-720,720,0.1"), "set_param", "get_param", PARAM_ANGLE); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angle_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGLE); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "angle_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANGLE); + ADD_GROUP("Scale", ""); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "scale", PROPERTY_HINT_RANGE, "0,1000,0.01"), "set_param", "get_param", PARAM_SCALE); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "scale_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_SCALE); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "scale_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_SCALE); + ADD_GROUP("Color", ""); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "color_ramp", PROPERTY_HINT_RESOURCE_TYPE, "GradientTexture"), "set_color_ramp", "get_color_ramp"); + + ADD_GROUP("Hue Variation", "hue_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation", PROPERTY_HINT_RANGE, "-1,1,0.1"), "set_param", "get_param", PARAM_HUE_VARIATION); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_HUE_VARIATION); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "hue_variation_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_HUE_VARIATION); + ADD_GROUP("Animation", "anim_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_speed", PROPERTY_HINT_RANGE, "0,128,0.01"), "set_param", "get_param", PARAM_ANIM_SPEED); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_speed_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANIM_SPEED); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anim_speed_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANIM_SPEED); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_offset", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_ANIM_OFFSET); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_offset_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANIM_OFFSET); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anim_offset_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANIM_OFFSET); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "anim_loop"), "set_flag", "get_flag", FLAG_ANIM_LOOP); + + BIND_CONSTANT(PARAM_INITIAL_LINEAR_VELOCITY); + BIND_CONSTANT(PARAM_ANGULAR_VELOCITY); + BIND_CONSTANT(PARAM_ORBIT_VELOCITY); + BIND_CONSTANT(PARAM_LINEAR_ACCEL); + BIND_CONSTANT(PARAM_RADIAL_ACCEL); + BIND_CONSTANT(PARAM_TANGENTIAL_ACCEL); + BIND_CONSTANT(PARAM_DAMPING); + BIND_CONSTANT(PARAM_ANGLE); + BIND_CONSTANT(PARAM_SCALE); + BIND_CONSTANT(PARAM_HUE_VARIATION); + BIND_CONSTANT(PARAM_ANIM_SPEED); + BIND_CONSTANT(PARAM_ANIM_OFFSET); + BIND_CONSTANT(PARAM_MAX); + + BIND_CONSTANT(FLAG_ALIGN_Y_TO_VELOCITY); + BIND_CONSTANT(FLAG_ROTATE_Y); + BIND_CONSTANT(FLAG_MAX); + + BIND_CONSTANT(EMISSION_SHAPE_POINT); + BIND_CONSTANT(EMISSION_SHAPE_SPHERE); + BIND_CONSTANT(EMISSION_SHAPE_BOX); + BIND_CONSTANT(EMISSION_SHAPE_POINTS); + BIND_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS); } -#endif +ParticlesMaterial::ParticlesMaterial() + : element(this) { + + set_spread(45); + set_flatness(0); + set_param(PARAM_INITIAL_LINEAR_VELOCITY, 1); + set_param(PARAM_ORBIT_VELOCITY, 0); + set_param(PARAM_LINEAR_ACCEL, 0); + set_param(PARAM_RADIAL_ACCEL, 0); + set_param(PARAM_TANGENTIAL_ACCEL, 0); + set_param(PARAM_DAMPING, 0); + set_param(PARAM_ANGLE, 0); + set_param(PARAM_SCALE, 1); + set_param(PARAM_HUE_VARIATION, 0); + set_param(PARAM_ANIM_SPEED, 0); + set_param(PARAM_ANIM_OFFSET, 0); + set_emission_shape(EMISSION_SHAPE_POINT); + set_emission_sphere_radius(1); + set_emission_box_extents(Vector3(1, 1, 1)); + set_trail_divisor(1); + set_gravity(Vector3(0, -9.8, 0)); + emission_point_count = 1; + + for (int i = 0; i < PARAM_MAX; i++) { + set_param_randomness(Parameter(i), 0); + } + + for (int i = 0; i < FLAG_MAX; i++) { + flags[i] = false; + } + + set_color(Color(1, 1, 1, 1)); + + current_key.key = 0; + current_key.invalid_key = 1; + + _queue_shader_change(); +} + +ParticlesMaterial::~ParticlesMaterial() { +} diff --git a/scene/3d/particles.h b/scene/3d/particles.h index 6cb1caad3..9c1436a47 100644 --- a/scene/3d/particles.h +++ b/scene/3d/particles.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -37,130 +38,362 @@ /** @author Juan Linietsky <reduzio@gmail.com> */ -#if 0 + class Particles : public GeometryInstance { +private: + GDCLASS(Particles, GeometryInstance); + public: + enum DrawOrder { + DRAW_ORDER_INDEX, + DRAW_ORDER_LIFETIME, + DRAW_ORDER_VIEW_DEPTH, + }; - enum Variable { - VAR_LIFETIME=VS::PARTICLE_LIFETIME, - VAR_SPREAD=VS::PARTICLE_SPREAD, - VAR_GRAVITY=VS::PARTICLE_GRAVITY, - VAR_LINEAR_VELOCITY=VS::PARTICLE_LINEAR_VELOCITY, - VAR_ANGULAR_VELOCITY=VS::PARTICLE_ANGULAR_VELOCITY, - VAR_LINEAR_ACCELERATION=VS::PARTICLE_LINEAR_ACCELERATION, - VAR_DRAG=VS::PARTICLE_RADIAL_ACCELERATION, - VAR_TANGENTIAL_ACCELERATION=VS::PARTICLE_TANGENTIAL_ACCELERATION, - VAR_DAMPING=VS::PARTICLE_DAMPING, - VAR_INITIAL_SIZE=VS::PARTICLE_INITIAL_SIZE, - VAR_FINAL_SIZE=VS::PARTICLE_FINAL_SIZE, - VAR_INITIAL_ANGLE=VS::PARTICLE_INITIAL_ANGLE, - VAR_HEIGHT=VS::PARTICLE_HEIGHT, - VAR_HEIGHT_SPEED_SCALE=VS::PARTICLE_HEIGHT_SPEED_SCALE, - VAR_MAX=VS::PARTICLE_VAR_MAX + enum { + MAX_DRAW_PASSES = 4 }; private: - GDCLASS( Particles, GeometryInstance ); - RID particles; - int amount; bool emitting; - float emit_timeout; - AABB visibility_aabb; - Vector3 gravity_normal; - Vector3 emission_half_extents; - bool using_points; - float var[VAR_MAX]; - float var_random[VAR_MAX]; - bool height_from_velocity; - Vector3 emission_base_velocity; - bool local_coordinates; + bool one_shot; + int amount; + float lifetime; + float pre_process_time; + float explosiveness_ratio; + float randomness_ratio; + float speed_scale; + Rect3 visibility_aabb; + bool local_coords; + int fixed_fps; + bool fractional_delta; - struct ColorPhase { + Ref<Material> process_material; - Color color; - float pos; - }; + DrawOrder draw_order; + + Vector<Ref<Mesh> > draw_passes; + +protected: + static void _bind_methods(); + void _notification(int p_what); + virtual void _validate_property(PropertyInfo &property) const; - virtual bool _can_gizmo_scale() const; - virtual RES _get_gizmo_geometry() const; +public: + Rect3 get_aabb() const; + PoolVector<Face3> get_faces(uint32_t p_usage_flags) const; - int color_phase_count; + void set_emitting(bool p_emitting); + void set_amount(int p_amount); + void set_lifetime(float p_lifetime); + void set_one_shot(bool p_one_shot); + void set_pre_process_time(float p_time); + void set_explosiveness_ratio(float p_ratio); + void set_randomness_ratio(float p_ratio); + void set_visibility_aabb(const Rect3 &p_aabb); + void set_use_local_coordinates(bool p_enable); + void set_process_material(const Ref<Material> &p_material); + void set_speed_scale(float p_scale); - ColorPhase color_phase[4]; + bool is_emitting() const; + int get_amount() const; + float get_lifetime() const; + bool get_one_shot() const; + float get_pre_process_time() const; + float get_explosiveness_ratio() const; + float get_randomness_ratio() const; + Rect3 get_visibility_aabb() const; + bool get_use_local_coordinates() const; + Ref<Material> get_process_material() const; + float get_speed_scale() const; - Ref<Material> material; + void set_fixed_fps(int p_count); + int get_fixed_fps() const; - Timer* timer; - void setup_timer(); + void set_fractional_delta(bool p_enable); + bool get_fractional_delta() const; -protected: + void set_draw_order(DrawOrder p_order); + DrawOrder get_draw_order() const; - static void _bind_methods(); + void set_draw_passes(int p_count); + int get_draw_passes() const; + + void set_draw_pass_mesh(int p_pass, const Ref<Mesh> &p_mesh); + Ref<Mesh> get_draw_pass_mesh(int p_pass) const; + + virtual String get_configuration_warning() const; + + void restart(); + + Rect3 capture_aabb() const; + Particles(); + ~Particles(); +}; + +VARIANT_ENUM_CAST(Particles::DrawOrder) + +class ParticlesMaterial : public Material { + + GDCLASS(ParticlesMaterial, Material) public: + enum Parameter { + PARAM_INITIAL_LINEAR_VELOCITY, + PARAM_ANGULAR_VELOCITY, + PARAM_ORBIT_VELOCITY, + PARAM_LINEAR_ACCEL, + PARAM_RADIAL_ACCEL, + PARAM_TANGENTIAL_ACCEL, + PARAM_DAMPING, + PARAM_ANGLE, + PARAM_SCALE, + PARAM_HUE_VARIATION, + PARAM_ANIM_SPEED, + PARAM_ANIM_OFFSET, + PARAM_MAX + }; - AABB get_aabb() const; - PoolVector<Face3> get_faces(uint32_t p_usage_flags) const; + enum Flags { + FLAG_ALIGN_Y_TO_VELOCITY, + FLAG_ROTATE_Y, + FLAG_DISABLE_Z, + FLAG_ANIM_LOOP, + FLAG_MAX + }; - void set_amount(int p_amount); - int get_amount() const; + enum EmissionShape { + EMISSION_SHAPE_POINT, + EMISSION_SHAPE_SPHERE, + EMISSION_SHAPE_BOX, + EMISSION_SHAPE_POINTS, + EMISSION_SHAPE_DIRECTED_POINTS, + }; - void set_emitting(bool p_emitting); - bool is_emitting() const; +private: + union MaterialKey { - void set_visibility_aabb(const AABB& p_aabb); - AABB get_visibility_aabb() const; + struct { + uint32_t texture_mask : 16; + uint32_t texture_color : 1; + uint32_t flags : 4; + uint32_t emission_shape : 2; + uint32_t trail_size_texture : 1; + uint32_t trail_color_texture : 1; + uint32_t invalid_key : 1; + uint32_t has_emission_color : 1; + }; - void set_emission_half_extents(const Vector3& p_half_extents); - Vector3 get_emission_half_extents() const; + uint32_t key; - void set_emission_base_velocity(const Vector3& p_base_velocity); - Vector3 get_emission_base_velocity() const; + bool operator<(const MaterialKey &p_key) const { + return key < p_key.key; + } + }; - void set_emission_points(const PoolVector<Vector3>& p_points); - PoolVector<Vector3> get_emission_points() const; + struct ShaderData { + RID shader; + int users; + }; - void set_gravity_normal(const Vector3& p_normal); - Vector3 get_gravity_normal() const; + static Map<MaterialKey, ShaderData> shader_map; - void set_variable(Variable p_variable,float p_value); - float get_variable(Variable p_variable) const; + MaterialKey current_key; - void set_randomness(Variable p_variable,float p_randomness); - float get_randomness(Variable p_variable) const; + _FORCE_INLINE_ MaterialKey _compute_key() const { - void set_color_phases(int p_phases); - int get_color_phases() const; + MaterialKey mk; + mk.key = 0; + for (int i = 0; i < PARAM_MAX; i++) { + if (tex_parameters[i].is_valid()) { + mk.texture_mask |= (1 << i); + } + } + for (int i = 0; i < FLAG_MAX; i++) { + if (flags[i]) { + mk.flags |= (1 << i); + } + } - void set_color_phase_pos(int p_phase, float p_pos); - float get_color_phase_pos(int p_phase) const; + mk.texture_color = color_ramp.is_valid() ? 1 : 0; + mk.emission_shape = emission_shape; + mk.trail_color_texture = trail_color_modifier.is_valid() ? 1 : 0; + mk.trail_size_texture = trail_size_modifier.is_valid() ? 1 : 0; + mk.has_emission_color = emission_shape >= EMISSION_SHAPE_POINTS && emission_color_texture.is_valid(); - void set_color_phase_color(int p_phase, const Color& p_color); - Color get_color_phase_color(int p_phase) const; + return mk; + } - void set_height_from_velocity(bool p_enable); - bool has_height_from_velocity() const; + static Mutex *material_mutex; + static SelfList<ParticlesMaterial>::List dirty_materials; - void set_material(const Ref<Material>& p_material); - Ref<Material> get_material() const; + struct ShaderNames { + StringName spread; + StringName flatness; + StringName initial_linear_velocity; + StringName initial_angle; + StringName angular_velocity; + StringName orbit_velocity; + StringName linear_accel; + StringName radial_accel; + StringName tangent_accel; + StringName damping; + StringName scale; + StringName hue_variation; + StringName anim_speed; + StringName anim_offset; - void set_emit_timeout(float p_timeout); - float get_emit_timeout() const; + StringName initial_linear_velocity_random; + StringName initial_angle_random; + StringName angular_velocity_random; + StringName orbit_velocity_random; + StringName linear_accel_random; + StringName radial_accel_random; + StringName tangent_accel_random; + StringName damping_random; + StringName scale_random; + StringName hue_variation_random; + StringName anim_speed_random; + StringName anim_offset_random; - void set_use_local_coordinates(bool p_use); - bool is_using_local_coordinates() const; + StringName angle_texture; + StringName angular_velocity_texture; + StringName orbit_velocity_texture; + StringName linear_accel_texture; + StringName radial_accel_texture; + StringName tangent_accel_texture; + StringName damping_texture; + StringName scale_texture; + StringName hue_variation_texture; + StringName anim_speed_texture; + StringName anim_offset_texture; - void start_emitting(float p_time); + StringName color; + StringName color_ramp; + StringName emission_sphere_radius; + StringName emission_box_extents; + StringName emission_texture_point_count; + StringName emission_texture_points; + StringName emission_texture_normal; + StringName emission_texture_color; - Particles(); - ~Particles(); + StringName trail_divisor; + StringName trail_size_modifier; + StringName trail_color_modifier; + + StringName gravity; + }; + + static ShaderNames *shader_names; + + SelfList<ParticlesMaterial> element; + + void _update_shader(); + _FORCE_INLINE_ void _queue_shader_change(); + _FORCE_INLINE_ bool _is_shader_dirty() const; + + float spread; + float flatness; + + float parameters[PARAM_MAX]; + float randomness[PARAM_MAX]; + Ref<Texture> tex_parameters[PARAM_MAX]; + Color color; + Ref<Texture> color_ramp; + + bool flags[FLAG_MAX]; + + EmissionShape emission_shape; + float emission_sphere_radius; + Vector3 emission_box_extents; + Ref<Texture> emission_point_texture; + Ref<Texture> emission_normal_texture; + Ref<Texture> emission_color_texture; + int emission_point_count; + + bool anim_loop; + + int trail_divisor; + + Ref<CurveTexture> trail_size_modifier; + Ref<GradientTexture> trail_color_modifier; + + Vector3 gravity; + + //do not save emission points here + +protected: + static void _bind_methods(); + virtual void _validate_property(PropertyInfo &property) const; + +public: + void set_spread(float p_spread); + float get_spread() const; + + void set_flatness(float p_flatness); + float get_flatness() const; + + void set_param(Parameter p_param, float p_value); + float get_param(Parameter p_param) const; + + void set_param_randomness(Parameter p_param, float p_value); + float get_param_randomness(Parameter p_param) const; + + void set_param_texture(Parameter p_param, const Ref<Texture> &p_texture); + Ref<Texture> get_param_texture(Parameter p_param) const; + + void set_color(const Color &p_color); + Color get_color() const; + + void set_color_ramp(const Ref<Texture> &p_texture); + Ref<Texture> get_color_ramp() const; + + void set_flag(Flags p_flag, bool p_enable); + bool get_flag(Flags p_flag) const; + + void set_emission_shape(EmissionShape p_shape); + void set_emission_sphere_radius(float p_radius); + void set_emission_box_extents(Vector3 p_extents); + void set_emission_point_texture(const Ref<Texture> &p_points); + void set_emission_normal_texture(const Ref<Texture> &p_normals); + void set_emission_color_texture(const Ref<Texture> &p_colors); + void set_emission_point_count(int p_count); + + EmissionShape get_emission_shape() const; + float get_emission_sphere_radius() const; + Vector3 get_emission_box_extents() const; + Ref<Texture> get_emission_point_texture() const; + Ref<Texture> get_emission_normal_texture() const; + Ref<Texture> get_emission_color_texture() const; + int get_emission_point_count() const; + + void set_trail_divisor(int p_divisor); + int get_trail_divisor() const; + + void set_trail_size_modifier(const Ref<CurveTexture> &p_trail_size_modifier); + Ref<CurveTexture> get_trail_size_modifier() const; + + void set_trail_color_modifier(const Ref<GradientTexture> &p_trail_color_modifier); + Ref<GradientTexture> get_trail_color_modifier() const; + + void set_gravity(const Vector3 &p_gravity); + Vector3 get_gravity() const; + + static void init_shaders(); + static void finish_shaders(); + static void flush_changes(); + + ParticlesMaterial(); + ~ParticlesMaterial(); }; -VARIANT_ENUM_CAST( Particles::Variable ); -#endif +VARIANT_ENUM_CAST(ParticlesMaterial::Parameter) +VARIANT_ENUM_CAST(ParticlesMaterial::Flags) +VARIANT_ENUM_CAST(ParticlesMaterial::EmissionShape) + #endif diff --git a/scene/3d/path.cpp b/scene/3d/path.cpp index 457e9e555..f8df21004 100644 --- a/scene/3d/path.cpp +++ b/scene/3d/path.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -77,8 +78,8 @@ Ref<Curve3D> Path::get_curve() const { void Path::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_curve", "curve:Curve3D"), &Path::set_curve); - ClassDB::bind_method(D_METHOD("get_curve:Curve3D", "curve"), &Path::get_curve); + ClassDB::bind_method(D_METHOD("set_curve", "curve"), &Path::set_curve); + ClassDB::bind_method(D_METHOD("get_curve"), &Path::get_curve); ClassDB::bind_method(D_METHOD("_curve_changed"), &Path::_curve_changed); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve3D"), "set_curve", "get_curve"); @@ -107,40 +108,58 @@ void PathFollow::_update_transform() { Vector3 pos = c->interpolate_baked(o, cubic); Transform t = get_transform(); + t.origin = pos; + Vector3 pos_offset = Vector3(h_offset, v_offset, 0); + if (rotation_mode != ROTATION_NONE) { + // perform parallel transport + // + // see C. Dougan, The Parallel Transport Frame, Game Programming Gems 2 for example + // for a discussion about why not Frenet frame. - Vector3 n = (c->interpolate_baked(o + lookahead, cubic) - pos).normalized(); + Vector3 t_prev = pos - c->interpolate_baked(o - lookahead, cubic); + Vector3 t_cur = c->interpolate_baked(o + lookahead, cubic) - pos; - if (rotation_mode == ROTATION_Y) { + Vector3 axis = t_prev.cross(t_cur); + float dot = t_prev.normalized().dot(t_cur.normalized()); + float angle = Math::acos(CLAMP(dot, -1, 1)); - n.y = 0; - n.normalize(); - } + if (axis.length() > CMP_EPSILON && angle > CMP_EPSILON) { + if (rotation_mode == ROTATION_Y) { + // assuming we're referring to global Y-axis. is this correct? + axis.x = 0; + axis.z = 0; + } else if (rotation_mode == ROTATION_XY) { + axis.z = 0; + } else if (rotation_mode == ROTATION_XYZ) { + // all components are OK + } - if (n.length() < CMP_EPSILON) { //nothing, use previous - n = -t.get_basis().get_axis(2).normalized(); + t.rotate_basis(axis.normalized(), angle); } - Vector3 up = Vector3(0, 1, 0); - - if (rotation_mode == ROTATION_XYZ) { + // do the additional tilting + float tilt_angle = c->interpolate_baked_tilt(o); + Vector3 tilt_axis = t_cur; // is this correct?? - float tilt = c->interpolate_baked_tilt(o); - if (tilt != 0) { - - Basis rot(-n, tilt); //remember.. lookat will be znegative.. znegative!! we abide by opengl clan. - up = rot.xform(up); + if (tilt_axis.length() > CMP_EPSILON && tilt_angle > CMP_EPSILON) { + if (rotation_mode == ROTATION_Y) { + tilt_axis.x = 0; + tilt_axis.z = 0; + } else if (rotation_mode == ROTATION_XY) { + tilt_axis.z = 0; + } else if (rotation_mode == ROTATION_XYZ) { + // all components are OK } - } - t.set_look_at(pos, pos + n, up); + t.rotate_basis(tilt_axis.normalized(), tilt_angle); + } + t.translate(pos_offset); } else { - - t.origin = pos; + t.origin += pos_offset; } - t.origin += t.basis.get_axis(0) * h_offset + t.basis.get_axis(1) * v_offset; set_transform(t); } diff --git a/scene/3d/path.h b/scene/3d/path.h index 94227799e..eeae0668a 100644 --- a/scene/3d/path.h +++ b/scene/3d/path.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 78a00e4a7..dc8f72d77 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -27,6 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "physics_body.h" +#include "method_bind_ext.gen.inc" #include "scene/scene_string_names.h" void PhysicsBody::_notification(int p_what) { @@ -57,15 +59,15 @@ float PhysicsBody::get_inverse_mass() const { return 0; } -void PhysicsBody::set_collision_layer(uint32_t p_mask) { +void PhysicsBody::set_collision_layer(uint32_t p_layer) { - layer_mask = p_mask; - PhysicsServer::get_singleton()->body_set_layer_mask(get_rid(), p_mask); + collision_layer = p_layer; + PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), p_layer); } uint32_t PhysicsBody::get_collision_layer() const { - return layer_mask; + return collision_layer; } void PhysicsBody::set_collision_mask(uint32_t p_mask) { @@ -165,7 +167,7 @@ void PhysicsBody::_bind_methods() { PhysicsBody::PhysicsBody(PhysicsServer::BodyMode p_mode) : CollisionObject(PhysicsServer::get_singleton()->body_create(p_mode), false) { - layer_mask = 1; + collision_layer = 1; collision_mask = 1; } @@ -227,8 +229,8 @@ void StaticBody::_bind_methods() { ClassDB::bind_method(D_METHOD("set_bounce", "bounce"), &StaticBody::set_bounce); ClassDB::bind_method(D_METHOD("get_bounce"), &StaticBody::get_bounce); - ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body:PhysicsBody"), &PhysicsBody::add_collision_exception_with); - ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body:PhysicsBody"), &PhysicsBody::remove_collision_exception_with); + ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &PhysicsBody::add_collision_exception_with); + ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &PhysicsBody::remove_collision_exception_with); ADD_PROPERTY(PropertyInfo(Variant::REAL, "friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_friction", "get_friction"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_bounce", "get_bounce"); @@ -471,6 +473,21 @@ void RigidBody::_direct_state_changed(Object *p_state) { } void RigidBody::_notification(int p_what) { + +#ifdef TOOLS_ENABLED + if (p_what == NOTIFICATION_ENTER_TREE) { + if (get_tree()->is_editor_hint()) { + set_notify_local_transform(true); //used for warnings and only in editor + } + } + + if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) { + if (get_tree()->is_editor_hint()) { + update_configuration_warning(); + } + } + +#endif } void RigidBody::set_mode(Mode p_mode) { @@ -518,11 +535,11 @@ real_t RigidBody::get_mass() const { void RigidBody::set_weight(real_t p_weight) { - set_mass(p_weight / 9.8); + set_mass(p_weight / real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8))); } real_t RigidBody::get_weight() const { - return mass * 9.8; + return mass * real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8)); } void RigidBody::set_friction(real_t p_friction) { @@ -745,6 +762,22 @@ Array RigidBody::get_colliding_bodies() const { return ret; } +String RigidBody::get_configuration_warning() const { + + Transform t = get_transform(); + + String warning = CollisionObject::get_configuration_warning(); + + if ((get_mode() == MODE_RIGID || get_mode() == MODE_CHARACTER) && (ABS(t.basis.get_axis(0).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(1).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(0).length() - 1.0) > 0.05)) { + if (warning != String()) { + warning += "\n"; + } + warning += TTR("Size changes to RigidBody (in character or rigid modes) will be overriden by the physics engine when running.\nChange the size in children collision shapes instead."); + } + + return warning; +} + void RigidBody::_bind_methods() { ClassDB::bind_method(D_METHOD("set_mode", "mode"), &RigidBody::set_mode); @@ -877,396 +910,260 @@ RigidBody::~RigidBody() { ////////////////////////////////////////////////////// ////////////////////////// -Variant KinematicBody::_get_collider() const { +Dictionary KinematicBody::_move(const Vector3 &p_motion) { - ObjectID oid = get_collider(); - if (oid == 0) - return Variant(); - Object *obj = ObjectDB::get_instance(oid); - if (!obj) - return Variant(); - - Reference *ref = obj->cast_to<Reference>(); - if (ref) { - return Ref<Reference>(ref); - } + Collision col; + if (move(p_motion, col)) { + Dictionary d; + d["position"] = col.collision; + d["normal"] = col.collision; + d["local_shape"] = col.local_shape; + d["travel"] = col.travel; + d["remainder"] = col.remainder; + d["collider_id"] = col.collider; + if (col.collider) { + d["collider"] = ObjectDB::get_instance(col.collider); + } else { + d["collider"] = Variant(); + } - return obj; -} + d["collider_shape_index"] = col.collider_shape; + d["collider_metadata"] = col.collider_metadata; -bool KinematicBody::_ignores_mode(PhysicsServer::BodyMode p_mode) const { + return d; - switch (p_mode) { - case PhysicsServer::BODY_MODE_STATIC: return !collide_static; - case PhysicsServer::BODY_MODE_KINEMATIC: return !collide_kinematic; - case PhysicsServer::BODY_MODE_RIGID: return !collide_rigid; - case PhysicsServer::BODY_MODE_CHARACTER: return !collide_character; + } else { + return Dictionary(); } - - return true; } -Vector3 KinematicBody::move(const Vector3 &p_motion) { +bool KinematicBody::move(const Vector3 &p_motion, Collision &r_collision) { - //give me back regular physics engine logic - //this is madness - //and most people using this function will think - //what it does is simpler than using physics - //this took about a week to get right.. - //but is it right? who knows at this point.. - - colliding = false; - ERR_FAIL_COND_V(!is_inside_tree(), Vector3()); - PhysicsDirectSpaceState *dss = PhysicsServer::get_singleton()->space_get_direct_state(get_world()->get_space()); - ERR_FAIL_COND_V(!dss, Vector3()); - const int max_shapes = 32; - Vector3 sr[max_shapes * 2]; - int res_shapes; + Transform gt = get_global_transform(); + PhysicsServer::MotionResult result; + bool colliding = PhysicsServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, margin, &result); - Set<RID> exclude; - exclude.insert(get_rid()); + if (colliding) { + r_collision.collider_metadata = result.collider_metadata; + r_collision.collider_shape = result.collider_shape; + r_collision.collider_vel = result.collider_velocity; + r_collision.collision = result.collision_point; + r_collision.normal = result.collision_normal; + r_collision.collider = result.collider_id; + r_collision.travel = result.motion; + r_collision.remainder = result.remainder; + r_collision.local_shape = result.collision_local_shape; + } - //recover first - int recover_attempts = 4; + gt.origin += result.motion; + set_global_transform(gt); - bool collided = false; - uint32_t mask = 0; - if (collide_static) - mask |= PhysicsDirectSpaceState::TYPE_MASK_STATIC_BODY; - if (collide_kinematic) - mask |= PhysicsDirectSpaceState::TYPE_MASK_KINEMATIC_BODY; - if (collide_rigid) - mask |= PhysicsDirectSpaceState::TYPE_MASK_RIGID_BODY; - if (collide_character) - mask |= PhysicsDirectSpaceState::TYPE_MASK_CHARACTER_BODY; + return colliding; +} - //print_line("motion: "+p_motion+" margin: "+rtos(margin)); +Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction, float p_slope_stop_min_velocity, int p_max_bounces, float p_floor_max_angle) { - //print_line("margin: "+rtos(margin)); + Vector3 motion = (floor_velocity + p_linear_velocity) * get_fixed_process_delta_time(); + Vector3 lv = p_linear_velocity; - float m = margin; - //m=0.001; + on_floor = false; + on_ceiling = false; + on_wall = false; + colliders.clear(); + floor_velocity = Vector3(); - do { + while (p_max_bounces) { - //motion recover - for (int i = 0; i < get_shape_count(); i++) { + Collision collision; - if (is_shape_set_as_trigger(i)) - continue; + bool collided = move(motion, collision); - if (dss->collide_shape(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i), m, sr, max_shapes, res_shapes, exclude, get_collision_layer(), mask)) { - collided = true; - } - } + if (collided) { - if (!collided) - break; + motion = collision.remainder; - //print_line("have to recover"); - Vector3 recover_motion; - bool all_outside = true; - for (int j = 0; j < 8; j++) { - for (int i = 0; i < res_shapes; i++) { + if (p_floor_direction == Vector3()) { + //all is a wall + on_wall = true; + } else { + if (collision.normal.dot(p_floor_direction) >= Math::cos(p_floor_max_angle)) { //floor - Vector3 a = sr[i * 2 + 0]; - Vector3 b = sr[i * 2 + 1]; -//print_line(String()+a+" -> "+b); -#if 0 - float d = a.distance_to(b); + on_floor = true; + floor_velocity = collision.collider_vel; - /* - if (d<margin) - continue; - */ - recover_motion+=(b-a)*0.2; -#else - float dist = a.distance_to(b); - if (dist > CMP_EPSILON) { - Vector3 norm = (b - a).normalized(); - if (dist > margin * 0.5) - all_outside = false; - float adv = norm.dot(recover_motion); - //print_line(itos(i)+" dist: "+rtos(dist)+" adv: "+rtos(adv)); - recover_motion += norm * MAX(dist - adv, 0) * 0.4; + /*if (collision.travel.length() < 0.01 && ABS((lv.x - floor_velocity.x)) < p_slope_stop_min_velocity) { + Transform gt = get_global_transform(); + gt.elements[2] -= collision.travel; + set_global_transform(gt); + return Vector3(); + }*/ + } else if (collision.normal.dot(-p_floor_direction) >= Math::cos(p_floor_max_angle)) { //ceiling + on_ceiling = true; + } else { + on_wall = true; } -#endif } - } - - if (recover_motion == Vector3()) { - collided = false; - break; - } - - //print_line("**** RECOVER: "+recover_motion); - Transform gt = get_global_transform(); - gt.origin += recover_motion; - set_global_transform(gt); + Vector3 n = collision.normal; + motion = motion.slide(n); + lv = lv.slide(n); - recover_attempts--; - - if (all_outside) - break; - - } while (recover_attempts); - - //move second - float safe = 1.0; - float unsafe = 1.0; - int best_shape = -1; - - PhysicsDirectSpaceState::ShapeRestInfo rest; - - //print_line("pos: "+get_global_transform().origin); - //print_line("motion: "+p_motion); - - for (int i = 0; i < get_shape_count(); i++) { - - if (is_shape_set_as_trigger(i)) - continue; - - float lsafe, lunsafe; - PhysicsDirectSpaceState::ShapeRestInfo lrest; - bool valid = dss->cast_motion(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i), p_motion, 0, lsafe, lunsafe, exclude, get_collision_layer(), mask, &lrest); - //print_line("shape: "+itos(i)+" travel:"+rtos(ltravel)); - if (!valid) { - safe = 0; - unsafe = 0; - best_shape = i; //sadly it's the best - //print_line("initial stuck"); + colliders.push_back(collision); + } else { break; } - if (lsafe == 1.0) { - //print_line("initial free"); - continue; - } - if (lsafe < safe) { - //print_line("initial at "+rtos(lsafe)); - safe = lsafe; - safe = MAX(0, lsafe - 0.01); - unsafe = lunsafe; - best_shape = i; - rest = lrest; - } - } - - //print_line("best shape: "+itos(best_shape)+" motion "+p_motion); - - if (safe >= 1) { - //not collided - colliding = false; - } else { - - colliding = true; - - if (true || (safe == 0 && unsafe == 0)) { //use it always because it's more precise than GJK - //no advance, use rest info from collision - Transform ugt = get_global_transform(); - ugt.origin += p_motion * unsafe; - - PhysicsDirectSpaceState::ShapeRestInfo rest_info; - bool c2 = dss->rest_info(get_shape(best_shape)->get_rid(), ugt * get_shape_transform(best_shape), m, &rest, exclude, get_collision_layer(), mask); - if (!c2) { - //should not happen, but floating point precision is so weird.. - colliding = false; - } - - //print_line("Rest Travel: "+rest.normal); - } - - if (colliding) { - - collision = rest.point; - normal = rest.normal; - collider = rest.collider_id; - collider_vel = rest.linear_velocity; - collider_shape = rest.shape; - } + p_max_bounces--; + if (motion == Vector3()) + break; } - Vector3 motion = p_motion * safe; - /* - if (colliding) - motion+=normal*0.001; - */ - Transform gt = get_global_transform(); - gt.origin += motion; - set_global_transform(gt); - - return p_motion - motion; + return lv; } -Vector3 KinematicBody::move_to(const Vector3 &p_position) { +bool KinematicBody::is_on_floor() const { - return move(p_position - get_global_transform().origin); + return on_floor; } +bool KinematicBody::is_on_wall() const { -bool KinematicBody::can_teleport_to(const Vector3 &p_position) { - - ERR_FAIL_COND_V(!is_inside_tree(), false); - PhysicsDirectSpaceState *dss = PhysicsServer::get_singleton()->space_get_direct_state(get_world()->get_space()); - ERR_FAIL_COND_V(!dss, false); - - uint32_t mask = 0; - if (collide_static) - mask |= PhysicsDirectSpaceState::TYPE_MASK_STATIC_BODY; - if (collide_kinematic) - mask |= PhysicsDirectSpaceState::TYPE_MASK_KINEMATIC_BODY; - if (collide_rigid) - mask |= PhysicsDirectSpaceState::TYPE_MASK_RIGID_BODY; - if (collide_character) - mask |= PhysicsDirectSpaceState::TYPE_MASK_CHARACTER_BODY; - - Transform xform = get_global_transform(); - xform.origin = p_position; - - Set<RID> exclude; - exclude.insert(get_rid()); - - for (int i = 0; i < get_shape_count(); i++) { + return on_wall; +} +bool KinematicBody::is_on_ceiling() const { - if (is_shape_set_as_trigger(i)) - continue; + return on_ceiling; +} - bool col = dss->intersect_shape(get_shape(i)->get_rid(), xform * get_shape_transform(i), 0, NULL, 1, exclude, get_collision_layer(), mask); - if (col) - return false; - } +Vector3 KinematicBody::get_floor_velocity() const { - return true; + return floor_velocity; } -bool KinematicBody::is_colliding() const { +bool KinematicBody::test_move(const Transform &p_from, const Vector3 &p_motion) { ERR_FAIL_COND_V(!is_inside_tree(), false); - return colliding; + return PhysicsServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, margin); } -Vector3 KinematicBody::get_collision_pos() const { - ERR_FAIL_COND_V(!colliding, Vector3()); - return collision; -} -Vector3 KinematicBody::get_collision_normal() const { +void KinematicBody::set_safe_margin(float p_margin) { - ERR_FAIL_COND_V(!colliding, Vector3()); - return normal; + margin = p_margin; } -Vector3 KinematicBody::get_collider_velocity() const { +float KinematicBody::get_safe_margin() const { - return collider_vel; + return margin; } -ObjectID KinematicBody::get_collider() const { +int KinematicBody::get_collision_count() const { - ERR_FAIL_COND_V(!colliding, 0); - return collider; + return colliders.size(); } -int KinematicBody::get_collider_shape() const { +Vector3 KinematicBody::get_collision_position(int p_collision) const { - ERR_FAIL_COND_V(!colliding, -1); - return collider_shape; -} -void KinematicBody::set_collide_with_static_bodies(bool p_enable) { + ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector3()); - collide_static = p_enable; + return colliders[p_collision].collision; } -bool KinematicBody::can_collide_with_static_bodies() const { - - return collide_static; +Vector3 KinematicBody::get_collision_normal(int p_collision) const { + ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector3()); + return colliders[p_collision].normal; } -void KinematicBody::set_collide_with_rigid_bodies(bool p_enable) { - - collide_rigid = p_enable; +Vector3 KinematicBody::get_collision_travel(int p_collision) const { + ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector3()); + return colliders[p_collision].travel; } -bool KinematicBody::can_collide_with_rigid_bodies() const { - - return collide_rigid; +Vector3 KinematicBody::get_collision_remainder(int p_collision) const { + ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector3()); + return colliders[p_collision].remainder; +} +Object *KinematicBody::get_collision_local_shape(int p_collision) const { + ERR_FAIL_INDEX_V(p_collision, colliders.size(), NULL); + uint32_t owner = shape_find_owner(colliders[p_collision].local_shape); + return shape_owner_get_owner(owner); } +Object *KinematicBody::get_collision_collider(int p_collision) const { + ERR_FAIL_INDEX_V(p_collision, colliders.size(), NULL); -void KinematicBody::set_collide_with_kinematic_bodies(bool p_enable) { + if (colliders[p_collision].collider) { + return ObjectDB::get_instance(colliders[p_collision].collider); + } - collide_kinematic = p_enable; + return NULL; } -bool KinematicBody::can_collide_with_kinematic_bodies() const { +ObjectID KinematicBody::get_collision_collider_id(int p_collision) const { + ERR_FAIL_INDEX_V(p_collision, colliders.size(), 0); - return collide_kinematic; + return colliders[p_collision].collider; } +Object *KinematicBody::get_collision_collider_shape(int p_collision) const { + ERR_FAIL_INDEX_V(p_collision, colliders.size(), NULL); + Object *collider = get_collision_collider(p_collision); + if (collider) { + CollisionObject *obj2d = collider->cast_to<CollisionObject>(); + if (obj2d) { + uint32_t owner = shape_find_owner(colliders[p_collision].collider_shape); + return obj2d->shape_owner_get_owner(owner); + } + } -void KinematicBody::set_collide_with_character_bodies(bool p_enable) { - - collide_character = p_enable; + return NULL; } -bool KinematicBody::can_collide_with_character_bodies() const { - - return collide_character; +int KinematicBody::get_collision_collider_shape_index(int p_collision) const { + ERR_FAIL_INDEX_V(p_collision, colliders.size(), -1); + return colliders[p_collision].collider_shape; } - -void KinematicBody::set_collision_margin(float p_margin) { - - margin = p_margin; +Vector3 KinematicBody::get_collision_collider_velocity(int p_collision) const { + ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector3()); + return colliders[p_collision].collider_vel; } - -float KinematicBody::get_collision_margin() const { - - return margin; +Variant KinematicBody::get_collision_collider_metadata(int p_collision) const { + ERR_FAIL_INDEX_V(p_collision, colliders.size(), Variant()); + return colliders[p_collision].collider_metadata; } void KinematicBody::_bind_methods() { - ClassDB::bind_method(D_METHOD("move", "rel_vec"), &KinematicBody::move); - ClassDB::bind_method(D_METHOD("move_to", "position"), &KinematicBody::move_to); + ClassDB::bind_method(D_METHOD("move", "rel_vec"), &KinematicBody::_move); + ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "slope_stop_min_velocity", "max_bounces", "floor_max_angle"), &KinematicBody::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(0.05), DEFVAL(4), DEFVAL(Math::deg2rad((float)45))); - ClassDB::bind_method(D_METHOD("can_teleport_to", "position"), &KinematicBody::can_teleport_to); + ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec"), &KinematicBody::test_move); - ClassDB::bind_method(D_METHOD("is_colliding"), &KinematicBody::is_colliding); + ClassDB::bind_method(D_METHOD("is_on_floor"), &KinematicBody::is_on_floor); + ClassDB::bind_method(D_METHOD("is_on_ceiling"), &KinematicBody::is_on_ceiling); + ClassDB::bind_method(D_METHOD("is_on_wall"), &KinematicBody::is_on_wall); + ClassDB::bind_method(D_METHOD("get_floor_velocity"), &KinematicBody::get_floor_velocity); - ClassDB::bind_method(D_METHOD("get_collision_pos"), &KinematicBody::get_collision_pos); - ClassDB::bind_method(D_METHOD("get_collision_normal"), &KinematicBody::get_collision_normal); - ClassDB::bind_method(D_METHOD("get_collider_velocity"), &KinematicBody::get_collider_velocity); - ClassDB::bind_method(D_METHOD("get_collider:Variant"), &KinematicBody::_get_collider); - ClassDB::bind_method(D_METHOD("get_collider_shape"), &KinematicBody::get_collider_shape); + ClassDB::bind_method(D_METHOD("set_safe_margin", "pixels"), &KinematicBody::set_safe_margin); + ClassDB::bind_method(D_METHOD("get_safe_margin"), &KinematicBody::get_safe_margin); - ClassDB::bind_method(D_METHOD("set_collide_with_static_bodies", "enable"), &KinematicBody::set_collide_with_static_bodies); - ClassDB::bind_method(D_METHOD("can_collide_with_static_bodies"), &KinematicBody::can_collide_with_static_bodies); + ClassDB::bind_method(D_METHOD("get_collision_count"), &KinematicBody::get_collision_count); + ClassDB::bind_method(D_METHOD("get_collision_position", "collision"), &KinematicBody::get_collision_position); + ClassDB::bind_method(D_METHOD("get_collision_normal", "collision"), &KinematicBody::get_collision_normal); + ClassDB::bind_method(D_METHOD("get_collision_travel", "collision"), &KinematicBody::get_collision_travel); + ClassDB::bind_method(D_METHOD("get_collision_remainder", "collision"), &KinematicBody::get_collision_remainder); + ClassDB::bind_method(D_METHOD("get_collision_local_shape", "collision"), &KinematicBody::get_collision_local_shape); + ClassDB::bind_method(D_METHOD("get_collision_collider", "collision"), &KinematicBody::get_collision_collider); + ClassDB::bind_method(D_METHOD("get_collision_collider_id", "collision"), &KinematicBody::get_collision_collider_id); + ClassDB::bind_method(D_METHOD("get_collision_collider_shape", "collision"), &KinematicBody::get_collision_collider_shape); + ClassDB::bind_method(D_METHOD("get_collision_collider_shape_index", "collision"), &KinematicBody::get_collision_collider_shape_index); + ClassDB::bind_method(D_METHOD("get_collision_collider_velocity", "collision"), &KinematicBody::get_collision_collider_velocity); + ClassDB::bind_method(D_METHOD("get_collision_collider_metadata", "collision"), &KinematicBody::get_collision_collider_metadata); - ClassDB::bind_method(D_METHOD("set_collide_with_kinematic_bodies", "enable"), &KinematicBody::set_collide_with_kinematic_bodies); - ClassDB::bind_method(D_METHOD("can_collide_with_kinematic_bodies"), &KinematicBody::can_collide_with_kinematic_bodies); - - ClassDB::bind_method(D_METHOD("set_collide_with_rigid_bodies", "enable"), &KinematicBody::set_collide_with_rigid_bodies); - ClassDB::bind_method(D_METHOD("can_collide_with_rigid_bodies"), &KinematicBody::can_collide_with_rigid_bodies); - - ClassDB::bind_method(D_METHOD("set_collide_with_character_bodies", "enable"), &KinematicBody::set_collide_with_character_bodies); - ClassDB::bind_method(D_METHOD("can_collide_with_character_bodies"), &KinematicBody::can_collide_with_character_bodies); - - ClassDB::bind_method(D_METHOD("set_collision_margin", "pixels"), &KinematicBody::set_collision_margin); - ClassDB::bind_method(D_METHOD("get_collision_margin", "pixels"), &KinematicBody::get_collision_margin); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with/static"), "set_collide_with_static_bodies", "can_collide_with_static_bodies"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with/kinematic"), "set_collide_with_kinematic_bodies", "can_collide_with_kinematic_bodies"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with/rigid"), "set_collide_with_rigid_bodies", "can_collide_with_rigid_bodies"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with/character"), "set_collide_with_character_bodies", "can_collide_with_character_bodies"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "collision/margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_collision_margin", "get_collision_margin"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin"); } KinematicBody::KinematicBody() : PhysicsBody(PhysicsServer::BODY_MODE_KINEMATIC) { - collide_static = true; - collide_rigid = true; - collide_kinematic = true; - collide_character = true; - - colliding = false; - collider = 0; margin = 0.001; - collider_shape = 0; + + on_floor = false; + on_ceiling = false; + on_wall = false; } KinematicBody::~KinematicBody() { } diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h index 1cef94683..83811a1d9 100644 --- a/scene/3d/physics_body.h +++ b/scene/3d/physics_body.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -37,7 +38,7 @@ class PhysicsBody : public CollisionObject { GDCLASS(PhysicsBody, CollisionObject); - uint32_t layer_mask; + uint32_t collision_layer; uint32_t collision_mask; void _set_layers(uint32_t p_mask); @@ -53,7 +54,7 @@ public: virtual Vector3 get_angular_velocity() const; virtual float get_inverse_mass() const; - void set_collision_layer(uint32_t p_mask); + void set_collision_layer(uint32_t p_layer); uint32_t get_collision_layer() const; void set_collision_mask(uint32_t p_mask); @@ -251,6 +252,8 @@ public: void apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse); + virtual String get_configuration_warning() const; + RigidBody(); ~RigidBody(); }; @@ -262,58 +265,60 @@ class KinematicBody : public PhysicsBody { GDCLASS(KinematicBody, PhysicsBody); - float margin; - bool collide_static; - bool collide_rigid; - bool collide_kinematic; - bool collide_character; +public: + struct Collision { + Vector3 collision; + Vector3 normal; + Vector3 collider_vel; + ObjectID collider; + int collider_shape; + Variant collider_metadata; + Vector3 remainder; + Vector3 travel; + int local_shape; + }; - bool colliding; - Vector3 collision; - Vector3 normal; - Vector3 collider_vel; - ObjectID collider; - int collider_shape; +private: + float margin; - Variant _get_collider() const; + Vector3 floor_velocity; + bool on_floor; + bool on_ceiling; + bool on_wall; + Vector<Collision> colliders; _FORCE_INLINE_ bool _ignores_mode(PhysicsServer::BodyMode) const; + Dictionary _move(const Vector3 &p_motion); + protected: static void _bind_methods(); public: - enum { - SLIDE_FLAG_FLOOR, - SLIDE_FLAG_WALL, - SLIDE_FLAG_ROOF - }; - - Vector3 move(const Vector3 &p_motion); - Vector3 move_to(const Vector3 &p_position); - - bool can_teleport_to(const Vector3 &p_position); - bool is_colliding() const; - Vector3 get_collision_pos() const; - Vector3 get_collision_normal() const; - Vector3 get_collider_velocity() const; - ObjectID get_collider() const; - int get_collider_shape() const; - - void set_collide_with_static_bodies(bool p_enable); - bool can_collide_with_static_bodies() const; - - void set_collide_with_rigid_bodies(bool p_enable); - bool can_collide_with_rigid_bodies() const; + bool move(const Vector3 &p_motion, Collision &r_collision); + bool test_move(const Transform &p_from, const Vector3 &p_motion); - void set_collide_with_kinematic_bodies(bool p_enable); - bool can_collide_with_kinematic_bodies() const; + void set_safe_margin(float p_margin); + float get_safe_margin() const; - void set_collide_with_character_bodies(bool p_enable); - bool can_collide_with_character_bodies() const; + Vector3 move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction = Vector3(0, 0, 0), float p_slope_stop_min_velocity = 0.05, int p_max_bounces = 4, float p_floor_max_angle = Math::deg2rad((float)45)); + bool is_on_floor() const; + bool is_on_wall() const; + bool is_on_ceiling() const; + Vector3 get_floor_velocity() const; - void set_collision_margin(float p_margin); - float get_collision_margin() const; + int get_collision_count() const; + Vector3 get_collision_position(int p_collision) const; + Vector3 get_collision_normal(int p_collision) const; + Vector3 get_collision_travel(int p_collision) const; + Vector3 get_collision_remainder(int p_collision) const; + Object *get_collision_local_shape(int p_collision) const; + Object *get_collision_collider(int p_collision) const; + ObjectID get_collision_collider_id(int p_collision) const; + Object *get_collision_collider_shape(int p_collision) const; + int get_collision_collider_shape_index(int p_collision) const; + Vector3 get_collision_collider_velocity(int p_collision) const; + Variant get_collision_collider_metadata(int p_collision) const; KinematicBody(); ~KinematicBody(); diff --git a/scene/3d/physics_joint.cpp b/scene/3d/physics_joint.cpp index 8c20b003f..61d496935 100644 --- a/scene/3d/physics_joint.cpp +++ b/scene/3d/physics_joint.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -978,9 +979,9 @@ Generic6DOFJoint::Generic6DOFJoint() { void PhysicsJoint::_set(const String& p_name, const Variant& p_value) { if (p_name=="body_A") - set_body_A(p_value); + set_body_a(p_value); else if (p_name=="body_B") - set_body_B(p_value); + set_body_b(p_value); else if (p_name=="active") set_active(p_value); else if (p_name=="no_collision") @@ -989,9 +990,9 @@ void PhysicsJoint::_set(const String& p_name, const Variant& p_value) { Variant PhysicsJoint::_get(const String& p_name) const { if (p_name=="body_A") - return get_body_A(); + return get_body_a(); else if (p_name=="body_B") - return get_body_B(); + return get_body_b(); else if (p_name=="active") return is_active(); else if (p_name=="no_collision") @@ -1033,7 +1034,7 @@ void PhysicsJoint::_notification(int p_what) { if (indicator.is_valid()) { indicator_instance=VisualServer::get_singleton()->instance_create(indicator,get_world()->get_scenario()); - VisualServer::get_singleton()->instance_attach_object_instance_ID( indicator_instance,get_instance_ID() ); + VisualServer::get_singleton()->instance_attach_object_instance_id( indicator_instance,get_instance_id() ); } } break; case NOTIFICATION_TRANSFORM_CHANGED: { @@ -1066,10 +1067,10 @@ RID PhysicsJoint::_get_visual_instance_rid() const { void PhysicsJoint::_bind_methods() { ClassDB::bind_method(D_METHOD("_get_visual_instance_rid"),&PhysicsJoint::_get_visual_instance_rid); - ClassDB::bind_method(D_METHOD("set_body_A","path"),&PhysicsJoint::set_body_A); - ClassDB::bind_method(D_METHOD("set_body_B"),&PhysicsJoint::set_body_B); - ClassDB::bind_method(D_METHOD("get_body_A","path"),&PhysicsJoint::get_body_A); - ClassDB::bind_method(D_METHOD("get_body_B"),&PhysicsJoint::get_body_B); + ClassDB::bind_method(D_METHOD("set_body_a","path"),&PhysicsJoint::set_body_a); + ClassDB::bind_method(D_METHOD("set_body_b"),&PhysicsJoint::set_body_b); + ClassDB::bind_method(D_METHOD("get_body_a","path"),&PhysicsJoint::get_body_a); + ClassDB::bind_method(D_METHOD("get_body_b"),&PhysicsJoint::get_body_b); ClassDB::bind_method(D_METHOD("set_active","active"),&PhysicsJoint::set_active); ClassDB::bind_method(D_METHOD("is_active"),&PhysicsJoint::is_active); @@ -1084,14 +1085,14 @@ void PhysicsJoint::_bind_methods() { } -void PhysicsJoint::set_body_A(const NodePath& p_path) { +void PhysicsJoint::set_body_a(const NodePath& p_path) { _disconnect(); body_A=p_path; _connect(); _change_notify("body_A"); } -void PhysicsJoint::set_body_B(const NodePath& p_path) { +void PhysicsJoint::set_body_b(const NodePath& p_path) { _disconnect(); body_B=p_path; @@ -1099,11 +1100,11 @@ void PhysicsJoint::set_body_B(const NodePath& p_path) { _change_notify("body_B"); } -NodePath PhysicsJoint::get_body_A() const { +NodePath PhysicsJoint::get_body_a() const { return body_A; } -NodePath PhysicsJoint::get_body_B() const { +NodePath PhysicsJoint::get_body_b() const { return body_B; } diff --git a/scene/3d/physics_joint.h b/scene/3d/physics_joint.h index 90d86d652..b834aaf6d 100644 --- a/scene/3d/physics_joint.h +++ b/scene/3d/physics_joint.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -353,10 +354,10 @@ protected: void _connect(); public: - void set_body_A(const NodePath& p_path); - void set_body_B(const NodePath& p_path); - NodePath get_body_A() const; - NodePath get_body_B() const; + void set_body_a(const NodePath& p_path); + void set_body_b(const NodePath& p_path); + NodePath get_body_a() const; + NodePath get_body_b() const; void set_active(bool p_active); bool is_active() const; diff --git a/scene/3d/portal.cpp b/scene/3d/portal.cpp index 391a74ec4..d77dde1dd 100644 --- a/scene/3d/portal.cpp +++ b/scene/3d/portal.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -27,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "portal.h" -#include "global_config.h" +#include "project_settings.h" #include "scene/resources/surface_tool.h" #include "servers/visual_server.h" diff --git a/scene/3d/portal.h b/scene/3d/portal.h index 018708308..7c25e4904 100644 --- a/scene/3d/portal.h +++ b/scene/3d/portal.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/position_3d.cpp b/scene/3d/position_3d.cpp index ee09ed93a..4e66ef13c 100644 --- a/scene/3d/position_3d.cpp +++ b/scene/3d/position_3d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/position_3d.h b/scene/3d/position_3d.h index dae94dfba..0adde1934 100644 --- a/scene/3d/position_3d.h +++ b/scene/3d/position_3d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/proximity_group.cpp b/scene/3d/proximity_group.cpp index f1225b690..d0410f2c5 100644 --- a/scene/3d/proximity_group.cpp +++ b/scene/3d/proximity_group.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -115,9 +116,9 @@ void ProximityGroup::set_group_name(String p_group_name) { group_name = p_group_name; }; -void ProximityGroup::_notification(int what) { +void ProximityGroup::_notification(int p_what) { - switch (what) { + switch (p_what) { case NOTIFICATION_EXIT_TREE: ++group_version; diff --git a/scene/3d/proximity_group.h b/scene/3d/proximity_group.h index f40ffe2ff..fec3add41 100644 --- a/scene/3d/proximity_group.h +++ b/scene/3d/proximity_group.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/quad.cpp b/scene/3d/quad.cpp deleted file mode 100644 index e32320681..000000000 --- a/scene/3d/quad.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/*************************************************************************/ -/* quad.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "quad.h" -#include "servers/visual_server.h" - -void Quad::_update() { - - if (!is_inside_tree()) - return; - - Vector3 normal; - normal[axis] = 1.0; - - const int axis_order_1[3] = { 1, 2, 0 }; - const int axis_order_2[3] = { 2, 0, 1 }; - const int a1 = axis_order_1[axis]; - const int a2 = axis_order_2[axis]; - - PoolVector<Vector3> points; - points.resize(4); - PoolVector<Vector3>::Write pointsw = points.write(); - - Vector2 s2 = size * 0.5; - Vector2 o = offset; - if (!centered) - o += s2; - - pointsw[0][a1] = -s2.x + offset.x; - pointsw[0][a2] = s2.y + offset.y; - - pointsw[1][a1] = s2.x + offset.x; - pointsw[1][a2] = s2.y + offset.y; - - pointsw[2][a1] = s2.x + offset.x; - pointsw[2][a2] = -s2.y + offset.y; - - pointsw[3][a1] = -s2.x + offset.x; - pointsw[3][a2] = -s2.y + offset.y; - - aabb = Rect3(pointsw[0], Vector3()); - for (int i = 1; i < 4; i++) - aabb.expand_to(pointsw[i]); - - pointsw = PoolVector<Vector3>::Write(); - - PoolVector<Vector3> normals; - normals.resize(4); - PoolVector<Vector3>::Write normalsw = normals.write(); - - for (int i = 0; i < 4; i++) - normalsw[i] = normal; - - normalsw = PoolVector<Vector3>::Write(); - - PoolVector<Vector2> uvs; - uvs.resize(4); - PoolVector<Vector2>::Write uvsw = uvs.write(); - - uvsw[0] = Vector2(0, 0); - uvsw[1] = Vector2(1, 0); - uvsw[2] = Vector2(1, 1); - uvsw[3] = Vector2(0, 1); - - uvsw = PoolVector<Vector2>::Write(); - - PoolVector<int> indices; - indices.resize(6); - - PoolVector<int>::Write indicesw = indices.write(); - indicesw[0] = 0; - indicesw[1] = 1; - indicesw[2] = 2; - indicesw[3] = 2; - indicesw[4] = 3; - indicesw[5] = 0; - - indicesw = PoolVector<int>::Write(); - - Array arr; - arr.resize(VS::ARRAY_MAX); - arr[VS::ARRAY_VERTEX] = points; - arr[VS::ARRAY_NORMAL] = normals; - arr[VS::ARRAY_TEX_UV] = uvs; - arr[VS::ARRAY_INDEX] = indices; - - if (configured) { - VS::get_singleton()->mesh_remove_surface(mesh, 0); - } else { - configured = true; - } - VS::get_singleton()->mesh_add_surface_from_arrays(mesh, VS::PRIMITIVE_TRIANGLES, arr); - - pending_update = false; -} - -void Quad::set_axis(Vector3::Axis p_axis) { - - axis = p_axis; - _update(); -} - -Vector3::Axis Quad::get_axis() const { - - return axis; -} - -void Quad::set_size(const Vector2 &p_size) { - - size = p_size; - _update(); -} -Vector2 Quad::get_size() const { - - return size; -} - -void Quad::set_offset(const Vector2 &p_offset) { - - offset = p_offset; - _update(); -} -Vector2 Quad::get_offset() const { - - return offset; -} - -void Quad::set_centered(bool p_enabled) { - - centered = p_enabled; - _update(); -} -bool Quad::is_centered() const { - - return centered; -} - -void Quad::_notification(int p_what) { - - switch (p_what) { - - case NOTIFICATION_ENTER_TREE: { - - if (pending_update) - _update(); - - } break; - case NOTIFICATION_EXIT_TREE: { - - pending_update = true; - - } break; - } -} - -PoolVector<Face3> Quad::get_faces(uint32_t p_usage_flags) const { - - return PoolVector<Face3>(); -} - -Rect3 Quad::get_aabb() const { - - return aabb; -} - -void Quad::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_axis", "axis"), &Quad::set_axis); - ClassDB::bind_method(D_METHOD("get_axis"), &Quad::get_axis); - - ClassDB::bind_method(D_METHOD("set_size", "size"), &Quad::set_size); - ClassDB::bind_method(D_METHOD("get_size"), &Quad::get_size); - - ClassDB::bind_method(D_METHOD("set_centered", "centered"), &Quad::set_centered); - ClassDB::bind_method(D_METHOD("is_centered"), &Quad::is_centered); - - ClassDB::bind_method(D_METHOD("set_offset", "offset"), &Quad::set_offset); - ClassDB::bind_method(D_METHOD("get_offset"), &Quad::get_offset); - - ADD_PROPERTY(PropertyInfo(Variant::INT, "axis", PROPERTY_HINT_ENUM, "X,Y,Z"), "set_axis", "get_axis"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "centered"), "set_centered", "is_centered"); -} - -Quad::Quad() { - - pending_update = true; - centered = true; - //offset=0; - size = Vector2(1, 1); - axis = Vector3::AXIS_Z; - mesh = VisualServer::get_singleton()->mesh_create(); - set_base(mesh); - configured = false; -} - -Quad::~Quad() { - VisualServer::get_singleton()->free(mesh); -} diff --git a/scene/3d/quad.h b/scene/3d/quad.h deleted file mode 100644 index 607d7238e..000000000 --- a/scene/3d/quad.h +++ /dev/null @@ -1,75 +0,0 @@ -/*************************************************************************/ -/* quad.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef QUAD_H -#define QUAD_H - -#include "rid.h" -#include "scene/3d/visual_instance.h" - -class Quad : public GeometryInstance { - - GDCLASS(Quad, GeometryInstance); - - Vector3::Axis axis; - bool centered; - Vector2 offset; - Vector2 size; - - Rect3 aabb; - bool configured; - bool pending_update; - RID mesh; - - void _update(); - -protected: - void _notification(int p_what); - static void _bind_methods(); - -public: - void set_axis(Vector3::Axis p_axis); - Vector3::Axis get_axis() const; - - void set_size(const Vector2 &p_sizze); - Vector2 get_size() const; - - void set_offset(const Vector2 &p_offset); - Vector2 get_offset() const; - - void set_centered(bool p_enabled); - bool is_centered() const; - - virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const; - virtual Rect3 get_aabb() const; - - Quad(); - ~Quad(); -}; - -#endif // QUAD_H diff --git a/scene/3d/ray_cast.cpp b/scene/3d/ray_cast.cpp index a73114a7c..67e7fb0e1 100644 --- a/scene/3d/ray_cast.cpp +++ b/scene/3d/ray_cast.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,12 +30,15 @@ #include "ray_cast.h" #include "collision_object.h" +#include "mesh_instance.h" #include "servers/physics_server.h" void RayCast::set_cast_to(const Vector3 &p_point) { cast_to = p_point; if (is_inside_tree() && (get_tree()->is_editor_hint() || get_tree()->is_debugging_collisions_hint())) update_gizmo(); + if (is_inside_tree() && get_tree()->is_debugging_collisions_hint()) + _update_debug_shape(); } Vector3 RayCast::get_cast_to() const { @@ -42,14 +46,14 @@ Vector3 RayCast::get_cast_to() const { return cast_to; } -void RayCast::set_layer_mask(uint32_t p_mask) { +void RayCast::set_collision_layer(uint32_t p_layer) { - layer_mask = p_mask; + collision_layer = p_layer; } -uint32_t RayCast::get_layer_mask() const { +uint32_t RayCast::get_collision_layer() const { - return layer_mask; + return collision_layer; } void RayCast::set_type_mask(uint32_t p_mask) { @@ -94,6 +98,13 @@ void RayCast::set_enabled(bool p_enabled) { set_fixed_process(p_enabled); if (!p_enabled) collided = false; + + if (is_inside_tree() && get_tree()->is_debugging_collisions_hint()) { + if (p_enabled) + _update_debug_shape(); + else + _clear_debug_shape(); + } } bool RayCast::is_enabled() const { @@ -109,6 +120,9 @@ void RayCast::_notification(int p_what) { if (enabled && !get_tree()->is_editor_hint()) { set_fixed_process(true); + + if (get_tree()->is_debugging_collisions_hint()) + _update_debug_shape(); } else set_fixed_process(false); @@ -119,13 +133,23 @@ void RayCast::_notification(int p_what) { set_fixed_process(false); } + if (debug_shape) + _clear_debug_shape(); + } break; case NOTIFICATION_FIXED_PROCESS: { if (!enabled) break; + bool prev_collision_state = collided; _update_raycast_state(); + if (prev_collision_state != collided && get_tree()->is_debugging_collisions_hint()) { + if (debug_material.is_valid()) { + Ref<SpatialMaterial> line_material = static_cast<Ref<SpatialMaterial> >(debug_material); + line_material->set_albedo(collided ? Color(1.0, 0, 0) : Color(1.0, 0.8, 0.6)); + } + } } break; } @@ -146,7 +170,7 @@ void RayCast::_update_raycast_state() { PhysicsDirectSpaceState::RayResult rr; - if (dss->intersect_ray(gt.get_origin(), gt.xform(to), rr, exclude, layer_mask, type_mask)) { + if (dss->intersect_ray(gt.get_origin(), gt.xform(to), rr, exclude, collision_layer, type_mask)) { collided = true; against = rr.collider_id; @@ -219,25 +243,88 @@ void RayCast::_bind_methods() { ClassDB::bind_method(D_METHOD("clear_exceptions"), &RayCast::clear_exceptions); - ClassDB::bind_method(D_METHOD("set_layer_mask", "mask"), &RayCast::set_layer_mask); - ClassDB::bind_method(D_METHOD("get_layer_mask"), &RayCast::get_layer_mask); + ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &RayCast::set_collision_layer); + ClassDB::bind_method(D_METHOD("get_collision_layer"), &RayCast::get_collision_layer); ClassDB::bind_method(D_METHOD("set_type_mask", "mask"), &RayCast::set_type_mask); ClassDB::bind_method(D_METHOD("get_type_mask"), &RayCast::get_type_mask); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "cast_to"), "set_cast_to", "get_cast_to"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "layer_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_layer_mask", "get_layer_mask"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer"); ADD_PROPERTY(PropertyInfo(Variant::INT, "type_mask", PROPERTY_HINT_FLAGS, "Static,Kinematic,Rigid,Character,Area"), "set_type_mask", "get_type_mask"); } +void RayCast::_create_debug_shape() { + + if (!debug_material.is_valid()) { + debug_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); + + Ref<SpatialMaterial> line_material = static_cast<Ref<SpatialMaterial> >(debug_material); + line_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + line_material->set_line_width(3.0); + line_material->set_albedo(Color(1.0, 0.8, 0.6)); + } + + Ref<ArrayMesh> mesh = memnew(ArrayMesh); + + MeshInstance *mi = memnew(MeshInstance); + mi->set_mesh(mesh); + + add_child(mi); + debug_shape = mi; +} + +void RayCast::_update_debug_shape() { + + if (!enabled) + return; + + if (!debug_shape) + _create_debug_shape(); + + MeshInstance *mi = static_cast<MeshInstance *>(debug_shape); + if (!mi->get_mesh().is_valid()) + return; + + Ref<ArrayMesh> mesh = mi->get_mesh(); + if (mesh->get_surface_count() > 0) + mesh->surface_remove(0); + + Array a; + a.resize(Mesh::ARRAY_MAX); + + Vector<Vector3> verts; + verts.push_back(Vector3()); + verts.push_back(cast_to); + a[Mesh::ARRAY_VERTEX] = verts; + + mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a); + mesh->surface_set_material(0, debug_material); +} + +void RayCast::_clear_debug_shape() { + + if (!debug_shape) + return; + + MeshInstance *mi = static_cast<MeshInstance *>(debug_shape); + if (mi->is_inside_tree()) + mi->queue_delete(); + else + memdelete(mi); + + debug_shape = NULL; +} + RayCast::RayCast() { enabled = false; against = 0; collided = false; against_shape = 0; - layer_mask = 1; + collision_layer = 1; type_mask = PhysicsDirectSpaceState::TYPE_MASK_COLLISION; cast_to = Vector3(0, -1, 0); + debug_shape = NULL; } diff --git a/scene/3d/ray_cast.h b/scene/3d/ray_cast.h index 00a10446a..e9b34c4f7 100644 --- a/scene/3d/ray_cast.h +++ b/scene/3d/ray_cast.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -46,9 +47,16 @@ class RayCast : public Spatial { Set<RID> exclude; - uint32_t layer_mask; + uint32_t collision_layer; uint32_t type_mask; + Node *debug_shape; + Ref<Material> debug_material; + + void _create_debug_shape(); + void _update_debug_shape(); + void _clear_debug_shape(); + protected: void _notification(int p_what); void _update_raycast_state(); @@ -61,8 +69,8 @@ public: void set_cast_to(const Vector3 &p_point); Vector3 get_cast_to() const; - void set_layer_mask(uint32_t p_mask); - uint32_t get_layer_mask() const; + void set_collision_layer(uint32_t p_layer); + uint32_t get_collision_layer() const; void set_type_mask(uint32_t p_mask); uint32_t get_type_mask() const; diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp index 90dbd5127..0dc5b58e4 100644 --- a/scene/3d/reflection_probe.cpp +++ b/scene/3d/reflection_probe.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -161,7 +162,7 @@ bool ReflectionProbe::are_shadows_enabled() const { void ReflectionProbe::set_cull_mask(uint32_t p_layers) { cull_mask = p_layers; - VS::get_singleton()->reflection_probe_set_enable_shadows(probe, p_layers); + VS::get_singleton()->reflection_probe_set_cull_mask(probe, p_layers); } uint32_t ReflectionProbe::get_cull_mask() const { @@ -180,7 +181,7 @@ ReflectionProbe::UpdateMode ReflectionProbe::get_update_mode() const { Rect3 ReflectionProbe::get_aabb() const { Rect3 aabb; - aabb.pos = -origin_offset; + aabb.position = -origin_offset; aabb.size = origin_offset + extents; return aabb; } diff --git a/scene/3d/reflection_probe.h b/scene/3d/reflection_probe.h index a2e4a18d6..d2a5facb5 100644 --- a/scene/3d/reflection_probe.h +++ b/scene/3d/reflection_probe.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/remote_transform.cpp b/scene/3d/remote_transform.cpp index 202206dd0..492930ea9 100644 --- a/scene/3d/remote_transform.cpp +++ b/scene/3d/remote_transform.cpp @@ -7,6 +7,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -38,7 +39,7 @@ void RemoteTransform::_update_cache() { return; } - cache = node->get_instance_ID(); + cache = node->get_instance_id(); } } @@ -62,7 +63,45 @@ void RemoteTransform::_update_remote() { return; //todo make faster - n->set_global_transform(get_global_transform()); + if (use_global_coordinates) { + + if (update_remote_position && update_remote_rotation && update_remote_scale) { + n->set_global_transform(get_global_transform()); + } else { + Transform n_trans = n->get_global_transform(); + Transform our_trans = get_global_transform(); + + if (!update_remote_position) + our_trans.set_origin(n_trans.get_origin()); + + n->set_global_transform(our_trans); + + if (!update_remote_rotation) + n->set_rotation(n_trans.basis.get_rotation()); + + if (!update_remote_scale) + n->set_scale(n_trans.basis.get_scale()); + } + + } else { + if (update_remote_position && update_remote_rotation && update_remote_scale) { + n->set_global_transform(get_global_transform()); + } else { + Transform n_trans = n->get_transform(); + Transform our_trans = get_transform(); + + if (!update_remote_position) + our_trans.set_origin(n_trans.get_origin()); + + n->set_transform(our_trans); + + if (!update_remote_rotation) + n->set_rotation(n_trans.basis.get_rotation()); + + if (!update_remote_scale) + n->set_scale(n_trans.basis.get_scale()); + } + } } void RemoteTransform::_notification(int p_what) { @@ -101,6 +140,41 @@ NodePath RemoteTransform::get_remote_node() const { return remote_node; } +void RemoteTransform::set_use_global_coordinates(const bool p_enable) { + use_global_coordinates = p_enable; +} + +bool RemoteTransform::get_use_global_coordinates() const { + return use_global_coordinates; +} + +void RemoteTransform::set_update_position(const bool p_update) { + update_remote_position = p_update; + _update_remote(); +} + +bool RemoteTransform::get_update_position() const { + return update_remote_position; +} + +void RemoteTransform::set_update_rotation(const bool p_update) { + update_remote_rotation = p_update; + _update_remote(); +} + +bool RemoteTransform::get_update_rotation() const { + return update_remote_rotation; +} + +void RemoteTransform::set_update_scale(const bool p_update) { + update_remote_scale = p_update; + _update_remote(); +} + +bool RemoteTransform::get_update_scale() const { + return update_remote_scale; +} + String RemoteTransform::get_configuration_warning() const { if (!has_node(remote_node) || !get_node(remote_node) || !get_node(remote_node)->cast_to<Spatial>()) { @@ -115,11 +189,32 @@ void RemoteTransform::_bind_methods() { ClassDB::bind_method(D_METHOD("set_remote_node", "path"), &RemoteTransform::set_remote_node); ClassDB::bind_method(D_METHOD("get_remote_node"), &RemoteTransform::get_remote_node); + ClassDB::bind_method(D_METHOD("set_use_global_coordinates", "use_global_coordinates"), &RemoteTransform::set_use_global_coordinates); + ClassDB::bind_method(D_METHOD("get_use_global_coordinates"), &RemoteTransform::get_use_global_coordinates); + + ClassDB::bind_method(D_METHOD("set_update_position", "update_remote_position"), &RemoteTransform::set_update_position); + ClassDB::bind_method(D_METHOD("get_update_position"), &RemoteTransform::get_update_position); + ClassDB::bind_method(D_METHOD("set_update_rotation", "update_remote_rotation"), &RemoteTransform::set_update_rotation); + ClassDB::bind_method(D_METHOD("get_update_rotation"), &RemoteTransform::get_update_rotation); + ClassDB::bind_method(D_METHOD("set_update_scale", "update_remote_scale"), &RemoteTransform::set_update_scale); + ClassDB::bind_method(D_METHOD("get_update_scale"), &RemoteTransform::get_update_scale); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "remote_path"), "set_remote_node", "get_remote_node"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_global_coordinates"), "set_use_global_coordinates", "get_use_global_coordinates"); + + ADD_GROUP("Update", "update_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_position"), "set_update_position", "get_update_position"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_rotation"), "set_update_rotation", "get_update_rotation"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_scale"), "set_update_scale", "get_update_scale"); } RemoteTransform::RemoteTransform() { + use_global_coordinates = true; + update_remote_position = true; + update_remote_rotation = true; + update_remote_scale = true; + cache = 0; set_notify_transform(true); } diff --git a/scene/3d/remote_transform.h b/scene/3d/remote_transform.h index fdfd959a9..c25b57966 100644 --- a/scene/3d/remote_transform.h +++ b/scene/3d/remote_transform.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -38,6 +39,11 @@ class RemoteTransform : public Spatial { ObjectID cache; + bool use_global_coordinates; + bool update_remote_position; + bool update_remote_rotation; + bool update_remote_scale; + void _update_remote(); void _update_cache(); @@ -49,6 +55,18 @@ public: void set_remote_node(const NodePath &p_remote_node); NodePath get_remote_node() const; + void set_use_global_coordinates(const bool p_enable); + bool get_use_global_coordinates() const; + + void set_update_position(const bool p_update); + bool get_update_position() const; + + void set_update_rotation(const bool p_update); + bool get_update_rotation() const; + + void set_update_scale(const bool p_update); + bool get_update_scale() const; + virtual String get_configuration_warning() const; RemoteTransform(); diff --git a/scene/3d/room_instance.cpp b/scene/3d/room_instance.cpp index 3b6ae32d1..c5ea6c54d 100644 --- a/scene/3d/room_instance.cpp +++ b/scene/3d/room_instance.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +32,7 @@ #include "servers/visual_server.h" #include "geometry.h" -#include "global_config.h" +#include "project_settings.h" #include "scene/resources/surface_tool.h" void Room::_notification(int p_what) { @@ -142,8 +143,8 @@ void Room::_bounds_changed() { void Room::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_room", "room:Room"), &Room::set_room); - ClassDB::bind_method(D_METHOD("get_room:Room"), &Room::get_room); + ClassDB::bind_method(D_METHOD("set_room", "room"), &Room::set_room); + ClassDB::bind_method(D_METHOD("get_room"), &Room::get_room); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "room/room", PROPERTY_HINT_RESOURCE_TYPE, "Area"), "set_room", "get_room"); } diff --git a/scene/3d/room_instance.h b/scene/3d/room_instance.h index 68be5eecf..4176da92e 100644 --- a/scene/3d/room_instance.h +++ b/scene/3d/room_instance.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/scenario_fx.cpp b/scene/3d/scenario_fx.cpp index 92ee608f7..0780ce22f 100644 --- a/scene/3d/scenario_fx.cpp +++ b/scene/3d/scenario_fx.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -27,43 +28,44 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "scenario_fx.h" +#include "scene/main/viewport.h" void WorldEnvironment::_notification(int p_what) { - if (p_what == NOTIFICATION_ENTER_WORLD) { + if (p_what == Spatial::NOTIFICATION_ENTER_WORLD || p_what == Spatial::NOTIFICATION_ENTER_TREE) { if (environment.is_valid()) { - if (get_world()->get_environment().is_valid()) { + if (get_viewport()->find_world()->get_environment().is_valid()) { WARN_PRINT("World already has an environment (Another WorldEnvironment?), overriding."); } - get_world()->set_environment(environment); - add_to_group("_world_environment_" + itos(get_world()->get_scenario().get_id())); + get_viewport()->find_world()->set_environment(environment); + add_to_group("_world_environment_" + itos(get_viewport()->find_world()->get_scenario().get_id())); } - } else if (p_what == NOTIFICATION_EXIT_WORLD) { + } else if (p_what == Spatial::NOTIFICATION_EXIT_WORLD || p_what == Spatial::NOTIFICATION_EXIT_TREE) { - if (environment.is_valid() && get_world()->get_environment() == environment) { - get_world()->set_environment(Ref<Environment>()); - remove_from_group("_world_environment_" + itos(get_world()->get_scenario().get_id())); + if (environment.is_valid() && get_viewport()->find_world()->get_environment() == environment) { + get_viewport()->find_world()->set_environment(Ref<Environment>()); + remove_from_group("_world_environment_" + itos(get_viewport()->find_world()->get_scenario().get_id())); } } } void WorldEnvironment::set_environment(const Ref<Environment> &p_environment) { - if (is_inside_world() && environment.is_valid() && get_world()->get_environment() == environment) { - get_world()->set_environment(Ref<Environment>()); - remove_from_group("_world_environment_" + itos(get_world()->get_scenario().get_id())); + if (is_inside_tree() && environment.is_valid() && get_viewport()->find_world()->get_environment() == environment) { + get_viewport()->find_world()->set_environment(Ref<Environment>()); + remove_from_group("_world_environment_" + itos(get_viewport()->find_world()->get_scenario().get_id())); //clean up } environment = p_environment; - if (is_inside_world() && environment.is_valid()) { - if (get_world()->get_environment().is_valid()) { + if (is_inside_tree() && environment.is_valid()) { + if (get_viewport()->find_world()->get_environment().is_valid()) { WARN_PRINT("World already has an environment (Another WorldEnvironment?), overriding."); } - get_world()->set_environment(environment); - add_to_group("_world_environment_" + itos(get_world()->get_scenario().get_id())); + get_viewport()->find_world()->set_environment(environment); + add_to_group("_world_environment_" + itos(get_viewport()->find_world()->get_scenario().get_id())); } update_configuration_warning(); @@ -76,11 +78,11 @@ Ref<Environment> WorldEnvironment::get_environment() const { String WorldEnvironment::get_configuration_warning() const { - if (!is_visible_in_tree() || !is_inside_tree() || !environment.is_valid()) + if (/*!is_visible_in_tree() ||*/ !is_inside_tree() || !environment.is_valid()) return String(); List<Node *> nodes; - get_tree()->get_nodes_in_group("_world_environment_" + itos(get_world()->get_scenario().get_id()), &nodes); + get_tree()->get_nodes_in_group("_world_environment_" + itos(get_viewport()->find_world()->get_scenario().get_id()), &nodes); if (nodes.size() > 1) { return TTR("Only one WorldEnvironment is allowed per scene (or set of instanced scenes)."); @@ -91,8 +93,8 @@ String WorldEnvironment::get_configuration_warning() const { void WorldEnvironment::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_environment", "env:Environment"), &WorldEnvironment::set_environment); - ClassDB::bind_method(D_METHOD("get_environment:Environment"), &WorldEnvironment::get_environment); + ClassDB::bind_method(D_METHOD("set_environment", "env"), &WorldEnvironment::set_environment); + ClassDB::bind_method(D_METHOD("get_environment"), &WorldEnvironment::get_environment); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_environment", "get_environment"); } diff --git a/scene/3d/scenario_fx.h b/scene/3d/scenario_fx.h index bbdffdc13..d1e0a6313 100644 --- a/scene/3d/scenario_fx.h +++ b/scene/3d/scenario_fx.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -35,9 +36,9 @@ @author Juan Linietsky <reduzio@gmail.com> */ -class WorldEnvironment : public Spatial { +class WorldEnvironment : public Node { - GDCLASS(WorldEnvironment, Spatial); + GDCLASS(WorldEnvironment, Node); Ref<Environment> environment; diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp index 3a5453c8e..cee97af24 100644 --- a/scene/3d/skeleton.cpp +++ b/scene/3d/skeleton.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +31,7 @@ #include "message_queue.h" -#include "core/global_config.h" +#include "core/project_settings.h" #include "scene/resources/surface_tool.h" bool Skeleton::_set(const StringName &p_path, const Variant &p_value) { @@ -81,9 +82,9 @@ bool Skeleton::_set(const StringName &p_path, const Variant &p_value) { return true; } -bool Skeleton::_get(const StringName &p_name, Variant &r_ret) const { +bool Skeleton::_get(const StringName &p_path, Variant &r_ret) const { - String path = p_name; + String path = p_path; if (!path.begins_with("bones/")) return false; @@ -406,7 +407,7 @@ void Skeleton::bind_child_node_to_bone(int p_bone, Node *p_node) { ERR_FAIL_NULL(p_node); ERR_FAIL_INDEX(p_bone, bones.size()); - uint32_t id = p_node->get_instance_ID(); + uint32_t id = p_node->get_instance_id(); for (List<uint32_t>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) { @@ -421,7 +422,7 @@ void Skeleton::unbind_child_node_from_bone(int p_bone, Node *p_node) { ERR_FAIL_NULL(p_node); ERR_FAIL_INDEX(p_bone, bones.size()); - uint32_t id = p_node->get_instance_ID(); + uint32_t id = p_node->get_instance_id(); bones[p_bone].nodes_bound.erase(id); } void Skeleton::get_bound_child_nodes_to_bone(int p_bone, List<Node *> *p_bound) const { @@ -517,8 +518,8 @@ void Skeleton::_bind_methods() { ClassDB::bind_method(D_METHOD("set_bone_disable_rest", "bone_idx", "disable"), &Skeleton::set_bone_disable_rest); ClassDB::bind_method(D_METHOD("is_bone_rest_disabled", "bone_idx"), &Skeleton::is_bone_rest_disabled); - ClassDB::bind_method(D_METHOD("bind_child_node_to_bone", "bone_idx", "node:Node"), &Skeleton::bind_child_node_to_bone); - ClassDB::bind_method(D_METHOD("unbind_child_node_from_bone", "bone_idx", "node:Node"), &Skeleton::unbind_child_node_from_bone); + ClassDB::bind_method(D_METHOD("bind_child_node_to_bone", "bone_idx", "node"), &Skeleton::bind_child_node_to_bone); + ClassDB::bind_method(D_METHOD("unbind_child_node_from_bone", "bone_idx", "node"), &Skeleton::unbind_child_node_from_bone); ClassDB::bind_method(D_METHOD("get_bound_child_nodes_to_bone", "bone_idx"), &Skeleton::_get_bound_child_nodes_to_bone); ClassDB::bind_method(D_METHOD("clear_bones"), &Skeleton::clear_bones); diff --git a/scene/3d/skeleton.h b/scene/3d/skeleton.h index 707428972..a6546af64 100644 --- a/scene/3d/skeleton.h +++ b/scene/3d/skeleton.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -90,8 +91,8 @@ class Skeleton : public Spatial { } protected: - bool _get(const StringName &p_name, Variant &r_ret) const; - bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_path, Variant &r_ret) const; + bool _set(const StringName &p_path, const Variant &p_value); void _get_property_list(List<PropertyInfo> *p_list) const; void _notification(int p_what); static void _bind_methods(); @@ -112,7 +113,7 @@ public: void set_bone_parent(int p_bone, int p_parent); int get_bone_parent(int p_bone) const; - void unparent_bone_and_rest(int p_idx); + void unparent_bone_and_rest(int p_bone); void set_bone_disable_rest(int p_bone, bool p_disable); bool is_bone_rest_disabled(int p_bone) const; diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp index 1125a7a4d..848b08eb8 100644 --- a/scene/3d/spatial.cpp +++ b/scene/3d/spatial.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -71,8 +72,12 @@ SpatialGizmo::SpatialGizmo() { void Spatial::_notify_dirty() { +#ifdef TOOLS_ENABLED + if ((data.gizmo.is_valid() || data.notify_transform) && !data.ignore_notification && !xform_change.in_list()) { +#else if (data.notify_transform && !data.ignore_notification && !xform_change.in_list()) { +#endif get_tree()->xform_change_list.add(&xform_change); } } @@ -103,9 +108,11 @@ void Spatial::_propagate_transform_changed(Spatial *p_origin) { continue; //don't propagate to a toplevel E->get()->_propagate_transform_changed(p_origin); } - +#ifdef TOOLS_ENABLED + if ((data.gizmo.is_valid() || data.notify_transform) && !data.ignore_notification && !xform_change.in_list()) { +#else if (data.notify_transform && !data.ignore_notification && !xform_change.in_list()) { - +#endif get_tree()->xform_change_list.add(&xform_change); } data.dirty |= DIRTY_GLOBAL; @@ -220,9 +227,10 @@ void Spatial::set_transform(const Transform &p_transform) { data.local_transform = p_transform; data.dirty |= DIRTY_VECTORS; - _change_notify("transform/translation"); - _change_notify("transform/rotation"); - _change_notify("transform/scale"); + _change_notify("translation"); + _change_notify("rotation"); + _change_notify("rotation_deg"); + _change_notify("scale"); _propagate_transform_changed(this); if (data.notify_local_transform) { notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); @@ -510,22 +518,11 @@ Ref<World> Spatial::get_world() const { return data.viewport->find_world(); } -#ifdef TOOLS_ENABLED -void Spatial::set_import_transform(const Transform &p_transform) { - data.import_transform = p_transform; -} - -Transform Spatial::get_import_transform() const { - - return data.import_transform; -} -#endif - void Spatial::_propagate_visibility_changed() { notification(NOTIFICATION_VISIBILITY_CHANGED); emit_signal(SceneStringNames::get_singleton()->visibility_changed); - _change_notify("visibility/visible"); + _change_notify("visible"); #ifdef TOOLS_ENABLED if (data.gizmo.is_valid()) _update_gizmo(); @@ -550,10 +547,7 @@ void Spatial::show() { if (!is_inside_tree()) return; - if (!data.parent || is_visible_in_tree()) { - - _propagate_visibility_changed(); - } + _propagate_visibility_changed(); } void Spatial::hide() { @@ -561,14 +555,14 @@ void Spatial::hide() { if (!data.visible) return; - bool was_visible = is_visible_in_tree(); data.visible = false; - if (!data.parent || was_visible) { + if (!is_inside_tree()) + return; - _propagate_visibility_changed(); - } + _propagate_visibility_changed(); } + bool Spatial::is_visible_in_tree() const { const Spatial *s = this; @@ -686,6 +680,16 @@ void Spatial::look_at_from_pos(const Vector3 &p_pos, const Vector3 &p_target, co set_global_transform(lookat); } +Vector3 Spatial::to_local(Vector3 p_global) const { + + return get_global_transform().affine_inverse().xform(p_global); +} + +Vector3 Spatial::to_global(Vector3 p_local) const { + + return get_global_transform().xform(p_local); +} + void Spatial::set_notify_transform(bool p_enable) { data.notify_transform = p_enable; } @@ -720,7 +724,7 @@ void Spatial::_bind_methods() { ClassDB::bind_method(D_METHOD("set_ignore_transform_notification", "enabled"), &Spatial::set_ignore_transform_notification); ClassDB::bind_method(D_METHOD("set_as_toplevel", "enable"), &Spatial::set_as_toplevel); ClassDB::bind_method(D_METHOD("is_set_as_toplevel"), &Spatial::is_set_as_toplevel); - ClassDB::bind_method(D_METHOD("get_world:World"), &Spatial::get_world); + ClassDB::bind_method(D_METHOD("get_world"), &Spatial::get_world); // TODO: Obsolete those two methods (old name) properly (GH-4397) ClassDB::bind_method(D_METHOD("_set_rotation_deg", "rotation_deg"), &Spatial::_set_rotation_deg); @@ -728,16 +732,13 @@ void Spatial::_bind_methods() { #ifdef TOOLS_ENABLED ClassDB::bind_method(D_METHOD("_update_gizmo"), &Spatial::_update_gizmo); - ClassDB::bind_method(D_METHOD("_set_import_transform"), &Spatial::set_import_transform); - ClassDB::bind_method(D_METHOD("_get_import_transform"), &Spatial::get_import_transform); - ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "_import_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_import_transform", "_get_import_transform"); #endif ClassDB::bind_method(D_METHOD("update_gizmo"), &Spatial::update_gizmo); - ClassDB::bind_method(D_METHOD("set_gizmo", "gizmo:SpatialGizmo"), &Spatial::set_gizmo); - ClassDB::bind_method(D_METHOD("get_gizmo:SpatialGizmo"), &Spatial::get_gizmo); + ClassDB::bind_method(D_METHOD("set_gizmo", "gizmo"), &Spatial::set_gizmo); + ClassDB::bind_method(D_METHOD("get_gizmo"), &Spatial::get_gizmo); - ClassDB::bind_method(D_METHOD("set_visible"), &Spatial::set_visible); + ClassDB::bind_method(D_METHOD("set_visible", "visible"), &Spatial::set_visible); ClassDB::bind_method(D_METHOD("is_visible"), &Spatial::is_visible); ClassDB::bind_method(D_METHOD("is_visible_in_tree"), &Spatial::is_visible_in_tree); ClassDB::bind_method(D_METHOD("show"), &Spatial::show); @@ -771,6 +772,9 @@ void Spatial::_bind_methods() { ClassDB::bind_method(D_METHOD("look_at", "target", "up"), &Spatial::look_at); ClassDB::bind_method(D_METHOD("look_at_from_pos", "pos", "target", "up"), &Spatial::look_at_from_pos); + ClassDB::bind_method(D_METHOD("to_local", "global_point"), &Spatial::to_local); + ClassDB::bind_method(D_METHOD("to_global", "local_point"), &Spatial::to_global); + BIND_CONSTANT(NOTIFICATION_TRANSFORM_CHANGED); BIND_CONSTANT(NOTIFICATION_ENTER_WORLD); BIND_CONSTANT(NOTIFICATION_EXIT_WORLD); diff --git a/scene/3d/spatial.h b/scene/3d/spatial.h index e5817883d..f22b19d3c 100644 --- a/scene/3d/spatial.h +++ b/scene/3d/spatial.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +31,7 @@ #define SPATIAL_H #include "scene/main/node.h" -#include "scene/main/scene_main_loop.h" +#include "scene/main/scene_tree.h" /** @author Juan Linietsky <reduzio@gmail.com> @@ -94,7 +95,6 @@ class Spatial : public Node { Ref<SpatialGizmo> gizmo; bool gizmo_disabled; bool gizmo_dirty; - Transform import_transform; #endif } data; @@ -173,6 +173,9 @@ public: void look_at(const Vector3 &p_target, const Vector3 &p_up_normal); void look_at_from_pos(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up_normal); + Vector3 to_local(Vector3 p_global) const; + Vector3 to_global(Vector3 p_local) const; + void set_notify_transform(bool p_enable); bool is_transform_notification_enabled() const; @@ -188,11 +191,6 @@ public: void hide(); bool is_visible_in_tree() const; -#ifdef TOOLS_ENABLED - void set_import_transform(const Transform &p_transform); - Transform get_import_transform() const; -#endif - Spatial(); ~Spatial(); }; diff --git a/scene/3d/spatial_indexer.cpp b/scene/3d/spatial_indexer.cpp index cddbf9a4e..7090c974a 100644 --- a/scene/3d/spatial_indexer.cpp +++ b/scene/3d/spatial_indexer.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/spatial_indexer.h b/scene/3d/spatial_indexer.h index 94c579ba2..c8bdf8950 100644 --- a/scene/3d/spatial_indexer.h +++ b/scene/3d/spatial_indexer.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/spatial_velocity_tracker.cpp b/scene/3d/spatial_velocity_tracker.cpp new file mode 100644 index 000000000..dc822d044 --- /dev/null +++ b/scene/3d/spatial_velocity_tracker.cpp @@ -0,0 +1,104 @@ +#include "spatial_velocity_tracker.h" +#include "engine.h" + +void SpatialVelocityTracker::set_track_fixed_step(bool p_track_fixed_step) { + + fixed_step = p_track_fixed_step; +} + +bool SpatialVelocityTracker::is_tracking_fixed_step() const { + + return fixed_step; +} +void SpatialVelocityTracker::update_position(const Vector3 &p_position) { + + PositionHistory ph; + ph.position = p_position; + if (fixed_step) { + ph.frame = Engine::get_singleton()->get_fixed_frames(); + } else { + ph.frame = Engine::get_singleton()->get_idle_frame_ticks(); + } + + if (position_history_len == 0 || position_history[0].frame != ph.frame) { //in same frame, use latest + position_history_len = MIN(position_history.size(), position_history_len + 1); + for (int i = position_history_len - 1; i > 0; i--) { + position_history[i] = position_history[i - 1]; + } + } + + position_history[0] = ph; +} +Vector3 SpatialVelocityTracker::get_tracked_linear_velocity() const { + + Vector3 linear_velocity; + + float max_time = 1 / 5.0; //maximum time to interpolate a velocity + + Vector3 distance_accum; + float time_accum = 0.0; + float base_time = 0.0; + + if (position_history_len) { + if (fixed_step) { + uint64_t base = Engine::get_singleton()->get_fixed_frames(); + base_time = float(base - position_history[0].frame) / Engine::get_singleton()->get_iterations_per_second(); + } else { + uint64_t base = Engine::get_singleton()->get_idle_frame_ticks(); + base_time = double(base - position_history[0].frame) / 1000000.0; + } + } + + for (int i = 0; i < position_history_len - 1; i++) { + float delta = 0.0; + uint64_t diff = position_history[i].frame - position_history[i + 1].frame; + Vector3 distance = position_history[i].position - position_history[i + 1].position; + + if (fixed_step) { + delta = float(diff) / Engine::get_singleton()->get_iterations_per_second(); + } else { + delta = double(diff) / 1000000.0; + } + + if (base_time + time_accum + delta > max_time) + break; + + distance_accum += distance; + time_accum += delta; + } + + if (time_accum) { + linear_velocity = distance_accum / time_accum; + } + + return linear_velocity; +} + +void SpatialVelocityTracker::reset(const Vector3 &p_new_pos) { + + PositionHistory ph; + ph.position = p_new_pos; + if (fixed_step) { + ph.frame = Engine::get_singleton()->get_fixed_frames(); + } else { + ph.frame = Engine::get_singleton()->get_idle_frame_ticks(); + } + + position_history[0] = ph; + position_history_len = 1; +} + +void SpatialVelocityTracker::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_track_fixed_step", "enable"), &SpatialVelocityTracker::set_track_fixed_step); + ClassDB::bind_method(D_METHOD("is_tracking_fixed_step"), &SpatialVelocityTracker::is_tracking_fixed_step); + ClassDB::bind_method(D_METHOD("update_position", "position"), &SpatialVelocityTracker::update_position); + ClassDB::bind_method(D_METHOD("get_tracked_linear_velocity"), &SpatialVelocityTracker::get_tracked_linear_velocity); + ClassDB::bind_method(D_METHOD("reset", "position"), &SpatialVelocityTracker::reset); +} + +SpatialVelocityTracker::SpatialVelocityTracker() { + position_history.resize(4); // should be configurable + position_history_len = 0; + fixed_step = false; +} diff --git a/scene/3d/spatial_velocity_tracker.h b/scene/3d/spatial_velocity_tracker.h new file mode 100644 index 000000000..b8237613a --- /dev/null +++ b/scene/3d/spatial_velocity_tracker.h @@ -0,0 +1,31 @@ +#ifndef SPATIAL_VELOCITY_TRACKER_H +#define SPATIAL_VELOCITY_TRACKER_H + +#include "scene/3d/spatial.h" + +class SpatialVelocityTracker : public Reference { + GDCLASS(SpatialVelocityTracker, Reference) + + struct PositionHistory { + uint64_t frame; + Vector3 position; + }; + + bool fixed_step; + Vector<PositionHistory> position_history; + int position_history_len; + +protected: + static void _bind_methods(); + +public: + void reset(const Vector3 &p_new_pos); + void set_track_fixed_step(bool p_track_fixed_step); + bool is_tracking_fixed_step() const; + void update_position(const Vector3 &p_position); + Vector3 get_tracked_linear_velocity() const; + + SpatialVelocityTracker(); +}; + +#endif // SPATIAL_VELOCITY_TRACKER_H diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index 062e3943b..978662f7d 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -272,10 +273,12 @@ void SpriteBase3D::_bind_methods() { ADD_GROUP("Flags", ""); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "transparent"), "set_draw_flag", "get_draw_flag", FLAG_TRANSPARENT); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "shaded"), "set_draw_flag", "get_draw_flag", FLAG_SHADED); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "double_sided"), "set_draw_flag", "get_draw_flag", FLAG_DOUBLE_SIDED); ADD_PROPERTY(PropertyInfo(Variant::INT, "alpha_cut", PROPERTY_HINT_ENUM, "Disabled,Discard,Opaque Pre-Pass"), "set_alpha_cut_mode", "get_alpha_cut_mode"); BIND_CONSTANT(FLAG_TRANSPARENT); BIND_CONSTANT(FLAG_SHADED); + BIND_CONSTANT(FLAG_DOUBLE_SIDED); BIND_CONSTANT(FLAG_MAX); BIND_CONSTANT(ALPHA_CUT_DISABLED); @@ -293,7 +296,7 @@ SpriteBase3D::SpriteBase3D() { pI = NULL; for (int i = 0; i < FLAG_MAX; i++) - flags[i] = i == FLAG_TRANSPARENT; + flags[i] = i == FLAG_TRANSPARENT || i == FLAG_DOUBLE_SIDED; axis = Vector3::AXIS_Z; pixel_size = 0.01; @@ -334,8 +337,8 @@ void Sprite3D::_draw() { s = s / Size2i(hframes, vframes); src_rect.size = s; - src_rect.pos.x += (frame % hframes) * s.x; - src_rect.pos.y += (frame / hframes) * s.y; + src_rect.position.x += (frame % hframes) * s.x; + src_rect.position.y += (frame / hframes) * s.y; } Point2i ofs = get_offset(); @@ -359,17 +362,17 @@ void Sprite3D::_draw() { Vector2 vertices[4] = { - (final_rect.pos + Vector2(0, final_rect.size.y)) * pixel_size, - (final_rect.pos + final_rect.size) * pixel_size, - (final_rect.pos + Vector2(final_rect.size.x, 0)) * pixel_size, - final_rect.pos * pixel_size, + (final_rect.position + Vector2(0, final_rect.size.y)) * pixel_size, + (final_rect.position + final_rect.size) * pixel_size, + (final_rect.position + Vector2(final_rect.size.x, 0)) * pixel_size, + final_rect.position * pixel_size, }; Vector2 uvs[4] = { - final_src_rect.pos / tsize, - (final_src_rect.pos + Vector2(final_src_rect.size.x, 0)) / tsize, - (final_src_rect.pos + final_src_rect.size) / tsize, - (final_src_rect.pos + Vector2(0, final_src_rect.size.y)) / tsize, + final_src_rect.position / tsize, + (final_src_rect.position + Vector2(final_src_rect.size.x, 0)) / tsize, + (final_src_rect.position + final_src_rect.size) / tsize, + (final_src_rect.position + Vector2(0, final_src_rect.size.y)) / tsize, }; if (is_flipped_h()) { @@ -386,7 +389,7 @@ void Sprite3D::_draw() { int axis = get_axis(); normal[axis] = 1.0; - RID mat = VS::get_singleton()->material_2d_get(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS); + RID mat = SpatialMaterial::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS); VS::get_singleton()->immediate_set_material(immediate, mat); VS::get_singleton()->immediate_begin(immediate, VS::PRIMITIVE_TRIANGLE_FAN, texture->get_rid()); @@ -420,7 +423,7 @@ void Sprite3D::_draw() { vtx[y_axis] = vertices[i][1]; VS::get_singleton()->immediate_vertex(immediate, vtx); if (i == 0) { - aabb.pos = vtx; + aabb.position = vtx; aabb.size = Vector3(); } else { aabb.expand_to(vtx); @@ -499,7 +502,7 @@ void Sprite3D::set_vframes(int p_amount) { ERR_FAIL_COND(p_amount < 1); vframes = p_amount; _queue_update(); - _change_notify("frame"); + _change_notify(); } int Sprite3D::get_vframes() const { @@ -511,7 +514,7 @@ void Sprite3D::set_hframes(int p_amount) { ERR_FAIL_COND(p_amount < 1); hframes = p_amount; _queue_update(); - _change_notify("frame"); + _change_notify(); } int Sprite3D::get_hframes() const { @@ -559,8 +562,8 @@ void Sprite3D::_validate_property(PropertyInfo &property) const { void Sprite3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_texture", "texture:Texture"), &Sprite3D::set_texture); - ClassDB::bind_method(D_METHOD("get_texture:Texture"), &Sprite3D::get_texture); + ClassDB::bind_method(D_METHOD("set_texture", "texture"), &Sprite3D::set_texture); + ClassDB::bind_method(D_METHOD("get_texture"), &Sprite3D::get_texture); ClassDB::bind_method(D_METHOD("set_region", "enabled"), &Sprite3D::set_region); ClassDB::bind_method(D_METHOD("is_region"), &Sprite3D::is_region); @@ -578,10 +581,12 @@ void Sprite3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_hframes"), &Sprite3D::get_hframes); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture"); + ADD_GROUP("Animation", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "vframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_vframes", "get_vframes"); ADD_PROPERTY(PropertyInfo(Variant::INT, "hframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_hframes", "get_hframes"); ADD_PROPERTY(PropertyInfo(Variant::INT, "frame", PROPERTY_HINT_SPRITE_FRAME), "set_frame", "get_frame"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region"), "set_region", "is_region"); + ADD_GROUP("Region", "region_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region", "is_region"); ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect"); ADD_SIGNAL(MethodInfo("frame_changed")); @@ -719,8 +724,8 @@ void AnimatedSprite3D::_draw() { void AnimatedSprite3D::_bind_methods(){ - ClassDB::bind_method(D_METHOD("set_sprite_frames","sprite_frames:SpriteFrames"),&AnimatedSprite3D::set_sprite_frames); - ClassDB::bind_method(D_METHOD("get_sprite_frames:Texture"),&AnimatedSprite3D::get_sprite_frames); + ClassDB::bind_method(D_METHOD("set_sprite_frames","sprite_frames"),&AnimatedSprite3D::set_sprite_frames); + ClassDB::bind_method(D_METHOD("get_sprite_frames"),&AnimatedSprite3D::get_sprite_frames); ClassDB::bind_method(D_METHOD("set_frame","frame"),&AnimatedSprite3D::set_frame); ClassDB::bind_method(D_METHOD("get_frame"),&AnimatedSprite3D::get_frame); @@ -860,17 +865,17 @@ void AnimatedSprite3D::_draw() { Vector2 vertices[4] = { - (final_rect.pos + Vector2(0, final_rect.size.y)) * pixel_size, - (final_rect.pos + final_rect.size) * pixel_size, - (final_rect.pos + Vector2(final_rect.size.x, 0)) * pixel_size, - final_rect.pos * pixel_size, + (final_rect.position + Vector2(0, final_rect.size.y)) * pixel_size, + (final_rect.position + final_rect.size) * pixel_size, + (final_rect.position + Vector2(final_rect.size.x, 0)) * pixel_size, + final_rect.position * pixel_size, }; Vector2 uvs[4] = { - final_src_rect.pos / tsize, - (final_src_rect.pos + Vector2(final_src_rect.size.x, 0)) / tsize, - (final_src_rect.pos + final_src_rect.size) / tsize, - (final_src_rect.pos + Vector2(0, final_src_rect.size.y)) / tsize, + final_src_rect.position / tsize, + (final_src_rect.position + Vector2(final_src_rect.size.x, 0)) / tsize, + (final_src_rect.position + final_src_rect.size) / tsize, + (final_src_rect.position + Vector2(0, final_src_rect.size.y)) / tsize, }; if (is_flipped_h()) { @@ -887,7 +892,8 @@ void AnimatedSprite3D::_draw() { int axis = get_axis(); normal[axis] = 1.0; - RID mat = VS::get_singleton()->material_2d_get(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS); + RID mat = SpatialMaterial::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS); + VS::get_singleton()->immediate_set_material(immediate, mat); VS::get_singleton()->immediate_begin(immediate, VS::PRIMITIVE_TRIANGLE_FAN, texture->get_rid()); @@ -921,7 +927,7 @@ void AnimatedSprite3D::_draw() { vtx[y_axis] = vertices[i][1]; VS::get_singleton()->immediate_vertex(immediate, vtx); if (i == 0) { - aabb.pos = vtx; + aabb.position = vtx; aabb.size = Vector3(); } else { aabb.expand_to(vtx); @@ -1240,8 +1246,8 @@ String AnimatedSprite3D::get_configuration_warning() const { void AnimatedSprite3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_sprite_frames", "sprite_frames:SpriteFrames"), &AnimatedSprite3D::set_sprite_frames); - ClassDB::bind_method(D_METHOD("get_sprite_frames:SpriteFrames"), &AnimatedSprite3D::get_sprite_frames); + ClassDB::bind_method(D_METHOD("set_sprite_frames", "sprite_frames"), &AnimatedSprite3D::set_sprite_frames); + ClassDB::bind_method(D_METHOD("get_sprite_frames"), &AnimatedSprite3D::get_sprite_frames); ClassDB::bind_method(D_METHOD("set_animation", "animation"), &AnimatedSprite3D::set_animation); ClassDB::bind_method(D_METHOD("get_animation"), &AnimatedSprite3D::get_animation); diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h index d1de4e1b8..7dc4cd4ff 100644 --- a/scene/3d/sprite_3d.h +++ b/scene/3d/sprite_3d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -40,6 +41,7 @@ public: enum DrawFlags { FLAG_TRANSPARENT, FLAG_SHADED, + FLAG_DOUBLE_SIDED, FLAG_MAX }; @@ -117,7 +119,7 @@ public: void set_pixel_size(float p_amount); float get_pixel_size() const; - void set_axis(Vector3::Axis p_amount); + void set_axis(Vector3::Axis p_axis); Vector3::Axis get_axis() const; void set_draw_flag(DrawFlags p_flag, bool p_enable); diff --git a/scene/3d/test_cube.cpp b/scene/3d/test_cube.cpp deleted file mode 100644 index bab1d1e1c..000000000 --- a/scene/3d/test_cube.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/*************************************************************************/ -/* test_cube.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "test_cube.h" -#include "servers/visual_server.h" - -Rect3 TestCube::get_aabb() const { - - return Rect3(Vector3(-1, -1, -1), Vector3(2, 2, 2)); -} -PoolVector<Face3> TestCube::get_faces(uint32_t p_usage_flags) const { - - return PoolVector<Face3>(); -} - -TestCube::TestCube() { - - set_base(VisualServer::get_singleton()->get_test_cube()); -} - -TestCube::~TestCube() { -} diff --git a/scene/3d/test_cube.h b/scene/3d/test_cube.h deleted file mode 100644 index d03bea7b6..000000000 --- a/scene/3d/test_cube.h +++ /dev/null @@ -1,52 +0,0 @@ -/*************************************************************************/ -/* test_cube.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef TEST_CUBE_H -#define TEST_CUBE_H - -#include "rid.h" -#include "scene/3d/visual_instance.h" - -/** - @author Juan Linietsky <reduzio@gmail.com> -*/ -class TestCube : public GeometryInstance { - - GDCLASS(TestCube, GeometryInstance); - - RID instance; - -public: - virtual Rect3 get_aabb() const; - virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const; - - TestCube(); - ~TestCube(); -}; - -#endif diff --git a/scene/3d/vehicle_body.cpp b/scene/3d/vehicle_body.cpp index 4a647fe68..adf235c52 100644 --- a/scene/3d/vehicle_body.cpp +++ b/scene/3d/vehicle_body.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -213,6 +214,18 @@ float VehicleWheel::get_friction_slip() const { return m_frictionSlip; } +void VehicleWheel::set_roll_influence(float p_value) { + m_rollInfluence = p_value; +} + +float VehicleWheel::get_roll_influence() const { + return m_rollInfluence; +} + +bool VehicleWheel::is_in_contact() const { + return m_raycastInfo.m_isInContact; +} + void VehicleWheel::_bind_methods() { ClassDB::bind_method(D_METHOD("set_radius", "length"), &VehicleWheel::set_radius); @@ -245,9 +258,15 @@ void VehicleWheel::_bind_methods() { ClassDB::bind_method(D_METHOD("set_friction_slip", "length"), &VehicleWheel::set_friction_slip); ClassDB::bind_method(D_METHOD("get_friction_slip"), &VehicleWheel::get_friction_slip); + ClassDB::bind_method(D_METHOD("is_in_contact"), &VehicleWheel::is_in_contact); + + ClassDB::bind_method(D_METHOD("set_roll_influence", "roll_influence"), &VehicleWheel::set_roll_influence); + ClassDB::bind_method(D_METHOD("get_roll_influence"), &VehicleWheel::get_roll_influence); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_as_traction"), "set_use_as_traction", "is_used_as_traction"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_as_steering"), "set_use_as_steering", "is_used_as_steering"); ADD_GROUP("Wheel", "wheel_"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "wheel_roll_influence"), "set_roll_influence", "get_roll_influence"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "wheel_radius"), "set_radius", "get_radius"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "wheel_rest_length"), "set_suspension_rest_length", "get_suspension_rest_length"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "wheel_friction_slip"), "set_friction_slip", "get_friction_slip"); @@ -874,9 +893,9 @@ real_t VehicleBody::get_friction() const { return friction; } -void VehicleBody::set_engine_force(float p_force) { +void VehicleBody::set_engine_force(float p_engine_force) { - engine_force = p_force; + engine_force = p_engine_force; } float VehicleBody::get_engine_force() const { diff --git a/scene/3d/vehicle_body.h b/scene/3d/vehicle_body.h index 55b521cfa..d77880081 100644 --- a/scene/3d/vehicle_body.h +++ b/scene/3d/vehicle_body.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -125,6 +126,11 @@ public: void set_use_as_steering(bool p_enabled); bool is_used_as_steering() const; + bool is_in_contact() const; + + void set_roll_influence(float p_value); + float get_roll_influence() const; + VehicleWheel(); }; @@ -190,7 +196,7 @@ public: void set_engine_force(float p_engine_force); float get_engine_force() const; - void set_brake(float p_force); + void set_brake(float p_brake); float get_brake() const; void set_steering(float p_steering); diff --git a/scene/3d/visibility_notifier.cpp b/scene/3d/visibility_notifier.cpp index 909ac002b..cc81a4cb5 100644 --- a/scene/3d/visibility_notifier.cpp +++ b/scene/3d/visibility_notifier.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -28,6 +29,7 @@ /*************************************************************************/ #include "visibility_notifier.h" +#include "scene/3d/camera.h" #include "scene/3d/physics_body.h" #include "scene/animation/animation_player.h" #include "scene/scene_string_names.h" @@ -41,6 +43,7 @@ void VisibilityNotifier::_enter_camera(Camera *p_camera) { emit_signal(SceneStringNames::get_singleton()->screen_entered); _screen_enter(); } + emit_signal(SceneStringNames::get_singleton()->camera_entered, p_camera); } diff --git a/scene/3d/visibility_notifier.h b/scene/3d/visibility_notifier.h index 09c1175bf..316b2c357 100644 --- a/scene/3d/visibility_notifier.h +++ b/scene/3d/visibility_notifier.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp index 852881abd..1a294d016 100644 --- a/scene/3d/visual_instance.cpp +++ b/scene/3d/visual_instance.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -148,7 +149,7 @@ void VisualInstance::set_base(const RID &p_base) { VisualInstance::VisualInstance() { instance = VisualServer::get_singleton()->instance_create(); - VisualServer::get_singleton()->instance_attach_object_instance_ID(instance, get_instance_ID()); + VisualServer::get_singleton()->instance_attach_object_instance_id(instance, get_instance_id()); layers = 1; set_notify_transform(true); } @@ -315,12 +316,9 @@ void GeometryInstance::_bind_methods() { ClassDB::bind_method(D_METHOD("get_aabb"), &GeometryInstance::get_aabb); ADD_GROUP("Geometry", ""); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material_override", PROPERTY_HINT_RESOURCE_TYPE, "Material"), "set_material_override", "get_material_override"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material_override", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,SpatialMaterial"), "set_material_override", "get_material_override"); ADD_PROPERTY(PropertyInfo(Variant::INT, "cast_shadow", PROPERTY_HINT_ENUM, "Off,On,Double-Sided,Shadows Only"), "set_cast_shadows_setting", "get_cast_shadows_setting"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "extra_cull_margin", PROPERTY_HINT_RANGE, "0,16384,0"), "set_extra_cull_margin", "get_extra_cull_margin"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "use_as_billboard"), "set_flag", "get_flag", FLAG_BILLBOARD); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "use_as_y_billboard"), "set_flag", "get_flag", FLAG_BILLBOARD_FIX_Y); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "use_depth_scale"), "set_flag", "get_flag", FLAG_DEPH_SCALE); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "visible_in_all_rooms"), "set_flag", "get_flag", FLAG_VISIBLE_IN_ALL_ROOMS); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "use_in_baked_light"), "set_flag", "get_flag", FLAG_USE_BAKED_LIGHT); @@ -333,9 +331,6 @@ void GeometryInstance::_bind_methods() { //ADD_SIGNAL( MethodInfo("visibility_changed")); BIND_CONSTANT(FLAG_CAST_SHADOW); - BIND_CONSTANT(FLAG_BILLBOARD); - BIND_CONSTANT(FLAG_BILLBOARD_FIX_Y); - BIND_CONSTANT(FLAG_DEPH_SCALE); BIND_CONSTANT(FLAG_VISIBLE_IN_ALL_ROOMS); BIND_CONSTANT(FLAG_MAX); diff --git a/scene/3d/visual_instance.h b/scene/3d/visual_instance.h index 9f1cba923..9318198e5 100644 --- a/scene/3d/visual_instance.h +++ b/scene/3d/visual_instance.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -84,9 +85,6 @@ class GeometryInstance : public VisualInstance { public: enum Flags { FLAG_CAST_SHADOW = VS::INSTANCE_FLAG_CAST_SHADOW, - FLAG_BILLBOARD = VS::INSTANCE_FLAG_BILLBOARD, - FLAG_BILLBOARD_FIX_Y = VS::INSTANCE_FLAG_BILLBOARD_FIX_Y, - FLAG_DEPH_SCALE = VS::INSTANCE_FLAG_DEPH_SCALE, FLAG_VISIBLE_IN_ALL_ROOMS = VS::INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS, FLAG_USE_BAKED_LIGHT = VS::INSTANCE_FLAG_USE_BAKED_LIGHT, FLAG_MAX = VS::INSTANCE_FLAG_MAX, diff --git a/scene/SCsub b/scene/SCsub index bd2da1eab..df52e9c6c 100644 --- a/scene/SCsub +++ b/scene/SCsub @@ -3,10 +3,23 @@ Import('env') env.scene_sources = [] + + +# Thirdparty code +thirdparty_dir = "#thirdparty/misc/" +thirdparty_sources = [ + # C sources + "mikktspace.c", +] +thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] +env.add_source_files(env.scene_sources, thirdparty_sources) + + +# Godot's own sources env.add_source_files(env.scene_sources, "*.cpp") -Export('env') +# Chain load SCsubs SConscript('main/SCsub') SConscript('gui/SCsub') SConscript('3d/SCsub') @@ -17,6 +30,8 @@ SConscript('resources/SCsub') SConscript('io/SCsub') +# Build it all as a library lib = env.Library("scene", env.scene_sources) - env.Prepend(LIBS=[lib]) + +Export('env') diff --git a/scene/animation/animation_cache.cpp b/scene/animation/animation_cache.cpp index 93fbde519..31fee0e34 100644 --- a/scene/animation/animation_cache.cpp +++ b/scene/animation/animation_cache.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/animation/animation_cache.h b/scene/animation/animation_cache.h index 1668c6251..6687098d0 100644 --- a/scene/animation/animation_cache.h +++ b/scene/animation/animation_cache.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index dc9aa1758..e2a063646 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -201,6 +202,7 @@ void AnimationPlayer::_notification(int p_what) { if (!get_tree()->is_editor_hint() && animation_set.has(autoplay)) { play(autoplay); set_autoplay(""); //this line is the fix for autoplay issues with animatio + _animation_process(0); } } break; case NOTIFICATION_INTERNAL_PROCESS: { @@ -245,7 +247,7 @@ void AnimationPlayer::_generate_node_caches(AnimationData *p_anim) { ERR_EXPLAIN("On Animation: '" + p_anim->name + "', couldn't resolve track: '" + String(a->track_get_path(i)) + "'"); } ERR_CONTINUE(!child); // couldn't find the child node - uint32_t id = resource.is_valid() ? resource->get_instance_ID() : child->get_instance_ID(); + uint32_t id = resource.is_valid() ? resource->get_instance_id() : child->get_instance_id(); int bone_idx = -1; if (a->track_get_path(i).get_property() && child->cast_to<Skeleton>()) { @@ -610,7 +612,7 @@ void AnimationPlayer::_animation_update_transforms() { case SP_NONE: pa->object->set(pa->prop,pa->value_accum); break; //you are not speshul - case SP_NODE2D_POS: static_cast<Node2D*>(pa->object)->set_pos(pa->value_accum); break; + case SP_NODE2D_POS: static_cast<Node2D*>(pa->object)->set_position(pa->value_accum); break; case SP_NODE2D_ROT: static_cast<Node2D*>(pa->object)->set_rot(Math::deg2rad(pa->value_accum)); break; case SP_NODE2D_SCALE: static_cast<Node2D*>(pa->object)->set_scale(pa->value_accum); break; }*/ @@ -1213,11 +1215,11 @@ void AnimationPlayer::_bind_methods() { ClassDB::bind_method(D_METHOD("_node_removed"), &AnimationPlayer::_node_removed); ClassDB::bind_method(D_METHOD("_animation_changed"), &AnimationPlayer::_animation_changed); - ClassDB::bind_method(D_METHOD("add_animation", "name", "animation:Animation"), &AnimationPlayer::add_animation); + ClassDB::bind_method(D_METHOD("add_animation", "name", "animation"), &AnimationPlayer::add_animation); ClassDB::bind_method(D_METHOD("remove_animation", "name"), &AnimationPlayer::remove_animation); ClassDB::bind_method(D_METHOD("rename_animation", "name", "newname"), &AnimationPlayer::rename_animation); ClassDB::bind_method(D_METHOD("has_animation", "name"), &AnimationPlayer::has_animation); - ClassDB::bind_method(D_METHOD("get_animation:Animation", "name"), &AnimationPlayer::get_animation); + ClassDB::bind_method(D_METHOD("get_animation", "name"), &AnimationPlayer::get_animation); ClassDB::bind_method(D_METHOD("get_animation_list"), &AnimationPlayer::_get_animation_list); ClassDB::bind_method(D_METHOD("animation_set_next", "anim_from", "anim_to"), &AnimationPlayer::animation_set_next); @@ -1254,7 +1256,7 @@ void AnimationPlayer::_bind_methods() { ClassDB::bind_method(D_METHOD("seek", "pos_sec", "update"), &AnimationPlayer::seek, DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_pos"), &AnimationPlayer::get_current_animation_pos); - ClassDB::bind_method(D_METHOD("find_animation", "animation:Animation"), &AnimationPlayer::find_animation); + ClassDB::bind_method(D_METHOD("find_animation", "animation"), &AnimationPlayer::find_animation); ClassDB::bind_method(D_METHOD("clear_caches"), &AnimationPlayer::clear_caches); @@ -1266,7 +1268,7 @@ void AnimationPlayer::_bind_methods() { ClassDB::bind_method(D_METHOD("advance", "delta"), &AnimationPlayer::advance); - ADD_GROUP("Playback", "playback_"); + ADD_GROUP("Playback Options", "playback_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), "set_animation_process_mode", "get_animation_process_mode"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "playback_default_blend_time", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_default_blend_time", "get_default_blend_time"); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_node"), "set_root", "get_root"); diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index b5679d62f..01b709205 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -270,7 +271,7 @@ public: void set_speed_scale(float p_speed); float get_speed_scale() const; - void set_autoplay(const String &pname); + void set_autoplay(const String &p_name); String get_autoplay() const; void set_animation_process_mode(AnimationProcessMode p_mode); diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp index 6f4279526..c12e97c4a 100644 --- a/scene/animation/animation_tree_player.cpp +++ b/scene/animation/animation_tree_player.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -1480,7 +1481,7 @@ AnimationTreePlayer::Track *AnimationTreePlayer::_find_track(const NodePath &p_p return NULL; } - ObjectID id = child->get_instance_ID(); + ObjectID id = child->get_instance_id(); StringName property; int bone_idx = -1; @@ -1708,8 +1709,8 @@ void AnimationTreePlayer::_bind_methods() { ClassDB::bind_method(D_METHOD("node_get_input_count", "id"), &AnimationTreePlayer::node_get_input_count); ClassDB::bind_method(D_METHOD("node_get_input_source", "id", "idx"), &AnimationTreePlayer::node_get_input_source); - ClassDB::bind_method(D_METHOD("animation_node_set_animation", "id", "animation:Animation"), &AnimationTreePlayer::animation_node_set_animation); - ClassDB::bind_method(D_METHOD("animation_node_get_animation:Animation", "id"), &AnimationTreePlayer::animation_node_get_animation); + ClassDB::bind_method(D_METHOD("animation_node_set_animation", "id", "animation"), &AnimationTreePlayer::animation_node_set_animation); + ClassDB::bind_method(D_METHOD("animation_node_get_animation", "id"), &AnimationTreePlayer::animation_node_get_animation); ClassDB::bind_method(D_METHOD("animation_node_set_master_animation", "id", "source"), &AnimationTreePlayer::animation_node_set_master_animation); ClassDB::bind_method(D_METHOD("animation_node_get_master_animation", "id"), &AnimationTreePlayer::animation_node_get_master_animation); diff --git a/scene/animation/animation_tree_player.h b/scene/animation/animation_tree_player.h index 35fce9b15..47f18795b 100644 --- a/scene/animation/animation_tree_player.h +++ b/scene/animation/animation_tree_player.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -311,7 +312,7 @@ private: Map<StringName, NodeBase *> node_map; // return time left to finish animation - float _process_node(const StringName &p_node, AnimationNode **r_prev_anim, float p_step, bool p_seek = false, float p_fallback_weight = 1.0, HashMap<NodePath, float> *p_weights = NULL); + float _process_node(const StringName &p_node, AnimationNode **r_prev_anim, float p_time, bool p_seek = false, float p_fallback_weight = 1.0, HashMap<NodePath, float> *p_weights = NULL); void _process_animation(float p_delta); bool reset_request; @@ -366,7 +367,7 @@ public: float oneshot_node_get_autorestart_delay(const StringName &p_node) const; float oneshot_node_get_autorestart_random_delay(const StringName &p_node) const; - void oneshot_node_set_mix_mode(const StringName &p_node, bool p_enabled); + void oneshot_node_set_mix_mode(const StringName &p_node, bool p_mix); bool oneshot_node_get_mix_mode(const StringName &p_node) const; void oneshot_node_start(const StringName &p_node); @@ -427,8 +428,8 @@ public: void remove_node(const StringName &p_node); Error connect_nodes(const StringName &p_src_node, const StringName &p_dst_node, int p_dst_input); - bool are_nodes_connected(const StringName &p_src_node, const StringName &p_dst_node, int p_input) const; - void disconnect_nodes(const StringName &p_src_node, int p_input); + bool are_nodes_connected(const StringName &p_src_node, const StringName &p_dst_node, int p_dst_input) const; + void disconnect_nodes(const StringName &p_node, int p_input); void set_base_path(const NodePath &p_path); NodePath get_base_path() const; diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index c455d20b1..78d3357bb 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -27,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "tween.h" -#include "method_bind_ext.inc" +#include "method_bind_ext.gen.inc" void Tween::_add_pending_command(StringName p_key, const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3, const Variant &p_arg4, const Variant &p_arg5, const Variant &p_arg6, const Variant &p_arg7, const Variant &p_arg8, const Variant &p_arg9, const Variant &p_arg10) { @@ -420,9 +421,9 @@ Variant Tween::_run_equation(InterpolateData &p_data) { Rect3 d = delta_val; Rect3 r; - APPLY_EQUATION(pos.x); - APPLY_EQUATION(pos.y); - APPLY_EQUATION(pos.z); + APPLY_EQUATION(position.x); + APPLY_EQUATION(position.y); + APPLY_EQUATION(position.z); APPLY_EQUATION(size.x); APPLY_EQUATION(size.y); APPLY_EQUATION(size.z); @@ -610,6 +611,7 @@ void Tween::_tween_process(float p_delta) { _apply_tween_value(data, result); if (data.finish) { + _apply_tween_value(data, data.final_val); emit_signal("tween_completed", object, data.key); // not repeat mode, remove completed action if (!repeat) @@ -961,7 +963,7 @@ bool Tween::_calc_delta_val(const Variant &p_initial_val, const Variant &p_final case Variant::RECT3: { Rect3 i = initial_val; Rect3 f = final_val; - delta_val = Rect3(f.pos - i.pos, f.size - i.size); + delta_val = Rect3(f.position - i.position, f.size - i.size); } break; case Variant::TRANSFORM: { Transform i = initial_val; @@ -1022,7 +1024,7 @@ bool Tween::interpolate_property(Object *p_object, String p_property, Variant p_ data.finish = false; data.elapsed = 0; - data.id = p_object->get_instance_ID(); + data.id = p_object->get_instance_id(); data.key = p_property; data.initial_val = p_initial_val; data.final_val = p_final_val; @@ -1064,7 +1066,7 @@ bool Tween::interpolate_method(Object *p_object, String p_method, Variant p_init data.finish = false; data.elapsed = 0; - data.id = p_object->get_instance_ID(); + data.id = p_object->get_instance_id(); data.key = p_method; data.initial_val = p_initial_val; data.final_val = p_final_val; @@ -1101,7 +1103,7 @@ bool Tween::interpolate_callback(Object *p_object, real_t p_duration, String p_c data.call_deferred = false; data.elapsed = 0; - data.id = p_object->get_instance_ID(); + data.id = p_object->get_instance_id(); data.key = p_callback; data.duration = p_duration; data.delay = 0; @@ -1153,7 +1155,7 @@ bool Tween::interpolate_deferred_callback(Object *p_object, real_t p_duration, S data.call_deferred = true; data.elapsed = 0; - data.id = p_object->get_instance_ID(); + data.id = p_object->get_instance_id(); data.key = p_callback; data.duration = p_duration; data.delay = 0; @@ -1220,10 +1222,10 @@ bool Tween::follow_property(Object *p_object, String p_property, Variant p_initi data.finish = false; data.elapsed = 0; - data.id = p_object->get_instance_ID(); + data.id = p_object->get_instance_id(); data.key = p_property; data.initial_val = p_initial_val; - data.target_id = p_target->get_instance_ID(); + data.target_id = p_target->get_instance_id(); data.target_key = p_target_property; data.duration = p_duration; data.trans_type = p_trans_type; @@ -1270,10 +1272,10 @@ bool Tween::follow_method(Object *p_object, String p_method, Variant p_initial_v data.finish = false; data.elapsed = 0; - data.id = p_object->get_instance_ID(); + data.id = p_object->get_instance_id(); data.key = p_method; data.initial_val = p_initial_val; - data.target_id = p_target->get_instance_ID(); + data.target_id = p_target->get_instance_id(); data.target_key = p_target_method; data.duration = p_duration; data.trans_type = p_trans_type; @@ -1319,9 +1321,9 @@ bool Tween::targeting_property(Object *p_object, String p_property, Object *p_in data.finish = false; data.elapsed = 0; - data.id = p_object->get_instance_ID(); + data.id = p_object->get_instance_id(); data.key = p_property; - data.target_id = p_initial->get_instance_ID(); + data.target_id = p_initial->get_instance_id(); data.target_key = p_initial_property; data.initial_val = initial_val; data.final_val = p_final_val; @@ -1373,9 +1375,9 @@ bool Tween::targeting_method(Object *p_object, String p_method, Object *p_initia data.finish = false; data.elapsed = 0; - data.id = p_object->get_instance_ID(); + data.id = p_object->get_instance_id(); data.key = p_method; - data.target_id = p_initial->get_instance_ID(); + data.target_id = p_initial->get_instance_id(); data.target_key = p_initial_method; data.initial_val = initial_val; data.final_val = p_final_val; diff --git a/scene/animation/tween.h b/scene/animation/tween.h index 84f866f43..43234fab8 100644 --- a/scene/animation/tween.h +++ b/scene/animation/tween.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -131,7 +132,7 @@ private: void _tween_process(float p_delta); void _set_process(bool p_process, bool p_force = false); - void _remove(Object *p_node, String p_key, bool first_only); + void _remove(Object *p_object, String p_key, bool first_only); protected: bool _set(const StringName &p_name, const Variant &p_value); @@ -155,34 +156,34 @@ public: float get_speed_scale() const; bool start(); - bool reset(Object *p_node, String p_key); + bool reset(Object *p_object, String p_key); bool reset_all(); - bool stop(Object *p_node, String p_key); + bool stop(Object *p_object, String p_key); bool stop_all(); - bool resume(Object *p_node, String p_key); + bool resume(Object *p_object, String p_key); bool resume_all(); - bool remove(Object *p_node, String p_key); + bool remove(Object *p_object, String p_key); bool remove_all(); bool seek(real_t p_time); real_t tell() const; real_t get_runtime() const; - bool interpolate_property(Object *p_node, String p_property, Variant p_initial_val, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0); + bool interpolate_property(Object *p_object, String p_property, Variant p_initial_val, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0); - bool interpolate_method(Object *p_node, String p_method, Variant p_initial_val, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0); + bool interpolate_method(Object *p_object, String p_method, Variant p_initial_val, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0); bool interpolate_callback(Object *p_object, real_t p_duration, String p_callback, VARIANT_ARG_DECLARE); bool interpolate_deferred_callback(Object *p_object, real_t p_duration, String p_callback, VARIANT_ARG_DECLARE); - bool follow_property(Object *p_node, String p_property, Variant p_initial_val, Object *p_target, String p_target_property, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0); + bool follow_property(Object *p_object, String p_property, Variant p_initial_val, Object *p_target, String p_target_property, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0); - bool follow_method(Object *p_node, String p_method, Variant p_initial_val, Object *p_target, String p_target_method, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0); + bool follow_method(Object *p_object, String p_method, Variant p_initial_val, Object *p_target, String p_target_method, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0); - bool targeting_property(Object *p_node, String p_property, Object *p_initial, String p_initial_property, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0); + bool targeting_property(Object *p_object, String p_property, Object *p_initial, String p_initial_property, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0); - bool targeting_method(Object *p_node, String p_method, Object *p_initial, String p_initial_method, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0); + bool targeting_method(Object *p_object, String p_method, Object *p_initial, String p_initial_method, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0); Tween(); ~Tween(); diff --git a/scene/animation/tween_interpolaters.cpp b/scene/animation/tween_interpolaters.cpp index ef55b63ed..434f4df3e 100644 --- a/scene/animation/tween_interpolaters.cpp +++ b/scene/animation/tween_interpolaters.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/audio/audio_player.cpp b/scene/audio/audio_player.cpp index 1ee31a94d..a8ddcbbb4 100644 --- a/scene/audio/audio_player.cpp +++ b/scene/audio/audio_player.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -28,7 +29,7 @@ /*************************************************************************/ #include "audio_player.h" -void AudioPlayer::_mix_audio() { +void AudioStreamPlayer::_mix_audio() { if (!stream_playback.is_valid()) { return; @@ -94,7 +95,7 @@ void AudioPlayer::_mix_audio() { } } -void AudioPlayer::_notification(int p_what) { +void AudioStreamPlayer::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { @@ -110,8 +111,9 @@ void AudioPlayer::_notification(int p_what) { } } -void AudioPlayer::set_stream(Ref<AudioStream> p_stream) { +void AudioStreamPlayer::set_stream(Ref<AudioStream> p_stream) { + ERR_FAIL_COND(!p_stream.is_valid()); AudioServer::get_singleton()->lock(); mix_buffer.resize(AudioServer::get_singleton()->thread_get_mix_buffer_size()); @@ -134,21 +136,21 @@ void AudioPlayer::set_stream(Ref<AudioStream> p_stream) { AudioServer::get_singleton()->unlock(); } -Ref<AudioStream> AudioPlayer::get_stream() const { +Ref<AudioStream> AudioStreamPlayer::get_stream() const { return stream; } -void AudioPlayer::set_volume_db(float p_volume) { +void AudioStreamPlayer::set_volume_db(float p_volume) { volume_db = p_volume; } -float AudioPlayer::get_volume_db() const { +float AudioStreamPlayer::get_volume_db() const { return volume_db; } -void AudioPlayer::play(float p_from_pos) { +void AudioStreamPlayer::play(float p_from_pos) { if (stream_playback.is_valid()) { mix_volume_db = volume_db; //reset volume ramp @@ -157,21 +159,21 @@ void AudioPlayer::play(float p_from_pos) { } } -void AudioPlayer::seek(float p_seconds) { +void AudioStreamPlayer::seek(float p_seconds) { if (stream_playback.is_valid()) { setseek = p_seconds; } } -void AudioPlayer::stop() { +void AudioStreamPlayer::stop() { if (stream_playback.is_valid()) { active = false; } } -bool AudioPlayer::is_playing() const { +bool AudioStreamPlayer::is_playing() const { if (stream_playback.is_valid()) { return active && stream_playback->is_playing(); @@ -180,7 +182,7 @@ bool AudioPlayer::is_playing() const { return false; } -float AudioPlayer::get_pos() { +float AudioStreamPlayer::get_pos() { if (stream_playback.is_valid()) { return stream_playback->get_pos(); @@ -189,14 +191,14 @@ float AudioPlayer::get_pos() { return 0; } -void AudioPlayer::set_bus(const StringName &p_bus) { +void AudioStreamPlayer::set_bus(const StringName &p_bus) { //if audio is active, must lock this AudioServer::get_singleton()->lock(); bus = p_bus; AudioServer::get_singleton()->unlock(); } -StringName AudioPlayer::get_bus() const { +StringName AudioStreamPlayer::get_bus() const { for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { if (AudioServer::get_singleton()->get_bus_name(i) == bus) { @@ -206,38 +208,38 @@ StringName AudioPlayer::get_bus() const { return "Master"; } -void AudioPlayer::set_autoplay(bool p_enable) { +void AudioStreamPlayer::set_autoplay(bool p_enable) { autoplay = p_enable; } -bool AudioPlayer::is_autoplay_enabled() { +bool AudioStreamPlayer::is_autoplay_enabled() { return autoplay; } -void AudioPlayer::set_mix_target(MixTarget p_target) { +void AudioStreamPlayer::set_mix_target(MixTarget p_target) { mix_target = p_target; } -AudioPlayer::MixTarget AudioPlayer::get_mix_target() const { +AudioStreamPlayer::MixTarget AudioStreamPlayer::get_mix_target() const { return mix_target; } -void AudioPlayer::_set_playing(bool p_enable) { +void AudioStreamPlayer::_set_playing(bool p_enable) { if (p_enable) play(); else stop(); } -bool AudioPlayer::_is_active() const { +bool AudioStreamPlayer::_is_active() const { return active; } -void AudioPlayer::_validate_property(PropertyInfo &property) const { +void AudioStreamPlayer::_validate_property(PropertyInfo &property) const { if (property.name == "bus") { @@ -253,39 +255,39 @@ void AudioPlayer::_validate_property(PropertyInfo &property) const { } } -void AudioPlayer::_bus_layout_changed() { +void AudioStreamPlayer::_bus_layout_changed() { _change_notify(); } -void AudioPlayer::_bind_methods() { +void AudioStreamPlayer::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_stream", "stream:AudioStream"), &AudioPlayer::set_stream); - ClassDB::bind_method(D_METHOD("get_stream"), &AudioPlayer::get_stream); + ClassDB::bind_method(D_METHOD("set_stream", "stream"), &AudioStreamPlayer::set_stream); + ClassDB::bind_method(D_METHOD("get_stream"), &AudioStreamPlayer::get_stream); - ClassDB::bind_method(D_METHOD("set_volume_db", "volume_db"), &AudioPlayer::set_volume_db); - ClassDB::bind_method(D_METHOD("get_volume_db"), &AudioPlayer::get_volume_db); + ClassDB::bind_method(D_METHOD("set_volume_db", "volume_db"), &AudioStreamPlayer::set_volume_db); + ClassDB::bind_method(D_METHOD("get_volume_db"), &AudioStreamPlayer::get_volume_db); - ClassDB::bind_method(D_METHOD("play", "from_pos"), &AudioPlayer::play, DEFVAL(0.0)); - ClassDB::bind_method(D_METHOD("seek", "to_pos"), &AudioPlayer::seek); - ClassDB::bind_method(D_METHOD("stop"), &AudioPlayer::stop); + ClassDB::bind_method(D_METHOD("play", "from_pos"), &AudioStreamPlayer::play, DEFVAL(0.0)); + ClassDB::bind_method(D_METHOD("seek", "to_pos"), &AudioStreamPlayer::seek); + ClassDB::bind_method(D_METHOD("stop"), &AudioStreamPlayer::stop); - ClassDB::bind_method(D_METHOD("is_playing"), &AudioPlayer::is_playing); - ClassDB::bind_method(D_METHOD("get_pos"), &AudioPlayer::get_pos); + ClassDB::bind_method(D_METHOD("is_playing"), &AudioStreamPlayer::is_playing); + ClassDB::bind_method(D_METHOD("get_pos"), &AudioStreamPlayer::get_pos); - ClassDB::bind_method(D_METHOD("set_bus", "bus"), &AudioPlayer::set_bus); - ClassDB::bind_method(D_METHOD("get_bus"), &AudioPlayer::get_bus); + ClassDB::bind_method(D_METHOD("set_bus", "bus"), &AudioStreamPlayer::set_bus); + ClassDB::bind_method(D_METHOD("get_bus"), &AudioStreamPlayer::get_bus); - ClassDB::bind_method(D_METHOD("set_autoplay", "enable"), &AudioPlayer::set_autoplay); - ClassDB::bind_method(D_METHOD("is_autoplay_enabled"), &AudioPlayer::is_autoplay_enabled); + ClassDB::bind_method(D_METHOD("set_autoplay", "enable"), &AudioStreamPlayer::set_autoplay); + ClassDB::bind_method(D_METHOD("is_autoplay_enabled"), &AudioStreamPlayer::is_autoplay_enabled); - ClassDB::bind_method(D_METHOD("set_mix_target", "mix_target"), &AudioPlayer::set_mix_target); - ClassDB::bind_method(D_METHOD("get_mix_target"), &AudioPlayer::get_mix_target); + ClassDB::bind_method(D_METHOD("set_mix_target", "mix_target"), &AudioStreamPlayer::set_mix_target); + ClassDB::bind_method(D_METHOD("get_mix_target"), &AudioStreamPlayer::get_mix_target); - ClassDB::bind_method(D_METHOD("_set_playing", "enable"), &AudioPlayer::_set_playing); - ClassDB::bind_method(D_METHOD("_is_active"), &AudioPlayer::_is_active); + ClassDB::bind_method(D_METHOD("_set_playing", "enable"), &AudioStreamPlayer::_set_playing); + ClassDB::bind_method(D_METHOD("_is_active"), &AudioStreamPlayer::_is_active); - ClassDB::bind_method(D_METHOD("_bus_layout_changed"), &AudioPlayer::_bus_layout_changed); + ClassDB::bind_method(D_METHOD("_bus_layout_changed"), &AudioStreamPlayer::_bus_layout_changed); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_stream", "get_stream"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "volume_db", PROPERTY_HINT_RANGE, "-80,24"), "set_volume_db", "get_volume_db"); @@ -295,7 +297,7 @@ void AudioPlayer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "bus", PROPERTY_HINT_ENUM, ""), "set_bus", "get_bus"); } -AudioPlayer::AudioPlayer() { +AudioStreamPlayer::AudioStreamPlayer() { mix_volume_db = 0; volume_db = 0; @@ -307,5 +309,5 @@ AudioPlayer::AudioPlayer() { AudioServer::get_singleton()->connect("bus_layout_changed", this, "_bus_layout_changed"); } -AudioPlayer::~AudioPlayer() { +AudioStreamPlayer::~AudioStreamPlayer() { } diff --git a/scene/audio/audio_player.h b/scene/audio/audio_player.h index 0d7862618..8bd6844de 100644 --- a/scene/audio/audio_player.h +++ b/scene/audio/audio_player.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,9 +33,9 @@ #include "scene/main/node.h" #include "servers/audio/audio_stream.h" -class AudioPlayer : public Node { +class AudioStreamPlayer : public Node { - GDCLASS(AudioPlayer, Node) + GDCLASS(AudioStreamPlayer, Node) public: enum MixTarget { @@ -59,7 +60,7 @@ private: MixTarget mix_target; void _mix_audio(); - static void _mix_audios(void *self) { reinterpret_cast<AudioPlayer *>(self)->_mix_audio(); } + static void _mix_audios(void *self) { reinterpret_cast<AudioStreamPlayer *>(self)->_mix_audio(); } void _set_playing(bool p_enable); bool _is_active() const; @@ -93,9 +94,9 @@ public: void set_mix_target(MixTarget p_target); MixTarget get_mix_target() const; - AudioPlayer(); - ~AudioPlayer(); + AudioStreamPlayer(); + ~AudioStreamPlayer(); }; -VARIANT_ENUM_CAST(AudioPlayer::MixTarget) +VARIANT_ENUM_CAST(AudioStreamPlayer::MixTarget) #endif // AUDIOPLAYER_H diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index eceee8e31..9c20decef 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -37,6 +38,8 @@ void BaseButton::_unpress_group() { if (!button_group.is_valid()) return; + status.pressed = true; + for (Set<BaseButton *>::Element *E = button_group->buttons.front(); E; E = E->next()) { if (E->get() == this) continue; @@ -45,188 +48,185 @@ void BaseButton::_unpress_group() { } } -void BaseButton::_gui_input(InputEvent p_event) { +void BaseButton::_gui_input(Ref<InputEvent> p_event) { if (status.disabled) // no interaction with disabled button return; - switch (p_event.type) { - - case InputEvent::MOUSE_BUTTON: { - - const InputEventMouseButton &b = p_event.mouse_button; + Ref<InputEventMouseButton> b = p_event; - if (status.disabled || b.button_index != 1) - return; + if (b.is_valid()) { + if (status.disabled || b->get_button_index() != 1) + return; - if (status.pressing_button) - break; + if (status.pressing_button) + return; - if (action_mode == ACTION_MODE_BUTTON_PRESS) { + if (action_mode == ACTION_MODE_BUTTON_PRESS) { - if (b.pressed) { + if (b->is_pressed()) { - emit_signal("button_down"); - - if (!toggle_mode) { //mouse press attempt + emit_signal("button_down"); - status.press_attempt = true; - status.pressing_inside = true; + if (!toggle_mode) { //mouse press attempt - pressed(); - if (get_script_instance()) { - Variant::CallError ce; - get_script_instance()->call(SceneStringNames::get_singleton()->_pressed, NULL, 0, ce); - } + status.press_attempt = true; + status.pressing_inside = true; - emit_signal("pressed"); - _unpress_group(); + pressed(); + if (get_script_instance()) { + Variant::CallError ce; + get_script_instance()->call(SceneStringNames::get_singleton()->_pressed, NULL, 0, ce); + } - } else { + emit_signal("pressed"); + _unpress_group(); - status.pressed = !status.pressed; - pressed(); - if (get_script_instance()) { - Variant::CallError ce; - get_script_instance()->call(SceneStringNames::get_singleton()->_pressed, NULL, 0, ce); - } - emit_signal("pressed"); - _unpress_group(); + } else { - toggled(status.pressed); - emit_signal("toggled", status.pressed); + status.pressed = !status.pressed; + pressed(); + if (get_script_instance()) { + Variant::CallError ce; + get_script_instance()->call(SceneStringNames::get_singleton()->_pressed, NULL, 0, ce); } + emit_signal("pressed"); + _unpress_group(); - } else { + toggled(status.pressed); + emit_signal("toggled", status.pressed); + } - emit_signal("button_up"); + } else { - /* this is pointless if (status.press_attempt && status.pressing_inside) { - //released(); - emit_signal("released"); - } -*/ - status.press_attempt = false; + emit_signal("button_up"); + + /* this is pointless if (status.press_attempt && status.pressing_inside) { + //released(); + emit_signal("released"); } - update(); - break; +*/ + status.press_attempt = false; } + update(); + return; + } - if (b.pressed) { + if (b->is_pressed()) { - status.press_attempt = true; - status.pressing_inside = true; - emit_signal("button_down"); + status.press_attempt = true; + status.pressing_inside = true; + emit_signal("button_down"); - } else { + } else { - emit_signal("button_up"); + emit_signal("button_up"); - if (status.press_attempt && status.pressing_inside) { + if (status.press_attempt && status.pressing_inside) { - if (!toggle_mode) { //mouse press attempt + if (!toggle_mode) { //mouse press attempt - pressed(); - if (get_script_instance()) { - Variant::CallError ce; - get_script_instance()->call(SceneStringNames::get_singleton()->_pressed, NULL, 0, ce); - } + pressed(); + if (get_script_instance()) { + Variant::CallError ce; + get_script_instance()->call(SceneStringNames::get_singleton()->_pressed, NULL, 0, ce); + } - emit_signal("pressed"); + emit_signal("pressed"); - } else { + } else { - status.pressed = !status.pressed; + status.pressed = !status.pressed; - pressed(); - emit_signal("pressed"); + pressed(); + emit_signal("pressed"); - toggled(status.pressed); - emit_signal("toggled", status.pressed); - if (get_script_instance()) { - get_script_instance()->call(SceneStringNames::get_singleton()->_toggled, status.pressed); - } + toggled(status.pressed); + emit_signal("toggled", status.pressed); + if (get_script_instance()) { + get_script_instance()->call(SceneStringNames::get_singleton()->_toggled, status.pressed); } - - _unpress_group(); } - status.press_attempt = false; + _unpress_group(); } - update(); - } break; - case InputEvent::MOUSE_MOTION: { + status.press_attempt = false; + } - if (status.press_attempt && status.pressing_button == 0) { - bool last_press_inside = status.pressing_inside; - status.pressing_inside = has_point(Point2(p_event.mouse_motion.x, p_event.mouse_motion.y)); - if (last_press_inside != status.pressing_inside) - update(); - } - } break; - case InputEvent::ACTION: - case InputEvent::JOYPAD_BUTTON: - case InputEvent::KEY: { + update(); + } - if (p_event.is_echo()) { - break; - } + Ref<InputEventMouseMotion> mm = p_event; - if (status.disabled) { - break; - } + if (mm.is_valid()) { + if (status.press_attempt && status.pressing_button == 0) { + bool last_press_inside = status.pressing_inside; + status.pressing_inside = has_point(mm->get_position()); + if (last_press_inside != status.pressing_inside) + update(); + } + } - if (status.press_attempt && status.pressing_button == 0) { - break; - } + if (!mm.is_valid() && !b.is_valid()) { - if (p_event.is_action("ui_accept")) { + if (p_event->is_echo()) { + return; + } - if (p_event.is_pressed()) { + if (status.disabled) { + return; + } - status.pressing_button++; - status.press_attempt = true; - status.pressing_inside = true; - emit_signal("button_down"); + if (status.press_attempt && status.pressing_button == 0) { + return; + } - } else if (status.press_attempt) { + if (p_event->is_action("ui_accept")) { - if (status.pressing_button) - status.pressing_button--; + if (p_event->is_pressed()) { - if (status.pressing_button) - break; + status.pressing_button++; + status.press_attempt = true; + status.pressing_inside = true; + emit_signal("button_down"); - status.press_attempt = false; - status.pressing_inside = false; + } else if (status.press_attempt) { - emit_signal("button_up"); + if (status.pressing_button) + status.pressing_button--; - if (!toggle_mode) { //mouse press attempt + if (status.pressing_button) + return; - pressed(); - emit_signal("pressed"); - } else { + status.press_attempt = false; + status.pressing_inside = false; - status.pressed = !status.pressed; + emit_signal("button_up"); - pressed(); - emit_signal("pressed"); + if (!toggle_mode) { //mouse press attempt - toggled(status.pressed); - if (get_script_instance()) { - get_script_instance()->call(SceneStringNames::get_singleton()->_toggled, status.pressed); - } - emit_signal("toggled", status.pressed); - } + pressed(); + emit_signal("pressed"); + } else { - _unpress_group(); + status.pressed = !status.pressed; + + pressed(); + emit_signal("pressed"); + + toggled(status.pressed); + if (get_script_instance()) { + get_script_instance()->call(SceneStringNames::get_singleton()->_toggled, status.pressed); + } + emit_signal("toggled", status.pressed); } - accept_event(); - update(); + _unpress_group(); } + + accept_event(); + update(); } } } @@ -427,9 +427,9 @@ Ref<ShortCut> BaseButton::get_shortcut() const { return shortcut; } -void BaseButton::_unhandled_input(InputEvent p_event) { +void BaseButton::_unhandled_input(Ref<InputEvent> p_event) { - if (!is_disabled() && is_visible_in_tree() && p_event.is_pressed() && !p_event.is_echo() && shortcut.is_valid() && shortcut->is_shortcut(p_event)) { + if (!is_disabled() && is_visible_in_tree() && p_event->is_pressed() && !p_event->is_echo() && shortcut.is_valid() && shortcut->is_shortcut(p_event)) { if (get_viewport()->get_modal_stack_top() && !get_viewport()->get_modal_stack_top()->is_a_parent_of(this)) return; //ignore because of modal window @@ -508,7 +508,7 @@ void BaseButton::_bind_methods() { ADD_SIGNAL(MethodInfo("toggled", PropertyInfo(Variant::BOOL, "pressed"))); ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "toggle_mode"), "set_toggle_mode", "is_toggle_mode"); - ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "is_pressed"), "set_pressed", "is_pressed"); + ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed"); ADD_PROPERTYNO(PropertyInfo(Variant::INT, "action_mode", PROPERTY_HINT_ENUM, "Button Press,Button Release"), "set_action_mode", "get_action_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "enabled_focus_mode", PROPERTY_HINT_ENUM, "None,Click,All"), "set_enabled_focus_mode", "get_enabled_focus_mode"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut", PROPERTY_HINT_RESOURCE_TYPE, "ShortCut"), "set_shortcut", "get_shortcut"); @@ -563,7 +563,7 @@ BaseButton *ButtonGroup::get_pressed_button() { void ButtonGroup::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_pressed_button:BaseButton"), &ButtonGroup::get_pressed_button); + ClassDB::bind_method(D_METHOD("get_pressed_button"), &ButtonGroup::get_pressed_button); } ButtonGroup::ButtonGroup() { diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h index e382df61c..dfcf3b0f8 100644 --- a/scene/gui/base_button.h +++ b/scene/gui/base_button.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -72,8 +73,8 @@ protected: virtual void pressed(); virtual void toggled(bool p_pressed); static void _bind_methods(); - virtual void _gui_input(InputEvent p_event); - virtual void _unhandled_input(InputEvent p_event); + virtual void _gui_input(Ref<InputEvent> p_event); + virtual void _unhandled_input(Ref<InputEvent> p_event); void _notification(int p_what); public: diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp index 1096c43c1..16b2cfa08 100644 --- a/scene/gui/box_container.cpp +++ b/scene/gui/box_container.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -307,6 +308,7 @@ MarginContainer *VBoxContainer::add_margin_child(const String &p_label, Control l->set_text(p_label); add_child(l); MarginContainer *mc = memnew(MarginContainer); + mc->add_constant_override("margin_left", 0); mc->add_child(p_control); add_child(mc); if (p_expand) diff --git a/scene/gui/box_container.h b/scene/gui/box_container.h index 04b074896..d544ff79d 100644 --- a/scene/gui/box_container.h +++ b/scene/gui/box_container.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp index 23915c51a..9a0b3b3c8 100644 --- a/scene/gui/button.cpp +++ b/scene/gui/button.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -68,6 +69,7 @@ void Button::_notification(int p_what) { RID ci = get_canvas_item(); Size2 size = get_size(); Color color; + Color color_icon(1, 1, 1, 1); //print_line(get_text()+": "+itos(is_flat())+" hover "+itos(get_draw_mode())); @@ -81,29 +83,40 @@ void Button::_notification(int p_what) { if (!flat) style->draw(ci, Rect2(Point2(0, 0), size)); color = get_color("font_color"); + if (has_color("icon_color_normal")) + color_icon = get_color("icon_color_normal"); } break; case DRAW_PRESSED: { style = get_stylebox("pressed"); - style->draw(ci, Rect2(Point2(0, 0), size)); + if (!flat) + style->draw(ci, Rect2(Point2(0, 0), size)); if (has_color("font_color_pressed")) color = get_color("font_color_pressed"); else color = get_color("font_color"); + if (has_color("icon_color_pressed")) + color_icon = get_color("icon_color_pressed"); } break; case DRAW_HOVER: { style = get_stylebox("hover"); - style->draw(ci, Rect2(Point2(0, 0), size)); + if (!flat) + style->draw(ci, Rect2(Point2(0, 0), size)); color = get_color("font_color_hover"); + if (has_color("icon_color_hover")) + color_icon = get_color("icon_color_hover"); } break; case DRAW_DISABLED: { style = get_stylebox("disabled"); - style->draw(ci, Rect2(Point2(0, 0), size)); + if (!flat) + style->draw(ci, Rect2(Point2(0, 0), size)); color = get_color("font_color_disabled"); + if (has_color("icon_color_disabled")) + color_icon = get_color("icon_color_disabled"); } break; } @@ -147,8 +160,9 @@ void Button::_notification(int p_what) { if (!_icon.is_null()) { int valign = size.height - style->get_minimum_size().y; - - _icon->draw(ci, style->get_offset() + Point2(0, Math::floor((valign - _icon->get_height()) / 2.0)), is_disabled() ? Color(1, 1, 1, 0.4) : Color(1, 1, 1)); + if (is_disabled()) + color_icon.a = 0.4; + _icon->draw(ci, style->get_offset() + Point2(0, Math::floor((valign - _icon->get_height()) / 2.0)), color_icon); } } } @@ -222,8 +236,8 @@ void Button::_bind_methods() { ClassDB::bind_method(D_METHOD("set_text", "text"), &Button::set_text); ClassDB::bind_method(D_METHOD("get_text"), &Button::get_text); - ClassDB::bind_method(D_METHOD("set_button_icon", "texture:Texture"), &Button::set_icon); - ClassDB::bind_method(D_METHOD("get_button_icon:Texture"), &Button::get_icon); + ClassDB::bind_method(D_METHOD("set_button_icon", "texture"), &Button::set_icon); + ClassDB::bind_method(D_METHOD("get_button_icon"), &Button::get_icon); ClassDB::bind_method(D_METHOD("set_flat", "enabled"), &Button::set_flat); ClassDB::bind_method(D_METHOD("set_clip_text", "enabled"), &Button::set_clip_text); ClassDB::bind_method(D_METHOD("get_clip_text"), &Button::get_clip_text); diff --git a/scene/gui/button.h b/scene/gui/button.h index 38605bd3e..499e44c0e 100644 --- a/scene/gui/button.h +++ b/scene/gui/button.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/button_array.cpp b/scene/gui/button_array.cpp deleted file mode 100644 index c1cb9ad85..000000000 --- a/scene/gui/button_array.cpp +++ /dev/null @@ -1,541 +0,0 @@ -/*************************************************************************/ -/* button_array.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "button_array.h" - -bool ButtonArray::_set(const StringName &p_name, const Variant &p_value) { - - String n = String(p_name); - if (n.begins_with("button/")) { - - String what = n.get_slicec('/', 1); - if (what == "count") { - int new_size = p_value; - if (new_size > 0 && buttons.size() == 0) { - selected = 0; - } - - if (new_size < buttons.size()) { - if (selected >= new_size) - selected = new_size - 1; - } - buttons.resize(new_size); - _change_notify(); - minimum_size_changed(); - } else if (what == "align") { - set_align(Align(p_value.operator int())); - } else if (what == "selected") { - set_selected(p_value); - } else if (what == "min_button_size") { - min_button_size = p_value; - } else { - int idx = what.to_int(); - ERR_FAIL_INDEX_V(idx, buttons.size(), false); - String f = n.get_slicec('/', 2); - if (f == "text") { - buttons[idx].text = p_value; - buttons[idx].xl_text = XL_MESSAGE(p_value); - } else if (f == "tooltip") - buttons[idx].tooltip = p_value; - else if (f == "icon") - buttons[idx].icon = p_value; - else - return false; - } - - update(); - return true; - } - - return false; -} - -bool ButtonArray::_get(const StringName &p_name, Variant &r_ret) const { - - String n = String(p_name); - if (n.begins_with("button/")) { - - String what = n.get_slicec('/', 1); - if (what == "count") { - r_ret = buttons.size(); - } else if (what == "align") { - r_ret = get_align(); - } else if (what == "selected") { - r_ret = get_selected(); - } else if (what == "min_button_size") { - r_ret = min_button_size; - } else { - int idx = what.to_int(); - ERR_FAIL_INDEX_V(idx, buttons.size(), false); - String f = n.get_slicec('/', 2); - if (f == "text") - r_ret = buttons[idx].text; - else if (f == "tooltip") - r_ret = buttons[idx].tooltip; - else if (f == "icon") - r_ret = buttons[idx].icon; - else - return false; - } - - return true; - } - - return false; -} -void ButtonArray::_get_property_list(List<PropertyInfo> *p_list) const { - - p_list->push_back(PropertyInfo(Variant::INT, "button/count", PROPERTY_HINT_RANGE, "0,512,1")); - p_list->push_back(PropertyInfo(Variant::INT, "button/min_button_size", PROPERTY_HINT_RANGE, "0,1024,1")); - p_list->push_back(PropertyInfo(Variant::INT, "button/align", PROPERTY_HINT_ENUM, "Begin,Center,End,Fill,Expand")); - for (int i = 0; i < buttons.size(); i++) { - String base = "button/" + itos(i) + "/"; - p_list->push_back(PropertyInfo(Variant::STRING, base + "text")); - p_list->push_back(PropertyInfo(Variant::STRING, base + "tooltip")); - p_list->push_back(PropertyInfo(Variant::OBJECT, base + "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture")); - } - if (buttons.size() > 0) { - p_list->push_back(PropertyInfo(Variant::INT, "button/selected", PROPERTY_HINT_RANGE, "0," + itos(buttons.size() - 1) + ",1")); - } -} - -Size2 ButtonArray::get_minimum_size() const { - - Ref<StyleBox> style_normal = get_stylebox("normal"); - Ref<StyleBox> style_selected = get_stylebox("selected"); - Ref<Font> font_normal = get_font("font"); - Ref<Font> font_selected = get_font("font_selected"); - int icon_sep = get_constant("icon_separator"); - int button_sep = get_constant("button_separator"); - - Size2 minsize; - - for (int i = 0; i < buttons.size(); i++) { - - Ref<StyleBox> sb = i == selected ? style_selected : style_normal; - Ref<Font> f = i == selected ? font_selected : font_normal; - - Size2 ms; - ms = f->get_string_size(buttons[i].xl_text); - if (buttons[i].icon.is_valid()) { - - Size2 bs = buttons[i].icon->get_size(); - ms.height = MAX(ms.height, bs.height); - ms.width += bs.width + icon_sep; - } - - ms += sb->get_minimum_size(); - - buttons[i]._ms_cache = ms[orientation]; - - minsize[orientation] += ms[orientation]; - if (i > 0) - minsize[orientation] += button_sep; - minsize[!orientation] = MAX(minsize[!orientation], ms[!orientation]); - } - - return minsize; -} - -void ButtonArray::_notification(int p_what) { - - switch (p_what) { - case NOTIFICATION_MOUSE_EXIT: { - hover = -1; - update(); - } break; - case NOTIFICATION_READY: { - MethodInfo mi; - mi.name = "mouse_sub_enter"; - - add_user_signal(mi); - - } break; - case NOTIFICATION_DRAW: { - - Size2 size = get_size(); - Size2 minsize = get_combined_minimum_size(); - Ref<StyleBox> style_normal = get_stylebox("normal"); - Ref<StyleBox> style_selected = get_stylebox("selected"); - Ref<StyleBox> style_focus = get_stylebox("focus"); - Ref<StyleBox> style_hover = get_stylebox("hover"); - Ref<Font> font_normal = get_font("font"); - Ref<Font> font_selected = get_font("font_selected"); - int icon_sep = get_constant("icon_separator"); - int button_sep = get_constant("button_separator"); - Color color_normal = get_color("font_color"); - Color color_selected = get_color("font_color_selected"); - - int sep = button_sep; - int ofs = 0; - int expand = 0; - - switch (align) { - case ALIGN_BEGIN: { - - ofs = 0; - } break; - case ALIGN_CENTER: { - - ofs = Math::floor((size[orientation] - minsize[orientation]) / 2); - } break; - case ALIGN_END: { - - ofs = Math::floor((size[orientation] - minsize[orientation])); - } break; - case ALIGN_FILL: { - - if (buttons.size() > 1) - sep += Math::floor((size[orientation] - minsize[orientation]) / (buttons.size() - 1.0)); - ofs = 0; - } break; - case ALIGN_EXPAND_FILL: { - - ofs = 0; - expand = size[orientation] - minsize[orientation]; - } break; - } - - int op_size = orientation == VERTICAL ? size.width : size.height; - - for (int i = 0; i < buttons.size(); i++) { - - int ms = buttons[i]._ms_cache; - int s = ms; - if (expand > 0) { - s += expand / buttons.size(); - } - if (min_button_size != -1 && s < min_button_size) { - s = min_button_size; - } - - Rect2 r; - r.pos[orientation] = ofs; - r.pos[!orientation] = 0; - r.size[orientation] = s; - r.size[!orientation] = op_size; - - Ref<Font> f; - Color c; - Point2 sbsize; - Point2 sbofs; - if (i == selected) { - draw_style_box(style_selected, r); - sbsize = style_selected->get_minimum_size(); - sbofs = style_selected->get_offset(); - f = font_selected; - c = color_selected; - if (has_focus()) - draw_style_box(style_focus, r); - } else { - if (hover == i) - draw_style_box(style_hover, r); - else if (!flat) - draw_style_box(style_normal, r); - sbsize = style_normal->get_minimum_size(); - sbofs = style_normal->get_offset(); - f = font_normal; - c = color_normal; - } - - Size2 ssize = f->get_string_size(buttons[i].xl_text); - if (buttons[i].icon.is_valid()) { - - ssize.x += buttons[i].icon->get_width(); - } - Point2 text_ofs = ((r.size - ssize - sbsize) / 2.0 + Point2(0, f->get_ascent())).floor() + sbofs; - if (buttons[i].icon.is_valid()) { - - draw_texture(buttons[i].icon, r.pos + Point2(text_ofs.x, Math::floor((r.size.height - buttons[i].icon->get_height()) / 2.0))); - text_ofs.x += buttons[i].icon->get_width() + icon_sep; - } - draw_string(f, text_ofs + r.pos, buttons[i].xl_text, c); - buttons[i]._pos_cache = ofs; - buttons[i]._size_cache = s; - - ofs += s; - ofs += sep; - } - - } break; - } -} - -void ButtonArray::_gui_input(const InputEvent &p_event) { - - if ( - ((orientation == HORIZONTAL && p_event.is_action("ui_left")) || - (orientation == VERTICAL && p_event.is_action("ui_up"))) && - p_event.is_pressed() && selected > 0) { - set_selected(selected - 1); - accept_event(); - emit_signal("button_selected", selected); - return; - } - - if ( - ((orientation == HORIZONTAL && p_event.is_action("ui_right")) || - (orientation == VERTICAL && p_event.is_action("ui_down"))) && - p_event.is_pressed() && selected < (buttons.size() - 1)) { - set_selected(selected + 1); - accept_event(); - emit_signal("button_selected", selected); - return; - } - - if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed && p_event.mouse_button.button_index == BUTTON_LEFT) { - - int ofs = orientation == HORIZONTAL ? p_event.mouse_button.x : p_event.mouse_button.y; - - for (int i = 0; i < buttons.size(); i++) { - - if (ofs >= buttons[i]._pos_cache && ofs < buttons[i]._pos_cache + buttons[i]._size_cache) { - - set_selected(i); - emit_signal("button_selected", i); - return; - } - } - } - - if (p_event.type == InputEvent::MOUSE_MOTION) { - - int ofs = orientation == HORIZONTAL ? p_event.mouse_motion.x : p_event.mouse_motion.y; - int new_hover = -1; - for (int i = 0; i < buttons.size(); i++) { - - if (ofs >= buttons[i]._pos_cache && ofs < buttons[i]._pos_cache + buttons[i]._size_cache) { - - new_hover = i; - break; - } - } - - if (new_hover != hover) { - hover = new_hover; - emit_signal("mouse_sub_enter"); - update(); - } - } -} - -String ButtonArray::get_tooltip(const Point2 &p_pos) const { - - int ofs = orientation == HORIZONTAL ? p_pos.x : p_pos.y; - for (int i = 0; i < buttons.size(); i++) { - - if (ofs >= buttons[i]._pos_cache && ofs < buttons[i]._pos_cache + buttons[i]._size_cache) - return buttons[i].tooltip; - } - return Control::get_tooltip(p_pos); -} - -void ButtonArray::set_align(Align p_align) { - - align = p_align; - update(); -} - -ButtonArray::Align ButtonArray::get_align() const { - - return align; -} - -void ButtonArray::set_flat(bool p_flat) { - - flat = p_flat; - update(); -} - -bool ButtonArray::is_flat() const { - - return flat; -} - -void ButtonArray::add_button(const String &p_text, const String &p_tooltip) { - - Button button; - button.text = p_text; - button.xl_text = XL_MESSAGE(p_text); - button.tooltip = p_tooltip; - buttons.push_back(button); - update(); - - if (selected == -1) - selected = 0; - - minimum_size_changed(); -} - -void ButtonArray::add_icon_button(const Ref<Texture> &p_icon, const String &p_text, const String &p_tooltip) { - - Button button; - button.text = p_text; - button.xl_text = XL_MESSAGE(p_text); - button.icon = p_icon; - button.tooltip = p_tooltip; - buttons.push_back(button); - if (selected == -1) - selected = 0; - - update(); -} - -void ButtonArray::set_button_text(int p_button, const String &p_text) { - - ERR_FAIL_INDEX(p_button, buttons.size()); - buttons[p_button].text = p_text; - buttons[p_button].xl_text = XL_MESSAGE(p_text); - update(); - minimum_size_changed(); -} - -void ButtonArray::set_button_tooltip(int p_button, const String &p_text) { - - ERR_FAIL_INDEX(p_button, buttons.size()); - buttons[p_button].tooltip = p_text; -} - -void ButtonArray::set_button_icon(int p_button, const Ref<Texture> &p_icon) { - - ERR_FAIL_INDEX(p_button, buttons.size()); - buttons[p_button].icon = p_icon; - update(); - minimum_size_changed(); -} - -String ButtonArray::get_button_text(int p_button) const { - - ERR_FAIL_INDEX_V(p_button, buttons.size(), ""); - return buttons[p_button].text; -} - -String ButtonArray::get_button_tooltip(int p_button) const { - - ERR_FAIL_INDEX_V(p_button, buttons.size(), ""); - return buttons[p_button].tooltip; -} - -Ref<Texture> ButtonArray::get_button_icon(int p_button) const { - - ERR_FAIL_INDEX_V(p_button, buttons.size(), Ref<Texture>()); - return buttons[p_button].icon; -} - -int ButtonArray::get_selected() const { - - return selected; -} - -int ButtonArray::get_hovered() const { - - return hover; -} - -void ButtonArray::set_selected(int p_selected) { - - ERR_FAIL_INDEX(p_selected, buttons.size()); - selected = p_selected; - update(); -} - -void ButtonArray::erase_button(int p_button) { - - ERR_FAIL_INDEX(p_button, buttons.size()); - buttons.remove(p_button); - if (p_button >= selected) - selected--; - if (selected < 0) - selected = 0; - if (selected >= buttons.size()) - selected = buttons.size() - 1; - - update(); -} - -void ButtonArray::clear() { - - buttons.clear(); - selected = -1; - update(); -} - -int ButtonArray::get_button_count() const { - - return buttons.size(); -} - -void ButtonArray::get_translatable_strings(List<String> *p_strings) const { - - for (int i = 0; i < buttons.size(); i++) { - p_strings->push_back(buttons[i].text); - p_strings->push_back(buttons[i].tooltip); - } -} - -void ButtonArray::_bind_methods() { - - ClassDB::bind_method(D_METHOD("add_button", "text", "tooltip"), &ButtonArray::add_button, DEFVAL("")); - ClassDB::bind_method(D_METHOD("add_icon_button", "icon:Texture", "text", "tooltip"), &ButtonArray::add_icon_button, DEFVAL(""), DEFVAL("")); - ClassDB::bind_method(D_METHOD("set_button_text", "button_idx", "text"), &ButtonArray::set_button_text); - ClassDB::bind_method(D_METHOD("set_button_tooltip", "button_idx", "text"), &ButtonArray::set_button_tooltip); - ClassDB::bind_method(D_METHOD("set_button_icon", "button_idx", "icon:Texture"), &ButtonArray::set_button_icon); - ClassDB::bind_method(D_METHOD("get_button_text", "button_idx"), &ButtonArray::get_button_text); - ClassDB::bind_method(D_METHOD("get_button_tooltip", "button_idx"), &ButtonArray::get_button_tooltip); - ClassDB::bind_method(D_METHOD("get_button_icon:Texture", "button_idx"), &ButtonArray::get_button_icon); - ClassDB::bind_method(D_METHOD("get_button_count"), &ButtonArray::get_button_count); - ClassDB::bind_method(D_METHOD("set_flat", "enabled"), &ButtonArray::set_flat); - ClassDB::bind_method(D_METHOD("is_flat"), &ButtonArray::is_flat); - ClassDB::bind_method(D_METHOD("get_selected"), &ButtonArray::get_selected); - ClassDB::bind_method(D_METHOD("get_hovered"), &ButtonArray::get_hovered); - ClassDB::bind_method(D_METHOD("set_selected", "button_idx"), &ButtonArray::set_selected); - ClassDB::bind_method(D_METHOD("erase_button", "button_idx"), &ButtonArray::erase_button); - ClassDB::bind_method(D_METHOD("clear"), &ButtonArray::clear); - - ClassDB::bind_method(D_METHOD("_gui_input"), &ButtonArray::_gui_input); - - BIND_CONSTANT(ALIGN_BEGIN); - BIND_CONSTANT(ALIGN_CENTER); - BIND_CONSTANT(ALIGN_END); - BIND_CONSTANT(ALIGN_FILL); - BIND_CONSTANT(ALIGN_EXPAND_FILL); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat"); - - ADD_SIGNAL(MethodInfo("button_selected", PropertyInfo(Variant::INT, "button_idx"))); -} - -ButtonArray::ButtonArray(Orientation p_orientation) { - - orientation = p_orientation; - selected = -1; - set_focus_mode(FOCUS_ALL); - hover = -1; - flat = false; - min_button_size = -1; -} diff --git a/scene/gui/button_array.h b/scene/gui/button_array.h deleted file mode 100644 index dac130e79..000000000 --- a/scene/gui/button_array.h +++ /dev/null @@ -1,130 +0,0 @@ -/*************************************************************************/ -/* button_array.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef BUTTON_ARRAY_H -#define BUTTON_ARRAY_H - -#include "scene/gui/control.h" - -class ButtonArray : public Control { - - GDCLASS(ButtonArray, Control); - -public: - enum Align { - ALIGN_BEGIN, - ALIGN_CENTER, - ALIGN_END, - ALIGN_FILL, - ALIGN_EXPAND_FILL - }; - -private: - Orientation orientation; - Align align; - - struct Button { - - String text; - String xl_text; - String tooltip; - Ref<Texture> icon; - mutable int _ms_cache; - mutable int _pos_cache; - mutable int _size_cache; - }; - - int selected; - int hover; - bool flat; - double min_button_size; - - Vector<Button> buttons; - -protected: - bool _set(const StringName &p_name, const Variant &p_value); - bool _get(const StringName &p_name, Variant &r_ret) const; - void _get_property_list(List<PropertyInfo> *p_list) const; - - void _notification(int p_what); - static void _bind_methods(); - -public: - void _gui_input(const InputEvent &p_event); - - void set_align(Align p_align); - Align get_align() const; - - void set_flat(bool p_flat); - bool is_flat() const; - - void add_button(const String &p_button, const String &p_tooltip = ""); - void add_icon_button(const Ref<Texture> &p_icon, const String &p_button = "", const String &p_tooltip = ""); - - void set_button_text(int p_button, const String &p_text); - void set_button_tooltip(int p_button, const String &p_text); - void set_button_icon(int p_button, const Ref<Texture> &p_icon); - - String get_button_text(int p_button) const; - String get_button_tooltip(int p_button) const; - Ref<Texture> get_button_icon(int p_button) const; - - int get_selected() const; - int get_hovered() const; - void set_selected(int p_selected); - - int get_button_count() const; - - void erase_button(int p_button); - void clear(); - - virtual Size2 get_minimum_size() const; - - virtual void get_translatable_strings(List<String> *p_strings) const; - virtual String get_tooltip(const Point2 &p_pos) const; - - ButtonArray(Orientation p_orientation = HORIZONTAL); -}; - -class HButtonArray : public ButtonArray { - GDCLASS(HButtonArray, ButtonArray); - -public: - HButtonArray() - : ButtonArray(HORIZONTAL){}; -}; - -class VButtonArray : public ButtonArray { - GDCLASS(VButtonArray, ButtonArray); - -public: - VButtonArray() - : ButtonArray(VERTICAL){}; -}; - -#endif // BUTTON_ARRAY_H diff --git a/scene/gui/button_group.cpp b/scene/gui/button_group.cpp index 21c1559b8..e54e810d7 100644 --- a/scene/gui/button_group.cpp +++ b/scene/gui/button_group.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -151,12 +152,12 @@ int ButtonGroup::get_pressed_button_index() const { void ButtonGroup::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_pressed_button:BaseButton"),&ButtonGroup::get_pressed_button); + ClassDB::bind_method(D_METHOD("get_pressed_button"),&ButtonGroup::get_pressed_button); ClassDB::bind_method(D_METHOD("get_pressed_button_index"),&ButtonGroup::get_pressed_button_index); - ClassDB::bind_method(D_METHOD("get_focused_button:BaseButton"),&ButtonGroup::get_focused_button); + ClassDB::bind_method(D_METHOD("get_focused_button"),&ButtonGroup::get_focused_button); ClassDB::bind_method(D_METHOD("get_button_list"),&ButtonGroup::_get_button_list); ClassDB::bind_method(D_METHOD("_pressed"),&ButtonGroup::_pressed); - ClassDB::bind_method(D_METHOD("set_pressed_button","button:BaseButton"),&ButtonGroup::_pressed); + ClassDB::bind_method(D_METHOD("set_pressed_button","button"),&ButtonGroup::_pressed); ADD_SIGNAL( MethodInfo("button_selected",PropertyInfo(Variant::OBJECT,"button",PROPERTY_HINT_RESOURCE_TYPE,"BaseButton"))); } diff --git a/scene/gui/button_group.h b/scene/gui/button_group.h index 38acd0698..93c3aaaeb 100644 --- a/scene/gui/button_group.h +++ b/scene/gui/button_group.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/center_container.cpp b/scene/gui/center_container.cpp index 9cee8c0cc..bdc811870 100644 --- a/scene/gui/center_container.cpp +++ b/scene/gui/center_container.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/center_container.h b/scene/gui/center_container.h index c2deb823f..30b526e89 100644 --- a/scene/gui/center_container.h +++ b/scene/gui/center_container.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp index c7e2f4e7f..b61d51659 100644 --- a/scene/gui/check_box.cpp +++ b/scene/gui/check_box.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/check_box.h b/scene/gui/check_box.h index 9b682de17..ec8e097ba 100644 --- a/scene/gui/check_box.h +++ b/scene/gui/check_box.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/check_button.cpp b/scene/gui/check_button.cpp index 6b24e0889..1c3d4df30 100644 --- a/scene/gui/check_button.cpp +++ b/scene/gui/check_button.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/check_button.h b/scene/gui/check_button.h index adf210a1e..8634858cf 100644 --- a/scene/gui/check_button.h +++ b/scene/gui/check_button.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 0f982167b..5e110362c 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -47,7 +48,28 @@ void ColorPicker::_notification(int p_what) { btn_pick->set_icon(get_icon("screen_picker", "ColorPicker")); _update_color(); - } + } break; + + case NOTIFICATION_PARENTED: { + for (int i = 0; i < 4; i++) + set_margin((Margin)i, get_constant("margin")); + } break; + + case NOTIFICATION_VISIBILITY_CHANGED: { + if (get_parent()) { + Popup *p = get_parent()->cast_to<Popup>(); + if (p) + p->set_size(Size2(get_combined_minimum_size().width + get_constant("margin") * 2, get_combined_minimum_size().height + get_constant("margin") * 2)); + } + } break; + + case MainLoop::NOTIFICATION_WM_QUIT_REQUEST: { + if (screen != NULL) { + if (screen->is_visible()) { + screen->hide(); + } + } + } break; } } @@ -83,9 +105,6 @@ void ColorPicker::set_pick_color(const Color &p_color) { if (!is_inside_tree()) return; - return; //it crashes, so returning - uv_edit->get_child(0)->cast_to<Control>()->update(); - w_edit->get_child(0)->cast_to<Control>()->update(); _update_color(); } @@ -116,9 +135,6 @@ void ColorPicker::_value_changed(double) { } set_pick_color(color); - - _update_text_value(); - emit_signal("color_changed", color); } @@ -155,6 +171,8 @@ void ColorPicker::_update_color() { _update_text_value(); sample->update(); + uv_edit->update(); + w_edit->update(); updating = false; } @@ -177,7 +195,7 @@ void ColorPicker::_update_presets() { } } - Image i(size.x * presets.size(), size.y, false, Image::FORMAT_RGB8, img); + Ref<Image> i = memnew(Image(size.x * presets.size(), size.y, false, Image::FORMAT_RGB8, img)); Ref<ImageTexture> t; t.instance(); @@ -249,36 +267,36 @@ void ColorPicker::_update_text_value() { } void ColorPicker::_sample_draw() { - sample->draw_rect(Rect2(Point2(), Size2(256, 20)), color); + sample->draw_rect(Rect2(Point2(), Size2(uv_edit->get_size().width, sample->get_size().height * 0.95)), color); } -void ColorPicker::_hsv_draw(int p_wich, Control *c) { +void ColorPicker::_hsv_draw(int p_which, Control *c) { if (!c) return; - if (p_wich == 0) { + if (p_which == 0) { Vector<Point2> points; points.push_back(Vector2()); points.push_back(Vector2(c->get_size().x, 0)); points.push_back(c->get_size()); points.push_back(Vector2(0, c->get_size().y)); Vector<Color> colors; - colors.push_back(Color(1, 1, 1)); - colors.push_back(Color(1, 1, 1)); - colors.push_back(Color()); - colors.push_back(Color()); + colors.push_back(Color(1, 1, 1, 1)); + colors.push_back(Color(1, 1, 1, 1)); + colors.push_back(Color(0, 0, 0, 1)); + colors.push_back(Color(0, 0, 0, 1)); c->draw_polygon(points, colors); Vector<Color> colors2; Color col = color; - col.set_hsv(color.get_h(), 1, 1); + col.set_hsv(h, 1, 1); col.a = 0; colors2.push_back(col); col.a = 1; colors2.push_back(col); - col.set_hsv(color.get_h(), 1, 0); + col.set_hsv(h, 1, 0); colors2.push_back(col); col.a = 0; colors2.push_back(col); - c->draw_polygon(points, colors); + c->draw_polygon(points, colors2); int x = CLAMP(c->get_size().x * s, 0, c->get_size().x); int y = CLAMP(c->get_size().y - c->get_size().y * v, 0, c->get_size().y); col = color; @@ -286,25 +304,27 @@ void ColorPicker::_hsv_draw(int p_wich, Control *c) { c->draw_line(Point2(x, 0), Point2(x, c->get_size().y), col.inverted()); c->draw_line(Point2(0, y), Point2(c->get_size().x, y), col.inverted()); c->draw_line(Point2(x, y), Point2(x, y), Color(1, 1, 1), 2); - } else if (p_wich == 1) { + } else if (p_which == 1) { Ref<Texture> hue = get_icon("color_hue", "ColorPicker"); c->draw_texture_rect(hue, Rect2(Point2(), c->get_size())); - int y = c->get_size().y - c->get_size().y * h; + int y = c->get_size().y - c->get_size().y * (1.0 - h); Color col = Color(); col.set_hsv(h, 1, 1); c->draw_line(Point2(0, y), Point2(c->get_size().x, y), col.inverted()); } } -void ColorPicker::_uv_input(const InputEvent &ev) { - if (ev.type == InputEvent::MOUSE_BUTTON) { - const InputEventMouseButton &bev = ev.mouse_button; - if (bev.pressed && bev.button_index == BUTTON_LEFT) { +void ColorPicker::_uv_input(const Ref<InputEvent> &p_event) { + + Ref<InputEventMouseButton> bev = p_event; + + if (bev.is_valid()) { + if (bev->is_pressed() && bev->get_button_index() == BUTTON_LEFT) { changing_color = true; - float x = CLAMP((float)bev.x, 0, 256); - float y = CLAMP((float)bev.y, 0, 256); - s = x / 256; - v = 1.0 - y / 256.0; + float x = CLAMP((float)bev->get_position().x, 0, uv_edit->get_size().width); + float y = CLAMP((float)bev->get_position().y, 0, uv_edit->get_size().height); + s = x / uv_edit->get_size().width; + v = 1.0 - y / uv_edit->get_size().height; color.set_hsv(h, s, v, color.a); last_hsv = color; set_pick_color(color); @@ -313,14 +333,17 @@ void ColorPicker::_uv_input(const InputEvent &ev) { } else { changing_color = false; } - } else if (ev.type == InputEvent::MOUSE_MOTION) { - const InputEventMouse &bev = ev.mouse_motion; + } + + Ref<InputEventMouseMotion> mev = p_event; + + if (mev.is_valid()) { if (!changing_color) return; - float x = CLAMP((float)bev.x, 0, 256); - float y = CLAMP((float)bev.y, 0, 256); - s = x / 256; - v = 1.0 - y / 256.0; + float x = CLAMP((float)mev->get_position().x, 0, uv_edit->get_size().width); + float y = CLAMP((float)mev->get_position().y, 0, uv_edit->get_size().height); + s = x / uv_edit->get_size().width; + v = 1.0 - y / uv_edit->get_size().height; color.set_hsv(h, s, v, color.a); last_hsv = color; set_pick_color(color); @@ -329,13 +352,16 @@ void ColorPicker::_uv_input(const InputEvent &ev) { } } -void ColorPicker::_w_input(const InputEvent &ev) { - if (ev.type == InputEvent::MOUSE_BUTTON) { - const InputEventMouseButton &bev = ev.mouse_button; - if (bev.pressed && bev.button_index == BUTTON_LEFT) { - changing_color = true; - h = 1 - ((float)bev.y) / 256.0; +void ColorPicker::_w_input(const Ref<InputEvent> &p_event) { + Ref<InputEventMouseButton> bev = p_event; + + if (bev.is_valid()) { + + if (bev->is_pressed() && bev->get_button_index() == BUTTON_LEFT) { + changing_color = true; + float y = CLAMP((float)bev->get_position().y, 0, w_edit->get_size().height); + h = y / w_edit->get_size().height; } else { changing_color = false; } @@ -344,12 +370,16 @@ void ColorPicker::_w_input(const InputEvent &ev) { set_pick_color(color); _update_color(); emit_signal("color_changed", color); - } else if (ev.type == InputEvent::MOUSE_MOTION) { - const InputEventMouse &bev = ev.mouse_motion; + } + + Ref<InputEventMouseMotion> mev = p_event; + + if (mev.is_valid()) { + if (!changing_color) return; - float y = CLAMP((float)bev.y, 0, 256); - h = 1.0 - y / 256.0; + float y = CLAMP((float)mev->get_position().y, 0, w_edit->get_size().height); + h = y / w_edit->get_size().height; color.set_hsv(h, s, v, color.a); last_hsv = color; set_pick_color(color); @@ -358,23 +388,30 @@ void ColorPicker::_w_input(const InputEvent &ev) { } } -void ColorPicker::_preset_input(const InputEvent &ev) { - if (ev.type == InputEvent::MOUSE_BUTTON) { - const InputEventMouseButton &bev = ev.mouse_button; - if (bev.pressed && bev.button_index == BUTTON_LEFT) { - int index = bev.x / (preset->get_size().x / presets.size()); +void ColorPicker::_preset_input(const Ref<InputEvent> &p_event) { + + Ref<InputEventMouseButton> bev = p_event; + + if (bev.is_valid()) { + + if (bev->is_pressed() && bev->get_button_index() == BUTTON_LEFT) { + int index = bev->get_position().x / (preset->get_size().x / presets.size()); set_pick_color(presets[index]); - } else if (bev.pressed && bev.button_index == BUTTON_RIGHT) { - int index = bev.x / (preset->get_size().x / presets.size()); + } else if (bev->is_pressed() && bev->get_button_index() == BUTTON_RIGHT) { + int index = bev->get_position().x / (preset->get_size().x / presets.size()); presets.erase(presets[index]); _update_presets(); bt_add_preset->show(); } _update_color(); emit_signal("color_changed", color); - } else if (ev.type == InputEvent::MOUSE_MOTION) { - const InputEventMouse &mev = ev.mouse_motion; - int index = mev.x * presets.size(); + } + + Ref<InputEventMouseMotion> mev = p_event; + + if (mev.is_valid()) { + + int index = mev->get_position().x * presets.size(); if (preset->get_size().x != 0) { index /= preset->get_size().x; } @@ -386,31 +423,30 @@ void ColorPicker::_preset_input(const InputEvent &ev) { } } -void ColorPicker::_screen_input(const InputEvent &ev) { - if (ev.type == InputEvent::MOUSE_BUTTON) { - const InputEventMouseButton &bev = ev.mouse_button; - if (bev.button_index == BUTTON_LEFT && !bev.pressed) { +void ColorPicker::_screen_input(const Ref<InputEvent> &p_event) { + + Ref<InputEventMouseButton> bev = p_event; + + if (bev.is_valid()) { + + if (bev->get_button_index() == BUTTON_LEFT && !bev->is_pressed()) { emit_signal("color_changed", color); screen->hide(); } - } else if (ev.type == InputEvent::MOUSE_MOTION) { - const InputEventMouse &mev = ev.mouse_motion; - Viewport *r = get_tree()->get_root(); - if (!r->get_visible_rect().has_point(Point2(mev.global_x, mev.global_y))) - return; - Image img = r->get_screen_capture(); - if (!img.empty()) { - last_capture = img; - r->queue_screen_capture(); - } - if (!last_capture.empty()) { - int pw = last_capture.get_format() == Image::FORMAT_RGBA8 ? 4 : 3; - int ofs = (mev.global_y * last_capture.get_width() + mev.global_x) * pw; - - PoolVector<uint8_t>::Read r = last_capture.get_data().read(); + } - Color c(r[ofs + 0] / 255.0, r[ofs + 1] / 255.0, r[ofs + 2] / 255.0); + Ref<InputEventMouseMotion> mev = p_event; + if (mev.is_valid()) { + Viewport *r = get_tree()->get_root(); + if (!r->get_visible_rect().has_point(Point2(mev->get_global_position().x, mev->get_global_position().y))) + return; + Ref<Image> img = r->get_texture()->get_data(); + if (img.is_valid() && !img->empty()) { + img->lock(); + Vector2 ofs = mev->get_global_position() - r->get_visible_rect().get_position(); + Color c = img->get_pixel(ofs.x, r->get_visible_rect().size.height - ofs.y); + img->unlock(); set_pick_color(c); } } @@ -427,11 +463,11 @@ void ColorPicker::_screen_pick_pressed() { r->add_child(screen); screen->set_as_toplevel(true); screen->set_area_as_parent_rect(); + screen->set_default_cursor_shape(CURSOR_POINTING_HAND); screen->connect("gui_input", this, "_screen_input"); } screen->raise(); screen->show_modal(); - r->queue_screen_capture(); } void ColorPicker::_bind_methods() { @@ -442,7 +478,7 @@ void ColorPicker::_bind_methods() { ClassDB::bind_method(D_METHOD("is_raw_mode"), &ColorPicker::is_raw_mode); ClassDB::bind_method(D_METHOD("set_edit_alpha", "show"), &ColorPicker::set_edit_alpha); ClassDB::bind_method(D_METHOD("is_editing_alpha"), &ColorPicker::is_editing_alpha); - ClassDB::bind_method(D_METHOD("add_preset"), &ColorPicker::add_preset); + ClassDB::bind_method(D_METHOD("add_preset", "color"), &ColorPicker::add_preset); ClassDB::bind_method(D_METHOD("_value_changed"), &ColorPicker::_value_changed); ClassDB::bind_method(D_METHOD("_html_entered"), &ColorPicker::_html_entered); ClassDB::bind_method(D_METHOD("_text_type_toggled"), &ColorPicker::_text_type_toggled); @@ -481,27 +517,26 @@ ColorPicker::ColorPicker() add_child(hb_smpl); HBoxContainer *hb_edit = memnew(HBoxContainer); + hb_edit->set_v_size_flags(SIZE_EXPAND_FILL); uv_edit = memnew(Control); uv_edit->connect("gui_input", this, "_uv_input"); uv_edit->set_mouse_filter(MOUSE_FILTER_PASS); - uv_edit->set_custom_minimum_size(Size2(256, 256)); - Vector<Variant> args = Vector<Variant>(); - args.push_back(0); - args.push_back(uv_edit); - uv_edit->connect("draw", this, "_hsv_draw", args); + uv_edit->set_h_size_flags(SIZE_EXPAND_FILL); + uv_edit->set_v_size_flags(SIZE_EXPAND_FILL); + uv_edit->set_custom_minimum_size(Size2(get_constant("sv_width"), get_constant("sv_height"))); + uv_edit->connect("draw", this, "_hsv_draw", make_binds(0, uv_edit)); add_child(hb_edit); w_edit = memnew(Control); //w_edit->set_ignore_mouse(false); - w_edit->set_custom_minimum_size(Size2(30, 256)); + w_edit->set_custom_minimum_size(Size2(get_constant("h_width"), 0)); + w_edit->set_h_size_flags(SIZE_FILL); + w_edit->set_v_size_flags(SIZE_EXPAND_FILL); w_edit->connect("gui_input", this, "_w_input"); - args.clear(); - args.push_back(1); - args.push_back(w_edit); - w_edit->connect("draw", this, "_hsv_draw", args); + w_edit->connect("draw", this, "_hsv_draw", make_binds(1, w_edit)); hb_edit->add_child(uv_edit); hb_edit->add_child(memnew(VSeparator)); @@ -522,9 +557,12 @@ ColorPicker::ColorPicker() HBoxContainer *hbc = memnew(HBoxContainer); labels[i] = memnew(Label(lt[i])); + labels[i]->set_custom_minimum_size(Size2(get_constant("label_width"), 0)); + labels[i]->set_v_size_flags(SIZE_SHRINK_CENTER); hbc->add_child(labels[i]); scroll[i] = memnew(HSlider); + scroll[i]->set_v_size_flags(SIZE_SHRINK_CENTER); hbc->add_child(scroll[i]); values[i] = memnew(SpinBox); @@ -543,7 +581,7 @@ ColorPicker::ColorPicker() HBoxContainer *hhb = memnew(HBoxContainer); btn_mode = memnew(CheckButton); - btn_mode->set_text("RAW Mode"); + btn_mode->set_text(TTR("Raw Mode")); btn_mode->connect("toggled", this, "set_raw_mode"); hhb->add_child(btn_mode); vbr->add_child(hhb); @@ -574,7 +612,7 @@ ColorPicker::ColorPicker() bt_add_preset = memnew(Button); bt_add_preset->set_icon(get_icon("add_preset")); - bt_add_preset->set_tooltip("Add current color as a preset"); + bt_add_preset->set_tooltip(TTR("Add current color as a preset")); bt_add_preset->connect("pressed", this, "_add_preset_pressed"); bbc->add_child(bt_add_preset); } @@ -589,9 +627,7 @@ void ColorPickerButton::_color_changed(const Color &p_color) { void ColorPickerButton::pressed() { - Size2 ms = Size2(300, picker->get_combined_minimum_size().height + 10); - popup->set_pos(get_global_pos() - Size2(0, ms.height)); - popup->set_size(ms); + popup->set_position(get_global_position() - picker->get_combined_minimum_size()); popup->popup(); picker->set_focus_on_line_edit(); } @@ -603,6 +639,10 @@ void ColorPickerButton::_notification(int p_what) { Ref<StyleBox> normal = get_stylebox("normal"); draw_rect(Rect2(normal->get_offset(), get_size() - normal->get_minimum_size()), picker->get_pick_color()); } + + if (p_what == MainLoop::NOTIFICATION_WM_QUIT_REQUEST) { + popup->hide(); + } } void ColorPickerButton::set_pick_color(const Color &p_color) { @@ -634,7 +674,7 @@ void ColorPickerButton::_bind_methods() { ClassDB::bind_method(D_METHOD("set_pick_color", "color"), &ColorPickerButton::set_pick_color); ClassDB::bind_method(D_METHOD("get_pick_color"), &ColorPickerButton::get_pick_color); - ClassDB::bind_method(D_METHOD("get_picker:ColorPicker"), &ColorPickerButton::get_picker); + ClassDB::bind_method(D_METHOD("get_picker"), &ColorPickerButton::get_picker); ClassDB::bind_method(D_METHOD("set_edit_alpha", "show"), &ColorPickerButton::set_edit_alpha); ClassDB::bind_method(D_METHOD("is_editing_alpha"), &ColorPickerButton::is_editing_alpha); ClassDB::bind_method(D_METHOD("_color_changed"), &ColorPickerButton::_color_changed); diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index bd1abeecb..d35182e06 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -46,7 +47,6 @@ class ColorPicker : public BoxContainer { private: Control *screen; - Image last_capture; Control *uv_edit; Control *w_edit; TextureRect *sample; @@ -79,12 +79,12 @@ private: void _update_text_value(); void _text_type_toggled(); void _sample_draw(); - void _hsv_draw(int p_wich, Control *c); + void _hsv_draw(int p_which, Control *c); - void _uv_input(const InputEvent &p_input); - void _w_input(const InputEvent &p_input); - void _preset_input(const InputEvent &p_input); - void _screen_input(const InputEvent &p_input); + void _uv_input(const Ref<InputEvent> &p_event); + void _w_input(const Ref<InputEvent> &p_event); + void _preset_input(const Ref<InputEvent> &p_event); + void _screen_input(const Ref<InputEvent> &p_event); void _add_preset_pressed(); void _screen_pick_pressed(); diff --git a/scene/gui/color_rect.cpp b/scene/gui/color_rect.cpp index 7febecc0b..0641302b1 100644 --- a/scene/gui/color_rect.cpp +++ b/scene/gui/color_rect.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/color_rect.h b/scene/gui/color_rect.h index c6d0164ac..65da3d9a7 100644 --- a/scene/gui/color_rect.h +++ b/scene/gui/color_rect.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp index 811b41863..4bbe15ed7 100644 --- a/scene/gui/container.cpp +++ b/scene/gui/container.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -94,19 +95,31 @@ void Container::fit_child_in_rect(Control *p_child, const Rect2 &p_rect) { Rect2 r = p_rect; if (!(p_child->get_h_size_flags() & SIZE_FILL)) { - r.size.x = minsize.x; - r.pos.x += Math::floor((p_rect.size.x - minsize.x) / 2); + r.size.x = minsize.width; + if (p_child->get_h_size_flags() & SIZE_SHRINK_END) { + r.position.x += p_rect.size.width - minsize.width; + } else if (p_child->get_h_size_flags() & SIZE_SHRINK_CENTER) { + r.position.x += Math::floor((p_rect.size.x - minsize.width) / 2); + } else { + r.position.x += 0; + } } if (!(p_child->get_v_size_flags() & SIZE_FILL)) { r.size.y = minsize.y; - r.pos.y += Math::floor((p_rect.size.y - minsize.y) / 2); + if (p_child->get_v_size_flags() & SIZE_SHRINK_END) { + r.position.y += p_rect.size.height - minsize.height; + } else if (p_child->get_v_size_flags() & SIZE_SHRINK_CENTER) { + r.position.y += Math::floor((p_rect.size.y - minsize.height) / 2); + } else { + r.position.y += 0; + } } for (int i = 0; i < 4; i++) p_child->set_anchor(Margin(i), ANCHOR_BEGIN); - p_child->set_pos(r.pos); + p_child->set_position(r.position); p_child->set_size(r.size); p_child->set_rotation(0); p_child->set_scale(Vector2(1, 1)); @@ -155,7 +168,7 @@ void Container::_bind_methods() { ClassDB::bind_method(D_METHOD("_child_minsize_changed"), &Container::_child_minsize_changed); ClassDB::bind_method(D_METHOD("queue_sort"), &Container::queue_sort); - ClassDB::bind_method(D_METHOD("fit_child_in_rect", "child:Control", "rect"), &Container::fit_child_in_rect); + ClassDB::bind_method(D_METHOD("fit_child_in_rect", "child", "rect"), &Container::fit_child_in_rect); BIND_CONSTANT(NOTIFICATION_SORT_CHILDREN); ADD_SIGNAL(MethodInfo("sort_children")); diff --git a/scene/gui/container.h b/scene/gui/container.h index 78f647f59..bff24c6d5 100644 --- a/scene/gui/container.h +++ b/scene/gui/container.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index d2f3eea72..c97426ad4 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -27,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "control.h" -#include "global_config.h" +#include "project_settings.h" #include "scene/main/canvas_layer.h" #include "scene/main/viewport.h" #include "servers/visual_server.h" @@ -50,6 +51,12 @@ Variant Control::edit_get_state() const { s["rect"] = get_rect(); s["rot"] = get_rotation(); s["scale"] = get_scale(); + Array anchors; + anchors.push_back(get_anchor(MARGIN_LEFT)); + anchors.push_back(get_anchor(MARGIN_TOP)); + anchors.push_back(get_anchor(MARGIN_RIGHT)); + anchors.push_back(get_anchor(MARGIN_BOTTOM)); + s["anchors"] = anchors; return s; } void Control::edit_set_state(const Variant &p_state) { @@ -57,10 +64,15 @@ void Control::edit_set_state(const Variant &p_state) { Dictionary s = p_state; Rect2 state = s["rect"]; - set_pos(state.pos); + set_position(state.position); set_size(state.size); set_rotation(s["rot"]); set_scale(s["scale"]); + Array anchors = s["anchors"]; + set_anchor(MARGIN_LEFT, anchors[0]); + set_anchor(MARGIN_TOP, anchors[1]); + set_anchor(MARGIN_RIGHT, anchors[2]); + set_anchor(MARGIN_BOTTOM, anchors[3]); } void Control::set_custom_minimum_size(const Size2 &p_custom) { @@ -89,19 +101,30 @@ Size2 Control::edit_get_minimum_size() const { return get_combined_minimum_size(); } +Transform2D Control::_get_internal_transform() const { + + Transform2D rot_scale; + rot_scale.set_rotation_and_scale(data.rotation, data.scale); + Transform2D offset; + offset.set_origin(-data.pivot_offset); + + return offset.affine_inverse() * (rot_scale * offset); +} void Control::edit_set_rect(const Rect2 &p_edit_rect) { - Transform2D postxf; - postxf.set_rotation_and_scale(data.rotation, data.scale); - Vector2 new_pos = postxf.xform(p_edit_rect.pos); + Transform2D xform = _get_internal_transform(); + + // xform[2] += get_position(); - Vector2 pos = get_pos() + new_pos; + Vector2 new_pos = xform.basis_xform(p_edit_rect.position); + + Vector2 pos = get_position() + new_pos; Rect2 new_rect = get_rect(); - new_rect.pos = pos.snapped(Vector2(1, 1)); + new_rect.position = pos.snapped(Vector2(1, 1)); new_rect.size = p_edit_rect.size.snapped(Vector2(1, 1)); - set_pos(new_rect.pos); + set_position(new_rect.position); set_size(new_rect.size); } @@ -352,8 +375,9 @@ void Control::remove_child_notify(Node *p_child) { void Control::_update_canvas_item_transform() { - Transform2D xform = Transform2D(data.rotation, get_pos()); - xform.scale_basis(data.scale); + Transform2D xform = _get_internal_transform(); + xform[2] += get_position(); + VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), xform); } @@ -590,7 +614,7 @@ bool Control::has_point(const Point2 &p_point) const { void Control::set_drag_forwarding(Control *p_target) { if (p_target) - data.drag_owner = p_target->get_instance_ID(); + data.drag_owner = p_target->get_instance_id(); else data.drag_owner = 0; } @@ -1183,6 +1207,7 @@ Size2 Control::get_parent_area_size() const { parent_size = get_viewport()->get_visible_rect().size; } + return parent_size; } @@ -1198,29 +1223,31 @@ void Control::_size_changed() { for (int i = 0; i < 4; i++) { float area = parent_size[i & 1]; - switch (data.anchor[i]) { - - case ANCHOR_BEGIN: { + margin_pos[i] = data.margin[i] + (data.anchor[i] * area); + } - margin_pos[i] = data.margin[i]; - } break; - case ANCHOR_END: { + Point2 new_pos_cache = Point2(margin_pos[0], margin_pos[1]); + Size2 new_size_cache = Point2(margin_pos[2], margin_pos[3]) - new_pos_cache; - margin_pos[i] = area - data.margin[i]; - } break; - case ANCHOR_CENTER: { + Size2 minimum_size = get_combined_minimum_size(); - margin_pos[i] = (area / 2) - data.margin[i]; - } break; + if (data.h_grow == GROW_DIRECTION_BEGIN) { + if (minimum_size.width > new_size_cache.width) { + new_pos_cache.x = new_pos_cache.x + new_size_cache.width - minimum_size.width; + new_size_cache.width = minimum_size.width; } + } else { + new_size_cache.width = MAX(minimum_size.width, new_size_cache.width); } - Point2 new_pos_cache = Point2(margin_pos[0], margin_pos[1]).floor(); - Size2 new_size_cache = Point2(margin_pos[2], margin_pos[3]).floor() - new_pos_cache; - Size2 minimum_size = get_combined_minimum_size(); - - new_size_cache.x = MAX(minimum_size.x, new_size_cache.x); - new_size_cache.y = MAX(minimum_size.y, new_size_cache.y); + if (data.v_grow == GROW_DIRECTION_BEGIN) { + if (minimum_size.height > new_size_cache.height) { + new_pos_cache.y = new_pos_cache.y + new_size_cache.height - minimum_size.height; + new_size_cache.height = minimum_size.height; + } + } else { + new_size_cache.height = MAX(minimum_size.height, new_size_cache.height); + } bool pos_changed = new_pos_cache != data.pos_cache; bool size_changed = new_size_cache != data.size_cache; @@ -1269,59 +1296,38 @@ float Control::_get_range(int p_idx) const { return to - from; } -float Control::_s2a(float p_val, AnchorType p_anchor, float p_range) const { - - switch (p_anchor) { - - case ANCHOR_BEGIN: { - return p_val; - } break; - case ANCHOR_END: { - return p_range - p_val; - } break; - case ANCHOR_CENTER: { - return (p_range / 2) - p_val; - } break; - } - - return 0; +float Control::_s2a(float p_val, float p_anchor, float p_range) const { + return p_val - (p_anchor * p_range); } -float Control::_a2s(float p_val, AnchorType p_anchor, float p_range) const { - - switch (p_anchor) { - - case ANCHOR_BEGIN: { - return Math::floor(p_val); - } break; - case ANCHOR_END: { - return Math::floor(p_range - p_val); - } break; - case ANCHOR_CENTER: { - return Math::floor((p_range / 2) - p_val); - } break; - } - return 0; +float Control::_a2s(float p_val, float p_anchor, float p_range) const { + return Math::floor(p_val + (p_anchor * p_range)); } -void Control::set_anchor(Margin p_margin, AnchorType p_anchor, bool p_keep_margin) { +void Control::set_anchor(Margin p_margin, float p_anchor, bool p_keep_margin, bool p_push_opposite_anchor) { + bool pushed = false; + data.anchor[p_margin] = CLAMP(p_anchor, 0.0, 1.0); - if (!is_inside_tree()) { + if (((p_margin == MARGIN_LEFT || p_margin == MARGIN_TOP) && data.anchor[p_margin] > data.anchor[(p_margin + 2) % 4]) || + ((p_margin == MARGIN_RIGHT || p_margin == MARGIN_BOTTOM) && data.anchor[p_margin] < data.anchor[(p_margin + 2) % 4])) { + if (p_push_opposite_anchor) { + data.anchor[(p_margin + 2) % 4] = data.anchor[p_margin]; + pushed = true; + } else { + data.anchor[p_margin] = data.anchor[(p_margin + 2) % 4]; + } + } - data.anchor[p_margin] = p_anchor; - } else if (!p_keep_margin) { - float pr = _get_parent_range(p_margin); - float s = _a2s(data.margin[p_margin], data.anchor[p_margin], pr); - data.anchor[p_margin] = p_anchor; - data.margin[p_margin] = _s2a(s, p_anchor, pr); - } else { - data.anchor[p_margin] = p_anchor; - _size_changed(); + if (is_inside_tree()) { + if (p_keep_margin) { + _size_changed(); + } } + update(); _change_notify(); } -void Control::_set_anchor(Margin p_margin, AnchorType p_anchor) { +void Control::_set_anchor(Margin p_margin, float p_anchor) { #ifdef TOOLS_ENABLED if (is_inside_tree() && get_tree()->is_editor_hint()) { set_anchor(p_margin, p_anchor, EDITOR_DEF("editors/2d/keep_margins_when_changing_anchors", false)); @@ -1333,13 +1339,127 @@ void Control::_set_anchor(Margin p_margin, AnchorType p_anchor) { #endif } -void Control::set_anchor_and_margin(Margin p_margin, AnchorType p_anchor, float p_pos) { +void Control::set_anchor_and_margin(Margin p_margin, float p_anchor, float p_pos, bool p_push_opposite_anchor) { - set_anchor(p_margin, p_anchor); + set_anchor(p_margin, p_anchor, false, p_push_opposite_anchor); set_margin(p_margin, p_pos); } -Control::AnchorType Control::get_anchor(Margin p_margin) const { +void Control::set_anchors_preset(LayoutPreset p_preset, bool p_keep_margin) { + //Left + switch (p_preset) { + case PRESET_TOP_LEFT: + case PRESET_BOTTOM_LEFT: + case PRESET_CENTER_LEFT: + case PRESET_TOP_WIDE: + case PRESET_BOTTOM_WIDE: + case PRESET_LEFT_WIDE: + case PRESET_HCENTER_WIDE: + case PRESET_WIDE: + set_anchor(MARGIN_LEFT, ANCHOR_BEGIN, p_keep_margin); + break; + + case PRESET_CENTER_TOP: + case PRESET_CENTER_BOTTOM: + case PRESET_CENTER: + case PRESET_VCENTER_WIDE: + set_anchor(MARGIN_LEFT, 0.5, p_keep_margin); + break; + + case PRESET_TOP_RIGHT: + case PRESET_BOTTOM_RIGHT: + case PRESET_CENTER_RIGHT: + case PRESET_RIGHT_WIDE: + set_anchor(MARGIN_LEFT, ANCHOR_END, p_keep_margin); + break; + } + + // Top + switch (p_preset) { + case PRESET_TOP_LEFT: + case PRESET_TOP_RIGHT: + case PRESET_CENTER_TOP: + case PRESET_LEFT_WIDE: + case PRESET_RIGHT_WIDE: + case PRESET_TOP_WIDE: + case PRESET_VCENTER_WIDE: + case PRESET_WIDE: + set_anchor(MARGIN_TOP, ANCHOR_BEGIN, p_keep_margin); + break; + + case PRESET_CENTER_LEFT: + case PRESET_CENTER_RIGHT: + case PRESET_CENTER: + case PRESET_HCENTER_WIDE: + set_anchor(MARGIN_TOP, 0.5, p_keep_margin); + break; + + case PRESET_BOTTOM_LEFT: + case PRESET_BOTTOM_RIGHT: + case PRESET_CENTER_BOTTOM: + case PRESET_BOTTOM_WIDE: + set_anchor(MARGIN_TOP, ANCHOR_END, p_keep_margin); + break; + } + + // Right + switch (p_preset) { + case PRESET_TOP_LEFT: + case PRESET_BOTTOM_LEFT: + case PRESET_CENTER_LEFT: + case PRESET_LEFT_WIDE: + set_anchor(MARGIN_RIGHT, ANCHOR_BEGIN, p_keep_margin); + break; + + case PRESET_CENTER_TOP: + case PRESET_CENTER_BOTTOM: + case PRESET_CENTER: + case PRESET_VCENTER_WIDE: + set_anchor(MARGIN_RIGHT, 0.5, p_keep_margin); + break; + + case PRESET_TOP_RIGHT: + case PRESET_BOTTOM_RIGHT: + case PRESET_CENTER_RIGHT: + case PRESET_TOP_WIDE: + case PRESET_RIGHT_WIDE: + case PRESET_BOTTOM_WIDE: + case PRESET_HCENTER_WIDE: + case PRESET_WIDE: + set_anchor(MARGIN_RIGHT, ANCHOR_END, p_keep_margin); + break; + } + + // Bottom + switch (p_preset) { + case PRESET_TOP_LEFT: + case PRESET_TOP_RIGHT: + case PRESET_CENTER_TOP: + case PRESET_TOP_WIDE: + set_anchor(MARGIN_BOTTOM, ANCHOR_BEGIN, p_keep_margin); + break; + + case PRESET_CENTER_LEFT: + case PRESET_CENTER_RIGHT: + case PRESET_CENTER: + case PRESET_HCENTER_WIDE: + set_anchor(MARGIN_BOTTOM, 0.5, p_keep_margin); + break; + + case PRESET_BOTTOM_LEFT: + case PRESET_BOTTOM_RIGHT: + case PRESET_CENTER_BOTTOM: + case PRESET_LEFT_WIDE: + case PRESET_RIGHT_WIDE: + case PRESET_BOTTOM_WIDE: + case PRESET_VCENTER_WIDE: + case PRESET_WIDE: + set_anchor(MARGIN_BOTTOM, ANCHOR_END, p_keep_margin); + break; + } +} + +float Control::get_anchor(Margin p_margin) const { return data.anchor[p_margin]; } @@ -1347,12 +1467,12 @@ Control::AnchorType Control::get_anchor(Margin p_margin) const { void Control::_change_notify_margins() { // this avoids sending the whole object data again on a change - _change_notify("margin/left"); - _change_notify("margin/top"); - _change_notify("margin/right"); - _change_notify("margin/bottom"); - _change_notify("rect/pos"); - _change_notify("rect/size"); + _change_notify("margin_left"); + _change_notify("margin_top"); + _change_notify("margin_right"); + _change_notify("margin_bottom"); + _change_notify("rect_position"); + _change_notify("rect_size"); } void Control::set_margin(Margin p_margin, float p_value) { @@ -1389,12 +1509,12 @@ Size2 Control::get_end() const { return Size2(data.margin[2], data.margin[3]); } -Point2 Control::get_global_pos() const { +Point2 Control::get_global_position() const { return get_global_transform().get_origin(); } -void Control::set_global_pos(const Point2 &p_point) { +void Control::set_global_position(const Point2 &p_point) { Transform2D inv; @@ -1403,10 +1523,10 @@ void Control::set_global_pos(const Point2 &p_point) { inv = data.parent_canvas_item->get_global_transform().affine_inverse(); } - set_pos(inv.xform(p_point)); + set_position(inv.xform(p_point)); } -void Control::set_pos(const Size2 &p_point) { +void Control::set_position(const Size2 &p_point) { float pw = _get_parent_range(0); float ph = _get_parent_range(1); @@ -1458,7 +1578,7 @@ void Control::set_size(const Size2 &p_size) { _size_changed(); } -Size2 Control::get_pos() const { +Size2 Control::get_position() const { return data.pos_cache; } @@ -1470,19 +1590,19 @@ Size2 Control::get_size() const { Rect2 Control::get_global_rect() const { - return Rect2(get_global_pos(), get_size()); + return Rect2(get_global_position(), get_size()); } Rect2 Control::get_window_rect() const { ERR_FAIL_COND_V(!is_inside_tree(), Rect2()); Rect2 gr = get_global_rect(); - gr.pos += get_viewport()->get_visible_rect().pos; + gr.position += get_viewport()->get_visible_rect().position; return gr; } Rect2 Control::get_rect() const { - return Rect2(get_pos(), get_size()); + return Rect2(get_position(), get_size()); } Rect2 Control::get_item_rect() const { @@ -1493,11 +1613,13 @@ Rect2 Control::get_item_rect() const { void Control::set_area_as_parent_rect(int p_margin) { data.anchor[MARGIN_LEFT] = ANCHOR_BEGIN; + data.margin[MARGIN_LEFT] = p_margin; data.anchor[MARGIN_TOP] = ANCHOR_BEGIN; + data.margin[MARGIN_TOP] = p_margin; data.anchor[MARGIN_RIGHT] = ANCHOR_END; + data.margin[MARGIN_RIGHT] = -p_margin; data.anchor[MARGIN_BOTTOM] = ANCHOR_END; - for (int i = 0; i < 4; i++) - data.margin[i] = p_margin; + data.margin[MARGIN_BOTTOM] = -p_margin; _size_changed(); } @@ -1885,8 +2007,8 @@ Control::CursorShape Control::get_cursor_shape(const Point2 &p_pos) const { Transform2D Control::get_transform() const { - Transform2D xform = Transform2D(data.rotation, get_pos()); - xform.scale_basis(data.scale); + Transform2D xform = _get_internal_transform(); + xform[2] += get_position(); return xform; } @@ -1948,10 +2070,10 @@ Control *Control::_get_focus_neighbour(Margin p_margin, int p_count) { Transform2D xform = get_global_transform(); Rect2 rect = get_item_rect(); - points[0] = xform.xform(rect.pos); - points[1] = xform.xform(rect.pos + Point2(rect.size.x, 0)); - points[2] = xform.xform(rect.pos + rect.size); - points[3] = xform.xform(rect.pos + Point2(0, rect.size.y)); + points[0] = xform.xform(rect.position); + points[1] = xform.xform(rect.position + Point2(rect.size.x, 0)); + points[2] = xform.xform(rect.position + rect.size); + points[3] = xform.xform(rect.position + Point2(0, rect.size.y)); const Vector2 dir[4] = { Vector2(-1, 0), @@ -2007,10 +2129,10 @@ void Control::_window_find_focus_neighbour(const Vector2 &p_dir, Node *p_at, con Transform2D xform = c->get_global_transform(); Rect2 rect = c->get_item_rect(); - points[0] = xform.xform(rect.pos); - points[1] = xform.xform(rect.pos + Point2(rect.size.x, 0)); - points[2] = xform.xform(rect.pos + rect.size); - points[3] = xform.xform(rect.pos + Point2(0, rect.size.y)); + points[0] = xform.xform(rect.position); + points[1] = xform.xform(rect.position + Point2(rect.size.x, 0)); + points[2] = xform.xform(rect.position + rect.size); + points[3] = xform.xform(rect.position + Point2(0, rect.size.y)); float min = 1e7; @@ -2158,7 +2280,7 @@ void Control::set_rotation(float p_radians) { data.rotation = p_radians; update(); _notify_transform(); - _change_notify("rect/rotation"); + _change_notify("rect_rotation"); } float Control::get_rotation() const { @@ -2212,6 +2334,19 @@ void Control::_font_changed() { minimum_size_changed(); //fonts affect minimum size pretty much almost always } +void Control::set_pivot_offset(const Vector2 &p_pivot) { + + data.pivot_offset = p_pivot; + update(); + _notify_transform(); + _change_notify("rect_pivot_offset"); +} + +Vector2 Control::get_pivot_offset() const { + + return data.pivot_offset; +} + void Control::set_scale(const Vector2 &p_scale) { data.scale = p_scale; @@ -2298,6 +2433,27 @@ bool Control::is_clipping_contents() { return data.clip_contents; } +void Control::set_h_grow_direction(GrowDirection p_direction) { + + data.h_grow = p_direction; + _size_changed(); +} + +Control::GrowDirection Control::get_h_grow_direction() const { + + return data.h_grow; +} + +void Control::set_v_grow_direction(GrowDirection p_direction) { + + data.v_grow = p_direction; + _size_changed(); +} +Control::GrowDirection Control::get_v_grow_direction() const { + + return data.v_grow; +} + void Control::_bind_methods() { //ClassDB::bind_method(D_METHOD("_window_resize_event"),&Control::_window_resize_event); @@ -2307,35 +2463,38 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("accept_event"), &Control::accept_event); ClassDB::bind_method(D_METHOD("get_minimum_size"), &Control::get_minimum_size); ClassDB::bind_method(D_METHOD("get_combined_minimum_size"), &Control::get_combined_minimum_size); - ClassDB::bind_method(D_METHOD("set_anchor", "margin", "anchor_mode", "keep_margin"), &Control::set_anchor, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("_set_anchor", "margin", "anchor_mode"), &Control::_set_anchor); + ClassDB::bind_method(D_METHOD("set_anchor", "margin", "anchor", "keep_margin", "push_opposite_anchor"), &Control::set_anchor, DEFVAL(false), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("_set_anchor", "margin", "anchor"), &Control::_set_anchor); + ClassDB::bind_method(D_METHOD("set_anchors_preset", "preset", "keep_margin"), &Control::set_anchors_preset, DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_anchor", "margin"), &Control::get_anchor); ClassDB::bind_method(D_METHOD("set_margin", "margin", "offset"), &Control::set_margin); - ClassDB::bind_method(D_METHOD("set_anchor_and_margin", "margin", "anchor_mode", "offset"), &Control::set_anchor_and_margin); + ClassDB::bind_method(D_METHOD("set_anchor_and_margin", "margin", "anchor", "offset", "push_opposite_anchor"), &Control::set_anchor_and_margin, DEFVAL(false)); ClassDB::bind_method(D_METHOD("set_begin", "pos"), &Control::set_begin); ClassDB::bind_method(D_METHOD("set_end", "pos"), &Control::set_end); - ClassDB::bind_method(D_METHOD("set_pos", "pos"), &Control::set_pos); + ClassDB::bind_method(D_METHOD("set_position", "pos"), &Control::set_position); ClassDB::bind_method(D_METHOD("set_size", "size"), &Control::set_size); ClassDB::bind_method(D_METHOD("set_custom_minimum_size", "size"), &Control::set_custom_minimum_size); - ClassDB::bind_method(D_METHOD("set_global_pos", "pos"), &Control::set_global_pos); + ClassDB::bind_method(D_METHOD("set_global_position", "pos"), &Control::set_global_position); ClassDB::bind_method(D_METHOD("set_rotation", "radians"), &Control::set_rotation); ClassDB::bind_method(D_METHOD("set_rotation_deg", "degrees"), &Control::set_rotation_deg); // TODO: Obsolete this method (old name) properly (GH-4397) ClassDB::bind_method(D_METHOD("_set_rotation_deg", "degrees"), &Control::_set_rotation_deg); ClassDB::bind_method(D_METHOD("set_scale", "scale"), &Control::set_scale); + ClassDB::bind_method(D_METHOD("set_pivot_offset", "pivot_offset"), &Control::set_pivot_offset); ClassDB::bind_method(D_METHOD("get_margin", "margin"), &Control::get_margin); ClassDB::bind_method(D_METHOD("get_begin"), &Control::get_begin); ClassDB::bind_method(D_METHOD("get_end"), &Control::get_end); - ClassDB::bind_method(D_METHOD("get_pos"), &Control::get_pos); + ClassDB::bind_method(D_METHOD("get_position"), &Control::get_position); ClassDB::bind_method(D_METHOD("get_size"), &Control::get_size); ClassDB::bind_method(D_METHOD("get_rotation"), &Control::get_rotation); ClassDB::bind_method(D_METHOD("get_rotation_deg"), &Control::get_rotation_deg); // TODO: Obsolete this method (old name) properly (GH-4397) ClassDB::bind_method(D_METHOD("_get_rotation_deg"), &Control::_get_rotation_deg); ClassDB::bind_method(D_METHOD("get_scale"), &Control::get_scale); + ClassDB::bind_method(D_METHOD("get_pivot_offset"), &Control::get_pivot_offset); ClassDB::bind_method(D_METHOD("get_custom_minimum_size"), &Control::get_custom_minimum_size); ClassDB::bind_method(D_METHOD("get_parent_area_size"), &Control::get_size); - ClassDB::bind_method(D_METHOD("get_global_pos"), &Control::get_global_pos); + ClassDB::bind_method(D_METHOD("get_global_position"), &Control::get_global_position); ClassDB::bind_method(D_METHOD("get_rect"), &Control::get_rect); ClassDB::bind_method(D_METHOD("get_global_rect"), &Control::get_global_rect); ClassDB::bind_method(D_METHOD("set_area_as_parent_rect", "margin"), &Control::set_area_as_parent_rect, DEFVAL(0)); @@ -2345,7 +2504,7 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("has_focus"), &Control::has_focus); ClassDB::bind_method(D_METHOD("grab_focus"), &Control::grab_focus); ClassDB::bind_method(D_METHOD("release_focus"), &Control::release_focus); - ClassDB::bind_method(D_METHOD("get_focus_owner:Control"), &Control::get_focus_owner); + ClassDB::bind_method(D_METHOD("get_focus_owner"), &Control::get_focus_owner); ClassDB::bind_method(D_METHOD("set_h_size_flags", "flags"), &Control::set_h_size_flags); ClassDB::bind_method(D_METHOD("get_h_size_flags"), &Control::get_h_size_flags); @@ -2356,19 +2515,19 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("set_v_size_flags", "flags"), &Control::set_v_size_flags); ClassDB::bind_method(D_METHOD("get_v_size_flags"), &Control::get_v_size_flags); - ClassDB::bind_method(D_METHOD("set_theme", "theme:Theme"), &Control::set_theme); - ClassDB::bind_method(D_METHOD("get_theme:Theme"), &Control::get_theme); + ClassDB::bind_method(D_METHOD("set_theme", "theme"), &Control::set_theme); + ClassDB::bind_method(D_METHOD("get_theme"), &Control::get_theme); - ClassDB::bind_method(D_METHOD("add_icon_override", "name", "texture:Texture"), &Control::add_icon_override); - ClassDB::bind_method(D_METHOD("add_shader_override", "name", "shader:Shader"), &Control::add_shader_override); - ClassDB::bind_method(D_METHOD("add_style_override", "name", "stylebox:StyleBox"), &Control::add_style_override); - ClassDB::bind_method(D_METHOD("add_font_override", "name", "font:Font"), &Control::add_font_override); + ClassDB::bind_method(D_METHOD("add_icon_override", "name", "texture"), &Control::add_icon_override); + ClassDB::bind_method(D_METHOD("add_shader_override", "name", "shader"), &Control::add_shader_override); + ClassDB::bind_method(D_METHOD("add_style_override", "name", "stylebox"), &Control::add_style_override); + ClassDB::bind_method(D_METHOD("add_font_override", "name", "font"), &Control::add_font_override); ClassDB::bind_method(D_METHOD("add_color_override", "name", "color"), &Control::add_color_override); ClassDB::bind_method(D_METHOD("add_constant_override", "name", "constant"), &Control::add_constant_override); - ClassDB::bind_method(D_METHOD("get_icon:Texture", "name", "type"), &Control::get_icon, DEFVAL("")); - ClassDB::bind_method(D_METHOD("get_stylebox:StyleBox", "name", "type"), &Control::get_stylebox, DEFVAL("")); - ClassDB::bind_method(D_METHOD("get_font:Font", "name", "type"), &Control::get_font, DEFVAL("")); + ClassDB::bind_method(D_METHOD("get_icon", "name", "type"), &Control::get_icon, DEFVAL("")); + ClassDB::bind_method(D_METHOD("get_stylebox", "name", "type"), &Control::get_stylebox, DEFVAL("")); + ClassDB::bind_method(D_METHOD("get_font", "name", "type"), &Control::get_font, DEFVAL("")); ClassDB::bind_method(D_METHOD("get_color", "name", "type"), &Control::get_color, DEFVAL("")); ClassDB::bind_method(D_METHOD("get_constant", "name", "type"), &Control::get_constant, DEFVAL("")); @@ -2384,7 +2543,13 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("has_color", "name", "type"), &Control::has_color, DEFVAL("")); ClassDB::bind_method(D_METHOD("has_constant", "name", "type"), &Control::has_constant, DEFVAL("")); - ClassDB::bind_method(D_METHOD("get_parent_control:Control"), &Control::get_parent_control); + ClassDB::bind_method(D_METHOD("get_parent_control"), &Control::get_parent_control); + + ClassDB::bind_method(D_METHOD("set_h_grow_direction", "direction"), &Control::set_h_grow_direction); + ClassDB::bind_method(D_METHOD("get_h_grow_direction"), &Control::get_h_grow_direction); + + ClassDB::bind_method(D_METHOD("set_v_grow_direction", "direction"), &Control::set_v_grow_direction); + ClassDB::bind_method(D_METHOD("get_v_grow_direction"), &Control::get_v_grow_direction); ClassDB::bind_method(D_METHOD("set_tooltip", "tooltip"), &Control::set_tooltip); ClassDB::bind_method(D_METHOD("get_tooltip", "atpos"), &Control::get_tooltip, DEFVAL(Point2())); @@ -2407,8 +2572,8 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("grab_click_focus"), &Control::grab_click_focus); - ClassDB::bind_method(D_METHOD("set_drag_forwarding", "target:Control"), &Control::set_drag_forwarding); - ClassDB::bind_method(D_METHOD("set_drag_preview", "control:Control"), &Control::set_drag_preview); + ClassDB::bind_method(D_METHOD("set_drag_forwarding", "target"), &Control::set_drag_forwarding); + ClassDB::bind_method(D_METHOD("set_drag_preview", "control"), &Control::set_drag_preview); ClassDB::bind_method(D_METHOD("warp_mouse", "to_pos"), &Control::warp_mouse); @@ -2418,17 +2583,17 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("_font_changed"), &Control::_font_changed); - BIND_VMETHOD(MethodInfo("_gui_input", PropertyInfo(Variant::INPUT_EVENT, "event"))); + BIND_VMETHOD(MethodInfo("_gui_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); BIND_VMETHOD(MethodInfo(Variant::VECTOR2, "_get_minimum_size")); BIND_VMETHOD(MethodInfo(Variant::OBJECT, "get_drag_data", PropertyInfo(Variant::VECTOR2, "pos"))); BIND_VMETHOD(MethodInfo(Variant::BOOL, "can_drop_data", PropertyInfo(Variant::VECTOR2, "pos"), PropertyInfo(Variant::NIL, "data"))); BIND_VMETHOD(MethodInfo("drop_data", PropertyInfo(Variant::VECTOR2, "pos"), PropertyInfo(Variant::NIL, "data"))); ADD_GROUP("Anchor", "anchor_"); - ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "anchor_left", PROPERTY_HINT_ENUM, "Begin,End,Center"), "_set_anchor", "get_anchor", MARGIN_LEFT); - ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "anchor_top", PROPERTY_HINT_ENUM, "Begin,End,Center"), "_set_anchor", "get_anchor", MARGIN_TOP); - ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "anchor_right", PROPERTY_HINT_ENUM, "Begin,End,Center"), "_set_anchor", "get_anchor", MARGIN_RIGHT); - ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "anchor_bottom", PROPERTY_HINT_ENUM, "Begin,End,Center"), "_set_anchor", "get_anchor", MARGIN_BOTTOM); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anchor_left", PROPERTY_HINT_RANGE, "0,1,0.01"), "_set_anchor", "get_anchor", MARGIN_LEFT); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anchor_top", PROPERTY_HINT_RANGE, "0,1,0.01"), "_set_anchor", "get_anchor", MARGIN_TOP); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anchor_right", PROPERTY_HINT_RANGE, "0,1,0.01"), "_set_anchor", "get_anchor", MARGIN_RIGHT); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anchor_bottom", PROPERTY_HINT_RANGE, "0,1,0.01"), "_set_anchor", "get_anchor", MARGIN_BOTTOM); ADD_GROUP("Margin", "margin_"); ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "margin_left", PROPERTY_HINT_RANGE, "-4096,4096"), "set_margin", "get_margin", MARGIN_LEFT); @@ -2436,12 +2601,17 @@ void Control::_bind_methods() { ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "margin_right", PROPERTY_HINT_RANGE, "-4096,4096"), "set_margin", "get_margin", MARGIN_RIGHT); ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "margin_bottom", PROPERTY_HINT_RANGE, "-4096,4096"), "set_margin", "get_margin", MARGIN_BOTTOM); + ADD_GROUP("Grow Direction", "grow_"); + ADD_PROPERTYNO(PropertyInfo(Variant::INT, "grow_horizontal", PROPERTY_HINT_ENUM, "Begin,End"), "set_h_grow_direction", "get_h_grow_direction"); + ADD_PROPERTYNO(PropertyInfo(Variant::INT, "grow_vertical", PROPERTY_HINT_ENUM, "Begin,End"), "set_v_grow_direction", "get_v_grow_direction"); + ADD_GROUP("Rect", "rect_"); - ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "rect_pos", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_pos", "get_pos"); + ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "rect_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_position", "get_position"); ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "rect_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_size", "get_size"); ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "rect_min_size"), "set_custom_minimum_size", "get_custom_minimum_size"); ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "rect_rotation", PROPERTY_HINT_RANGE, "-1080,1080,0.01"), "set_rotation_deg", "get_rotation_deg"); ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2, "rect_scale"), "set_scale", "get_scale"); + ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2, "rect_pivot_offset"), "set_pivot_offset", "get_pivot_offset"); ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "rect_clip_content"), "set_clip_contents", "is_clipping_contents"); ADD_GROUP("Hint", "hint_"); @@ -2457,16 +2627,13 @@ void Control::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_filter", PROPERTY_HINT_ENUM, "Stop,Pass,Ignore"), "set_mouse_filter", "get_mouse_filter"); ADD_GROUP("Size Flags", "size_flags_"); - ADD_PROPERTYNO(PropertyInfo(Variant::INT, "size_flags_horizontal", PROPERTY_HINT_FLAGS, "Fill,Expand"), "set_h_size_flags", "get_h_size_flags"); - ADD_PROPERTYNO(PropertyInfo(Variant::INT, "size_flags_vertical", PROPERTY_HINT_FLAGS, "Fill,Expand"), "set_v_size_flags", "get_v_size_flags"); - ADD_PROPERTYNO(PropertyInfo(Variant::INT, "size_flags_stretch_ratio", PROPERTY_HINT_RANGE, "1,128,0.01"), "set_stretch_ratio", "get_stretch_ratio"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "size_flags_horizontal", PROPERTY_HINT_FLAGS, "Fill,Expand,Shrink Center,Shrink End"), "set_h_size_flags", "get_h_size_flags"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "size_flags_vertical", PROPERTY_HINT_FLAGS, "Fill,Expand,Shrink Center,Shrink End"), "set_v_size_flags", "get_v_size_flags"); + ADD_PROPERTYNO(PropertyInfo(Variant::REAL, "size_flags_stretch_ratio", PROPERTY_HINT_RANGE, "0,128,0.01"), "set_stretch_ratio", "get_stretch_ratio"); ADD_GROUP("Theme", ""); ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), "set_theme", "get_theme"); ADD_GROUP("", ""); - BIND_CONSTANT(ANCHOR_BEGIN); - BIND_CONSTANT(ANCHOR_END); - BIND_CONSTANT(ANCHOR_CENTER); BIND_CONSTANT(FOCUS_NONE); BIND_CONSTANT(FOCUS_CLICK); BIND_CONSTANT(FOCUS_ALL); @@ -2497,16 +2664,41 @@ void Control::_bind_methods() { BIND_CONSTANT(CURSOR_HSPLIT); BIND_CONSTANT(CURSOR_HELP); + BIND_CONSTANT(PRESET_TOP_LEFT); + BIND_CONSTANT(PRESET_TOP_RIGHT); + BIND_CONSTANT(PRESET_BOTTOM_LEFT); + BIND_CONSTANT(PRESET_BOTTOM_RIGHT); + BIND_CONSTANT(PRESET_CENTER_LEFT); + BIND_CONSTANT(PRESET_CENTER_TOP); + BIND_CONSTANT(PRESET_CENTER_RIGHT); + BIND_CONSTANT(PRESET_CENTER_BOTTOM); + BIND_CONSTANT(PRESET_CENTER); + BIND_CONSTANT(PRESET_LEFT_WIDE); + BIND_CONSTANT(PRESET_TOP_WIDE); + BIND_CONSTANT(PRESET_RIGHT_WIDE); + BIND_CONSTANT(PRESET_BOTTOM_WIDE); + BIND_CONSTANT(PRESET_VCENTER_WIDE); + BIND_CONSTANT(PRESET_HCENTER_WIDE); + BIND_CONSTANT(PRESET_WIDE); + BIND_CONSTANT(SIZE_EXPAND); BIND_CONSTANT(SIZE_FILL); BIND_CONSTANT(SIZE_EXPAND_FILL); + BIND_CONSTANT(SIZE_SHRINK_CENTER); + BIND_CONSTANT(SIZE_SHRINK_END); BIND_CONSTANT(MOUSE_FILTER_STOP); BIND_CONSTANT(MOUSE_FILTER_PASS); BIND_CONSTANT(MOUSE_FILTER_IGNORE); + BIND_CONSTANT(GROW_DIRECTION_BEGIN); + BIND_CONSTANT(GROW_DIRECTION_END); + + BIND_CONSTANT(ANCHOR_BEGIN); + BIND_CONSTANT(ANCHOR_END); + ADD_SIGNAL(MethodInfo("resized")); - ADD_SIGNAL(MethodInfo("gui_input", PropertyInfo(Variant::INPUT_EVENT, "ev"))); + ADD_SIGNAL(MethodInfo("gui_input", PropertyInfo(Variant::OBJECT, "ev", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); ADD_SIGNAL(MethodInfo("mouse_entered")); ADD_SIGNAL(MethodInfo("mouse_exited")); ADD_SIGNAL(MethodInfo("focus_entered")); @@ -2515,7 +2707,7 @@ void Control::_bind_methods() { ADD_SIGNAL(MethodInfo("minimum_size_changed")); ADD_SIGNAL(MethodInfo("modal_closed")); - BIND_VMETHOD(MethodInfo("has_point", PropertyInfo(Variant::VECTOR2, "point"))); + BIND_VMETHOD(MethodInfo("has_point:bool", PropertyInfo(Variant::VECTOR2, "point"))); } Control::Control() { @@ -2541,6 +2733,8 @@ Control::Control() { data.modal_frame = 0; data.block_minimum_size_adjust = false; data.disable_visibility_clip = false; + data.h_grow = GROW_DIRECTION_END; + data.v_grow = GROW_DIRECTION_END; data.clip_contents = false; for (int i = 0; i < 4; i++) { diff --git a/scene/gui/control.h b/scene/gui/control.h index a18567123..d73ca3f7c 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -50,10 +51,15 @@ class Control : public CanvasItem { OBJ_CATEGORY("GUI Nodes"); public: - enum AnchorType { - ANCHOR_BEGIN, - ANCHOR_END, - ANCHOR_CENTER, + enum Anchor { + + ANCHOR_BEGIN = 0, + ANCHOR_END = 1 + }; + + enum GrowDirection { + GROW_DIRECTION_BEGIN, + GROW_DIRECTION_END }; enum FocusMode { @@ -66,7 +72,9 @@ public: SIZE_FILL = 1, SIZE_EXPAND = 2, - SIZE_EXPAND_FILL = SIZE_EXPAND | SIZE_FILL + SIZE_EXPAND_FILL = SIZE_EXPAND | SIZE_FILL, + SIZE_SHRINK_CENTER = 4, //ignored by expand or fill + SIZE_SHRINK_END = 8, //ignored by expand or fil }; @@ -97,6 +105,25 @@ public: CURSOR_MAX }; + enum LayoutPreset { + PRESET_TOP_LEFT, + PRESET_TOP_RIGHT, + PRESET_BOTTOM_LEFT, + PRESET_BOTTOM_RIGHT, + PRESET_CENTER_LEFT, + PRESET_CENTER_TOP, + PRESET_CENTER_RIGHT, + PRESET_CENTER_BOTTOM, + PRESET_CENTER, + PRESET_LEFT_WIDE, + PRESET_TOP_WIDE, + PRESET_RIGHT_WIDE, + PRESET_BOTTOM_WIDE, + PRESET_VCENTER_WIDE, + PRESET_HCENTER_WIDE, + PRESET_WIDE + }; + private: struct CComparator { @@ -114,11 +141,14 @@ private: Size2 size_cache; float margin[4]; - AnchorType anchor[4]; + float anchor[4]; FocusMode focus_mode; + GrowDirection h_grow; + GrowDirection v_grow; float rotation; Vector2 scale; + Vector2 pivot_offset; bool pending_resize; @@ -171,12 +201,12 @@ private: void _window_find_focus_neighbour(const Vector2 &p_dir, Node *p_at, const Point2 *p_points, float p_min, float &r_closest_dist, Control **r_closest); Control *_get_focus_neighbour(Margin p_margin, int p_count = 0); - void _set_anchor(Margin p_margin, AnchorType p_anchor); + void _set_anchor(Margin p_margin, float p_anchor); float _get_parent_range(int p_idx) const; float _get_range(int p_idx) const; - float _s2a(float p_val, AnchorType p_anchor, float p_range) const; - float _a2s(float p_val, AnchorType p_anchor, float p_range) const; + float _s2a(float p_val, float p_anchor, float p_range) const; + float _a2s(float p_val, float p_anchor, float p_range) const; void _propagate_theme_changed(CanvasItem *p_at, Control *p_owner, bool p_assign = true); void _theme_changed(); @@ -199,6 +229,8 @@ private: void _update_canvas_item_transform(); + Transform2D _get_internal_transform() const; + friend class Viewport; void _modal_stack_remove(); void _modal_set_prev_focus_owner(ObjectID p_prev); @@ -262,26 +294,33 @@ public: /* POSITIONING */ - void set_anchor(Margin p_margin, AnchorType p_anchor, bool p_keep_margin = false); - void set_anchor_and_margin(Margin p_margin, AnchorType p_anchor, float p_pos); + void set_anchor(Margin p_margin, float p_anchor, bool p_keep_margin = false, bool p_push_opposite_anchor = true); + void set_anchor_and_margin(Margin p_margin, float p_anchor, float p_pos, bool p_push_opposite_anchor = true); + void set_anchors_preset(LayoutPreset p_preset, bool p_keep_margin = false); - AnchorType get_anchor(Margin p_margin) const; + float get_anchor(Margin p_margin) const; void set_margin(Margin p_margin, float p_value); void set_begin(const Point2 &p_point); // helper void set_end(const Point2 &p_point); // helper + void set_h_grow_direction(GrowDirection p_direction); + GrowDirection get_h_grow_direction() const; + + void set_v_grow_direction(GrowDirection p_direction); + GrowDirection get_v_grow_direction() const; + float get_margin(Margin p_margin) const; Point2 get_begin() const; Point2 get_end() const; - void set_pos(const Point2 &p_point); + void set_position(const Point2 &p_point); void set_size(const Size2 &p_size); - void set_global_pos(const Point2 &p_point); + void set_global_position(const Point2 &p_point); - Point2 get_pos() const; - Point2 get_global_pos() const; + Point2 get_position() const; + Point2 get_global_position() const; Size2 get_size() const; Rect2 get_rect() const; Rect2 get_global_rect() const; @@ -292,6 +331,9 @@ public: float get_rotation() const; float get_rotation_deg() const; + void set_pivot_offset(const Vector2 &p_pivot); + Vector2 get_pivot_offset() const; + void set_scale(const Vector2 &p_scale); Vector2 get_scale() const; @@ -403,10 +445,12 @@ public: ~Control(); }; -VARIANT_ENUM_CAST(Control::AnchorType); VARIANT_ENUM_CAST(Control::FocusMode); VARIANT_ENUM_CAST(Control::SizeFlags); VARIANT_ENUM_CAST(Control::CursorShape); +VARIANT_ENUM_CAST(Control::LayoutPreset); VARIANT_ENUM_CAST(Control::MouseFilter); +VARIANT_ENUM_CAST(Control::GrowDirection); +VARIANT_ENUM_CAST(Control::Anchor); #endif diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index 35d54d984..8232a7a46 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -35,6 +36,8 @@ #include "editor/editor_node.h" #endif +// WindowDialog + void WindowDialog::_post_popup() { drag_type = DRAG_NONE; // just in case @@ -45,22 +48,35 @@ void WindowDialog::_fix_size() { // Perhaps this should be called when the viewport resizes as well or windows go out of bounds... // Ensure the whole window is visible. - Point2i pos = get_global_pos(); + Point2i pos = get_global_position(); Size2i size = get_size(); Size2i viewport_size = get_viewport_rect().size; // Windows require additional padding to keep the window chrome visible. Ref<StyleBox> panel = get_stylebox("panel", "WindowDialog"); - float top = panel->get_margin(MARGIN_TOP); - float left = panel->get_margin(MARGIN_LEFT); - float bottom = panel->get_margin(MARGIN_BOTTOM); - float right = panel->get_margin(MARGIN_RIGHT); + float top = 0; + float left = 0; + float bottom = 0; + float right = 0; + // Check validity, because the theme could contain a different type of StyleBox + if (panel->get_class() == "StyleBoxTexture") { + Ref<StyleBoxTexture> panel_texture = panel->cast_to<StyleBoxTexture>(); + top = panel_texture->get_expand_margin_size(MARGIN_TOP); + left = panel_texture->get_expand_margin_size(MARGIN_LEFT); + bottom = panel_texture->get_expand_margin_size(MARGIN_BOTTOM); + right = panel_texture->get_expand_margin_size(MARGIN_RIGHT); + } else if (panel->get_class() == "StyleBoxFlat") { + Ref<StyleBoxFlat> panel_flat = panel->cast_to<StyleBoxFlat>(); + top = panel_flat->get_expand_margin_size(MARGIN_TOP); + left = panel_flat->get_expand_margin_size(MARGIN_LEFT); + bottom = panel_flat->get_expand_margin_size(MARGIN_BOTTOM); + right = panel_flat->get_expand_margin_size(MARGIN_RIGHT); + } pos.x = MAX(left, MIN(pos.x, viewport_size.x - size.x - right)); pos.y = MAX(top, MIN(pos.y, viewport_size.y - size.y - bottom)); - set_global_pos(pos); + set_global_position(pos); - // Also resize the window to fit if a resize should be possible at all. if (resizable) { size.x = MIN(size.x, viewport_size.x - left - right); size.y = MIN(size.y, viewport_size.y - top - bottom); @@ -73,45 +89,49 @@ bool WindowDialog::has_point(const Point2 &p_point) const { Rect2 r(Point2(), get_size()); // Enlarge upwards for title bar. - int titlebar_height = get_constant("titlebar_height", "WindowDialog"); - r.pos.y -= titlebar_height; - r.size.y += titlebar_height; + int title_height = get_constant("title_height", "WindowDialog"); + r.position.y -= title_height; + r.size.y += title_height; // Inflate by the resizable border thickness. if (resizable) { int scaleborder_size = get_constant("scaleborder_size", "WindowDialog"); - r.pos.x -= scaleborder_size; + r.position.x -= scaleborder_size; r.size.width += scaleborder_size * 2; - r.pos.y -= scaleborder_size; + r.position.y -= scaleborder_size; r.size.height += scaleborder_size * 2; } return r.has_point(p_point); } -void WindowDialog::_gui_input(const InputEvent &p_event) { +void WindowDialog::_gui_input(const Ref<InputEvent> &p_event) { - if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == BUTTON_LEFT) { + Ref<InputEventMouseButton> mb = p_event; - if (p_event.mouse_button.pressed) { + if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) { + + if (mb->is_pressed()) { // Begin a possible dragging operation. - drag_type = _drag_hit_test(Point2(p_event.mouse_button.x, p_event.mouse_button.y)); + drag_type = _drag_hit_test(Point2(mb->get_position().x, mb->get_position().y)); if (drag_type != DRAG_NONE) - drag_offset = get_global_mouse_pos() - get_pos(); - drag_offset_far = get_pos() + get_size() - get_global_mouse_pos(); - } else if (drag_type != DRAG_NONE && !p_event.mouse_button.pressed) { + drag_offset = get_global_mouse_position() - get_position(); + drag_offset_far = get_position() + get_size() - get_global_mouse_position(); + } else if (drag_type != DRAG_NONE && !mb->is_pressed()) { // End a dragging operation. drag_type = DRAG_NONE; } } - if (p_event.type == InputEvent::MOUSE_MOTION) { + Ref<InputEventMouseMotion> mm = p_event; + + if (mm.is_valid()) { if (drag_type == DRAG_NONE) { // Update the cursor while moving along the borders. CursorShape cursor = CURSOR_ARROW; if (resizable) { - int preview_drag_type = _drag_hit_test(Point2(p_event.mouse_button.x, p_event.mouse_button.y)); + int preview_drag_type = _drag_hit_test(Point2(mm->get_position().x, mm->get_position().y)); switch (preview_drag_type) { case DRAG_RESIZE_TOP: case DRAG_RESIZE_BOTTOM: @@ -135,35 +155,35 @@ void WindowDialog::_gui_input(const InputEvent &p_event) { set_default_cursor_shape(cursor); } else { // Update while in a dragging operation. - Point2 global_pos = get_global_mouse_pos(); + Point2 global_pos = get_global_mouse_position(); global_pos.y = MAX(global_pos.y, 0); // Ensure title bar stays visible. Rect2 rect = get_rect(); Size2 min_size = get_minimum_size(); if (drag_type == DRAG_MOVE) { - rect.pos = global_pos - drag_offset; + rect.position = global_pos - drag_offset; } else { if (drag_type & DRAG_RESIZE_TOP) { - int bottom = rect.pos.y + rect.size.height; + int bottom = rect.position.y + rect.size.height; int max_y = bottom - min_size.height; - rect.pos.y = MIN(global_pos.y - drag_offset.y, max_y); - rect.size.height = bottom - rect.pos.y; + rect.position.y = MIN(global_pos.y - drag_offset.y, max_y); + rect.size.height = bottom - rect.position.y; } else if (drag_type & DRAG_RESIZE_BOTTOM) { - rect.size.height = global_pos.y - rect.pos.y + drag_offset_far.y; + rect.size.height = global_pos.y - rect.position.y + drag_offset_far.y; } if (drag_type & DRAG_RESIZE_LEFT) { - int right = rect.pos.x + rect.size.width; + int right = rect.position.x + rect.size.width; int max_x = right - min_size.width; - rect.pos.x = MIN(global_pos.x - drag_offset.x, max_x); - rect.size.width = right - rect.pos.x; + rect.position.x = MIN(global_pos.x - drag_offset.x, max_x); + rect.size.width = right - rect.position.x; } else if (drag_type & DRAG_RESIZE_RIGHT) { - rect.size.width = global_pos.x - rect.pos.x + drag_offset_far.x; + rect.size.width = global_pos.x - rect.position.x + drag_offset_far.x; } } set_size(rect.size); - set_pos(rect.pos); + set_position(rect.position); } } } @@ -172,28 +192,30 @@ void WindowDialog::_notification(int p_what) { switch (p_what) { case NOTIFICATION_DRAW: { - RID canvas = get_canvas_item(); - Size2 size = get_size(); + // Draw the background. Ref<StyleBox> panel = get_stylebox("panel", "WindowDialog"); - panel->draw(canvas, Rect2(Point2(), size)); + Size2 size = get_size(); + panel->draw(canvas, Rect2(0, 0, size.x, size.y)); - int title_height = get_constant("title_height", "WindowDialog"); + // Draw the title bar text. + Ref<Font> title_font = get_font("title_font", "WindowDialog"); Color title_color = get_color("title_color", "WindowDialog"); - Ref<Font> font = get_font("title_font", "WindowDialog"); - int ofs = (size.width - font->get_string_size(title).width) / 2; - draw_string(font, Point2(ofs, -title_height + font->get_ascent()), title, title_color, size.width - panel->get_minimum_size().width); - + int title_height = get_constant("title_height", "WindowDialog"); + int font_height = title_font->get_height() - title_font->get_descent() * 2; + int x = (size.x - title_font->get_string_size(title).x) / 2; + int y = (-title_height + font_height) / 2; + title_font->draw(canvas, Point2(x, y), title, title_color, size.x - panel->get_minimum_size().x); } break; case NOTIFICATION_THEME_CHANGED: case NOTIFICATION_ENTER_TREE: { close_button->set_normal_texture(get_icon("close", "WindowDialog")); close_button->set_pressed_texture(get_icon("close", "WindowDialog")); - close_button->set_hover_texture(get_icon("close_hilite", "WindowDialog")); + close_button->set_hover_texture(get_icon("close_highlight", "WindowDialog")); close_button->set_anchor(MARGIN_LEFT, ANCHOR_END); - close_button->set_begin(Point2(get_constant("close_h_ofs", "WindowDialog"), -get_constant("close_v_ofs", "WindowDialog"))); + close_button->set_begin(Point2(-get_constant("close_h_ofs", "WindowDialog"), -get_constant("close_v_ofs", "WindowDialog"))); } break; case NOTIFICATION_MOUSE_EXIT: { @@ -226,12 +248,12 @@ int WindowDialog::_drag_hit_test(const Point2 &pos) const { int drag_type = DRAG_NONE; if (resizable) { - int titlebar_height = get_constant("titlebar_height", "WindowDialog"); + int title_height = get_constant("title_height", "WindowDialog"); int scaleborder_size = get_constant("scaleborder_size", "WindowDialog"); Rect2 rect = get_rect(); - if (pos.y < (-titlebar_height + scaleborder_size)) + if (pos.y < (-title_height + scaleborder_size)) drag_type = DRAG_RESIZE_TOP; else if (pos.y >= (rect.size.height - scaleborder_size)) drag_type = DRAG_RESIZE_BOTTOM; @@ -286,7 +308,7 @@ void WindowDialog::_bind_methods() { ClassDB::bind_method(D_METHOD("set_resizable", "resizable"), &WindowDialog::set_resizable); ClassDB::bind_method(D_METHOD("get_resizable"), &WindowDialog::get_resizable); ClassDB::bind_method(D_METHOD("_closed"), &WindowDialog::_closed); - ClassDB::bind_method(D_METHOD("get_close_button:TextureButton"), &WindowDialog::get_close_button); + ClassDB::bind_method(D_METHOD("get_close_button"), &WindowDialog::get_close_button); ADD_PROPERTY(PropertyInfo(Variant::STRING, "window_title", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT_INTL), "set_title", "get_title"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "resizable", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT_INTL), "set_resizable", "get_resizable"); @@ -305,6 +327,8 @@ WindowDialog::WindowDialog() { WindowDialog::~WindowDialog() { } +// PopupDialog + void PopupDialog::_notification(int p_what) { if (p_what == NOTIFICATION_DRAW) { @@ -333,6 +357,9 @@ void AcceptDialog::_notification(int p_what) { if (p_what == NOTIFICATION_MODAL_CLOSE) { cancel_pressed(); + } else if (p_what == NOTIFICATION_READY) { + + _update_child_rects(); } else if (p_what == NOTIFICATION_RESIZED) { _update_child_rects(); @@ -404,14 +431,14 @@ void AcceptDialog::_update_child_rects() { if (c == hbc || c == label || c == get_close_button() || c->is_set_as_toplevel()) continue; - c->set_pos(cpos); + c->set_position(cpos); c->set_size(csize); } cpos.y += csize.y + margin; csize.y = hminsize.y; - hbc->set_pos(cpos); + hbc->set_position(cpos); hbc->set_size(csize); } @@ -488,10 +515,10 @@ void AcceptDialog::_bind_methods() { ClassDB::bind_method(D_METHOD("get_label"), &AcceptDialog::get_label); ClassDB::bind_method(D_METHOD("set_hide_on_ok", "enabled"), &AcceptDialog::set_hide_on_ok); ClassDB::bind_method(D_METHOD("get_hide_on_ok"), &AcceptDialog::get_hide_on_ok); - ClassDB::bind_method(D_METHOD("add_button:Button", "text", "right", "action"), &AcceptDialog::add_button, DEFVAL(false), DEFVAL("")); - ClassDB::bind_method(D_METHOD("add_cancel:Button", "name"), &AcceptDialog::add_cancel); + ClassDB::bind_method(D_METHOD("add_button", "text", "right", "action"), &AcceptDialog::add_button, DEFVAL(false), DEFVAL("")); + ClassDB::bind_method(D_METHOD("add_cancel", "name"), &AcceptDialog::add_cancel); ClassDB::bind_method(D_METHOD("_builtin_text_entered"), &AcceptDialog::_builtin_text_entered); - ClassDB::bind_method(D_METHOD("register_text_enter:LineEdit", "line_edit"), &AcceptDialog::register_text_enter); + ClassDB::bind_method(D_METHOD("register_text_enter", "line_edit"), &AcceptDialog::register_text_enter); ClassDB::bind_method(D_METHOD("_custom_action"), &AcceptDialog::_custom_action); ClassDB::bind_method(D_METHOD("set_text", "text"), &AcceptDialog::set_text); ClassDB::bind_method(D_METHOD("get_text"), &AcceptDialog::get_text); @@ -519,7 +546,7 @@ AcceptDialog::AcceptDialog() { label->set_anchor(MARGIN_RIGHT, ANCHOR_END); label->set_anchor(MARGIN_BOTTOM, ANCHOR_END); label->set_begin(Point2(margin, margin)); - label->set_end(Point2(margin, button_margin + 10)); + label->set_end(Point2(-margin, -button_margin - 10)); //label->set_autowrap(true); add_child(label); @@ -542,9 +569,11 @@ AcceptDialog::AcceptDialog() { AcceptDialog::~AcceptDialog() { } +// ConfirmationDialog + void ConfirmationDialog::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_cancel:Button"), &ConfirmationDialog::get_cancel); + ClassDB::bind_method(D_METHOD("get_cancel"), &ConfirmationDialog::get_cancel); } Button *ConfirmationDialog::get_cancel() { @@ -555,5 +584,8 @@ Button *ConfirmationDialog::get_cancel() { ConfirmationDialog::ConfirmationDialog() { set_title(RTR("Please Confirm...")); +#ifdef TOOLS_ENABLED + set_custom_minimum_size(Size2(200, 70) * EDSCALE); +#endif cancel = add_cancel(); } diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h index a729a8f90..9d8f113ca 100644 --- a/scene/gui/dialogs.h +++ b/scene/gui/dialogs.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -59,7 +60,7 @@ class WindowDialog : public Popup { Point2 drag_offset_far; bool resizable; - void _gui_input(const InputEvent &p_event); + void _gui_input(const Ref<InputEvent> &p_event); void _closed(); int _drag_hit_test(const Point2 &pos) const; diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index d4643b399..74255b38b 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -60,21 +61,20 @@ void FileDialog::_notification(int p_what) { } } -void FileDialog::_unhandled_input(const InputEvent &p_event) { +void FileDialog::_unhandled_input(const Ref<InputEvent> &p_event) { - if (p_event.type == InputEvent::KEY && is_window_modal_on_top()) { + Ref<InputEventKey> k = p_event; + if (k.is_valid() && is_window_modal_on_top()) { - const InputEventKey &k = p_event.key; - - if (k.pressed) { + if (k->is_pressed()) { bool handled = true; - switch (k.scancode) { + switch (k->get_scancode()) { case KEY_H: { - if (k.mod.command) { + if (k->get_command()) { set_show_hidden_files(!show_hidden_files); } else { handled = false; @@ -335,8 +335,8 @@ void FileDialog::update_file_list() { dirs.push_back(".."); } - dirs.sort_custom<NoCaseComparator>(); - files.sort_custom<NoCaseComparator>(); + dirs.sort_custom<NaturalNoCaseComparator>(); + files.sort_custom<NaturalNoCaseComparator>(); while (!dirs.empty()) { String &dir_name = dirs.front()->get(); @@ -701,7 +701,7 @@ void FileDialog::_bind_methods() { ClassDB::bind_method(D_METHOD("set_current_path", "path"), &FileDialog::set_current_path); ClassDB::bind_method(D_METHOD("set_mode", "mode"), &FileDialog::set_mode); ClassDB::bind_method(D_METHOD("get_mode"), &FileDialog::get_mode); - ClassDB::bind_method(D_METHOD("get_vbox:VBoxContainer"), &FileDialog::get_vbox); + ClassDB::bind_method(D_METHOD("get_vbox"), &FileDialog::get_vbox); ClassDB::bind_method(D_METHOD("set_access", "access"), &FileDialog::set_access); ClassDB::bind_method(D_METHOD("get_access"), &FileDialog::get_access); ClassDB::bind_method(D_METHOD("set_show_hidden_files", "show"), &FileDialog::set_show_hidden_files); @@ -850,9 +850,9 @@ void LineEditFileChooser::_bind_methods() { ClassDB::bind_method(D_METHOD("_browse"), &LineEditFileChooser::_browse); ClassDB::bind_method(D_METHOD("_chosen"), &LineEditFileChooser::_chosen); - ClassDB::bind_method(D_METHOD("get_button:Button"), &LineEditFileChooser::get_button); - ClassDB::bind_method(D_METHOD("get_line_edit:LineEdit"), &LineEditFileChooser::get_line_edit); - ClassDB::bind_method(D_METHOD("get_file_dialog:FileDialog"), &LineEditFileChooser::get_file_dialog); + ClassDB::bind_method(D_METHOD("get_button"), &LineEditFileChooser::get_button); + ClassDB::bind_method(D_METHOD("get_line_edit"), &LineEditFileChooser::get_line_edit); + ClassDB::bind_method(D_METHOD("get_file_dialog"), &LineEditFileChooser::get_file_dialog); } void LineEditFileChooser::_chosen(const String &p_text) { diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h index 397b0feba..9873a677b 100644 --- a/scene/gui/file_dialog.h +++ b/scene/gui/file_dialog.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -114,7 +115,7 @@ private: void _update_drives(); - void _unhandled_input(const InputEvent &p_event); + void _unhandled_input(const Ref<InputEvent> &p_event); virtual void _post_popup(); diff --git a/scene/gui/color_ramp_edit.cpp b/scene/gui/gradient_edit.cpp index 131638bb7..22de28ea7 100644 --- a/scene/gui/color_ramp_edit.cpp +++ b/scene/gui/gradient_edit.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -26,10 +27,10 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "color_ramp_edit.h" +#include "gradient_edit.h" #include "os/keyboard.h" -ColorRampEdit::ColorRampEdit() { +GradientEdit::GradientEdit() { grabbed = -1; grabbing = false; set_focus_mode(FOCUS_ALL); @@ -41,10 +42,11 @@ ColorRampEdit::ColorRampEdit() { add_child(popup); checker = Ref<ImageTexture>(memnew(ImageTexture)); - checker->create_from_image(Image(checker_bg_png), ImageTexture::FLAG_REPEAT); + Ref<Image> img = memnew(Image(checker_bg_png)); + checker->create_from_image(img, ImageTexture::FLAG_REPEAT); } -int ColorRampEdit::_get_point_from_pos(int x) { +int GradientEdit::_get_point_from_pos(int x) { int result = -1; int total_w = get_size().width - get_size().height - 3; for (int i = 0; i < points.size(); i++) { @@ -56,22 +58,22 @@ int ColorRampEdit::_get_point_from_pos(int x) { return result; } -void ColorRampEdit::_show_color_picker() { +void GradientEdit::_show_color_picker() { if (grabbed == -1) return; - Size2 ms = Size2(350, picker->get_combined_minimum_size().height + 10); picker->set_pick_color(points[grabbed].color); - popup->set_pos(get_global_pos() - Vector2(ms.width - get_size().width, ms.height)); - popup->set_size(ms); + popup->set_position(get_global_position() - popup->get_combined_minimum_size()); popup->popup(); } -ColorRampEdit::~ColorRampEdit() { +GradientEdit::~GradientEdit() { } -void ColorRampEdit::_gui_input(const InputEvent &p_event) { +void GradientEdit::_gui_input(const Ref<InputEvent> &p_event) { - if (p_event.type == InputEvent::KEY && p_event.key.pressed && p_event.key.scancode == KEY_DELETE && grabbed != -1) { + Ref<InputEventKey> k = p_event; + + if (k.is_valid() && k->is_pressed() && k->get_scancode() == KEY_DELETE && grabbed != -1) { points.remove(grabbed); grabbed = -1; @@ -81,16 +83,17 @@ void ColorRampEdit::_gui_input(const InputEvent &p_event) { accept_event(); } + Ref<InputEventMouseButton> mb = p_event; //Show color picker on double click. - if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 1 && p_event.mouse_button.doubleclick && p_event.mouse_button.pressed) { - grabbed = _get_point_from_pos(p_event.mouse_button.x); + if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_doubleclick() && mb->is_pressed()) { + grabbed = _get_point_from_pos(mb->get_position().x); _show_color_picker(); accept_event(); } //Delete point on right click - if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 2 && p_event.mouse_button.pressed) { - grabbed = _get_point_from_pos(p_event.mouse_button.x); + if (mb.is_valid() && mb->get_button_index() == 2 && mb->is_pressed()) { + grabbed = _get_point_from_pos(mb->get_position().x); if (grabbed != -1) { points.remove(grabbed); grabbed = -1; @@ -102,14 +105,14 @@ void ColorRampEdit::_gui_input(const InputEvent &p_event) { } //Hold alt key to duplicate selected color - if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 1 && p_event.mouse_button.pressed && p_event.key.mod.alt) { + if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed() && mb->get_alt()) { - int x = p_event.mouse_button.x; + int x = mb->get_position().x; grabbed = _get_point_from_pos(x); if (grabbed != -1) { int total_w = get_size().width - get_size().height - 3; - ColorRamp::Point newPoint = points[grabbed]; + Gradient::Point newPoint = points[grabbed]; newPoint.offset = CLAMP(x / float(total_w), 0, 1); points.push_back(newPoint); @@ -126,10 +129,10 @@ void ColorRampEdit::_gui_input(const InputEvent &p_event) { } } - if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 1 && p_event.mouse_button.pressed) { + if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) { update(); - int x = p_event.mouse_button.x; + int x = mb->get_position().x; int total_w = get_size().width - get_size().height - 3; //Check if color selector was clicked. @@ -147,11 +150,11 @@ void ColorRampEdit::_gui_input(const InputEvent &p_event) { } //insert - ColorRamp::Point newPoint; + Gradient::Point newPoint; newPoint.offset = CLAMP(x / float(total_w), 0, 1); - ColorRamp::Point prev; - ColorRamp::Point next; + Gradient::Point prev; + Gradient::Point next; int pos = -1; for (int i = 0; i < points.size(); i++) { @@ -194,7 +197,7 @@ void ColorRampEdit::_gui_input(const InputEvent &p_event) { emit_signal("ramp_changed"); } - if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 1 && !p_event.mouse_button.pressed) { + if (mb.is_valid() && mb->get_button_index() == 1 && !mb->is_pressed()) { if (grabbing) { grabbing = false; @@ -203,15 +206,18 @@ void ColorRampEdit::_gui_input(const InputEvent &p_event) { update(); } - if (p_event.type == InputEvent::MOUSE_MOTION && grabbing) { + Ref<InputEventMouseMotion> mm = p_event; + + if (mm.is_valid() && grabbing) { int total_w = get_size().width - get_size().height - 3; - int x = p_event.mouse_motion.x; + int x = mm->get_position().x; + float newofs = CLAMP(x / float(total_w), 0, 1); //Snap to nearest point if holding shift - if (p_event.key.mod.shift) { + if (mm->get_shift()) { float snap_treshhold = 0.03; float smallest_ofs = snap_treshhold; bool founded = false; @@ -264,7 +270,7 @@ void ColorRampEdit::_gui_input(const InputEvent &p_event) { } } -void ColorRampEdit::_notification(int p_what) { +void GradientEdit::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { if (!picker->is_connected("color_changed", this, "_color_changed")) { @@ -285,7 +291,7 @@ void ColorRampEdit::_notification(int p_what) { _draw_checker(0, 0, total_w, h); //Draw color ramp - ColorRamp::Point prev; + Gradient::Point prev; prev.offset = 0; if (points.size() == 0) prev.color = Color(0, 0, 0); //Draw black rectangle if we have no points @@ -294,7 +300,7 @@ void ColorRampEdit::_notification(int p_what) { for (int i = -1; i < points.size(); i++) { - ColorRamp::Point next; + Gradient::Point next; //If there is no next point if (i + 1 == points.size()) { if (points.size() == 0) @@ -362,7 +368,7 @@ void ColorRampEdit::_notification(int p_what) { } } -void ColorRampEdit::_draw_checker(int x, int y, int w, int h) { +void GradientEdit::_draw_checker(int x, int y, int w, int h) { //Draw it with polygon to insert UVs for scale Vector<Vector2> backPoints; backPoints.push_back(Vector2(x, y)); @@ -383,12 +389,12 @@ void ColorRampEdit::_draw_checker(int x, int y, int w, int h) { draw_polygon(backPoints, colorPoints, uvPoints, checker); } -Size2 ColorRampEdit::get_minimum_size() const { +Size2 GradientEdit::get_minimum_size() const { return Vector2(0, 16); } -void ColorRampEdit::_color_changed(const Color &p_color) { +void GradientEdit::_color_changed(const Color &p_color) { if (grabbed == -1) return; @@ -397,12 +403,12 @@ void ColorRampEdit::_color_changed(const Color &p_color) { emit_signal("ramp_changed"); } -void ColorRampEdit::set_ramp(const Vector<float> &p_offsets, const Vector<Color> &p_colors) { +void GradientEdit::set_ramp(const Vector<float> &p_offsets, const Vector<Color> &p_colors) { ERR_FAIL_COND(p_offsets.size() != p_colors.size()); points.clear(); for (int i = 0; i < p_offsets.size(); i++) { - ColorRamp::Point p; + Gradient::Point p; p.offset = p_offsets[i]; p.color = p_colors[i]; points.push_back(p); @@ -412,33 +418,33 @@ void ColorRampEdit::set_ramp(const Vector<float> &p_offsets, const Vector<Color> update(); } -Vector<float> ColorRampEdit::get_offsets() const { +Vector<float> GradientEdit::get_offsets() const { Vector<float> ret; for (int i = 0; i < points.size(); i++) ret.push_back(points[i].offset); return ret; } -Vector<Color> ColorRampEdit::get_colors() const { +Vector<Color> GradientEdit::get_colors() const { Vector<Color> ret; for (int i = 0; i < points.size(); i++) ret.push_back(points[i].color); return ret; } -void ColorRampEdit::set_points(Vector<ColorRamp::Point> &p_points) { +void GradientEdit::set_points(Vector<Gradient::Point> &p_points) { if (points.size() != p_points.size()) grabbed = -1; points.clear(); points = p_points; } -Vector<ColorRamp::Point> &ColorRampEdit::get_points() { +Vector<Gradient::Point> &GradientEdit::get_points() { return points; } -void ColorRampEdit::_bind_methods() { - ClassDB::bind_method(D_METHOD("_gui_input"), &ColorRampEdit::_gui_input); - ClassDB::bind_method(D_METHOD("_color_changed"), &ColorRampEdit::_color_changed); +void GradientEdit::_bind_methods() { + ClassDB::bind_method(D_METHOD("_gui_input"), &GradientEdit::_gui_input); + ClassDB::bind_method(D_METHOD("_color_changed"), &GradientEdit::_color_changed); ADD_SIGNAL(MethodInfo("ramp_changed")); } diff --git a/scene/gui/color_ramp_edit.h b/scene/gui/gradient_edit.h index bb12064dd..6c4ae6fd1 100644 --- a/scene/gui/color_ramp_edit.h +++ b/scene/gui/gradient_edit.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -36,9 +37,9 @@ #define POINT_WIDTH 8 -class ColorRampEdit : public Control { +class GradientEdit : public Control { - GDCLASS(ColorRampEdit, Control); + GDCLASS(GradientEdit, Control); PopupPanel *popup; ColorPicker *picker; @@ -47,7 +48,7 @@ class ColorRampEdit : public Control { bool grabbing; int grabbed; - Vector<ColorRamp::Point> points; + Vector<Gradient::Point> points; void _draw_checker(int x, int y, int w, int h); void _color_changed(const Color &p_color); @@ -55,7 +56,7 @@ class ColorRampEdit : public Control { void _show_color_picker(); protected: - void _gui_input(const InputEvent &p_event); + void _gui_input(const Ref<InputEvent> &p_event); void _notification(int p_what); static void _bind_methods(); @@ -63,12 +64,12 @@ public: void set_ramp(const Vector<float> &p_offsets, const Vector<Color> &p_colors); Vector<float> get_offsets() const; Vector<Color> get_colors() const; - void set_points(Vector<ColorRamp::Point> &p_points); - Vector<ColorRamp::Point> &get_points(); + void set_points(Vector<Gradient::Point> &p_points); + Vector<Gradient::Point> &get_points(); virtual Size2 get_minimum_size() const; - ColorRampEdit(); - virtual ~ColorRampEdit(); + GradientEdit(); + virtual ~GradientEdit(); }; /*class ColorRampEditPanel : public Panel diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 6a3b5e713..ec1932ed5 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -139,13 +140,13 @@ void GraphEdit::_update_scroll_offset() { Point2 pos = gn->get_offset() * zoom; pos -= Point2(h_scroll->get_value(), v_scroll->get_value()); - gn->set_pos(pos); + gn->set_position(pos); if (gn->get_scale() != Vector2(zoom, zoom)) { gn->set_scale(Vector2(zoom, zoom)); } } - connections_layer->set_pos(-Point2(h_scroll->get_value(), v_scroll->get_value())); + connections_layer->set_position(-Point2(h_scroll->get_value(), v_scroll->get_value())); set_block_minimum_size_adjust(false); awaiting_scroll_offset_update = false; } @@ -167,24 +168,24 @@ void GraphEdit::_update_scroll() { continue; Rect2 r; - r.pos = gn->get_offset() * zoom; + r.position = gn->get_offset() * zoom; r.size = gn->get_size() * zoom; screen = screen.merge(r); } - screen.pos -= get_size(); + screen.position -= get_size(); screen.size += get_size() * 2.0; - h_scroll->set_min(screen.pos.x); - h_scroll->set_max(screen.pos.x + screen.size.x); + h_scroll->set_min(screen.position.x); + h_scroll->set_max(screen.position.x + screen.size.x); h_scroll->set_page(get_size().x); if (h_scroll->get_max() - h_scroll->get_min() <= h_scroll->get_page()) h_scroll->hide(); else h_scroll->show(); - v_scroll->set_min(screen.pos.y); - v_scroll->set_max(screen.pos.y + screen.size.y); + v_scroll->set_min(screen.position.y); + v_scroll->set_max(screen.position.y + screen.size.y); v_scroll->set_page(get_size().y); if (v_scroll->get_max() - v_scroll->get_min() <= v_scroll->get_page()) @@ -206,9 +207,10 @@ void GraphEdit::_graph_node_raised(Node *p_gn) { GraphNode *gn = p_gn->cast_to<GraphNode>(); ERR_FAIL_COND(!gn); - gn->raise(); if (gn->is_comment()) { move_child(gn, 0); + } else { + gn->raise(); } int first_not_comment = 0; for (int i = 0; i < get_child_count(); i++) { @@ -267,14 +269,14 @@ void GraphEdit::_notification(int p_what) { Size2 hmin = h_scroll->get_combined_minimum_size(); Size2 vmin = v_scroll->get_combined_minimum_size(); - v_scroll->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, vmin.width); + v_scroll->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -vmin.width); v_scroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0); v_scroll->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 0); v_scroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0); h_scroll->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 0); h_scroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0); - h_scroll->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, hmin.height); + h_scroll->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, -hmin.height); h_scroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0); zoom_minus->set_icon(get_icon("minus")); @@ -349,14 +351,14 @@ bool GraphEdit::_filter_input(const Point2 &p_point) { for (int j = 0; j < gn->get_connection_output_count(); j++) { - Vector2 pos = gn->get_connection_output_pos(j) + gn->get_pos(); + Vector2 pos = gn->get_connection_output_pos(j) + gn->get_position(); if (pos.distance_to(p_point) < grab_r) return true; } for (int j = 0; j < gn->get_connection_input_count(); j++) { - Vector2 pos = gn->get_connection_input_pos(j) + gn->get_pos(); + Vector2 pos = gn->get_connection_input_pos(j) + gn->get_position(); if (pos.distance_to(p_point) < grab_r) { return true; } @@ -366,13 +368,14 @@ bool GraphEdit::_filter_input(const Point2 &p_point) { return false; } -void GraphEdit::_top_layer_input(const InputEvent &p_ev) { +void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { float grab_r_extend = 2.0; - if (p_ev.type == InputEvent::MOUSE_BUTTON && p_ev.mouse_button.button_index == BUTTON_LEFT && p_ev.mouse_button.pressed) { + Ref<InputEventMouseButton> mb = p_ev; + if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) { Ref<Texture> port = get_icon("port", "GraphNode"); - Vector2 mpos(p_ev.mouse_button.x, p_ev.mouse_button.y); + Vector2 mpos(mb->get_position().x, mb->get_position().y); float grab_r = port->get_width() * 0.5 * grab_r_extend; for (int i = get_child_count() - 1; i >= 0; i--) { @@ -382,7 +385,7 @@ void GraphEdit::_top_layer_input(const InputEvent &p_ev) { for (int j = 0; j < gn->get_connection_output_count(); j++) { - Vector2 pos = gn->get_connection_output_pos(j) + gn->get_pos(); + Vector2 pos = gn->get_connection_output_pos(j) + gn->get_position(); if (pos.distance_to(mpos) < grab_r) { if (valid_left_disconnect_types.has(gn->get_connection_output_type(j))) { @@ -429,7 +432,7 @@ void GraphEdit::_top_layer_input(const InputEvent &p_ev) { for (int j = 0; j < gn->get_connection_input_count(); j++) { - Vector2 pos = gn->get_connection_input_pos(j) + gn->get_pos(); + Vector2 pos = gn->get_connection_input_pos(j) + gn->get_position(); if (pos.distance_to(mpos) < grab_r) { @@ -478,14 +481,15 @@ void GraphEdit::_top_layer_input(const InputEvent &p_ev) { } } - if (p_ev.type == InputEvent::MOUSE_MOTION && connecting) { + Ref<InputEventMouseMotion> mm = p_ev; + if (mm.is_valid() && connecting) { - connecting_to = Vector2(p_ev.mouse_motion.x, p_ev.mouse_motion.y); + connecting_to = mm->get_position(); connecting_target = false; top_layer->update(); Ref<Texture> port = get_icon("port", "GraphNode"); - Vector2 mpos(p_ev.mouse_button.x, p_ev.mouse_button.y); + Vector2 mpos = mm->get_position(); float grab_r = port->get_width() * 0.5 * grab_r_extend; for (int i = get_child_count() - 1; i >= 0; i--) { @@ -496,7 +500,7 @@ void GraphEdit::_top_layer_input(const InputEvent &p_ev) { if (!connecting_out) { for (int j = 0; j < gn->get_connection_output_count(); j++) { - Vector2 pos = gn->get_connection_output_pos(j) + gn->get_pos(); + Vector2 pos = gn->get_connection_output_pos(j) + gn->get_position(); int type = gn->get_connection_output_type(j); if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && pos.distance_to(mpos) < grab_r) { @@ -511,7 +515,7 @@ void GraphEdit::_top_layer_input(const InputEvent &p_ev) { for (int j = 0; j < gn->get_connection_input_count(); j++) { - Vector2 pos = gn->get_connection_input_pos(j) + gn->get_pos(); + Vector2 pos = gn->get_connection_input_pos(j) + gn->get_position(); int type = gn->get_connection_input_type(j); if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && pos.distance_to(mpos) < grab_r) { connecting_target = true; @@ -525,7 +529,7 @@ void GraphEdit::_top_layer_input(const InputEvent &p_ev) { } } - if (p_ev.type == InputEvent::MOUSE_BUTTON && p_ev.mouse_button.button_index == BUTTON_LEFT && !p_ev.mouse_button.pressed) { + if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && !mb->is_pressed()) { if (connecting && connecting_target) { @@ -543,7 +547,7 @@ void GraphEdit::_top_layer_input(const InputEvent &p_ev) { } else if (!just_disconected) { String from = connecting_from; int from_slot = connecting_index; - Vector2 ofs = Vector2(p_ev.mouse_button.x, p_ev.mouse_button.y); + Vector2 ofs = Vector2(mb->get_position().x, mb->get_position().y); emit_signal("connection_to_empty", from, from_slot, ofs); } connecting = false; @@ -565,7 +569,7 @@ static _FORCE_INLINE_ Vector2 _bezier_interp(real_t t, Vector2 start, Vector2 co return start * omt3 + control_1 * omt2 * t * 3.0 + control_2 * omt * t2 * 3.0 + end * t3; } -void GraphEdit::_bake_segment2d(CanvasItem *p_where, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color &p_color, const Color &p_to_color, int &lines) const { +void GraphEdit::_bake_segment2d(Vector<Vector2> &points, Vector<Color> &colors, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color &p_color, const Color &p_to_color, int &lines) const { float mp = p_begin + (p_end - p_begin) * 0.5; Vector2 beg = _bezier_interp(p_begin, p_a, p_a + p_out, p_b + p_in, p_b); @@ -578,11 +582,12 @@ void GraphEdit::_bake_segment2d(CanvasItem *p_where, float p_begin, float p_end, if (p_depth >= p_min_depth && (dp < p_tol || p_depth >= p_max_depth)) { - p_where->draw_line(beg, end, p_color.linear_interpolate(p_to_color, mp), 2, true); + points.push_back((beg + end) * 0.5); + colors.push_back(p_color.linear_interpolate(p_to_color, mp)); lines++; } else { - _bake_segment2d(p_where, p_begin, mp, p_a, p_out, p_b, p_in, p_depth + 1, p_min_depth, p_max_depth, p_tol, p_color, p_to_color, lines); - _bake_segment2d(p_where, mp, p_end, p_a, p_out, p_b, p_in, p_depth + 1, p_min_depth, p_max_depth, p_tol, p_color, p_to_color, lines); + _bake_segment2d(points, colors, p_begin, mp, p_a, p_out, p_b, p_in, p_depth + 1, p_min_depth, p_max_depth, p_tol, p_color, p_to_color, lines); + _bake_segment2d(points, colors, mp, p_end, p_a, p_out, p_b, p_in, p_depth + 1, p_min_depth, p_max_depth, p_tol, p_color, p_to_color, lines); } } @@ -597,7 +602,7 @@ void GraphEdit::_draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const int cp_neg_len = get_constant("bezier_len_neg"); if (diff > 0) { - cp_offset = MAX(cp_len, diff * 0.5); + cp_offset = MIN(cp_len, diff * 0.5); } else { cp_offset = MAX(MIN(cp_len - diff, cp_neg_len), -diff * 0.5); } @@ -606,7 +611,16 @@ void GraphEdit::_draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const Vector2 c2 = Vector2(-cp_offset * zoom, 0); int lines = 0; - _bake_segment2d(p_where, 0, 1, p_from, c1, p_to, c2, 0, 3, 9, 8, p_color, p_to_color, lines); + + Vector<Point2> points; + Vector<Color> colors; + points.push_back(p_from); + colors.push_back(p_color); + _bake_segment2d(points, colors, 0, 1, p_from, c1, p_to, c2, 0, 3, 9, 8, p_color, p_to_color, lines); + points.push_back(p_to); + colors.push_back(p_to_color); + + p_where->draw_polyline_colors(points, colors, 2, true); #else @@ -703,7 +717,7 @@ void GraphEdit::_top_layer_draw() { pos = from->get_connection_output_pos(connecting_index); else pos = from->get_connection_input_pos(connecting_index); - pos += from->get_pos(); + pos += from->get_position(); Vector2 topos; topos = connecting_to; @@ -738,18 +752,19 @@ void GraphEdit::set_selected(Node *p_child) { } } -void GraphEdit::_gui_input(const InputEvent &p_ev) { +void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { - if (p_ev.type == InputEvent::MOUSE_MOTION && (p_ev.mouse_motion.button_mask & BUTTON_MASK_MIDDLE || (p_ev.mouse_motion.button_mask & BUTTON_MASK_LEFT && Input::get_singleton()->is_key_pressed(KEY_SPACE)))) { - h_scroll->set_value(h_scroll->get_value() - p_ev.mouse_motion.relative_x); - v_scroll->set_value(v_scroll->get_value() - p_ev.mouse_motion.relative_y); + Ref<InputEventMouseMotion> mm = p_ev; + if (mm.is_valid() && (mm->get_button_mask() & BUTTON_MASK_MIDDLE || (mm->get_button_mask() & BUTTON_MASK_LEFT && Input::get_singleton()->is_key_pressed(KEY_SPACE)))) { + h_scroll->set_value(h_scroll->get_value() - mm->get_relative().x); + v_scroll->set_value(v_scroll->get_value() - mm->get_relative().y); } - if (p_ev.type == InputEvent::MOUSE_MOTION && dragging) { + if (mm.is_valid() && dragging) { just_selected = true; // TODO: Remove local mouse pos hack if/when InputEventMouseMotion is fixed to support floats - //drag_accum+=Vector2(p_ev.mouse_motion.relative_x,p_ev.mouse_motion.relative_y); + //drag_accum+=Vector2(mm->get_relative().x,mm->get_relative().y); drag_accum = get_local_mouse_pos() - drag_origin; for (int i = get_child_count() - 1; i >= 0; i--) { GraphNode *gn = get_child(i)->cast_to<GraphNode>(); @@ -766,7 +781,7 @@ void GraphEdit::_gui_input(const InputEvent &p_ev) { } } - if (p_ev.type == InputEvent::MOUSE_MOTION && box_selecting) { + if (mm.is_valid() && box_selecting) { box_selecting_to = get_local_mouse_pos(); box_selecting_rect = Rect2(MIN(box_selecting_from.x, box_selecting_to.x), @@ -793,11 +808,10 @@ void GraphEdit::_gui_input(const InputEvent &p_ev) { top_layer->update(); } - if (p_ev.type == InputEvent::MOUSE_BUTTON) { + Ref<InputEventMouseButton> b = p_ev; + if (b.is_valid()) { - const InputEventMouseButton &b = p_ev.mouse_button; - - if (b.button_index == BUTTON_RIGHT && b.pressed) { + if (b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) { if (box_selecting) { box_selecting = false; for (int i = get_child_count() - 1; i >= 0; i--) { @@ -814,12 +828,12 @@ void GraphEdit::_gui_input(const InputEvent &p_ev) { connecting = false; top_layer->update(); } else { - emit_signal("popup_request", Vector2(b.global_x, b.global_y)); + emit_signal("popup_request", b->get_global_position()); } } } - if (b.button_index == BUTTON_LEFT && !b.pressed && dragging) { + if (b->get_button_index() == BUTTON_LEFT && !b->is_pressed() && dragging) { if (!just_selected && drag_accum == Vector2() && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { //deselect current node for (int i = get_child_count() - 1; i >= 0; i--) { @@ -854,30 +868,28 @@ void GraphEdit::_gui_input(const InputEvent &p_ev) { connections_layer->update(); } - if (b.button_index == BUTTON_LEFT && b.pressed) { + if (b->get_button_index() == BUTTON_LEFT && b->is_pressed()) { GraphNode *gn = NULL; - GraphNode *gn_selected = NULL; + for (int i = get_child_count() - 1; i >= 0; i--) { - gn_selected = get_child(i)->cast_to<GraphNode>(); + GraphNode *gn_selected = get_child(i)->cast_to<GraphNode>(); if (gn_selected) { - if (gn_selected->is_resizing()) continue; - Rect2 r = gn_selected->get_rect(); - r.size *= zoom; - if (r.has_point(get_local_mouse_pos())) + if (gn_selected->has_point(gn_selected->get_local_mouse_pos())) { gn = gn_selected; - break; + break; + } } } if (gn) { - if (_filter_input(Vector2(b.x, b.y))) + if (_filter_input(b->get_position())) return; dragging = true; @@ -902,14 +914,14 @@ void GraphEdit::_gui_input(const InputEvent &p_ev) { } } else { - if (_filter_input(Vector2(b.x, b.y))) + if (_filter_input(b->get_position())) return; if (Input::get_singleton()->is_key_pressed(KEY_SPACE)) return; box_selecting = true; box_selecting_from = get_local_mouse_pos(); - if (b.mod.control) { + if (b->get_control()) { box_selection_mode_aditive = true; previus_selected.clear(); for (int i = get_child_count() - 1; i >= 0; i--) { @@ -920,7 +932,7 @@ void GraphEdit::_gui_input(const InputEvent &p_ev) { previus_selected.push_back(gn); } - } else if (b.mod.shift) { + } else if (b->get_shift()) { box_selection_mode_aditive = false; previus_selected.clear(); for (int i = get_child_count() - 1; i >= 0; i--) { @@ -946,29 +958,42 @@ void GraphEdit::_gui_input(const InputEvent &p_ev) { } } - if (b.button_index == BUTTON_LEFT && !b.pressed && box_selecting) { + if (b->get_button_index() == BUTTON_LEFT && !b->is_pressed() && box_selecting) { box_selecting = false; previus_selected.clear(); top_layer->update(); } - if (b.button_index == BUTTON_WHEEL_UP && b.pressed) { + if (b->get_button_index() == BUTTON_WHEEL_UP && b->is_pressed()) { //too difficult to get right //set_zoom(zoom*ZOOM_SCALE); } - if (b.button_index == BUTTON_WHEEL_DOWN && b.pressed) { + if (b->get_button_index() == BUTTON_WHEEL_DOWN && b->is_pressed()) { //too difficult to get right //set_zoom(zoom/ZOOM_SCALE); } + if (b->get_button_index() == BUTTON_WHEEL_UP) { + h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * b->get_factor() / 8); + } + if (b->get_button_index() == BUTTON_WHEEL_DOWN) { + h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * b->get_factor() / 8); + } + if (b->get_button_index() == BUTTON_WHEEL_RIGHT) { + v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * b->get_factor() / 8); + } + if (b->get_button_index() == BUTTON_WHEEL_LEFT) { + v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * b->get_factor() / 8); + } } - if (p_ev.type == InputEvent::KEY && p_ev.key.scancode == KEY_D && p_ev.key.pressed && p_ev.key.mod.command) { + Ref<InputEventKey> k = p_ev; + if (k.is_valid() && k->get_scancode() == KEY_D && k->is_pressed() && k->get_command()) { emit_signal("duplicate_nodes_request"); accept_event(); } - if (p_ev.type == InputEvent::KEY && p_ev.key.scancode == KEY_DELETE && p_ev.key.pressed) { + if (k.is_valid() && k->get_scancode() == KEY_DELETE && k->is_pressed()) { emit_signal("delete_nodes_request"); accept_event(); } @@ -1132,7 +1157,7 @@ void GraphEdit::_snap_value_changed(double) { void GraphEdit::_bind_methods() { - ClassDB::bind_method(D_METHOD("connect_node:Error", "from", "from_port", "to", "to_port"), &GraphEdit::connect_node); + ClassDB::bind_method(D_METHOD("connect_node", "from", "from_port", "to", "to_port"), &GraphEdit::connect_node); ClassDB::bind_method(D_METHOD("is_node_connected", "from", "from_port", "to", "to_port"), &GraphEdit::is_node_connected); ClassDB::bind_method(D_METHOD("disconnect_node", "from", "from_port", "to", "to_port"), &GraphEdit::disconnect_node); ClassDB::bind_method(D_METHOD("get_connection_list"), &GraphEdit::_get_connection_list); @@ -1199,6 +1224,7 @@ GraphEdit::GraphEdit() { connections_layer->connect("draw", this, "_connections_layer_draw"); connections_layer->set_name("CLAYER"); connections_layer->set_disable_visibility_clip(true); // so it can draw freely and be offseted + connections_layer->set_mouse_filter(MOUSE_FILTER_IGNORE); h_scroll = memnew(HScrollBar); h_scroll->set_name("_h_scroll"); @@ -1228,7 +1254,7 @@ GraphEdit::GraphEdit() { HBoxContainer *zoom_hb = memnew(HBoxContainer); top_layer->add_child(zoom_hb); - zoom_hb->set_pos(Vector2(10, 10)); + zoom_hb->set_position(Vector2(10, 10)); zoom_minus = memnew(ToolButton); zoom_hb->add_child(zoom_minus); diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index 5166f8231..e908829d5 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -109,7 +110,7 @@ private: bool awaiting_scroll_offset_update; List<Connection> connections; - void _bake_segment2d(CanvasItem *p_where, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color &p_color, const Color &p_to_color, int &lines) const; + void _bake_segment2d(Vector<Vector2> &points, Vector<Color> &colors, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color &p_color, const Color &p_to_color, int &lines) const; void _draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const Vector2 &p_to, const Color &p_color, const Color &p_to_color); @@ -118,11 +119,11 @@ private: void _update_scroll(); void _scroll_moved(double); - void _gui_input(const InputEvent &p_ev); + void _gui_input(const Ref<InputEvent> &p_ev); Control *connections_layer; GraphEditFilter *top_layer; - void _top_layer_input(const InputEvent &p_ev); + void _top_layer_input(const Ref<InputEvent> &p_ev); void _top_layer_draw(); void _connections_layer_draw(); void _update_scroll_offset(); diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index afbb0bbad..b9062295b 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -27,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "graph_node.h" -#include "method_bind_ext.inc" +#include "method_bind_ext.gen.inc" bool GraphNode::_set(const StringName &p_name, const Variant &p_value) { @@ -175,6 +176,7 @@ bool GraphNode::has_point(const Point2 &p_point) const { if (Rect2(get_size() - resizer->get_size(), resizer->get_size()).has_point(p_point)) { return true; } + if (Rect2(0, 0, get_size().width, comment->get_margin(MARGIN_TOP)).has_point(p_point)) { return true; } @@ -238,7 +240,7 @@ void GraphNode::_notification(int p_what) { if (show_close) { Vector2 cpos = Point2(w + sb->get_margin(MARGIN_LEFT), -close->get_height() + close_offset); draw_texture(close, cpos); - close_rect.pos = cpos; + close_rect.position = cpos; close_rect.size = close->get_size(); } else { close_rect = Rect2(); @@ -573,18 +575,17 @@ Color GraphNode::get_connection_output_color(int p_idx) { return conn_output_cache[p_idx].color; } -void GraphNode::_gui_input(const InputEvent &p_ev) { +void GraphNode::_gui_input(const Ref<InputEvent> &p_ev) { - if (p_ev.type == InputEvent::MOUSE_BUTTON) { + Ref<InputEventMouseButton> mb = p_ev; + if (mb.is_valid()) { ERR_EXPLAIN("GraphNode must be the child of a GraphEdit node."); ERR_FAIL_COND(get_parent_control() == NULL); - print_line("INPUT EVENT BUTTON"); - - if (p_ev.mouse_button.pressed && p_ev.mouse_button.button_index == BUTTON_LEFT) { + if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { - Vector2 mpos = Vector2(p_ev.mouse_button.x, p_ev.mouse_button.y); + Vector2 mpos = Vector2(mb->get_position().x, mb->get_position().y); if (close_rect.size != Size2() && close_rect.has_point(mpos)) { emit_signal("close_request"); accept_event(); @@ -607,13 +608,14 @@ void GraphNode::_gui_input(const InputEvent &p_ev) { get_parent_control()->grab_focus(); } - if (!p_ev.mouse_button.pressed && p_ev.mouse_button.button_index == BUTTON_LEFT) { + if (!mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { resizing = false; } } - if (resizing && p_ev.type == InputEvent::MOUSE_MOTION) { - Vector2 mpos = Vector2(p_ev.mouse_motion.x, p_ev.mouse_motion.y); + Ref<InputEventMouseMotion> mm = p_ev; + if (resizing && mm.is_valid()) { + Vector2 mpos = mm->get_position(); Vector2 diff = mpos - resizing_from; @@ -662,7 +664,7 @@ void GraphNode::_bind_methods() { ClassDB::bind_method(D_METHOD("set_slot", "idx", "enable_left", "type_left", "color_left", "enable_right", "type_right", "color_right", "custom_left", "custom_right"), &GraphNode::set_slot, DEFVAL(Ref<Texture>()), DEFVAL(Ref<Texture>())); ClassDB::bind_method(D_METHOD("clear_slot", "idx"), &GraphNode::clear_slot); - ClassDB::bind_method(D_METHOD("clear_all_slots", "idx"), &GraphNode::clear_all_slots); + ClassDB::bind_method(D_METHOD("clear_all_slots"), &GraphNode::clear_all_slots); ClassDB::bind_method(D_METHOD("is_slot_enabled_left", "idx"), &GraphNode::is_slot_enabled_left); ClassDB::bind_method(D_METHOD("get_slot_type_left", "idx"), &GraphNode::get_slot_type_left); ClassDB::bind_method(D_METHOD("get_slot_color_left", "idx"), &GraphNode::get_slot_color_left); @@ -718,7 +720,7 @@ GraphNode::GraphNode() { overlay = OVERLAY_DISABLED; show_close = false; connpos_dirty = true; - set_mouse_filter(MOUSE_FILTER_PASS); + set_mouse_filter(MOUSE_FILTER_STOP); comment = false; resizeable = false; resizing = false; diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h index bab78dedb..a7d9e8ddb 100644 --- a/scene/gui/graph_node.h +++ b/scene/gui/graph_node.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -98,10 +99,8 @@ private: Overlay overlay; - bool has_point(const Point2 &p_point) const; - protected: - void _gui_input(const InputEvent &p_ev); + void _gui_input(const Ref<InputEvent> &p_ev); void _notification(int p_what); static void _bind_methods(); @@ -110,6 +109,8 @@ protected: void _get_property_list(List<PropertyInfo> *p_list) const; public: + bool has_point(const Point2 &p_point) const; + void set_slot(int p_idx, bool p_enable_left, int p_type_left, const Color &p_color_left, bool p_enable_right, int p_type_right, const Color &p_color_right, const Ref<Texture> &p_custom_left = Ref<Texture>(), const Ref<Texture> &p_custom_right = Ref<Texture>()); void clear_slot(int p_idx); void clear_all_slots(); diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp index aae11255e..06a58d69b 100644 --- a/scene/gui/grid_container.cpp +++ b/scene/gui/grid_container.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/grid_container.h b/scene/gui/grid_container.h index 61dda4e22..aaa6a295f 100644 --- a/scene/gui/grid_container.h +++ b/scene/gui/grid_container.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/input_action.cpp b/scene/gui/input_action.cpp index 9576bb07e..c08059a04 100644 --- a/scene/gui/input_action.cpp +++ b/scene/gui/input_action.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,95 +30,73 @@ #include "input_action.h" #include "os/keyboard.h" -void ShortCut::set_shortcut(const InputEvent &p_shortcut) { +void ShortCut::set_shortcut(const Ref<InputEvent> &p_shortcut) { shortcut = p_shortcut; emit_changed(); } -InputEvent ShortCut::get_shortcut() const { +Ref<InputEvent> ShortCut::get_shortcut() const { return shortcut; } -bool ShortCut::is_shortcut(const InputEvent &p_event) const { +bool ShortCut::is_shortcut(const Ref<InputEvent> &p_event) const { - bool same = false; - - switch (p_event.type) { - - case InputEvent::KEY: { - - same = (shortcut.key.scancode == p_event.key.scancode && shortcut.key.mod == p_event.key.mod); - - } break; - case InputEvent::JOYPAD_BUTTON: { - - same = (shortcut.joy_button.button_index == p_event.joy_button.button_index); - - } break; - case InputEvent::MOUSE_BUTTON: { - - same = (shortcut.mouse_button.button_index == p_event.mouse_button.button_index); - - } break; - case InputEvent::JOYPAD_MOTION: { - - same = (shortcut.joy_motion.axis == p_event.joy_motion.axis && (shortcut.joy_motion.axis_value < 0) == (p_event.joy_motion.axis_value < 0)); - - } break; - default: {}; - } - - return same; + return shortcut.is_valid() && shortcut->shortcut_match(p_event); } String ShortCut::get_as_text() const { + if (shortcut.is_valid()) + return shortcut->as_text(); + else + return "None"; +#if 0 switch (shortcut.type) { - case InputEvent::NONE: { + case Ref<InputEvent>::NONE: { return "None"; } break; - case InputEvent::KEY: { + case Ref<InputEvent>::KEY: { String str; - if (shortcut.key.mod.shift) + if (shortcut->get_shift()) str += RTR("Shift+"); - if (shortcut.key.mod.alt) + if (shortcut->get_alt()) str += RTR("Alt+"); - if (shortcut.key.mod.control) + if (shortcut->get_control()) str += RTR("Ctrl+"); - if (shortcut.key.mod.meta) + if (shortcut->get_metakey()) str += RTR("Meta+"); - str += keycode_get_string(shortcut.key.scancode).capitalize(); + str += keycode_get_string(shortcut->get_scancode()).capitalize(); return str; } break; - case InputEvent::JOYPAD_BUTTON: { + case Ref<InputEvent>::JOYPAD_BUTTON: { - String str = RTR("Device") + " " + itos(shortcut.device) + ", " + RTR("Button") + " " + itos(shortcut.joy_button.button_index); + String str = RTR("Device") + " " + itos(shortcut.device) + ", " + RTR("Button") + " " + itos(shortcut.joy_button->get_button_index()); str += "."; return str; } break; - case InputEvent::MOUSE_BUTTON: { + case Ref<InputEvent>::MOUSE_BUTTON: { String str = RTR("Device") + " " + itos(shortcut.device) + ", "; - switch (shortcut.mouse_button.button_index) { + switch (shortcut->get_button_index()) { case BUTTON_LEFT: str += RTR("Left Button."); break; case BUTTON_RIGHT: str += RTR("Right Button."); break; case BUTTON_MIDDLE: str += RTR("Middle Button."); break; case BUTTON_WHEEL_UP: str += RTR("Wheel Up."); break; case BUTTON_WHEEL_DOWN: str += RTR("Wheel Down."); break; - default: str += RTR("Button") + " " + itos(shortcut.mouse_button.button_index) + "."; + default: str += RTR("Button") + " " + itos(shortcut->get_button_index()) + "."; } return str; } break; - case InputEvent::JOYPAD_MOTION: { + case Ref<InputEvent>::JOYPAD_MOTION: { int ax = shortcut.joy_motion.axis; String str = RTR("Device") + " " + itos(shortcut.device) + ", " + RTR("Axis") + " " + itos(ax) + "."; @@ -127,11 +106,12 @@ String ShortCut::get_as_text() const { } return ""; +#endif } bool ShortCut::is_valid() const { - return shortcut.type != InputEvent::NONE; + return shortcut.is_valid(); } void ShortCut::_bind_methods() { @@ -144,7 +124,7 @@ void ShortCut::_bind_methods() { ClassDB::bind_method(D_METHOD("is_shortcut", "event"), &ShortCut::is_shortcut); ClassDB::bind_method(D_METHOD("get_as_text"), &ShortCut::get_as_text); - ADD_PROPERTY(PropertyInfo(Variant::INPUT_EVENT, "shortcut"), "set_shortcut", "get_shortcut"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), "set_shortcut", "get_shortcut"); } ShortCut::ShortCut() { diff --git a/scene/gui/input_action.h b/scene/gui/input_action.h index a0f5cf2c1..5c91d2be2 100644 --- a/scene/gui/input_action.h +++ b/scene/gui/input_action.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,21 +30,22 @@ #ifndef INPUTACTION_H #define INPUTACTION_H +#include "os/input_event.h" #include "resource.h" class ShortCut : public Resource { GDCLASS(ShortCut, Resource); - InputEvent shortcut; + Ref<InputEvent> shortcut; protected: static void _bind_methods(); public: - void set_shortcut(const InputEvent &p_shortcut); - InputEvent get_shortcut() const; - bool is_shortcut(const InputEvent &p_Event) const; + void set_shortcut(const Ref<InputEvent> &p_shortcut); + Ref<InputEvent> get_shortcut() const; + bool is_shortcut(const Ref<InputEvent> &p_event) const; bool is_valid() const; String get_as_text() const; diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 1db748a6b..b30a6000f 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -27,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "item_list.h" -#include "global_config.h" #include "os/os.h" +#include "project_settings.h" void ItemList::add_item(const String &p_item, const Ref<Texture> &p_texture, bool p_selectable) { @@ -338,7 +339,7 @@ void ItemList::set_same_column_width(bool p_enable) { update(); shape_changed = true; } -int ItemList::is_same_column_width() const { +bool ItemList::is_same_column_width() const { return same_column_width; } @@ -408,14 +409,17 @@ Size2 ItemList::Item::get_icon_size() const { return icon_region.size; } -void ItemList::_gui_input(const InputEvent &p_event) { +void ItemList::_gui_input(const Ref<InputEvent> &p_event) { - if (defer_select_single >= 0 && p_event.type == InputEvent::MOUSE_MOTION) { + Ref<InputEventMouseMotion> mm = p_event; + if (defer_select_single >= 0 && mm.is_valid()) { defer_select_single = -1; return; } - if (defer_select_single >= 0 && p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == BUTTON_LEFT && !p_event.mouse_button.pressed) { + Ref<InputEventMouseButton> mb = p_event; + + if (defer_select_single >= 0 && mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && !mb->is_pressed()) { select(defer_select_single, true); @@ -424,12 +428,10 @@ void ItemList::_gui_input(const InputEvent &p_event) { return; } - if (p_event.type == InputEvent::MOUSE_BUTTON && (p_event.mouse_button.button_index == BUTTON_LEFT || (allow_rmb_select && p_event.mouse_button.button_index == BUTTON_RIGHT)) && p_event.mouse_button.pressed) { - - const InputEventMouseButton &mb = p_event.mouse_button; + if (mb.is_valid() && (mb->get_button_index() == BUTTON_LEFT || (allow_rmb_select && mb->get_button_index() == BUTTON_RIGHT)) && mb->is_pressed()) { search_string = ""; //any mousepress cancels - Vector2 pos(mb.x, mb.y); + Vector2 pos = mb->get_position(); Ref<StyleBox> bg = get_stylebox("bg"); pos -= bg->get_offset(); pos.y += scroll_bar->get_value(); @@ -453,11 +455,11 @@ void ItemList::_gui_input(const InputEvent &p_event) { int i = closest; - if (select_mode == SELECT_MULTI && items[i].selected && mb.mod.command) { + if (select_mode == SELECT_MULTI && items[i].selected && mb->get_command()) { unselect(i); emit_signal("multi_selected", i, false); - } else if (select_mode == SELECT_MULTI && mb.mod.shift && current >= 0 && current < items.size() && current != i) { + } else if (select_mode == SELECT_MULTI && mb->get_shift() && current >= 0 && current < items.size() && current != i) { int from = current; int to = i; @@ -471,24 +473,24 @@ void ItemList::_gui_input(const InputEvent &p_event) { emit_signal("multi_selected", i, true); } - if (p_event.mouse_button.button_index == BUTTON_RIGHT) { + if (mb->get_button_index() == BUTTON_RIGHT) { - emit_signal("item_rmb_selected", i, Vector2(mb.x, mb.y)); + emit_signal("item_rmb_selected", i, pos); } } else { - if (!mb.doubleclick && !mb.mod.command && select_mode == SELECT_MULTI && items[i].selectable && !items[i].disabled && items[i].selected && p_event.mouse_button.button_index == BUTTON_LEFT) { + if (!mb->is_doubleclick() && !mb->get_command() && select_mode == SELECT_MULTI && items[i].selectable && !items[i].disabled && items[i].selected && mb->get_button_index() == BUTTON_LEFT) { defer_select_single = i; return; } - if (items[i].selected && p_event.mouse_button.button_index == BUTTON_RIGHT) { + if (items[i].selected && mb->get_button_index() == BUTTON_RIGHT) { - emit_signal("item_rmb_selected", i, Vector2(mb.x, mb.y)); + emit_signal("item_rmb_selected", i, pos); } else { bool selected = !items[i].selected; - select(i, select_mode == SELECT_SINGLE || !mb.mod.command); + select(i, select_mode == SELECT_SINGLE || !mb->get_command()); if (selected) { if (select_mode == SELECT_SINGLE) { @@ -497,10 +499,10 @@ void ItemList::_gui_input(const InputEvent &p_event) { emit_signal("multi_selected", i, true); } - if (p_event.mouse_button.button_index == BUTTON_RIGHT) { + if (mb->get_button_index() == BUTTON_RIGHT) { - emit_signal("item_rmb_selected", i, Vector2(mb.x, mb.y)); - } else if (/*select_mode==SELECT_SINGLE &&*/ mb.doubleclick) { + emit_signal("item_rmb_selected", i, pos); + } else if (/*select_mode==SELECT_SINGLE &&*/ mb->is_doubleclick()) { emit_signal("item_activated", i); } @@ -515,24 +517,24 @@ void ItemList::_gui_input(const InputEvent &p_event) { } } } - if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == BUTTON_WHEEL_UP && p_event.mouse_button.pressed) { + if (mb.is_valid() && mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed()) { - scroll_bar->set_value(scroll_bar->get_value() - scroll_bar->get_page() / 8); + scroll_bar->set_value(scroll_bar->get_value() - scroll_bar->get_page() * mb->get_factor() / 8); } - if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == BUTTON_WHEEL_DOWN && p_event.mouse_button.pressed) { + if (mb.is_valid() && mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed()) { - scroll_bar->set_value(scroll_bar->get_value() + scroll_bar->get_page() / 8); + scroll_bar->set_value(scroll_bar->get_value() + scroll_bar->get_page() * mb->get_factor() / 8); } - if (p_event.is_pressed() && items.size() > 0) { - if (p_event.is_action("ui_up")) { + if (p_event->is_pressed() && items.size() > 0) { + if (p_event->is_action("ui_up")) { if (search_string != "") { uint64_t now = OS::get_singleton()->get_ticks_msec(); uint64_t diff = now - search_time_msec; - if (diff < int(GlobalConfig::get_singleton()->get("gui/timers/incremental_search_max_interval_msec")) * 2) { + if (diff < int(ProjectSettings::get_singleton()->get("gui/timers/incremental_search_max_interval_msec")) * 2) { for (int i = current - 1; i >= 0; i--) { @@ -560,14 +562,14 @@ void ItemList::_gui_input(const InputEvent &p_event) { } accept_event(); } - } else if (p_event.is_action("ui_down")) { + } else if (p_event->is_action("ui_down")) { if (search_string != "") { uint64_t now = OS::get_singleton()->get_ticks_msec(); uint64_t diff = now - search_time_msec; - if (diff < int(GlobalConfig::get_singleton()->get("gui/timers/incremental_search_max_interval_msec")) * 2) { + if (diff < int(ProjectSettings::get_singleton()->get("gui/timers/incremental_search_max_interval_msec")) * 2) { for (int i = current + 1; i < items.size(); i++) { @@ -594,7 +596,7 @@ void ItemList::_gui_input(const InputEvent &p_event) { } accept_event(); } - } else if (p_event.is_action("ui_page_up")) { + } else if (p_event->is_action("ui_page_up")) { search_string = ""; //any mousepress cancels @@ -609,7 +611,7 @@ void ItemList::_gui_input(const InputEvent &p_event) { break; } } - } else if (p_event.is_action("ui_page_down")) { + } else if (p_event->is_action("ui_page_down")) { search_string = ""; //any mousepress cancels @@ -625,7 +627,7 @@ void ItemList::_gui_input(const InputEvent &p_event) { break; } } - } else if (p_event.is_action("ui_left")) { + } else if (p_event->is_action("ui_left")) { search_string = ""; //any mousepress cancels @@ -637,7 +639,7 @@ void ItemList::_gui_input(const InputEvent &p_event) { } accept_event(); } - } else if (p_event.is_action("ui_right")) { + } else if (p_event->is_action("ui_right")) { search_string = ""; //any mousepress cancels @@ -649,9 +651,9 @@ void ItemList::_gui_input(const InputEvent &p_event) { } accept_event(); } - } else if (p_event.is_action("ui_cancel")) { + } else if (p_event->is_action("ui_cancel")) { search_string = ""; - } else if (p_event.is_action("ui_select")) { + } else if (p_event->is_action("ui_select")) { if (select_mode == SELECT_MULTI && current >= 0 && current < items.size()) { if (items[current].selectable && !items[current].disabled && !items[current].selected) { @@ -662,15 +664,17 @@ void ItemList::_gui_input(const InputEvent &p_event) { emit_signal("multi_selected", current, false); } } - } else if (p_event.is_action("ui_accept")) { + } else if (p_event->is_action("ui_accept")) { search_string = ""; //any mousepress cance if (current >= 0 && current < items.size()) { emit_signal("item_activated", current); } - } else if (p_event.type == InputEvent::KEY) { + } else { - if (p_event.key.unicode) { + Ref<InputEventKey> k = p_event; + + if (k.is_valid() && k->get_unicode()) { uint64_t now = OS::get_singleton()->get_ticks_msec(); uint64_t diff = now - search_time_msec; @@ -681,7 +685,7 @@ void ItemList::_gui_input(const InputEvent &p_event) { search_string = ""; } - search_string += String::chr(p_event.key.unicode); + search_string += String::chr(k->get_unicode()); for (int i = 0; i < items.size(); i++) { if (items[i].text.begins_with(search_string)) { set_current(i); @@ -732,19 +736,17 @@ void ItemList::_notification(int p_what) { Ref<StyleBox> bg = get_stylebox("bg"); int mw = scroll_bar->get_minimum_size().x; - scroll_bar->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, mw + bg->get_margin(MARGIN_RIGHT)); - scroll_bar->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, bg->get_margin(MARGIN_RIGHT)); + scroll_bar->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -mw + bg->get_margin(MARGIN_RIGHT)); + scroll_bar->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, -bg->get_margin(MARGIN_RIGHT)); scroll_bar->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, bg->get_margin(MARGIN_TOP)); - scroll_bar->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, bg->get_margin(MARGIN_BOTTOM)); + scroll_bar->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, -bg->get_margin(MARGIN_BOTTOM)); Size2 size = get_size(); - float page = size.height - bg->get_minimum_size().height; int width = size.width - bg->get_minimum_size().width; if (scroll_bar->is_visible()) { width -= mw + bg->get_margin(MARGIN_RIGHT); } - scroll_bar->set_page(page); draw_style_box(bg, Rect2(Point2(), size)); @@ -853,7 +855,7 @@ void ItemList::_notification(int p_what) { items[i].rect_cache = items[i].min_rect_cache; if (same_column_width) items[i].rect_cache.size.x = max_column_width; - items[i].rect_cache.pos = ofs; + items[i].rect_cache.position = ofs; max_h = MAX(max_h, items[i].rect_cache.size.y); ofs.x += items[i].rect_cache.size.x + hseparation; //print_line("item "+itos(i)+" ofs "+rtos(items[i].rect_cache.size.x)); @@ -879,8 +881,12 @@ void ItemList::_notification(int p_what) { } if (all_fit) { + float page = size.height - bg->get_minimum_size().height; float max = MAX(page, ofs.y + max_h); + if (auto_height) + auto_height_value = ofs.y + max_h + bg->get_minimum_size().height; scroll_bar->set_max(max); + scroll_bar->set_page(page); //print_line("max: "+rtos(max)+" page "+rtos(page)); if (max <= page) { scroll_bar->set_value(0); @@ -902,10 +908,10 @@ void ItemList::_notification(int p_what) { int from = scroll_bar->get_value(); int to = from + scroll_bar->get_page(); - if (r.pos.y < from) { - scroll_bar->set_value(r.pos.y); - } else if (r.pos.y + r.size.y > to) { - scroll_bar->set_value(r.pos.y + r.size.y - (to - from)); + if (r.position.y < from) { + scroll_bar->set_value(r.position.y); + } else if (r.position.y + r.size.y > to) { + scroll_bar->set_value(r.position.y + r.size.y - (to - from)); } } @@ -924,26 +930,29 @@ void ItemList::_notification(int p_what) { continue; if (current_columns == 1) { - rcache.size.width = width - rcache.pos.x; + rcache.size.width = width - rcache.position.x; } - Rect2 r = rcache; - r.pos += base_ofs; - - // Use stylebox to dimension potential bg color, even if not selected - r.pos.x -= sbsel->get_margin(MARGIN_LEFT); - r.size.x += sbsel->get_margin(MARGIN_LEFT) + sbsel->get_margin(MARGIN_RIGHT); - r.pos.y -= sbsel->get_margin(MARGIN_TOP); - r.size.y += sbsel->get_margin(MARGIN_TOP) + sbsel->get_margin(MARGIN_BOTTOM); - if (items[i].selected) { + Rect2 r = rcache; + r.position += base_ofs; + + // Use stylebox to dimension potential bg color + r.position.x -= sbsel->get_margin(MARGIN_LEFT); + r.size.x += sbsel->get_margin(MARGIN_LEFT) + sbsel->get_margin(MARGIN_RIGHT); + r.position.y -= sbsel->get_margin(MARGIN_TOP); + r.size.y += sbsel->get_margin(MARGIN_TOP) + sbsel->get_margin(MARGIN_BOTTOM); draw_style_box(sbsel, r); } + if (items[i].custom_bg.a > 0.001) { - r.pos.x += 2; - r.size.x -= 4; - r.pos.y += 2; - r.size.y -= 4; + + Rect2 r = rcache; + r.position += base_ofs; + + // Size rect to make the align the temperature colors + r.position.y -= vseparation / 2; + r.size.y += vseparation; draw_rect(r, items[i].custom_bg); } @@ -961,7 +970,7 @@ void ItemList::_notification(int p_what) { Vector2 icon_ofs; - Point2 pos = items[i].rect_cache.pos + icon_ofs + base_ofs; + Point2 pos = items[i].rect_cache.position + icon_ofs + base_ofs; if (icon_mode == ICON_MODE_TOP) { @@ -981,7 +990,7 @@ void ItemList::_notification(int p_what) { if (fixed_icon_size.x > 0 && fixed_icon_size.y > 0) { Rect2 adj = _adjust_to_max_size(items[i].get_icon_size() * icon_scale, icon_size); - draw_rect.pos += adj.pos; + draw_rect.position += adj.position; draw_rect.size = adj.size; } @@ -997,7 +1006,7 @@ void ItemList::_notification(int p_what) { if (items[i].tag_icon.is_valid()) { - draw_texture(items[i].tag_icon, items[i].rect_cache.pos + base_ofs); + draw_texture(items[i].tag_icon, items[i].rect_cache.position + base_ofs); } if (items[i].text != "") { @@ -1042,7 +1051,7 @@ void ItemList::_notification(int p_what) { text_ofs.y += font->get_ascent(); text_ofs = text_ofs.floor(); text_ofs += base_ofs; - text_ofs += items[i].rect_cache.pos; + text_ofs += items[i].rect_cache.position; for (int j = 0; j < ss; j++) { @@ -1070,7 +1079,7 @@ void ItemList::_notification(int p_what) { text_ofs.y += font->get_ascent(); text_ofs = text_ofs.floor(); text_ofs += base_ofs; - text_ofs += items[i].rect_cache.pos; + text_ofs += items[i].rect_cache.position; draw_string(font, text_ofs, items[i].text, modulate, max_len + 1); } @@ -1079,7 +1088,7 @@ void ItemList::_notification(int p_what) { if (select_mode == SELECT_MULTI && i == current) { Rect2 r = rcache; - r.pos += base_ofs; + r.position += base_ofs; draw_style_box(cursor, r); } } @@ -1137,7 +1146,7 @@ bool ItemList::is_pos_at_end_of_items(const Point2 &p_pos) const { pos.y += scroll_bar->get_value(); Rect2 endrect = items[items.size() - 1].rect_cache; - return (pos.y > endrect.pos.y + endrect.size.y); + return (pos.y > endrect.position.y + endrect.size.y); } String ItemList::get_tooltip(const Point2 &p_pos) const { @@ -1216,16 +1225,66 @@ Vector<int> ItemList::get_selected_items() { return selected; } +void ItemList::_set_items(const Array &p_items) { + + ERR_FAIL_COND(p_items.size() % 3); + clear(); + + for (int i = 0; i < p_items.size(); i += 3) { + + String text = p_items[i + 0]; + Ref<Texture> icon = p_items[i + 1]; + bool disabled = p_items[i + 2]; + + int idx = get_item_count(); + add_item(text, icon); + set_item_disabled(idx, disabled); + } +} + +Array ItemList::_get_items() const { + + Array items; + for (int i = 0; i < get_item_count(); i++) { + + items.push_back(get_item_text(i)); + items.push_back(get_item_icon(i)); + items.push_back(is_item_disabled(i)); + } + + return items; +} + +Size2 ItemList::get_minimum_size() const { + + if (auto_height) { + return Size2(0, auto_height_value); + } + return Size2(); +} + +void ItemList::set_auto_height(bool p_enable) { + + auto_height = p_enable; + shape_changed = true; + update(); +} + +bool ItemList::has_auto_height() const { + + return auto_height; +} + void ItemList::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_item", "text", "icon:Texture", "selectable"), &ItemList::add_item, DEFVAL(Variant()), DEFVAL(true)); - ClassDB::bind_method(D_METHOD("add_icon_item", "icon:Texture", "selectable"), &ItemList::add_icon_item, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("add_item", "text", "icon", "selectable"), &ItemList::add_item, DEFVAL(Variant()), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("add_icon_item", "icon", "selectable"), &ItemList::add_icon_item, DEFVAL(true)); ClassDB::bind_method(D_METHOD("set_item_text", "idx", "text"), &ItemList::set_item_text); ClassDB::bind_method(D_METHOD("get_item_text", "idx"), &ItemList::get_item_text); - ClassDB::bind_method(D_METHOD("set_item_icon", "idx", "icon:Texture"), &ItemList::set_item_icon); - ClassDB::bind_method(D_METHOD("get_item_icon:Texture", "idx"), &ItemList::get_item_icon); + ClassDB::bind_method(D_METHOD("set_item_icon", "idx", "icon"), &ItemList::set_item_icon); + ClassDB::bind_method(D_METHOD("get_item_icon", "idx"), &ItemList::get_item_icon); ClassDB::bind_method(D_METHOD("set_item_icon_region", "idx", "rect"), &ItemList::set_item_icon_region); ClassDB::bind_method(D_METHOD("get_item_icon_region", "idx"), &ItemList::get_item_icon_region); @@ -1286,6 +1345,9 @@ void ItemList::_bind_methods() { ClassDB::bind_method(D_METHOD("set_allow_rmb_select", "allow"), &ItemList::set_allow_rmb_select); ClassDB::bind_method(D_METHOD("get_allow_rmb_select"), &ItemList::get_allow_rmb_select); + ClassDB::bind_method(D_METHOD("set_auto_height", "enable"), &ItemList::set_auto_height); + ClassDB::bind_method(D_METHOD("has_auto_height"), &ItemList::has_auto_height); + ClassDB::bind_method(D_METHOD("get_item_at_pos", "pos", "exact"), &ItemList::get_item_at_pos, DEFVAL(false)); ClassDB::bind_method(D_METHOD("ensure_current_is_visible"), &ItemList::ensure_current_is_visible); @@ -1295,6 +1357,23 @@ void ItemList::_bind_methods() { ClassDB::bind_method(D_METHOD("_scroll_changed"), &ItemList::_scroll_changed); ClassDB::bind_method(D_METHOD("_gui_input"), &ItemList::_gui_input); + ClassDB::bind_method(D_METHOD("_set_items"), &ItemList::_set_items); + ClassDB::bind_method(D_METHOD("_get_items"), &ItemList::_get_items); + + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_items", "_get_items"); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "select_mode", PROPERTY_HINT_ENUM, "Single,Multi"), "set_select_mode", "get_select_mode"); + ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "allow_rmb_select"), "set_allow_rmb_select", "get_allow_rmb_select"); + ADD_PROPERTYNO(PropertyInfo(Variant::INT, "max_text_lines"), "set_max_text_lines", "get_max_text_lines"); + ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "auto_height"), "set_auto_height", "has_auto_height"); + ADD_GROUP("Columns", ""); + ADD_PROPERTYNO(PropertyInfo(Variant::INT, "max_columns"), "set_max_columns", "get_max_columns"); + ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "same_column_width"), "set_same_column_width", "is_same_column_width"); + ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "fixed_column_width"), "set_fixed_column_width", "get_fixed_column_width"); + ADD_GROUP("Icon", ""); + ADD_PROPERTY(PropertyInfo(Variant::INT, "icon_mode", PROPERTY_HINT_ENUM, "Top,Left"), "set_icon_mode", "get_icon_mode"); + ADD_PROPERTYNO(PropertyInfo(Variant::REAL, "icon_scale"), "set_icon_scale", "get_icon_scale"); + BIND_CONSTANT(ICON_MODE_TOP); BIND_CONSTANT(ICON_MODE_LEFT); BIND_CONSTANT(SELECT_SINGLE); @@ -1319,6 +1398,8 @@ ItemList::ItemList() { same_column_width = false; max_text_lines = 1; max_columns = 1; + auto_height = false; + auto_height_value = 0.0f; scroll_bar = memnew(VScrollBar); add_child(scroll_bar); diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h index 5de58cfde..a80727f56 100644 --- a/scene/gui/item_list.h +++ b/scene/gui/item_list.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -77,6 +78,9 @@ private: bool ensure_selected_visible; bool same_column_width; + bool auto_height; + float auto_height_value; + Vector<Item> items; Vector<int> separators; @@ -102,8 +106,11 @@ private: real_t icon_scale; + Array _get_items() const; + void _set_items(const Array &p_items); + void _scroll_changed(double); - void _gui_input(const InputEvent &p_event); + void _gui_input(const Ref<InputEvent> &p_event); protected: void _notification(int p_what); @@ -162,9 +169,9 @@ public: int get_fixed_column_width() const; void set_same_column_width(bool p_enable); - int is_same_column_width() const; + bool is_same_column_width() const; - void set_max_text_lines(int p_amount); + void set_max_text_lines(int p_lines); int get_max_text_lines() const; void set_max_columns(int p_amount); @@ -194,6 +201,11 @@ public: void set_icon_scale(real_t p_scale); real_t get_icon_scale() const; + void set_auto_height(bool p_enable); + bool has_auto_height() const; + + Size2 get_minimum_size() const; + VScrollBar *get_v_scroll() { return scroll_bar; } ItemList(); diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index 0dec69d9b..874156821 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -27,15 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "label.h" -#include "global_config.h" #include "print_string.h" +#include "project_settings.h" #include "translation.h" void Label::set_autowrap(bool p_autowrap) { autowrap = p_autowrap; word_cache_dirty = true; - minimum_size_changed(); update(); } bool Label::has_autowrap() const { @@ -47,7 +47,6 @@ void Label::set_uppercase(bool p_uppercase) { uppercase = p_uppercase; word_cache_dirty = true; - minimum_size_changed(); update(); } bool Label::is_uppercase() const { @@ -64,8 +63,12 @@ void Label::_notification(int p_what) { if (p_what == NOTIFICATION_TRANSLATION_CHANGED) { - xl_text = XL_MESSAGE(text); - minimum_size_changed(); + String new_text = XL_MESSAGE(text); + if (new_text == xl_text) + return; //nothing new + xl_text = new_text; + + regenerate_word_cache(); update(); } @@ -286,7 +289,7 @@ void Label::_notification(int p_what) { Size2 Label::get_minimum_size() const { if (autowrap) - return Size2(1, 1); + return Size2(1, clip ? 1 : minsize.height); else { // don't want to mutable everything @@ -481,15 +484,16 @@ void Label::regenerate_word_cache() { } } - if (!autowrap) { + if (!autowrap) minsize.width = width; - if (max_lines_visible > 0 && line_count > max_lines_visible) { - minsize.height = (font->get_height() * max_lines_visible) + (line_spacing * (max_lines_visible - 1)); - } else { - minsize.height = (font->get_height() * line_count) + (line_spacing * (line_count - 1)); - } + + if (max_lines_visible > 0 && line_count > max_lines_visible) { + minsize.height = (font->get_height() * max_lines_visible) + (line_spacing * (max_lines_visible - 1)); + } else { + minsize.height = (font->get_height() * line_count) + (line_spacing * (line_count - 1)); } + minimum_size_changed(); word_cache_dirty = false; } @@ -527,9 +531,6 @@ void Label::set_text(const String &p_string) { if (percent_visible < 1) visible_chars = get_total_character_count() * percent_visible; update(); - if (!autowrap) { - minimum_size_changed(); - } } void Label::set_clip_text(bool p_clip) { @@ -680,6 +681,7 @@ Label::Label(const String &p_text) { max_lines_visible = -1; set_text(p_text); uppercase = false; + set_v_size_flags(SIZE_SHRINK_CENTER); } Label::~Label() { diff --git a/scene/gui/label.h b/scene/gui/label.h index 769e4b225..dce68f442 100644 --- a/scene/gui/label.h +++ b/scene/gui/label.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 20725194c..c1784fb7b 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -41,445 +42,442 @@ static bool _is_text_char(CharType c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_'; } -void LineEdit::_gui_input(InputEvent p_event) { +void LineEdit::_gui_input(Ref<InputEvent> p_event) { - switch (p_event.type) { + Ref<InputEventMouseButton> b = p_event; - case InputEvent::MOUSE_BUTTON: { + if (b.is_valid()) { - const InputEventMouseButton &b = p_event.mouse_button; - - if (b.pressed && b.button_index == BUTTON_RIGHT) { - menu->set_pos(get_global_transform().xform(get_local_mouse_pos())); - menu->set_size(Vector2(1, 1)); - menu->popup(); - grab_focus(); - return; - } + if (b->is_pressed() && b->get_button_index() == BUTTON_RIGHT) { + menu->set_position(get_global_transform().xform(get_local_mouse_pos())); + menu->set_size(Vector2(1, 1)); + menu->popup(); + grab_focus(); + return; + } - if (b.button_index != BUTTON_LEFT) - break; + if (b->get_button_index() != BUTTON_LEFT) + return; - _reset_caret_blink_timer(); - if (b.pressed) { + _reset_caret_blink_timer(); + if (b->is_pressed()) { - shift_selection_check_pre(b.mod.shift); + shift_selection_check_pre(b->get_shift()); - set_cursor_at_pixel_pos(b.x); + set_cursor_at_pixel_pos(b->get_position().x); - if (b.mod.shift) { + if (b->get_shift()) { - selection_fill_at_cursor(); - selection.creating = true; + selection_fill_at_cursor(); + selection.creating = true; - } else { + } else { - if (b.doubleclick) { + if (b->is_doubleclick()) { - selection.enabled = true; - selection.begin = 0; - selection.end = text.length(); - selection.doubleclick = true; - } + selection.enabled = true; + selection.begin = 0; + selection.end = text.length(); + selection.doubleclick = true; + } - selection.drag_attempt = false; + selection.drag_attempt = false; - if ((cursor_pos < selection.begin) || (cursor_pos > selection.end) || !selection.enabled) { + if ((cursor_pos < selection.begin) || (cursor_pos > selection.end) || !selection.enabled) { - selection_clear(); - selection.cursor_start = cursor_pos; - selection.creating = true; - } else if (selection.enabled) { + selection_clear(); + selection.cursor_start = cursor_pos; + selection.creating = true; + } else if (selection.enabled) { - selection.drag_attempt = true; - } + selection.drag_attempt = true; } + } - update(); - - } else { + update(); - if ((!selection.creating) && (!selection.doubleclick)) { - selection_clear(); - } - selection.creating = false; - selection.doubleclick = false; + } else { - if (OS::get_singleton()->has_virtual_keyboard()) - OS::get_singleton()->show_virtual_keyboard(text, get_global_rect()); + if ((!selection.creating) && (!selection.doubleclick)) { + selection_clear(); } + selection.creating = false; + selection.doubleclick = false; - update(); - } break; - case InputEvent::MOUSE_MOTION: { + if (OS::get_singleton()->has_virtual_keyboard()) + OS::get_singleton()->show_virtual_keyboard(text, get_global_rect()); + } - const InputEventMouseMotion &m = p_event.mouse_motion; + update(); + } - if (m.button_mask & BUTTON_LEFT) { + Ref<InputEventMouseMotion> m = p_event; - if (selection.creating) { - set_cursor_at_pixel_pos(m.x); - selection_fill_at_cursor(); - } - } + if (m.is_valid()) { - } break; - case InputEvent::KEY: { + if (m->get_button_mask() & BUTTON_LEFT) { - const InputEventKey &k = p_event.key; + if (selection.creating) { + set_cursor_at_pixel_pos(m->get_position().x); + selection_fill_at_cursor(); + } + } + } - if (!k.pressed) - return; - unsigned int code = k.scancode; + Ref<InputEventKey> k = p_event; - if (k.mod.command) { + if (k.is_valid()) { - bool handled = true; + if (!k->is_pressed()) + return; + unsigned int code = k->get_scancode(); - switch (code) { + if (k->get_command()) { - case (KEY_X): { // CUT + bool handled = true; - if (editable) { - cut_text(); - } + switch (code) { - } break; + case (KEY_X): { // CUT - case (KEY_C): { // COPY + if (editable) { + cut_text(); + } - copy_text(); + } break; - } break; + case (KEY_C): { // COPY - case (KEY_V): { // PASTE + copy_text(); - if (editable) { + } break; - paste_text(); - } + case (KEY_V): { // PASTE - } break; + if (editable) { - case (KEY_Z): { // Simple One level undo + paste_text(); + } - if (editable) { + } break; - undo(); - } + case (KEY_Z): { // Simple One level undo - } break; + if (editable) { - case (KEY_U): { // Delete from start to cursor + undo(); + } - if (editable) { + } break; - selection_clear(); - undo_text = text; - text = text.substr(cursor_pos, text.length() - cursor_pos); + case (KEY_U): { // Delete from start to cursor - Ref<Font> font = get_font("font"); + if (editable) { - cached_width = 0; - if (font != NULL) { - for (int i = 0; i < text.length(); i++) - cached_width += font->get_char_size(text[i]).width; - } + selection_clear(); + undo_text = text; + text = text.substr(cursor_pos, text.length() - cursor_pos); - set_cursor_pos(0); - _text_changed(); + Ref<Font> font = get_font("font"); + + cached_width = 0; + if (font != NULL) { + for (int i = 0; i < text.length(); i++) + cached_width += font->get_char_size(text[i]).width; } - } break; + set_cursor_pos(0); + _text_changed(); + } - case (KEY_Y): { // PASTE (Yank for unix users) + } break; - if (editable) { + case (KEY_Y): { // PASTE (Yank for unix users) - paste_text(); - } + if (editable) { - } break; - case (KEY_K): { // Delete from cursor_pos to end + paste_text(); + } - if (editable) { + } break; + case (KEY_K): { // Delete from cursor_pos to end - selection_clear(); - undo_text = text; - text = text.substr(0, cursor_pos); - _text_changed(); - } + if (editable) { - } break; - case (KEY_A): { //Select All - select(); - } break; - default: { handled = false; } - } + selection_clear(); + undo_text = text; + text = text.substr(0, cursor_pos); + _text_changed(); + } - if (handled) { - accept_event(); - return; - } + } break; + case (KEY_A): { //Select All + select(); + } break; + default: { handled = false; } + } + + if (handled) { + accept_event(); + return; } + } - _reset_caret_blink_timer(); - if (!k.mod.meta) { + _reset_caret_blink_timer(); + if (!k->get_metakey()) { - bool handled = true; - switch (code) { + bool handled = true; + switch (code) { - case KEY_ENTER: - case KEY_RETURN: { + case KEY_KP_ENTER: + case KEY_ENTER: { - emit_signal("text_entered", text); - if (OS::get_singleton()->has_virtual_keyboard()) - OS::get_singleton()->hide_virtual_keyboard(); + emit_signal("text_entered", text); + if (OS::get_singleton()->has_virtual_keyboard()) + OS::get_singleton()->hide_virtual_keyboard(); - return; - } break; + return; + } break; - case KEY_BACKSPACE: { + case KEY_BACKSPACE: { - if (!editable) - break; + if (!editable) + break; - if (selection.enabled) { - undo_text = text; - selection_delete(); - break; - } + if (selection.enabled) { + undo_text = text; + selection_delete(); + break; + } #ifdef APPLE_STYLE_KEYS - if (k.mod.alt) { + if (k->get_alt()) { #else - if (k.mod.alt) { - handled = false; - break; - } else if (k.mod.command) { + if (k->get_alt()) { + handled = false; + break; + } else if (k->get_command()) { #endif - int cc = cursor_pos; - bool prev_char = false; + int cc = cursor_pos; + bool prev_char = false; - while (cc > 0) { - bool ischar = _is_text_char(text[cc - 1]); + while (cc > 0) { + bool ischar = _is_text_char(text[cc - 1]); - if (prev_char && !ischar) - break; + if (prev_char && !ischar) + break; - prev_char = ischar; - cc--; - } + prev_char = ischar; + cc--; + } - delete_text(cc, cursor_pos); + delete_text(cc, cursor_pos); - set_cursor_pos(cc); + set_cursor_pos(cc); - } else { - undo_text = text; - delete_char(); - } + } else { + undo_text = text; + delete_char(); + } - } break; - case KEY_KP_4: { - if (k.unicode != 0) { - handled = false; - break; - } - // numlock disabled. fallthrough to key_left + } break; + case KEY_KP_4: { + if (k->get_unicode() != 0) { + handled = false; + break; } - case KEY_LEFT: { + // numlock disabled. fallthrough to key_left + } + case KEY_LEFT: { #ifndef APPLE_STYLE_KEYS - if (!k.mod.alt) + if (!k->get_alt()) #endif - shift_selection_check_pre(k.mod.shift); + shift_selection_check_pre(k->get_shift()); #ifdef APPLE_STYLE_KEYS - if (k.mod.command) { - set_cursor_pos(0); - } else if (k.mod.alt) { + if (k->get_command()) { + set_cursor_pos(0); + } else if (k->get_alt()) { #else - if (k.mod.alt) { - handled = false; - break; - } else if (k.mod.command) { + if (k->get_alt()) { + handled = false; + break; + } else if (k->get_command()) { #endif - bool prev_char = false; - int cc = cursor_pos; + bool prev_char = false; + int cc = cursor_pos; - while (cc > 0) { - bool ischar = _is_text_char(text[cc - 1]); + while (cc > 0) { + bool ischar = _is_text_char(text[cc - 1]); - if (prev_char && !ischar) - break; + if (prev_char && !ischar) + break; - prev_char = ischar; - cc--; - } + prev_char = ischar; + cc--; + } - set_cursor_pos(cc); + set_cursor_pos(cc); - } else { - set_cursor_pos(get_cursor_pos() - 1); - } + } else { + set_cursor_pos(get_cursor_pos() - 1); + } - shift_selection_check_post(k.mod.shift); + shift_selection_check_post(k->get_shift()); - } break; - case KEY_KP_6: { - if (k.unicode != 0) { - handled = false; - break; - } - // numlock disabled. fallthrough to key_right + } break; + case KEY_KP_6: { + if (k->get_unicode() != 0) { + handled = false; + break; } - case KEY_RIGHT: { + // numlock disabled. fallthrough to key_right + } + case KEY_RIGHT: { - shift_selection_check_pre(k.mod.shift); + shift_selection_check_pre(k->get_shift()); #ifdef APPLE_STYLE_KEYS - if (k.mod.command) { - set_cursor_pos(text.length()); - } else if (k.mod.alt) { + if (k->get_command()) { + set_cursor_pos(text.length()); + } else if (k->get_alt()) { #else - if (k.mod.alt) { - handled = false; - break; - } else if (k.mod.command) { + if (k->get_alt()) { + handled = false; + break; + } else if (k->get_command()) { #endif - bool prev_char = false; - int cc = cursor_pos; + bool prev_char = false; + int cc = cursor_pos; - while (cc < text.length()) { - bool ischar = _is_text_char(text[cc]); + while (cc < text.length()) { + bool ischar = _is_text_char(text[cc]); - if (prev_char && !ischar) - break; + if (prev_char && !ischar) + break; - prev_char = ischar; - cc++; - } + prev_char = ischar; + cc++; + } - set_cursor_pos(cc); + set_cursor_pos(cc); - } else { - set_cursor_pos(get_cursor_pos() + 1); - } + } else { + set_cursor_pos(get_cursor_pos() + 1); + } - shift_selection_check_post(k.mod.shift); + shift_selection_check_post(k->get_shift()); - } break; - case KEY_DELETE: { + } break; + case KEY_DELETE: { - if (!editable) - break; + if (!editable) + break; - if (k.mod.shift && !k.mod.command && !k.mod.alt) { - cut_text(); - break; - } + if (k->get_shift() && !k->get_command() && !k->get_alt()) { + cut_text(); + break; + } - if (selection.enabled) { - undo_text = text; - selection_delete(); - break; - } + if (selection.enabled) { + undo_text = text; + selection_delete(); + break; + } - int text_len = text.length(); + int text_len = text.length(); - if (cursor_pos == text_len) - break; // nothing to do + if (cursor_pos == text_len) + break; // nothing to do #ifdef APPLE_STYLE_KEYS - if (k.mod.alt) { + if (k->get_alt()) { #else - if (k.mod.alt) { - handled = false; - break; - } else if (k.mod.command) { + if (k->get_alt()) { + handled = false; + break; + } else if (k->get_command()) { #endif - int cc = cursor_pos; - - bool prev_char = false; + int cc = cursor_pos; - while (cc < text.length()) { + bool prev_char = false; - bool ischar = _is_text_char(text[cc]); + while (cc < text.length()) { - if (prev_char && !ischar) - break; - prev_char = ischar; - cc++; - } + bool ischar = _is_text_char(text[cc]); - delete_text(cursor_pos, cc); - - } else { - undo_text = text; - set_cursor_pos(cursor_pos + 1); - delete_char(); + if (prev_char && !ischar) + break; + prev_char = ischar; + cc++; } - } break; - case KEY_KP_7: { - if (k.unicode != 0) { - handled = false; - break; - } - // numlock disabled. fallthrough to key_home - } - case KEY_HOME: { + delete_text(cursor_pos, cc); - shift_selection_check_pre(k.mod.shift); - set_cursor_pos(0); - shift_selection_check_post(k.mod.shift); - } break; - case KEY_KP_1: { - if (k.unicode != 0) { - handled = false; - break; - } - // numlock disabled. fallthrough to key_end + } else { + undo_text = text; + set_cursor_pos(cursor_pos + 1); + delete_char(); } - case KEY_END: { - shift_selection_check_pre(k.mod.shift); - set_cursor_pos(text.length()); - shift_selection_check_post(k.mod.shift); - } break; - - default: { + } break; + case KEY_KP_7: { + if (k->get_unicode() != 0) { + handled = false; + break; + } + // numlock disabled. fallthrough to key_home + } + case KEY_HOME: { + shift_selection_check_pre(k->get_shift()); + set_cursor_pos(0); + shift_selection_check_post(k->get_shift()); + } break; + case KEY_KP_1: { + if (k->get_unicode() != 0) { handled = false; - } break; + break; + } + // numlock disabled. fallthrough to key_end } + case KEY_END: { + + shift_selection_check_pre(k->get_shift()); + set_cursor_pos(text.length()); + shift_selection_check_post(k->get_shift()); + } break; - if (handled) { - accept_event(); - } else if (!k.mod.alt && !k.mod.command) { - if (k.unicode >= 32 && k.scancode != KEY_DELETE) { + default: { - if (editable) { - selection_delete(); - CharType ucodestr[2] = { (CharType)k.unicode, 0 }; - append_at_cursor(ucodestr); - _text_changed(); - accept_event(); - } + handled = false; + } break; + } - } else { - return; + if (handled) { + accept_event(); + } else if (!k->get_alt() && !k->get_command()) { + if (k->get_unicode() >= 32 && k->get_scancode() != KEY_DELETE) { + + if (editable) { + selection_delete(); + CharType ucodestr[2] = { (CharType)k->get_unicode(), 0 }; + append_at_cursor(ucodestr); + _text_changed(); + accept_event(); } - } - update(); + } else { + return; + } } - return; + update(); + } - } break; + return; } } @@ -576,8 +574,12 @@ void LineEdit::_notification(int p_what) { RID ci = get_canvas_item(); Ref<StyleBox> style = get_stylebox("normal"); - if (!is_editable()) + float disabled_alpha = 1.0; // used to set the disabled input text color + if (!is_editable()) { style = get_stylebox("read_only"); + disabled_alpha = .5; + draw_caret = false; + } Ref<Font> font = get_font("font"); @@ -624,6 +626,13 @@ void LineEdit::_notification(int p_what) { // draw placeholder color if (text.empty()) font_color.a *= placeholder_alpha; + font_color.a *= disabled_alpha; + + if (has_icon("right_icon")) { + Ref<Texture> r_icon = Control::get_icon("right_icon"); + ofs_max -= r_icon->get_width(); + r_icon->draw(ci, Point2(width - r_icon->get_width() - x_ofs, y_ofs), Color(1, 1, 1, disabled_alpha * .9)); + } int caret_height = font->get_height() > y_area ? y_area : font->get_height(); while (true) { @@ -632,8 +641,37 @@ void LineEdit::_notification(int p_what) { if (char_ofs >= t.length()) break; - CharType cchar = pass ? '*' : t[char_ofs]; - CharType next = pass ? '*' : t[char_ofs + 1]; + if (char_ofs == cursor_pos) { + if (ime_text.length() > 0) { + int ofs = 0; + while (true) { + if (ofs >= ime_text.length()) + break; + + CharType cchar = (pass && !text.empty()) ? '*' : ime_text[ofs]; + CharType next = (pass && !text.empty()) ? '*' : ime_text[ofs + 1]; + int im_char_width = font->get_char_size(cchar, next).width; + + if ((x_ofs + im_char_width) > ofs_max) + break; + + bool selected = ofs >= ime_selection.x && ofs < ime_selection.x + ime_selection.y; + if (selected) { + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs + caret_height), Size2(im_char_width, 3)), font_color); + } else { + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs + caret_height), Size2(im_char_width, 1)), font_color); + } + + font->draw_char(ci, Point2(x_ofs, y_ofs + font_ascent), cchar, next, font_color); + + x_ofs += im_char_width; + ofs++; + } + } + } + + CharType cchar = (pass && !text.empty()) ? '*' : t[char_ofs]; + CharType next = (pass && !text.empty()) ? '*' : t[char_ofs + 1]; int char_width = font->get_char_size(cchar, next).width; // end of widget, break! @@ -648,19 +686,54 @@ void LineEdit::_notification(int p_what) { font->draw_char(ci, Point2(x_ofs, y_ofs + font_ascent), cchar, next, selected ? font_color_selected : font_color); if (char_ofs == cursor_pos && draw_caret) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2( - Point2(x_ofs, y_ofs), Size2(1, caret_height)), - cursor_color); + if (ime_text.length() == 0) { + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs), Size2(1, caret_height)), cursor_color); + } } x_ofs += char_width; char_ofs++; } + if (char_ofs == cursor_pos) { + if (ime_text.length() > 0) { + int ofs = 0; + while (true) { + if (ofs >= ime_text.length()) + break; + + CharType cchar = (pass && !text.empty()) ? '*' : ime_text[ofs]; + CharType next = (pass && !text.empty()) ? '*' : ime_text[ofs + 1]; + int im_char_width = font->get_char_size(cchar, next).width; + + if ((x_ofs + im_char_width) > ofs_max) + break; + + bool selected = ofs >= ime_selection.x && ofs < ime_selection.x + ime_selection.y; + if (selected) { + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs + caret_height), Size2(im_char_width, 3)), font_color); + } else { + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs + caret_height), Size2(im_char_width, 1)), font_color); + } + + font->draw_char(ci, Point2(x_ofs, y_ofs + font_ascent), cchar, next, font_color); + + x_ofs += im_char_width; + ofs++; + } + } + } + if (char_ofs == cursor_pos && draw_caret) { //may be at the end - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2( - Point2(x_ofs, y_ofs), Size2(1, caret_height)), - cursor_color); + if (ime_text.length() == 0) { + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs), Size2(1, caret_height)), cursor_color); + } + } + + if (has_focus()) { + + OS::get_singleton()->set_ime_position(get_global_position() + Point2(x_ofs, y_ofs + caret_height)); + OS::get_singleton()->set_ime_intermediate_text_callback(_ime_text_callback, this); } } break; case NOTIFICATION_FOCUS_ENTER: { @@ -669,12 +742,21 @@ void LineEdit::_notification(int p_what) { draw_caret = true; } + Point2 cursor_pos = Point2(get_cursor_pos(), 1) * get_minimum_size().height; + OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos); + OS::get_singleton()->set_ime_intermediate_text_callback(_ime_text_callback, this); + if (OS::get_singleton()->has_virtual_keyboard()) OS::get_singleton()->show_virtual_keyboard(text, get_global_rect()); } break; case NOTIFICATION_FOCUS_EXIT: { + OS::get_singleton()->set_ime_position(Point2()); + OS::get_singleton()->set_ime_intermediate_text_callback(NULL, NULL); + ime_text = ""; + ime_selection = Point2(); + if (OS::get_singleton()->has_virtual_keyboard()) OS::get_singleton()->hide_virtual_keyboard(); @@ -1183,7 +1265,9 @@ void LineEdit::menu_option(int p_option) { select_all(); } break; case MENU_UNDO: { - undo(); + if (editable) { + undo(); + } } break; } } @@ -1210,6 +1294,13 @@ bool LineEdit::get_expand_to_text_length() const { return expand_to_text_length; } +void LineEdit::_ime_text_callback(void *p_self, String p_text, Point2 p_selection) { + LineEdit *self = (LineEdit *)p_self; + self->ime_text = p_text; + self->ime_selection = p_selection; + self->update(); +} + void LineEdit::_text_changed() { if (expand_to_text_length) @@ -1256,7 +1347,7 @@ void LineEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("is_secret"), &LineEdit::is_secret); ClassDB::bind_method(D_METHOD("select", "from", "to"), &LineEdit::select, DEFVAL(0), DEFVAL(-1)); ClassDB::bind_method(D_METHOD("menu_option", "option"), &LineEdit::menu_option); - ClassDB::bind_method(D_METHOD("get_menu:PopupMenu"), &LineEdit::get_menu); + ClassDB::bind_method(D_METHOD("get_menu"), &LineEdit::get_menu); ADD_SIGNAL(MethodInfo("text_changed", PropertyInfo(Variant::STRING, "text"))); ADD_SIGNAL(MethodInfo("text_entered", PropertyInfo(Variant::STRING, "text"))); diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 074654711..fb0eaa944 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -69,6 +70,8 @@ private: String text; String placeholder; float placeholder_alpha; + String ime_text; + Point2 ime_selection; PopupMenu *menu; @@ -91,6 +94,7 @@ private: Timer *caret_blink_timer; + static void _ime_text_callback(void *p_self, String p_text, Point2 p_selection); void _text_changed(); bool expand_to_text_length; @@ -118,7 +122,7 @@ private: void _editor_settings_changed(); #endif - void _gui_input(InputEvent p_event); + void _gui_input(Ref<InputEvent> p_event); void _notification(int p_what); protected: @@ -173,7 +177,7 @@ public: virtual Size2 get_minimum_size() const; - void set_expand_to_text_length(bool p_len); + void set_expand_to_text_length(bool p_enabled); bool get_expand_to_text_length() const; virtual bool is_text_field() const; diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp index 17e549c90..9cb67b75e 100644 --- a/scene/gui/link_button.cpp +++ b/scene/gui/link_button.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/link_button.h b/scene/gui/link_button.h index 97c2bfc3c..98a3dc66f 100644 --- a/scene/gui/link_button.h +++ b/scene/gui/link_button.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/margin_container.cpp b/scene/gui/margin_container.cpp index b7824e903..2bc9db529 100644 --- a/scene/gui/margin_container.cpp +++ b/scene/gui/margin_container.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/margin_container.h b/scene/gui/margin_container.h index 9f0829a34..1cdb3a36c 100644 --- a/scene/gui/margin_container.h +++ b/scene/gui/margin_container.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index f2e2c9b25..93284f2b6 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,9 +31,9 @@ #include "os/keyboard.h" #include "scene/main/viewport.h" -void MenuButton::_unhandled_key_input(InputEvent p_event) { +void MenuButton::_unhandled_key_input(Ref<InputEvent> p_event) { - if (p_event.is_pressed() && !p_event.is_echo() && (p_event.type == InputEvent::KEY || p_event.type == InputEvent::ACTION || p_event.type == InputEvent::JOYPAD_BUTTON)) { + if (p_event->is_pressed() && !p_event->is_echo() && (p_event->cast_to<InputEventKey>() || p_event->cast_to<InputEventJoypadButton>() || p_event->cast_to<InputEventAction>())) { if (!get_parent() || !is_visible_in_tree() || is_disabled()) return; @@ -49,19 +50,18 @@ void MenuButton::pressed() { emit_signal("about_to_show"); Size2 size = get_size(); - Point2 gp = get_global_pos(); - popup->set_global_pos(gp + Size2(0, size.height)); + Point2 gp = get_global_position(); + popup->set_global_position(gp + Size2(0, size.height)); popup->set_size(Size2(size.width, 0)); - popup->set_parent_rect(Rect2(Point2(gp - popup->get_global_pos()), get_size())); + popup->set_parent_rect(Rect2(Point2(gp - popup->get_global_position()), get_size())); popup->popup(); - popup->call_deferred("grab_click_focus"); popup->set_invalidate_click_until_motion(); } -void MenuButton::_gui_input(InputEvent p_event) { +void MenuButton::_gui_input(Ref<InputEvent> p_event) { - /*if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==BUTTON_LEFT) { - clicked=p_event.mouse_button.pressed; + /*if (p_event.type==InputEvent::MOUSE_BUTTON && p_event->get_button_index()==BUTTON_LEFT) { + clicked=p_event->is_pressed(); } if (clicked && p_event.type==InputEvent::MOUSE_MOTION && popup->is_visible_in_tree()) { @@ -94,7 +94,7 @@ void MenuButton::_set_items(const Array &p_items) { void MenuButton::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_popup:PopupMenu"), &MenuButton::get_popup); + ClassDB::bind_method(D_METHOD("get_popup"), &MenuButton::get_popup); ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &MenuButton::_unhandled_key_input); ClassDB::bind_method(D_METHOD("_set_items"), &MenuButton::_set_items); ClassDB::bind_method(D_METHOD("_get_items"), &MenuButton::_get_items); @@ -111,6 +111,7 @@ MenuButton::MenuButton() { popup->hide(); add_child(popup); popup->set_as_toplevel(true); + connect("button_up", popup, "call_deferred", make_binds("grab_click_focus")); set_process_unhandled_key_input(true); set_action_mode(ACTION_MODE_BUTTON_PRESS); } diff --git a/scene/gui/menu_button.h b/scene/gui/menu_button.h index 4acb62cf3..6bb23452d 100644 --- a/scene/gui/menu_button.h +++ b/scene/gui/menu_button.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -42,11 +43,11 @@ class MenuButton : public Button { PopupMenu *popup; virtual void pressed(); - void _unhandled_key_input(InputEvent p_event); + void _unhandled_key_input(Ref<InputEvent> p_event); Array _get_items() const; void _set_items(const Array &p_items); - void _gui_input(InputEvent p_event); + void _gui_input(Ref<InputEvent> p_event); protected: static void _bind_methods(); diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index 43f68d92a..00df266a0 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -51,11 +52,26 @@ void OptionButton::_notification(int p_what) { RID ci = get_canvas_item(); Ref<Texture> arrow = Control::get_icon("arrow"); Ref<StyleBox> normal = get_stylebox("normal"); + Color clr = Color(1, 1, 1); + if (get_constant("modulate_arrow")) + switch (get_draw_mode()) { + case DRAW_PRESSED: + clr = get_color("font_color_pressed"); + break; + case DRAW_HOVER: + clr = get_color("font_color_hover"); + break; + case DRAW_DISABLED: + clr = get_color("font_color_disabled"); + break; + default: + clr = get_color("font_color"); + } Size2 size = get_size(); Point2 ofs(size.width - arrow->get_width() - get_constant("arrow_margin"), int(Math::abs((size.height - arrow->get_height()) / 2))); - arrow->draw(ci, ofs); + arrow->draw(ci, ofs, clr); } break; } @@ -66,7 +82,7 @@ void OptionButton::_selected(int p_which) { int selid = -1; for (int i = 0; i < popup->get_item_count(); i++) { - bool is_clicked = popup->get_item_ID(i) == p_which; + bool is_clicked = popup->get_item_id(i) == p_which; if (is_clicked) { selid = i; break; @@ -86,7 +102,7 @@ void OptionButton::_selected(int p_which) { void OptionButton::pressed() { Size2 size = get_size(); - popup->set_global_pos(get_global_pos() + Size2(0, size.height)); + popup->set_global_position(get_global_position() + Size2(0, size.height)); popup->set_size(Size2(size.width, 0)); popup->popup(); @@ -113,9 +129,9 @@ void OptionButton::set_item_icon(int p_idx, const Ref<Texture> &p_icon) { popup->set_item_icon(p_idx, p_icon); } -void OptionButton::set_item_ID(int p_idx, int p_ID) { +void OptionButton::set_item_id(int p_idx, int p_ID) { - popup->set_item_ID(p_idx, p_ID); + popup->set_item_id(p_idx, p_ID); } void OptionButton::set_item_metadata(int p_idx, const Variant &p_metadata) { @@ -138,9 +154,9 @@ Ref<Texture> OptionButton::get_item_icon(int p_idx) const { return popup->get_item_icon(p_idx); } -int OptionButton::get_item_ID(int p_idx) const { +int OptionButton::get_item_id(int p_idx) const { - return popup->get_item_ID(p_idx); + return popup->get_item_id(p_idx); } Variant OptionButton::get_item_metadata(int p_idx) const { @@ -169,21 +185,21 @@ void OptionButton::clear() { current = -1; } -void OptionButton::_select(int p_idx, bool p_emit) { +void OptionButton::_select(int p_which, bool p_emit) { - if (p_idx < 0) + if (p_which < 0) return; - if (p_idx == current) + if (p_which == current) return; - ERR_FAIL_INDEX(p_idx, popup->get_item_count()); + ERR_FAIL_INDEX(p_which, popup->get_item_count()); for (int i = 0; i < popup->get_item_count(); i++) { - popup->set_item_checked(i, i == p_idx); + popup->set_item_checked(i, i == p_which); } - current = p_idx; + current = p_which; set_text(popup->get_item_text(current)); set_icon(popup->get_item_icon(current)); @@ -208,12 +224,12 @@ int OptionButton::get_selected() const { return current; } -int OptionButton::get_selected_ID() const { +int OptionButton::get_selected_id() const { int idx = get_selected(); if (idx < 0) return 0; - return get_item_ID(current); + return get_item_id(current); } Variant OptionButton::get_selected_metadata() const { @@ -236,7 +252,7 @@ Array OptionButton::_get_items() const { items.push_back(get_item_text(i)); items.push_back(get_item_icon(i)); items.push_back(is_item_disabled(i)); - items.push_back(get_item_ID(i)); + items.push_back(get_item_id(i)); items.push_back(get_item_metadata(i)); } @@ -273,15 +289,15 @@ void OptionButton::_bind_methods() { ClassDB::bind_method(D_METHOD("_selected"), &OptionButton::_selected); ClassDB::bind_method(D_METHOD("add_item", "label", "id"), &OptionButton::add_item, DEFVAL(-1)); - ClassDB::bind_method(D_METHOD("add_icon_item", "texture:Texture", "label", "id"), &OptionButton::add_icon_item); + ClassDB::bind_method(D_METHOD("add_icon_item", "texture", "label", "id"), &OptionButton::add_icon_item); ClassDB::bind_method(D_METHOD("set_item_text", "idx", "text"), &OptionButton::set_item_text); - ClassDB::bind_method(D_METHOD("set_item_icon", "idx", "texture:Texture"), &OptionButton::set_item_icon); + ClassDB::bind_method(D_METHOD("set_item_icon", "idx", "texture"), &OptionButton::set_item_icon); ClassDB::bind_method(D_METHOD("set_item_disabled", "idx", "disabled"), &OptionButton::set_item_disabled); - ClassDB::bind_method(D_METHOD("set_item_ID", "idx", "id"), &OptionButton::set_item_ID); + ClassDB::bind_method(D_METHOD("set_item_id", "idx", "id"), &OptionButton::set_item_id); ClassDB::bind_method(D_METHOD("set_item_metadata", "idx", "metadata"), &OptionButton::set_item_metadata); ClassDB::bind_method(D_METHOD("get_item_text", "idx"), &OptionButton::get_item_text); - ClassDB::bind_method(D_METHOD("get_item_icon:Texture", "idx"), &OptionButton::get_item_icon); - ClassDB::bind_method(D_METHOD("get_item_ID", "idx"), &OptionButton::get_item_ID); + ClassDB::bind_method(D_METHOD("get_item_icon", "idx"), &OptionButton::get_item_icon); + ClassDB::bind_method(D_METHOD("get_item_id", "idx"), &OptionButton::get_item_id); ClassDB::bind_method(D_METHOD("get_item_metadata", "idx"), &OptionButton::get_item_metadata); ClassDB::bind_method(D_METHOD("is_item_disabled", "idx"), &OptionButton::is_item_disabled); ClassDB::bind_method(D_METHOD("get_item_count"), &OptionButton::get_item_count); @@ -289,7 +305,7 @@ void OptionButton::_bind_methods() { ClassDB::bind_method(D_METHOD("clear"), &OptionButton::clear); ClassDB::bind_method(D_METHOD("select", "idx"), &OptionButton::select); ClassDB::bind_method(D_METHOD("get_selected"), &OptionButton::get_selected); - ClassDB::bind_method(D_METHOD("get_selected_ID"), &OptionButton::get_selected_ID); + ClassDB::bind_method(D_METHOD("get_selected_id"), &OptionButton::get_selected_id); ClassDB::bind_method(D_METHOD("get_selected_metadata"), &OptionButton::get_selected_metadata); ClassDB::bind_method(D_METHOD("remove_item", "idx"), &OptionButton::remove_item); ClassDB::bind_method(D_METHOD("_select_int"), &OptionButton::_select_int); diff --git a/scene/gui/option_button.h b/scene/gui/option_button.h index 55a98cb50..db921b8b9 100644 --- a/scene/gui/option_button.h +++ b/scene/gui/option_button.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -61,13 +62,13 @@ public: void set_item_text(int p_idx, const String &p_text); void set_item_icon(int p_idx, const Ref<Texture> &p_icon); - void set_item_ID(int p_idx, int p_ID); + void set_item_id(int p_idx, int p_ID); void set_item_metadata(int p_idx, const Variant &p_metadata); void set_item_disabled(int p_idx, bool p_disabled); String get_item_text(int p_idx) const; Ref<Texture> get_item_icon(int p_idx) const; - int get_item_ID(int p_idx) const; + int get_item_id(int p_idx) const; Variant get_item_metadata(int p_idx) const; bool is_item_disabled(int p_idx) const; @@ -79,7 +80,7 @@ public: void select(int p_idx); int get_selected() const; - int get_selected_ID() const; + int get_selected_id() const; Variant get_selected_metadata() const; void remove_item(int p_idx); diff --git a/scene/gui/panel.cpp b/scene/gui/panel.cpp index 536f0baf7..f3c6142f9 100644 --- a/scene/gui/panel.cpp +++ b/scene/gui/panel.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/panel.h b/scene/gui/panel.h index 3d2c0a3e9..eac8f2d4e 100644 --- a/scene/gui/panel.h +++ b/scene/gui/panel.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/panel_container.cpp b/scene/gui/panel_container.cpp index 9dc7a6b32..86874f7cf 100644 --- a/scene/gui/panel_container.cpp +++ b/scene/gui/panel_container.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/panel_container.h b/scene/gui/panel_container.h index 13ed1c935..f8f1fb649 100644 --- a/scene/gui/panel_container.h +++ b/scene/gui/panel_container.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/patch_9_rect.cpp b/scene/gui/patch_9_rect.cpp index d0bd45e43..249090830 100644 --- a/scene/gui/patch_9_rect.cpp +++ b/scene/gui/patch_9_rect.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -37,27 +38,13 @@ void NinePatchRect::_notification(int p_what) { if (texture.is_null()) return; - Size2 s = get_size(); - RID ci = get_canvas_item(); - VS::get_singleton()->canvas_item_add_nine_patch(ci, Rect2(Point2(), s), region_rect, texture->get_rid(), Vector2(margin[MARGIN_LEFT], margin[MARGIN_TOP]), Vector2(margin[MARGIN_RIGHT], margin[MARGIN_BOTTOM]), VS::NINE_PATCH_STRETCH, VS::NINE_PATCH_STRETCH, draw_center); - //draw_texture_rect(texture,Rect2(Point2(),s),false,modulate); + Rect2 rect = Rect2(Point2(), get_size()); + Rect2 src_rect = region_rect; - /* - Vector<Point2> points; - points.resize(4); - points[0]=Point2(0,0); - points[1]=Point2(s.x,0); - points[2]=Point2(s.x,s.y); - points[3]=Point2(0,s.y); - Vector<Point2> uvs; - uvs.resize(4); - uvs[0]=Point2(0,0); - uvs[1]=Point2(1,0); - uvs[2]=Point2(1,1); - uvs[3]=Point2(0,1); + texture->get_rect_region(rect, src_rect, rect, src_rect); - VisualServer::get_singleton()->canvas_item_add_primitive(ci,points,Vector<Color>(),uvs,texture->get_rid()); -*/ + RID ci = get_canvas_item(); + VS::get_singleton()->canvas_item_add_nine_patch(ci, rect, src_rect, texture->get_rid(), Vector2(margin[MARGIN_LEFT], margin[MARGIN_TOP]), Vector2(margin[MARGIN_RIGHT], margin[MARGIN_BOTTOM]), VS::NinePatchAxisMode(axis_h), VS::NinePatchAxisMode(axis_v), draw_center); } } @@ -75,6 +62,10 @@ void NinePatchRect::_bind_methods() { ClassDB::bind_method(D_METHOD("get_region_rect"), &NinePatchRect::get_region_rect); ClassDB::bind_method(D_METHOD("set_draw_center", "draw_center"), &NinePatchRect::set_draw_center); ClassDB::bind_method(D_METHOD("get_draw_center"), &NinePatchRect::get_draw_center); + ClassDB::bind_method(D_METHOD("set_h_axis_stretch_mode", "mode"), &NinePatchRect::set_h_axis_stretch_mode); + ClassDB::bind_method(D_METHOD("get_h_axis_stretch_mode"), &NinePatchRect::get_h_axis_stretch_mode); + ClassDB::bind_method(D_METHOD("set_v_axis_stretch_mode", "mode"), &NinePatchRect::set_v_axis_stretch_mode); + ClassDB::bind_method(D_METHOD("get_v_axis_stretch_mode"), &NinePatchRect::get_v_axis_stretch_mode); ADD_SIGNAL(MethodInfo("texture_changed")); @@ -87,6 +78,13 @@ void NinePatchRect::_bind_methods() { ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "patch_margin_top", PROPERTY_HINT_RANGE, "0,16384,1"), "set_patch_margin", "get_patch_margin", MARGIN_TOP); ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "patch_margin_right", PROPERTY_HINT_RANGE, "0,16384,1"), "set_patch_margin", "get_patch_margin", MARGIN_RIGHT); ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "patch_margin_bottom", PROPERTY_HINT_RANGE, "0,16384,1"), "set_patch_margin", "get_patch_margin", MARGIN_BOTTOM); + ADD_GROUP("Axis Stretch", "axis_stretch_"); + ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "axis_stretch_horizontal", PROPERTY_HINT_ENUM, "Stretch,Tile,Tile Fit"), "set_h_axis_stretch_mode", "get_h_axis_stretch_mode"); + ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "axis_stretch_vertical", PROPERTY_HINT_ENUM, "Stretch,Tile,Tile Fit"), "set_v_axis_stretch_mode", "get_v_axis_stretch_mode"); + + BIND_CONSTANT(AXIS_STRETCH_MODE_STRETCH); + BIND_CONSTANT(AXIS_STRETCH_MODE_TILE); + BIND_CONSTANT(AXIS_STRETCH_MODE_TILE_FIT); } void NinePatchRect::set_texture(const Ref<Texture> &p_tex) { @@ -101,6 +99,7 @@ void NinePatchRect::set_texture(const Ref<Texture> &p_tex) { */ minimum_size_changed(); emit_signal("texture_changed"); + _change_notify("texture"); } Ref<Texture> NinePatchRect::get_texture() const { @@ -116,16 +115,16 @@ void NinePatchRect::set_patch_margin(Margin p_margin, int p_size) { minimum_size_changed(); switch (p_margin) { case MARGIN_LEFT: - _change_notify("patch_margin/left"); + _change_notify("patch_margin_left"); break; case MARGIN_TOP: - _change_notify("patch_margin/top"); + _change_notify("patch_margin_top"); break; case MARGIN_RIGHT: - _change_notify("patch_margin/right"); + _change_notify("patch_margin_right"); break; case MARGIN_BOTTOM: - _change_notify("patch_margin/bottom"); + _change_notify("patch_margin_bottom"); break; } } @@ -163,6 +162,26 @@ bool NinePatchRect::get_draw_center() const { return draw_center; } +void NinePatchRect::set_h_axis_stretch_mode(AxisStretchMode p_mode) { + axis_h = p_mode; + update(); +} + +NinePatchRect::AxisStretchMode NinePatchRect::get_h_axis_stretch_mode() const { + return axis_h; +} + +void NinePatchRect::set_v_axis_stretch_mode(AxisStretchMode p_mode) { + + axis_v = p_mode; + update(); +} + +NinePatchRect::AxisStretchMode NinePatchRect::get_v_axis_stretch_mode() const { + + return axis_v; +} + NinePatchRect::NinePatchRect() { margin[MARGIN_LEFT] = 0; @@ -172,6 +191,9 @@ NinePatchRect::NinePatchRect() { set_mouse_filter(MOUSE_FILTER_IGNORE); draw_center = true; + + axis_h = AXIS_STRETCH_MODE_STRETCH; + axis_v = AXIS_STRETCH_MODE_STRETCH; } NinePatchRect::~NinePatchRect() { diff --git a/scene/gui/patch_9_rect.h b/scene/gui/patch_9_rect.h index 09663e62f..636b9127e 100644 --- a/scene/gui/patch_9_rect.h +++ b/scene/gui/patch_9_rect.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -37,11 +38,20 @@ class NinePatchRect : public Control { GDCLASS(NinePatchRect, Control); +public: + enum AxisStretchMode { + AXIS_STRETCH_MODE_STRETCH, + AXIS_STRETCH_MODE_TILE, + AXIS_STRETCH_MODE_TILE_FIT, + }; + bool draw_center; int margin[4]; Rect2 region_rect; Ref<Texture> texture; + AxisStretchMode axis_h, axis_v; + protected: void _notification(int p_what); virtual Size2 get_minimum_size() const; @@ -57,10 +67,18 @@ public: void set_region_rect(const Rect2 &p_region_rect); Rect2 get_region_rect() const; - void set_draw_center(bool p_enable); + void set_draw_center(bool p_draw); bool get_draw_center() const; + void set_h_axis_stretch_mode(AxisStretchMode p_mode); + AxisStretchMode get_h_axis_stretch_mode() const; + + void set_v_axis_stretch_mode(AxisStretchMode p_mode); + AxisStretchMode get_v_axis_stretch_mode() const; + NinePatchRect(); ~NinePatchRect(); }; + +VARIANT_ENUM_CAST(NinePatchRect::AxisStretchMode) #endif // PATCH_9_FRAME_H diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index 52ad37e9a..f2ba6bfbc 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,7 +30,7 @@ #include "popup.h" #include "os/keyboard.h" -void Popup::_gui_input(InputEvent p_event) { +void Popup::_gui_input(Ref<InputEvent> p_event) { } void Popup::_notification(int p_what) { @@ -57,12 +58,12 @@ void Popup::_notification(int p_what) { void Popup::_fix_size() { #if 0 - Point2 pos = get_pos(); + Point2 pos = get_position(); Size2 size = get_size(); Point2 window_size = window==this ? get_parent_area_size() :window->get_size(); #else - Point2 pos = get_global_pos(); + Point2 pos = get_global_position(); Size2 size = get_size(); Point2 window_size = get_viewport_rect().size; @@ -78,10 +79,10 @@ void Popup::_fix_size() { pos.y = 0; #if 0 if (pos!=get_pos()) - set_pos(pos); + set_position(pos); #else - if (pos != get_pos()) - set_global_pos(pos); + if (pos != get_position()) + set_global_position(pos); #endif } @@ -107,13 +108,10 @@ void Popup::set_as_minsize() { float margin_begin = c->get_margin(m_beg); float margin_end = c->get_margin(m_end); - AnchorType anchor_begin = c->get_anchor(m_beg); - AnchorType anchor_end = c->get_anchor(m_end); + float anchor_begin = c->get_anchor(m_beg); + float anchor_end = c->get_anchor(m_end); - if (anchor_begin == ANCHOR_BEGIN) - minsize[j] += margin_begin; - if (anchor_end == ANCHOR_END) - minsize[j] += margin_end; + minsize[j] += margin_begin * (ANCHOR_END - anchor_begin) + margin_end * anchor_end; } total_minsize.width = MAX(total_minsize.width, minsize.width); @@ -144,13 +142,10 @@ void Popup::popup_centered_minsize(const Size2 &p_minsize) { float margin_begin = c->get_margin(m_beg); float margin_end = c->get_margin(m_end); - AnchorType anchor_begin = c->get_anchor(m_beg); - AnchorType anchor_end = c->get_anchor(m_end); + float anchor_begin = c->get_anchor(m_beg); + float anchor_end = c->get_anchor(m_end); - if (anchor_begin == ANCHOR_BEGIN) - minsize[j] += margin_begin; - if (anchor_end == ANCHOR_END) - minsize[j] += margin_end; + minsize[j] += margin_begin * (ANCHOR_END - anchor_begin) + margin_end * anchor_end; } total_minsize.width = MAX(total_minsize.width, minsize.width); @@ -169,8 +164,8 @@ void Popup::popup_centered(const Size2 &p_size) { Rect2 rect; rect.size = p_size == Size2() ? get_size() : p_size; - rect.pos = ((window_size - rect.size) / 2.0).floor(); - set_pos(rect.pos); + rect.position = ((window_size - rect.size) / 2.0).floor(); + set_position(rect.position); set_size(rect.size); show_modal(exclusive); @@ -192,8 +187,8 @@ void Popup::popup_centered_ratio(float p_screen_ratio) { Rect2 rect; Point2 window_size = get_viewport_rect().size; rect.size = (window_size * p_screen_ratio).floor(); - rect.pos = ((window_size - rect.size) / 2.0).floor(); - set_pos(rect.pos); + rect.position = ((window_size - rect.size) / 2.0).floor(); + set_position(rect.position); set_size(rect.size); show_modal(exclusive); @@ -208,15 +203,15 @@ void Popup::popup_centered_ratio(float p_screen_ratio) { popped_up = true; } -void Popup::popup(const Rect2 &bounds) { +void Popup::popup(const Rect2 &p_bounds) { emit_signal("about_to_show"); show_modal(exclusive); // Fit the popup into the optionally provided bounds. - if (!bounds.has_no_area()) { - set_pos(bounds.pos); - set_size(bounds.size); + if (!p_bounds.has_no_area()) { + set_position(p_bounds.position); + set_size(p_bounds.size); } _fix_size(); diff --git a/scene/gui/popup.h b/scene/gui/popup.h index d80daaad1..0543ae193 100644 --- a/scene/gui/popup.h +++ b/scene/gui/popup.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -44,7 +45,7 @@ class Popup : public Control { protected: virtual void _post_popup() {} - void _gui_input(InputEvent p_event); + void _gui_input(Ref<InputEvent> p_event); void _notification(int p_what); virtual void _fix_size(); static void _bind_methods(); diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index a2a670fa1..46aa0e505 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -107,6 +108,11 @@ Size2 PopupMenu::get_minimum_size() const { accel_max_w = MAX(accel_w, accel_max_w); } + if (items[i].submenu != "") { + + size.width += get_icon("submenu")->get_width(); + } + minsize.height += size.height; max_w = MAX(max_w, size.width); } @@ -168,7 +174,7 @@ void PopupMenu::_activate_submenu(int over) { if (pm->is_visible_in_tree()) return; //already visible! - Point2 p = get_global_pos(); + Point2 p = get_global_position(); Rect2 pr(p, get_size()); Ref<StyleBox> style = get_stylebox("panel"); @@ -178,18 +184,18 @@ void PopupMenu::_activate_submenu(int over) { if (pos.x + size.width > get_viewport_rect().size.width) pos.x = p.x - size.width; - pm->set_pos(pos); + pm->set_position(pos); pm->popup(); PopupMenu *pum = pm->cast_to<PopupMenu>(); if (pum) { - pr.pos -= pum->get_global_pos(); + pr.position -= pum->get_global_position(); pum->clear_autohide_areas(); - pum->add_autohide_area(Rect2(pr.pos.x, pr.pos.y, pr.size.x, items[over]._ofs_cache)); + pum->add_autohide_area(Rect2(pr.position.x, pr.position.y, pr.size.x, items[over]._ofs_cache)); if (over < items.size() - 1) { int from = items[over + 1]._ofs_cache; - pum->add_autohide_area(Rect2(pr.pos.x, pr.pos.y + from, pr.size.x, pr.size.y - from)); + pum->add_autohide_area(Rect2(pr.position.x, pr.position.y + from, pr.size.x, pr.size.y - from)); } } } @@ -202,171 +208,170 @@ void PopupMenu::_submenu_timeout() { } } -void PopupMenu::_gui_input(const InputEvent &p_event) { +void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) { - switch (p_event.type) { + Ref<InputEventKey> k = p_event; - case InputEvent::KEY: { + if (k.is_valid()) { - if (!p_event.key.pressed) - break; + if (!k->is_pressed()) + return; - switch (p_event.key.scancode) { + switch (k->get_scancode()) { - case KEY_DOWN: { + case KEY_DOWN: { - for (int i = mouse_over + 1; i < items.size(); i++) { + for (int i = mouse_over + 1; i < items.size(); i++) { - if (i < 0 || i >= items.size()) - continue; + if (i < 0 || i >= items.size()) + continue; - if (!items[i].separator && !items[i].disabled) { + if (!items[i].separator && !items[i].disabled) { - mouse_over = i; - update(); - break; - } + mouse_over = i; + update(); + break; } - } break; - case KEY_UP: { + } + } break; + case KEY_UP: { - for (int i = mouse_over - 1; i >= 0; i--) { + for (int i = mouse_over - 1; i >= 0; i--) { - if (i < 0 || i >= items.size()) - continue; + if (i < 0 || i >= items.size()) + continue; - if (!items[i].separator && !items[i].disabled) { + if (!items[i].separator && !items[i].disabled) { - mouse_over = i; - update(); - break; - } + mouse_over = i; + update(); + break; } - } break; - case KEY_RETURN: - case KEY_ENTER: { + } + } break; + case KEY_ENTER: + case KEY_KP_ENTER: { - if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator) { + if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator) { - activate_item(mouse_over); - } - } break; - } + activate_item(mouse_over); + } + } break; + } + } - } break; + Ref<InputEventMouseButton> b = p_event; - case InputEvent::MOUSE_BUTTON: { + if (b.is_valid()) { - const InputEventMouseButton &b = p_event.mouse_button; - if (b.pressed) - break; + if (b->is_pressed()) + return; - switch (b.button_index) { + switch (b->get_button_index()) { - case BUTTON_WHEEL_DOWN: { + case BUTTON_WHEEL_DOWN: { - if (get_global_pos().y + get_size().y > get_viewport_rect().size.y) { + if (get_global_position().y + get_size().y > get_viewport_rect().size.y) { - int vseparation = get_constant("vseparation"); - Ref<Font> font = get_font("font"); + int vseparation = get_constant("vseparation"); + Ref<Font> font = get_font("font"); - Point2 pos = get_pos(); - int s = (vseparation + font->get_height()) * 3; - pos.y -= s; - set_pos(pos); + Point2 pos = get_position(); + int s = (vseparation + font->get_height()) * 3; + pos.y -= (s * b->get_factor()); + set_position(pos); - //update hover - InputEvent ie; - ie.type = InputEvent::MOUSE_MOTION; - ie.mouse_motion.x = b.x; - ie.mouse_motion.y = b.y + s; - _gui_input(ie); - } - } break; - case BUTTON_WHEEL_UP: { + //update hover + Ref<InputEventMouseMotion> ie; + ie.instance(); + ie->set_position(b->get_position() + Vector2(0, s)); + _gui_input(ie); + } + } break; + case BUTTON_WHEEL_UP: { - if (get_global_pos().y < 0) { + if (get_global_position().y < 0) { - int vseparation = get_constant("vseparation"); - Ref<Font> font = get_font("font"); + int vseparation = get_constant("vseparation"); + Ref<Font> font = get_font("font"); - Point2 pos = get_pos(); - int s = (vseparation + font->get_height()) * 3; - pos.y += s; - set_pos(pos); + Point2 pos = get_position(); + int s = (vseparation + font->get_height()) * 3; + pos.y += (s * b->get_factor()); + set_position(pos); - //update hover - InputEvent ie; - ie.type = InputEvent::MOUSE_MOTION; - ie.mouse_motion.x = b.x; - ie.mouse_motion.y = b.y - s; - _gui_input(ie); - } - } break; - case BUTTON_LEFT: { + //update hover + Ref<InputEventMouseMotion> ie; + ie.instance(); + ie->set_position(b->get_position() - Vector2(0, s)); + _gui_input(ie); + } + } break; + case BUTTON_LEFT: { - int over = _get_mouse_over(Point2(b.x, b.y)); + int over = _get_mouse_over(b->get_position()); - if (invalidated_click) { - invalidated_click = false; - break; - } - if (over < 0) { - hide(); - break; //non-activable - } + if (invalidated_click) { + invalidated_click = false; + break; + } + if (over < 0) { + hide(); + break; //non-activable + } - if (items[over].separator || items[over].disabled) - break; + if (items[over].separator || items[over].disabled) + break; - if (items[over].submenu != "") { + if (items[over].submenu != "") { - _activate_submenu(over); - return; - } - activate_item(over); + _activate_submenu(over); + return; + } + activate_item(over); - } break; - } + } break; + } - //update(); - } break; - case InputEvent::MOUSE_MOTION: { + //update(); + } - if (invalidated_click) { - moved += Vector2(p_event.mouse_motion.relative_x, p_event.mouse_motion.relative_y); - if (moved.length() > 4) - invalidated_click = false; - } + Ref<InputEventMouseMotion> m = p_event; - const InputEventMouseMotion &m = p_event.mouse_motion; - for (List<Rect2>::Element *E = autohide_areas.front(); E; E = E->next()) { + if (m.is_valid()) { - if (!Rect2(Point2(), get_size()).has_point(Point2(m.x, m.y)) && E->get().has_point(Point2(m.x, m.y))) { - call_deferred("hide"); - return; - } - } + if (invalidated_click) { + moved += m->get_relative(); + if (moved.length() > 4) + invalidated_click = false; + } - int over = _get_mouse_over(Point2(m.x, m.y)); - int id = (over < 0 || items[over].separator || items[over].disabled) ? -1 : (items[over].ID >= 0 ? items[over].ID : over); + for (List<Rect2>::Element *E = autohide_areas.front(); E; E = E->next()) { - if (id < 0) { - mouse_over = -1; - update(); - break; + if (!Rect2(Point2(), get_size()).has_point(m->get_position()) && E->get().has_point(m->get_position())) { + call_deferred("hide"); + return; } + } - if (items[over].submenu != "" && submenu_over != over) { - submenu_over = over; - submenu_timer->start(); - } + int over = _get_mouse_over(m->get_position()); + int id = (over < 0 || items[over].separator || items[over].disabled) ? -1 : (items[over].ID >= 0 ? items[over].ID : over); - if (over != mouse_over) { - mouse_over = over; - update(); - } - } break; + if (id < 0) { + mouse_over = -1; + update(); + return; + } + + if (items[over].submenu != "" && submenu_over != over) { + submenu_over = over; + submenu_timer->start(); + } + + if (over != mouse_over) { + mouse_over = over; + update(); + } } } @@ -642,7 +647,7 @@ void PopupMenu::set_item_checked(int p_idx, bool p_checked) { update(); } -void PopupMenu::set_item_ID(int p_idx, int p_ID) { +void PopupMenu::set_item_id(int p_idx, int p_ID) { ERR_FAIL_INDEX(p_idx, items.size()); items[p_idx].ID = p_ID; @@ -691,6 +696,17 @@ String PopupMenu::get_item_text(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, items.size(), ""); return items[p_idx].text; } + +int PopupMenu::get_item_idx_from_text(const String &text) const { + + for (int idx = 0; idx < items.size(); idx++) { + if (items[idx].text == text) + return idx; + } + + return -1; +} + Ref<Texture> PopupMenu::get_item_icon(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, items.size(), Ref<Texture>()); @@ -721,7 +737,7 @@ bool PopupMenu::is_item_checked(int p_idx) const { return items[p_idx].checked; } -int PopupMenu::get_item_ID(int p_idx) const { +int PopupMenu::get_item_id(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, items.size(), 0); return items[p_idx].ID; @@ -814,20 +830,22 @@ int PopupMenu::get_item_count() const { return items.size(); } -bool PopupMenu::activate_item_by_event(const InputEvent &p_event, bool p_for_global_only) { +bool PopupMenu::activate_item_by_event(const Ref<InputEvent> &p_event, bool p_for_global_only) { uint32_t code = 0; - if (p_event.type == InputEvent::KEY) { - code = p_event.key.scancode; + Ref<InputEventKey> k = p_event; + + if (k.is_valid()) { + code = k->get_scancode(); if (code == 0) - code = p_event.key.unicode; - if (p_event.key.mod.control) + code = k->get_unicode(); + if (k->get_control()) code |= KEY_MASK_CTRL; - if (p_event.key.mod.alt) + if (k->get_alt()) code |= KEY_MASK_ALT; - if (p_event.key.mod.meta) + if (k->get_metakey()) code |= KEY_MASK_META; - if (p_event.key.mod.shift) + if (k->get_shift()) code |= KEY_MASK_SHIFT; } @@ -877,7 +895,7 @@ void PopupMenu::activate_item(int p_item) { while (pop) { // We close all parents that are chained together, // with hide_on_item_selection enabled - if (hide_on_item_selection && pop->is_hide_on_item_selection()) { + if ((items[p_item].checkable && hide_on_checkable_item_selection && pop->is_hide_on_checkable_item_selection()) || (!items[p_item].checkable && hide_on_item_selection && pop->is_hide_on_item_selection())) { pop->hide(); next = next->get_parent(); pop = next->cast_to<PopupMenu>(); @@ -888,8 +906,8 @@ void PopupMenu::activate_item(int p_item) { } } // Hides popup by default; unless otherwise specified - // by using set_hide_on_item_selection - if (hide_on_item_selection) { + // by using set_hide_on_item_selection and set_hide_on_checkable_item_selection + if ((items[p_item].checkable && hide_on_checkable_item_selection) || (!items[p_item].checkable && hide_on_item_selection)) { hide(); } } @@ -938,7 +956,7 @@ Array PopupMenu::_get_items() const { items.push_back(is_item_checked(i)); items.push_back(is_item_disabled(i)); - items.push_back(get_item_ID(i)); + items.push_back(get_item_id(i)); items.push_back(get_item_accelerator(i)); items.push_back(get_item_metadata(i)); items.push_back(get_item_submenu(i)); @@ -993,7 +1011,7 @@ void PopupMenu::_set_items(const Array &p_items) { set_item_as_checkable(idx, checkable); set_item_checked(idx, checked); set_item_disabled(idx, disabled); - set_item_ID(idx, id); + set_item_id(idx, id); set_item_metadata(idx, meta); set_item_as_separator(idx, sep); set_item_accelerator(idx, accel); @@ -1012,6 +1030,16 @@ bool PopupMenu::is_hide_on_item_selection() { return hide_on_item_selection; } +void PopupMenu::set_hide_on_checkable_item_selection(bool p_enabled) { + + hide_on_checkable_item_selection = p_enabled; +} + +bool PopupMenu::is_hide_on_checkable_item_selection() { + + return hide_on_checkable_item_selection; +} + String PopupMenu::get_tooltip(const Point2 &p_pos) const { int over = _get_mouse_over(p_pos); @@ -1053,15 +1081,15 @@ void PopupMenu::_bind_methods() { ClassDB::bind_method(D_METHOD("add_check_item", "label", "id", "accel"), &PopupMenu::add_check_item, DEFVAL(-1), DEFVAL(0)); ClassDB::bind_method(D_METHOD("add_submenu_item", "label", "submenu", "id"), &PopupMenu::add_submenu_item, DEFVAL(-1)); - ClassDB::bind_method(D_METHOD("add_icon_shortcut", "texture", "shortcut:ShortCut", "id", "global"), &PopupMenu::add_icon_shortcut, DEFVAL(-1), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("add_shortcut", "shortcut:ShortCut", "id", "global"), &PopupMenu::add_shortcut, DEFVAL(-1), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("add_icon_check_shortcut", "texture", "shortcut:ShortCut", "id", "global"), &PopupMenu::add_icon_check_shortcut, DEFVAL(-1), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("add_check_shortcut", "shortcut:ShortCut", "id", "global"), &PopupMenu::add_check_shortcut, DEFVAL(-1), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("add_icon_shortcut", "texture", "shortcut", "id", "global"), &PopupMenu::add_icon_shortcut, DEFVAL(-1), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("add_shortcut", "shortcut", "id", "global"), &PopupMenu::add_shortcut, DEFVAL(-1), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("add_icon_check_shortcut", "texture", "shortcut", "id", "global"), &PopupMenu::add_icon_check_shortcut, DEFVAL(-1), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("add_check_shortcut", "shortcut", "id", "global"), &PopupMenu::add_check_shortcut, DEFVAL(-1), DEFVAL(false)); ClassDB::bind_method(D_METHOD("set_item_text", "idx", "text"), &PopupMenu::set_item_text); ClassDB::bind_method(D_METHOD("set_item_icon", "idx", "icon"), &PopupMenu::set_item_icon); ClassDB::bind_method(D_METHOD("set_item_checked", "idx", "checked"), &PopupMenu::set_item_checked); - ClassDB::bind_method(D_METHOD("set_item_ID", "idx", "id"), &PopupMenu::set_item_ID); + ClassDB::bind_method(D_METHOD("set_item_id", "idx", "id"), &PopupMenu::set_item_id); ClassDB::bind_method(D_METHOD("set_item_accelerator", "idx", "accel"), &PopupMenu::set_item_accelerator); ClassDB::bind_method(D_METHOD("set_item_metadata", "idx", "metadata"), &PopupMenu::set_item_metadata); ClassDB::bind_method(D_METHOD("set_item_disabled", "idx", "disabled"), &PopupMenu::set_item_disabled); @@ -1069,14 +1097,14 @@ void PopupMenu::_bind_methods() { ClassDB::bind_method(D_METHOD("set_item_as_separator", "idx", "enable"), &PopupMenu::set_item_as_separator); ClassDB::bind_method(D_METHOD("set_item_as_checkable", "idx", "enable"), &PopupMenu::set_item_as_checkable); ClassDB::bind_method(D_METHOD("set_item_tooltip", "idx", "tooltip"), &PopupMenu::set_item_tooltip); - ClassDB::bind_method(D_METHOD("set_item_shortcut", "idx", "shortcut:ShortCut", "global"), &PopupMenu::set_item_shortcut, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("set_item_shortcut", "idx", "shortcut", "global"), &PopupMenu::set_item_shortcut, DEFVAL(false)); ClassDB::bind_method(D_METHOD("toggle_item_checked", "idx"), &PopupMenu::toggle_item_checked); ClassDB::bind_method(D_METHOD("get_item_text", "idx"), &PopupMenu::get_item_text); ClassDB::bind_method(D_METHOD("get_item_icon", "idx"), &PopupMenu::get_item_icon); ClassDB::bind_method(D_METHOD("is_item_checked", "idx"), &PopupMenu::is_item_checked); - ClassDB::bind_method(D_METHOD("get_item_ID", "idx"), &PopupMenu::get_item_ID); + ClassDB::bind_method(D_METHOD("get_item_id", "idx"), &PopupMenu::get_item_id); ClassDB::bind_method(D_METHOD("get_item_index", "id"), &PopupMenu::get_item_index); ClassDB::bind_method(D_METHOD("get_item_accelerator", "idx"), &PopupMenu::get_item_accelerator); ClassDB::bind_method(D_METHOD("get_item_metadata", "idx"), &PopupMenu::get_item_metadata); @@ -1085,7 +1113,7 @@ void PopupMenu::_bind_methods() { ClassDB::bind_method(D_METHOD("is_item_separator", "idx"), &PopupMenu::is_item_separator); ClassDB::bind_method(D_METHOD("is_item_checkable", "idx"), &PopupMenu::is_item_checkable); ClassDB::bind_method(D_METHOD("get_item_tooltip", "idx"), &PopupMenu::get_item_tooltip); - ClassDB::bind_method(D_METHOD("get_item_shortcut:ShortCut", "idx"), &PopupMenu::get_item_shortcut); + ClassDB::bind_method(D_METHOD("get_item_shortcut", "idx"), &PopupMenu::get_item_shortcut); ClassDB::bind_method(D_METHOD("get_item_count"), &PopupMenu::get_item_count); @@ -1100,10 +1128,14 @@ void PopupMenu::_bind_methods() { ClassDB::bind_method(D_METHOD("set_hide_on_item_selection", "enable"), &PopupMenu::set_hide_on_item_selection); ClassDB::bind_method(D_METHOD("is_hide_on_item_selection"), &PopupMenu::is_hide_on_item_selection); + ClassDB::bind_method(D_METHOD("set_hide_on_checkable_item_selection", "enable"), &PopupMenu::set_hide_on_checkable_item_selection); + ClassDB::bind_method(D_METHOD("is_hide_on_checkable_item_selection"), &PopupMenu::is_hide_on_checkable_item_selection); + ClassDB::bind_method(D_METHOD("_submenu_timeout"), &PopupMenu::_submenu_timeout); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_items", "_get_items"); ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "hide_on_item_selection"), "set_hide_on_item_selection", "is_hide_on_item_selection"); + ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "hide_on_checkable_item_selection"), "set_hide_on_checkable_item_selection", "is_hide_on_checkable_item_selection"); ADD_SIGNAL(MethodInfo("id_pressed", PropertyInfo(Variant::INT, "ID"))); ADD_SIGNAL(MethodInfo("index_pressed", PropertyInfo(Variant::INT, "index"))); @@ -1121,6 +1153,7 @@ PopupMenu::PopupMenu() { set_focus_mode(FOCUS_ALL); set_as_toplevel(true); set_hide_on_item_selection(true); + set_hide_on_checkable_item_selection(true); submenu_timer = memnew(Timer); submenu_timer->set_wait_time(0.3); diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index 186d40f6d..37714ee98 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -78,12 +79,13 @@ class PopupMenu : public Popup { String _get_accel_text(int p_item) const; int _get_mouse_over(const Point2 &p_over) const; virtual Size2 get_minimum_size() const; - void _gui_input(const InputEvent &p_event); + void _gui_input(const Ref<InputEvent> &p_event); void _activate_submenu(int over); void _submenu_timeout(); bool invalidated_click; bool hide_on_item_selection; + bool hide_on_checkable_item_selection; Vector2 moved; Array _get_items() const; @@ -116,7 +118,7 @@ public: void set_item_text(int p_idx, const String &p_text); void set_item_icon(int p_idx, const Ref<Texture> &p_icon); void set_item_checked(int p_idx, bool p_checked); - void set_item_ID(int p_idx, int p_ID); + void set_item_id(int p_idx, int p_ID); void set_item_accelerator(int p_idx, uint32_t p_accel); void set_item_metadata(int p_idx, const Variant &p_meta); void set_item_disabled(int p_idx, bool p_disabled); @@ -130,14 +132,15 @@ public: void toggle_item_checked(int p_idx); String get_item_text(int p_idx) const; + int get_item_idx_from_text(const String &text) const; Ref<Texture> get_item_icon(int p_idx) const; bool is_item_checked(int p_idx) const; - int get_item_ID(int p_idx) const; + int get_item_id(int p_idx) const; int get_item_index(int p_ID) const; uint32_t get_item_accelerator(int p_idx) const; Variant get_item_metadata(int p_idx) const; bool is_item_disabled(int p_idx) const; - String get_item_submenu(int p_ID) const; + String get_item_submenu(int p_idx) const; bool is_item_separator(int p_idx) const; bool is_item_checkable(int p_idx) const; String get_item_tooltip(int p_idx) const; @@ -145,7 +148,7 @@ public: int get_item_count() const; - bool activate_item_by_event(const InputEvent &p_event, bool p_for_global_only = false); + bool activate_item_by_event(const Ref<InputEvent> &p_event, bool p_for_global_only = false); void activate_item(int p_item); void remove_item(int p_idx); @@ -167,6 +170,9 @@ public: void set_hide_on_item_selection(bool p_enabled); bool is_hide_on_item_selection(); + void set_hide_on_checkable_item_selection(bool p_enabled); + bool is_hide_on_checkable_item_selection(); + PopupMenu(); ~PopupMenu(); }; diff --git a/scene/gui/progress_bar.cpp b/scene/gui/progress_bar.cpp index 86dea6cd9..13d368d25 100644 --- a/scene/gui/progress_bar.cpp +++ b/scene/gui/progress_bar.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/progress_bar.h b/scene/gui/progress_bar.h index b5820d168..1121a78aa 100644 --- a/scene/gui/progress_bar.h +++ b/scene/gui/progress_bar.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp index f15f3a607..68afe8150 100644 --- a/scene/gui/range.cpp +++ b/scene/gui/range.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,7 +34,7 @@ void Range::_value_changed_notify() { _value_changed(shared->val); emit_signal("value_changed", shared->val); update(); - _change_notify("range/value"); + _change_notify("value"); } void Range::Shared::emit_value_changed() { @@ -87,26 +88,26 @@ void Range::set_min(double p_min) { shared->min = p_min; set_value(shared->val); - shared->emit_changed("range/min"); + shared->emit_changed("min"); } void Range::set_max(double p_max) { shared->max = p_max; set_value(shared->val); - shared->emit_changed("range/max"); + shared->emit_changed("max"); } void Range::set_step(double p_step) { shared->step = p_step; - shared->emit_changed("range/step"); + shared->emit_changed("step"); } void Range::set_page(double p_page) { shared->page = p_page; set_value(shared->val); - shared->emit_changed("range/page"); + shared->emit_changed("page"); } double Range::get_value() const { @@ -272,8 +273,8 @@ Range::Range() { shared = memnew(Shared); shared->min = 0; shared->max = 100; - shared->val = - shared->step = 1; + shared->val = 0; + shared->step = 1; shared->page = 0; shared->owners.insert(this); shared->exp_ratio = false; diff --git a/scene/gui/range.h b/scene/gui/range.h index 105bd08a4..fdcbbb09e 100644 --- a/scene/gui/range.h +++ b/scene/gui/range.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/reference_rect.cpp b/scene/gui/reference_rect.cpp index cc38b896d..400ff299a 100644 --- a/scene/gui/reference_rect.cpp +++ b/scene/gui/reference_rect.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/reference_rect.h b/scene/gui/reference_rect.h index b64f47982..b118425eb 100644 --- a/scene/gui/reference_rect.h +++ b/scene/gui/reference_rect.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index eaa2a66a5..42084ade2 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -593,7 +594,7 @@ void RichTextLabel::_update_scroll() { main->first_invalid_line = 0; scroll_w = vscroll->get_combined_minimum_size().width; vscroll->show(); - vscroll->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, scroll_w); + vscroll->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -scroll_w); _validate_line_caches(main); } else { @@ -733,158 +734,155 @@ Control::CursorShape RichTextLabel::get_cursor_shape(const Point2 &p_pos) const return CURSOR_ARROW; } -void RichTextLabel::_gui_input(InputEvent p_event) { +void RichTextLabel::_gui_input(Ref<InputEvent> p_event) { - switch (p_event.type) { + Ref<InputEventMouseButton> b = p_event; - case InputEvent::MOUSE_BUTTON: { - - if (main->first_invalid_line < main->lines.size()) - return; - - const InputEventMouseButton &b = p_event.mouse_button; + if (b.is_valid()) { + if (main->first_invalid_line < main->lines.size()) + return; - if (b.button_index == BUTTON_LEFT) { + if (b->get_button_index() == BUTTON_LEFT) { - if (true) { + if (true) { - if (b.pressed && !b.doubleclick) { - int line = 0; - Item *item = NULL; + if (b->is_pressed() && !b->is_doubleclick()) { + int line = 0; + Item *item = NULL; - bool outside; - _find_click(main, Point2i(b.x, b.y), &item, &line, &outside); + bool outside; + _find_click(main, b->get_position(), &item, &line, &outside); - if (item) { + if (item) { - Variant meta; - if (!outside && _find_meta(item, &meta)) { - //meta clicked + Variant meta; + if (!outside && _find_meta(item, &meta)) { + //meta clicked - emit_signal("meta_clicked", meta); - } else if (selection.enabled) { + emit_signal("meta_clicked", meta); + } else if (selection.enabled) { - selection.click = item; - selection.click_char = line; - } + selection.click = item; + selection.click_char = line; } + } - } else if (!b.pressed) { + } else if (!b->is_pressed()) { - selection.click = NULL; - } + selection.click = NULL; } } + } - if (b.button_index == BUTTON_WHEEL_UP) { + if (b->get_button_index() == BUTTON_WHEEL_UP) { - if (scroll_active) - vscroll->set_value(vscroll->get_value() - vscroll->get_page() / 8); - } - if (b.button_index == BUTTON_WHEEL_DOWN) { + if (scroll_active) - if (scroll_active) - vscroll->set_value(vscroll->get_value() + vscroll->get_page() / 8); - } - } break; - case InputEvent::KEY: { + vscroll->set_value(vscroll->get_value() - vscroll->get_page() * b->get_factor() * 0.5 / 8); + } + if (b->get_button_index() == BUTTON_WHEEL_DOWN) { + + if (scroll_active) - const InputEventKey &k = p_event.key; - if (k.pressed && !k.mod.alt && !k.mod.shift && !k.mod.meta) { - bool handled = true; - switch (k.scancode) { - case KEY_PAGEUP: { + vscroll->set_value(vscroll->get_value() + vscroll->get_page() * b->get_factor() * 0.5 / 8); + } + } - if (vscroll->is_visible_in_tree()) - vscroll->set_value(vscroll->get_value() - vscroll->get_page()); - } break; - case KEY_PAGEDOWN: { + Ref<InputEventKey> k = p_event; - if (vscroll->is_visible_in_tree()) - vscroll->set_value(vscroll->get_value() + vscroll->get_page()); - } break; - case KEY_UP: { + if (k.is_valid()) { + if (k->is_pressed() && !k->get_alt() && !k->get_shift() && !k->get_metakey()) { + bool handled = true; + switch (k->get_scancode()) { + case KEY_PAGEUP: { - if (vscroll->is_visible_in_tree()) - vscroll->set_value(vscroll->get_value() - get_font("normal_font")->get_height()); - } break; - case KEY_DOWN: { + if (vscroll->is_visible_in_tree()) + vscroll->set_value(vscroll->get_value() - vscroll->get_page()); + } break; + case KEY_PAGEDOWN: { - if (vscroll->is_visible_in_tree()) - vscroll->set_value(vscroll->get_value() + get_font("normal_font")->get_height()); - } break; - case KEY_HOME: { + if (vscroll->is_visible_in_tree()) + vscroll->set_value(vscroll->get_value() + vscroll->get_page()); + } break; + case KEY_UP: { - if (vscroll->is_visible_in_tree()) - vscroll->set_value(0); - } break; - case KEY_END: { + if (vscroll->is_visible_in_tree()) + vscroll->set_value(vscroll->get_value() - get_font("normal_font")->get_height()); + } break; + case KEY_DOWN: { - if (vscroll->is_visible_in_tree()) - vscroll->set_value(vscroll->get_max()); - } break; - case KEY_INSERT: - case KEY_C: { + if (vscroll->is_visible_in_tree()) + vscroll->set_value(vscroll->get_value() + get_font("normal_font")->get_height()); + } break; + case KEY_HOME: { - if (k.mod.command) { - selection_copy(); - } else { - handled = false; - } + if (vscroll->is_visible_in_tree()) + vscroll->set_value(0); + } break; + case KEY_END: { - } break; - default: handled = false; - } + if (vscroll->is_visible_in_tree()) + vscroll->set_value(vscroll->get_max()); + } break; + case KEY_INSERT: + case KEY_C: { - if (handled) - accept_event(); + if (k->get_command()) { + selection_copy(); + } else { + handled = false; + } + + } break; + default: handled = false; } - } break; - case InputEvent::MOUSE_MOTION: { + if (handled) + accept_event(); + } + } - if (main->first_invalid_line < main->lines.size()) - return; + Ref<InputEventMouseMotion> m = p_event; - const InputEventMouseMotion &m = p_event.mouse_motion; + if (m.is_valid()) { + if (main->first_invalid_line < main->lines.size()) + return; - if (selection.click) { + if (selection.click) { - int line = 0; - Item *item = NULL; - _find_click(main, Point2i(m.x, m.y), &item, &line); - if (!item) - return; // do not update + int line = 0; + Item *item = NULL; + _find_click(main, m->get_position(), &item, &line); + if (!item) + return; // do not update - selection.from = selection.click; - selection.from_char = selection.click_char; + selection.from = selection.click; + selection.from_char = selection.click_char; - selection.to = item; - selection.to_char = line; + selection.to = item; + selection.to_char = line; - bool swap = false; - if (selection.from->index > selection.to->index) + bool swap = false; + if (selection.from->index > selection.to->index) + swap = true; + else if (selection.from->index == selection.to->index) { + if (selection.from_char > selection.to_char) swap = true; - else if (selection.from->index == selection.to->index) { - if (selection.from_char > selection.to_char) - swap = true; - else if (selection.from_char == selection.to_char) { + else if (selection.from_char == selection.to_char) { - selection.active = false; - return; - } - } - - if (swap) { - SWAP(selection.from, selection.to); - SWAP(selection.from_char, selection.to_char); + selection.active = false; + return; } + } - selection.active = true; - update(); + if (swap) { + SWAP(selection.from, selection.to); + SWAP(selection.from_char, selection.to_char); } - } break; + selection.active = true; + update(); + } } } @@ -1824,15 +1822,40 @@ String RichTextLabel::get_text() { return text; } +void RichTextLabel::set_text(const String &p_string) { + clear(); + add_text(p_string); +} + +void RichTextLabel::set_percent_visible(float p_percent) { + + if (p_percent < 0 || p_percent >= 1) { + + visible_characters = -1; + percent_visible = 1; + + } else { + + visible_characters = get_total_character_count() * p_percent; + percent_visible = p_percent; + } + update(); +} + +float RichTextLabel::get_percent_visible() const { + return percent_visible; +} + void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("_gui_input"), &RichTextLabel::_gui_input); ClassDB::bind_method(D_METHOD("_scroll_changed"), &RichTextLabel::_scroll_changed); ClassDB::bind_method(D_METHOD("get_text"), &RichTextLabel::get_text); ClassDB::bind_method(D_METHOD("add_text", "text"), &RichTextLabel::add_text); - ClassDB::bind_method(D_METHOD("add_image", "image:Texture"), &RichTextLabel::add_image); + ClassDB::bind_method(D_METHOD("set_text", "text"), &RichTextLabel::set_text); + ClassDB::bind_method(D_METHOD("add_image", "image"), &RichTextLabel::add_image); ClassDB::bind_method(D_METHOD("newline"), &RichTextLabel::add_newline); - ClassDB::bind_method(D_METHOD("remove_line"), &RichTextLabel::remove_line); + ClassDB::bind_method(D_METHOD("remove_line", "line"), &RichTextLabel::remove_line); ClassDB::bind_method(D_METHOD("push_font", "font"), &RichTextLabel::push_font); ClassDB::bind_method(D_METHOD("push_color", "color"), &RichTextLabel::push_color); ClassDB::bind_method(D_METHOD("push_align", "align"), &RichTextLabel::push_align); @@ -1875,6 +1898,9 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("set_visible_characters", "amount"), &RichTextLabel::set_visible_characters); ClassDB::bind_method(D_METHOD("get_visible_characters"), &RichTextLabel::get_visible_characters); + ClassDB::bind_method(D_METHOD("set_percent_visible", "percent_visible"), &RichTextLabel::set_percent_visible); + ClassDB::bind_method(D_METHOD("get_percent_visible"), &RichTextLabel::get_percent_visible); + ClassDB::bind_method(D_METHOD("get_total_character_count"), &RichTextLabel::get_total_character_count); ClassDB::bind_method(D_METHOD("set_use_bbcode", "enable"), &RichTextLabel::set_use_bbcode); @@ -1883,7 +1909,9 @@ void RichTextLabel::_bind_methods() { ADD_GROUP("BBCode", "bbcode_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bbcode_enabled"), "set_use_bbcode", "is_using_bbcode"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "bbcode_text", PROPERTY_HINT_MULTILINE_TEXT), "set_bbcode", "get_bbcode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters", PROPERTY_HINT_RANGE, "-1,128000,1"), "set_visible_characters", "get_visible_characters"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "percent_visible", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_percent_visible", "get_percent_visible"); ADD_SIGNAL(MethodInfo("meta_clicked", PropertyInfo(Variant::NIL, "meta"))); @@ -1916,7 +1944,6 @@ void RichTextLabel::set_visible_characters(int p_visible) { } int RichTextLabel::get_visible_characters() const { - return visible_characters; } int RichTextLabel::get_total_character_count() const { @@ -1966,11 +1993,11 @@ RichTextLabel::RichTextLabel() { selection.enabled = false; visible_characters = -1; + percent_visible = 1; set_clip_contents(true); } RichTextLabel::~RichTextLabel() { - memdelete(main); } diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index a5f23d0ba..71fa76695 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -257,6 +258,7 @@ private: Selection selection; int visible_characters; + float percent_visible; void _process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &y, int p_width, int p_line, ProcessMode p_mode, const Ref<Font> &p_base_font, const Color &p_base_color, const Point2i &p_click_pos = Point2i(), Item **r_click_item = NULL, int *r_click_char = NULL, bool *r_outside = NULL, int p_char_count = 0); void _find_click(ItemFrame *p_frame, const Point2i &p_click, Item **r_click_item = NULL, int *r_click_char = NULL, bool *r_outside = NULL); @@ -271,7 +273,7 @@ private: void _update_scroll(); void _scroll_changed(double); - void _gui_input(InputEvent p_event); + void _gui_input(Ref<InputEvent> p_event); Item *_get_next_item(Item *p_item, bool p_free = false); bool use_bbcode; @@ -294,7 +296,7 @@ public: void push_align(Align p_align); void push_indent(int p_level); void push_list(ListType p_list); - void push_meta(const Variant &p_data); + void push_meta(const Variant &p_meta); void push_table(int p_columns); void set_table_column_expand(int p_column, bool p_expand, int p_ratio = 1); int get_current_table_column() const; @@ -339,10 +341,15 @@ public: void set_bbcode(const String &p_bbcode); String get_bbcode() const; + void set_text(const String &p_string); + void set_visible_characters(int p_visible); int get_visible_characters() const; int get_total_character_count() const; + void set_percent_visible(float p_percent); + float get_percent_visible() const; + RichTextLabel(); ~RichTextLabel(); }; diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp index b27104f78..2ccdbb05a 100644 --- a/scene/gui/scroll_bar.cpp +++ b/scene/gui/scroll_bar.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -37,191 +38,188 @@ void ScrollBar::set_can_focus_by_default(bool p_can_focus) { focus_by_default = p_can_focus; } -void ScrollBar::_gui_input(InputEvent p_event) { +void ScrollBar::_gui_input(Ref<InputEvent> p_event) { - switch (p_event.type) { + Ref<InputEventMouseButton> b = p_event; - case InputEvent::MOUSE_BUTTON: { + if (b.is_valid()) { + accept_event(); - const InputEventMouseButton &b = p_event.mouse_button; - accept_event(); - - if (b.button_index == 5 && b.pressed) { - - /* - if (orientation==VERTICAL) - set_val( get_val() + get_page() / 4.0 ); - else - */ - set_value(get_value() + get_page() / 4.0); - accept_event(); - } - - if (b.button_index == 4 && b.pressed) { + if (b->get_button_index() == 5 && b->is_pressed()) { - /* - if (orientation==HORIZONTAL) - set_val( get_val() - get_page() / 4.0 ); - else - */ - set_value(get_value() - get_page() / 4.0); - accept_event(); - } + /* + if (orientation==VERTICAL) + set_val( get_val() + get_page() / 4.0 ); + else + */ + set_value(get_value() + get_page() / 4.0); + accept_event(); + } - if (b.button_index != 1) - return; + if (b->get_button_index() == 4 && b->is_pressed()) { - if (b.pressed) { + /* + if (orientation==HORIZONTAL) + set_val( get_val() - get_page() / 4.0 ); + else + */ + set_value(get_value() - get_page() / 4.0); + accept_event(); + } - double ofs = orientation == VERTICAL ? b.y : b.x; - Ref<Texture> decr = get_icon("decrement"); - Ref<Texture> incr = get_icon("increment"); + if (b->get_button_index() != 1) + return; - double decr_size = orientation == VERTICAL ? decr->get_height() : decr->get_width(); - double incr_size = orientation == VERTICAL ? incr->get_height() : incr->get_width(); - double grabber_ofs = get_grabber_offset(); - double grabber_size = get_grabber_size(); - double total = orientation == VERTICAL ? get_size().height : get_size().width; + if (b->is_pressed()) { - if (ofs < decr_size) { + double ofs = orientation == VERTICAL ? b->get_position().y : b->get_position().x; + Ref<Texture> decr = get_icon("decrement"); + Ref<Texture> incr = get_icon("increment"); - set_value(get_value() - (custom_step >= 0 ? custom_step : get_step())); - break; - } + double decr_size = orientation == VERTICAL ? decr->get_height() : decr->get_width(); + double incr_size = orientation == VERTICAL ? incr->get_height() : incr->get_width(); + double grabber_ofs = get_grabber_offset(); + double grabber_size = get_grabber_size(); + double total = orientation == VERTICAL ? get_size().height : get_size().width; - if (ofs > total - incr_size) { + if (ofs < decr_size) { - set_value(get_value() + (custom_step >= 0 ? custom_step : get_step())); - break; - } + set_value(get_value() - (custom_step >= 0 ? custom_step : get_step())); + return; + } - ofs -= decr_size; + if (ofs > total - incr_size) { - if (ofs < grabber_ofs) { + set_value(get_value() + (custom_step >= 0 ? custom_step : get_step())); + return; + } - set_value(get_value() - get_page()); - break; - } + ofs -= decr_size; - ofs -= grabber_ofs; + if (ofs < grabber_ofs) { - if (ofs < grabber_size) { + set_value(get_value() - get_page()); + return; + } - drag.active = true; - drag.pos_at_click = grabber_ofs + ofs; - drag.value_at_click = get_as_ratio(); - update(); - } else { + ofs -= grabber_ofs; - set_value(get_value() + get_page()); - } + if (ofs < grabber_size) { + drag.active = true; + drag.pos_at_click = grabber_ofs + ofs; + drag.value_at_click = get_as_ratio(); + update(); } else { - drag.active = false; - update(); + set_value(get_value() + get_page()); } - } break; - case InputEvent::MOUSE_MOTION: { + } else { - const InputEventMouseMotion &m = p_event.mouse_motion; + drag.active = false; + update(); + } + } - accept_event(); + Ref<InputEventMouseMotion> m = p_event; - if (drag.active) { + if (m.is_valid()) { - double ofs = orientation == VERTICAL ? m.y : m.x; - Ref<Texture> decr = get_icon("decrement"); + accept_event(); - double decr_size = orientation == VERTICAL ? decr->get_height() : decr->get_width(); - ofs -= decr_size; + if (drag.active) { - double diff = (ofs - drag.pos_at_click) / get_area_size(); + double ofs = orientation == VERTICAL ? m->get_position().y : m->get_position().x; + Ref<Texture> decr = get_icon("decrement"); - set_as_ratio(drag.value_at_click + diff); - } else { + double decr_size = orientation == VERTICAL ? decr->get_height() : decr->get_width(); + ofs -= decr_size; - double ofs = orientation == VERTICAL ? m.y : m.x; - Ref<Texture> decr = get_icon("decrement"); - Ref<Texture> incr = get_icon("increment"); + double diff = (ofs - drag.pos_at_click) / get_area_size(); - double decr_size = orientation == VERTICAL ? decr->get_height() : decr->get_width(); - double incr_size = orientation == VERTICAL ? incr->get_height() : incr->get_width(); - double total = orientation == VERTICAL ? get_size().height : get_size().width; + set_as_ratio(drag.value_at_click + diff); + } else { - HiliteStatus new_hilite; + double ofs = orientation == VERTICAL ? m->get_position().y : m->get_position().x; + Ref<Texture> decr = get_icon("decrement"); + Ref<Texture> incr = get_icon("increment"); - if (ofs < decr_size) { + double decr_size = orientation == VERTICAL ? decr->get_height() : decr->get_width(); + double incr_size = orientation == VERTICAL ? incr->get_height() : incr->get_width(); + double total = orientation == VERTICAL ? get_size().height : get_size().width; - new_hilite = HILITE_DECR; + HighlightStatus new_hilite; - } else if (ofs > total - incr_size) { + if (ofs < decr_size) { - new_hilite = HILITE_INCR; + new_hilite = HIGHLIGHT_DECR; - } else { + } else if (ofs > total - incr_size) { - new_hilite = HILITE_RANGE; - } + new_hilite = HIGHLIGHT_INCR; - if (new_hilite != hilite) { + } else { - hilite = new_hilite; - update(); - } + new_hilite = HIGHLIGHT_RANGE; } - } break; - case InputEvent::KEY: { - const InputEventKey &k = p_event.key; + if (new_hilite != highlight) { - if (!k.pressed) - return; + highlight = new_hilite; + update(); + } + } + } - switch (k.scancode) { + Ref<InputEventKey> k = p_event; - case KEY_LEFT: { + if (k.is_valid()) { - if (orientation != HORIZONTAL) - return; - set_value(get_value() - (custom_step >= 0 ? custom_step : get_step())); + if (!k->is_pressed()) + return; - } break; - case KEY_RIGHT: { + switch (k->get_scancode()) { - if (orientation != HORIZONTAL) - return; - set_value(get_value() + (custom_step >= 0 ? custom_step : get_step())); + case KEY_LEFT: { - } break; - case KEY_UP: { + if (orientation != HORIZONTAL) + return; + set_value(get_value() - (custom_step >= 0 ? custom_step : get_step())); - if (orientation != VERTICAL) - return; + } break; + case KEY_RIGHT: { - set_value(get_value() - (custom_step >= 0 ? custom_step : get_step())); + if (orientation != HORIZONTAL) + return; + set_value(get_value() + (custom_step >= 0 ? custom_step : get_step())); - } break; - case KEY_DOWN: { + } break; + case KEY_UP: { - if (orientation != VERTICAL) - return; - set_value(get_value() + (custom_step >= 0 ? custom_step : get_step())); + if (orientation != VERTICAL) + return; - } break; - case KEY_HOME: { + set_value(get_value() - (custom_step >= 0 ? custom_step : get_step())); - set_value(get_min()); + } break; + case KEY_DOWN: { - } break; - case KEY_END: { + if (orientation != VERTICAL) + return; + set_value(get_value() + (custom_step >= 0 ? custom_step : get_step())); - set_value(get_max()); + } break; + case KEY_HOME: { - } break; - } - break; + set_value(get_min()); + + } break; + case KEY_END: { + + set_value(get_max()); + + } break; } } } @@ -232,10 +230,17 @@ void ScrollBar::_notification(int p_what) { RID ci = get_canvas_item(); - Ref<Texture> decr = hilite == HILITE_DECR ? get_icon("decrement_hilite") : get_icon("decrement"); - Ref<Texture> incr = hilite == HILITE_INCR ? get_icon("increment_hilite") : get_icon("increment"); + Ref<Texture> decr = highlight == HIGHLIGHT_DECR ? get_icon("decrement_highlight") : get_icon("decrement"); + Ref<Texture> incr = highlight == HIGHLIGHT_INCR ? get_icon("increment_highlight") : get_icon("increment"); Ref<StyleBox> bg = has_focus() ? get_stylebox("scroll_focus") : get_stylebox("scroll"); - Ref<StyleBox> grabber = (drag.active || hilite == HILITE_RANGE) ? get_stylebox("grabber_hilite") : get_stylebox("grabber"); + + Ref<StyleBox> grabber; + if (drag.active) + grabber = get_stylebox("grabber_pressed"); + else if (highlight == HIGHLIGHT_RANGE) + grabber = get_stylebox("grabber_highlight"); + else + grabber = get_stylebox("grabber"); Point2 ofs; @@ -269,14 +274,14 @@ void ScrollBar::_notification(int p_what) { grabber_rect.size.width = get_grabber_size(); grabber_rect.size.height = get_size().height; - grabber_rect.pos.y = 0; - grabber_rect.pos.x = get_grabber_offset() + decr->get_width() + bg->get_margin(MARGIN_LEFT); + grabber_rect.position.y = 0; + grabber_rect.position.x = get_grabber_offset() + decr->get_width() + bg->get_margin(MARGIN_LEFT); } else { grabber_rect.size.width = get_size().width; grabber_rect.size.height = get_grabber_size(); - grabber_rect.pos.y = get_grabber_offset() + decr->get_height() + bg->get_margin(MARGIN_TOP); - grabber_rect.pos.x = 0; + grabber_rect.position.y = get_grabber_offset() + decr->get_height() + bg->get_margin(MARGIN_TOP); + grabber_rect.position.x = 0; } grabber->draw(ci, grabber_rect); @@ -385,7 +390,7 @@ void ScrollBar::_notification(int p_what) { if (p_what == NOTIFICATION_MOUSE_EXIT) { - hilite = HILITE_NONE; + highlight = HIGHLIGHT_NONE; update(); } } @@ -521,87 +526,84 @@ void ScrollBar::_drag_slave_exit() { drag_slave = NULL; } -void ScrollBar::_drag_slave_input(const InputEvent &p_input) { - - switch (p_input.type) { +void ScrollBar::_drag_slave_input(const Ref<InputEvent> &p_input) { - case InputEvent::MOUSE_BUTTON: { + Ref<InputEventMouseButton> mb = p_input; - const InputEventMouseButton &mb = p_input.mouse_button; + if (mb.is_valid()) { - if (mb.button_index != 1) - break; + if (mb->get_button_index() != 1) + return; - if (mb.pressed) { + if (mb->is_pressed()) { - if (drag_slave_touching) { - set_fixed_process(false); - drag_slave_touching_deaccel = false; - drag_slave_touching = false; - drag_slave_speed = Vector2(); - drag_slave_accum = Vector2(); - last_drag_slave_accum = Vector2(); - drag_slave_from = Vector2(); - } + if (drag_slave_touching) { + set_fixed_process(false); + drag_slave_touching_deaccel = false; + drag_slave_touching = false; + drag_slave_speed = Vector2(); + drag_slave_accum = Vector2(); + last_drag_slave_accum = Vector2(); + drag_slave_from = Vector2(); + } - if (true) { - drag_slave_speed = Vector2(); - drag_slave_accum = Vector2(); - last_drag_slave_accum = Vector2(); - //drag_slave_from=Vector2(h_scroll->get_val(),v_scroll->get_val()); - drag_slave_from = Vector2(orientation == HORIZONTAL ? get_value() : 0, orientation == VERTICAL ? get_value() : 0); + if (true) { + drag_slave_speed = Vector2(); + drag_slave_accum = Vector2(); + last_drag_slave_accum = Vector2(); + //drag_slave_from=Vector2(h_scroll->get_val(),v_scroll->get_val()); + drag_slave_from = Vector2(orientation == HORIZONTAL ? get_value() : 0, orientation == VERTICAL ? get_value() : 0); - drag_slave_touching = OS::get_singleton()->has_touchscreen_ui_hint(); - drag_slave_touching_deaccel = false; + drag_slave_touching = OS::get_singleton()->has_touchscreen_ui_hint(); + drag_slave_touching_deaccel = false; + time_since_motion = 0; + if (drag_slave_touching) { + set_fixed_process(true); time_since_motion = 0; - if (drag_slave_touching) { - set_fixed_process(true); - time_since_motion = 0; - } } + } - } else { + } else { - if (drag_slave_touching) { + if (drag_slave_touching) { - if (drag_slave_speed == Vector2()) { - drag_slave_touching_deaccel = false; - drag_slave_touching = false; - set_fixed_process(false); - } else { + if (drag_slave_speed == Vector2()) { + drag_slave_touching_deaccel = false; + drag_slave_touching = false; + set_fixed_process(false); + } else { - drag_slave_touching_deaccel = true; - } + drag_slave_touching_deaccel = true; } } - } break; - case InputEvent::MOUSE_MOTION: { + } + } - const InputEventMouseMotion &mm = p_input.mouse_motion; + Ref<InputEventMouseMotion> mm = p_input; - if (drag_slave_touching && !drag_slave_touching_deaccel) { + if (mm.is_valid()) { - Vector2 motion = Vector2(mm.relative_x, mm.relative_y); + if (drag_slave_touching && !drag_slave_touching_deaccel) { - drag_slave_accum -= motion; - Vector2 diff = drag_slave_from + drag_slave_accum; + Vector2 motion = Vector2(mm->get_relative().x, mm->get_relative().y); - if (orientation == HORIZONTAL) - set_value(diff.x); - /* - else - drag_slave_accum.x=0; - */ - if (orientation == VERTICAL) - set_value(diff.y); - /* - else - drag_slave_accum.y=0; - */ - time_since_motion = 0; - } + drag_slave_accum -= motion; + Vector2 diff = drag_slave_from + drag_slave_accum; - } break; + if (orientation == HORIZONTAL) + set_value(diff.x); + /* + else + drag_slave_accum.x=0; + */ + if (orientation == VERTICAL) + set_value(diff.y); + /* + else + drag_slave_accum.y=0; + */ + time_since_motion = 0; + } } } @@ -639,11 +641,11 @@ NodePath ScrollBar::get_drag_slave() const { #if 0 -void ScrollBar::mouse_button(const Point2& p_pos, int b.button_index,bool b.pressed,int p_modifier_mask) { +void ScrollBar::mouse_button(const Point2& p_pos, int b->get_button_index(),bool b->is_pressed(),int p_modifier_mask) { // wheel! - if (b.button_index==BUTTON_WHEEL_UP && b.pressed) { + if (b->get_button_index()==BUTTON_WHEEL_UP && b->is_pressed()) { if (orientation==VERTICAL) set_val( get_val() - get_page() / 4.0 ); @@ -651,7 +653,7 @@ void ScrollBar::mouse_button(const Point2& p_pos, int b.button_index,bool b.pres set_val( get_val() + get_page() / 4.0 ); } - if (b.button_index==BUTTON_WHEEL_DOWN && b.pressed) { + if (b->get_button_index()==BUTTON_WHEEL_DOWN && b->is_pressed()) { if (orientation==HORIZONTAL) set_val( get_val() - get_page() / 4.0 ); @@ -659,10 +661,10 @@ void ScrollBar::mouse_button(const Point2& p_pos, int b.button_index,bool b.pres set_val( get_val() + get_page() / 4.0 ); } - if (b.button_index!=BUTTON_LEFT) + if (b->get_button_index()!=BUTTON_LEFT) return; - if (b.pressed) { + if (b->is_pressed()) { int ofs = orientation==VERTICAL ? p_pos.y : p_pos.x ; int grabber_ofs = get_grabber_offset(); @@ -691,7 +693,7 @@ void ScrollBar::mouse_button(const Point2& p_pos, int b.button_index,bool b.pres } } -void ScrollBar::mouse_motion(const Point2& p_pos, const Point2& p_rel, int b.button_index_mask) { +void ScrollBar::mouse_motion(const Point2& p_pos, const Point2& p_rel, int b->get_button_index()_mask) { if (!drag.active) return; @@ -711,9 +713,9 @@ void ScrollBar::mouse_motion(const Point2& p_pos, const Point2& p_rel, int b.but } -bool ScrollBar::key(unsigned long p_unicode, unsigned long p_scan_code,bool b.pressed,bool p_repeat,int p_modifier_mask) { +bool ScrollBar::key(unsigned long p_unicode, unsigned long p_scan_code,bool b->is_pressed(),bool p_repeat,int p_modifier_mask) { - if (!b.pressed) + if (!b->is_pressed()) return false; switch (p_scan_code) { @@ -783,7 +785,7 @@ void ScrollBar::_bind_methods() { ScrollBar::ScrollBar(Orientation p_orientation) { orientation = p_orientation; - hilite = HILITE_NONE; + highlight = HIGHLIGHT_NONE; custom_step = -1; drag_slave = NULL; diff --git a/scene/gui/scroll_bar.h b/scene/gui/scroll_bar.h index 5227fa45a..8310e1259 100644 --- a/scene/gui/scroll_bar.h +++ b/scene/gui/scroll_bar.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -38,11 +39,11 @@ class ScrollBar : public Range { GDCLASS(ScrollBar, Range); - enum HiliteStatus { - HILITE_NONE, - HILITE_DECR, - HILITE_RANGE, - HILITE_INCR, + enum HighlightStatus { + HIGHLIGHT_NONE, + HIGHLIGHT_DECR, + HIGHLIGHT_RANGE, + HIGHLIGHT_INCR, }; static bool focus_by_default; @@ -51,7 +52,7 @@ class ScrollBar : public Range { Size2 size; float custom_step; - HiliteStatus hilite; + HighlightStatus highlight; struct Drag { @@ -83,9 +84,9 @@ class ScrollBar : public Range { bool click_handled; void _drag_slave_exit(); - void _drag_slave_input(const InputEvent &p_input); + void _drag_slave_input(const Ref<InputEvent> &p_input); - void _gui_input(InputEvent p_event); + void _gui_input(Ref<InputEvent> p_event); protected: void _notification(int p_what); diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index c543b783b..939bdd8d0 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -75,101 +76,109 @@ void ScrollContainer::_cancel_drag() { drag_from = Vector2(); } -void ScrollContainer::_gui_input(const InputEvent &p_gui_input) { +void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) { - switch (p_gui_input.type) { + Ref<InputEventMouseButton> mb = p_gui_input; - case InputEvent::MOUSE_BUTTON: { + if (mb.is_valid()) { - const InputEventMouseButton &mb = p_gui_input.mouse_button; + if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed()) { + // only horizontal is enabled, scroll horizontally + if (h_scroll->is_visible() && !v_scroll->is_visible()) { + h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() / 8 * mb->get_factor()); + } else if (v_scroll->is_visible_in_tree()) { + v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() / 8 * mb->get_factor()); + } + } - if (mb.button_index == BUTTON_WHEEL_UP && mb.pressed) { - if (h_scroll->is_visible_in_tree() && !v_scroll->is_visible_in_tree()) { - // only horizontal is enabled, scroll horizontally - h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() / 8); - } else if (v_scroll->is_visible_in_tree()) { - v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() / 8); - } + if (mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed()) { + // only horizontal is enabled, scroll horizontally + if (h_scroll->is_visible() && !v_scroll->is_visible()) { + h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() / 8 * mb->get_factor()); + } else if (v_scroll->is_visible()) { + v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() / 8 * mb->get_factor()); } + } - if (mb.button_index == BUTTON_WHEEL_DOWN && mb.pressed) { - if (h_scroll->is_visible_in_tree() && !v_scroll->is_visible_in_tree()) { - // only horizontal is enabled, scroll horizontally - h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() / 8); - } else if (v_scroll->is_visible_in_tree()) { - v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() / 8); - } + if (mb->get_button_index() == BUTTON_WHEEL_LEFT && mb->is_pressed()) { + if (h_scroll->is_visible_in_tree()) { + h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * mb->get_factor() / 8); } + } - if (!OS::get_singleton()->has_touchscreen_ui_hint()) - return; + if (mb->get_button_index() == BUTTON_WHEEL_RIGHT && mb->is_pressed()) { + if (h_scroll->is_visible_in_tree()) { + h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * mb->get_factor() / 8); + } + } - if (mb.button_index != BUTTON_LEFT) - break; + if (!OS::get_singleton()->has_touchscreen_ui_hint()) + return; - if (mb.pressed) { + if (mb->get_button_index() != BUTTON_LEFT) + return; - if (drag_touching) { - set_fixed_process(false); - drag_touching_deaccel = false; - drag_touching = false; - drag_speed = Vector2(); - drag_accum = Vector2(); - last_drag_accum = Vector2(); - drag_from = Vector2(); - } + if (mb->is_pressed()) { - if (true) { - drag_speed = Vector2(); - drag_accum = Vector2(); - last_drag_accum = Vector2(); - drag_from = Vector2(h_scroll->get_value(), v_scroll->get_value()); - drag_touching = OS::get_singleton()->has_touchscreen_ui_hint(); - drag_touching_deaccel = false; + if (drag_touching) { + set_fixed_process(false); + drag_touching_deaccel = false; + drag_touching = false; + drag_speed = Vector2(); + drag_accum = Vector2(); + last_drag_accum = Vector2(); + drag_from = Vector2(); + } + + if (true) { + drag_speed = Vector2(); + drag_accum = Vector2(); + last_drag_accum = Vector2(); + drag_from = Vector2(h_scroll->get_value(), v_scroll->get_value()); + drag_touching = OS::get_singleton()->has_touchscreen_ui_hint(); + drag_touching_deaccel = false; + time_since_motion = 0; + if (drag_touching) { + set_fixed_process(true); time_since_motion = 0; - if (drag_touching) { - set_fixed_process(true); - time_since_motion = 0; - } } + } - } else { - if (drag_touching) { + } else { + if (drag_touching) { - if (drag_speed == Vector2()) { - drag_touching_deaccel = false; - drag_touching = false; - set_fixed_process(false); - } else { + if (drag_speed == Vector2()) { + drag_touching_deaccel = false; + drag_touching = false; + set_fixed_process(false); + } else { - drag_touching_deaccel = true; - } + drag_touching_deaccel = true; } } + } + } - } break; - case InputEvent::MOUSE_MOTION: { - - const InputEventMouseMotion &mm = p_gui_input.mouse_motion; + Ref<InputEventMouseMotion> mm = p_gui_input; - if (drag_touching && !drag_touching_deaccel) { + if (mm.is_valid()) { - Vector2 motion = Vector2(mm.relative_x, mm.relative_y); - drag_accum -= motion; - Vector2 diff = drag_from + drag_accum; + if (drag_touching && !drag_touching_deaccel) { - if (scroll_h) - h_scroll->set_value(diff.x); - else - drag_accum.x = 0; - if (scroll_v) - v_scroll->set_value(diff.y); - else - drag_accum.y = 0; - time_since_motion = 0; - } + Vector2 motion = Vector2(mm->get_relative().x, mm->get_relative().y); + drag_accum -= motion; + Vector2 diff = drag_from + drag_accum; - } break; + if (scroll_h) + h_scroll->set_value(diff.x); + else + drag_accum.x = 0; + if (scroll_v) + v_scroll->set_value(diff.y); + else + drag_accum.y = 0; + time_since_motion = 0; + } } } @@ -178,14 +187,14 @@ void ScrollContainer::_update_scrollbar_pos() { Size2 hmin = h_scroll->get_combined_minimum_size(); Size2 vmin = v_scroll->get_combined_minimum_size(); - v_scroll->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, vmin.width); + v_scroll->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -vmin.width); v_scroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0); v_scroll->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 0); v_scroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0); h_scroll->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 0); h_scroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0); - h_scroll->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, hmin.height); + h_scroll->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, -hmin.height); h_scroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0); h_scroll->raise(); @@ -224,14 +233,14 @@ void ScrollContainer::_notification(int p_what) { Rect2 r = Rect2(-scroll, minsize); if (!scroll_h || (!h_scroll->is_visible_in_tree() && c->get_h_size_flags() & SIZE_EXPAND)) { - r.pos.x = 0; + r.position.x = 0; if (c->get_h_size_flags() & SIZE_EXPAND) r.size.width = MAX(size.width, minsize.width); else r.size.width = minsize.width; } if (!scroll_v || (!v_scroll->is_visible_in_tree() && c->get_v_size_flags() & SIZE_EXPAND)) { - r.pos.y = 0; + r.position.y = 0; r.size.height = size.height; if (c->get_v_size_flags() & SIZE_EXPAND) r.size.height = MAX(size.height, minsize.height); diff --git a/scene/gui/scroll_container.h b/scene/gui/scroll_container.h index 07b127843..e5df3e5e1 100644 --- a/scene/gui/scroll_container.h +++ b/scene/gui/scroll_container.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -63,7 +64,7 @@ class ScrollContainer : public Container { protected: Size2 get_minimum_size() const; - void _gui_input(const InputEvent &p_gui_input); + void _gui_input(const Ref<InputEvent> &p_gui_input); void _notification(int p_what); void _scroll_moved(float); diff --git a/scene/gui/separator.cpp b/scene/gui/separator.cpp index e256b8f92..3b00ab460 100644 --- a/scene/gui/separator.cpp +++ b/scene/gui/separator.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/separator.h b/scene/gui/separator.h index 791353174..9a5fe2ac6 100644 --- a/scene/gui/separator.h +++ b/scene/gui/separator.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp index 365d450ed..9ba17ce34 100644 --- a/scene/gui/slider.cpp +++ b/scene/gui/slider.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -36,16 +37,21 @@ Size2 Slider::get_minimum_size() const { return ms; } -void Slider::_gui_input(InputEvent p_event) { +void Slider::_gui_input(Ref<InputEvent> p_event) { - if (p_event.type == InputEvent::MOUSE_BUTTON) { + if (!editable) { + return; + } + + Ref<InputEventMouseButton> mb = p_event; - InputEventMouseButton &mb = p_event.mouse_button; - if (mb.button_index == BUTTON_LEFT) { + if (mb.is_valid()) { + if (mb->get_button_index() == BUTTON_LEFT) { + + if (mb->is_pressed()) { + Ref<Texture> grabber = get_icon(mouse_inside || has_focus() ? "grabber_highlight" : "grabber"); + grab.pos = orientation == VERTICAL ? mb->get_position().y : mb->get_position().x; - if (mb.pressed) { - Ref<Texture> grabber = get_icon(mouse_inside || has_focus() ? "grabber_hilite" : "grabber"); - grab.pos = orientation == VERTICAL ? mb.y : mb.x; double grab_width = (double)grabber->get_size().width; double grab_height = (double)grabber->get_size().height; double max = orientation == VERTICAL ? get_size().height - grab_height : get_size().width - grab_width; @@ -58,20 +64,22 @@ void Slider::_gui_input(InputEvent p_event) { } else { grab.active = false; } - } else if (mb.pressed && mb.button_index == BUTTON_WHEEL_UP) { + } else if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_UP) { set_value(get_value() + get_step()); - } else if (mb.pressed && mb.button_index == BUTTON_WHEEL_DOWN) { + } else if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_DOWN) { set_value(get_value() - get_step()); } + } - } else if (p_event.type == InputEvent::MOUSE_MOTION) { + Ref<InputEventMouseMotion> mm = p_event; + if (mm.is_valid()) { if (grab.active) { Size2i size = get_size(); Ref<Texture> grabber = get_icon("grabber"); - float motion = (orientation == VERTICAL ? p_event.mouse_motion.y : p_event.mouse_motion.x) - grab.pos; + float motion = (orientation == VERTICAL ? mm->get_position().y : mm->get_position().x) - grab.pos; if (orientation == VERTICAL) motion = -motion; float areasize = orientation == VERTICAL ? size.height - grabber->get_size().height : size.width - grabber->get_size().width; @@ -80,42 +88,44 @@ void Slider::_gui_input(InputEvent p_event) { float umotion = motion / float(areasize); set_as_ratio(grab.uvalue + umotion); } - } else { + } + + if (!mm.is_valid() && !mb.is_valid()) { - if (p_event.is_action("ui_left") && p_event.is_pressed()) { + if (p_event->is_action("ui_left") && p_event->is_pressed()) { if (orientation != HORIZONTAL) return; set_value(get_value() - (custom_step >= 0 ? custom_step : get_step())); accept_event(); - } else if (p_event.is_action("ui_right") && p_event.is_pressed()) { + } else if (p_event->is_action("ui_right") && p_event->is_pressed()) { if (orientation != HORIZONTAL) return; set_value(get_value() + (custom_step >= 0 ? custom_step : get_step())); accept_event(); - } else if (p_event.is_action("ui_up") && p_event.is_pressed()) { + } else if (p_event->is_action("ui_up") && p_event->is_pressed()) { if (orientation != VERTICAL) return; set_value(get_value() + (custom_step >= 0 ? custom_step : get_step())); accept_event(); - } else if (p_event.is_action("ui_down") && p_event.is_pressed()) { + } else if (p_event->is_action("ui_down") && p_event->is_pressed()) { if (orientation != VERTICAL) return; set_value(get_value() - (custom_step >= 0 ? custom_step : get_step())); accept_event(); - } else if (p_event.type == InputEvent::KEY) { + } else { - const InputEventKey &k = p_event.key; + Ref<InputEventKey> k = p_event; - if (!k.pressed) + if (!k.is_valid() || !k->is_pressed()) return; - switch (k.scancode) { + switch (k->get_scancode()) { case KEY_HOME: { @@ -128,7 +138,7 @@ void Slider::_gui_input(InputEvent p_event) { accept_event(); } break; - }; + } } } } @@ -152,12 +162,13 @@ void Slider::_notification(int p_what) { Size2i size = get_size(); Ref<StyleBox> style = get_stylebox("slider"); Ref<StyleBox> focus = get_stylebox("focus"); - Ref<Texture> grabber = get_icon(mouse_inside || has_focus() ? "grabber_hilite" : "grabber"); + Ref<Texture> grabber = get_icon(editable ? ((mouse_inside || has_focus()) ? "grabber_highlight" : "grabber") : "grabber_disabled"); Ref<Texture> tick = get_icon("tick"); if (orientation == VERTICAL) { - style->draw(ci, Rect2i(Point2i(), Size2i(style->get_minimum_size().width + style->get_center_size().width, size.height))); + int widget_width = style->get_minimum_size().width + style->get_center_size().width; + style->draw(ci, Rect2i(Point2i(size.width / 2 - widget_width / 2, 0), Size2i(widget_width, size.height))); /* if (mouse_inside||has_focus()) focus->draw(ci,Rect2i(Point2i(),Size2i(style->get_minimum_size().width+style->get_center_size().width,size.height))); @@ -173,7 +184,9 @@ void Slider::_notification(int p_what) { } grabber->draw(ci, Point2i(size.width / 2 - grabber->get_size().width / 2, size.height - get_as_ratio() * areasize - grabber->get_size().height)); } else { - style->draw(ci, Rect2i(Point2i(), Size2i(size.width, style->get_minimum_size().height + style->get_center_size().height))); + + int widget_height = style->get_minimum_size().height + style->get_center_size().height; + style->draw(ci, Rect2i(Point2i(0, size.height / 2 - widget_height / 2), Size2i(size.width, widget_height))); /* if (mouse_inside||has_focus()) focus->draw(ci,Rect2i(Point2i(),Size2i(size.width,style->get_minimum_size().height+style->get_center_size().height))); @@ -225,6 +238,17 @@ void Slider::set_ticks_on_borders(bool _tob) { update(); } +void Slider::set_editable(bool p_editable) { + + editable = p_editable; + update(); +} + +bool Slider::is_editable() const { + + return editable; +} + void Slider::_bind_methods() { ClassDB::bind_method(D_METHOD("_gui_input"), &Slider::_gui_input); @@ -234,6 +258,10 @@ void Slider::_bind_methods() { ClassDB::bind_method(D_METHOD("get_ticks_on_borders"), &Slider::get_ticks_on_borders); ClassDB::bind_method(D_METHOD("set_ticks_on_borders", "ticks_on_border"), &Slider::set_ticks_on_borders); + ClassDB::bind_method(D_METHOD("set_editable", "editable"), &Slider::set_editable); + ClassDB::bind_method(D_METHOD("is_editable"), &Slider::is_editable); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editable"), "set_editable", "is_editable"); ADD_PROPERTY(PropertyInfo(Variant::INT, "tick_count", PROPERTY_HINT_RANGE, "0,4096,1"), "set_ticks", "get_ticks"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ticks_on_borders"), "set_ticks_on_borders", "get_ticks_on_borders"); ADD_PROPERTY(PropertyInfo(Variant::INT, "focus_mode", PROPERTY_HINT_ENUM, "None,Click,All"), "set_focus_mode", "get_focus_mode"); @@ -245,5 +273,6 @@ Slider::Slider(Orientation p_orientation) { grab.active = false; ticks = 0; custom_step = -1; + editable = true; set_focus_mode(FOCUS_ALL); } diff --git a/scene/gui/slider.h b/scene/gui/slider.h index f649a4d15..f3cf3c6f4 100644 --- a/scene/gui/slider.h +++ b/scene/gui/slider.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -45,9 +46,10 @@ class Slider : public Range { bool mouse_inside; Orientation orientation; float custom_step; + bool editable; protected: - void _gui_input(InputEvent p_event); + void _gui_input(Ref<InputEvent> p_event); void _notification(int p_what); static void _bind_methods(); bool ticks_on_borders; @@ -64,6 +66,9 @@ public: void set_ticks_on_borders(bool); bool get_ticks_on_borders() const; + void set_editable(bool p_editable); + bool is_editable() const; + Slider(Orientation p_orientation = VERTICAL); }; diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index 3f21093fb..c5b9df15b 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -64,7 +65,7 @@ LineEdit *SpinBox::get_line_edit() { return line_edit; } -void SpinBox::_line_edit_input(const InputEvent &p_event) { +void SpinBox::_line_edit_input(const Ref<InputEvent> &p_event) { } void SpinBox::_range_click_timeout() { @@ -85,17 +86,19 @@ void SpinBox::_range_click_timeout() { } } -void SpinBox::_gui_input(const InputEvent &p_event) { +void SpinBox::_gui_input(const Ref<InputEvent> &p_event) { if (!is_editable()) { return; } - if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed) { - const InputEventMouseButton &mb = p_event.mouse_button; - bool up = mb.y < (get_size().height / 2); + Ref<InputEventMouseButton> mb = p_event; - switch (mb.button_index) { + if (mb.is_valid() && mb->is_pressed()) { + + bool up = mb->get_position().y < (get_size().height / 2); + + switch (mb->get_button_index()) { case BUTTON_LEFT: { @@ -114,27 +117,29 @@ void SpinBox::_gui_input(const InputEvent &p_event) { } break; case BUTTON_WHEEL_UP: { if (line_edit->has_focus()) { - set_value(get_value() + get_step()); + + set_value(get_value() + get_step() * mb->get_factor()); accept_event(); } } break; case BUTTON_WHEEL_DOWN: { if (line_edit->has_focus()) { - set_value(get_value() - get_step()); + + set_value(get_value() - get_step() * mb->get_factor()); accept_event(); } } break; } } - if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed && p_event.mouse_button.button_index == 1) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == 1) { //set_default_cursor_shape(CURSOR_VSIZE); - Vector2 cpos = Vector2(p_event.mouse_button.x, p_event.mouse_button.y); + Vector2 cpos = Vector2(mb->get_position().x, mb->get_position().y); drag.mouse_pos = cpos; } - if (p_event.type == InputEvent::MOUSE_BUTTON && !p_event.mouse_button.pressed && p_event.mouse_button.button_index == 1) { + if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == 1) { //set_default_cursor_shape(CURSOR_ARROW); range_click_timer->stop(); @@ -146,9 +151,12 @@ void SpinBox::_gui_input(const InputEvent &p_event) { } } - if (p_event.type == InputEvent::MOUSE_MOTION && p_event.mouse_button.button_mask & 1) { + Ref<InputEventMouseMotion> mm = p_event; + + if (mm.is_valid() && mm->get_button_mask() & 1) { + + Vector2 cpos = mm->get_position(); - Vector2 cpos = Vector2(p_event.mouse_motion.x, p_event.mouse_motion.y); if (drag.enabled) { float diff_y = drag.mouse_pos.y - cpos.y; diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h index eba58402f..683ed0c34 100644 --- a/scene/gui/spin_box.h +++ b/scene/gui/spin_box.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -48,7 +49,7 @@ class SpinBox : public Range { String prefix; String suffix; - void _line_edit_input(const InputEvent &p_event); + void _line_edit_input(const Ref<InputEvent> &p_event); struct Drag { float base_val; @@ -61,7 +62,7 @@ class SpinBox : public Range { void _line_edit_focus_exit(); protected: - void _gui_input(const InputEvent &p_event); + void _gui_input(const Ref<InputEvent> &p_event); void _notification(int p_what); diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp index 5b6f17e0f..e3dad0880 100644 --- a/scene/gui/split_container.cpp +++ b/scene/gui/split_container.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -130,7 +131,12 @@ void SplitContainer::_resort() { if (ratiomode) { - middle_sep = ms_first[axis] + available / 2; + int first_ratio = first->get_stretch_ratio(); + int second_ratio = second->get_stretch_ratio(); + + float ratio = float(first_ratio) / (first_ratio + second_ratio); + + middle_sep = ms_first[axis] + available * ratio; } else if (expand_first_mode) { @@ -143,12 +149,17 @@ void SplitContainer::_resort() { } else if (ratiomode) { - if (expand_ofs < -(available / 2)) - expand_ofs = -(available / 2); - else if (expand_ofs > (available / 2)) - expand_ofs = (available / 2); + int first_ratio = first->get_stretch_ratio(); + int second_ratio = second->get_stretch_ratio(); + + float ratio = float(first_ratio) / (first_ratio + second_ratio); + + if (expand_ofs < -(available * ratio)) + expand_ofs = -(available * ratio); + else if (expand_ofs > (available * (1.0 - ratio))) + expand_ofs = (available * (1.0 - ratio)); - middle_sep = ms_first[axis] + available / 2 + expand_ofs; + middle_sep = ms_first[axis] + available * ratio + expand_ofs; } else if (expand_first_mode) { @@ -185,7 +196,7 @@ void SplitContainer::_resort() { } update(); - _change_notify("split/offset"); + _change_notify("split_offset"); } Size2 SplitContainer::get_minimum_size() const { @@ -269,32 +280,32 @@ void SplitContainer::_notification(int p_what) { } } -void SplitContainer::_gui_input(const InputEvent &p_event) { +void SplitContainer::_gui_input(const Ref<InputEvent> &p_event) { if (collapsed || !_getch(0) || !_getch(1) || dragger_visibility != DRAGGER_VISIBLE) return; - if (p_event.type == InputEvent::MOUSE_BUTTON) { + Ref<InputEventMouseButton> mb = p_event; - const InputEventMouseButton &mb = p_event.mouse_button; + if (mb.is_valid()) { - if (mb.button_index == BUTTON_LEFT) { + if (mb->get_button_index() == BUTTON_LEFT) { - if (mb.pressed) { + if (mb->is_pressed()) { int sep = get_constant("separation"); if (vertical) { - if (mb.y > middle_sep && mb.y < middle_sep + sep) { + if (mb->get_position().y > middle_sep && mb->get_position().y < middle_sep + sep) { dragging = true; - drag_from = mb.y; + drag_from = mb->get_position().y; drag_ofs = expand_ofs; } } else { - if (mb.x > middle_sep && mb.x < middle_sep + sep) { + if (mb->get_position().x > middle_sep && mb->get_position().x < middle_sep + sep) { dragging = true; - drag_from = mb.x; + drag_from = mb->get_position().x; drag_ofs = expand_ofs; } } @@ -305,13 +316,13 @@ void SplitContainer::_gui_input(const InputEvent &p_event) { } } - if (p_event.type == InputEvent::MOUSE_MOTION) { + Ref<InputEventMouseMotion> mm = p_event; - const InputEventMouseMotion &mm = p_event.mouse_motion; + if (mm.is_valid()) { if (dragging) { - expand_ofs = drag_ofs + ((vertical ? mm.y : mm.x) - drag_from); + expand_ofs = drag_ofs + ((vertical ? mm->get_position().y : mm->get_position().x) - drag_from); queue_sort(); emit_signal("dragged", get_split_offset()); } diff --git a/scene/gui/split_container.h b/scene/gui/split_container.h index 8db6bfa65..87a210f24 100644 --- a/scene/gui/split_container.h +++ b/scene/gui/split_container.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,7 +34,7 @@ class SplitContainer : public Container { - GDCLASS(SplitContainer, Container); + GDCLASS(SplitContainer, Container) public: enum DraggerVisibility { @@ -58,7 +59,7 @@ private: void _resort(); protected: - void _gui_input(const InputEvent &p_event); + void _gui_input(const Ref<InputEvent> &p_event); void _notification(int p_what); static void _bind_methods(); diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 89769937d..1352569f3 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -62,11 +63,13 @@ int TabContainer::_get_top_margin() const { return tab_height + content_height; } -void TabContainer::_gui_input(const InputEvent &p_event) { +void TabContainer::_gui_input(const Ref<InputEvent> &p_event) { - if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed && p_event.mouse_button.button_index == BUTTON_LEFT) { + Ref<InputEventMouseButton> mb = p_event; - Point2 pos(p_event.mouse_button.x, p_event.mouse_button.y); + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + + Point2 pos(mb->get_position().x, mb->get_position().y); Size2 size = get_size(); // Click must be on tabs in the tab header area. @@ -78,11 +81,11 @@ void TabContainer::_gui_input(const InputEvent &p_event) { if (popup && pos.x > size.width - menu->get_width()) { emit_signal("pre_popup_pressed"); - Vector2 popup_pos = get_global_pos(); + Vector2 popup_pos = get_global_position(); popup_pos.x += size.width - popup->get_size().width; popup_pos.y += menu->get_height(); - popup->set_global_pos(popup_pos); + popup->set_global_position(popup_pos); popup->popup(); return; } @@ -230,7 +233,7 @@ void TabContainer::_notification(int p_what) { Control *control = tabs[i + first_tab_cache]->cast_to<Control>(); String text = control->has_meta("_tab_name") ? String(XL_MESSAGE(String(control->get_meta("_tab_name")))) : String(control->get_name()); - int x_content = tab_rect.pos.x + tab_style->get_margin(MARGIN_LEFT); + int x_content = tab_rect.position.x + tab_style->get_margin(MARGIN_LEFT); int top_margin = tab_style->get_margin(MARGIN_TOP); int y_center = top_margin + (tab_rect.size.y - tab_style->get_minimum_size().y) / 2; @@ -368,8 +371,10 @@ void TabContainer::add_child_notify(Node *p_child) { if (tabs_visible) c->set_margin(MARGIN_TOP, _get_top_margin()); Ref<StyleBox> sb = get_stylebox("panel"); - for (int i = 0; i < 4; i++) - c->set_margin(Margin(i), c->get_margin(Margin(i)) + sb->get_margin(Margin(i))); + c->set_margin(Margin(MARGIN_TOP), c->get_margin(Margin(MARGIN_TOP)) + sb->get_margin(Margin(MARGIN_TOP))); + c->set_margin(Margin(MARGIN_LEFT), c->get_margin(Margin(MARGIN_LEFT)) + sb->get_margin(Margin(MARGIN_LEFT))); + c->set_margin(Margin(MARGIN_RIGHT), c->get_margin(Margin(MARGIN_RIGHT)) - sb->get_margin(Margin(MARGIN_RIGHT))); + c->set_margin(Margin(MARGIN_BOTTOM), c->get_margin(Margin(MARGIN_BOTTOM)) - sb->get_margin(Margin(MARGIN_BOTTOM))); update(); p_child->connect("renamed", this, "_child_renamed_callback"); @@ -399,8 +404,10 @@ void TabContainer::set_current_tab(int p_current) { c->set_area_as_parent_rect(); if (tabs_visible) c->set_margin(MARGIN_TOP, _get_top_margin()); - for (int i = 0; i < 4; i++) - c->set_margin(Margin(i), c->get_margin(Margin(i)) + sb->get_margin(Margin(i))); + c->set_margin(Margin(MARGIN_TOP), c->get_margin(Margin(MARGIN_TOP)) + sb->get_margin(Margin(MARGIN_TOP))); + c->set_margin(Margin(MARGIN_LEFT), c->get_margin(Margin(MARGIN_LEFT)) + sb->get_margin(Margin(MARGIN_LEFT))); + c->set_margin(Margin(MARGIN_RIGHT), c->get_margin(Margin(MARGIN_RIGHT)) - sb->get_margin(Margin(MARGIN_RIGHT))); + c->set_margin(Margin(MARGIN_BOTTOM), c->get_margin(Margin(MARGIN_BOTTOM)) - sb->get_margin(Margin(MARGIN_BOTTOM))); } else c->hide(); @@ -541,11 +548,11 @@ Ref<Texture> TabContainer::get_tab_icon(int p_tab) const { return Ref<Texture>(); } -void TabContainer::set_tab_disabled(int p_tab, bool p_enabled) { +void TabContainer::set_tab_disabled(int p_tab, bool p_disabled) { Control *child = _get_tab(p_tab); ERR_FAIL_COND(!child); - child->set_meta("_tab_disabled", p_enabled); + child->set_meta("_tab_disabled", p_disabled); update(); } @@ -624,20 +631,20 @@ void TabContainer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_current_tab", "tab_idx"), &TabContainer::set_current_tab); ClassDB::bind_method(D_METHOD("get_current_tab"), &TabContainer::get_current_tab); ClassDB::bind_method(D_METHOD("get_previous_tab"), &TabContainer::get_previous_tab); - ClassDB::bind_method(D_METHOD("get_current_tab_control:Control"), &TabContainer::get_current_tab_control); - ClassDB::bind_method(D_METHOD("get_tab_control:Control", "idx"), &TabContainer::get_tab_control); + ClassDB::bind_method(D_METHOD("get_current_tab_control"), &TabContainer::get_current_tab_control); + ClassDB::bind_method(D_METHOD("get_tab_control", "idx"), &TabContainer::get_tab_control); ClassDB::bind_method(D_METHOD("set_tab_align", "align"), &TabContainer::set_tab_align); ClassDB::bind_method(D_METHOD("get_tab_align"), &TabContainer::get_tab_align); ClassDB::bind_method(D_METHOD("set_tabs_visible", "visible"), &TabContainer::set_tabs_visible); ClassDB::bind_method(D_METHOD("are_tabs_visible"), &TabContainer::are_tabs_visible); ClassDB::bind_method(D_METHOD("set_tab_title", "tab_idx", "title"), &TabContainer::set_tab_title); ClassDB::bind_method(D_METHOD("get_tab_title", "tab_idx"), &TabContainer::get_tab_title); - ClassDB::bind_method(D_METHOD("set_tab_icon", "tab_idx", "icon:Texture"), &TabContainer::set_tab_icon); - ClassDB::bind_method(D_METHOD("get_tab_icon:Texture", "tab_idx"), &TabContainer::get_tab_icon); + ClassDB::bind_method(D_METHOD("set_tab_icon", "tab_idx", "icon"), &TabContainer::set_tab_icon); + ClassDB::bind_method(D_METHOD("get_tab_icon", "tab_idx"), &TabContainer::get_tab_icon); ClassDB::bind_method(D_METHOD("set_tab_disabled", "tab_idx", "disabled"), &TabContainer::set_tab_disabled); ClassDB::bind_method(D_METHOD("get_tab_disabled", "tab_idx"), &TabContainer::get_tab_disabled); - ClassDB::bind_method(D_METHOD("set_popup", "popup:Popup"), &TabContainer::set_popup); - ClassDB::bind_method(D_METHOD("get_popup:Popup"), &TabContainer::get_popup); + ClassDB::bind_method(D_METHOD("set_popup", "popup"), &TabContainer::set_popup); + ClassDB::bind_method(D_METHOD("get_popup"), &TabContainer::get_popup); ClassDB::bind_method(D_METHOD("_child_renamed_callback"), &TabContainer::_child_renamed_callback); @@ -661,4 +668,4 @@ TabContainer::TabContainer() { align = ALIGN_CENTER; tabs_visible = true; popup = NULL; -}
\ No newline at end of file +} diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h index 259461184..3e1a2c159 100644 --- a/scene/gui/tab_container.h +++ b/scene/gui/tab_container.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -53,7 +54,7 @@ private: bool tabs_visible; bool buttons_visible_cache; TabAlign align; - Control *_get_tab(int idx) const; + Control *_get_tab(int p_idx) const; int _get_top_margin() const; Popup *popup; @@ -62,7 +63,7 @@ private: protected: void _child_renamed_callback(); - void _gui_input(const InputEvent &p_event); + void _gui_input(const Ref<InputEvent> &p_event); void _notification(int p_what); virtual void add_child_notify(Node *p_child); virtual void remove_child_notify(Node *p_child); diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp index 319755387..acffbbc49 100644 --- a/scene/gui/tabs.cpp +++ b/scene/gui/tabs.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -78,13 +79,15 @@ Size2 Tabs::get_minimum_size() const { return ms; } -void Tabs::_gui_input(const InputEvent &p_event) { +void Tabs::_gui_input(const Ref<InputEvent> &p_event) { - if (p_event.type == InputEvent::MOUSE_MOTION) { + Ref<InputEventMouseMotion> mm = p_event; - Point2 pos(p_event.mouse_motion.x, p_event.mouse_motion.y); + if (mm.is_valid()) { - hilite_arrow = -1; + Point2 pos = mm->get_position(); + + highlight_arrow = -1; if (buttons_visible) { Ref<Texture> incr = get_icon("increment"); @@ -93,20 +96,24 @@ void Tabs::_gui_input(const InputEvent &p_event) { int limit = get_size().width - incr->get_width() - decr->get_width(); if (pos.x > limit + decr->get_width()) { - hilite_arrow = 1; + highlight_arrow = 1; } else if (pos.x > limit) { - hilite_arrow = 0; + highlight_arrow = 0; } } // test hovering to display right or close button + int hover_now = -1; int hover_buttons = -1; - hover = -1; for (int i = 0; i < tabs.size(); i++) { if (i < offset) continue; + Rect2 rect = get_tab_rect(i); + if (rect.has_point(pos)) { + hover_now = i; + } if (tabs[i].rb_rect.has_point(pos)) { rb_hover = i; cb_hover = -1; @@ -119,6 +126,10 @@ void Tabs::_gui_input(const InputEvent &p_event) { break; } } + if (hover != hover_now) { + hover = hover_now; + emit_signal("tab_hover", hover); + } if (hover_buttons == -1) { // no hover rb_hover = hover_buttons; @@ -129,9 +140,11 @@ void Tabs::_gui_input(const InputEvent &p_event) { return; } - if (rb_pressing && p_event.type == InputEvent::MOUSE_BUTTON && - !p_event.mouse_button.pressed && - p_event.mouse_button.button_index == BUTTON_LEFT) { + Ref<InputEventMouseButton> mb = p_event; + + if (rb_pressing && mb.is_valid() && + !mb->is_pressed() && + mb->get_button_index() == BUTTON_LEFT) { if (rb_hover != -1) { //pressed @@ -142,9 +155,9 @@ void Tabs::_gui_input(const InputEvent &p_event) { update(); } - if (cb_pressing && p_event.type == InputEvent::MOUSE_BUTTON && - !p_event.mouse_button.pressed && - p_event.mouse_button.button_index == BUTTON_LEFT) { + if (cb_pressing && mb.is_valid() && + !mb->is_pressed() && + mb->get_button_index() == BUTTON_LEFT) { if (cb_hover != -1) { //pressed @@ -155,12 +168,12 @@ void Tabs::_gui_input(const InputEvent &p_event) { update(); } - if (p_event.type == InputEvent::MOUSE_BUTTON && - p_event.mouse_button.pressed && - p_event.mouse_button.button_index == BUTTON_LEFT) { + if (mb.is_valid() && + mb->is_pressed() && + mb->get_button_index() == BUTTON_LEFT) { // clicks - Point2 pos(p_event.mouse_button.x, p_event.mouse_button.y); + Point2 pos(mb->get_position().x, mb->get_position().y); if (buttons_visible) { @@ -213,7 +226,7 @@ void Tabs::_gui_input(const InputEvent &p_event) { if (found != -1) { set_current_tab(found); - emit_signal("tab_changed", found); + emit_signal("tab_clicked", found); } } } @@ -229,11 +242,13 @@ void Tabs::_notification(int p_what) { update(); } break; case NOTIFICATION_RESIZED: { - + _update_cache(); _ensure_no_over_offset(); + ensure_tab_visible(current); + } break; case NOTIFICATION_DRAW: { - + _update_cache(); RID ci = get_canvas_item(); Ref<StyleBox> tab_bg = get_stylebox("tab_bg"); @@ -267,8 +282,8 @@ void Tabs::_notification(int p_what) { Ref<Texture> incr = get_icon("increment"); Ref<Texture> decr = get_icon("decrement"); - Ref<Texture> incr_hl = get_icon("increment_hilite"); - Ref<Texture> decr_hl = get_icon("decrement_hilite"); + Ref<Texture> incr_hl = get_icon("increment_highlight"); + Ref<Texture> decr_hl = get_icon("decrement_highlight"); int limit = get_size().width - incr->get_size().width - decr->get_size().width; @@ -281,18 +296,7 @@ void Tabs::_notification(int p_what) { tabs[i].ofs_cache = w; - int lsize = get_tab_width(i); - - String text = tabs[i].text; - int slen = font->get_string_size(text).width; - - if (w + lsize > limit) { - max_drawn_tab = i - 1; - missing_right = true; - break; - } else { - max_drawn_tab = i; - } + int lsize = tabs[i].size_cache; Ref<StyleBox> sb; Color col; @@ -308,7 +312,15 @@ void Tabs::_notification(int p_what) { col = color_bg; } - Rect2 sb_rect = Rect2(w, 0, lsize, h); + if (w + lsize > limit) { + max_drawn_tab = i - 1; + missing_right = true; + break; + } else { + max_drawn_tab = i; + } + + Rect2 sb_rect = Rect2(w, 0, tabs[i].size_cache, h); sb->draw(ci, sb_rect); w += sb->get_margin(MARGIN_LEFT); @@ -318,13 +330,13 @@ void Tabs::_notification(int p_what) { if (icon.is_valid()) { icon->draw(ci, Point2i(w, sb->get_margin(MARGIN_TOP) + ((sb_rect.size.y - sb_ms.y) - icon->get_height()) / 2)); - if (text != "") + if (tabs[i].text != "") w += icon->get_width() + get_constant("hseparation"); } - font->draw(ci, Point2i(w, sb->get_margin(MARGIN_TOP) + ((sb_rect.size.y - sb_ms.y) - font->get_height()) / 2 + font->get_ascent()), text, col); + font->draw(ci, Point2i(w, sb->get_margin(MARGIN_TOP) + ((sb_rect.size.y - sb_ms.y) - font->get_height()) / 2 + font->get_ascent()), tabs[i].text, col, tabs[i].size_text); - w += slen; + w += tabs[i].size_text; if (tabs[i].right_button.is_valid()) { @@ -335,8 +347,8 @@ void Tabs::_notification(int p_what) { Rect2 rb_rect; rb_rect.size = style->get_minimum_size() + rb->get_size(); - rb_rect.pos.x = w; - rb_rect.pos.y = sb->get_margin(MARGIN_TOP) + ((sb_rect.size.y - sb_ms.y) - (rb_rect.size.y)) / 2; + rb_rect.position.x = w; + rb_rect.position.y = sb->get_margin(MARGIN_TOP) + ((sb_rect.size.y - sb_ms.y) - (rb_rect.size.y)) / 2; if (rb_hover == i) { if (rb_pressing) @@ -345,7 +357,7 @@ void Tabs::_notification(int p_what) { style->draw(ci, rb_rect); } - rb->draw(ci, Point2i(w + style->get_margin(MARGIN_LEFT), rb_rect.pos.y + style->get_margin(MARGIN_TOP))); + rb->draw(ci, Point2i(w + style->get_margin(MARGIN_LEFT), rb_rect.position.y + style->get_margin(MARGIN_TOP))); w += rb->get_width(); tabs[i].rb_rect = rb_rect; } @@ -359,8 +371,8 @@ void Tabs::_notification(int p_what) { Rect2 cb_rect; cb_rect.size = style->get_minimum_size() + cb->get_size(); - cb_rect.pos.x = w; - cb_rect.pos.y = sb->get_margin(MARGIN_TOP) + ((sb_rect.size.y - sb_ms.y) - (cb_rect.size.y)) / 2; + cb_rect.position.x = w; + cb_rect.position.y = sb->get_margin(MARGIN_TOP) + ((sb_rect.size.y - sb_ms.y) - (cb_rect.size.y)) / 2; if (!tabs[i].disabled && cb_hover == i) { if (cb_pressing) @@ -369,14 +381,12 @@ void Tabs::_notification(int p_what) { style->draw(ci, cb_rect); } - cb->draw(ci, Point2i(w + style->get_margin(MARGIN_LEFT), cb_rect.pos.y + style->get_margin(MARGIN_TOP))); + cb->draw(ci, Point2i(w + style->get_margin(MARGIN_LEFT), cb_rect.position.y + style->get_margin(MARGIN_TOP))); w += cb->get_width(); tabs[i].cb_rect = cb_rect; } w += sb->get_margin(MARGIN_RIGHT); - - tabs[i].size_cache = w - tabs[i].ofs_cache; } if (offset > 0 || missing_right) { @@ -384,12 +394,12 @@ void Tabs::_notification(int p_what) { int vofs = (get_size().height - incr->get_size().height) / 2; if (offset > 0) - draw_texture(hilite_arrow == 0 ? decr_hl : decr, Point2(limit, vofs)); + draw_texture(highlight_arrow == 0 ? decr_hl : decr, Point2(limit, vofs)); else draw_texture(decr, Point2(limit, vofs), Color(1, 1, 1, 0.5)); if (missing_right) - draw_texture(hilite_arrow == 1 ? incr_hl : incr, Point2(limit + decr->get_size().width, vofs)); + draw_texture(highlight_arrow == 1 ? incr_hl : incr, Point2(limit + decr->get_size().width, vofs)); else draw_texture(incr, Point2(limit + decr->get_size().width, vofs), Color(1, 1, 1, 0.5)); @@ -409,12 +419,16 @@ int Tabs::get_tab_count() const { void Tabs::set_current_tab(int p_current) { + if (current == p_current) return; ERR_FAIL_INDEX(p_current, get_tab_count()); current = p_current; _change_notify("current_tab"); + _update_cache(); update(); + + emit_signal("tab_changed", p_current); } int Tabs::get_current_tab() const { @@ -422,6 +436,10 @@ int Tabs::get_current_tab() const { return current; } +int Tabs::get_hovered_tab() const { + return hover; +} + void Tabs::set_tab_title(int p_tab, const String &p_title) { ERR_FAIL_INDEX(p_tab, tabs.size()); @@ -475,15 +493,81 @@ Ref<Texture> Tabs::get_tab_right_button(int p_tab) const { return tabs[p_tab].right_button; } +void Tabs::_update_cache() { + Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled"); + Ref<StyleBox> tab_bg = get_stylebox("tab_bg"); + Ref<StyleBox> tab_fg = get_stylebox("tab_fg"); + Ref<Font> font = get_font("font"); + Ref<Texture> incr = get_icon("increment"); + Ref<Texture> decr = get_icon("decrement"); + int limit = get_size().width - incr->get_width() - decr->get_width(); + + int w = 0; + int mw = 0; + int size_fixed = 0; + int count_resize = 0; + for (int i = 0; i < tabs.size(); i++) { + tabs[i].ofs_cache = mw; + tabs[i].size_cache = get_tab_width(i); + tabs[i].size_text = font->get_string_size(tabs[i].text).width; + mw += tabs[i].size_cache; + if (tabs[i].size_cache <= min_width || i == current) { + size_fixed += tabs[i].size_cache; + } else { + count_resize++; + } + } + int m_width = min_width; + if (count_resize > 0) { + m_width = MAX((limit - size_fixed) / count_resize, min_width); + } + for (int i = 0; i < tabs.size(); i++) { + if (i < offset) + continue; + Ref<StyleBox> sb; + if (tabs[i].disabled) { + sb = tab_disabled; + } else if (i == current) { + sb = tab_fg; + } else { + sb = tab_bg; + } + int lsize = tabs[i].size_cache; + int slen = tabs[i].size_text; + if (min_width > 0 && mw > limit && i != current) { + if (lsize > m_width) { + slen = m_width - (sb->get_margin(MARGIN_LEFT) + sb->get_margin(MARGIN_RIGHT)); + if (tabs[i].icon.is_valid()) { + slen -= tabs[i].icon->get_width(); + slen -= get_constant("hseparation"); + } + if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i == current)) { + Ref<Texture> cb = get_icon("close"); + slen -= cb->get_width(); + slen -= get_constant("hseparation"); + } + slen = MAX(slen, 1); + lsize = m_width; + } + } + tabs[i].ofs_cache = w; + tabs[i].size_cache = lsize; + tabs[i].size_text = slen; + w += lsize; + } +} + void Tabs::add_tab(const String &p_str, const Ref<Texture> &p_icon) { Tab t; t.text = p_str; t.icon = p_icon; t.disabled = false; + t.ofs_cache = 0; + t.size_cache = 0; tabs.push_back(t); - + _update_cache(); update(); minimum_size_changed(); } @@ -500,6 +584,7 @@ void Tabs::remove_tab(int p_idx) { tabs.remove(p_idx); if (current >= p_idx) current--; + _update_cache(); update(); minimum_size_changed(); @@ -511,8 +596,44 @@ void Tabs::remove_tab(int p_idx) { _ensure_no_over_offset(); } +Variant Tabs::get_drag_data(const Point2 &p_point) { + + return get_tab_idx_at_point(p_point); +} + +bool Tabs::can_drop_data(const Point2 &p_point, const Variant &p_data) const { + + return get_tab_idx_at_point(p_point) > -1; +} + +void Tabs::drop_data(const Point2 &p_point, const Variant &p_data) { + + int hover_now = get_tab_idx_at_point(p_point); + + ERR_FAIL_INDEX(hover_now, tabs.size()); + emit_signal("reposition_active_tab_request", hover_now); +} + +int Tabs::get_tab_idx_at_point(const Point2 &p_point) const { + + int hover_now = -1; + for (int i = 0; i < tabs.size(); i++) { + + if (i < offset) + continue; + + Rect2 rect = get_tab_rect(i); + if (rect.has_point(p_point)) { + hover_now = i; + } + } + + return hover_now; +} + void Tabs::set_tab_align(TabAlign p_align) { + ERR_FAIL_INDEX(p_align, ALIGN_MAX); tab_align = p_align; update(); } @@ -522,6 +643,22 @@ Tabs::TabAlign Tabs::get_tab_align() const { return tab_align; } +void Tabs::move_tab(int from, int to) { + + if (from == to) + return; + + ERR_FAIL_INDEX(from, tabs.size()); + ERR_FAIL_INDEX(to, tabs.size()); + + Tab tab_from = tabs[from]; + tabs.remove(from); + tabs.insert(to, tab_from); + + _update_cache(); + update(); +} + int Tabs::get_tab_width(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, tabs.size(), 0); @@ -582,7 +719,7 @@ void Tabs::_ensure_no_over_offset() { if (i < offset - 1) continue; - total_w += get_tab_width(i); + total_w += tabs[i].size_cache; } if (total_w < limit) { @@ -599,44 +736,53 @@ void Tabs::ensure_tab_visible(int p_idx) { if (!is_inside_tree()) return; + if (tabs.size() == 0) return; ERR_FAIL_INDEX(p_idx, tabs.size()); - _ensure_no_over_offset(); - - if (p_idx <= offset) { + if (p_idx == offset) { + return; + } + if (p_idx < offset) { offset = p_idx; update(); return; } + int prev_offset = offset; Ref<Texture> incr = get_icon("increment"); Ref<Texture> decr = get_icon("decrement"); int limit = get_size().width - incr->get_width() - decr->get_width(); - - int x = 0; - for (int i = 0; i < tabs.size(); i++) { - - if (i < offset) - continue; - - int sz = get_tab_width(i); - tabs[i].x_cache = x; - tabs[i].x_size_cache = sz; - x += sz; + for (int i = offset; i <= p_idx; i++) { + if (tabs[i].ofs_cache + tabs[i].size_cache > limit) { + offset++; + } } - while (offset < tabs.size() && ((tabs[p_idx].x_cache + tabs[p_idx].x_size_cache) - tabs[offset].x_cache) > limit) { - offset++; + if (prev_offset != offset) { + update(); } +} - update(); +Rect2 Tabs::get_tab_rect(int p_tab) const { + return Rect2(tabs[p_tab].ofs_cache, 0, tabs[p_tab].size_cache, get_size().height); } void Tabs::set_tab_close_display_policy(CloseButtonDisplayPolicy p_policy) { + + ERR_FAIL_INDEX(p_policy, CLOSE_BUTTON_MAX); cb_displaypolicy = p_policy; update(); } +Tabs::CloseButtonDisplayPolicy Tabs::get_tab_close_display_policy() const { + + return cb_displaypolicy; +} + +void Tabs::set_min_width(int p_width) { + min_width = p_width; +} + void Tabs::_bind_methods() { ClassDB::bind_method(D_METHOD("_gui_input"), &Tabs::_gui_input); @@ -645,29 +791,39 @@ void Tabs::_bind_methods() { ClassDB::bind_method(D_METHOD("get_current_tab"), &Tabs::get_current_tab); ClassDB::bind_method(D_METHOD("set_tab_title", "tab_idx", "title"), &Tabs::set_tab_title); ClassDB::bind_method(D_METHOD("get_tab_title", "tab_idx"), &Tabs::get_tab_title); - ClassDB::bind_method(D_METHOD("set_tab_icon", "tab_idx", "icon:Texture"), &Tabs::set_tab_icon); - ClassDB::bind_method(D_METHOD("get_tab_icon:Texture", "tab_idx"), &Tabs::get_tab_icon); + ClassDB::bind_method(D_METHOD("set_tab_icon", "tab_idx", "icon"), &Tabs::set_tab_icon); + ClassDB::bind_method(D_METHOD("get_tab_icon", "tab_idx"), &Tabs::get_tab_icon); ClassDB::bind_method(D_METHOD("set_tab_disabled", "tab_idx", "disabled"), &Tabs::set_tab_disabled); ClassDB::bind_method(D_METHOD("get_tab_disabled", "tab_idx"), &Tabs::get_tab_disabled); ClassDB::bind_method(D_METHOD("remove_tab", "tab_idx"), &Tabs::remove_tab); - ClassDB::bind_method(D_METHOD("add_tab", "title", "icon:Texture"), &Tabs::add_tab); + ClassDB::bind_method(D_METHOD("add_tab", "title", "icon"), &Tabs::add_tab, DEFVAL(""), DEFVAL(Ref<Texture>())); ClassDB::bind_method(D_METHOD("set_tab_align", "align"), &Tabs::set_tab_align); ClassDB::bind_method(D_METHOD("get_tab_align"), &Tabs::get_tab_align); ClassDB::bind_method(D_METHOD("ensure_tab_visible", "idx"), &Tabs::ensure_tab_visible); + ClassDB::bind_method(D_METHOD("get_tab_rect", "tab_idx"), &Tabs::get_tab_rect); + ClassDB::bind_method(D_METHOD("move_tab", "from", "to"), &Tabs::move_tab); + ClassDB::bind_method(D_METHOD("set_tab_close_display_policy", "policy"), &Tabs::set_tab_close_display_policy); + ClassDB::bind_method(D_METHOD("get_tab_close_display_policy"), &Tabs::get_tab_close_display_policy); ADD_SIGNAL(MethodInfo("tab_changed", PropertyInfo(Variant::INT, "tab"))); ADD_SIGNAL(MethodInfo("right_button_pressed", PropertyInfo(Variant::INT, "tab"))); ADD_SIGNAL(MethodInfo("tab_close", PropertyInfo(Variant::INT, "tab"))); + ADD_SIGNAL(MethodInfo("tab_hover", PropertyInfo(Variant::INT, "tab"))); + ADD_SIGNAL(MethodInfo("reposition_active_tab_request", PropertyInfo(Variant::INT, "idx_to"))); + ADD_SIGNAL(MethodInfo("tab_clicked", PropertyInfo(Variant::INT, "tab"))); ADD_PROPERTY(PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE, "-1,4096,1", PROPERTY_USAGE_EDITOR), "set_current_tab", "get_current_tab"); + ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "tab_close_display_policy", PROPERTY_HINT_ENUM, "Show Never,Show Active Only,Show Always"), "set_tab_close_display_policy", "get_tab_close_display_policy"); BIND_CONSTANT(ALIGN_LEFT); BIND_CONSTANT(ALIGN_CENTER); BIND_CONSTANT(ALIGN_RIGHT); + BIND_CONSTANT(ALIGN_MAX); BIND_CONSTANT(CLOSE_BUTTON_SHOW_ACTIVE_ONLY); BIND_CONSTANT(CLOSE_BUTTON_SHOW_ALWAYS); BIND_CONSTANT(CLOSE_BUTTON_SHOW_NEVER); + BIND_CONSTANT(CLOSE_BUTTON_MAX); } Tabs::Tabs() { @@ -676,11 +832,13 @@ Tabs::Tabs() { tab_align = ALIGN_CENTER; rb_hover = -1; rb_pressing = false; - hilite_arrow = -1; + highlight_arrow = -1; cb_hover = -1; cb_pressing = false; cb_displaypolicy = CLOSE_BUTTON_SHOW_NEVER; offset = 0; max_drawn_tab = 0; + + min_width = 0; } diff --git a/scene/gui/tabs.h b/scene/gui/tabs.h index 39811f13c..86ad128dc 100644 --- a/scene/gui/tabs.h +++ b/scene/gui/tabs.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -40,7 +41,8 @@ public: ALIGN_LEFT, ALIGN_CENTER, - ALIGN_RIGHT + ALIGN_RIGHT, + ALIGN_MAX }; enum CloseButtonDisplayPolicy { @@ -48,6 +50,7 @@ public: CLOSE_BUTTON_SHOW_NEVER, CLOSE_BUTTON_SHOW_ACTIVE_ONLY, CLOSE_BUTTON_SHOW_ALWAYS, + CLOSE_BUTTON_MAX }; private: @@ -58,6 +61,7 @@ private: int ofs_cache; bool disabled; int size_cache; + int size_text; int x_cache; int x_size_cache; @@ -68,12 +72,11 @@ private: int offset; int max_drawn_tab; - int hilite_arrow; + int highlight_arrow; bool buttons_visible; bool missing_right; Vector<Tab> tabs; int current; - Control *_get_tab(int idx) const; int _get_top_margin() const; TabAlign tab_align; int rb_hover; @@ -84,15 +87,22 @@ private: CloseButtonDisplayPolicy cb_displaypolicy; int hover; // hovered tab + int min_width; int get_tab_width(int p_idx) const; void _ensure_no_over_offset(); + void _update_cache(); protected: - void _gui_input(const InputEvent &p_event); + void _gui_input(const Ref<InputEvent> &p_event); void _notification(int p_what); static void _bind_methods(); + Variant get_drag_data(const Point2 &p_point); + bool can_drop_data(const Point2 &p_point, const Variant &p_data) const; + void drop_data(const Point2 &p_point, const Variant &p_data); + int get_tab_idx_at_point(const Point2 &p_point) const; + public: void add_tab(const String &p_str = "", const Ref<Texture> &p_icon = Ref<Texture>()); @@ -111,23 +121,30 @@ public: void set_tab_align(TabAlign p_align); TabAlign get_tab_align() const; + void move_tab(int from, int to); + void set_tab_close_display_policy(CloseButtonDisplayPolicy p_policy); + CloseButtonDisplayPolicy get_tab_close_display_policy() const; int get_tab_count() const; void set_current_tab(int p_current); int get_current_tab() const; + int get_hovered_tab() const; void remove_tab(int p_idx); void clear_tabs(); void ensure_tab_visible(int p_idx); + void set_min_width(int p_width); + Rect2 get_tab_rect(int p_tab) const; Size2 get_minimum_size() const; Tabs(); }; VARIANT_ENUM_CAST(Tabs::TabAlign); +VARIANT_ENUM_CAST(Tabs::CloseButtonDisplayPolicy); #endif // TABS_H diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 3b7ad910d..2b47539c4 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,8 +33,8 @@ #include "os/keyboard.h" #include "os/os.h" -#include "global_config.h" #include "message_queue.h" +#include "project_settings.h" #include "scene/main/viewport.h" #define TAB_PIXELS @@ -48,6 +49,10 @@ static bool _is_symbol(CharType c) { return c != '_' && ((c >= '!' && c <= '/') || (c >= ':' && c <= '@') || (c >= '[' && c <= '`') || (c >= '{' && c <= '~') || c == '\t' || c == ' '); } +static bool _is_whitespace(CharType c) { + return c == '\t' || c == ' '; +} + static bool _is_char(CharType c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; @@ -100,15 +105,15 @@ void TextEdit::Text::set_font(const Ref<Font> &p_font) { font = p_font; } -void TextEdit::Text::set_tab_size(int p_tab_size) { +void TextEdit::Text::set_indent_size(int p_indent_size) { - tab_size = p_tab_size; + indent_size = p_indent_size; } void TextEdit::Text::_update_line_cache(int p_line) const { int w = 0; - int tab_w = font->get_char_size(' ').width * tab_size; + int tab_w = font->get_char_size(' ').width * indent_size; int len = text[p_line].data.length(); const CharType *str = text[p_line].data.c_str(); @@ -333,7 +338,10 @@ void TextEdit::_update_scrollbars() { v_scroll->show(); v_scroll->set_max(total_rows); v_scroll->set_page(visible_rows); - v_scroll->set_value(cursor.line_ofs); + + if (fabs(v_scroll->get_value() - (double)cursor.line_ofs) >= 1) { + v_scroll->set_value(cursor.line_ofs); + } } else { cursor.line_ofs = 0; @@ -345,7 +353,9 @@ void TextEdit::_update_scrollbars() { h_scroll->show(); h_scroll->set_max(total_width); h_scroll->set_page(visible_width); - h_scroll->set_value(cursor.x_ofs); + if (fabs(h_scroll->get_value() - (double)cursor.x_ofs) >= 1) { + h_scroll->set_value(cursor.x_ofs); + } } else { @@ -359,7 +369,7 @@ void TextEdit::_click_selection_held() { if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT) && selection.selecting_mode != Selection::MODE_NONE) { - Point2 mp = Input::get_singleton()->get_mouse_pos() - get_global_pos(); + Point2 mp = Input::get_singleton()->get_mouse_position() - get_global_position(); int row, col; _get_mouse_pos(Point2i(mp.x, mp.y), row, col); @@ -455,7 +465,7 @@ void TextEdit::_notification(int p_what) { int visible_rows = get_visible_rows(); - int tab_w = cache.font->get_char_size(' ').width * tab_size; + int tab_w = cache.font->get_char_size(' ').width * indent_size; Color color = cache.font_color; int in_region = -1; @@ -812,8 +822,8 @@ void TextEdit::_notification(int p_what) { keyword_color = *col; } - if (select_identifiers_enabled && hilighted_word != String()) { - if (hilighted_word == range) { + if (select_identifiers_enabled && highlighted_word != String()) { + if (highlighted_word == range) { underlined = true; } } @@ -977,13 +987,41 @@ void TextEdit::_notification(int p_what) { } int caret_w = (str[j] == '\t') ? cache.font->get_char_size(' ').width : char_w; - if (draw_caret) { - if (insert_mode) { - int caret_h = (block_caret) ? 4 : 1; - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(caret_w, caret_h)), cache.caret_color); - } else { - caret_w = (block_caret) ? caret_w : 1; - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(caret_w, get_row_height())), cache.caret_color); + if (ime_text.length() > 0) { + int ofs = 0; + while (true) { + if (ofs >= ime_text.length()) + break; + + CharType cchar = ime_text[ofs]; + CharType next = ime_text[ofs + 1]; + int im_char_width = cache.font->get_char_size(cchar, next).width; + + if ((char_ofs + char_margin + im_char_width) >= xmargin_end) + break; + + bool selected = ofs >= ime_selection.x && ofs < ime_selection.x + ime_selection.y; + if (selected) { + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(char_ofs + char_margin, ofs_y + get_row_height()), Size2(im_char_width, 3)), color); + } else { + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(char_ofs + char_margin, ofs_y + get_row_height()), Size2(im_char_width, 1)), color); + } + + cache.font->draw_char(ci, Point2(char_ofs + char_margin, ofs_y + ascent), cchar, next, color); + + char_ofs += im_char_width; + ofs++; + } + } + if (ime_text.length() == 0) { + if (draw_caret) { + if (insert_mode) { + int caret_h = (block_caret) ? 4 : 1; + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(caret_w, caret_h)), cache.caret_color); + } else { + caret_w = (block_caret) ? caret_w : 1; + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(caret_w, get_row_height())), cache.caret_color); + } } } } @@ -1014,16 +1052,43 @@ void TextEdit::_notification(int p_what) { if (insert_mode) { cursor_pos.y += (get_row_height() - 3); } + if (ime_text.length() > 0) { + int ofs = 0; + while (true) { + if (ofs >= ime_text.length()) + break; - if (draw_caret) { - if (insert_mode) { - int char_w = cache.font->get_char_size(' ').width; - int caret_h = (block_caret) ? 4 : 1; - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(char_w, caret_h)), cache.caret_color); - } else { - int char_w = cache.font->get_char_size(' ').width; - int caret_w = (block_caret) ? char_w : 1; - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(caret_w, get_row_height())), cache.caret_color); + CharType cchar = ime_text[ofs]; + CharType next = ime_text[ofs + 1]; + int im_char_width = cache.font->get_char_size(cchar, next).width; + + if ((char_ofs + char_margin + im_char_width) >= xmargin_end) + break; + + bool selected = ofs >= ime_selection.x && ofs < ime_selection.x + ime_selection.y; + if (selected) { + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(char_ofs + char_margin, ofs_y + get_row_height()), Size2(im_char_width, 3)), color); + } else { + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(char_ofs + char_margin, ofs_y + get_row_height()), Size2(im_char_width, 1)), color); + } + + cache.font->draw_char(ci, Point2(char_ofs + char_margin, ofs_y + ascent), cchar, next, color); + + char_ofs += im_char_width; + ofs++; + } + } + if (ime_text.length() == 0) { + if (draw_caret) { + if (insert_mode) { + int char_w = cache.font->get_char_size(' ').width; + int caret_h = (block_caret) ? 4 : 1; + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(char_w, caret_h)), cache.caret_color); + } else { + int char_w = cache.font->get_char_size(' ').width; + int caret_w = (block_caret) ? char_w : 1; + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(caret_w, get_row_height())), cache.caret_color); + } } } } @@ -1063,16 +1128,16 @@ void TextEdit::_notification(int p_what) { int th = h + csb->get_minimum_size().y; if (cursor_pos.y + get_row_height() + th > get_size().height) { - completion_rect.pos.y = cursor_pos.y - th; + completion_rect.position.y = cursor_pos.y - th; } else { - completion_rect.pos.y = cursor_pos.y + get_row_height() + csb->get_offset().y; + completion_rect.position.y = cursor_pos.y + get_row_height() + csb->get_offset().y; completion_below = true; } if (cursor_pos.x - nofs + w + scrollw > get_size().width) { - completion_rect.pos.x = get_size().width - w - scrollw; + completion_rect.position.x = get_size().width - w - scrollw; } else { - completion_rect.pos.x = cursor_pos.x - nofs; + completion_rect.position.x = cursor_pos.x - nofs; } completion_rect.size.width = w + 2; @@ -1080,14 +1145,14 @@ void TextEdit::_notification(int p_what) { if (completion_options.size() <= maxlines) scrollw = 0; - draw_style_box(csb, Rect2(completion_rect.pos - csb->get_offset(), completion_rect.size + csb->get_minimum_size() + Size2(scrollw, 0))); + draw_style_box(csb, Rect2(completion_rect.position - csb->get_offset(), completion_rect.size + csb->get_minimum_size() + Size2(scrollw, 0))); if (cache.completion_background_color.a > 0.01) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(completion_rect.pos, completion_rect.size + Size2(scrollw, 0)), cache.completion_background_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(completion_rect.position, completion_rect.size + Size2(scrollw, 0)), cache.completion_background_color); } int line_from = CLAMP(completion_index - lines / 2, 0, completion_options.size() - lines); - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(completion_rect.pos.x, completion_rect.pos.y + (completion_index - line_from) * get_row_height()), Size2(completion_rect.size.width, get_row_height())), cache.completion_selected_color); - draw_rect(Rect2(completion_rect.pos, Size2(nofs, completion_rect.size.height)), cache.completion_existing_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(completion_rect.position.x, completion_rect.position.y + (completion_index - line_from) * get_row_height()), Size2(completion_rect.size.width, get_row_height())), cache.completion_selected_color); + draw_rect(Rect2(completion_rect.position, Size2(nofs, completion_rect.size.height)), cache.completion_existing_color); for (int i = 0; i < lines; i++) { @@ -1099,14 +1164,14 @@ void TextEdit::_notification(int p_what) { text_color = color_regions[j].color; } } - draw_string(cache.font, Point2(completion_rect.pos.x, completion_rect.pos.y + i * get_row_height() + cache.font->get_ascent()), completion_options[l], text_color, completion_rect.size.width); + draw_string(cache.font, Point2(completion_rect.position.x, completion_rect.position.y + i * get_row_height() + cache.font->get_ascent()), completion_options[l], text_color, completion_rect.size.width); } if (scrollw) { //draw a small scroll rectangle to show a position in the options float r = maxlines / (float)completion_options.size(); float o = line_from / (float)completion_options.size(); - draw_rect(Rect2(completion_rect.pos.x + completion_rect.size.width, completion_rect.pos.y + o * completion_rect.size.y, scrollw, completion_rect.size.y * r), scrollc); + draw_rect(Rect2(completion_rect.position.x + completion_rect.size.width, completion_rect.position.y + o * completion_rect.size.y, scrollw, completion_rect.size.y * r), scrollc); } completion_line_ofs = line_from; @@ -1185,12 +1250,21 @@ void TextEdit::_notification(int p_what) { } } + if (has_focus()) { + OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos + Point2(0, get_row_height())); + OS::get_singleton()->set_ime_intermediate_text_callback(_ime_text_callback, this); + } } break; case NOTIFICATION_FOCUS_ENTER: { if (!caret_blink_enabled) { draw_caret = true; } + + Point2 cursor_pos = Point2(cursor_get_column(), cursor_get_line()) * get_row_height(); + OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos); + OS::get_singleton()->set_ime_intermediate_text_callback(_ime_text_callback, this); + if (OS::get_singleton()->has_virtual_keyboard()) OS::get_singleton()->show_virtual_keyboard(get_text(), get_global_rect()); if (raised_from_completion) { @@ -1200,6 +1274,11 @@ void TextEdit::_notification(int p_what) { } break; case NOTIFICATION_FOCUS_EXIT: { + OS::get_singleton()->set_ime_position(Point2()); + OS::get_singleton()->set_ime_intermediate_text_callback(NULL, NULL); + ime_text = ""; + ime_selection = Point2(); + if (OS::get_singleton()->has_virtual_keyboard()) OS::get_singleton()->hide_virtual_keyboard(); if (raised_from_completion) { @@ -1209,6 +1288,13 @@ void TextEdit::_notification(int p_what) { } } +void TextEdit::_ime_text_callback(void *p_self, String p_text, Point2 p_selection) { + TextEdit *self = (TextEdit *)p_self; + self->ime_text = p_text; + self->ime_selection = p_selection; + self->update(); +} + void TextEdit::_consume_pair_symbol(CharType ch) { int cursor_position_to_move = cursor_get_column() + 1; @@ -1304,7 +1390,38 @@ void TextEdit::backspace_at_cursor() { _is_pair_left_symbol(text[cursor.line][cursor.column - 1])) { _consume_backspace_for_pair_symbol(prev_line, prev_column); } else { - _remove_text(prev_line, prev_column, cursor.line, cursor.column); + // handle space indentation + if (cursor.column - indent_size >= 0 && indent_using_spaces) { + + // if there is enough spaces to count as a tab + bool unindent = true; + for (int i = 1; i <= indent_size; i++) { + if (text[cursor.line][cursor.column - i] != ' ') { + unindent = false; + break; + } + } + + // and it is before the first character + int i = 0; + while (i < cursor.column && i < text[cursor.line].length()) { + if (text[cursor.line][i] != ' ' && text[cursor.line][i] != '\t') { + unindent = false; + break; + } + i++; + } + + // then we can remove it as a single character. + if (unindent) { + _remove_text(cursor.line, cursor.column - indent_size, cursor.line, cursor.column); + prev_column = cursor.column - indent_size; + } else { + _remove_text(prev_line, prev_column, cursor.line, cursor.column); + } + } else { + _remove_text(prev_line, prev_column, cursor.line, cursor.column); + } } cursor_set_line(prev_line); @@ -1327,7 +1444,11 @@ void TextEdit::indent_selection_right() { for (int i = start_line; i <= end_line; i++) { String line_text = get_line(i); - line_text = '\t' + line_text; + if (indent_using_spaces) { + line_text = space_indent + line_text; + } else { + line_text = '\t' + line_text; + } set_line(i, line_text); } @@ -1358,8 +1479,8 @@ void TextEdit::indent_selection_left() { if (line_text.begins_with("\t")) { line_text = line_text.substr(1, line_text.length()); set_line(i, line_text); - } else if (line_text.begins_with(" ")) { - line_text = line_text.substr(4, line_text.length()); + } else if (line_text.begins_with(space_indent)) { + line_text = line_text.substr(indent_size, line_text.length()); set_line(i, line_text); } } @@ -1399,1227 +1520,1262 @@ void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) co r_col = col; } -void TextEdit::_gui_input(const InputEvent &p_gui_input) { +void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { - switch (p_gui_input.type) { + Ref<InputEventMouseButton> mb = p_gui_input; - case InputEvent::MOUSE_BUTTON: { + if (mb.is_valid()) { + if (completion_active && completion_rect.has_point(mb->get_position())) { - const InputEventMouseButton &mb = p_gui_input.mouse_button; - - if (completion_active && completion_rect.has_point(Point2(mb.x, mb.y))) { - - if (!mb.pressed) - return; + if (!mb->is_pressed()) + return; - if (mb.button_index == BUTTON_WHEEL_UP) { - if (completion_index > 0) { - completion_index--; - completion_current = completion_options[completion_index]; - update(); - } + if (mb->get_button_index() == BUTTON_WHEEL_UP) { + if (completion_index > 0) { + completion_index--; + completion_current = completion_options[completion_index]; + update(); } - if (mb.button_index == BUTTON_WHEEL_DOWN) { + } + if (mb->get_button_index() == BUTTON_WHEEL_DOWN) { - if (completion_index < completion_options.size() - 1) { - completion_index++; - completion_current = completion_options[completion_index]; - update(); - } + if (completion_index < completion_options.size() - 1) { + completion_index++; + completion_current = completion_options[completion_index]; + update(); } + } - if (mb.button_index == BUTTON_LEFT) { + if (mb->get_button_index() == BUTTON_LEFT) { - completion_index = CLAMP(completion_line_ofs + (mb.y - completion_rect.pos.y) / get_row_height(), 0, completion_options.size() - 1); + completion_index = CLAMP(completion_line_ofs + (mb->get_position().y - completion_rect.position.y) / get_row_height(), 0, completion_options.size() - 1); - completion_current = completion_options[completion_index]; - update(); - if (mb.doubleclick) - _confirm_completion(); - } - return; - } else { - _cancel_completion(); - _cancel_code_hint(); + completion_current = completion_options[completion_index]; + update(); + if (mb->is_doubleclick()) + _confirm_completion(); } + return; + } else { + _cancel_completion(); + _cancel_code_hint(); + } - if (mb.pressed) { - if (mb.button_index == BUTTON_WHEEL_UP && !mb.mod.command) { - v_scroll->set_value(v_scroll->get_value() - 3); - } - if (mb.button_index == BUTTON_WHEEL_DOWN && !mb.mod.command) { - v_scroll->set_value(v_scroll->get_value() + 3); - } - if (mb.button_index == BUTTON_WHEEL_LEFT) { - h_scroll->set_value(h_scroll->get_value() - 3); - } - if (mb.button_index == BUTTON_WHEEL_RIGHT) { - h_scroll->set_value(h_scroll->get_value() + 3); - } - if (mb.button_index == BUTTON_LEFT) { + if (mb->is_pressed()) { - _reset_caret_blink_timer(); + if (mb->get_button_index() == BUTTON_WHEEL_UP && !mb->get_command()) { + v_scroll->set_value(v_scroll->get_value() - (3 * mb->get_factor())); + } + if (mb->get_button_index() == BUTTON_WHEEL_DOWN && !mb->get_command()) { + v_scroll->set_value(v_scroll->get_value() + (3 * mb->get_factor())); + } + if (mb->get_button_index() == BUTTON_WHEEL_LEFT) { + h_scroll->set_value(h_scroll->get_value() - (100 * mb->get_factor())); + } + if (mb->get_button_index() == BUTTON_WHEEL_RIGHT) { + h_scroll->set_value(h_scroll->get_value() + (100 * mb->get_factor())); + } + if (mb->get_button_index() == BUTTON_LEFT) { + + _reset_caret_blink_timer(); + + int row, col; + _get_mouse_pos(Point2i(mb->get_position().x, mb->get_position().y), row, col); - int row, col; - _get_mouse_pos(Point2i(mb.x, mb.y), row, col); + if (mb->get_command() && highlighted_word != String()) { - if (mb.mod.command && hilighted_word != String()) { + emit_signal("symbol_lookup", highlighted_word, row, col); + return; + } - emit_signal("symbol_lookup", hilighted_word, row, col); + // toggle breakpoint on gutter click + if (draw_breakpoint_gutter) { + int gutter = cache.style_normal->get_margin(MARGIN_LEFT); + if (mb->get_position().x > gutter && mb->get_position().x <= gutter + cache.breakpoint_gutter_width + 3) { + set_line_as_breakpoint(row, !is_line_set_as_breakpoint(row)); + emit_signal("breakpoint_toggled", row); return; } + } - // toggle breakpoint on gutter click - if (draw_breakpoint_gutter) { - int gutter = cache.style_normal->get_margin(MARGIN_LEFT); - if (mb.x > gutter && mb.x <= gutter + cache.breakpoint_gutter_width + 3) { - set_line_as_breakpoint(row, !is_line_set_as_breakpoint(row)); - emit_signal("breakpoint_toggled", row); - return; - } - } + int prev_col = cursor.column; + int prev_line = cursor.line; - int prev_col = cursor.column; - int prev_line = cursor.line; + cursor_set_line(row); + cursor_set_column(col); - cursor_set_line(row); - cursor_set_column(col); + if (mb->get_shift() && (cursor.column != prev_col || cursor.line != prev_line)) { - if (mb.mod.shift && (cursor.column != prev_col || cursor.line != prev_line)) { + if (!selection.active) { + selection.active = true; + selection.selecting_mode = Selection::MODE_POINTER; + selection.from_column = prev_col; + selection.from_line = prev_line; + selection.to_column = cursor.column; + selection.to_line = cursor.line; - if (!selection.active) { - selection.active = true; - selection.selecting_mode = Selection::MODE_POINTER; - selection.from_column = prev_col; - selection.from_line = prev_line; - selection.to_column = cursor.column; - selection.to_line = cursor.line; + if (selection.from_line > selection.to_line || (selection.from_line == selection.to_line && selection.from_column > selection.to_column)) { + SWAP(selection.from_column, selection.to_column); + SWAP(selection.from_line, selection.to_line); + selection.shiftclick_left = false; + } else { + selection.shiftclick_left = true; + } + selection.selecting_line = prev_line; + selection.selecting_column = prev_col; + update(); + } else { + + if (cursor.line < selection.selecting_line || (cursor.line == selection.selecting_line && cursor.column < selection.selecting_column)) { - if (selection.from_line > selection.to_line || (selection.from_line == selection.to_line && selection.from_column > selection.to_column)) { + if (selection.shiftclick_left) { SWAP(selection.from_column, selection.to_column); SWAP(selection.from_line, selection.to_line); - selection.shiftclick_left = false; - } else { - selection.shiftclick_left = true; + selection.shiftclick_left = !selection.shiftclick_left; } - selection.selecting_line = prev_line; - selection.selecting_column = prev_col; - update(); - } else { - - if (cursor.line < selection.selecting_line || (cursor.line == selection.selecting_line && cursor.column < selection.selecting_column)) { - - if (selection.shiftclick_left) { - SWAP(selection.from_column, selection.to_column); - SWAP(selection.from_line, selection.to_line); - selection.shiftclick_left = !selection.shiftclick_left; - } - selection.from_column = cursor.column; - selection.from_line = cursor.line; + selection.from_column = cursor.column; + selection.from_line = cursor.line; - } else if (cursor.line > selection.selecting_line || (cursor.line == selection.selecting_line && cursor.column > selection.selecting_column)) { + } else if (cursor.line > selection.selecting_line || (cursor.line == selection.selecting_line && cursor.column > selection.selecting_column)) { - if (!selection.shiftclick_left) { - SWAP(selection.from_column, selection.to_column); - SWAP(selection.from_line, selection.to_line); - selection.shiftclick_left = !selection.shiftclick_left; - } - selection.to_column = cursor.column; - selection.to_line = cursor.line; - - } else { - selection.active = false; + if (!selection.shiftclick_left) { + SWAP(selection.from_column, selection.to_column); + SWAP(selection.from_line, selection.to_line); + selection.shiftclick_left = !selection.shiftclick_left; } + selection.to_column = cursor.column; + selection.to_line = cursor.line; - update(); + } else { + selection.active = false; } - } else { - - //if sel active and dblick last time < something - - //else - selection.active = false; - selection.selecting_mode = Selection::MODE_POINTER; - selection.selecting_line = row; - selection.selecting_column = col; + update(); } - if (!mb.doubleclick && (OS::get_singleton()->get_ticks_msec() - last_dblclk) < 600 && cursor.line == prev_line) { - //tripleclick select line - select(cursor.line, 0, cursor.line, text[cursor.line].length()); - selection.selecting_column = 0; - last_dblclk = 0; + } else { - } else if (mb.doubleclick && text[cursor.line].length()) { + //if sel active and dblick last time < something - //doubleclick select world - String s = text[cursor.line]; - int beg = CLAMP(cursor.column, 0, s.length()); - int end = beg; + //else + selection.active = false; + selection.selecting_mode = Selection::MODE_POINTER; + selection.selecting_line = row; + selection.selecting_column = col; + } - if (s[beg] > 32 || beg == s.length()) { + if (!mb->is_doubleclick() && (OS::get_singleton()->get_ticks_msec() - last_dblclk) < 600 && cursor.line == prev_line) { + //tripleclick select line + select(cursor.line, 0, cursor.line, text[cursor.line].length()); + selection.selecting_column = 0; + last_dblclk = 0; - bool symbol = beg < s.length() && _is_symbol(s[beg]); //not sure if right but most editors behave like this + } else if (mb->is_doubleclick() && text[cursor.line].length()) { - while (beg > 0 && s[beg - 1] > 32 && (symbol == _is_symbol(s[beg - 1]))) { - beg--; - } - while (end < s.length() && s[end + 1] > 32 && (symbol == _is_symbol(s[end + 1]))) { - end++; - } + //doubleclick select world + String s = text[cursor.line]; + int beg = CLAMP(cursor.column, 0, s.length()); + int end = beg; - if (end < s.length()) - end += 1; + if (s[beg] > 32 || beg == s.length()) { - select(cursor.line, beg, cursor.line, end); + bool symbol = beg < s.length() && _is_symbol(s[beg]); //not sure if right but most editors behave like this - selection.selecting_column = beg; + while (beg > 0 && s[beg - 1] > 32 && (symbol == _is_symbol(s[beg - 1]))) { + beg--; + } + while (end < s.length() && s[end + 1] > 32 && (symbol == _is_symbol(s[end + 1]))) { + end++; } - last_dblclk = OS::get_singleton()->get_ticks_msec(); - } + if (end < s.length()) + end += 1; - update(); - } + select(cursor.line, beg, cursor.line, end); - if (mb.button_index == BUTTON_RIGHT && context_menu_enabled) { + selection.selecting_column = beg; + } - menu->set_pos(get_global_transform().xform(get_local_mouse_pos())); - menu->set_size(Vector2(1, 1)); - menu->popup(); - grab_focus(); + last_dblclk = OS::get_singleton()->get_ticks_msec(); } - } else { - if (mb.button_index == BUTTON_LEFT) - click_select_held->stop(); + update(); + } + + if (mb->get_button_index() == BUTTON_RIGHT && context_menu_enabled) { - // notify to show soft keyboard - notification(NOTIFICATION_FOCUS_ENTER); + menu->set_position(get_global_transform().xform(get_local_mouse_pos())); + menu->set_size(Vector2(1, 1)); + menu->popup(); + grab_focus(); } + } else { - } break; - case InputEvent::MOUSE_MOTION: { + if (mb->get_button_index() == BUTTON_LEFT) + click_select_held->stop(); - const InputEventMouseMotion &mm = p_gui_input.mouse_motion; + // notify to show soft keyboard + notification(NOTIFICATION_FOCUS_ENTER); + } + } - if (select_identifiers_enabled) { - if (mm.mod.command && mm.button_mask == 0) { + Ref<InputEventMouseMotion> mm = p_gui_input; - String new_word = get_word_at_pos(Vector2(mm.x, mm.y)); - if (new_word != hilighted_word) { - hilighted_word = new_word; - update(); - } - } else { - if (hilighted_word != String()) { - hilighted_word = String(); - update(); - } + if (mm.is_valid()) { + + if (select_identifiers_enabled) { + if (mm->get_command() && mm->get_button_mask() == 0) { + + String new_word = get_word_at_pos(mm->get_position()); + if (new_word != highlighted_word) { + highlighted_word = new_word; + update(); + } + } else { + if (highlighted_word != String()) { + highlighted_word = String(); + update(); } } + } - if (mm.button_mask & BUTTON_MASK_LEFT && get_viewport()->gui_get_drag_data() == Variant()) { //ignore if dragging + if (mm->get_button_mask() & BUTTON_MASK_LEFT && get_viewport()->gui_get_drag_data() == Variant()) { //ignore if dragging - if (selection.selecting_mode != Selection::MODE_NONE) { + if (selection.selecting_mode != Selection::MODE_NONE) { - _reset_caret_blink_timer(); + _reset_caret_blink_timer(); - int row, col; - _get_mouse_pos(Point2i(mm.x, mm.y), row, col); + int row, col; + _get_mouse_pos(mm->get_position(), row, col); - select(selection.selecting_line, selection.selecting_column, row, col); + select(selection.selecting_line, selection.selecting_column, row, col); - cursor_set_line(row); - cursor_set_column(col); - update(); + cursor_set_line(row); + cursor_set_column(col); + update(); - click_select_held->start(); - } + click_select_held->start(); } + } + } - } break; + Ref<InputEventKey> k = p_gui_input; - case InputEvent::KEY: { + if (k.is_valid()) { - InputEventKey k = p_gui_input.key; + k = k->duplicate(); //it will be modified later on #ifdef OSX_ENABLED - if (k.scancode == KEY_META) { + if (k->get_scancode() == KEY_META) { #else - if (k.scancode == KEY_CONTROL) { + if (k->get_scancode() == KEY_CONTROL) { #endif - if (select_identifiers_enabled) { + if (select_identifiers_enabled) { - if (k.pressed) { + if (k->is_pressed()) { - hilighted_word = get_word_at_pos(get_local_mouse_pos()); - update(); + highlighted_word = get_word_at_pos(get_local_mouse_pos()); + update(); - } else { - hilighted_word = String(); - update(); - } + } else { + highlighted_word = String(); + update(); } } + } - if (!k.pressed) - return; - - if (completion_active) { - if (readonly) - break; - - bool valid = true; - if (k.mod.command || k.mod.meta) - valid = false; - - if (valid) { - - if (!k.mod.alt) { - if (k.scancode == KEY_UP) { + if (!k->is_pressed()) + return; - if (completion_index > 0) { - completion_index--; - completion_current = completion_options[completion_index]; - update(); - } - accept_event(); - return; - } + if (completion_active) { + if (readonly) + return; - if (k.scancode == KEY_DOWN) { + bool valid = true; + if (k->get_command() || k->get_metakey()) + valid = false; - if (completion_index < completion_options.size() - 1) { - completion_index++; - completion_current = completion_options[completion_index]; - update(); - } - accept_event(); - return; - } + if (valid) { - if (k.scancode == KEY_PAGEUP) { + if (!k->get_alt()) { + if (k->get_scancode() == KEY_UP) { - completion_index -= get_constant("completion_lines"); - if (completion_index < 0) - completion_index = 0; + if (completion_index > 0) { + completion_index--; completion_current = completion_options[completion_index]; update(); - accept_event(); - return; } + accept_event(); + return; + } - if (k.scancode == KEY_PAGEDOWN) { + if (k->get_scancode() == KEY_DOWN) { - completion_index += get_constant("completion_lines"); - if (completion_index >= completion_options.size()) - completion_index = completion_options.size() - 1; + if (completion_index < completion_options.size() - 1) { + completion_index++; completion_current = completion_options[completion_index]; update(); - accept_event(); - return; } + accept_event(); + return; + } - if (k.scancode == KEY_HOME && completion_index > 0) { + if (k->get_scancode() == KEY_PAGEUP) { + completion_index -= get_constant("completion_lines"); + if (completion_index < 0) completion_index = 0; - completion_current = completion_options[completion_index]; - update(); - accept_event(); - return; - } + completion_current = completion_options[completion_index]; + update(); + accept_event(); + return; + } - if (k.scancode == KEY_END && completion_index < completion_options.size() - 1) { + if (k->get_scancode() == KEY_PAGEDOWN) { + completion_index += get_constant("completion_lines"); + if (completion_index >= completion_options.size()) completion_index = completion_options.size() - 1; - completion_current = completion_options[completion_index]; - update(); - accept_event(); - return; - } + completion_current = completion_options[completion_index]; + update(); + accept_event(); + return; + } - if (k.scancode == KEY_DOWN) { + if (k->get_scancode() == KEY_HOME && completion_index > 0) { - if (completion_index < completion_options.size() - 1) { - completion_index++; - completion_current = completion_options[completion_index]; - update(); - } - accept_event(); - return; - } + completion_index = 0; + completion_current = completion_options[completion_index]; + update(); + accept_event(); + return; + } - if (k.scancode == KEY_ENTER || k.scancode == KEY_RETURN || k.scancode == KEY_TAB) { + if (k->get_scancode() == KEY_END && completion_index < completion_options.size() - 1) { - _confirm_completion(); - accept_event(); - return; - } - - if (k.scancode == KEY_BACKSPACE) { + completion_index = completion_options.size() - 1; + completion_current = completion_options[completion_index]; + update(); + accept_event(); + return; + } - _reset_caret_blink_timer(); + if (k->get_scancode() == KEY_DOWN) { - backspace_at_cursor(); - _update_completion_candidates(); - accept_event(); - return; + if (completion_index < completion_options.size() - 1) { + completion_index++; + completion_current = completion_options[completion_index]; + update(); } + accept_event(); + return; + } - if (k.scancode == KEY_SHIFT) { - accept_event(); - return; - } + if (k->get_scancode() == KEY_KP_ENTER || k->get_scancode() == KEY_ENTER || k->get_scancode() == KEY_TAB) { + + _confirm_completion(); + accept_event(); + return; } - if (k.unicode > 32) { + if (k->get_scancode() == KEY_BACKSPACE) { _reset_caret_blink_timer(); - const CharType chr[2] = { (CharType)k.unicode, 0 }; - if (auto_brace_completion_enabled && _is_pair_symbol(chr[0])) { - _consume_pair_symbol(chr[0]); - } else { + backspace_at_cursor(); + _update_completion_candidates(); + accept_event(); + return; + } - // remove the old character if in insert mode - if (insert_mode) { - begin_complex_operation(); + if (k->get_scancode() == KEY_SHIFT) { + accept_event(); + return; + } + } - // make sure we don't try and remove empty space - if (cursor.column < get_line(cursor.line).length()) { - _remove_text(cursor.line, cursor.column, cursor.line, cursor.column + 1); - } - } + if (k->get_unicode() > 32) { - _insert_text_at_cursor(chr); + _reset_caret_blink_timer(); - if (insert_mode) { - end_complex_operation(); + const CharType chr[2] = { (CharType)k->get_unicode(), 0 }; + if (auto_brace_completion_enabled && _is_pair_symbol(chr[0])) { + _consume_pair_symbol(chr[0]); + } else { + + // remove the old character if in insert mode + if (insert_mode) { + begin_complex_operation(); + + // make sure we don't try and remove empty space + if (cursor.column < get_line(cursor.line).length()) { + _remove_text(cursor.line, cursor.column, cursor.line, cursor.column + 1); } } - _update_completion_candidates(); - accept_event(); - return; + _insert_text_at_cursor(chr); + + if (insert_mode) { + end_complex_operation(); + } } - } + _update_completion_candidates(); + accept_event(); - _cancel_completion(); + return; + } } - /* TEST CONTROL FIRST!! */ + _cancel_completion(); + } - // some remaps for duplicate functions.. - if (k.mod.command && !k.mod.shift && !k.mod.alt && !k.mod.meta && k.scancode == KEY_INSERT) { + /* TEST CONTROL FIRST!! */ - k.scancode = KEY_C; - } - if (!k.mod.command && k.mod.shift && !k.mod.alt && !k.mod.meta && k.scancode == KEY_INSERT) { + // some remaps for duplicate functions.. + if (k->get_command() && !k->get_shift() && !k->get_alt() && !k->get_metakey() && k->get_scancode() == KEY_INSERT) { - k.scancode = KEY_V; - k.mod.command = true; - k.mod.shift = false; - } + k->set_scancode(KEY_C); + } + if (!k->get_command() && k->get_shift() && !k->get_alt() && !k->get_metakey() && k->get_scancode() == KEY_INSERT) { - if (!k.mod.command) { - _reset_caret_blink_timer(); - } + k->set_scancode(KEY_V); + k->set_command(true); + k->set_shift(false); + } - // save here for insert mode, just in case it is cleared in the following section - bool had_selection = selection.active; + if (!k->get_command()) { + _reset_caret_blink_timer(); + } - // stuff to do when selection is active.. - if (selection.active) { + // save here for insert mode, just in case it is cleared in the following section + bool had_selection = selection.active; - if (readonly) - break; + // stuff to do when selection is active.. + if (selection.active) { - bool clear = false; - bool unselect = false; - bool dobreak = false; + if (readonly) + return; - switch (k.scancode) { + bool clear = false; + bool unselect = false; + bool dobreak = false; - case KEY_TAB: { - if (k.mod.shift) { - indent_selection_left(); - } else { - indent_selection_right(); - } - dobreak = true; - accept_event(); - } break; - case KEY_X: - case KEY_C: - //special keys often used with control, wait... - clear = (!k.mod.command || k.mod.shift || k.mod.alt); - break; - case KEY_DELETE: - if (!k.mod.shift) { - accept_event(); - clear = true; - dobreak = true; - } else if (k.mod.command || k.mod.alt) { - dobreak = true; - } - break; - case KEY_BACKSPACE: + switch (k->get_scancode()) { + + case KEY_TAB: { + if (k->get_shift()) { + indent_selection_left(); + } else { + indent_selection_right(); + } + dobreak = true; + accept_event(); + } break; + case KEY_X: + case KEY_C: + //special keys often used with control, wait... + clear = (!k->get_command() || k->get_shift() || k->get_alt()); + break; + case KEY_DELETE: + if (!k->get_shift()) { accept_event(); clear = true; dobreak = true; + } else if (k->get_command() || k->get_alt()) { + dobreak = true; + } + break; + case KEY_BACKSPACE: + accept_event(); + clear = true; + dobreak = true; + break; + case KEY_LEFT: + case KEY_RIGHT: + case KEY_UP: + case KEY_DOWN: + case KEY_PAGEUP: + case KEY_PAGEDOWN: + case KEY_HOME: + case KEY_END: + // ignore arrows if any modifiers are held (shift = selecting, others may be used for editor hotkeys) + if (k->get_command() || k->get_shift() || k->get_alt()) break; - case KEY_LEFT: - case KEY_RIGHT: - case KEY_UP: - case KEY_DOWN: - case KEY_PAGEUP: - case KEY_PAGEDOWN: - case KEY_HOME: - case KEY_END: - // ignore arrows if any modifiers are held (shift = selecting, others may be used for editor hotkeys) - if (k.mod.command || k.mod.shift || k.mod.alt) - break; - unselect = true; - break; + unselect = true; + break; - default: - if (k.unicode >= 32 && !k.mod.command && !k.mod.alt && !k.mod.meta) - clear = true; - if (auto_brace_completion_enabled && _is_pair_left_symbol(k.unicode)) - clear = false; - } + default: + if (k->get_unicode() >= 32 && !k->get_command() && !k->get_alt() && !k->get_metakey()) + clear = true; + if (auto_brace_completion_enabled && _is_pair_left_symbol(k->get_unicode())) + clear = false; + } - if (unselect) { - selection.active = false; - selection.selecting_mode = Selection::MODE_NONE; - update(); - } - if (clear) { + if (unselect) { + selection.active = false; + selection.selecting_mode = Selection::MODE_NONE; + update(); + } + if (clear) { - if (!dobreak) { - begin_complex_operation(); - } - selection.active = false; - update(); - _remove_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column); - cursor_set_line(selection.from_line); - cursor_set_column(selection.from_column); - update(); + if (!dobreak) { + begin_complex_operation(); } - if (dobreak) - break; + selection.active = false; + update(); + _remove_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column); + cursor_set_line(selection.from_line); + cursor_set_column(selection.from_column); + update(); } + if (dobreak) + return; + } - selection.selecting_text = false; + selection.selecting_text = false; - bool scancode_handled = true; + bool scancode_handled = true; - // special scancode test... + // special scancode test... - switch (k.scancode) { + switch (k->get_scancode()) { - case KEY_ENTER: - case KEY_RETURN: { + case KEY_KP_ENTER: + case KEY_ENTER: { - if (readonly) - break; + if (readonly) + break; - String ins = "\n"; + String ins = "\n"; - //keep indentation - for (int i = 0; i < text[cursor.line].length(); i++) { - if (text[cursor.line][i] == '\t') - ins += "\t"; - else - break; - } - if (auto_indent) { - // indent once again if previous line will end with ':' - // (i.e. colon precedes current cursor position) - if (cursor.column > 0 && text[cursor.line][cursor.column - 1] == ':') { + //keep indentation + int space_count = 0; + for (int i = 0; i < text[cursor.line].length(); i++) { + if (text[cursor.line][i] == '\t') { + if (indent_using_spaces) { + ins += space_indent; + } else { ins += "\t"; } - } + space_count = 0; + } else if (text[cursor.line][i] == ' ') { + space_count++; - bool first_line = false; - if (k.mod.command) { - if (k.mod.shift) { - if (cursor.line > 0) { - cursor_set_line(cursor.line - 1); - cursor_set_column(text[cursor.line].length()); + if (space_count == indent_size) { + if (indent_using_spaces) { + ins += space_indent; } else { - cursor_set_column(0); - first_line = true; + ins += "\t"; } - } else { - cursor_set_column(text[cursor.line].length()); + space_count = 0; } + } else { + break; } - - _insert_text_at_cursor(ins); - _push_current_op(); - - if (first_line) { - cursor_set_line(0); + } + if (auto_indent) { + // indent once again if previous line will end with ':' + // (i.e. colon precedes current cursor position) + if (cursor.column > 0 && text[cursor.line][cursor.column - 1] == ':') { + if (indent_using_spaces) { + ins += space_indent; + } else { + ins += "\t"; + } } + } - } break; - case KEY_ESCAPE: { - if (completion_hint != "") { - completion_hint = ""; - update(); + bool first_line = false; + if (k->get_command()) { + if (k->get_shift()) { + if (cursor.line > 0) { + cursor_set_line(cursor.line - 1); + cursor_set_column(text[cursor.line].length()); + } else { + cursor_set_column(0); + first_line = true; + } } else { - scancode_handled = false; + cursor_set_column(text[cursor.line].length()); } - } break; - case KEY_TAB: { - if (k.mod.command) break; // avoid tab when command + } - if (readonly) - break; + _insert_text_at_cursor(ins); + _push_current_op(); - if (selection.active) { + if (first_line) { + cursor_set_line(0); + } - } else { - if (k.mod.shift) { + } break; + case KEY_ESCAPE: { + if (completion_hint != "") { + completion_hint = ""; + update(); + } else { + scancode_handled = false; + } + } break; + case KEY_TAB: { + if (k->get_command()) break; // avoid tab when command - int cc = cursor.column; - if (cc > 0 && cc <= text[cursor.line].length() && text[cursor.line][cursor.column - 1] == '\t') { - //simple unindent + if (readonly) + break; + if (selection.active) { + + } else { + if (k->get_shift()) { + + //simple unindent + int cc = cursor.column; + if (cc > 0 && cc <= text[cursor.line].length()) { + if (text[cursor.line][cursor.column - 1] == '\t') { backspace_at_cursor(); + } else { + if (cursor.column - indent_size >= 0) { + + bool unindent = true; + for (int i = 1; i <= indent_size; i++) { + if (text[cursor.line][cursor.column - i] != ' ') { + unindent = false; + break; + } + } + + if (unindent) { + _remove_text(cursor.line, cursor.column - indent_size, cursor.line, cursor.column); + cursor_set_column(cursor.column - indent_size); + } + } } + } + } else { + //simple indent + if (indent_using_spaces) { + _insert_text_at_cursor(space_indent); } else { - //simple indent _insert_text_at_cursor("\t"); } } + } - } break; - case KEY_BACKSPACE: { - if (readonly) - break; + } break; + case KEY_BACKSPACE: { + if (readonly) + break; #ifdef APPLE_STYLE_KEYS - if (k.mod.alt) { + if (k->get_alt() && cursor.column > 1) { #else - if (k.mod.alt) { - scancode_handled = false; - break; - } else if (k.mod.command) { + if (k->get_alt()) { + scancode_handled = false; + break; + } else if (k->get_command() && cursor.column > 1) { #endif - int line = cursor.line; - int column = cursor.column; - - bool prev_char = false; - bool only_whitespace = true; - - while (only_whitespace && line > 0) { + int line = cursor.line; + int column = cursor.column; - while (column > 0) { - CharType c = text[line][column - 1]; - - if (c != '\t' && c != ' ') { - only_whitespace = false; - break; - } - - column--; - } + // check if we are removing a single whitespace, if so remove it and the next char type + // else we just remove the whitespace + bool only_whitespace = false; + if (_is_whitespace(text[line][column - 1]) && _is_whitespace(text[line][column - 2])) { + only_whitespace = true; + } else if (_is_whitespace(text[line][column - 1])) { + // remove the single whitespace + column--; + } - if (only_whitespace) { - line--; - column = text[line].length(); - } - } + // check if its a text char + bool only_char = (_is_text_char(text[line][column - 1]) && !only_whitespace); - while (column > 0) { - bool ischar = _is_text_char(text[line][column - 1]); + // if its not whitespace or char then symbol. + bool only_symbols = !(only_whitespace || only_char); - if (prev_char && !ischar) - break; + while (column > 0) { + bool is_whitespace = _is_whitespace(text[line][column - 1]); + bool is_text_char = _is_text_char(text[line][column - 1]); - prev_char = ischar; - column--; + if (only_whitespace && !is_whitespace) { + break; + } else if (only_char && !is_text_char) { + break; + } else if (only_symbols && (is_whitespace || is_text_char)) { + break; } + column--; + } - _remove_text(line, column, cursor.line, cursor.column); + _remove_text(line, column, cursor.line, cursor.column); - cursor_set_line(line); - cursor_set_column(column); + cursor_set_line(line); + cursor_set_column(column); - } else { - backspace_at_cursor(); - } + } else { + backspace_at_cursor(); + } - } break; - case KEY_KP_4: { - if (k.unicode != 0) { - scancode_handled = false; - break; - } - // numlock disabled. fallthrough to key_left + } break; + case KEY_KP_4: { + if (k->get_unicode() != 0) { + scancode_handled = false; + break; } - case KEY_LEFT: { + // numlock disabled. fallthrough to key_left + } + case KEY_LEFT: { - if (k.mod.shift) - _pre_shift_selection(); + if (k->get_shift()) + _pre_shift_selection(); #ifdef APPLE_STYLE_KEYS - else + else #else - else if (!k.mod.alt) + else if (!k->get_alt()) #endif - deselect(); + deselect(); #ifdef APPLE_STYLE_KEYS - if (k.mod.command) { - cursor_set_column(0); - } else if (k.mod.alt) { + if (k->get_command()) { + cursor_set_column(0); + } else if (k->get_alt()) { #else - if (k.mod.alt) { - scancode_handled = false; - break; - } else if (k.mod.command) { + if (k->get_alt()) { + scancode_handled = false; + break; + } else if (k->get_command()) { #endif - bool prev_char = false; - int cc = cursor.column; - while (cc > 0) { + bool prev_char = false; + int cc = cursor.column; + while (cc > 0) { - bool ischar = _is_text_char(text[cursor.line][cc - 1]); + bool ischar = _is_text_char(text[cursor.line][cc - 1]); - if (prev_char && !ischar) - break; + if (prev_char && !ischar) + break; - prev_char = ischar; - cc--; - } + prev_char = ischar; + cc--; + } - cursor_set_column(cc); + cursor_set_column(cc); - } else if (cursor.column == 0) { + } else if (cursor.column == 0) { - if (cursor.line > 0) { - cursor_set_line(cursor.line - 1); - cursor_set_column(text[cursor.line].length()); - } - } else { - cursor_set_column(cursor_get_column() - 1); + if (cursor.line > 0) { + cursor_set_line(cursor.line - 1); + cursor_set_column(text[cursor.line].length()); } + } else { + cursor_set_column(cursor_get_column() - 1); + } - if (k.mod.shift) - _post_shift_selection(); + if (k->get_shift()) + _post_shift_selection(); - } break; - case KEY_KP_6: { - if (k.unicode != 0) { - scancode_handled = false; - break; - } - // numlock disabled. fallthrough to key_right + } break; + case KEY_KP_6: { + if (k->get_unicode() != 0) { + scancode_handled = false; + break; } - case KEY_RIGHT: { + // numlock disabled. fallthrough to key_right + } + case KEY_RIGHT: { - if (k.mod.shift) - _pre_shift_selection(); + if (k->get_shift()) + _pre_shift_selection(); #ifdef APPLE_STYLE_KEYS - else + else #else - else if (!k.mod.alt) + else if (!k->get_alt()) #endif - deselect(); + deselect(); #ifdef APPLE_STYLE_KEYS - if (k.mod.command) { - cursor_set_column(text[cursor.line].length()); - } else if (k.mod.alt) { + if (k->get_command()) { + cursor_set_column(text[cursor.line].length()); + } else if (k->get_alt()) { #else - if (k.mod.alt) { - scancode_handled = false; - break; - } else if (k.mod.command) { + if (k->get_alt()) { + scancode_handled = false; + break; + } else if (k->get_command()) { #endif - bool prev_char = false; - int cc = cursor.column; - while (cc < text[cursor.line].length()) { + bool prev_char = false; + int cc = cursor.column; + while (cc < text[cursor.line].length()) { - bool ischar = _is_text_char(text[cursor.line][cc]); + bool ischar = _is_text_char(text[cursor.line][cc]); - if (prev_char && !ischar) - break; - prev_char = ischar; - cc++; - } + if (prev_char && !ischar) + break; + prev_char = ischar; + cc++; + } - cursor_set_column(cc); + cursor_set_column(cc); - } else if (cursor.column == text[cursor.line].length()) { + } else if (cursor.column == text[cursor.line].length()) { - if (cursor.line < text.size() - 1) { - cursor_set_line(cursor.line + 1); - cursor_set_column(0); - } - } else { - cursor_set_column(cursor_get_column() + 1); + if (cursor.line < text.size() - 1) { + cursor_set_line(cursor.line + 1); + cursor_set_column(0); } + } else { + cursor_set_column(cursor_get_column() + 1); + } - if (k.mod.shift) - _post_shift_selection(); + if (k->get_shift()) + _post_shift_selection(); - } break; - case KEY_KP_8: { - if (k.unicode != 0) { - scancode_handled = false; - break; - } - // numlock disabled. fallthrough to key_up + } break; + case KEY_KP_8: { + if (k->get_unicode() != 0) { + scancode_handled = false; + break; } - case KEY_UP: { + // numlock disabled. fallthrough to key_up + } + case KEY_UP: { - if (k.mod.shift) - _pre_shift_selection(); - if (k.mod.alt) { - scancode_handled = false; - break; - } + if (k->get_shift()) + _pre_shift_selection(); + if (k->get_alt()) { + scancode_handled = false; + break; + } #ifndef APPLE_STYLE_KEYS - if (k.mod.command) { - _scroll_lines_up(); - break; - } + if (k->get_command()) { + _scroll_lines_up(); + break; + } #else - if (k.mod.command && k.mod.alt) { - _scroll_lines_up(); - break; - } + if (k->get_command() && k->get_alt()) { + _scroll_lines_up(); + break; + } - if (k.mod.command) - cursor_set_line(0); - else + if (k->get_command()) + cursor_set_line(0); + else #endif - cursor_set_line(cursor_get_line() - 1); + cursor_set_line(cursor_get_line() - 1); - if (k.mod.shift) - _post_shift_selection(); - _cancel_code_hint(); + if (k->get_shift()) + _post_shift_selection(); + _cancel_code_hint(); - } break; - case KEY_KP_2: { - if (k.unicode != 0) { - scancode_handled = false; - break; - } - // numlock disabled. fallthrough to key_down + } break; + case KEY_KP_2: { + if (k->get_unicode() != 0) { + scancode_handled = false; + break; } - case KEY_DOWN: { + // numlock disabled. fallthrough to key_down + } + case KEY_DOWN: { - if (k.mod.shift) - _pre_shift_selection(); - if (k.mod.alt) { - scancode_handled = false; - break; - } + if (k->get_shift()) + _pre_shift_selection(); + if (k->get_alt()) { + scancode_handled = false; + break; + } #ifndef APPLE_STYLE_KEYS - if (k.mod.command) { - _scroll_lines_down(); - break; - } + if (k->get_command()) { + _scroll_lines_down(); + break; + } #else - if (k.mod.command && k.mod.alt) { - _scroll_lines_down(); - break; - } + if (k->get_command() && k->get_alt()) { + _scroll_lines_down(); + break; + } - if (k.mod.command) - cursor_set_line(text.size() - 1); - else + if (k->get_command()) + cursor_set_line(text.size() - 1); + else #endif - cursor_set_line(cursor_get_line() + 1); + cursor_set_line(cursor_get_line() + 1); - if (k.mod.shift) - _post_shift_selection(); - _cancel_code_hint(); + if (k->get_shift()) + _post_shift_selection(); + _cancel_code_hint(); - } break; + } break; - case KEY_DELETE: { + case KEY_DELETE: { - if (readonly) - break; + if (readonly) + break; - if (k.mod.shift && !k.mod.command && !k.mod.alt) { - cut(); - break; - } + if (k->get_shift() && !k->get_command() && !k->get_alt()) { + cut(); + break; + } - int curline_len = text[cursor.line].length(); + int curline_len = text[cursor.line].length(); - if (cursor.line == text.size() - 1 && cursor.column == curline_len) - break; //nothing to do + if (cursor.line == text.size() - 1 && cursor.column == curline_len) + break; //nothing to do - int next_line = cursor.column < curline_len ? cursor.line : cursor.line + 1; - int next_column; + int next_line = cursor.column < curline_len ? cursor.line : cursor.line + 1; + int next_column; #ifdef APPLE_STYLE_KEYS - if (k.mod.alt) { + if (k->get_alt() && cursor.column < curline_len - 1) { #else - if (k.mod.alt) { - scancode_handled = false; - break; - } else if (k.mod.command) { + if (k->get_alt()) { + scancode_handled = false; + break; + } else if (k->get_command() && cursor.column < curline_len - 1) { #endif - int last_line = text.size() - 1; - int line = cursor.line; - int column = cursor.column; + int line = cursor.line; + int column = cursor.column; - bool prev_char = false; - bool only_whitespace = true; + // check if we are removing a single whitespace, if so remove it and the next char type + // else we just remove the whitespace + bool only_whitespace = false; + if (_is_whitespace(text[line][column]) && _is_whitespace(text[line][column + 1])) { + only_whitespace = true; + } else if (_is_whitespace(text[line][column])) { + // remove the single whitespace + column++; + } - while (only_whitespace && line < last_line) { + // check if its a text char + bool only_char = (_is_text_char(text[line][column]) && !only_whitespace); - while (column < text[line].length()) { - CharType c = text[line][column]; + // if its not whitespace or char then symbol. + bool only_symbols = !(only_whitespace || only_char); - if (c != '\t' && c != ' ') { - only_whitespace = false; - break; - } - - column++; - } + while (column < curline_len) { + bool is_whitespace = _is_whitespace(text[line][column]); + bool is_text_char = _is_text_char(text[line][column]); - if (only_whitespace) { - line++; - column = 0; - } + if (only_whitespace && !is_whitespace) { + break; + } else if (only_char && !is_text_char) { + break; + } else if (only_symbols && (is_whitespace || is_text_char)) { + break; } + column++; + } - while (column < text[line].length()) { - - bool ischar = _is_text_char(text[line][column]); + next_line = line; + next_column = column; - if (prev_char && !ischar) - break; - prev_char = ischar; - column++; - } - - next_line = line; - next_column = column; - } else { - next_column = cursor.column < curline_len ? (cursor.column + 1) : 0; - } + } else { + next_column = cursor.column < curline_len ? (cursor.column + 1) : 0; + } - _remove_text(cursor.line, cursor.column, next_line, next_column); - update(); + _remove_text(cursor.line, cursor.column, next_line, next_column); + update(); - } break; - case KEY_KP_7: { - if (k.unicode != 0) { - scancode_handled = false; - break; - } - // numlock disabled. fallthrough to key_home + } break; + case KEY_KP_7: { + if (k->get_unicode() != 0) { + scancode_handled = false; + break; } + // numlock disabled. fallthrough to key_home + } #ifdef APPLE_STYLE_KEYS - case KEY_HOME: { + case KEY_HOME: { - if (k.mod.shift) - _pre_shift_selection(); + if (k->get_shift()) + _pre_shift_selection(); - cursor_set_line(0); + cursor_set_line(0); - if (k.mod.shift) - _post_shift_selection(); - else if (k.mod.command || k.mod.control) - deselect(); + if (k->get_shift()) + _post_shift_selection(); + else if (k->get_command() || k->get_control()) + deselect(); - } break; + } break; #else - case KEY_HOME: { - - if (k.mod.shift) - _pre_shift_selection(); + case KEY_HOME: { - if (k.mod.command) { - cursor_set_line(0); - cursor_set_column(0); - } else { - // compute whitespace symbols seq length - int current_line_whitespace_len = 0; - while (current_line_whitespace_len < text[cursor.line].length()) { - CharType c = text[cursor.line][current_line_whitespace_len]; - if (c != '\t' && c != ' ') - break; - current_line_whitespace_len++; - } + if (k->get_shift()) + _pre_shift_selection(); - if (cursor_get_column() == current_line_whitespace_len) - cursor_set_column(0); - else - cursor_set_column(current_line_whitespace_len); + if (k->get_command()) { + cursor_set_line(0); + cursor_set_column(0); + } else { + // compute whitespace symbols seq length + int current_line_whitespace_len = 0; + while (current_line_whitespace_len < text[cursor.line].length()) { + CharType c = text[cursor.line][current_line_whitespace_len]; + if (c != '\t' && c != ' ') + break; + current_line_whitespace_len++; } - if (k.mod.shift) - _post_shift_selection(); - else if (k.mod.command || k.mod.control) - deselect(); - _cancel_completion(); - completion_hint = ""; + if (cursor_get_column() == current_line_whitespace_len) + cursor_set_column(0); + else + cursor_set_column(current_line_whitespace_len); + } - } break; + if (k->get_shift()) + _post_shift_selection(); + else if (k->get_command() || k->get_control()) + deselect(); + _cancel_completion(); + completion_hint = ""; + + } break; #endif - case KEY_KP_1: { - if (k.unicode != 0) { - scancode_handled = false; - break; - } - // numlock disabled. fallthrough to key_end + case KEY_KP_1: { + if (k->get_unicode() != 0) { + scancode_handled = false; + break; } + // numlock disabled. fallthrough to key_end + } #ifdef APPLE_STYLE_KEYS - case KEY_END: { + case KEY_END: { - if (k.mod.shift) - _pre_shift_selection(); + if (k->get_shift()) + _pre_shift_selection(); - cursor_set_line(text.size() - 1); + cursor_set_line(text.size() - 1); - if (k.mod.shift) - _post_shift_selection(); - else if (k.mod.command || k.mod.control) - deselect(); + if (k->get_shift()) + _post_shift_selection(); + else if (k->get_command() || k->get_control()) + deselect(); - } break; + } break; #else - case KEY_END: { + case KEY_END: { - if (k.mod.shift) - _pre_shift_selection(); + if (k->get_shift()) + _pre_shift_selection(); - if (k.mod.command) - cursor_set_line(text.size() - 1); - cursor_set_column(text[cursor.line].length()); + if (k->get_command()) + cursor_set_line(text.size() - 1); + cursor_set_column(text[cursor.line].length()); - if (k.mod.shift) - _post_shift_selection(); - else if (k.mod.command || k.mod.control) - deselect(); + if (k->get_shift()) + _post_shift_selection(); + else if (k->get_command() || k->get_control()) + deselect(); - _cancel_completion(); - completion_hint = ""; + _cancel_completion(); + completion_hint = ""; - } break; + } break; #endif - case KEY_KP_9: { - if (k.unicode != 0) { - scancode_handled = false; - break; - } - // numlock disabled. fallthrough to key_pageup + case KEY_KP_9: { + if (k->get_unicode() != 0) { + scancode_handled = false; + break; } - case KEY_PAGEUP: { + // numlock disabled. fallthrough to key_pageup + } + case KEY_PAGEUP: { - if (k.mod.shift) - _pre_shift_selection(); + if (k->get_shift()) + _pre_shift_selection(); - cursor_set_line(cursor_get_line() - get_visible_rows()); + cursor_set_line(cursor_get_line() - get_visible_rows()); - if (k.mod.shift) - _post_shift_selection(); + if (k->get_shift()) + _post_shift_selection(); - _cancel_completion(); - completion_hint = ""; + _cancel_completion(); + completion_hint = ""; - } break; - case KEY_KP_3: { - if (k.unicode != 0) { - scancode_handled = false; - break; - } - // numlock disabled. fallthrough to key_pageup + } break; + case KEY_KP_3: { + if (k->get_unicode() != 0) { + scancode_handled = false; + break; } - case KEY_PAGEDOWN: { + // numlock disabled. fallthrough to key_pageup + } + case KEY_PAGEDOWN: { - if (k.mod.shift) - _pre_shift_selection(); + if (k->get_shift()) + _pre_shift_selection(); - cursor_set_line(cursor_get_line() + get_visible_rows()); + cursor_set_line(cursor_get_line() + get_visible_rows()); - if (k.mod.shift) - _post_shift_selection(); + if (k->get_shift()) + _post_shift_selection(); - _cancel_completion(); - completion_hint = ""; + _cancel_completion(); + completion_hint = ""; - } break; - case KEY_A: { + } break; + case KEY_A: { - if (!k.mod.command || k.mod.shift || k.mod.alt) { - scancode_handled = false; - break; - } + if (!k->get_command() || k->get_shift() || k->get_alt()) { + scancode_handled = false; + break; + } - select_all(); + select_all(); - } break; - case KEY_X: { - if (readonly) { - break; - } - if (!k.mod.command || k.mod.shift || k.mod.alt) { - scancode_handled = false; - break; - } + } break; + case KEY_X: { + if (readonly) { + break; + } + if (!k->get_command() || k->get_shift() || k->get_alt()) { + scancode_handled = false; + break; + } - cut(); + cut(); - } break; - case KEY_C: { + } break; + case KEY_C: { - if (!k.mod.command || k.mod.shift || k.mod.alt) { - scancode_handled = false; - break; - } + if (!k->get_command() || k->get_shift() || k->get_alt()) { + scancode_handled = false; + break; + } - copy(); + copy(); - } break; - case KEY_Z: { + } break; + case KEY_Z: { - if (!k.mod.command) { - scancode_handled = false; - break; - } + if (!k->get_command()) { + scancode_handled = false; + break; + } - if (k.mod.shift) - redo(); - else - undo(); - } break; - case KEY_V: { - if (readonly) { - break; - } - if (!k.mod.command || k.mod.shift || k.mod.alt) { - scancode_handled = false; - break; - } + if (k->get_shift()) + redo(); + else + undo(); + } break; + case KEY_V: { + if (readonly) { + break; + } + if (!k->get_command() || k->get_shift() || k->get_alt()) { + scancode_handled = false; + break; + } - paste(); + paste(); - } break; - case KEY_SPACE: { + } break; + case KEY_SPACE: { #ifdef OSX_ENABLED - if (completion_enabled && k.mod.meta) { //cmd-space is spotlight shortcut in OSX + if (completion_enabled && k->get_metakey()) { //cmd-space is spotlight shortcut in OSX #else - if (completion_enabled && k.mod.command) { + if (completion_enabled && k->get_command()) { #endif - query_code_comple(); - scancode_handled = true; - } else { - scancode_handled = false; - } + query_code_comple(); + scancode_handled = true; + } else { + scancode_handled = false; + } - } break; + } break; - case KEY_U: { - if (!k.mod.command || k.mod.shift) { - scancode_handled = false; - break; - } else { - if (selection.active) { - int ini = selection.from_line; - int end = selection.to_line; - for (int i = ini; i <= end; i++) { - if (text[i][0] == '#') - _remove_text(i, 0, i, 1); - } - } else { - if (text[cursor.line][0] == '#') - _remove_text(cursor.line, 0, cursor.line, 1); + case KEY_U: { + if (!k->get_command() || k->get_shift()) { + scancode_handled = false; + break; + } else { + if (selection.active) { + int ini = selection.from_line; + int end = selection.to_line; + for (int i = ini; i <= end; i++) { + if (text[i][0] == '#') + _remove_text(i, 0, i, 1); } - update(); + } else { + if (text[cursor.line][0] == '#') + _remove_text(cursor.line, 0, cursor.line, 1); } - } break; + update(); + } + } break; - default: { + default: { - scancode_handled = false; - } break; - } + scancode_handled = false; + } break; + } - if (scancode_handled) - accept_event(); - /* - if (!scancode_handled && !k.mod.command && !k.mod.alt) { + if (scancode_handled) + accept_event(); + /* + if (!scancode_handled && !k->get_command() && !k->get_alt()) { - if (k.unicode>=32) { + if (k->get_unicode()>=32) { - if (readonly) - break; + if (readonly) + break; - accept_event(); - } else { + accept_event(); + } else { - break; - } - } + break; + } + } */ - if (k.scancode == KEY_INSERT) { - set_insert_mode(!insert_mode); - accept_event(); - return; - } - - if (!scancode_handled && !k.mod.command) { //for german kbds - - if (k.unicode >= 32) { + if (k->get_scancode() == KEY_INSERT) { + set_insert_mode(!insert_mode); + accept_event(); + return; + } - if (readonly) - break; + if (!scancode_handled && !k->get_command()) { //for german kbds - // remove the old character if in insert mode and no selection - if (insert_mode && !had_selection) { - begin_complex_operation(); + if (k->get_unicode() >= 32) { - // make sure we don't try and remove empty space - if (cursor.column < get_line(cursor.line).length()) { - _remove_text(cursor.line, cursor.column, cursor.line, cursor.column + 1); - } - } + if (readonly) + return; - const CharType chr[2] = { (CharType)k.unicode, 0 }; + // remove the old character if in insert mode and no selection + if (insert_mode && !had_selection) { + begin_complex_operation(); - if (completion_hint != "" && k.unicode == ')') { - completion_hint = ""; - } - if (auto_brace_completion_enabled && _is_pair_symbol(chr[0])) { - _consume_pair_symbol(chr[0]); - } else { - _insert_text_at_cursor(chr); + // make sure we don't try and remove empty space + if (cursor.column < get_line(cursor.line).length()) { + _remove_text(cursor.line, cursor.column, cursor.line, cursor.column + 1); } + } - if (insert_mode && !had_selection) { - end_complex_operation(); - } + const CharType chr[2] = { (CharType)k->get_unicode(), 0 }; - if (selection.active != had_selection) { - end_complex_operation(); - } - accept_event(); + if (completion_hint != "" && k->get_unicode() == ')') { + completion_hint = ""; + } + if (auto_brace_completion_enabled && _is_pair_symbol(chr[0])) { + _consume_pair_symbol(chr[0]); } else { + _insert_text_at_cursor(chr); + } - break; + if (insert_mode && !had_selection) { + end_complex_operation(); } + + if (selection.active != had_selection) { + end_complex_operation(); + } + accept_event(); + } else { } + } - return; - } break; + return; } } @@ -2777,7 +2933,7 @@ void TextEdit::_base_remove_text(int p_from_line, int p_from_column, int p_to_li } } -void TextEdit::_insert_text(int p_line, int p_char, const String &p_text, int *r_end_line, int *r_end_column) { +void TextEdit::_insert_text(int p_line, int p_char, const String &p_text, int *r_end_line, int *r_end_char) { if (!setting_text) idle_detect->start(); @@ -2790,8 +2946,8 @@ void TextEdit::_insert_text(int p_line, int p_char, const String &p_text, int *r _base_insert_text(p_line, p_char, p_text, retline, retchar); if (r_end_line) *r_end_line = retline; - if (r_end_column) - *r_end_column = retchar; + if (r_end_char) + *r_end_char = retchar; if (!undo_enabled) return; @@ -3102,7 +3258,7 @@ int TextEdit::get_char_pos_for(int p_px, String p_str) const { int px = 0; int c = 0; - int tab_w = cache.font->get_char_size(' ').width * tab_size; + int tab_w = cache.font->get_char_size(' ').width * indent_size; while (c < p_str.length()) { @@ -3134,7 +3290,7 @@ int TextEdit::get_column_x_offset(int p_char, String p_str) { int px = 0; - int tab_w = cache.font->get_char_size(' ').width * tab_size; + int tab_w = cache.font->get_char_size(' ').width * indent_size; for (int i = 0; i < p_char; i++) { @@ -3174,7 +3330,7 @@ void TextEdit::insert_text_at_cursor(const String &p_text) { } Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const { - if (hilighted_word != String()) + if (highlighted_word != String()) return CURSOR_POINTING_HAND; int gutter = cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width; @@ -3951,10 +4107,24 @@ void TextEdit::_push_current_op() { current_op.chain_forward = false; } -void TextEdit::set_tab_size(const int p_size) { +void TextEdit::set_indent_using_spaces(const bool p_use_spaces) { + indent_using_spaces = p_use_spaces; +} + +bool TextEdit::is_indent_using_spaces() const { + return indent_using_spaces; +} + +void TextEdit::set_indent_size(const int p_size) { ERR_FAIL_COND(p_size <= 0); - tab_size = p_size; - text.set_tab_size(p_size); + indent_size = p_size; + text.set_indent_size(p_size); + + space_indent = ""; + for (int i = 0; i < p_size; i++) { + space_indent += " "; + } + update(); } @@ -4250,6 +4420,23 @@ String TextEdit::get_word_at_pos(const Vector2 &p_pos) const { bool symbol = beg < s.length() && _is_symbol(s[beg]); //not sure if right but most editors behave like this + bool inside_quotes = false; + int qbegin, qend; + for (int i = 0; i < s.length(); i++) { + if (s[i] == '"') { + if (inside_quotes) { + qend = i; + inside_quotes = false; + if (col >= qbegin && col <= qend) { + return s.substr(qbegin, qend - qbegin); + } + } else { + qbegin = i + 1; + inside_quotes = true; + } + } + } + while (beg > 0 && s[beg - 1] > 32 && (symbol == _is_symbol(s[beg - 1]))) { beg--; } @@ -4447,8 +4634,8 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("get_text"), &TextEdit::get_text); ClassDB::bind_method(D_METHOD("get_line", "line"), &TextEdit::get_line); - ClassDB::bind_method(D_METHOD("cursor_set_column", "column", "adjust_viewport"), &TextEdit::cursor_set_column, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("cursor_set_line", "line", "adjust_viewport"), &TextEdit::cursor_set_line, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("cursor_set_column", "column", "adjust_viewport"), &TextEdit::cursor_set_column, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("cursor_set_line", "line", "adjust_viewport"), &TextEdit::cursor_set_line, DEFVAL(true)); ClassDB::bind_method(D_METHOD("cursor_get_column"), &TextEdit::cursor_get_column); ClassDB::bind_method(D_METHOD("cursor_get_line"), &TextEdit::cursor_get_line); @@ -4476,7 +4663,7 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("get_selection_to_column"), &TextEdit::get_selection_to_column); ClassDB::bind_method(D_METHOD("get_selection_text"), &TextEdit::get_selection_text); ClassDB::bind_method(D_METHOD("get_word_under_cursor"), &TextEdit::get_word_under_cursor); - ClassDB::bind_method(D_METHOD("search", "flags", "from_line", "from_column", "to_line", "to_column"), &TextEdit::_search_bind); + ClassDB::bind_method(D_METHOD("search", "key", "flags", "from_line", "from_column"), &TextEdit::_search_bind); ClassDB::bind_method(D_METHOD("undo"), &TextEdit::undo); ClassDB::bind_method(D_METHOD("redo"), &TextEdit::redo); @@ -4494,8 +4681,8 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("add_keyword_color", "keyword", "color"), &TextEdit::add_keyword_color); ClassDB::bind_method(D_METHOD("add_color_region", "begin_key", "end_key", "color", "line_only"), &TextEdit::add_color_region, DEFVAL(false)); ClassDB::bind_method(D_METHOD("clear_colors"), &TextEdit::clear_colors); - ClassDB::bind_method(D_METHOD("menu_option"), &TextEdit::menu_option); - ClassDB::bind_method(D_METHOD("get_menu:PopupMenu"), &TextEdit::get_menu); + ClassDB::bind_method(D_METHOD("menu_option", "option"), &TextEdit::menu_option); + ClassDB::bind_method(D_METHOD("get_menu"), &TextEdit::get_menu); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "syntax_highlighting"), "set_syntax_coloring", "is_syntax_coloring_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_line_numbers"), "set_show_line_numbers", "is_show_line_numbers_enabled"); @@ -4541,8 +4728,8 @@ TextEdit::TextEdit() { cache.breakpoint_gutter_width = 0; breakpoint_gutter_width = 0; - tab_size = 4; - text.set_tab_size(tab_size); + indent_size = 4; + text.set_indent_size(indent_size); text.clear(); //text.insert(1,"Mongolia.."); //text.insert(2,"PAIS GENEROSO!!"); @@ -4630,6 +4817,8 @@ TextEdit::TextEdit() { auto_brace_completion_enabled = false; brace_matching_enabled = false; highlight_all_occurrences = false; + indent_using_spaces = false; + space_indent = " "; auto_indent = false; insert_mode = false; window_has_focus = true; diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index e38d484b0..4c17347a5 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -140,18 +141,18 @@ class TextEdit : public Control { const Vector<ColorRegion> *color_regions; mutable Vector<Line> text; Ref<Font> font; - int tab_size; + int indent_size; void _update_line_cache(int p_line) const; public: - void set_tab_size(int p_tab_size); + void set_indent_size(int p_indent_size); void set_font(const Ref<Font> &p_font); void set_color_regions(const Vector<ColorRegion> *p_regions) { color_regions = p_regions; } int get_line_width(int p_line) const; int get_max_width() const; const Map<int, ColorRegionInfo> &get_color_region_info(int p_line); - void set(int p_line, const String &p_string); + void set(int p_line, const String &p_text); void set_marked(int p_line, bool p_marked) { text[p_line].marked = p_marked; } bool is_marked(int p_line) const { return text[p_line].marked; } void set_breakpoint(int p_line, bool p_breakpoint) { text[p_line].breakpoint = p_breakpoint; } @@ -162,7 +163,7 @@ class TextEdit : public Control { void clear(); void clear_caches(); _FORCE_INLINE_ const String &operator[](int p_line) const { return text[p_line].data; } - Text() { tab_size = 4; } + Text() { indent_size = 4; } }; struct TextOperation { @@ -183,6 +184,9 @@ class TextEdit : public Control { bool chain_backward; }; + String ime_text; + Point2 ime_selection; + TextOperation current_op; List<TextOperation> undo_stack; @@ -220,7 +224,9 @@ class TextEdit : public Control { int max_chars; bool readonly; bool syntax_coloring; - int tab_size; + bool indent_using_spaces; + int indent_size; + String space_indent; Timer *caret_blink_timer; bool caret_blink_enabled; @@ -252,7 +258,7 @@ class TextEdit : public Control { bool raised_from_completion; - String hilighted_word; + String highlighted_word; uint64_t last_dblclk; @@ -282,8 +288,8 @@ class TextEdit : public Control { int get_char_count(); - int get_char_pos_for(int p_px, String p_pos) const; - int get_column_x_offset(int p_column, String p_pos); + int get_char_pos_for(int p_px, String p_str) const; + int get_column_x_offset(int p_char, String p_str); void adjust_viewport_to_cursor(); void _scroll_moved(double); @@ -296,6 +302,8 @@ class TextEdit : public Control { void _scroll_lines_up(); void _scroll_lines_down(); + static void _ime_text_callback(void *p_self, String p_text, Point2 p_selection); + //void mouse_motion(const Point& p_pos, const Point& p_rel, int p_button_mask); Size2 get_minimum_size() const; @@ -312,7 +320,7 @@ class TextEdit : public Control { /* super internal api, undo/redo builds on it */ - void _base_insert_text(int p_line, int p_column, const String &p_text, int &r_end_line, int &r_end_column); + void _base_insert_text(int p_line, int p_char, const String &p_text, int &r_end_line, int &r_end_column); String _base_get_text(int p_from_line, int p_from_column, int p_to_line, int p_to_column) const; void _base_remove_text(int p_from_line, int p_from_column, int p_to_line, int p_to_column); @@ -331,10 +339,10 @@ class TextEdit : public Control { protected: virtual String get_tooltip(const Point2 &p_pos) const; - void _insert_text(int p_line, int p_column, const String &p_text, int *r_end_line = NULL, int *r_end_char = NULL); + void _insert_text(int p_line, int p_char, const String &p_text, int *r_end_line = NULL, int *r_end_char = NULL); void _remove_text(int p_from_line, int p_from_column, int p_to_line, int p_to_column); void _insert_text_at_cursor(const String &p_text); - void _gui_input(const InputEvent &p_input); + void _gui_input(const Ref<InputEvent> &p_gui_input); void _notification(int p_what); void _consume_pair_symbol(CharType ch); @@ -460,7 +468,9 @@ public: void redo(); void clear_undo_history(); - void set_tab_size(const int p_size); + void set_indent_using_spaces(const bool p_use_spaces); + bool is_indent_using_spaces() const; + void set_indent_size(const int p_size); void set_draw_tabs(bool p_draw); bool is_drawing_tabs() const; diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp index 54f09cbf6..7abf8380c 100644 --- a/scene/gui/texture_button.cpp +++ b/scene/gui/texture_button.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -179,21 +180,21 @@ void TextureButton::_notification(int p_what) { void TextureButton::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_normal_texture", "texture:Texture"), &TextureButton::set_normal_texture); - ClassDB::bind_method(D_METHOD("set_pressed_texture", "texture:Texture"), &TextureButton::set_pressed_texture); - ClassDB::bind_method(D_METHOD("set_hover_texture", "texture:Texture"), &TextureButton::set_hover_texture); - ClassDB::bind_method(D_METHOD("set_disabled_texture", "texture:Texture"), &TextureButton::set_disabled_texture); - ClassDB::bind_method(D_METHOD("set_focused_texture", "texture:Texture"), &TextureButton::set_focused_texture); - ClassDB::bind_method(D_METHOD("set_click_mask", "mask:BitMap"), &TextureButton::set_click_mask); + ClassDB::bind_method(D_METHOD("set_normal_texture", "texture"), &TextureButton::set_normal_texture); + ClassDB::bind_method(D_METHOD("set_pressed_texture", "texture"), &TextureButton::set_pressed_texture); + ClassDB::bind_method(D_METHOD("set_hover_texture", "texture"), &TextureButton::set_hover_texture); + ClassDB::bind_method(D_METHOD("set_disabled_texture", "texture"), &TextureButton::set_disabled_texture); + ClassDB::bind_method(D_METHOD("set_focused_texture", "texture"), &TextureButton::set_focused_texture); + ClassDB::bind_method(D_METHOD("set_click_mask", "mask"), &TextureButton::set_click_mask); ClassDB::bind_method(D_METHOD("set_expand", "p_expand"), &TextureButton::set_expand); ClassDB::bind_method(D_METHOD("set_stretch_mode", "p_mode"), &TextureButton::set_stretch_mode); - ClassDB::bind_method(D_METHOD("get_normal_texture:Texture"), &TextureButton::get_normal_texture); - ClassDB::bind_method(D_METHOD("get_pressed_texture:Texture"), &TextureButton::get_pressed_texture); - ClassDB::bind_method(D_METHOD("get_hover_texture:Texture"), &TextureButton::get_hover_texture); - ClassDB::bind_method(D_METHOD("get_disabled_texture:Texture"), &TextureButton::get_disabled_texture); - ClassDB::bind_method(D_METHOD("get_focused_texture:Texture"), &TextureButton::get_focused_texture); - ClassDB::bind_method(D_METHOD("get_click_mask:BitMap"), &TextureButton::get_click_mask); + ClassDB::bind_method(D_METHOD("get_normal_texture"), &TextureButton::get_normal_texture); + ClassDB::bind_method(D_METHOD("get_pressed_texture"), &TextureButton::get_pressed_texture); + ClassDB::bind_method(D_METHOD("get_hover_texture"), &TextureButton::get_hover_texture); + ClassDB::bind_method(D_METHOD("get_disabled_texture"), &TextureButton::get_disabled_texture); + ClassDB::bind_method(D_METHOD("get_focused_texture"), &TextureButton::get_focused_texture); + ClassDB::bind_method(D_METHOD("get_click_mask"), &TextureButton::get_click_mask); ClassDB::bind_method(D_METHOD("get_expand"), &TextureButton::get_expand); ClassDB::bind_method(D_METHOD("get_stretch_mode"), &TextureButton::get_stretch_mode); @@ -205,7 +206,7 @@ void TextureButton::_bind_methods() { ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "texture_focused", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_focused_texture", "get_focused_texture"); ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "texture_click_mask", PROPERTY_HINT_RESOURCE_TYPE, "BitMap"), "set_click_mask", "get_click_mask"); ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "expand", PROPERTY_HINT_RESOURCE_TYPE, "bool"), "set_expand", "get_expand"); - ADD_PROPERTYNO(PropertyInfo(Variant::INT, "stretch_mode", PROPERTY_HINT_ENUM, "Scale,Tile,Keep,Keep Centered,Keep Aspect,Keep Aspect Centered,Keep Aspect Covered"), "set_stretch_mode", "get_stretch_mode"); + ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "stretch_mode", PROPERTY_HINT_ENUM, "Scale,Tile,Keep,Keep Centered,Keep Aspect,Keep Aspect Centered,Keep Aspect Covered"), "set_stretch_mode", "get_stretch_mode"); BIND_CONSTANT(STRETCH_SCALE); BIND_CONSTANT(STRETCH_TILE); @@ -285,8 +286,8 @@ void TextureButton::set_expand(bool p_expand) { update(); } -void TextureButton::set_stretch_mode(StretchMode p_mode) { - stretch_mode = p_mode; +void TextureButton::set_stretch_mode(StretchMode p_stretch_mode) { + stretch_mode = p_stretch_mode; update(); } diff --git a/scene/gui/texture_button.h b/scene/gui/texture_button.h index fc5079dbf..8df30cd35 100644 --- a/scene/gui/texture_button.h +++ b/scene/gui/texture_button.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -68,7 +69,7 @@ public: void set_hover_texture(const Ref<Texture> &p_hover); void set_disabled_texture(const Ref<Texture> &p_disabled); void set_focused_texture(const Ref<Texture> &p_focused); - void set_click_mask(const Ref<BitMap> &p_image); + void set_click_mask(const Ref<BitMap> &p_click_mask); Ref<Texture> get_normal_texture() const; Ref<Texture> get_pressed_texture() const; @@ -80,7 +81,7 @@ public: bool get_expand() const; void set_expand(bool p_expand); - void set_stretch_mode(StretchMode stretch_mode); + void set_stretch_mode(StretchMode p_stretch_mode); StretchMode get_stretch_mode() const; TextureButton(); diff --git a/scene/gui/texture_progress.cpp b/scene/gui/texture_progress.cpp index 914d17d2d..081c7ddb7 100644 --- a/scene/gui/texture_progress.cpp +++ b/scene/gui/texture_progress.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/texture_progress.h b/scene/gui/texture_progress.h index 0d9b5e6b1..c0c2779cf 100644 --- a/scene/gui/texture_progress.h +++ b/scene/gui/texture_progress.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/texture_rect.cpp b/scene/gui/texture_rect.cpp index ea35ee8b5..92a3db6a7 100644 --- a/scene/gui/texture_rect.cpp +++ b/scene/gui/texture_rect.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/texture_rect.h b/scene/gui/texture_rect.h index 2cc6b97b1..dcc6c3f9b 100644 --- a/scene/gui/texture_rect.h +++ b/scene/gui/texture_rect.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/tool_button.cpp b/scene/gui/tool_button.cpp index 817b506f1..5fc4b6ecf 100644 --- a/scene/gui/tool_button.cpp +++ b/scene/gui/tool_button.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/tool_button.h b/scene/gui/tool_button.h index 02d2bfaef..d243b5559 100644 --- a/scene/gui/tool_button.h +++ b/scene/gui/tool_button.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 9a999c932..fa499ff27 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -27,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "tree.h" -#include "global_config.h" #include "os/input.h" #include "os/keyboard.h" #include "os/os.h" #include "print_string.h" +#include "project_settings.h" #include "scene/main/viewport.h" void TreeItem::move_to_top() { @@ -69,7 +70,7 @@ Size2 TreeItem::Cell::get_icon_size() const { return icon_region.size; } -void TreeItem::Cell::draw_icon(const RID &p_where, const Point2 &p_pos, const Size2 &p_size) const { +void TreeItem::Cell::draw_icon(const RID &p_where, const Point2 &p_pos, const Size2 &p_size, const Color &p_color) const { if (icon.is_null()) return; @@ -78,10 +79,10 @@ void TreeItem::Cell::draw_icon(const RID &p_where, const Point2 &p_pos, const Si if (icon_region == Rect2i()) { - icon->draw_rect_region(p_where, Rect2(p_pos, dsize), Rect2(Point2(), icon->get_size())); + icon->draw_rect_region(p_where, Rect2(p_pos, dsize), Rect2(Point2(), icon->get_size()), p_color); } else { - icon->draw_rect_region(p_where, Rect2(p_pos, dsize), icon_region); + icon->draw_rect_region(p_where, Rect2(p_pos, dsize), icon_region, p_color); } } @@ -202,6 +203,19 @@ Rect2 TreeItem::get_icon_region(int p_column) const { return cells[p_column].icon_region; } +void TreeItem::set_icon_color(int p_column, const Color &p_icon_color) { + + ERR_FAIL_INDEX(p_column, cells.size()); + cells[p_column].icon_color = p_icon_color; + _changed_notify(p_column); +} + +Color TreeItem::get_icon_color(int p_column) const { + + ERR_FAIL_INDEX_V(p_column, cells.size(), Color()); + return cells[p_column].icon_color; +} + void TreeItem::set_icon_max_width(int p_column, int p_max) { ERR_FAIL_INDEX(p_column, cells.size()); @@ -277,7 +291,7 @@ void TreeItem::set_custom_draw(int p_column, Object *p_object, const StringName ERR_FAIL_INDEX(p_column, cells.size()); ERR_FAIL_NULL(p_object); - cells[p_column].custom_draw_obj = p_object->get_instance_ID(); + cells[p_column].custom_draw_obj = p_object->get_instance_id(); cells[p_column].custom_draw_callback = p_callback; } @@ -463,7 +477,7 @@ void TreeItem::deselect(int p_column) { _cell_deselected(p_column); } -void TreeItem::add_button(int p_column, const Ref<Texture> &p_button, int p_id, bool p_disabled) { +void TreeItem::add_button(int p_column, const Ref<Texture> &p_button, int p_id, bool p_disabled, const String &p_tooltip) { ERR_FAIL_INDEX(p_column, cells.size()); ERR_FAIL_COND(!p_button.is_valid()); @@ -473,6 +487,7 @@ void TreeItem::add_button(int p_column, const Ref<Texture> &p_button, int p_id, p_id = cells[p_column].buttons.size(); button.id = p_id; button.disabled = p_disabled; + button.tooltip = p_tooltip; cells[p_column].buttons.push_back(button); _changed_notify(p_column); } @@ -608,6 +623,52 @@ Color TreeItem::get_custom_bg_color(int p_column) const { return cells[p_column].bg_color; } +void TreeItem::set_custom_as_button(int p_column, bool p_button) { + + ERR_FAIL_INDEX(p_column, cells.size()); + cells[p_column].custom_button = p_button; +} + +bool TreeItem::is_custom_set_as_button(int p_column) const { + + ERR_FAIL_INDEX_V(p_column, cells.size(), false); + return cells[p_column].custom_button; +} + +void TreeItem::set_text_align(int p_column, TextAlign p_align) { + ERR_FAIL_INDEX(p_column, cells.size()); + cells[p_column].text_align = p_align; + _changed_notify(p_column); +} + +TreeItem::TextAlign TreeItem::get_text_align(int p_column) const { + ERR_FAIL_INDEX_V(p_column, cells.size(), ALIGN_LEFT); + return cells[p_column].text_align; +} + +void TreeItem::set_expand_right(int p_column, bool p_enable) { + + ERR_FAIL_INDEX(p_column, cells.size()); + cells[p_column].expand_right = p_enable; + _changed_notify(p_column); +} + +bool TreeItem::get_expand_right(int p_column) const { + + ERR_FAIL_INDEX_V(p_column, cells.size(), false); + return cells[p_column].expand_right; +} + +void TreeItem::set_disable_folding(bool p_disable) { + + disable_folding = p_disable; + _changed_notify(0); +} + +bool TreeItem::is_folding_disabled() const { + return disable_folding; +} + void TreeItem::_bind_methods() { ClassDB::bind_method(D_METHOD("set_cell_mode", "column", "mode"), &TreeItem::set_cell_mode); @@ -619,8 +680,8 @@ void TreeItem::_bind_methods() { ClassDB::bind_method(D_METHOD("set_text", "column", "text"), &TreeItem::set_text); ClassDB::bind_method(D_METHOD("get_text", "column"), &TreeItem::get_text); - ClassDB::bind_method(D_METHOD("set_icon", "column", "texture:Texture"), &TreeItem::set_icon); - ClassDB::bind_method(D_METHOD("get_icon:Texture", "column"), &TreeItem::get_icon); + ClassDB::bind_method(D_METHOD("set_icon", "column", "texture"), &TreeItem::set_icon); + ClassDB::bind_method(D_METHOD("get_icon", "column"), &TreeItem::get_icon); ClassDB::bind_method(D_METHOD("set_icon_region", "column", "region"), &TreeItem::set_icon_region); ClassDB::bind_method(D_METHOD("get_icon_region", "column"), &TreeItem::get_icon_region); @@ -641,15 +702,15 @@ void TreeItem::_bind_methods() { ClassDB::bind_method(D_METHOD("set_collapsed", "enable"), &TreeItem::set_collapsed); ClassDB::bind_method(D_METHOD("is_collapsed"), &TreeItem::is_collapsed); - ClassDB::bind_method(D_METHOD("get_next:TreeItem"), &TreeItem::get_next); - ClassDB::bind_method(D_METHOD("get_prev:TreeItem"), &TreeItem::get_prev); - ClassDB::bind_method(D_METHOD("get_parent:TreeItem"), &TreeItem::get_parent); - ClassDB::bind_method(D_METHOD("get_children:TreeItem"), &TreeItem::get_children); + ClassDB::bind_method(D_METHOD("get_next"), &TreeItem::get_next); + ClassDB::bind_method(D_METHOD("get_prev"), &TreeItem::get_prev); + ClassDB::bind_method(D_METHOD("get_parent"), &TreeItem::get_parent); + ClassDB::bind_method(D_METHOD("get_children"), &TreeItem::get_children); - ClassDB::bind_method(D_METHOD("get_next_visible:TreeItem"), &TreeItem::get_next_visible); - ClassDB::bind_method(D_METHOD("get_prev_visible:TreeItem"), &TreeItem::get_prev_visible); + ClassDB::bind_method(D_METHOD("get_next_visible"), &TreeItem::get_next_visible); + ClassDB::bind_method(D_METHOD("get_prev_visible"), &TreeItem::get_prev_visible); - ClassDB::bind_method(D_METHOD("remove_child:TreeItem", "child"), &TreeItem::_remove_child); + ClassDB::bind_method(D_METHOD("remove_child", "child"), &TreeItem::_remove_child); ClassDB::bind_method(D_METHOD("set_selectable", "column", "selectable"), &TreeItem::set_selectable); ClassDB::bind_method(D_METHOD("is_selectable", "column"), &TreeItem::is_selectable); @@ -668,19 +729,29 @@ void TreeItem::_bind_methods() { ClassDB::bind_method(D_METHOD("clear_custom_bg_color", "column"), &TreeItem::clear_custom_bg_color); ClassDB::bind_method(D_METHOD("get_custom_bg_color", "column"), &TreeItem::get_custom_bg_color); - ClassDB::bind_method(D_METHOD("add_button", "column", "button:Texture", "button_idx", "disabled"), &TreeItem::add_button, DEFVAL(-1), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("set_custom_as_button", "column", "enable"), &TreeItem::set_custom_as_button); + ClassDB::bind_method(D_METHOD("is_custom_set_as_button", "column"), &TreeItem::is_custom_set_as_button); + + ClassDB::bind_method(D_METHOD("add_button", "column", "button", "button_idx", "disabled", "tooltip"), &TreeItem::add_button, DEFVAL(-1), DEFVAL(false), DEFVAL("")); ClassDB::bind_method(D_METHOD("get_button_count", "column"), &TreeItem::get_button_count); - ClassDB::bind_method(D_METHOD("get_button:Texture", "column", "button_idx"), &TreeItem::get_button); - ClassDB::bind_method(D_METHOD("set_button", "column", "button_idx", "button:Texture"), &TreeItem::set_button); + ClassDB::bind_method(D_METHOD("get_button", "column", "button_idx"), &TreeItem::get_button); + ClassDB::bind_method(D_METHOD("set_button", "column", "button_idx", "button"), &TreeItem::set_button); ClassDB::bind_method(D_METHOD("erase_button", "column", "button_idx"), &TreeItem::erase_button); ClassDB::bind_method(D_METHOD("is_button_disabled", "column", "button_idx"), &TreeItem::is_button_disabled); + ClassDB::bind_method(D_METHOD("set_expand_right", "column", "enable"), &TreeItem::set_expand_right); + ClassDB::bind_method(D_METHOD("get_expand_right", "column"), &TreeItem::get_expand_right); + ClassDB::bind_method(D_METHOD("set_tooltip", "column", "tooltip"), &TreeItem::set_tooltip); ClassDB::bind_method(D_METHOD("get_tooltip", "column"), &TreeItem::get_tooltip); - + ClassDB::bind_method(D_METHOD("set_text_align", "column", "text_align"), &TreeItem::set_text_align); + ClassDB::bind_method(D_METHOD("get_text_align", "column"), &TreeItem::get_text_align); ClassDB::bind_method(D_METHOD("move_to_top"), &TreeItem::move_to_top); ClassDB::bind_method(D_METHOD("move_to_bottom"), &TreeItem::move_to_bottom); + ClassDB::bind_method(D_METHOD("set_disable_folding", "disable"), &TreeItem::set_disable_folding); + ClassDB::bind_method(D_METHOD("is_folding_disabled"), &TreeItem::is_folding_disabled); + BIND_CONSTANT(CELL_MODE_STRING); BIND_CONSTANT(CELL_MODE_CHECK); BIND_CONSTANT(CELL_MODE_RANGE); @@ -707,6 +778,7 @@ TreeItem::TreeItem(Tree *p_tree) { tree = p_tree; collapsed = false; + disable_folding = false; parent = 0; // parent item next = 0; // next in list @@ -730,6 +802,10 @@ TreeItem::~TreeItem() { tree->pressing_for_editor = false; } + if (tree && tree->cache.hover_item == this) { + tree->cache.hover_item = NULL; + } + if (tree && tree->selected_item == this) tree->selected_item = NULL; @@ -770,6 +846,11 @@ void Tree::update_cache() { cache.select_arrow = get_icon("select_arrow"); cache.updown = get_icon("updown"); + cache.custom_button = get_stylebox("custom_button"); + cache.custom_button_hover = get_stylebox("custom_button_hover"); + cache.custom_button_pressed = get_stylebox("custom_button_pressed"); + cache.custom_button_font_highlight = get_color("custom_button_font_highlight"); + cache.font_color = get_color("font_color"); cache.font_color_selected = get_color("font_color_selected"); cache.guide_color = get_color("guide_color"); @@ -831,6 +912,9 @@ int Tree::compute_item_height(TreeItem *p_item) const { if (s.height > height) height = s.height; } + if (p_item->cells[i].mode == TreeItem::CELL_MODE_CUSTOM && p_item->cells[i].custom_button) { + height += cache.custom_button->get_minimum_size().height; + } } break; default: {} @@ -862,9 +946,35 @@ int Tree::get_item_height(TreeItem *p_item) const { return height; } -void Tree::draw_item_rect(const TreeItem::Cell &p_cell, const Rect2i &p_rect, const Color &p_color) { +void Tree::draw_item_rect(const TreeItem::Cell &p_cell, const Rect2i &p_rect, const Color &p_color, const Color &p_icon_color) { Rect2i rect = p_rect; + Ref<Font> font = cache.font; + String text = p_cell.text; + if (p_cell.suffix != String()) + text += " " + p_cell.suffix; + + int w = 0; + if (!p_cell.icon.is_null()) { + Size2i bmsize = p_cell.get_icon_size(); + + if (p_cell.icon_max_w > 0 && bmsize.width > p_cell.icon_max_w) { + bmsize.width = p_cell.icon_max_w; + } + w += bmsize.width + cache.hseparation; + } + w += font->get_string_size(text).width; + + switch (p_cell.text_align) { + case TreeItem::ALIGN_LEFT: + break; //do none + case TreeItem::ALIGN_CENTER: + rect.position.x = MAX(0, (rect.size.width - w) / 2); + break; //do none + case TreeItem::ALIGN_RIGHT: + rect.position.x = MAX(0, (rect.size.width - w)); + break; //do none + } RID ci = get_canvas_item(); if (!p_cell.icon.is_null()) { @@ -875,8 +985,8 @@ void Tree::draw_item_rect(const TreeItem::Cell &p_cell, const Rect2i &p_rect, co bmsize.width = p_cell.icon_max_w; } - p_cell.draw_icon(ci, rect.pos + Size2i(0, Math::floor((real_t)(rect.size.y - bmsize.y) / 2)), bmsize); - rect.pos.x += bmsize.x + cache.hseparation; + p_cell.draw_icon(ci, rect.position + Size2i(0, Math::floor((real_t)(rect.size.y - bmsize.y) / 2)), bmsize, p_icon_color); + rect.position.x += bmsize.x + cache.hseparation; rect.size.x -= bmsize.x + cache.hseparation; } @@ -885,14 +995,8 @@ void Tree::draw_item_rect(const TreeItem::Cell &p_cell, const Rect2i &p_rect, co rect.size.x-=Math::floor(rect.size.y/2); */ - Ref<Font> font = cache.font; - - String text = p_cell.text; - if (p_cell.suffix != String()) - text += " " + p_cell.suffix; - - rect.pos.y += Math::floor((rect.size.y - font->get_height()) / 2.0) + font->get_ascent(); - font->draw(ci, rect.pos, text, p_color, rect.size.x); + rect.position.y += Math::floor((rect.size.y - font->get_height()) / 2.0) + font->get_ascent(); + font->draw(ci, rect.position, text, p_color, rect.size.x); } #if 0 @@ -941,20 +1045,6 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 if (!skip && (p_pos.y + label_h - cache.offset.y) > 0) { - if (!hide_folding && p_item->childs) { //has childs, draw the guide box - - Ref<Texture> arrow; - - if (p_item->collapsed) { - - arrow = cache.arrow_collapsed; - } else { - arrow = cache.arrow; - } - - arrow->draw(ci, p_pos + p_draw_ofs + Point2i(0, (label_h - arrow->get_height()) / 2) - cache.offset); - } - //draw separation. //if (p_item->get_parent()!=root || !hide_root) @@ -962,9 +1052,15 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 int font_ascent = font->get_ascent(); - int ofs = p_pos.x + (hide_folding ? cache.hseparation : cache.item_margin); + int ofs = p_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin); + int skip = 0; for (int i = 0; i < columns.size(); i++) { + if (skip) { + skip--; + continue; + } + int w = get_column_width(i); if (i == 0) { @@ -982,6 +1078,16 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 w -= cache.hseparation; } + if (p_item->cells[i].expand_right) { + + int plus = 1; + while (i + plus < columns.size() && !p_item->cells[i + plus].editable && p_item->cells[i + plus].mode == TreeItem::CELL_MODE_STRING && p_item->cells[i + plus].text == "" && p_item->cells[i + plus].icon.is_null()) { + w += get_column_width(i + plus); + plus++; + skip++; + } + } + int bw = 0; for (int j = p_item->cells[i].buttons.size() - 1; j >= 0; j--) { Ref<Texture> b = p_item->cells[i].buttons[j].texture; @@ -1005,16 +1111,16 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 Rect2i item_rect = Rect2i(Point2i(ofs, p_pos.y) - cache.offset + p_draw_ofs, Size2i(w, label_h)); Rect2i cell_rect = item_rect; if (i != 0) { - cell_rect.pos.x -= cache.hseparation; + cell_rect.position.x -= cache.hseparation; cell_rect.size.x += cache.hseparation; } - VisualServer::get_singleton()->canvas_item_add_line(ci, Point2i(cell_rect.pos.x, cell_rect.pos.y + cell_rect.size.height), cell_rect.pos + cell_rect.size, cache.guide_color, 1); + VisualServer::get_singleton()->canvas_item_add_line(ci, Point2i(cell_rect.position.x, cell_rect.position.y + cell_rect.size.height), cell_rect.position + cell_rect.size, cache.guide_color, 1); if (i == 0) { if (p_item->cells[0].selected && select_mode == SELECT_ROW) { - Rect2i row_rect = Rect2i(Point2i(cache.bg->get_margin(MARGIN_LEFT), item_rect.pos.y), Size2i(get_size().width - cache.bg->get_minimum_size().width, item_rect.size.y)); + Rect2i row_rect = Rect2i(Point2i(cache.bg->get_margin(MARGIN_LEFT), item_rect.position.y), Size2i(get_size().width - cache.bg->get_minimum_size().width, item_rect.size.y)); //Rect2 r = Rect2i(row_rect.pos,row_rect.size); //r.grow(cache.selected->get_margin(MARGIN_LEFT)); if (has_focus()) @@ -1026,34 +1132,39 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 if (p_item->cells[i].selected && select_mode != SELECT_ROW) { - Rect2i r(item_rect.pos, item_rect.size); + Rect2i r(item_rect.position, item_rect.size); if (p_item->cells[i].text.size() > 0) { float icon_width = p_item->cells[i].get_icon_size().width; - r.pos.x += icon_width; + r.position.x += icon_width; r.size.x -= icon_width; } //r.grow(cache.selected->get_margin(MARGIN_LEFT)); if (has_focus()) { cache.selected_focus->draw(ci, r); - p_item->set_meta("__focus_rect", Rect2(r.pos, r.size)); + p_item->set_meta("__focus_rect", Rect2(r.position, r.size)); } else { cache.selected->draw(ci, r); } if (text_editor->is_visible_in_tree()) { - text_editor->set_pos(get_global_pos() + r.pos); + text_editor->set_position(get_global_position() + r.position); } } if (p_item->cells[i].custom_bg_color) { Rect2 r = cell_rect; - r.pos.x -= cache.hseparation; - r.size.x += cache.hseparation; + if (i == 0) { + r.position.x = p_draw_ofs.x; + r.size.x = w + ofs; + } else { + r.position.x -= cache.hseparation; + r.size.x += cache.hseparation; + } if (p_item->cells[i].custom_bg_outline) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.pos.x, r.pos.y, r.size.x, 1), p_item->cells[i].bg_color); - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.pos.x, r.pos.y + r.size.y - 1, r.size.x, 1), p_item->cells[i].bg_color); - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.pos.x, r.pos.y, 1, r.size.y), p_item->cells[i].bg_color); - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.pos.x + r.size.x - 1, r.pos.y, 1, r.size.y), p_item->cells[i].bg_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, r.size.x, 1), p_item->cells[i].bg_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y + r.size.y - 1, r.size.x, 1), p_item->cells[i].bg_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, 1, r.size.y), p_item->cells[i].bg_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x + r.size.x - 1, r.position.y, 1, r.size.y), p_item->cells[i].bg_color); } else { VisualServer::get_singleton()->canvas_item_add_rect(ci, r, p_item->cells[i].bg_color); } @@ -1064,42 +1175,43 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 Rect2 r = cell_rect; if (drop_mode_section == -1 || drop_mode_section == 0) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.pos.x, r.pos.y, r.size.x, 1), cache.drop_position_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, r.size.x, 1), cache.drop_position_color); } if (drop_mode_section == 0) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.pos.x, r.pos.y, 1, r.size.y), cache.drop_position_color); - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.pos.x + r.size.x - 1, r.pos.y, 1, r.size.y), cache.drop_position_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, 1, r.size.y), cache.drop_position_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x + r.size.x - 1, r.position.y, 1, r.size.y), cache.drop_position_color); } if (drop_mode_section == 1 || drop_mode_section == 0) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.pos.x, r.pos.y + r.size.y, r.size.x, 1), cache.drop_position_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y + r.size.y, r.size.x, 1), cache.drop_position_color); } } Color col = p_item->cells[i].custom_color ? p_item->cells[i].color : get_color(p_item->cells[i].selected ? "font_color_selected" : "font_color"); + Color icon_col = p_item->cells[i].icon_color; - Point2i text_pos = item_rect.pos; + Point2i text_pos = item_rect.position; text_pos.y += Math::floor((item_rect.size.y - font->get_height()) / 2) + font_ascent; switch (p_item->cells[i].mode) { case TreeItem::CELL_MODE_STRING: { - draw_item_rect(p_item->cells[i], item_rect, col); + draw_item_rect(p_item->cells[i], item_rect, col, icon_col); } break; case TreeItem::CELL_MODE_CHECK: { Ref<Texture> checked = cache.checked; Ref<Texture> unchecked = cache.unchecked; - Point2i check_ofs = item_rect.pos; + Point2i check_ofs = item_rect.position; check_ofs.y += Math::floor((real_t)(item_rect.size.y - checked->get_height()) / 2); if (p_item->cells[i].checked) { - checked->draw(ci, check_ofs); + checked->draw(ci, check_ofs, icon_col); } else { - unchecked->draw(ci, check_ofs); + unchecked->draw(ci, check_ofs, icon_col); } int check_w = checked->get_width() + cache.hseparation; @@ -1107,9 +1219,9 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 text_pos.x += check_w; item_rect.size.x -= check_w; - item_rect.pos.x += check_w; + item_rect.position.x += check_w; - draw_item_rect(p_item->cells[i], item_rect, col); + draw_item_rect(p_item->cells[i], item_rect, col, icon_col); //font->draw( ci, text_pos, p_item->cells[i].text, col,item_rect.size.x-check_w ); @@ -1135,11 +1247,11 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 font->draw(ci, text_pos, s, col, item_rect.size.x - downarrow->get_width()); //? - Point2i arrow_pos = item_rect.pos; + Point2i arrow_pos = item_rect.position; arrow_pos.x += item_rect.size.x - downarrow->get_width(); arrow_pos.y += Math::floor(((item_rect.size.y - downarrow->get_height())) / 2.0); - downarrow->draw(ci, arrow_pos); + downarrow->draw(ci, arrow_pos, icon_col); } else { Ref<Texture> updown = cache.updown; @@ -1155,11 +1267,11 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 if (!p_item->cells[i].editable) break; - Point2i updown_pos = item_rect.pos; + Point2i updown_pos = item_rect.position; updown_pos.x += item_rect.size.x - updown->get_width(); updown_pos.y += Math::floor(((item_rect.size.y - updown->get_height())) / 2.0); - updown->draw(ci, updown_pos); + updown->draw(ci, updown_pos, icon_col); } } break; @@ -1174,9 +1286,9 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 } Point2i icon_ofs = (item_rect.size - icon_size) / 2; - icon_ofs += item_rect.pos; + icon_ofs += item_rect.position; - draw_texture_rect(p_item->cells[i].icon, Rect2(icon_ofs, icon_size)); + draw_texture_rect(p_item->cells[i].icon, Rect2(icon_ofs, icon_size), false, icon_col); //p_item->cells[i].icon->draw(ci, icon_ofs); } break; @@ -1193,19 +1305,35 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 if (!p_item->cells[i].editable) { - draw_item_rect(p_item->cells[i], item_rect, col); + draw_item_rect(p_item->cells[i], item_rect, col, icon_col); break; } Ref<Texture> downarrow = cache.select_arrow; Rect2i ir = item_rect; - ir.size.width -= downarrow->get_width(); - draw_item_rect(p_item->cells[i], ir, col); - Point2i arrow_pos = item_rect.pos; + Point2i arrow_pos = item_rect.position; arrow_pos.x += item_rect.size.x - downarrow->get_width(); arrow_pos.y += Math::floor(((item_rect.size.y - downarrow->get_height())) / 2.0); + ir.size.width -= downarrow->get_width(); + + if (p_item->cells[i].custom_button) { + if (cache.hover_item == p_item && cache.hover_cell == i) { + if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) { + draw_style_box(cache.custom_button_pressed, ir); + } else { + draw_style_box(cache.custom_button_hover, ir); + col = cache.custom_button_font_highlight; + } + } else { + draw_style_box(cache.custom_button, ir); + } + ir.size -= cache.custom_button->get_minimum_size(); + ir.position += cache.custom_button->get_offset(); + } + + draw_item_rect(p_item->cells[i], ir, col, icon_col); downarrow->draw(ci, arrow_pos); @@ -1229,6 +1357,19 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 } } + if (!p_item->disable_folding && !hide_folding && p_item->childs) { //has childs, draw the guide box + + Ref<Texture> arrow; + + if (p_item->collapsed) { + + arrow = cache.arrow_collapsed; + } else { + arrow = cache.arrow; + } + + arrow->draw(ci, p_pos + p_draw_ofs + Point2i(0, (label_h - arrow->get_height()) / 2) - cache.offset); + } //separator //get_painter()->draw_fill_rect( Point2i(0,pos.y),Size2i(get_size().width,1),color( COLOR_TREE_GRID) ); @@ -1250,8 +1391,8 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 while (c) { if (cache.draw_relationship_lines == 1) { - int root_ofs = children_pos.x + (hide_folding ? cache.hseparation : cache.item_margin); - int parent_ofs = p_pos.x + (hide_folding ? cache.hseparation : cache.item_margin); + int root_ofs = children_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin); + int parent_ofs = p_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin); Point2i root_pos = Point2i(root_ofs, children_pos.y + label_h / 2) - cache.offset + p_draw_ofs; if (c->get_children() != NULL) root_pos -= Point2i(cache.arrow->get_width(), 0); @@ -1337,7 +1478,7 @@ void Tree::select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_c if (!r_in_range && &selected_cell == &c) { - if (!selected_cell.selected) { + if (!selected_cell.selected || force_select_on_already_selected) { selected_cell.selected = true; @@ -1408,10 +1549,12 @@ void Tree::_range_click_timeout() { } click_handled = false; - InputModifierState mod = InputModifierState(); // should be irrelevant.. + Ref<InputEventMouseButton> mb; + mb.instance(); + ; blocked++; - propagate_mouse_event(pos + cache.offset, 0, 0, false, root, BUTTON_LEFT, mod); + propagate_mouse_event(pos + cache.offset, 0, 0, false, root, BUTTON_LEFT, mb); blocked--; if (range_click_timer->is_one_shot()) { @@ -1428,7 +1571,7 @@ void Tree::_range_click_timeout() { } } -int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool p_doubleclick, TreeItem *p_item, int p_button, const InputModifierState &p_mod) { +int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool p_doubleclick, TreeItem *p_item, int p_button, const Ref<InputEventWithModifiers> &p_mod) { int item_h = compute_item_height(p_item) + cache.vseparation; @@ -1441,7 +1584,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool return -1; } - if (!hide_folding && (p_pos.x >= x_ofs && p_pos.x < (x_ofs + cache.item_margin))) { + if (!p_item->disable_folding && !hide_folding && (p_pos.x >= x_ofs && p_pos.x < (x_ofs + cache.item_margin))) { if (p_item->childs) p_item->set_collapsed(!p_item->is_collapsed()); @@ -1457,6 +1600,17 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool for (int i = 0; i < columns.size(); i++) { col_width = get_column_width(i); + + if (p_item->cells[i].expand_right) { + + int plus = 1; + while (i + plus < columns.size() && !p_item->cells[i + plus].editable && p_item->cells[i + plus].mode == TreeItem::CELL_MODE_STRING && p_item->cells[i + plus].text == "" && p_item->cells[i + plus].icon.is_null()) { + col_width += cache.hseparation; + col_width += get_column_width(i + plus); + plus++; + } + } + if (x > col_width) { col_ofs += col_width; x -= col_width; @@ -1481,6 +1635,11 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool x -= cache.hseparation; } + if (!p_item->disable_folding && !hide_folding && !p_item->cells[col].editable && !p_item->cells[col].selectable && p_item->get_children()) { + p_item->set_collapsed(!p_item->is_collapsed()); + return -1; //collapse/uncollapse because nothing can be done with item + } + TreeItem::Cell &c = p_item->cells[col]; bool already_selected = c.selected; @@ -1502,7 +1661,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool cache.click_id = c.buttons[j].id; cache.click_item = p_item; cache.click_column = col; - cache.click_pos = get_global_mouse_pos() - get_global_pos(); + cache.click_pos = get_global_mouse_position() - get_global_position(); update(); //emit_signal("button_pressed"); return -1; @@ -1516,10 +1675,11 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool if (p_doubleclick && (!c.editable || c.mode == TreeItem::CELL_MODE_CUSTOM || c.mode == TreeItem::CELL_MODE_ICON /*|| c.mode==TreeItem::CELL_MODE_CHECK*/)) { //it' s confusing for check emit_signal("item_activated"); + incr_search.clear(); return -1; } - if (select_mode == SELECT_MULTI && p_mod.command && c.selectable) { + if (select_mode == SELECT_MULTI && p_mod->get_command() && c.selectable) { if (!c.selected || p_button == BUTTON_RIGHT) { @@ -1541,7 +1701,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool if (c.selectable) { - if (select_mode == SELECT_MULTI && p_mod.shift && selected_item && selected_item != p_item) { + if (select_mode == SELECT_MULTI && p_mod->get_shift() && selected_item && selected_item != p_item) { bool inrange = false; @@ -1626,7 +1786,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool } popup_menu->set_size(Size2(col_width, 0)); - popup_menu->set_pos(get_global_pos() + Point2i(col_ofs, _get_title_button_height() + y_ofs + item_h) - cache.offset); + popup_menu->set_position(get_global_position() + Point2i(col_ofs, _get_title_button_height() + y_ofs + item_h) - cache.offset); popup_menu->popup(); popup_edited_item = p_item; popup_edited_item_col = col; @@ -1692,11 +1852,19 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool case TreeItem::CELL_MODE_CUSTOM: { edited_item = p_item; edited_col = col; - custom_popup_rect = Rect2i(get_global_pos() + Point2i(col_ofs, _get_title_button_height() + y_ofs + item_h - cache.offset.y), Size2(get_column_width(col), item_h)); - emit_signal("custom_popup_edited", ((bool)(x >= (col_width - item_h / 2)))); + bool on_arrow = x > col_width - cache.select_arrow->get_width(); bring_up_editor = false; - item_edited(col, p_item); + + custom_popup_rect = Rect2i(get_global_position() + Point2i(col_ofs, _get_title_button_height() + y_ofs + item_h - cache.offset.y), Size2(get_column_width(col), item_h)); + + if (on_arrow || !p_item->cells[col].custom_button) { + emit_signal("custom_popup_edited", ((bool)(x >= (col_width - item_h / 2)))); + } + + if (!p_item->cells[col].custom_button || !on_arrow) { + item_edited(col, p_item, p_button == BUTTON_LEFT); + } click_handled = true; return -1; } break; @@ -1709,7 +1877,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool popup_edited_item = p_item; popup_edited_item_col = col; - pressing_item_rect = Rect2(get_global_pos() + Point2i(col_ofs, _get_title_button_height() + y_ofs) - cache.offset, Size2(col_width, item_h)); + pressing_item_rect = Rect2(get_global_position() + Point2i(col_ofs, _get_title_button_height() + y_ofs) - cache.offset, Size2(col_width, item_h)); pressing_for_editor_text = editor_text; pressing_for_editor = true; @@ -1750,8 +1918,8 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool void Tree::_text_editor_modal_close() { if (Input::get_singleton()->is_key_pressed(KEY_ESCAPE) || - Input::get_singleton()->is_key_pressed(KEY_ENTER) || - Input::get_singleton()->is_key_pressed(KEY_RETURN)) { + Input::get_singleton()->is_key_pressed(KEY_KP_ENTER) || + Input::get_singleton()->is_key_pressed(KEY_ENTER)) { return; } @@ -1799,6 +1967,14 @@ void Tree::text_editor_enter(String p_text) { c.val = evaluator->eval(p_text); else c.val = p_text.to_double(); + + if (c.step > 0) + c.val = Math::stepify(c.val, c.step); + if (c.val < c.min) + c.val = c.min; + else if (c.val > c.max) + c.val = c.max; + } break; default: { ERR_FAIL(); } } @@ -1836,516 +2012,540 @@ void Tree::popup_select(int p_option) { item_edited(popup_edited_item_col, popup_edited_item); } -void Tree::_gui_input(InputEvent p_event) { +void Tree::_gui_input(Ref<InputEvent> p_event) { - switch (p_event.type) { + Ref<InputEventKey> k = p_event; - case InputEvent::KEY: { + if (k.is_valid()) { - if (!p_event.key.pressed) - break; - if (p_event.key.mod.alt || p_event.key.mod.command || (p_event.key.mod.shift && p_event.key.unicode == 0) || p_event.key.mod.meta) - break; - if (!root) - return; + if (!k->is_pressed()) + return; + if (k->get_alt() || k->get_command() || (k->get_shift() && k->get_unicode() == 0) || k->get_metakey()) + return; + if (!root) + return; - if (hide_root && !root->get_next_visible()) - return; + if (hide_root && !root->get_next_visible()) + return; - switch (p_event.key.scancode) { + switch (k->get_scancode()) { #define EXIT_BREAK \ { \ if (!cursor_can_exit_tree) accept_event(); \ break; \ } - case KEY_RIGHT: { + case KEY_RIGHT: { - //TreeItem *next = NULL; - if (!selected_item) - break; - if (select_mode == SELECT_ROW) - EXIT_BREAK; - if (selected_col >= (columns.size() - 1)) - EXIT_BREAK; - if (select_mode == SELECT_MULTI) { - selected_col++; - emit_signal("cell_selected"); - } else { + //TreeItem *next = NULL; + if (!selected_item) + break; + if (select_mode == SELECT_ROW) + EXIT_BREAK; + if (selected_col >= (columns.size() - 1)) + EXIT_BREAK; + if (select_mode == SELECT_MULTI) { + selected_col++; + emit_signal("cell_selected"); + } else { - selected_item->select(selected_col + 1); - } + selected_item->select(selected_col + 1); + } - update(); - ensure_cursor_is_visible(); - accept_event(); + update(); + ensure_cursor_is_visible(); + accept_event(); - } break; - case KEY_LEFT: { + } break; + case KEY_LEFT: { - //TreeItem *next = NULL; - if (!selected_item) - break; - if (select_mode == SELECT_ROW) - EXIT_BREAK; - if (selected_col <= 0) - EXIT_BREAK; - if (select_mode == SELECT_MULTI) { - selected_col--; - emit_signal("cell_selected"); - } else { + //TreeItem *next = NULL; + if (!selected_item) + break; + if (select_mode == SELECT_ROW) + EXIT_BREAK; + if (selected_col <= 0) + EXIT_BREAK; + if (select_mode == SELECT_MULTI) { + selected_col--; + emit_signal("cell_selected"); + } else { - selected_item->select(selected_col - 1); - } + selected_item->select(selected_col - 1); + } - update(); - accept_event(); + update(); + accept_event(); - } break; - case KEY_DOWN: { + } break; + case KEY_DOWN: { - TreeItem *next = NULL; - if (!selected_item) { + TreeItem *next = NULL; + if (!selected_item) { - next = hide_root ? root->get_next_visible() : root; - selected_item = 0; - } else { + next = hide_root ? root->get_next_visible() : root; + selected_item = 0; + } else { - next = selected_item->get_next_visible(); + next = selected_item->get_next_visible(); - //if (diff < uint64_t(GLOBAL_DEF("gui/incr_search_max_interval_msec",2000))) { - if (last_keypress != 0) { - //incr search next - int col; - next = _search_item_text(next, incr_search, &col, true); - if (!next) { - accept_event(); - return; - } + //if (diff < uint64_t(GLOBAL_DEF("gui/incr_search_max_interval_msec",2000))) { + if (last_keypress != 0) { + //incr search next + int col; + next = _search_item_text(next, incr_search, &col, true); + if (!next) { + accept_event(); + return; } } + } - if (select_mode == SELECT_MULTI) { + if (select_mode == SELECT_MULTI) { - if (!next) - EXIT_BREAK; + if (!next) + EXIT_BREAK; - selected_item = next; - emit_signal("cell_selected"); - update(); - } else { + selected_item = next; + emit_signal("cell_selected"); + update(); + } else { - int col = selected_col < 0 ? 0 : selected_col; + int col = selected_col < 0 ? 0 : selected_col; - while (next && !next->cells[col].selectable) - next = next->get_next_visible(); - if (!next) - EXIT_BREAK; // do nothing.. - next->select(col); - } + while (next && !next->cells[col].selectable) + next = next->get_next_visible(); + if (!next) + EXIT_BREAK; // do nothing.. + next->select(col); + } - ensure_cursor_is_visible(); - accept_event(); + ensure_cursor_is_visible(); + accept_event(); - } break; - case KEY_UP: { + } break; + case KEY_UP: { - TreeItem *prev = NULL; - if (!selected_item) { - prev = get_last_item(); - selected_col = 0; - } else { + TreeItem *prev = NULL; + if (!selected_item) { + prev = get_last_item(); + selected_col = 0; + } else { - prev = selected_item->get_prev_visible(); - if (last_keypress != 0) { - //incr search next - int col; - prev = _search_item_text(prev, incr_search, &col, true, true); - if (!prev) { - accept_event(); - return; - } + prev = selected_item->get_prev_visible(); + if (last_keypress != 0) { + //incr search next + int col; + prev = _search_item_text(prev, incr_search, &col, true, true); + if (!prev) { + accept_event(); + return; } } + } - if (select_mode == SELECT_MULTI) { + if (select_mode == SELECT_MULTI) { - if (!prev) - break; - selected_item = prev; - emit_signal("cell_selected"); - update(); - } else { + if (!prev) + break; + selected_item = prev; + emit_signal("cell_selected"); + update(); + } else { - int col = selected_col < 0 ? 0 : selected_col; - while (prev && !prev->cells[col].selectable) - prev = prev->get_prev_visible(); - if (!prev) - break; // do nothing.. - prev->select(col); - } + int col = selected_col < 0 ? 0 : selected_col; + while (prev && !prev->cells[col].selectable) + prev = prev->get_prev_visible(); + if (!prev) + break; // do nothing.. + prev->select(col); + } - ensure_cursor_is_visible(); - accept_event(); + ensure_cursor_is_visible(); + accept_event(); - } break; - case KEY_PAGEDOWN: { + } break; + case KEY_PAGEDOWN: { - TreeItem *next = NULL; - if (!selected_item) - break; - next = selected_item; + TreeItem *next = NULL; + if (!selected_item) + break; + next = selected_item; - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 10; i++) { - TreeItem *_n = next->get_next_visible(); - if (_n) { - next = _n; - } else { + TreeItem *_n = next->get_next_visible(); + if (_n) { + next = _n; + } else { - break; - } - } - if (next == selected_item) break; + } + } + if (next == selected_item) + break; - if (select_mode == SELECT_MULTI) { + if (select_mode == SELECT_MULTI) { - selected_item = next; - emit_signal("cell_selected"); - update(); - } else { + selected_item = next; + emit_signal("cell_selected"); + update(); + } else { - while (next && !next->cells[selected_col].selectable) - next = next->get_next_visible(); - if (!next) - EXIT_BREAK; // do nothing.. - next->select(selected_col); - } + while (next && !next->cells[selected_col].selectable) + next = next->get_next_visible(); + if (!next) + EXIT_BREAK; // do nothing.. + next->select(selected_col); + } - ensure_cursor_is_visible(); - } break; - case KEY_PAGEUP: { + ensure_cursor_is_visible(); + } break; + case KEY_PAGEUP: { - TreeItem *prev = NULL; - if (!selected_item) - break; - prev = selected_item; + TreeItem *prev = NULL; + if (!selected_item) + break; + prev = selected_item; - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 10; i++) { - TreeItem *_n = prev->get_prev_visible(); - if (_n) { - prev = _n; - } else { + TreeItem *_n = prev->get_prev_visible(); + if (_n) { + prev = _n; + } else { - break; - } - } - if (prev == selected_item) break; + } + } + if (prev == selected_item) + break; - if (select_mode == SELECT_MULTI) { + if (select_mode == SELECT_MULTI) { - selected_item = prev; - emit_signal("cell_selected"); - update(); - } else { + selected_item = prev; + emit_signal("cell_selected"); + update(); + } else { - while (prev && !prev->cells[selected_col].selectable) - prev = prev->get_prev_visible(); - if (!prev) - EXIT_BREAK; // do nothing.. - prev->select(selected_col); - } + while (prev && !prev->cells[selected_col].selectable) + prev = prev->get_prev_visible(); + if (!prev) + EXIT_BREAK; // do nothing.. + prev->select(selected_col); + } - ensure_cursor_is_visible(); + ensure_cursor_is_visible(); - } break; - case KEY_F2: - case KEY_RETURN: - case KEY_ENTER: { + } break; + case KEY_F2: + case KEY_ENTER: + case KEY_KP_ENTER: { - if (selected_item) { - //bring up editor if possible - if (!edit_selected()) { - emit_signal("item_activated"); - } + if (selected_item) { + //bring up editor if possible + if (!edit_selected()) { + emit_signal("item_activated"); + incr_search.clear(); } - accept_event(); + } + accept_event(); - } break; - case KEY_SPACE: { - if (select_mode == SELECT_MULTI) { - if (!selected_item) - break; - if (selected_item->is_selected(selected_col)) { - selected_item->deselect(selected_col); - emit_signal("multi_selected", selected_item, selected_col, false); - } else if (selected_item->is_selectable(selected_col)) { - selected_item->select(selected_col); - emit_signal("multi_selected", selected_item, selected_col, true); - } + } break; + case KEY_SPACE: { + if (select_mode == SELECT_MULTI) { + if (!selected_item) + break; + if (selected_item->is_selected(selected_col)) { + selected_item->deselect(selected_col); + emit_signal("multi_selected", selected_item, selected_col, false); + } else if (selected_item->is_selectable(selected_col)) { + selected_item->select(selected_col); + emit_signal("multi_selected", selected_item, selected_col, true); } - accept_event(); + } + accept_event(); - } break; - default: { + } break; + default: { - if (p_event.key.unicode > 0) { + if (k->get_unicode() > 0) { - _do_incr_search(String::chr(p_event.key.unicode)); - accept_event(); + _do_incr_search(String::chr(k->get_unicode())); + accept_event(); - return; - } else { - if (p_event.key.scancode != KEY_SHIFT) - last_keypress = 0; - } - } break; + return; + } else { + if (k->get_scancode() != KEY_SHIFT) + last_keypress = 0; + } + } break; - last_keypress = 0; - } + last_keypress = 0; + } + } - } break; + Ref<InputEventMouseMotion> mm = p_event; - case InputEvent::MOUSE_MOTION: { + if (mm.is_valid()) { - if (cache.font.is_null()) // avoid a strange case that may fuckup stuff - update_cache(); - const InputEventMouseMotion &b = p_event.mouse_motion; + if (cache.font.is_null()) // avoid a strange case that may fuckup stuff + update_cache(); - Ref<StyleBox> bg = cache.bg; + Ref<StyleBox> bg = cache.bg; - Point2 pos = Point2(b.x, b.y) - bg->get_offset(); + Point2 pos = mm->get_position() - bg->get_offset(); - Cache::ClickType old_hover = cache.hover_type; - int old_index = cache.hover_index; + Cache::ClickType old_hover = cache.hover_type; + int old_index = cache.hover_index; - cache.hover_type = Cache::CLICK_NONE; - cache.hover_index = 0; - if (show_column_titles) { - pos.y -= _get_title_button_height(); - if (pos.y < 0) { - pos.x += cache.offset.x; - int len = 0; - for (int i = 0; i < columns.size(); i++) { + cache.hover_type = Cache::CLICK_NONE; + cache.hover_index = 0; + if (show_column_titles) { + pos.y -= _get_title_button_height(); + if (pos.y < 0) { + pos.x += cache.offset.x; + int len = 0; + for (int i = 0; i < columns.size(); i++) { - len += get_column_width(i); - if (pos.x < len) { + len += get_column_width(i); + if (pos.x < len) { - cache.hover_type = Cache::CLICK_TITLE; - cache.hover_index = i; - update(); - break; - } + cache.hover_type = Cache::CLICK_TITLE; + cache.hover_index = i; + update(); + break; } } } + } - if (drop_mode_flags && root) { + if (root) { - Point2 mpos = Point2(b.x, b.y); - mpos -= cache.bg->get_offset(); - mpos.y -= _get_title_button_height(); - if (mpos.y >= 0) { + Point2 mpos = mm->get_position(); + mpos -= cache.bg->get_offset(); + mpos.y -= _get_title_button_height(); + if (mpos.y >= 0) { - if (h_scroll->is_visible_in_tree()) - mpos.x += h_scroll->get_value(); - if (v_scroll->is_visible_in_tree()) - mpos.y += v_scroll->get_value(); + if (h_scroll->is_visible_in_tree()) + mpos.x += h_scroll->get_value(); + if (v_scroll->is_visible_in_tree()) + mpos.y += v_scroll->get_value(); - int col, h, section; - TreeItem *it = _find_item_at_pos(root, mpos, col, h, section); + int col, h, section; + TreeItem *it = _find_item_at_pos(root, mpos, col, h, section); - if (it != drop_mode_over || section != drop_mode_section) { - drop_mode_over = it; - drop_mode_section = section; - update(); - } + if (drop_mode_flags && it != drop_mode_over || section != drop_mode_section) { + drop_mode_over = it; + drop_mode_section = section; + update(); } - } - if (cache.hover_type != old_hover || cache.hover_index != old_index) { - update(); + if (it != cache.hover_item || col != cache.hover_cell) { + cache.hover_item = it; + cache.hover_cell = col; + update(); + } } + } - if (pressing_for_editor && popup_edited_item && (popup_edited_item->get_cell_mode(popup_edited_item_col) == TreeItem::CELL_MODE_RANGE || popup_edited_item->get_cell_mode(popup_edited_item_col) == TreeItem::CELL_MODE_RANGE_EXPRESSION)) { - //range drag + if (cache.hover_type != old_hover || cache.hover_index != old_index) { + update(); + } - if (!range_drag_enabled) { + if (pressing_for_editor && popup_edited_item && (popup_edited_item->get_cell_mode(popup_edited_item_col) == TreeItem::CELL_MODE_RANGE || popup_edited_item->get_cell_mode(popup_edited_item_col) == TreeItem::CELL_MODE_RANGE_EXPRESSION)) { + //range drag - Vector2 cpos = Vector2(b.x, b.y); - if (cpos.distance_to(pressing_pos) > 2) { - range_drag_enabled = true; - range_drag_capture_pos = cpos; - range_drag_base = popup_edited_item->get_range(popup_edited_item_col); - Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED); - } - } else { + if (!range_drag_enabled) { - TreeItem::Cell &c = popup_edited_item->cells[popup_edited_item_col]; - float diff_y = -b.relative_y; - diff_y = Math::pow(ABS(diff_y), 1.8f) * SGN(diff_y); - diff_y *= 0.1; - range_drag_base = CLAMP(range_drag_base + c.step * diff_y, c.min, c.max); - popup_edited_item->set_range(popup_edited_item_col, range_drag_base); - item_edited(popup_edited_item_col, popup_edited_item); + Vector2 cpos = mm->get_position(); + if (cpos.distance_to(pressing_pos) > 2) { + range_drag_enabled = true; + range_drag_capture_pos = cpos; + range_drag_base = popup_edited_item->get_range(popup_edited_item_col); + Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED); } + } else { + + TreeItem::Cell &c = popup_edited_item->cells[popup_edited_item_col]; + float diff_y = -mm->get_relative().y; + diff_y = Math::pow(ABS(diff_y), 1.8f) * SGN(diff_y); + diff_y *= 0.1; + range_drag_base = CLAMP(range_drag_base + c.step * diff_y, c.min, c.max); + popup_edited_item->set_range(popup_edited_item_col, range_drag_base); + item_edited(popup_edited_item_col, popup_edited_item); } + } - if (drag_touching && !drag_touching_deaccel) { + if (drag_touching && !drag_touching_deaccel) { - drag_accum -= b.relative_y; - v_scroll->set_value(drag_from + drag_accum); - drag_speed = -b.speed_y; - } - } break; - case InputEvent::MOUSE_BUTTON: { + drag_accum -= mm->get_relative().y; + v_scroll->set_value(drag_from + drag_accum); + drag_speed = -mm->get_speed().y; + } + } + + Ref<InputEventMouseButton> b = p_event; + + if (b.is_valid()) { + if (cache.font.is_null()) // avoid a strange case that may fuckup stuff + update_cache(); + + if (!b->is_pressed()) { - if (cache.font.is_null()) // avoid a strange case that may fuckup stuff - update_cache(); - const InputEventMouseButton &b = p_event.mouse_button; + if (b->get_button_index() == BUTTON_LEFT) { - if (!b.pressed) { + Point2 pos = b->get_position() - cache.bg->get_offset(); + if (show_column_titles) { + pos.y -= _get_title_button_height(); - if (b.button_index == BUTTON_LEFT) { + if (pos.y < 0) { + pos.x += cache.offset.x; + int len = 0; + for (int i = 0; i < columns.size(); i++) { - if (single_select_defer) { - select_single_item(single_select_defer, root, single_select_defer_column); - single_select_defer = NULL; + len += get_column_width(i); + if (pos.x < len) { + emit_signal("column_title_pressed", i); + break; + } + } } + } - range_click_timer->stop(); + if (single_select_defer) { + select_single_item(single_select_defer, root, single_select_defer_column); + single_select_defer = NULL; + } + + range_click_timer->stop(); - if (pressing_for_editor) { + if (pressing_for_editor) { - if (range_drag_enabled) { + if (range_drag_enabled) { - range_drag_enabled = false; - Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); - warp_mouse(range_drag_capture_pos); + range_drag_enabled = false; + Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); + warp_mouse(range_drag_capture_pos); + } else { + Rect2 rect = get_selected()->get_meta("__focus_rect"); + if (rect.has_point(Point2(b->get_position().x, b->get_position().y))) { + edit_selected(); } else { - Rect2 rect = get_selected()->get_meta("__focus_rect"); - if (rect.has_point(Point2(p_event.mouse_button.x, p_event.mouse_button.y))) { - edit_selected(); - } else { - emit_signal("item_double_clicked"); - } + emit_signal("item_double_clicked"); } - pressing_for_editor = false; } + pressing_for_editor = false; + } - if (cache.click_type == Cache::CLICK_BUTTON) { - // make sure in case of wrong reference after reconstructing whole TreeItems - cache.click_item = get_item_at_pos(cache.click_pos); - emit_signal("button_pressed", cache.click_item, cache.click_column, cache.click_id); - } - cache.click_type = Cache::CLICK_NONE; - cache.click_index = -1; - cache.click_id = -1; - cache.click_item = NULL; - cache.click_column = 0; + if (cache.click_type == Cache::CLICK_BUTTON) { + // make sure in case of wrong reference after reconstructing whole TreeItems + cache.click_item = get_item_at_pos(cache.click_pos); + emit_signal("button_pressed", cache.click_item, cache.click_column, cache.click_id); + } + cache.click_type = Cache::CLICK_NONE; + cache.click_index = -1; + cache.click_id = -1; + cache.click_item = NULL; + cache.click_column = 0; - if (drag_touching) { + if (drag_touching) { - if (drag_speed == 0) { - drag_touching_deaccel = false; - drag_touching = false; - set_fixed_process(false); - } else { + if (drag_speed == 0) { + drag_touching_deaccel = false; + drag_touching = false; + set_fixed_process(false); + } else { - drag_touching_deaccel = true; - } + drag_touching_deaccel = true; } - update(); } - break; + update(); } + return; + } - if (range_drag_enabled) - break; + if (range_drag_enabled) + return; - switch (b.button_index) { - case BUTTON_RIGHT: - case BUTTON_LEFT: { - Ref<StyleBox> bg = cache.bg; + switch (b->get_button_index()) { + case BUTTON_RIGHT: + case BUTTON_LEFT: { + Ref<StyleBox> bg = cache.bg; - Point2 pos = Point2(b.x, b.y) - bg->get_offset(); - cache.click_type = Cache::CLICK_NONE; - if (show_column_titles && b.button_index == BUTTON_LEFT) { - pos.y -= _get_title_button_height(); + Point2 pos = b->get_position() - bg->get_offset(); + cache.click_type = Cache::CLICK_NONE; + if (show_column_titles && b->get_button_index() == BUTTON_LEFT) { + pos.y -= _get_title_button_height(); - if (pos.y < 0) { - pos.x += cache.offset.x; - int len = 0; - for (int i = 0; i < columns.size(); i++) { + if (pos.y < 0) { + pos.x += cache.offset.x; + int len = 0; + for (int i = 0; i < columns.size(); i++) { - len += get_column_width(i); - if (pos.x < len) { + len += get_column_width(i); + if (pos.x < len) { - cache.click_type = Cache::CLICK_TITLE; - cache.click_index = i; - //cache.click_id=; - update(); - break; - } + cache.click_type = Cache::CLICK_TITLE; + cache.click_index = i; + //cache.click_id=; + update(); + break; } - break; - } - } - if (!root || (!root->get_children() && hide_root)) { - if (b.button_index == BUTTON_RIGHT && allow_rmb_select) { - emit_signal("empty_tree_rmb_selected", get_local_mouse_pos()); } break; } + } + if (!root || (!root->get_children() && hide_root)) { + if (b->get_button_index() == BUTTON_RIGHT && allow_rmb_select) { + emit_signal("empty_tree_rmb_selected", get_local_mouse_pos()); + } + break; + } - click_handled = false; - pressing_for_editor = false; + click_handled = false; + pressing_for_editor = false; - blocked++; - bool handled = propagate_mouse_event(pos + cache.offset, 0, 0, b.doubleclick, root, b.button_index, b.mod); - blocked--; + blocked++; + bool handled = propagate_mouse_event(pos + cache.offset, 0, 0, b->is_doubleclick(), root, b->get_button_index(), b); + blocked--; - if (pressing_for_editor) { - pressing_pos = Point2(b.x, b.y); - } + if (pressing_for_editor) { + pressing_pos = b->get_position(); + } - if (b.button_index == BUTTON_RIGHT) - break; + if (b->get_button_index() == BUTTON_RIGHT) + break; - if (drag_touching) { - set_fixed_process(false); - drag_touching_deaccel = false; - drag_touching = false; - drag_speed = 0; - drag_from = 0; - } + if (drag_touching) { + set_fixed_process(false); + drag_touching_deaccel = false; + drag_touching = false; + drag_speed = 0; + drag_from = 0; + } - if (!click_handled) { - drag_speed = 0; - drag_accum = 0; - //last_drag_accum=0; - drag_from = v_scroll->get_value(); - drag_touching = OS::get_singleton()->has_touchscreen_ui_hint(); - drag_touching_deaccel = false; - if (drag_touching) { - set_fixed_process(true); - } + if (!click_handled) { + drag_speed = 0; + drag_accum = 0; + //last_drag_accum=0; + drag_from = v_scroll->get_value(); + drag_touching = OS::get_singleton()->has_touchscreen_ui_hint(); + drag_touching_deaccel = false; + if (drag_touching) { + set_fixed_process(true); } + } - } break; - case BUTTON_WHEEL_UP: { - - v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() / 8); - } break; - case BUTTON_WHEEL_DOWN: { + } break; + case BUTTON_WHEEL_UP: { - v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() / 8); - } break; - } + v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * b->get_factor() / 8); + } break; + case BUTTON_WHEEL_DOWN: { - } break; + v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * b->get_factor() / 8); + } break; + } } } @@ -2378,7 +2578,7 @@ bool Tree::edit_selected() { edited_item = s; edited_col = col; - custom_popup_rect = Rect2i(get_global_pos() + rect.pos, rect.size); + custom_popup_rect = Rect2i(get_global_position() + rect.position, rect.size); emit_signal("custom_popup_edited", false); item_edited(col, s); @@ -2393,7 +2593,7 @@ bool Tree::edit_selected() { } popup_menu->set_size(Size2(rect.size.width, 0)); - popup_menu->set_pos(get_global_pos() + rect.pos + Point2i(0, rect.size.height)); + popup_menu->set_position(get_global_position() + rect.position + Point2i(0, rect.size.height)); popup_menu->popup(); popup_edited_item = s; popup_edited_item_col = col; @@ -2401,8 +2601,8 @@ bool Tree::edit_selected() { } else if (c.mode == TreeItem::CELL_MODE_STRING || c.mode == TreeItem::CELL_MODE_RANGE || c.mode == TreeItem::CELL_MODE_RANGE_EXPRESSION) { - Point2i textedpos = get_global_pos() + rect.pos; - text_editor->set_pos(textedpos); + Point2i textedpos = get_global_position() + rect.position; + text_editor->set_position(textedpos); text_editor->set_size(rect.size); text_editor->clear(); text_editor->set_text(c.mode == TreeItem::CELL_MODE_STRING ? c.text : String::num(c.val, Math::step_decimals(c.step))); @@ -2410,7 +2610,7 @@ bool Tree::edit_selected() { if (c.mode == TreeItem::CELL_MODE_RANGE || c.mode == TreeItem::CELL_MODE_RANGE_EXPRESSION) { - value_editor->set_pos(textedpos + Point2i(0, text_editor->get_size().height)); + value_editor->set_position(textedpos + Point2i(0, text_editor->get_size().height)); value_editor->set_size(Size2(rect.size.width, 1)); value_editor->show_modal(); updating_value_editor = true; @@ -2528,7 +2728,7 @@ void Tree::_notification(int p_what) { if (p_what == NOTIFICATION_DRAG_BEGIN) { single_select_defer = NULL; - if (cache.scroll_speed > 0 && get_rect().has_point(get_viewport()->get_mouse_pos() - get_global_pos())) { + if (cache.scroll_speed > 0 && get_rect().has_point(get_viewport()->get_mouse_position() - get_global_position())) { scrolling = true; set_fixed_process(true); } @@ -2576,7 +2776,7 @@ void Tree::_notification(int p_what) { } if (scrolling) { - Point2 point = get_viewport()->get_mouse_pos() - get_global_pos(); + Point2 point = get_viewport()->get_mouse_position() - get_global_position(); if (point.x < cache.scroll_border) { point.x -= cache.scroll_border; } else if (point.x > get_size().width - cache.scroll_border) { @@ -2648,7 +2848,7 @@ void Tree::_notification(int p_what) { ofs += tbrect.size.width; //text int clip_w = tbrect.size.width - sb->get_minimum_size().width; - f->draw_halign(ci, tbrect.pos + Point2i(sb->get_offset().x, (tbrect.size.height - f->get_height()) / 2 + f->get_ascent()), HALIGN_CENTER, clip_w, columns[i].title, cache.title_button_color); + f->draw_halign(ci, tbrect.position + Point2i(sb->get_offset().x, (tbrect.size.height - f->get_height()) / 2 + f->get_ascent()), HALIGN_CENTER, clip_w, columns[i].title, cache.title_button_color); } } } @@ -2726,11 +2926,14 @@ TreeItem *Tree::get_last_item() { return last; } -void Tree::item_edited(int p_column, TreeItem *p_item) { +void Tree::item_edited(int p_column, TreeItem *p_item, bool p_lmb) { edited_item = p_item; edited_col = p_column; - emit_signal("item_edited"); + if (p_lmb) + emit_signal("item_edited"); + else + emit_signal("item_rmb_edited"); } void Tree::item_changed(int p_column, TreeItem *p_item) { @@ -3009,7 +3212,7 @@ void Tree::ensure_cursor_is_visible() { int screenh = get_size().height - h_scroll->get_combined_minimum_size().height; if (ofs + h > v_scroll->get_value() + screenh) - v_scroll->call_deferred("set_val", ofs - screenh + h); + v_scroll->call_deferred("set_value", ofs - screenh + h); else if (ofs < v_scroll->get_value()) v_scroll->set_value(ofs); } @@ -3030,11 +3233,11 @@ Rect2 Tree::get_item_rect(TreeItem *p_item, int p_column) const { int ofs = get_item_offset(p_item); int height = compute_item_height(p_item); Rect2 r; - r.pos.y = ofs; + r.position.y = ofs; r.size.height = height; if (p_column == -1) { - r.pos.x = 0; + r.position.x = 0; r.size.x = get_size().width; } else { @@ -3042,7 +3245,7 @@ Rect2 Tree::get_item_rect(TreeItem *p_item, int p_column) const { for (int i = 0; i < p_column; i++) { accum += get_column_width(i); } - r.pos.x = accum; + r.position.x = accum; r.size.x = get_column_width(p_column); } @@ -3289,6 +3492,19 @@ String Tree::get_tooltip(const Point2 &p_pos) const { if (it) { + TreeItem::Cell &c = it->cells[col]; + int col_width = get_column_width(col); + for (int j = c.buttons.size() - 1; j >= 0; j--) { + Ref<Texture> b = c.buttons[j].texture; + Size2 size = b->get_size() + cache.button_pressed->get_minimum_size(); + if (pos.x > col_width - size.width) { + String tooltip = c.buttons[j].tooltip; + if (tooltip != "") { + return tooltip; + } + } + col_width -= size.width; + } String ret; if (it->get_tooltip(col) == "") ret = it->get_text(col); @@ -3382,16 +3598,16 @@ void Tree::_bind_methods() { ClassDB::bind_method(D_METHOD("_scroll_moved"), &Tree::_scroll_moved); ClassDB::bind_method(D_METHOD("clear"), &Tree::clear); - ClassDB::bind_method(D_METHOD("create_item:TreeItem", "parent:TreeItem"), &Tree::_create_item, DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("create_item", "parent"), &Tree::_create_item, DEFVAL(Variant())); - ClassDB::bind_method(D_METHOD("get_root:TreeItem"), &Tree::get_root); + ClassDB::bind_method(D_METHOD("get_root"), &Tree::get_root); ClassDB::bind_method(D_METHOD("set_column_min_width", "column", "min_width"), &Tree::set_column_min_width); ClassDB::bind_method(D_METHOD("set_column_expand", "column", "expand"), &Tree::set_column_expand); ClassDB::bind_method(D_METHOD("get_column_width", "column"), &Tree::get_column_width); ClassDB::bind_method(D_METHOD("set_hide_root", "enable"), &Tree::set_hide_root); - ClassDB::bind_method(D_METHOD("get_next_selected:TreeItem", "from:TreeItem"), &Tree::_get_next_selected); - ClassDB::bind_method(D_METHOD("get_selected:TreeItem"), &Tree::get_selected); + ClassDB::bind_method(D_METHOD("get_next_selected", "from"), &Tree::_get_next_selected); + ClassDB::bind_method(D_METHOD("get_selected"), &Tree::get_selected); ClassDB::bind_method(D_METHOD("get_selected_column"), &Tree::get_selected_column); ClassDB::bind_method(D_METHOD("get_pressed_button"), &Tree::get_pressed_button); ClassDB::bind_method(D_METHOD("set_select_mode", "mode"), &Tree::set_select_mode); @@ -3399,11 +3615,11 @@ void Tree::_bind_methods() { ClassDB::bind_method(D_METHOD("set_columns", "amount"), &Tree::set_columns); ClassDB::bind_method(D_METHOD("get_columns"), &Tree::get_columns); - ClassDB::bind_method(D_METHOD("get_edited:TreeItem"), &Tree::get_edited); + ClassDB::bind_method(D_METHOD("get_edited"), &Tree::get_edited); ClassDB::bind_method(D_METHOD("get_edited_column"), &Tree::get_edited_column); ClassDB::bind_method(D_METHOD("get_custom_popup_rect"), &Tree::get_custom_popup_rect); - ClassDB::bind_method(D_METHOD("get_item_area_rect", "item:TreeItem", "column"), &Tree::_get_item_rect, DEFVAL(-1)); - ClassDB::bind_method(D_METHOD("get_item_at_pos:TreeItem", "pos"), &Tree::get_item_at_pos); + ClassDB::bind_method(D_METHOD("get_item_area_rect", "item", "column"), &Tree::_get_item_rect, DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("get_item_at_pos", "pos"), &Tree::get_item_at_pos); ClassDB::bind_method(D_METHOD("get_column_at_pos", "pos"), &Tree::get_column_at_pos); ClassDB::bind_method(D_METHOD("ensure_cursor_is_visible"), &Tree::ensure_cursor_is_visible); @@ -3433,12 +3649,15 @@ void Tree::_bind_methods() { ADD_SIGNAL(MethodInfo("item_rmb_selected", PropertyInfo(Variant::VECTOR2, "pos"))); ADD_SIGNAL(MethodInfo("empty_tree_rmb_selected", PropertyInfo(Variant::VECTOR2, "pos"))); ADD_SIGNAL(MethodInfo("item_edited")); + ADD_SIGNAL(MethodInfo("item_rmb_edited")); + ADD_SIGNAL(MethodInfo("item_custom_button_pressed")); ADD_SIGNAL(MethodInfo("item_double_clicked")); ADD_SIGNAL(MethodInfo("item_collapsed", PropertyInfo(Variant::OBJECT, "item"))); //ADD_SIGNAL( MethodInfo("item_doubleclicked" ) ); ADD_SIGNAL(MethodInfo("button_pressed", PropertyInfo(Variant::OBJECT, "item"), PropertyInfo(Variant::INT, "column"), PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("custom_popup_edited", PropertyInfo(Variant::BOOL, "arrow_clicked"))); ADD_SIGNAL(MethodInfo("item_activated")); + ADD_SIGNAL(MethodInfo("column_title_pressed", PropertyInfo(Variant::INT, "column"))); BIND_CONSTANT(SELECT_SINGLE); BIND_CONSTANT(SELECT_ROW); @@ -3538,6 +3757,9 @@ Tree::Tree() { force_edit_checkbox_only_on_checkbox = false; set_clip_contents(true); + + cache.hover_item = NULL; + cache.hover_cell = -1; } Tree::~Tree() { diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 68d445315..81880122a 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -57,6 +58,12 @@ public: CELL_MODE_CUSTOM, ///< Contains a custom value, show a string, and an edit button }; + enum TextAlign { + ALIGN_LEFT, + ALIGN_CENTER, + ALIGN_RIGHT + }; + private: friend class Tree; @@ -80,6 +87,11 @@ private: bool custom_bg_color; bool custom_bg_outline; Color bg_color; + bool custom_button; + bool expand_right; + Color icon_color; + + TextAlign text_align; Variant meta; String tooltip; @@ -92,10 +104,12 @@ private: bool disabled; Ref<Texture> texture; Color color; + String tooltip; Button() { id = 0; disabled = false; color = Color(1, 1, 1, 1); + tooltip = ""; } }; @@ -104,6 +118,7 @@ private: Cell() { custom_draw_obj = 0; + custom_button = false; mode = TreeItem::CELL_MODE_STRING; min = 0; max = 100; @@ -117,15 +132,19 @@ private: custom_bg_color = false; expr = false; icon_max_w = 0; + text_align = ALIGN_LEFT; + expand_right = false; + icon_color = Color(1, 1, 1); } Size2 get_icon_size() const; - void draw_icon(const RID &p_where, const Point2 &p_pos, const Size2 &p_size = Size2()) const; + void draw_icon(const RID &p_where, const Point2 &p_pos, const Size2 &p_size = Size2(), const Color &p_color = Color()) const; }; Vector<Cell> cells; bool collapsed; // wont show childs + bool disable_folding; TreeItem *parent; // parent item TreeItem *next; // next in list @@ -176,10 +195,13 @@ public: void set_icon_region(int p_column, const Rect2 &p_icon_region); Rect2 get_icon_region(int p_column) const; + void set_icon_color(int p_column, const Color &p_icon_color); + Color get_icon_color(int p_column) const; + void set_icon_max_width(int p_column, int p_max); int get_icon_max_width(int p_column) const; - void add_button(int p_column, const Ref<Texture> &p_button, int p_id = -1, bool p_disabled = false); + void add_button(int p_column, const Ref<Texture> &p_button, int p_id = -1, bool p_disabled = false, const String &p_tooltip = ""); int get_button_count(int p_column) const; Ref<Texture> get_button(int p_column, int p_idx) const; int get_button_id(int p_column, int p_idx) const; @@ -235,18 +257,31 @@ public: void clear_custom_bg_color(int p_column); Color get_custom_bg_color(int p_column) const; + void set_custom_as_button(int p_column, bool p_button); + bool is_custom_set_as_button(int p_column) const; + void set_tooltip(int p_column, const String &p_tooltip); String get_tooltip(int p_column) const; void clear_children(); + void set_text_align(int p_column, TextAlign p_align); + TextAlign get_text_align(int p_column) const; + + void set_expand_right(int p_column, bool p_enable); + bool get_expand_right(int p_column) const; + void move_to_top(); void move_to_bottom(); + void set_disable_folding(bool p_disable); + bool is_folding_disabled() const; + ~TreeItem(); }; VARIANT_ENUM_CAST(TreeItem::TreeCellMode); +VARIANT_ENUM_CAST(TreeItem::TextAlign); class Tree : public Control { @@ -331,22 +366,22 @@ private: int compute_item_height(TreeItem *p_item) const; int get_item_height(TreeItem *p_item) const; //void draw_item_text(String p_text,const Ref<Texture>& p_icon,int p_icon_max_w,bool p_tool,Rect2i p_rect,const Color& p_color); - void draw_item_rect(const TreeItem::Cell &p_cell, const Rect2i &p_rect, const Color &p_color); + void draw_item_rect(const TreeItem::Cell &p_cell, const Rect2i &p_rect, const Color &p_color, const Color &p_icon_color); int draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 &p_draw_size, TreeItem *p_item); void select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_col, TreeItem *p_prev = NULL, bool *r_in_range = NULL, bool p_force_deselect = false); - int propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool p_doubleclick, TreeItem *p_item, int p_button, const InputModifierState &p_mod); + int propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool p_doubleclick, TreeItem *p_item, int p_button, const Ref<InputEventWithModifiers> &p_mod); void text_editor_enter(String p_text); void _text_editor_modal_close(); void value_editor_changed(double p_value); void popup_select(int p_option); - void _gui_input(InputEvent p_event); + void _gui_input(Ref<InputEvent> p_event); void _notification(int p_what); Size2 get_minimum_size() const; - void item_edited(int p_column, TreeItem *p_item); + void item_edited(int p_column, TreeItem *p_item, bool p_lmb = true); void item_changed(int p_column, TreeItem *p_item); void item_selected(int p_column, TreeItem *p_item); void item_deselected(int p_column, TreeItem *p_item); @@ -366,6 +401,10 @@ private: Ref<StyleBox> title_button; Ref<StyleBox> title_button_hover; Ref<StyleBox> title_button_pressed; + Ref<StyleBox> custom_button; + Ref<StyleBox> custom_button_hover; + Ref<StyleBox> custom_button_pressed; + Color title_button_color; Ref<Texture> checked; @@ -380,6 +419,7 @@ private: Color guide_color; Color drop_position_color; Color relationship_line_color; + Color custom_button_font_highlight; int hseparation; int vseparation; @@ -407,6 +447,9 @@ private: int hover_index; Point2 click_pos; + TreeItem *hover_item; + int hover_cell; + } cache; int _get_title_button_height() const; @@ -428,7 +471,7 @@ private: TreeItem *_search_item_text(TreeItem *p_at, const String &p_find, int *r_col, bool p_selectable, bool p_backwards = false); - TreeItem *_find_item_at_pos(TreeItem *p_current, const Point2 &p_pos, int &r_column, int &h, int §ion) const; + TreeItem *_find_item_at_pos(TreeItem *p_item, const Point2 &p_pos, int &r_column, int &h, int §ion) const; /* float drag_speed; float drag_accum; @@ -481,7 +524,7 @@ public: void set_column_expand(int p_column, bool p_expand); int get_column_width(int p_column) const; - void set_hide_root(bool p_eanbled); + void set_hide_root(bool p_enabled); TreeItem *get_next_selected(TreeItem *p_item); TreeItem *get_selected() const; int get_selected_column() const; diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp index 433cc546a..9c018a4e7 100644 --- a/scene/gui/video_player.cpp +++ b/scene/gui/video_player.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -347,8 +348,8 @@ bool VideoPlayer::has_autoplay() const { void VideoPlayer::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_stream", "stream:VideoStream"), &VideoPlayer::set_stream); - ClassDB::bind_method(D_METHOD("get_stream:VideoStream"), &VideoPlayer::get_stream); + ClassDB::bind_method(D_METHOD("set_stream", "stream"), &VideoPlayer::set_stream); + ClassDB::bind_method(D_METHOD("get_stream"), &VideoPlayer::get_stream); ClassDB::bind_method(D_METHOD("play"), &VideoPlayer::play); ClassDB::bind_method(D_METHOD("stop"), &VideoPlayer::stop); @@ -380,7 +381,7 @@ void VideoPlayer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_buffering_msec", "msec"), &VideoPlayer::set_buffering_msec); ClassDB::bind_method(D_METHOD("get_buffering_msec"), &VideoPlayer::get_buffering_msec); - ClassDB::bind_method(D_METHOD("get_video_texture:Texture"), &VideoPlayer::get_video_texture); + ClassDB::bind_method(D_METHOD("get_video_texture"), &VideoPlayer::get_video_texture); ADD_PROPERTY(PropertyInfo(Variant::INT, "audio_track", PROPERTY_HINT_RANGE, "0,128,1"), "set_audio_track", "get_audio_track"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "VideoStream"), "set_stream", "get_stream"); diff --git a/scene/gui/video_player.h b/scene/gui/video_player.h index 4f2894cdc..87c452509 100644 --- a/scene/gui/video_player.h +++ b/scene/gui/video_player.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -58,7 +59,7 @@ class VideoPlayer : public Control { RID stream_rid; Ref<ImageTexture> texture; - Image last_frame; + Ref<Image> last_frame; AudioRBResampler resampler; @@ -104,7 +105,7 @@ public: String get_stream_name() const; float get_stream_pos() const; - void set_autoplay(bool p_vol); + void set_autoplay(bool p_enable); bool has_autoplay() const; void set_audio_track(int p_track); diff --git a/scene/gui/viewport_container.cpp b/scene/gui/viewport_container.cpp index 93789d945..dbc269986 100644 --- a/scene/gui/viewport_container.cpp +++ b/scene/gui/viewport_container.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/gui/viewport_container.h b/scene/gui/viewport_container.h index 96b352b1c..27eb6ec81 100644 --- a/scene/gui/viewport_container.h +++ b/scene/gui/viewport_container.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/io/resource_format_image.cpp b/scene/io/resource_format_image.cpp index 6a550a847..04b6177c3 100644 --- a/scene/io/resource_format_image.cpp +++ b/scene/io/resource_format_image.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,9 +30,9 @@ #include "resource_format_image.h" #if 0 -#include "global_config.h" #include "io/image_loader.h" #include "os/os.h" +#include "project_settings.h" #include "scene/resources/texture.h" RES ResourceFormatLoaderImage::load(const String &p_path, const String& p_original_path, Error *r_error) { @@ -127,7 +128,7 @@ RES ResourceFormatLoaderImage::load(const String &p_path, const String& p_origin if (max_texture_size && (image.get_width() > max_texture_size || image.get_height() > max_texture_size)) { - if (bool(GlobalConfig::get_singleton()->get("debug/image_loader/max_texture_size_alert"))) { + if (bool(ProjectSettings::get_singleton()->get("debug/image_loader/max_texture_size_alert"))) { OS::get_singleton()->alert("Texture is too large: '"+p_path+"', at "+itos(image.get_width())+"x"+itos(image.get_height())+". Max allowed size is: "+itos(max_texture_size)+"x"+itos(max_texture_size)+".","BAD ARTIST, NO COOKIE!"); } diff --git a/scene/io/resource_format_image.h b/scene/io/resource_format_image.h index 0638e9778..2cf6315f1 100644 --- a/scene/io/resource_format_image.h +++ b/scene/io/resource_format_image.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/io/resource_format_wav.cpp b/scene/io/resource_format_wav.cpp index 0d64743d1..dabbb79de 100644 --- a/scene/io/resource_format_wav.cpp +++ b/scene/io/resource_format_wav.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -97,7 +98,7 @@ RES ResourceFormatLoaderWAV::load(const String &p_path, const String& p_original /* chunk size */ uint32_t chunksize=file->get_32(); - uint32_t file_pos=file->get_pos(); //save file pos, so we can skip to next chunk safely + uint32_t file_pos=file->get_position(); //save file pos, so we can skip to next chunk safely if (file->eof_reached()) { diff --git a/scene/io/resource_format_wav.h b/scene/io/resource_format_wav.h index fd274625f..910568967 100644 --- a/scene/io/resource_format_wav.h +++ b/scene/io/resource_format_wav.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp index 1fecb6fd9..77407fdde 100644 --- a/scene/main/canvas_layer.cpp +++ b/scene/main/canvas_layer.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -203,7 +204,7 @@ void CanvasLayer::set_custom_viewport(Node *p_viewport) { custom_viewport = p_viewport->cast_to<Viewport>(); if (custom_viewport) { - custom_viewport_id = custom_viewport->get_instance_ID(); + custom_viewport_id = custom_viewport->get_instance_id(); } else { custom_viewport_id = 0; } @@ -261,10 +262,10 @@ void CanvasLayer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_scale", "scale"), &CanvasLayer::set_scale); ClassDB::bind_method(D_METHOD("get_scale"), &CanvasLayer::get_scale); - ClassDB::bind_method(D_METHOD("set_custom_viewport", "viewport:Viewport"), &CanvasLayer::set_custom_viewport); - ClassDB::bind_method(D_METHOD("get_custom_viewport:Viewport"), &CanvasLayer::get_custom_viewport); + ClassDB::bind_method(D_METHOD("set_custom_viewport", "viewport"), &CanvasLayer::set_custom_viewport); + ClassDB::bind_method(D_METHOD("get_custom_viewport"), &CanvasLayer::get_custom_viewport); - ClassDB::bind_method(D_METHOD("get_world_2d:World2D"), &CanvasLayer::get_world_2d); + ClassDB::bind_method(D_METHOD("get_world_2d"), &CanvasLayer::get_world_2d); //ClassDB::bind_method(D_METHOD("get_viewport"),&CanvasLayer::get_viewport); ADD_PROPERTY(PropertyInfo(Variant::INT, "layer", PROPERTY_HINT_RANGE, "-128,128,1"), "set_layer", "get_layer"); diff --git a/scene/main/canvas_layer.h b/scene/main/canvas_layer.h index 26d21e3a0..b14a915fe 100644 --- a/scene/main/canvas_layer.h +++ b/scene/main/canvas_layer.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -54,7 +55,7 @@ class CanvasLayer : public Node { int sort_index; // Deprecated, should be removed in a future version. - void _set_rotationd(real_t p_rotation); + void _set_rotationd(real_t p_degrees); real_t _get_rotationd() const; void _update_xform(); diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index 38ee03ab4..a9b2dba18 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -28,6 +29,8 @@ /*************************************************************************/ #include "http_request.h" +#include "version.h" + void HTTPRequest::_redirect_request(const String &p_new_url) { } diff --git a/scene/main/http_request.h b/scene/main/http_request.h index 2b2d7f9a3..6099d4e9b 100644 --- a/scene/main/http_request.h +++ b/scene/main/http_request.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/main/instance_placeholder.cpp b/scene/main/instance_placeholder.cpp index 469a5e944..5580ef486 100644 --- a/scene/main/instance_placeholder.cpp +++ b/scene/main/instance_placeholder.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -122,7 +123,7 @@ Dictionary InstancePlaceholder::get_stored_values(bool p_with_order) { void InstancePlaceholder::_bind_methods() { ClassDB::bind_method(D_METHOD("get_stored_values", "with_order"), &InstancePlaceholder::get_stored_values, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("replace_by_instance", "custom_scene:PackedScene"), &InstancePlaceholder::replace_by_instance, DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("replace_by_instance", "custom_scene"), &InstancePlaceholder::replace_by_instance, DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("get_instance_path"), &InstancePlaceholder::get_instance_path); } diff --git a/scene/main/instance_placeholder.h b/scene/main/instance_placeholder.h index 7900e35b0..ec4520e1c 100644 --- a/scene/main/instance_placeholder.h +++ b/scene/main/instance_placeholder.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/main/node.cpp b/scene/main/node.cpp index c13ed232a..0474c6fd2 100755 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -36,7 +37,6 @@ #include "viewport.h" VARIANT_ENUM_CAST(Node::PauseMode); -VARIANT_ENUM_CAST(Node::NetworkMode); VARIANT_ENUM_CAST(Node::RPCMode); void Node::_notification(int p_notification) { @@ -76,22 +76,12 @@ void Node::_notification(int p_notification) { data.pause_owner = this; } - if (data.network_mode == NETWORK_MODE_INHERIT) { - - if (data.parent) - data.network_owner = data.parent->data.network_owner; - else - data.network_owner = NULL; - } else { - data.network_owner = this; - } - if (data.input) - add_to_group("_vp_input" + itos(get_viewport()->get_instance_ID())); + add_to_group("_vp_input" + itos(get_viewport()->get_instance_id())); if (data.unhandled_input) - add_to_group("_vp_unhandled_input" + itos(get_viewport()->get_instance_ID())); + add_to_group("_vp_unhandled_input" + itos(get_viewport()->get_instance_id())); if (data.unhandled_key_input) - add_to_group("_vp_unhandled_key_input" + itos(get_viewport()->get_instance_ID())); + add_to_group("_vp_unhandled_key_input" + itos(get_viewport()->get_instance_id())); get_tree()->node_count++; @@ -100,14 +90,13 @@ void Node::_notification(int p_notification) { get_tree()->node_count--; if (data.input) - remove_from_group("_vp_input" + itos(get_viewport()->get_instance_ID())); + remove_from_group("_vp_input" + itos(get_viewport()->get_instance_id())); if (data.unhandled_input) - remove_from_group("_vp_unhandled_input" + itos(get_viewport()->get_instance_ID())); + remove_from_group("_vp_unhandled_input" + itos(get_viewport()->get_instance_id())); if (data.unhandled_key_input) - remove_from_group("_vp_unhandled_key_input" + itos(get_viewport()->get_instance_ID())); + remove_from_group("_vp_unhandled_key_input" + itos(get_viewport()->get_instance_id())); data.pause_owner = NULL; - data.network_owner = NULL; if (data.path_cache) { memdelete(data.path_cache); data.path_cache = NULL; @@ -322,6 +311,11 @@ void Node::move_child(Node *p_child, int p_pos) { ERR_FAIL_COND(data.blocked > 0); } + // Specifying one place beyond the end + // means the same as moving to the last position + if (p_pos == data.children.size()) + p_pos--; + if (p_child->data.pos == p_pos) return; //do nothing @@ -462,7 +456,7 @@ Node::PauseMode Node::get_pause_mode() const { void Node::_propagate_pause_owner(Node *p_owner) { - if (data.pause_mode != PAUSE_MODE_INHERIT) + if (this != p_owner && data.pause_mode != PAUSE_MODE_INHERIT) return; data.pause_owner = p_owner; for (int i = 0; i < data.children.size(); i++) { @@ -471,69 +465,28 @@ void Node::_propagate_pause_owner(Node *p_owner) { } } -void Node::set_network_mode(NetworkMode p_mode) { +void Node::set_network_master(int p_peer_id, bool p_recursive) { - if (data.network_mode == p_mode) - return; + data.network_master = p_peer_id; - bool prev_inherits = data.network_mode == NETWORK_MODE_INHERIT; - data.network_mode = p_mode; - if (!is_inside_tree()) - return; //pointless - if ((data.network_mode == NETWORK_MODE_INHERIT) == prev_inherits) - return; ///nothing changed - - Node *owner = NULL; - - if (data.network_mode == NETWORK_MODE_INHERIT) { + if (p_recursive) { + for (int i = 0; i < data.children.size(); i++) { - if (data.parent) - owner = data.parent->data.network_owner; - } else { - owner = this; + data.children[i]->set_network_master(p_peer_id, true); + } } - - _propagate_network_owner(owner); } -Node::NetworkMode Node::get_network_mode() const { +int Node::get_network_master() const { - return data.network_mode; + return data.network_master; } bool Node::is_network_master() const { ERR_FAIL_COND_V(!is_inside_tree(), false); - switch (data.network_mode) { - case NETWORK_MODE_INHERIT: { - - if (data.network_owner) - return data.network_owner->is_network_master(); - else - return get_tree()->is_network_server(); - } break; - case NETWORK_MODE_MASTER: { - - return true; - } break; - case NETWORK_MODE_SLAVE: { - return false; - } break; - } - - return false; -} - -void Node::_propagate_network_owner(Node *p_owner) { - - if (data.network_mode != NETWORK_MODE_INHERIT) - return; - data.network_owner = p_owner; - for (int i = 0; i < data.children.size(); i++) { - - data.children[i]->_propagate_network_owner(p_owner); - } + return get_tree()->get_network_unique_id() == data.network_master; } /***** RPC CONFIG ********/ @@ -752,12 +705,12 @@ void Node::rpcp(int p_peer_id, bool p_unreliable, const StringName &p_method, co ERR_FAIL_COND(!is_inside_tree()); bool skip_rpc = false; + bool call_local_native = false; + bool call_local_script = false; if (p_peer_id == 0 || p_peer_id == get_tree()->get_network_unique_id() || (p_peer_id < 0 && p_peer_id != -get_tree()->get_network_unique_id())) { //check that send mode can use local call - bool call_local = false; - Map<StringName, RPCMode>::Element *E = data.rpc_methods.find(p_method); if (E) { @@ -771,29 +724,22 @@ void Node::rpcp(int p_peer_id, bool p_unreliable, const StringName &p_method, co } break; case RPC_MODE_SYNC: { //call it, sync always results in call - call_local = true; + call_local_native = true; } break; case RPC_MODE_MASTER: { - call_local = is_network_master(); - if (call_local) { + call_local_native = is_network_master(); + if (call_local_native) { skip_rpc = true; //no other master so.. } } break; case RPC_MODE_SLAVE: { - call_local = !is_network_master(); + call_local_native = !is_network_master(); } break; } } - if (call_local) { - Variant::CallError ce; - call(p_method, p_arg, p_argcount, ce); - if (ce.error != Variant::CallError::CALL_OK) { - String error = Variant::get_call_error_text(this, p_method, p_arg, p_argcount, ce); - error = "rpc() aborted in local call: - " + error; - ERR_PRINTS(error); - return; - } + if (call_local_native) { + // done below } else if (get_script_instance()) { //attempt with script ScriptInstance::RPCMode rpc_mode = get_script_instance()->get_rpc_mode(p_method); @@ -808,37 +754,47 @@ void Node::rpcp(int p_peer_id, bool p_unreliable, const StringName &p_method, co } break; case ScriptInstance::RPC_MODE_SYNC: { //call it, sync always results in call - call_local = true; + call_local_script = true; } break; case ScriptInstance::RPC_MODE_MASTER: { - call_local = is_network_master(); - if (call_local) { + call_local_script = is_network_master(); + if (call_local_script) { skip_rpc = true; //no other master so.. } } break; case ScriptInstance::RPC_MODE_SLAVE: { - call_local = !is_network_master(); + call_local_script = !is_network_master(); } break; } - - if (call_local) { - Variant::CallError ce; - ce.error = Variant::CallError::CALL_OK; - get_script_instance()->call(p_method, p_arg, p_argcount, ce); - if (ce.error != Variant::CallError::CALL_OK) { - String error = Variant::get_call_error_text(this, p_method, p_arg, p_argcount, ce); - error = "rpc() aborted in script local call: - " + error; - ERR_PRINTS(error); - return; - } - } } } - if (skip_rpc) - return; + if (!skip_rpc) { + get_tree()->_rpc(this, p_peer_id, p_unreliable, false, p_method, p_arg, p_argcount); + } + + if (call_local_native) { + Variant::CallError ce; + call(p_method, p_arg, p_argcount, ce); + if (ce.error != Variant::CallError::CALL_OK) { + String error = Variant::get_call_error_text(this, p_method, p_arg, p_argcount, ce); + error = "rpc() aborted in local call: - " + error; + ERR_PRINTS(error); + return; + } + } - get_tree()->_rpc(this, p_peer_id, p_unreliable, false, p_method, p_arg, p_argcount); + if (call_local_script) { + Variant::CallError ce; + ce.error = Variant::CallError::CALL_OK; + get_script_instance()->call(p_method, p_arg, p_argcount, ce); + if (ce.error != Variant::CallError::CALL_OK) { + String error = Variant::get_call_error_text(this, p_method, p_arg, p_argcount, ce); + error = "rpc() aborted in script local call: - " + error; + ERR_PRINTS(error); + return; + } + } } /******** RSET *********/ @@ -961,7 +917,7 @@ void Node::rset_unreliable_id(int p_peer_id, const StringName &p_property, const //////////// end of rpc -bool Node::can_call_rpc(const StringName &p_method) const { +bool Node::can_call_rpc(const StringName &p_method, int p_from) const { const Map<StringName, RPCMode>::Element *E = data.rpc_methods.find(p_method); if (E) { @@ -981,7 +937,7 @@ bool Node::can_call_rpc(const StringName &p_method) const { return is_network_master(); } break; case RPC_MODE_SLAVE: { - return !is_network_master(); + return !is_network_master() && p_from == get_network_master(); } break; } } @@ -1005,16 +961,16 @@ bool Node::can_call_rpc(const StringName &p_method) const { return is_network_master(); } break; case ScriptInstance::RPC_MODE_SLAVE: { - return !is_network_master(); + return !is_network_master() && p_from == get_network_master(); } break; } } - ERR_PRINTS("RPC on unauthorized method attempted: " + String(p_method) + " on base: " + String(Variant(this))); + ERR_PRINTS("RPC from " + itos(p_from) + " on unauthorized method attempted: " + String(p_method) + " on base: " + String(Variant(this))); return false; } -bool Node::can_call_rset(const StringName &p_property) const { +bool Node::can_call_rset(const StringName &p_property, int p_from) const { const Map<StringName, RPCMode>::Element *E = data.rpc_properties.find(p_property); if (E) { @@ -1034,7 +990,7 @@ bool Node::can_call_rset(const StringName &p_property) const { return is_network_master(); } break; case RPC_MODE_SLAVE: { - return !is_network_master(); + return !is_network_master() && p_from == get_network_master(); } break; } } @@ -1058,12 +1014,12 @@ bool Node::can_call_rset(const StringName &p_property) const { return is_network_master(); } break; case ScriptInstance::RPC_MODE_SLAVE: { - return !is_network_master(); + return !is_network_master() && p_from == get_network_master(); } break; } } - ERR_PRINTS("RSET on unauthorized property attempted: " + String(p_property) + " on base: " + String(Variant(this))); + ERR_PRINTS("RSET from " + itos(p_from) + " on unauthorized property attempted: " + String(p_property) + " on base: " + String(Variant(this))); return false; } @@ -1162,9 +1118,9 @@ void Node::set_process_input(bool p_enable) { return; if (p_enable) - add_to_group("_vp_input" + itos(get_viewport()->get_instance_ID())); + add_to_group("_vp_input" + itos(get_viewport()->get_instance_id())); else - remove_from_group("_vp_input" + itos(get_viewport()->get_instance_ID())); + remove_from_group("_vp_input" + itos(get_viewport()->get_instance_id())); } bool Node::is_processing_input() const { @@ -1180,9 +1136,9 @@ void Node::set_process_unhandled_input(bool p_enable) { return; if (p_enable) - add_to_group("_vp_unhandled_input" + itos(get_viewport()->get_instance_ID())); + add_to_group("_vp_unhandled_input" + itos(get_viewport()->get_instance_id())); else - remove_from_group("_vp_unhandled_input" + itos(get_viewport()->get_instance_ID())); + remove_from_group("_vp_unhandled_input" + itos(get_viewport()->get_instance_id())); } bool Node::is_processing_unhandled_input() const { @@ -1198,9 +1154,9 @@ void Node::set_process_unhandled_key_input(bool p_enable) { return; if (p_enable) - add_to_group("_vp_unhandled_key_input" + itos(get_viewport()->get_instance_ID())); + add_to_group("_vp_unhandled_key_input" + itos(get_viewport()->get_instance_id())); else - remove_from_group("_vp_unhandled_key_input" + itos(get_viewport()->get_instance_ID())); + remove_from_group("_vp_unhandled_key_input" + itos(get_viewport()->get_instance_id())); } bool Node::is_processing_unhandled_key_input() const { @@ -1310,7 +1266,7 @@ String Node::_generate_serial_child_name(Node *p_child) { name = p_child->get_class(); // Adjust casing according to project setting. The current type name is expected to be in PascalCase. - switch (GlobalConfig::get_singleton()->get("node/name_casing").operator int()) { + switch (ProjectSettings::get_singleton()->get("node/name_casing").operator int()) { case NAME_CASING_PASCAL_CASE: break; case NAME_CASING_CAMEL_CASE: @@ -1345,8 +1301,9 @@ String Node::_generate_serial_child_name(Node *p_child) { } } + int num_places = nums.length(); for (;;) { - String attempt = (name + (num > 0 || explicit_zero ? nnsep + itos(num) : "")).strip_edges(); + String attempt = (name + (num > 0 || explicit_zero ? nnsep + itos(num).pad_zeros(num_places) : "")).strip_edges(); bool found = false; for (int i = 0; i < data.children.size(); i++) { if (data.children[i] == p_child) @@ -2063,10 +2020,14 @@ void Node::set_editable_instance(Node *p_node, bool p_editable) { ERR_FAIL_NULL(p_node); ERR_FAIL_COND(!is_a_parent_of(p_node)); NodePath p = get_path_to(p_node); - if (!p_editable) + if (!p_editable) { data.editable_instances.erase(p); - else + // Avoid this flag being needlessly saved; + // also give more visual feedback if editable children is reenabled + set_display_folded(false); + } else { data.editable_instances[p] = true; + } } bool Node::is_editable_instance(Node *p_node) const { @@ -2649,7 +2610,7 @@ static void _Node_debug_sn(Object *p_obj) { path = n->get_name(); else path = String(p->get_name()) + "/" + p->get_path_to(n); - print_line(itos(p_obj->get_instance_ID()) + "- Stray Node: " + path + " (Type: " + n->get_class() + ")"); + print_line(itos(p_obj->get_instance_id()) + "- Stray Node: " + path + " (Type: " + n->get_class() + ")"); } void Node::_print_stray_nodes() { @@ -2760,40 +2721,40 @@ void Node::request_ready() { void Node::_bind_methods() { GLOBAL_DEF("node/name_num_separator", 0); - GlobalConfig::get_singleton()->set_custom_property_info("node/name_num_separator", PropertyInfo(Variant::INT, "node/name_num_separator", PROPERTY_HINT_ENUM, "None,Space,Underscore,Dash")); + ProjectSettings::get_singleton()->set_custom_property_info("node/name_num_separator", PropertyInfo(Variant::INT, "node/name_num_separator", PROPERTY_HINT_ENUM, "None,Space,Underscore,Dash")); GLOBAL_DEF("node/name_casing", NAME_CASING_PASCAL_CASE); - GlobalConfig::get_singleton()->set_custom_property_info("node/name_casing", PropertyInfo(Variant::INT, "node/name_casing", PROPERTY_HINT_ENUM, "PascalCase,camelCase,snake_case")); + ProjectSettings::get_singleton()->set_custom_property_info("node/name_casing", PropertyInfo(Variant::INT, "node/name_casing", PROPERTY_HINT_ENUM, "PascalCase,camelCase,snake_case")); - ClassDB::bind_method(D_METHOD("_add_child_below_node", "node:Node", "child_node:Node", "legible_unique_name"), &Node::add_child_below_node, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("_add_child_below_node", "node", "child_node", "legible_unique_name"), &Node::add_child_below_node, DEFVAL(false)); ClassDB::bind_method(D_METHOD("set_name", "name"), &Node::set_name); ClassDB::bind_method(D_METHOD("get_name"), &Node::get_name); - ClassDB::bind_method(D_METHOD("add_child", "node:Node", "legible_unique_name"), &Node::add_child, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("remove_child", "node:Node"), &Node::remove_child); - //ClassDB::bind_method(D_METHOD("remove_and_delete_child","node:Node"),&Node::remove_and_delete_child); + ClassDB::bind_method(D_METHOD("add_child", "node", "legible_unique_name"), &Node::add_child, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("remove_child", "node"), &Node::remove_child); + //ClassDB::bind_method(D_METHOD("remove_and_delete_child","node"),&Node::remove_and_delete_child); ClassDB::bind_method(D_METHOD("get_child_count"), &Node::get_child_count); ClassDB::bind_method(D_METHOD("get_children"), &Node::_get_children); - ClassDB::bind_method(D_METHOD("get_child:Node", "idx"), &Node::get_child); + ClassDB::bind_method(D_METHOD("get_child", "idx"), &Node::get_child); ClassDB::bind_method(D_METHOD("has_node", "path"), &Node::has_node); - ClassDB::bind_method(D_METHOD("get_node:Node", "path"), &Node::get_node); - ClassDB::bind_method(D_METHOD("get_parent:Node"), &Node::get_parent); - ClassDB::bind_method(D_METHOD("find_node:Node", "mask", "recursive", "owned"), &Node::find_node, DEFVAL(true), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("get_node", "path"), &Node::get_node); + ClassDB::bind_method(D_METHOD("get_parent"), &Node::get_parent); + ClassDB::bind_method(D_METHOD("find_node", "mask", "recursive", "owned"), &Node::find_node, DEFVAL(true), DEFVAL(true)); ClassDB::bind_method(D_METHOD("has_node_and_resource", "path"), &Node::has_node_and_resource); ClassDB::bind_method(D_METHOD("get_node_and_resource", "path"), &Node::_get_node_and_resource); ClassDB::bind_method(D_METHOD("is_inside_tree"), &Node::is_inside_tree); - ClassDB::bind_method(D_METHOD("is_a_parent_of", "node:Node"), &Node::is_a_parent_of); - ClassDB::bind_method(D_METHOD("is_greater_than", "node:Node"), &Node::is_greater_than); + ClassDB::bind_method(D_METHOD("is_a_parent_of", "node"), &Node::is_a_parent_of); + ClassDB::bind_method(D_METHOD("is_greater_than", "node"), &Node::is_greater_than); ClassDB::bind_method(D_METHOD("get_path"), &Node::get_path); - ClassDB::bind_method(D_METHOD("get_path_to", "node:Node"), &Node::get_path_to); + ClassDB::bind_method(D_METHOD("get_path_to", "node"), &Node::get_path_to); ClassDB::bind_method(D_METHOD("add_to_group", "group", "persistent"), &Node::add_to_group, DEFVAL(false)); ClassDB::bind_method(D_METHOD("remove_from_group", "group"), &Node::remove_from_group); ClassDB::bind_method(D_METHOD("is_in_group", "group"), &Node::is_in_group); - ClassDB::bind_method(D_METHOD("move_child", "child_node:Node", "to_pos"), &Node::move_child); + ClassDB::bind_method(D_METHOD("move_child", "child_node", "to_pos"), &Node::move_child); ClassDB::bind_method(D_METHOD("get_groups"), &Node::_get_groups); ClassDB::bind_method(D_METHOD("raise"), &Node::raise); - ClassDB::bind_method(D_METHOD("set_owner", "owner:Node"), &Node::set_owner); - ClassDB::bind_method(D_METHOD("get_owner:Node"), &Node::get_owner); + ClassDB::bind_method(D_METHOD("set_owner", "owner"), &Node::set_owner); + ClassDB::bind_method(D_METHOD("get_owner"), &Node::get_owner); ClassDB::bind_method(D_METHOD("remove_and_skip"), &Node::remove_and_skip); ClassDB::bind_method(D_METHOD("get_index"), &Node::get_index); ClassDB::bind_method(D_METHOD("print_tree"), &Node::print_tree); @@ -2826,10 +2787,10 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("set_fixed_process_internal", "enable"), &Node::set_fixed_process_internal); ClassDB::bind_method(D_METHOD("is_fixed_processing_internal"), &Node::is_fixed_processing_internal); - ClassDB::bind_method(D_METHOD("get_tree:SceneTree"), &Node::get_tree); + ClassDB::bind_method(D_METHOD("get_tree"), &Node::get_tree); - ClassDB::bind_method(D_METHOD("duplicate:Node", "flags"), &Node::duplicate, DEFVAL(DUPLICATE_USE_INSTANCING | DUPLICATE_SIGNALS | DUPLICATE_GROUPS | DUPLICATE_SCRIPTS)); - ClassDB::bind_method(D_METHOD("replace_by", "node:Node", "keep_data"), &Node::replace_by, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("duplicate", "flags"), &Node::duplicate, DEFVAL(DUPLICATE_USE_INSTANCING | DUPLICATE_SIGNALS | DUPLICATE_GROUPS | DUPLICATE_SCRIPTS)); + ClassDB::bind_method(D_METHOD("replace_by", "node", "keep_data"), &Node::replace_by, DEFVAL(false)); ClassDB::bind_method(D_METHOD("set_scene_instance_load_placeholder", "load_placeholder"), &Node::set_scene_instance_load_placeholder); ClassDB::bind_method(D_METHOD("get_scene_instance_load_placeholder"), &Node::get_scene_instance_load_placeholder); @@ -2840,8 +2801,8 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("request_ready"), &Node::request_ready); - ClassDB::bind_method(D_METHOD("set_network_mode", "mode"), &Node::set_network_mode); - ClassDB::bind_method(D_METHOD("get_network_mode"), &Node::get_network_mode); + ClassDB::bind_method(D_METHOD("set_network_master", "id", "recursive"), &Node::set_network_master, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("get_network_master"), &Node::get_network_master); ClassDB::bind_method(D_METHOD("is_network_master"), &Node::is_network_master); @@ -2873,10 +2834,10 @@ void Node::_bind_methods() { ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "rpc_unreliable_id", &Node::_rpc_unreliable_id_bind, mi); } - ClassDB::bind_method(D_METHOD("rset", "property", "value:Variant"), &Node::rset); - ClassDB::bind_method(D_METHOD("rset_id", "peer_id", "property", "value:Variant"), &Node::rset_id); - ClassDB::bind_method(D_METHOD("rset_unreliable", "property", "value:Variant"), &Node::rset_unreliable); - ClassDB::bind_method(D_METHOD("rset_unreliable_id", "peer_id", "property", "value:Variant"), &Node::rset_unreliable_id); + ClassDB::bind_method(D_METHOD("rset", "property", "value"), &Node::rset); + ClassDB::bind_method(D_METHOD("rset_id", "peer_id", "property", "value"), &Node::rset_id); + ClassDB::bind_method(D_METHOD("rset_unreliable", "property", "value"), &Node::rset_unreliable); + ClassDB::bind_method(D_METHOD("rset_unreliable_id", "peer_id", "property", "value"), &Node::rset_unreliable_id); BIND_CONSTANT(NOTIFICATION_ENTER_TREE); BIND_CONSTANT(NOTIFICATION_EXIT_TREE); @@ -2897,10 +2858,6 @@ void Node::_bind_methods() { BIND_CONSTANT(NOTIFICATION_INTERNAL_PROCESS); BIND_CONSTANT(NOTIFICATION_INTERNAL_FIXED_PROCESS); - BIND_CONSTANT(NETWORK_MODE_INHERIT); - BIND_CONSTANT(NETWORK_MODE_MASTER); - BIND_CONSTANT(NETWORK_MODE_SLAVE); - BIND_CONSTANT(RPC_MODE_DISABLED); BIND_CONSTANT(RPC_MODE_REMOTE); BIND_CONSTANT(RPC_MODE_SYNC); @@ -2914,6 +2871,7 @@ void Node::_bind_methods() { BIND_CONSTANT(DUPLICATE_SIGNALS); BIND_CONSTANT(DUPLICATE_GROUPS); BIND_CONSTANT(DUPLICATE_SCRIPTS); + BIND_CONSTANT(DUPLICATE_USE_INSTANCING); ADD_SIGNAL(MethodInfo("renamed")); ADD_SIGNAL(MethodInfo("tree_entered")); @@ -2932,16 +2890,16 @@ void Node::_bind_methods() { BIND_VMETHOD(MethodInfo("_enter_tree")); BIND_VMETHOD(MethodInfo("_exit_tree")); BIND_VMETHOD(MethodInfo("_ready")); - BIND_VMETHOD(MethodInfo("_input", PropertyInfo(Variant::INPUT_EVENT, "event"))); - BIND_VMETHOD(MethodInfo("_unhandled_input", PropertyInfo(Variant::INPUT_EVENT, "event"))); - BIND_VMETHOD(MethodInfo("_unhandled_key_input", PropertyInfo(Variant::INPUT_EVENT, "key_event"))); + BIND_VMETHOD(MethodInfo("_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); + BIND_VMETHOD(MethodInfo("_unhandled_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); + BIND_VMETHOD(MethodInfo("_unhandled_key_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEventKey"))); //ClassDB::bind_method(D_METHOD("get_child",&Node::get_child,PH("index"))); //ClassDB::bind_method(D_METHOD("get_node",&Node::get_node,PH("path"))); } String Node::_get_name_num_separator() { - switch (GlobalConfig::get_singleton()->get("node/name_num_separator").operator int()) { + switch (ProjectSettings::get_singleton()->get("node/name_num_separator").operator int()) { case 0: return ""; case 1: return " "; case 2: return "_"; @@ -2971,8 +2929,7 @@ Node::Node() { data.unhandled_key_input = false; data.pause_mode = PAUSE_MODE_INHERIT; data.pause_owner = NULL; - data.network_mode = NETWORK_MODE_INHERIT; - data.network_owner = NULL; + data.network_master = 1; //server by default data.path_cache = NULL; data.parent_owned = false; data.in_constructor = true; diff --git a/scene/main/node.h b/scene/main/node.h index 714a58bd8..bb8d80a0c 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,11 +31,11 @@ #define NODE_H #include "class_db.h" -#include "global_config.h" #include "map.h" +#include "node_path.h" #include "object.h" -#include "path_db.h" -#include "scene/main/scene_main_loop.h" +#include "project_settings.h" +#include "scene/main/scene_tree.h" #include "script_language.h" class Viewport; @@ -60,13 +61,6 @@ public: DUPLICATE_USE_INSTANCING = 8 }; - enum NetworkMode { - - NETWORK_MODE_INHERIT, - NETWORK_MODE_MASTER, - NETWORK_MODE_SLAVE - }; - enum RPCMode { RPC_MODE_DISABLED, //no rpc for this method, calls to this will be blocked (default) @@ -121,8 +115,7 @@ private: PauseMode pause_mode; Node *pause_owner; - NetworkMode network_mode; - Node *network_owner; + int network_master; Map<StringName, RPCMode> rpc_methods; Map<StringName, RPCMode> rpc_properties; @@ -172,7 +165,6 @@ private: void _propagate_validate_owner(); void _print_stray_nodes(); void _propagate_pause_owner(Node *p_owner); - void _propagate_network_owner(Node *p_owner); Array _get_node_and_resource(const NodePath &p_path); void _duplicate_signals(const Node *p_original, Node *p_copy) const; @@ -311,14 +303,14 @@ public: float get_fixed_process_delta_time() const; bool is_fixed_processing() const; - void set_process(bool p_process); + void set_process(bool p_idle_process); float get_process_delta_time() const; bool is_processing() const; - void set_fixed_process_internal(bool p_process); + void set_fixed_process_internal(bool p_process_internal); bool is_fixed_processing_internal() const; - void set_process_internal(bool p_process); + void set_process_internal(bool p_idle_process_internal); bool is_processing_internal() const; void set_process_input(bool p_enable); @@ -392,8 +384,8 @@ public: bool is_displayed_folded() const; /* NETWORK */ - void set_network_mode(NetworkMode p_mode); - NetworkMode get_network_mode() const; + void set_network_master(int p_peer_id, bool p_recursive = true); + int get_network_master() const; bool is_network_master() const; void rpc_config(const StringName &p_method, RPCMode p_mode); // config a local method for RPC @@ -413,8 +405,8 @@ public: void rsetp(int p_peer_id, bool p_unreliable, const StringName &p_property, const Variant &p_value); - bool can_call_rpc(const StringName &p_method) const; - bool can_call_rset(const StringName &p_property) const; + bool can_call_rpc(const StringName &p_method, int p_from) const; + bool can_call_rset(const StringName &p_property, int p_from) const; Node(); ~Node(); diff --git a/scene/main/resource_preloader.cpp b/scene/main/resource_preloader.cpp index c08a6bcd5..ae323ba02 100644 --- a/scene/main/resource_preloader.cpp +++ b/scene/main/resource_preloader.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/main/resource_preloader.h b/scene/main/resource_preloader.h index 5fba70c1c..a54781dc8 100644 --- a/scene/main/resource_preloader.h +++ b/scene/main/resource_preloader.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_tree.cpp index 79ee4a6f7..66eafa107 100644 --- a/scene/main/scene_main_loop.cpp +++ b/scene/main/scene_tree.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -26,16 +27,17 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "scene_main_loop.h" +#include "scene_tree.h" -#include "global_config.h" #include "message_queue.h" #include "node.h" #include "os/keyboard.h" #include "os/os.h" #include "print_string.h" +#include "project_settings.h" #include <stdio.h> //#include "servers/spatial_sound_2d_server.h" + #include "io/marshalls.h" #include "io/resource_loader.h" #include "scene/resources/material.h" @@ -374,9 +376,13 @@ void SceneTree::input_text(const String &p_text) { root_lock--; } -void SceneTree::input_event(const InputEvent &p_event) { +bool SceneTree::is_input_handled() { + return input_handled; +} + +void SceneTree::input_event(const Ref<InputEvent> &p_event) { - if (is_editor_hint() && (p_event.type == InputEvent::JOYPAD_MOTION || p_event.type == InputEvent::JOYPAD_BUTTON)) + if (is_editor_hint() && (p_event->cast_to<InputEventJoypadButton>() || p_event->cast_to<InputEventJoypadMotion>())) return; //avoid joy input on editor root_lock++; @@ -384,8 +390,8 @@ void SceneTree::input_event(const InputEvent &p_event) { input_handled = false; - InputEvent ev = p_event; - ev.ID = ++last_id; //this should work better + Ref<InputEvent> ev = p_event; + ev->set_id(++last_id); //this should work better #if 0 switch(ev.type) { @@ -393,9 +399,9 @@ void SceneTree::input_event(const InputEvent &p_event) { Matrix32 ai = root->get_final_transform().affine_inverse(); Vector2 g = ai.xform(Vector2(ev.mouse_button.global_x,ev.mouse_button.global_y)); - Vector2 l = ai.xform(Vector2(ev.mouse_button.x,ev.mouse_button.y)); - ev.mouse_button.x=l.x; - ev.mouse_button.y=l.y; + Vector2 l = ai.xform(Vector2(ev->get_pos().x,ev->get_pos().y)); + ev->get_pos().x=l.x; + ev->get_pos().y=l.y; ev.mouse_button.global_x=g.x; ev.mouse_button.global_y=g.y; @@ -405,13 +411,13 @@ void SceneTree::input_event(const InputEvent &p_event) { Matrix32 ai = root->get_final_transform().affine_inverse(); Vector2 g = ai.xform(Vector2(ev.mouse_motion.global_x,ev.mouse_motion.global_y)); Vector2 l = ai.xform(Vector2(ev.mouse_motion.x,ev.mouse_motion.y)); - Vector2 r = ai.xform(Vector2(ev.mouse_motion.relative_x,ev.mouse_motion.relative_y)); + Vector2 r = ai.xform(Vector2(ev->get_relative().x,ev->get_relative().y)); ev.mouse_motion.x=l.x; ev.mouse_motion.y=l.y; ev.mouse_motion.global_x=g.x; ev.mouse_motion.global_y=g.y; - ev.mouse_motion.relative_x=r.x; - ev.mouse_motion.relative_y=r.y; + ev->get_relative().x=r.x; + ev->get_relative().y=r.y; } break; case InputEvent::SCREEN_TOUCH: { @@ -448,12 +454,12 @@ void SceneTree::input_event(const InputEvent &p_event) { //call_group(GROUP_CALL_REVERSE|GROUP_CALL_REALTIME|GROUP_CALL_MULIILEVEL,"input","_input",ev); /* - if (ev.type==InputEvent::KEY && ev.key.pressed && !ev.key.echo && ev.key.scancode==KEY_F12) { + if (ev.type==InputEvent::KEY && ev->is_pressed() && !ev->is_echo() && ev->get_scancode()==KEY_F12) { print_line("RAM: "+itos(Memory::get_static_mem_usage())); print_line("DRAM: "+itos(Memory::get_dynamic_mem_usage())); } - if (ev.type==InputEvent::KEY && ev.key.pressed && !ev.key.echo && ev.key.scancode==KEY_F11) { + if (ev.type==InputEvent::KEY && ev->is_pressed() && !ev->is_echo() && ev->get_scancode()==KEY_F11) { Memory::dump_static_mem_to_file("memdump.txt"); } @@ -465,9 +471,13 @@ void SceneTree::input_event(const InputEvent &p_event) { call_group_flags(GROUP_CALL_REALTIME, "_viewports", "_vp_input", ev); //special one for GUI, as controls use their own process check #endif - if (ScriptDebugger::get_singleton() && ScriptDebugger::get_singleton()->is_remote() && ev.type == InputEvent::KEY && ev.key.pressed && !ev.key.echo && ev.key.scancode == KEY_F8) { - ScriptDebugger::get_singleton()->request_quit(); + if (ScriptDebugger::get_singleton() && ScriptDebugger::get_singleton()->is_remote()) { + //quit from game window using F8 + Ref<InputEventKey> k = ev; + if (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_scancode() == KEY_F8) { + ScriptDebugger::get_singleton()->request_quit(); + } } _flush_ugc(); @@ -505,8 +515,6 @@ void SceneTree::input_event(const InputEvent &p_event) { void SceneTree::init() { //_quit=false; - accept_quit = true; - quit_on_go_back = true; initialized = true; input_handled = false; @@ -532,6 +540,7 @@ bool SceneTree::iteration(float p_time) { _notify_group_pause("fixed_process_internal", Node::NOTIFICATION_INTERNAL_FIXED_PROCESS); _notify_group_pause("fixed_process", Node::NOTIFICATION_FIXED_PROCESS); _flush_ugc(); + MessageQueue::get_singleton()->flush(); //small little hack _flush_transform_notifications(); call_group_flags(GROUP_CALL_REALTIME, "_viewports", "update_worlds"); root_lock--; @@ -558,6 +567,8 @@ bool SceneTree::idle(float p_time) { emit_signal("idle_frame"); + MessageQueue::get_singleton()->flush(); //small little hack + _flush_transform_notifications(); _notify_group_pause("idle_process_internal", Node::NOTIFICATION_INTERNAL_PROCESS); @@ -573,6 +584,7 @@ bool SceneTree::idle(float p_time) { } _flush_ugc(); + MessageQueue::get_singleton()->flush(); //small little hack _flush_transform_notifications(); //transforms after world update, to avoid unnecessary enter/exit notifications call_group_flags(GROUP_CALL_REALTIME, "_viewports", "update_worlds"); @@ -602,6 +614,30 @@ bool SceneTree::idle(float p_time) { _call_idle_callbacks(); +#ifdef TOOLS_ENABLED + + if (is_editor_hint()) { + //simple hack to reload fallback environment if it changed from editor + String env_path = ProjectSettings::get_singleton()->get("rendering/environment/default_environment"); + env_path = env_path.strip_edges(); //user may have added a space or two + String cpath; + Ref<Environment> fallback = get_root()->get_world()->get_fallback_environment(); + if (fallback.is_valid()) { + cpath = fallback->get_path(); + } + if (cpath != env_path) { + + if (env_path != String()) { + fallback = ResourceLoader::load(env_path); + } else { + fallback.unref(); + } + get_root()->get_world()->set_fallback_environment(fallback); + } + } + +#endif + return _quit; } @@ -655,7 +691,9 @@ void SceneTree::_notification(int p_notification) { get_root()->propagate_notification(p_notification); } break; case NOTIFICATION_TRANSLATION_CHANGED: { - get_root()->propagate_notification(Node::NOTIFICATION_TRANSLATION_CHANGED); + if (!is_editor_hint()) { + get_root()->propagate_notification(Node::NOTIFICATION_TRANSLATION_CHANGED); + } } break; case NOTIFICATION_WM_UNFOCUS_REQUEST: { @@ -678,24 +716,24 @@ void SceneTree::set_quit_on_go_back(bool p_enable) { quit_on_go_back = p_enable; } +#ifdef TOOLS_ENABLED void SceneTree::set_editor_hint(bool p_enabled) { editor_hint = p_enabled; } bool SceneTree::is_node_being_edited(const Node *p_node) const { -#ifdef TOOLS_ENABLED + return editor_hint && edited_scene_root && edited_scene_root->is_a_parent_of(p_node); -#else - return false; -#endif } bool SceneTree::is_editor_hint() const { return editor_hint; } +#endif +#ifdef DEBUG_ENABLED void SceneTree::set_debug_collisions_hint(bool p_enabled) { debug_collisions_hint = p_enabled; @@ -715,6 +753,7 @@ bool SceneTree::is_debugging_navigation_hint() const { return debug_navigation_hint; } +#endif void SceneTree::set_debug_collisions_color(const Color &p_color) { @@ -761,12 +800,12 @@ Ref<Material> SceneTree::get_debug_navigation_material() { if (navigation_material.is_valid()) return navigation_material; - Ref<FixedSpatialMaterial> line_material = Ref<FixedSpatialMaterial>(memnew(FixedSpatialMaterial)); - /* line_material->set_flag(Material::FLAG_UNSHADED, true); - line_material->set_line_width(3.0); - line_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA, true); - line_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_COLOR_ARRAY, true); - line_material->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,get_debug_navigation_color());*/ + Ref<SpatialMaterial> line_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); + line_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + line_material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); + line_material->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); + line_material->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + line_material->set_albedo(get_debug_navigation_color()); navigation_material = line_material; @@ -778,12 +817,12 @@ Ref<Material> SceneTree::get_debug_navigation_disabled_material() { if (navigation_disabled_material.is_valid()) return navigation_disabled_material; - Ref<FixedSpatialMaterial> line_material = Ref<FixedSpatialMaterial>(memnew(FixedSpatialMaterial)); - /* line_material->set_flag(Material::FLAG_UNSHADED, true); - line_material->set_line_width(3.0); - line_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA, true); - line_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_COLOR_ARRAY, true); - line_material->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,get_debug_navigation_disabled_color());*/ + Ref<SpatialMaterial> line_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); + line_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + line_material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); + line_material->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); + line_material->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + line_material->set_albedo(get_debug_navigation_disabled_color()); navigation_disabled_material = line_material; @@ -794,30 +833,31 @@ Ref<Material> SceneTree::get_debug_collision_material() { if (collision_material.is_valid()) return collision_material; - Ref<FixedSpatialMaterial> line_material = Ref<FixedSpatialMaterial>(memnew(FixedSpatialMaterial)); - /*line_material->set_flag(Material::FLAG_UNSHADED, true); - line_material->set_line_width(3.0); - line_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA, true); - line_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_COLOR_ARRAY, true); - line_material->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,get_debug_collisions_color());*/ + Ref<SpatialMaterial> line_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); + line_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + line_material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); + line_material->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); + line_material->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + line_material->set_albedo(get_debug_collisions_color()); collision_material = line_material; return collision_material; } -Ref<Mesh> SceneTree::get_debug_contact_mesh() { +Ref<ArrayMesh> SceneTree::get_debug_contact_mesh() { if (debug_contact_mesh.is_valid()) return debug_contact_mesh; - debug_contact_mesh = Ref<Mesh>(memnew(Mesh)); + debug_contact_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); - Ref<FixedSpatialMaterial> mat = memnew(FixedSpatialMaterial); - /*mat->set_flag(Material::FLAG_UNSHADED,true); - mat->set_flag(Material::FLAG_DOUBLE_SIDED,true); - mat->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true); - mat->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,get_debug_collision_contact_color());*/ + Ref<SpatialMaterial> mat = Ref<SpatialMaterial>(memnew(SpatialMaterial)); + mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); + mat->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); + mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + mat->set_albedo(get_debug_collision_contact_color()); Vector3 diamond[6] = { Vector3(-1, 0, 0), @@ -874,7 +914,7 @@ bool SceneTree::is_paused() const { return pause; } -void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p_method, const InputEvent &p_input) { +void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p_method, const Ref<InputEvent> &p_input) { Map<StringName, Group>::Element *E = group_map.find(p_group); if (!E) @@ -1071,7 +1111,7 @@ static void _fill_array(Node *p_node, Array &array, int p_level) { array.push_back(p_level); array.push_back(p_node->get_name()); array.push_back(p_node->get_class()); - array.push_back(p_node->get_instance_ID()); + array.push_back(p_node->get_instance_id()); for (int i = 0; i < p_node->get_child_count(); i++) { _fill_array(p_node->get_child(i), array, p_level + 1); @@ -1106,7 +1146,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()); + delete_queue.push_back(p_object->get_instance_id()); } int SceneTree::get_node_count() const { @@ -1118,7 +1158,7 @@ void SceneTree::_update_root_rect() { if (stretch_mode == STRETCH_MODE_DISABLED) { - root->set_size(last_screen_size); + root->set_size((last_screen_size / stretch_shrink).floor()); root->set_attach_to_screen_rect(Rect2(Point2(), last_screen_size)); root->set_size_override_stretch(false); root->set_size_override(false, Size2()); @@ -1142,7 +1182,7 @@ void SceneTree::_update_root_rect() { } else if (viewport_aspect < video_mode_aspect) { // screen ratio is smaller vertically - if (stretch_aspect == STRETCH_ASPECT_KEEP_HEIGHT) { + if (stretch_aspect == STRETCH_ASPECT_KEEP_HEIGHT || stretch_aspect == STRETCH_ASPECT_EXPAND) { //will stretch horizontally viewport_size.x = desired_res.y * video_mode_aspect; @@ -1157,7 +1197,7 @@ void SceneTree::_update_root_rect() { } } else { //screen ratio is smaller horizontally - if (stretch_aspect == STRETCH_ASPECT_KEEP_WIDTH) { + if (stretch_aspect == STRETCH_ASPECT_KEEP_WIDTH || stretch_aspect == STRETCH_ASPECT_EXPAND) { //will stretch horizontally viewport_size.x = desired_res.x; @@ -1178,12 +1218,11 @@ void SceneTree::_update_root_rect() { Size2 margin; Size2 offset; //black bars and margin - if (screen_size.x < video_mode.x) { + if (stretch_aspect != STRETCH_ASPECT_EXPAND && screen_size.x < video_mode.x) { margin.x = Math::round((video_mode.x - screen_size.x) / 2.0); VisualServer::get_singleton()->black_bars_set_margins(margin.x, 0, margin.x, 0); offset.x = Math::round(margin.x * viewport_size.y / screen_size.y); - } else if (screen_size.y < video_mode.y) { - + } else if (stretch_aspect != STRETCH_ASPECT_EXPAND && screen_size.y < video_mode.y) { margin.y = Math::round((video_mode.y - screen_size.y) / 2.0); VisualServer::get_singleton()->black_bars_set_margins(0, margin.y, 0, margin.y); offset.y = Math::round(margin.y * viewport_size.x / screen_size.x); @@ -1196,15 +1235,15 @@ void SceneTree::_update_root_rect() { switch (stretch_mode) { case STRETCH_MODE_2D: { - root->set_size(screen_size); + root->set_size((screen_size / stretch_shrink).floor()); root->set_attach_to_screen_rect(Rect2(margin, screen_size)); root->set_size_override_stretch(true); - root->set_size_override(true, viewport_size); + root->set_size_override(true, (viewport_size / stretch_shrink).floor()); } break; case STRETCH_MODE_VIEWPORT: { - root->set_size(viewport_size); + root->set_size((viewport_size / stretch_shrink).floor()); root->set_attach_to_screen_rect(Rect2(margin, screen_size)); root->set_size_override_stretch(false); root->set_size_override(false, Size2()); @@ -1213,11 +1252,12 @@ void SceneTree::_update_root_rect() { } } -void SceneTree::set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 p_minsize) { +void SceneTree::set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 p_minsize, int p_shrink) { stretch_mode = p_mode; stretch_aspect = p_aspect; stretch_min = p_minsize; + stretch_shrink = p_shrink; _update_root_rect(); } @@ -1728,6 +1768,16 @@ int SceneTree::get_network_unique_id() const { return network_peer->get_unique_id(); } +Vector<int> SceneTree::get_network_connected_peers() const { + ERR_FAIL_COND_V(!network_peer.is_valid(), Vector<int>()); + + Vector<int> ret; + for (Set<int>::Element *E = connected_peers.front(); E; E = E->next()) { + ret.push_back(E->get()); + } + + return ret; +} void SceneTree::set_refuse_new_network_connections(bool p_refuse) { ERR_FAIL_COND(!network_peer.is_valid()); network_peer->set_refuse_new_connections(p_refuse); @@ -1938,6 +1988,7 @@ void SceneTree::_network_process_packet(int p_from, const uint8_t *p_packet, int Node *node = NULL; if (target & 0x80000000) { + //use full path (not cached yet) int ofs = target & 0x7FFFFFFF; ERR_FAIL_COND(ofs >= p_packet_len); @@ -1953,7 +2004,7 @@ void SceneTree::_network_process_packet(int p_from, const uint8_t *p_packet, int ERR_FAIL_COND(node == NULL); } } else { - + //use cached path int id = target; Map<int, PathGetCache>::Element *E = path_get_cache.find(p_from); @@ -1988,7 +2039,7 @@ void SceneTree::_network_process_packet(int p_from, const uint8_t *p_packet, int if (packet_type == NETWORK_COMMAND_REMOTE_CALL) { - if (!node->can_call_rpc(name)) + if (!node->can_call_rpc(name, p_from)) return; int ofs = len_end + 1; @@ -2025,7 +2076,7 @@ void SceneTree::_network_process_packet(int p_from, const uint8_t *p_packet, int } else { - if (!node->can_call_rset(name)) + if (!node->can_call_rset(name, p_from)) return; int ofs = len_end + 1; @@ -2133,7 +2184,7 @@ void SceneTree::_bind_methods() { //ClassDB::bind_method(D_METHOD("call_group","call_flags","group","method","arg1","arg2"),&SceneMainLoop::_call_group,DEFVAL(Variant()),DEFVAL(Variant())); - ClassDB::bind_method(D_METHOD("get_root:Viewport"), &SceneTree::get_root); + ClassDB::bind_method(D_METHOD("get_root"), &SceneTree::get_root); ClassDB::bind_method(D_METHOD("has_group", "name"), &SceneTree::has_group); ClassDB::bind_method(D_METHOD("set_auto_accept_quit", "enabled"), &SceneTree::set_auto_accept_quit); @@ -2153,14 +2204,15 @@ void SceneTree::_bind_methods() { ClassDB::bind_method(D_METHOD("set_pause", "enable"), &SceneTree::set_pause); ClassDB::bind_method(D_METHOD("is_paused"), &SceneTree::is_paused); ClassDB::bind_method(D_METHOD("set_input_as_handled"), &SceneTree::set_input_as_handled); + ClassDB::bind_method(D_METHOD("is_input_handled"), &SceneTree::is_input_handled); - ClassDB::bind_method(D_METHOD("create_timer:SceneTreeTimer", "time_sec", "pause_mode_process"), &SceneTree::create_timer, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("create_timer", "time_sec", "pause_mode_process"), &SceneTree::create_timer, DEFVAL(true)); ClassDB::bind_method(D_METHOD("get_node_count"), &SceneTree::get_node_count); ClassDB::bind_method(D_METHOD("get_frame"), &SceneTree::get_frame); ClassDB::bind_method(D_METHOD("quit"), &SceneTree::quit); - ClassDB::bind_method(D_METHOD("set_screen_stretch", "mode", "aspect", "minsize"), &SceneTree::set_screen_stretch); + ClassDB::bind_method(D_METHOD("set_screen_stretch", "mode", "aspect", "minsize", "shrink"), &SceneTree::set_screen_stretch, DEFVAL(1)); ClassDB::bind_method(D_METHOD("queue_delete", "obj"), &SceneTree::queue_delete); @@ -2182,24 +2234,25 @@ void SceneTree::_bind_methods() { ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call_group", &SceneTree::_call_group, mi2); - ClassDB::bind_method(D_METHOD("notify_group", "call_flags", "group", "notification"), &SceneTree::notify_group); - ClassDB::bind_method(D_METHOD("set_group", "call_flags", "group", "property", "value"), &SceneTree::set_group); + ClassDB::bind_method(D_METHOD("notify_group", "group", "notification"), &SceneTree::notify_group); + ClassDB::bind_method(D_METHOD("set_group", "group", "property", "value"), &SceneTree::set_group); ClassDB::bind_method(D_METHOD("get_nodes_in_group", "group"), &SceneTree::_get_nodes_in_group); - ClassDB::bind_method(D_METHOD("set_current_scene", "child_node:Node"), &SceneTree::set_current_scene); - ClassDB::bind_method(D_METHOD("get_current_scene:Node"), &SceneTree::get_current_scene); + ClassDB::bind_method(D_METHOD("set_current_scene", "child_node"), &SceneTree::set_current_scene); + ClassDB::bind_method(D_METHOD("get_current_scene"), &SceneTree::get_current_scene); ClassDB::bind_method(D_METHOD("change_scene", "path"), &SceneTree::change_scene); - ClassDB::bind_method(D_METHOD("change_scene_to", "packed_scene:PackedScene"), &SceneTree::change_scene_to); + ClassDB::bind_method(D_METHOD("change_scene_to", "packed_scene"), &SceneTree::change_scene_to); ClassDB::bind_method(D_METHOD("reload_current_scene"), &SceneTree::reload_current_scene); ClassDB::bind_method(D_METHOD("_change_scene"), &SceneTree::_change_scene); - ClassDB::bind_method(D_METHOD("set_network_peer", "peer:NetworkedMultiplayerPeer"), &SceneTree::set_network_peer); + ClassDB::bind_method(D_METHOD("set_network_peer", "peer"), &SceneTree::set_network_peer); ClassDB::bind_method(D_METHOD("is_network_server"), &SceneTree::is_network_server); ClassDB::bind_method(D_METHOD("has_network_peer"), &SceneTree::has_network_peer); + ClassDB::bind_method(D_METHOD("get_network_connected_peers"), &SceneTree::get_network_connected_peers); ClassDB::bind_method(D_METHOD("get_network_unique_id"), &SceneTree::get_network_unique_id); ClassDB::bind_method(D_METHOD("set_refuse_new_network_connections", "refuse"), &SceneTree::set_refuse_new_network_connections); ClassDB::bind_method(D_METHOD("is_refusing_new_network_connections"), &SceneTree::is_refusing_new_network_connections); @@ -2259,15 +2312,21 @@ SceneTree::SceneTree() { singleton = this; _quit = false; + accept_quit = true; + quit_on_go_back = true; initialized = false; +#ifdef TOOLS_ENABLED editor_hint = false; +#endif +#ifdef DEBUG_ENABLED debug_collisions_hint = false; debug_navigation_hint = false; - debug_collisions_color = GLOBAL_DEF("debug/collision/shape_color", Color(0.0, 0.6, 0.7, 0.5)); - debug_collision_contact_color = GLOBAL_DEF("debug/collision/contact_color", Color(1.0, 0.2, 0.1, 0.8)); - debug_navigation_color = GLOBAL_DEF("debug/navigation/geometry_color", Color(0.1, 1.0, 0.7, 0.4)); - debug_navigation_disabled_color = GLOBAL_DEF("debug/navigation/disabled_geometry_color", Color(1.0, 0.7, 0.1, 0.4)); - collision_debug_contacts = GLOBAL_DEF("debug/collision/max_contacts_displayed", 10000); +#endif + debug_collisions_color = GLOBAL_DEF("debug/shapes/collision/shape_color", Color(0.0, 0.6, 0.7, 0.5)); + debug_collision_contact_color = GLOBAL_DEF("debug/shapes/collision/contact_color", Color(1.0, 0.2, 0.1, 0.8)); + debug_navigation_color = GLOBAL_DEF("debug/shapes/navigation/geometry_color", Color(0.1, 1.0, 0.7, 0.4)); + debug_navigation_disabled_color = GLOBAL_DEF("debug/shapes/navigation/disabled_geometry_color", Color(1.0, 0.7, 0.1, 0.4)); + collision_debug_contacts = GLOBAL_DEF("debug/shapes/collision/max_contacts_displayed", 10000); tree_version = 1; fixed_process_time = 1; @@ -2286,27 +2345,65 @@ SceneTree::SceneTree() { root = memnew(Viewport); root->set_name("root"); - root->set_world(Ref<World>(memnew(World))); + if (!root->get_world().is_valid()) + root->set_world(Ref<World>(memnew(World))); + //root->set_world_2d( Ref<World2D>( memnew( World2D ))); root->set_as_audio_listener(true); root->set_as_audio_listener_2d(true); current_scene = NULL; - int ref_atlas_size = GLOBAL_DEF("rendering/reflections/atlas_size", 2048); - int ref_atlas_subdiv = GLOBAL_DEF("rendering/reflections/atlas_subdiv", 8); - int msaa_mode = GLOBAL_DEF("rendering/quality/msaa", 0); - GlobalConfig::get_singleton()->set_custom_property_info("rendering/quality/msaa", PropertyInfo(Variant::INT, "rendering/quality/msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x")); + int ref_atlas_size = GLOBAL_DEF("rendering/quality/reflections/atlas_size", 2048); + int ref_atlas_subdiv = GLOBAL_DEF("rendering/quality/reflections/atlas_subdiv", 8); + int msaa_mode = GLOBAL_DEF("rendering/quality/filters/msaa", 0); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/filters/msaa", PropertyInfo(Variant::INT, "rendering/quality/filters/msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x")); root->set_msaa(Viewport::MSAA(msaa_mode)); - bool hdr = GLOBAL_DEF("rendering/quality/hdr", true); + + GLOBAL_DEF("rendering/quality/depth/hdr", true); + GLOBAL_DEF("rendering/quality/depth/hdr.mobile", false); + + bool hdr = GLOBAL_GET("rendering/quality/depth/hdr"); root->set_hdr(hdr); VS::get_singleton()->scenario_set_reflection_atlas_size(root->get_world()->get_scenario(), ref_atlas_size, ref_atlas_subdiv); + { //load default fallback environment + //get possible extensions + List<String> exts; + ResourceLoader::get_recognized_extensions_for_type("Environment", &exts); + String ext_hint; + for (List<String>::Element *E = exts.front(); E; E = E->next()) { + if (ext_hint != String()) + ext_hint += ","; + ext_hint += "*." + E->get(); + } + //get path + String env_path = GLOBAL_DEF("rendering/environment/default_environment", ""); + //setup property + ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/default_environment", PropertyInfo(Variant::STRING, "rendering/viewport/default_environment", PROPERTY_HINT_FILE, ext_hint)); + env_path = env_path.strip_edges(); + if (env_path != String()) { + Ref<Environment> env = ResourceLoader::load(env_path); + if (env.is_valid()) { + root->get_world()->set_fallback_environment(env); + } else { + if (is_editor_hint()) { + //file was erased, clear the field. + ProjectSettings::get_singleton()->set("rendering/environment/default_environment", ""); + } else { + //file was erased, notify user. + ERR_PRINTS(RTR("Default Environment as specified in Project Setings (Rendering -> Viewport -> Default Environment) could not be loaded.")); + } + } + } + } + stretch_mode = STRETCH_MODE_DISABLED; stretch_aspect = STRETCH_ASPECT_IGNORE; + stretch_shrink = 1; last_screen_size = Size2(OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height); - root->set_size(last_screen_size); + _update_root_rect(); if (ScriptDebugger::get_singleton()) { ScriptDebugger::get_singleton()->set_request_scene_tree_message_func(_debugger_request_tree, this); diff --git a/scene/main/scene_main_loop.h b/scene/main/scene_tree.h index fadf77e30..3543ebee9 100644 --- a/scene/main/scene_main_loop.h +++ b/scene/main/scene_tree.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,6 +33,7 @@ #include "io/networked_multiplayer_peer.h" #include "os/main_loop.h" #include "os/thread_safe.h" +#include "scene/resources/mesh.h" #include "scene/resources/world.h" #include "scene/resources/world_2d.h" #include "self_list.h" @@ -88,6 +90,7 @@ public: STRETCH_ASPECT_KEEP, STRETCH_ASPECT_KEEP_WIDTH, STRETCH_ASPECT_KEEP_HEIGHT, + STRETCH_ASPECT_EXPAND, }; private: @@ -108,9 +111,13 @@ private: bool quit_on_go_back; uint32_t last_id; +#ifdef TOOLS_ENABLED bool editor_hint; +#endif +#ifdef DEBUG_ENABLED bool debug_collisions_hint; bool debug_navigation_hint; +#endif bool pause; int root_lock; @@ -143,6 +150,7 @@ private: StretchMode stretch_mode; StretchAspect stretch_aspect; Size2i stretch_min; + int stretch_shrink; void _update_root_rect(); @@ -164,7 +172,7 @@ private: Color debug_collision_contact_color; Color debug_navigation_color; Color debug_navigation_disabled_color; - Ref<Mesh> debug_contact_mesh; + Ref<ArrayMesh> debug_contact_mesh; Ref<Material> navigation_material; Ref<Material> navigation_disabled_material; Ref<Material> collision_material; @@ -232,7 +240,7 @@ private: void remove_from_group(const StringName &p_group, Node *p_node); void _notify_group_pause(const StringName &p_group, int p_notification); - void _call_input_pause(const StringName &p_group, const StringName &p_method, const InputEvent &p_input); + void _call_input_pause(const StringName &p_group, const StringName &p_method, const Ref<InputEvent> &p_input); Variant _call_group_flags(const Variant **p_args, int p_argcount, Variant::CallError &r_error); Variant _call_group(const Variant **p_args, int p_argcount, Variant::CallError &r_error); @@ -336,7 +344,7 @@ public: void set_group(const StringName &p_group, const String &p_name, const Variant &p_value); virtual void input_text(const String &p_text); - virtual void input_event(const InputEvent &p_event); + virtual void input_event(const Ref<InputEvent> &p_event); virtual void init(); virtual bool iteration(float p_time); @@ -350,13 +358,21 @@ public: void quit(); void set_input_as_handled(); + bool is_input_handled(); _FORCE_INLINE_ float get_fixed_process_time() const { return fixed_process_time; } _FORCE_INLINE_ float get_idle_process_time() const { return idle_process_time; } +#ifdef TOOLS_ENABLED void set_editor_hint(bool p_enabled); - bool is_editor_hint() const; + bool is_editor_hint() const; bool is_node_being_edited(const Node *p_node) const; +#else + void set_editor_hint(bool p_enabled) {} + + bool is_editor_hint() const { return false; } + bool is_node_being_edited(const Node *p_node) const { return false; } +#endif void set_pause(bool p_enabled); bool is_paused() const; @@ -364,11 +380,19 @@ public: void set_camera(const RID &p_camera); RID get_camera() const; +#ifdef DEBUG_ENABLED void set_debug_collisions_hint(bool p_enabled); bool is_debugging_collisions_hint() const; void set_debug_navigation_hint(bool p_enabled); bool is_debugging_navigation_hint() const; +#else + void set_debug_collisions_hint(bool p_enabled) {} + bool is_debugging_collisions_hint() const { return false; } + + void set_debug_navigation_hint(bool p_enabled) {} + bool is_debugging_navigation_hint() const { return false; } +#endif void set_debug_collisions_color(const Color &p_color); Color get_debug_collisions_color() const; @@ -385,7 +409,7 @@ public: Ref<Material> get_debug_navigation_material(); Ref<Material> get_debug_navigation_disabled_material(); Ref<Material> get_debug_collision_material(); - Ref<Mesh> get_debug_contact_mesh(); + Ref<ArrayMesh> get_debug_contact_mesh(); int get_collision_debug_contact_count() { return collision_debug_contacts; } @@ -398,7 +422,7 @@ public: void get_nodes_in_group(const StringName &p_group, List<Node *> *p_list); bool has_group(const StringName &p_identifier) const; - void set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 p_minsize); + void set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 p_minsize, int p_shrink = 1); //void change_scene(const String& p_path); //Node *get_loaded_scene(); @@ -429,6 +453,7 @@ public: bool is_network_server() const; bool has_network_peer() const; int get_network_unique_id() const; + Vector<int> get_network_connected_peers() const; void set_refuse_new_network_connections(bool p_refuse); bool is_refusing_new_network_connections() const; diff --git a/scene/main/timer.cpp b/scene/main/timer.cpp index 2263e8231..a61d1100e 100755 --- a/scene/main/timer.cpp +++ b/scene/main/timer.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -50,8 +51,7 @@ void Timer::_notification(int p_what) { if (time_left < 0) { if (!one_shot) - //time_left=wait_time+time_left; - time_left = wait_time; + time_left += wait_time; else stop(); @@ -66,8 +66,7 @@ void Timer::_notification(int p_what) { if (time_left < 0) { if (!one_shot) - //time_left = wait_time + time_left; - time_left = wait_time; + time_left += wait_time; else stop(); emit_signal("timeout"); diff --git a/scene/main/timer.h b/scene/main/timer.h index 53a2ddb2b..dd4711ec3 100755 --- a/scene/main/timer.h +++ b/scene/main/timer.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 23f818916..a22d89766 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -47,7 +48,8 @@ #include "scene/main/timer.h" #include "scene/scene_string_names.h" -#include "global_config.h" +#include "project_settings.h" +#include "scene/3d/scenario_fx.h" void ViewportTexture::setup_local_to_scene() { @@ -116,7 +118,11 @@ bool ViewportTexture::has_alpha() const { return false; } +Ref<Image> ViewportTexture::get_data() const { + ERR_FAIL_COND_V(!vp, Ref<Image>()); + return VS::get_singleton()->texture_get_data(vp->texture_rid); +} void ViewportTexture::set_flags(uint32_t p_flags) { if (!vp) @@ -318,7 +324,8 @@ void Viewport::update_worlds() { if (!is_inside_tree()) return; - Rect2 xformed_rect = (global_canvas_transform * canvas_transform).affine_inverse().xform(get_visible_rect()); + Rect2 abstracted_rect = Rect2(Vector2(), get_visible_rect().size); + Rect2 xformed_rect = (global_canvas_transform * canvas_transform).affine_inverse().xform(abstracted_rect); find_world_2d()->_update_viewport(this, xformed_rect); find_world_2d()->_update(); @@ -502,30 +509,36 @@ void Viewport::_notification(int p_what) { while (physics_picking_events.size()) { - InputEvent ev = physics_picking_events.front()->get(); + Ref<InputEvent> ev = physics_picking_events.front()->get(); physics_picking_events.pop_front(); Vector2 pos; - switch (ev.type) { - case InputEvent::MOUSE_MOTION: { - pos.x = ev.mouse_motion.x; - pos.y = ev.mouse_motion.y; - motion_tested = true; - physics_last_mousepos = pos; - } break; - case InputEvent::MOUSE_BUTTON: { - pos.x = ev.mouse_button.x; - pos.y = ev.mouse_button.y; - } break; - case InputEvent::SCREEN_DRAG: { - pos.x = ev.screen_drag.x; - pos.y = ev.screen_drag.y; - } break; - case InputEvent::SCREEN_TOUCH: { - pos.x = ev.screen_touch.x; - pos.y = ev.screen_touch.y; - } break; + Ref<InputEventMouseMotion> mm = ev; + + if (mm.is_valid()) { + + pos = mm->get_position(); + motion_tested = true; + physics_last_mousepos = pos; + } + + Ref<InputEventMouseButton> mb = ev; + + if (mb.is_valid()) { + pos = mb->get_position(); + } + + Ref<InputEventScreenDrag> sd = ev; + + if (sd.is_valid()) { + pos = sd->get_position(); + } + + Ref<InputEventScreenTouch> st = ev; + + if (st.is_valid()) { + pos = st->get_position(); } if (ss2d) { @@ -588,7 +601,7 @@ void Viewport::_notification(int p_what) { if (co) { co->_input_event(camera, ev, Vector3(), Vector3(), 0); captured = true; - if (ev.type == InputEvent::MOUSE_BUTTON && ev.mouse_button.button_index == 1 && !ev.mouse_button.pressed) { + if (mb.is_valid() && mb->get_button_index() == 1 && !mb->is_pressed()) { physics_object_capture = 0; } @@ -608,7 +621,7 @@ void Viewport::_notification(int p_what) { if (ObjectDB::get_instance(last_id)) { //good, exists last_object->_input_event(camera, ev, result.position, result.normal, result.shape); - if (last_object->get_capture_input_on_drag() && ev.type == InputEvent::MOUSE_BUTTON && ev.mouse_button.button_index == 1 && ev.mouse_button.pressed) { + if (last_object->get_capture_input_on_drag() && mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) { physics_object_capture = last_id; } } @@ -636,14 +649,14 @@ void Viewport::_notification(int p_what) { last_object = co; last_id = result.collider_id; new_collider = last_id; - if (co->get_capture_input_on_drag() && ev.type == InputEvent::MOUSE_BUTTON && ev.mouse_button.button_index == 1 && ev.mouse_button.pressed) { + if (co->get_capture_input_on_drag() && mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) { physics_object_capture = last_id; } } } } - if (ev.type == InputEvent::MOUSE_MOTION) { + if (mm.is_valid()) { _test_new_mouseover(new_collider); } } @@ -688,6 +701,16 @@ RID Viewport::get_viewport_rid() const { return viewport; } +void Viewport::set_use_arvr(bool p_use_arvr) { + arvr = p_use_arvr; + + VS::get_singleton()->viewport_set_use_arvr(viewport, arvr); +} + +bool Viewport::use_arvr() { + return arvr; +} + void Viewport::set_size(const Size2 &p_size) { if (size == p_size.floor()) @@ -1006,10 +1029,9 @@ void Viewport::_propagate_enter_world(Node *p_node) { if (!p_node->is_inside_tree()) //may not have entered scene yet return; - Spatial *s = p_node->cast_to<Spatial>(); - if (s) { + if (p_node->cast_to<Spatial>() || p_node->cast_to<WorldEnvironment>()) { - s->notification(Spatial::NOTIFICATION_ENTER_WORLD); + p_node->notification(Spatial::NOTIFICATION_ENTER_WORLD); } else { Viewport *v = p_node->cast_to<Viewport>(); if (v) { @@ -1044,10 +1066,9 @@ void Viewport::_propagate_exit_world(Node *p_node) { if (!p_node->is_inside_tree()) //may have exited scene already return; - Spatial *s = p_node->cast_to<Spatial>(); - if (s) { + if (p_node->cast_to<Spatial>() || p_node->cast_to<WorldEnvironment>()) { - s->notification(Spatial::NOTIFICATION_EXIT_WORLD, true); + p_node->notification(Spatial::NOTIFICATION_EXIT_WORLD); } else { Viewport *v = p_node->cast_to<Viewport>(); if (v) { @@ -1145,6 +1166,7 @@ void Viewport::set_size_override(bool p_enable, const Size2 &p_size, const Vecto size_override_margin = p_margin; _update_rect(); _update_stretch_transform(); + emit_signal("size_changed"); } Size2 Viewport::get_size_override() const { @@ -1221,16 +1243,6 @@ Viewport::UpdateMode Viewport::get_update_mode() const { } //RID get_texture() const; -void Viewport::queue_screen_capture() { - - //VS::get_singleton()->viewport_queue_screen_capture(viewport); -} -Image Viewport::get_screen_capture() const { - - //return VS::get_singleton()->viewport_get_screen_capture(viewport); - return Image(); -} - Ref<ViewportTexture> Viewport::get_texture() const { return default_texture; @@ -1303,7 +1315,7 @@ Transform2D Viewport::_get_input_pre_xform() const { if (to_screen_rect != Rect2()) { - pre_xf.elements[2] = -to_screen_rect.pos; + pre_xf.elements[2] = -to_screen_rect.position; pre_xf.scale(size / to_screen_rect.size); } @@ -1321,71 +1333,12 @@ Vector2 Viewport::_get_window_offset() const { return Vector2(); } -void Viewport::_make_input_local(InputEvent &ev) { - - switch (ev.type) { - - case InputEvent::MOUSE_BUTTON: { - - Vector2 vp_ofs = _get_window_offset(); - - Transform2D ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); - Vector2 g = ai.xform(Vector2(ev.mouse_button.global_x, ev.mouse_button.global_y)); - Vector2 l = ai.xform(Vector2(ev.mouse_button.x, ev.mouse_button.y) - vp_ofs); - - ev.mouse_button.x = l.x; - ev.mouse_button.y = l.y; - ev.mouse_button.global_x = g.x; - ev.mouse_button.global_y = g.y; - - } break; - case InputEvent::MOUSE_MOTION: { - - Vector2 vp_ofs = _get_window_offset(); - - Transform2D ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); - Vector2 g = ai.xform(Vector2(ev.mouse_motion.global_x, ev.mouse_motion.global_y)); - Vector2 l = ai.xform(Vector2(ev.mouse_motion.x, ev.mouse_motion.y) - vp_ofs); - Vector2 r = ai.basis_xform(Vector2(ev.mouse_motion.relative_x, ev.mouse_motion.relative_y)); - Vector2 s = ai.basis_xform(Vector2(ev.mouse_motion.speed_x, ev.mouse_motion.speed_y)); +Ref<InputEvent> Viewport::_make_input_local(const Ref<InputEvent> &ev) { - ev.mouse_motion.x = l.x; - ev.mouse_motion.y = l.y; - ev.mouse_motion.global_x = g.x; - ev.mouse_motion.global_y = g.y; - ev.mouse_motion.relative_x = r.x; - ev.mouse_motion.relative_y = r.y; - ev.mouse_motion.speed_x = s.x; - ev.mouse_motion.speed_y = s.y; + Vector2 vp_ofs = _get_window_offset(); + Transform2D ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); - } break; - case InputEvent::SCREEN_TOUCH: { - - Vector2 vp_ofs = _get_window_offset(); - - Transform2D ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); - Vector2 t = ai.xform(Vector2(ev.screen_touch.x, ev.screen_touch.y) - vp_ofs); - - ev.screen_touch.x = t.x; - ev.screen_touch.y = t.y; - - } break; - case InputEvent::SCREEN_DRAG: { - - Vector2 vp_ofs = _get_window_offset(); - - Transform2D ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); - Vector2 t = ai.xform(Vector2(ev.screen_drag.x, ev.screen_drag.y) - vp_ofs); - Vector2 r = ai.basis_xform(Vector2(ev.screen_drag.relative_x, ev.screen_drag.relative_y)); - Vector2 s = ai.basis_xform(Vector2(ev.screen_drag.speed_x, ev.screen_drag.speed_y)); - ev.screen_drag.x = t.x; - ev.screen_drag.y = t.y; - ev.screen_drag.relative_x = r.x; - ev.screen_drag.relative_y = r.y; - ev.screen_drag.speed_x = s.x; - ev.screen_drag.speed_y = s.y; - } break; - } + return ev->xformed_by(ai, -vp_ofs); } void Viewport::_vp_input_text(const String &p_text) { @@ -1395,13 +1348,13 @@ void Viewport::_vp_input_text(const String &p_text) { } } -void Viewport::_vp_input(const InputEvent &p_ev) { +void Viewport::_vp_input(const Ref<InputEvent> &p_ev) { if (disable_input) return; #ifdef TOOLS_ENABLED - if (get_tree()->is_editor_hint() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) { + if (get_tree()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) { return; } #endif @@ -1412,17 +1365,16 @@ void Viewport::_vp_input(const InputEvent &p_ev) { //this one handles system input, p_ev are in system coordinates //they are converted to viewport coordinates - InputEvent ev = p_ev; - _make_input_local(ev); + Ref<InputEvent> ev = _make_input_local(p_ev); input(ev); } -void Viewport::_vp_unhandled_input(const InputEvent &p_ev) { +void Viewport::_vp_unhandled_input(const Ref<InputEvent> &p_ev) { if (disable_input) return; #ifdef TOOLS_ENABLED - if (get_tree()->is_editor_hint() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) { + if (get_tree()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) { return; } #endif @@ -1438,14 +1390,13 @@ void Viewport::_vp_unhandled_input(const InputEvent &p_ev) { //this one handles system input, p_ev are in system coordinates //they are converted to viewport coordinates - InputEvent ev = p_ev; - _make_input_local(ev); + Ref<InputEvent> ev = _make_input_local(p_ev); unhandled_input(ev); } -Vector2 Viewport::get_mouse_pos() const { +Vector2 Viewport::get_mouse_position() const { - return (get_final_transform().affine_inverse() * _get_input_pre_xform()).xform(Input::get_singleton()->get_mouse_pos() - _get_window_offset()); + return (get_final_transform().affine_inverse() * _get_input_pre_xform()).xform(Input::get_singleton()->get_mouse_position() - _get_window_offset()); } void Viewport::warp_mouse(const Vector2 &p_pos) { @@ -1522,40 +1473,44 @@ void Viewport::_gui_show_tooltip() { gui.tooltip_label->set_anchor_and_margin(MARGIN_LEFT, Control::ANCHOR_BEGIN, ttp->get_margin(MARGIN_LEFT)); gui.tooltip_label->set_anchor_and_margin(MARGIN_TOP, Control::ANCHOR_BEGIN, ttp->get_margin(MARGIN_TOP)); - gui.tooltip_label->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, ttp->get_margin(MARGIN_RIGHT)); - gui.tooltip_label->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_END, ttp->get_margin(MARGIN_BOTTOM)); + gui.tooltip_label->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -ttp->get_margin(MARGIN_RIGHT)); + gui.tooltip_label->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_END, -ttp->get_margin(MARGIN_BOTTOM)); gui.tooltip_label->set_text(tooltip); Rect2 r(gui.tooltip_pos + Point2(10, 10), gui.tooltip_label->get_combined_minimum_size() + ttp->get_minimum_size()); Rect2 vr = gui.tooltip_label->get_viewport_rect(); - if (r.size.x + r.pos.x > vr.size.x) - r.pos.x = vr.size.x - r.size.x; - else if (r.pos.x < 0) - r.pos.x = 0; + if (r.size.x + r.position.x > vr.size.x) + r.position.x = vr.size.x - r.size.x; + else if (r.position.x < 0) + r.position.x = 0; - if (r.size.y + r.pos.y > vr.size.y) - r.pos.y = vr.size.y - r.size.y; - else if (r.pos.y < 0) - r.pos.y = 0; + if (r.size.y + r.position.y > vr.size.y) + r.position.y = vr.size.y - r.size.y; + else if (r.position.y < 0) + r.position.y = 0; - gui.tooltip_popup->set_global_pos(r.pos); + gui.tooltip_popup->set_global_position(r.position); gui.tooltip_popup->set_size(r.size); gui.tooltip_popup->raise(); gui.tooltip_popup->show(); } -void Viewport::_gui_call_input(Control *p_control, const InputEvent &p_input) { +void Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_input) { //_block(); - InputEvent ev = p_input; + Ref<InputEvent> ev = p_input; //mouse wheel events can't be stopped - bool cant_stop_me_now = (ev.type == InputEvent::MOUSE_BUTTON && - (ev.mouse_button.button_index == BUTTON_WHEEL_DOWN || - ev.mouse_button.button_index == BUTTON_WHEEL_UP || - ev.mouse_button.button_index == BUTTON_WHEEL_LEFT || - ev.mouse_button.button_index == BUTTON_WHEEL_RIGHT)); + Ref<InputEventMouseButton> mb = p_input; + + bool cant_stop_me_now = (mb.is_valid() && + (mb->get_button_index() == BUTTON_WHEEL_DOWN || + mb->get_button_index() == BUTTON_WHEEL_UP || + mb->get_button_index() == BUTTON_WHEEL_LEFT || + mb->get_button_index() == BUTTON_WHEEL_RIGHT)); + + bool ismouse = ev.is_valid() || p_input->cast_to<InputEventMouseMotion>() != NULL; CanvasItem *ci = p_control; while (ci) { @@ -1572,14 +1527,14 @@ void Viewport::_gui_call_input(Control *p_control, const InputEvent &p_input) { break; if (gui.key_event_accepted) break; - if (!cant_stop_me_now && control->data.mouse_filter == Control::MOUSE_FILTER_STOP && (ev.type == InputEvent::MOUSE_BUTTON || ev.type == InputEvent::MOUSE_MOTION)) + if (!cant_stop_me_now && control->data.mouse_filter == Control::MOUSE_FILTER_STOP && ismouse) break; } if (ci->is_set_as_toplevel()) break; - ev = ev.xform_by(ci->get_transform()); //transform event upwards + ev = ev->xformed_by(ci->get_transform()); //transform event upwards ci = ci->get_parent_item(); } @@ -1639,7 +1594,7 @@ Control *Viewport::_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_ Control *c = p_node->cast_to<Control>(); if (c) { - //print_line("at "+String(c->get_path())+" POS "+c->get_pos()+" bt "+p_xform); + //print_line("at "+String(c->get_path())+" POS "+c->get_position()+" bt "+p_xform); } //subwindows first!! @@ -1717,9 +1672,9 @@ bool Viewport::_gui_drop(Control *p_at_control, Point2 p_at_pos, bool p_just_che return false; } -void Viewport::_gui_input_event(InputEvent p_event) { +void Viewport::_gui_input_event(Ref<InputEvent> p_event) { - if (p_event.ID == gui.cancelled_input_ID) { + if (p_event->get_id() == gui.cancelled_input_ID) { return; } //? @@ -1729,430 +1684,513 @@ void Viewport::_gui_input_event(InputEvent p_event) { } */ - switch (p_event.type) { + Ref<InputEventMouseButton> mb = p_event; - case InputEvent::MOUSE_BUTTON: { + if (mb.is_valid()) { - gui.key_event_accepted = false; - - Point2 mpos = Point2(p_event.mouse_button.x, p_event.mouse_button.y); - if (p_event.mouse_button.pressed) { + gui.key_event_accepted = false; - Size2 pos = mpos; - if (gui.mouse_focus && p_event.mouse_button.button_index != gui.mouse_focus_button) { + Point2 mpos = mb->get_position(); + if (mb->is_pressed()) { - //do not steal mouse focus and stuff + Size2 pos = mpos; + if (gui.mouse_focus && mb->get_button_index() != gui.mouse_focus_button) { - } else { + //do not steal mouse focus and stuff - _gui_sort_modal_stack(); - while (!gui.modal_stack.empty()) { + } else { - Control *top = gui.modal_stack.back()->get(); - Vector2 pos = top->get_global_transform_with_canvas().affine_inverse().xform(mpos); - if (!top->has_point(pos)) { + _gui_sort_modal_stack(); + while (!gui.modal_stack.empty()) { - if (top->data.modal_exclusive || top->data.modal_frame == Engine::get_singleton()->get_frames_drawn()) { - //cancel event, sorry, modal exclusive EATS UP ALL - //alternative, you can't pop out a window the same frame it was made modal (fixes many issues) - get_tree()->set_input_as_handled(); - return; // no one gets the event if exclusive NO ONE - } + Control *top = gui.modal_stack.back()->get(); + Vector2 pos = top->get_global_transform_with_canvas().affine_inverse().xform(mpos); + if (!top->has_point(pos)) { - top->notification(Control::NOTIFICATION_MODAL_CLOSE); - top->_modal_stack_remove(); - top->hide(); - } else { - break; + if (top->data.modal_exclusive || top->data.modal_frame == Engine::get_singleton()->get_frames_drawn()) { + //cancel event, sorry, modal exclusive EATS UP ALL + //alternative, you can't pop out a window the same frame it was made modal (fixes many issues) + get_tree()->set_input_as_handled(); + return; // no one gets the event if exclusive NO ONE } + + top->notification(Control::NOTIFICATION_MODAL_CLOSE); + top->_modal_stack_remove(); + top->hide(); + } else { + break; } + } - //Matrix32 parent_xform; + //Matrix32 parent_xform; - /* - if (data.parent_canvas_item) - parent_xform=data.parent_canvas_item->get_global_transform(); - */ + /* + if (data.parent_canvas_item) + parent_xform=data.parent_canvas_item->get_global_transform(); + */ - gui.mouse_focus = _gui_find_control(pos); - //print_line("has mf "+itos(gui.mouse_focus!=NULL)); - gui.mouse_focus_button = p_event.mouse_button.button_index; + gui.mouse_focus = _gui_find_control(pos); + //print_line("has mf "+itos(gui.mouse_focus!=NULL)); + gui.mouse_focus_button = mb->get_button_index(); - if (!gui.mouse_focus) { - break; - } + if (!gui.mouse_focus) { + return; + } - if (p_event.mouse_button.button_index == BUTTON_LEFT) { - gui.drag_accum = Vector2(); - gui.drag_attempted = false; - } + if (mb->get_button_index() == BUTTON_LEFT) { + gui.drag_accum = Vector2(); + gui.drag_attempted = false; } + } + + mb = mb->xformed_by(Transform2D()); // make a copy of the event + + mb->set_global_position(pos); - p_event.mouse_button.global_x = pos.x; - p_event.mouse_button.global_y = pos.y; + pos = gui.focus_inv_xform.xform(pos); - pos = gui.focus_inv_xform.xform(pos); - p_event.mouse_button.x = pos.x; - p_event.mouse_button.y = pos.y; + mb->set_position(pos); #ifdef DEBUG_ENABLED - if (ScriptDebugger::get_singleton()) { + if (ScriptDebugger::get_singleton()) { - Array arr; - arr.push_back(gui.mouse_focus->get_path()); - arr.push_back(gui.mouse_focus->get_class()); - ScriptDebugger::get_singleton()->send_message("click_ctrl", arr); - } + Array arr; + arr.push_back(gui.mouse_focus->get_path()); + arr.push_back(gui.mouse_focus->get_class()); + ScriptDebugger::get_singleton()->send_message("click_ctrl", arr); + } /*if (bool(GLOBAL_DEF("debug/print_clicked_control",false))) { - print_line(String(gui.mouse_focus->get_path())+" - "+pos); - }*/ + print_line(String(gui.mouse_focus->get_path())+" - "+pos); + }*/ #endif - if (p_event.mouse_button.button_index == BUTTON_LEFT) { //assign focus - CanvasItem *ci = gui.mouse_focus; - while (ci) { + if (mb->get_button_index() == BUTTON_LEFT) { //assign focus + CanvasItem *ci = gui.mouse_focus; + while (ci) { - Control *control = ci->cast_to<Control>(); - if (control) { - if (control->get_focus_mode() != Control::FOCUS_NONE) { - if (control != gui.key_focus) { - control->grab_focus(); - } - break; + Control *control = ci->cast_to<Control>(); + if (control) { + if (control->get_focus_mode() != Control::FOCUS_NONE) { + if (control != gui.key_focus) { + control->grab_focus(); } - - if (control->data.mouse_filter == Control::MOUSE_FILTER_STOP) - break; + break; } - if (ci->is_set_as_toplevel()) + if (control->data.mouse_filter == Control::MOUSE_FILTER_STOP) break; - - ci = ci->get_parent_item(); } - } - if (gui.mouse_focus->can_process()) { - _gui_call_input(gui.mouse_focus, p_event); - } + if (ci->is_set_as_toplevel()) + break; - get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, "windows", "_cancel_input_ID", p_event.ID); - get_tree()->set_input_as_handled(); + ci = ci->get_parent_item(); + } + } - if (gui.drag_data.get_type() != Variant::NIL && p_event.mouse_button.button_index == BUTTON_LEFT) { + if (gui.mouse_focus->can_process()) { + _gui_call_input(gui.mouse_focus, mb); + } - //alternate drop use (when using force_drag(), as proposed by #5342 - if (gui.mouse_focus) { - _gui_drop(gui.mouse_focus, pos, false); - } + get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, "windows", "_cancel_input_ID", mb->get_id()); + get_tree()->set_input_as_handled(); - gui.drag_data = Variant(); + if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == BUTTON_LEFT) { - if (gui.drag_preview) { - memdelete(gui.drag_preview); - gui.drag_preview = NULL; - } - _propagate_viewport_notification(this, NOTIFICATION_DRAG_END); - //change mouse accordingly + //alternate drop use (when using force_drag(), as proposed by #5342 + if (gui.mouse_focus) { + _gui_drop(gui.mouse_focus, pos, false); } - _gui_cancel_tooltip(); - //gui.tooltip_popup->hide(); + gui.drag_data = Variant(); - } else { + if (gui.drag_preview) { + memdelete(gui.drag_preview); + gui.drag_preview = NULL; + } + _propagate_viewport_notification(this, NOTIFICATION_DRAG_END); + //change mouse accordingly + } - if (gui.drag_data.get_type() != Variant::NIL && p_event.mouse_button.button_index == BUTTON_LEFT) { + _gui_cancel_tooltip(); + //gui.tooltip_popup->hide(); - if (gui.mouse_over) { - Size2 pos = mpos; - pos = gui.focus_inv_xform.xform(pos); + } else { - _gui_drop(gui.mouse_over, pos, false); - } + if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == BUTTON_LEFT) { - if (gui.drag_preview && p_event.mouse_button.button_index == BUTTON_LEFT) { - memdelete(gui.drag_preview); - gui.drag_preview = NULL; - } + if (gui.mouse_over) { + Size2 pos = mpos; + pos = gui.focus_inv_xform.xform(pos); - gui.drag_data = Variant(); - _propagate_viewport_notification(this, NOTIFICATION_DRAG_END); - //change mouse accordingly + _gui_drop(gui.mouse_over, pos, false); } - if (!gui.mouse_focus) { - //release event is only sent if a mouse focus (previously pressed button) exists - break; + if (gui.drag_preview && mb->get_button_index() == BUTTON_LEFT) { + memdelete(gui.drag_preview); + gui.drag_preview = NULL; } - Size2 pos = mpos; - p_event.mouse_button.global_x = pos.x; - p_event.mouse_button.global_y = pos.y; - pos = gui.focus_inv_xform.xform(pos); - p_event.mouse_button.x = pos.x; - p_event.mouse_button.y = pos.y; + gui.drag_data = Variant(); + _propagate_viewport_notification(this, NOTIFICATION_DRAG_END); + //change mouse accordingly + } - if (gui.mouse_focus->can_process()) { - _gui_call_input(gui.mouse_focus, p_event); - } + if (!gui.mouse_focus) { + //release event is only sent if a mouse focus (previously pressed button) exists + return; + } - if (p_event.mouse_button.button_index == gui.mouse_focus_button) { - gui.mouse_focus = NULL; - gui.mouse_focus_button = -1; - } + Size2 pos = mpos; - /*if (gui.drag_data.get_type()!=Variant::NIL && p_event.mouse_button.button_index==BUTTON_LEFT) { - _propagate_viewport_notification(this,NOTIFICATION_DRAG_END); - gui.drag_data=Variant(); //always clear - }*/ + mb = mb->xformed_by(Transform2D()); //make a copy + mb->set_global_position(pos); + pos = gui.focus_inv_xform.xform(pos); + mb->set_position(pos); - get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, "windows", "_cancel_input_ID", p_event.ID); - get_tree()->set_input_as_handled(); + if (gui.mouse_focus->can_process()) { + _gui_call_input(gui.mouse_focus, mb); } - } break; - case InputEvent::MOUSE_MOTION: { - gui.key_event_accepted = false; - Point2 mpos = Point2(p_event.mouse_motion.x, p_event.mouse_motion.y); + if (mb->get_button_index() == gui.mouse_focus_button) { + gui.mouse_focus = NULL; + gui.mouse_focus_button = -1; + } + + /*if (gui.drag_data.get_type()!=Variant::NIL && mb->get_button_index()==BUTTON_LEFT) { + _propagate_viewport_notification(this,NOTIFICATION_DRAG_END); + gui.drag_data=Variant(); //always clear + }*/ + + get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, "windows", "_cancel_input_ID", mb->get_id()); + get_tree()->set_input_as_handled(); + } + } - gui.last_mouse_pos = mpos; + Ref<InputEventMouseMotion> mm = p_event; - Control *over = NULL; + if (mm.is_valid()) { - // D&D - if (!gui.drag_attempted && gui.mouse_focus && p_event.mouse_motion.button_mask & BUTTON_MASK_LEFT) { + gui.key_event_accepted = false; + Point2 mpos = mm->get_position(); - gui.drag_accum += Point2(p_event.mouse_motion.relative_x, p_event.mouse_motion.relative_y); - float len = gui.drag_accum.length(); - if (len > 10) { + gui.last_mouse_pos = mpos; - { //attempt grab, try parent controls too - CanvasItem *ci = gui.mouse_focus; - while (ci) { + Control *over = NULL; - Control *control = ci->cast_to<Control>(); - if (control) { + // D&D + if (!gui.drag_attempted && gui.mouse_focus && mm->get_button_mask() & BUTTON_MASK_LEFT) { - gui.drag_data = control->get_drag_data(control->get_global_transform_with_canvas().affine_inverse().xform(mpos) - gui.drag_accum); - if (gui.drag_data.get_type() != Variant::NIL) { + gui.drag_accum += mm->get_relative(); + float len = gui.drag_accum.length(); + if (len > 10) { - gui.mouse_focus = NULL; - } + { //attempt grab, try parent controls too + CanvasItem *ci = gui.mouse_focus; + while (ci) { + + Control *control = ci->cast_to<Control>(); + if (control) { + + gui.drag_data = control->get_drag_data(control->get_global_transform_with_canvas().affine_inverse().xform(mpos) - gui.drag_accum); + if (gui.drag_data.get_type() != Variant::NIL) { - if (control->data.mouse_filter == Control::MOUSE_FILTER_STOP) - break; + gui.mouse_focus = NULL; } - if (ci->is_set_as_toplevel()) + if (control->data.mouse_filter == Control::MOUSE_FILTER_STOP) break; - - ci = ci->get_parent_item(); } - } - gui.drag_attempted = true; - if (gui.drag_data.get_type() != Variant::NIL) { + if (ci->is_set_as_toplevel()) + break; - _propagate_viewport_notification(this, NOTIFICATION_DRAG_BEGIN); + ci = ci->get_parent_item(); } } + + gui.drag_attempted = true; + if (gui.drag_data.get_type() != Variant::NIL) { + + _propagate_viewport_notification(this, NOTIFICATION_DRAG_BEGIN); + } } + } - if (gui.mouse_focus) { - over = gui.mouse_focus; - //recompute focus_inv_xform again here + if (gui.mouse_focus) { + over = gui.mouse_focus; + //recompute focus_inv_xform again here - } else { + } else { + + over = _gui_find_control(mpos); + } - over = _gui_find_control(mpos); + if (gui.drag_data.get_type() == Variant::NIL && over && !gui.modal_stack.empty()) { + + Control *top = gui.modal_stack.back()->get(); + if (over != top && !top->is_a_parent_of(over)) { + over = NULL; //nothing can be found outside the modal stack } + } - if (gui.drag_data.get_type() == Variant::NIL && over && !gui.modal_stack.empty()) { + if (over != gui.mouse_over) { - Control *top = gui.modal_stack.back()->get(); - if (over != top && !top->is_a_parent_of(over)) { + if (gui.mouse_over) + gui.mouse_over->notification(Control::NOTIFICATION_MOUSE_EXIT); - break; // don't send motion event to anything below modal stack top - } - } + _gui_cancel_tooltip(); + + if (over) + over->notification(Control::NOTIFICATION_MOUSE_ENTER); + } + + gui.mouse_over = over; + + if (gui.drag_preview) { + gui.drag_preview->set_position(mpos); + } - if (over != gui.mouse_over) { + if (!over) { + OS::get_singleton()->set_cursor_shape(OS::CURSOR_ARROW); + return; + } - if (gui.mouse_over) - gui.mouse_over->notification(Control::NOTIFICATION_MOUSE_EXIT); + Transform2D localizer = over->get_global_transform_with_canvas().affine_inverse(); + Size2 pos = localizer.xform(mpos); + Vector2 speed = localizer.basis_xform(mm->get_speed()); + Vector2 rel = localizer.basis_xform(mm->get_relative()); - _gui_cancel_tooltip(); + mm = mm->xformed_by(Transform2D()); //make a copy - if (over) - over->notification(Control::NOTIFICATION_MOUSE_ENTER); - } + mm->set_global_position(mpos); + mm->set_speed(speed); + mm->set_relative(rel); + + if (mm->get_button_mask() == 0) { + //nothing pressed - gui.mouse_over = over; + bool can_tooltip = true; - if (gui.drag_preview) { - gui.drag_preview->set_pos(mpos); + if (!gui.modal_stack.empty()) { + if (gui.modal_stack.back()->get() != over && !gui.modal_stack.back()->get()->is_a_parent_of(over)) + can_tooltip = false; } - if (!over) { - OS::get_singleton()->set_cursor_shape(OS::CURSOR_ARROW); - break; + bool is_tooltip_shown = false; + + if (gui.tooltip_popup) { + if (can_tooltip) { + String tooltip = over->get_tooltip(gui.tooltip->get_global_transform().xform_inv(mpos)); + + if (tooltip.length() == 0) + _gui_cancel_tooltip(); + else if (tooltip == gui.tooltip_label->get_text()) + is_tooltip_shown = true; + } else + _gui_cancel_tooltip(); } - Transform2D localizer = over->get_global_transform_with_canvas().affine_inverse(); - Size2 pos = localizer.xform(mpos); - Vector2 speed = localizer.basis_xform(Point2(p_event.mouse_motion.speed_x, p_event.mouse_motion.speed_y)); - Vector2 rel = localizer.basis_xform(Point2(p_event.mouse_motion.relative_x, p_event.mouse_motion.relative_y)); + if (can_tooltip && !is_tooltip_shown) { - p_event.mouse_motion.global_x = mpos.x; - p_event.mouse_motion.global_y = mpos.y; - p_event.mouse_motion.speed_x = speed.x; - p_event.mouse_motion.speed_y = speed.y; - p_event.mouse_motion.relative_x = rel.x; - p_event.mouse_motion.relative_y = rel.y; + gui.tooltip = over; + gui.tooltip_pos = mpos; //(parent_xform * get_transform()).affine_inverse().xform(pos); + gui.tooltip_timer = gui.tooltip_delay; + } + } - if (p_event.mouse_motion.button_mask == 0) { - //nothing pressed + //pos = gui.focus_inv_xform.xform(pos); - bool can_tooltip = true; + mm->set_position(pos); - if (!gui.modal_stack.empty()) { - if (gui.modal_stack.back()->get() != over && !gui.modal_stack.back()->get()->is_a_parent_of(over)) - can_tooltip = false; - } + Control::CursorShape cursor_shape = over->get_cursor_shape(pos); + OS::get_singleton()->set_cursor_shape((OS::CursorShape)cursor_shape); - bool is_tooltip_shown = false; + if (over->can_process()) { + _gui_call_input(over, mm); + } - if (gui.tooltip_popup) { - if (can_tooltip) { - String tooltip = over->get_tooltip(gui.tooltip->get_global_transform().xform_inv(mpos)); + get_tree()->set_input_as_handled(); - if (tooltip.length() == 0) - _gui_cancel_tooltip(); - else if (tooltip == gui.tooltip_label->get_text()) - is_tooltip_shown = true; - } else - _gui_cancel_tooltip(); - } + if (gui.drag_data.get_type() != Variant::NIL && mm->get_button_mask() & BUTTON_MASK_LEFT) { - if (can_tooltip && !is_tooltip_shown) { + bool can_drop = _gui_drop(over, pos, true); - gui.tooltip = over; - gui.tooltip_pos = mpos; //(parent_xform * get_transform()).affine_inverse().xform(pos); - gui.tooltip_timer = gui.tooltip_delay; - } + if (!can_drop) { + OS::get_singleton()->set_cursor_shape(OS::CURSOR_FORBIDDEN); + } else { + OS::get_singleton()->set_cursor_shape(OS::CURSOR_CAN_DROP); } + //change mouse accordingly i guess + } + } - //pos = gui.focus_inv_xform.xform(pos); + Ref<InputEventScreenTouch> touch_event = p_event; + if (touch_event.is_valid()) { - p_event.mouse_motion.x = pos.x; - p_event.mouse_motion.y = pos.y; + Size2 pos = touch_event->get_position(); + if (touch_event->is_pressed()) { - Control::CursorShape cursor_shape = over->get_cursor_shape(pos); - OS::get_singleton()->set_cursor_shape((OS::CursorShape)cursor_shape); + Control *over = _gui_find_control(pos); + if (over) { - if (over->can_process()) { - _gui_call_input(over, p_event); + if (!gui.modal_stack.empty()) { + + Control *top = gui.modal_stack.back()->get(); + if (over != top && !top->is_a_parent_of(over)) { + + return; + } + } + if (over->can_process()) { + + touch_event = touch_event->xformed_by(Transform2D()); //make a copy + if (over == gui.mouse_focus) { + pos = gui.focus_inv_xform.xform(pos); + } else { + pos = over->get_global_transform_with_canvas().affine_inverse().xform(pos); + } + touch_event->set_position(pos); + _gui_call_input(over, touch_event); + } + get_tree()->set_input_as_handled(); + return; } + } else if (gui.mouse_focus) { + + if (gui.mouse_focus->can_process()) { + touch_event = touch_event->xformed_by(Transform2D()); //make a copy + touch_event->set_position(gui.focus_inv_xform.xform(pos)); + + _gui_call_input(gui.mouse_focus, touch_event); + } get_tree()->set_input_as_handled(); + return; + } + } + + Ref<InputEventScreenDrag> drag_event = p_event; + if (drag_event.is_valid()) { - if (gui.drag_data.get_type() != Variant::NIL && p_event.mouse_motion.button_mask & BUTTON_MASK_LEFT) { + Control *over = gui.mouse_focus; + if (!over) { + over = _gui_find_control(drag_event->get_position()); + } + if (over) { + + if (!gui.modal_stack.empty()) { - bool can_drop = _gui_drop(over, pos, true); + Control *top = gui.modal_stack.back()->get(); + if (over != top && !top->is_a_parent_of(over)) { - if (!can_drop) { - OS::get_singleton()->set_cursor_shape(OS::CURSOR_FORBIDDEN); - } else { - OS::get_singleton()->set_cursor_shape(OS::CURSOR_CAN_DROP); + return; } - //change mouse accordingly i guess } + if (over->can_process()) { - } break; - case InputEvent::ACTION: - case InputEvent::JOYPAD_BUTTON: - case InputEvent::JOYPAD_MOTION: - case InputEvent::KEY: { + Transform2D localizer = over->get_global_transform_with_canvas().affine_inverse(); + Size2 pos = localizer.xform(drag_event->get_position()); + Vector2 speed = localizer.basis_xform(drag_event->get_speed()); + Vector2 rel = localizer.basis_xform(drag_event->get_relative()); + + drag_event = drag_event->xformed_by(Transform2D()); //make a copy - if (gui.key_focus && !gui.key_focus->is_visible_in_tree()) { - gui.key_focus->release_focus(); + drag_event->set_speed(speed); + drag_event->set_relative(rel); + drag_event->set_position(pos); + + _gui_call_input(over, drag_event); } - if (gui.key_focus) { + get_tree()->set_input_as_handled(); + return; + } + } + + if (mm.is_null() && mb.is_null() && p_event->is_action_type()) { - gui.key_event_accepted = false; - if (gui.key_focus->can_process()) { - gui.key_focus->call_multilevel(SceneStringNames::get_singleton()->_gui_input, p_event); - if (gui.key_focus) //maybe lost it - gui.key_focus->emit_signal(SceneStringNames::get_singleton()->gui_input, p_event); - } + if (gui.key_focus && !gui.key_focus->is_visible_in_tree()) { + gui.key_focus->release_focus(); + } - if (gui.key_event_accepted) { + if (gui.key_focus) { - get_tree()->set_input_as_handled(); - break; - } + gui.key_event_accepted = false; + if (gui.key_focus->can_process()) { + gui.key_focus->call_multilevel(SceneStringNames::get_singleton()->_gui_input, p_event); + if (gui.key_focus) //maybe lost it + gui.key_focus->emit_signal(SceneStringNames::get_singleton()->gui_input, p_event); } - if (p_event.is_pressed() && p_event.is_action("ui_cancel") && !gui.modal_stack.empty()) { + if (gui.key_event_accepted) { - _gui_sort_modal_stack(); - Control *top = gui.modal_stack.back()->get(); - if (!top->data.modal_exclusive) { + get_tree()->set_input_as_handled(); + return; + } + } - top->notification(Control::NOTIFICATION_MODAL_CLOSE); - top->_modal_stack_remove(); - top->hide(); - } + if (p_event->is_pressed() && p_event->is_action("ui_cancel") && !gui.modal_stack.empty()) { + + _gui_sort_modal_stack(); + Control *top = gui.modal_stack.back()->get(); + if (!top->data.modal_exclusive) { + + top->notification(Control::NOTIFICATION_MODAL_CLOSE); + top->_modal_stack_remove(); + top->hide(); } + } - Control *from = gui.key_focus ? gui.key_focus : NULL; //hmm + Control *from = gui.key_focus ? gui.key_focus : NULL; //hmm - //keyboard focus - //if (from && p_event.key.pressed && !p_event.key.mod.alt && !p_event.key.mod.meta && !p_event.key.mod.command) { + //keyboard focus + //if (from && p_event->is_pressed() && !p_event->get_alt() && !p_event->get_metakey() && !p_event->key->get_command()) { - if (from && p_event.is_pressed()) { - Control *next = NULL; + Ref<InputEventKey> k = p_event; + //need to check for mods, otherwise any combination of alt/ctrl/shift+<up/down/left/righ/etc> is handled here when it shouldn't be. + bool mods = k.is_valid() && (k->get_control() || k->get_alt() || k->get_shift() || k->get_metakey()); - if (p_event.is_action("ui_focus_next")) { + if (from && p_event->is_pressed()) { + Control *next = NULL; - next = from->find_next_valid_focus(); - } + if (p_event->is_action("ui_focus_next")) { - if (p_event.is_action("ui_focus_prev")) { + next = from->find_next_valid_focus(); + } - next = from->find_prev_valid_focus(); - } + if (p_event->is_action("ui_focus_prev")) { - if (p_event.is_action("ui_up")) { + next = from->find_prev_valid_focus(); + } - next = from->_get_focus_neighbour(MARGIN_TOP); - } + if (!mods && p_event->is_action("ui_up")) { - if (p_event.is_action("ui_left")) { + next = from->_get_focus_neighbour(MARGIN_TOP); + } - next = from->_get_focus_neighbour(MARGIN_LEFT); - } + if (!mods && p_event->is_action("ui_left")) { - if (p_event.is_action("ui_right")) { + next = from->_get_focus_neighbour(MARGIN_LEFT); + } - next = from->_get_focus_neighbour(MARGIN_RIGHT); - } + if (!mods && p_event->is_action("ui_right")) { - if (p_event.is_action("ui_down")) { + next = from->_get_focus_neighbour(MARGIN_RIGHT); + } - next = from->_get_focus_neighbour(MARGIN_BOTTOM); - } + if (!mods && p_event->is_action("ui_down")) { - if (next) { - next->grab_focus(); - get_tree()->set_input_as_handled(); - } + next = from->_get_focus_neighbour(MARGIN_BOTTOM); } - } break; + if (next) { + next->grab_focus(); + get_tree()->set_input_as_handled(); + } + } } } @@ -2236,7 +2274,7 @@ void Viewport::_gui_set_drag_preview(Control *p_base, Control *p_control) { memdelete(gui.drag_preview); } p_control->set_as_toplevel(true); - p_control->set_pos(gui.last_mouse_pos); + p_control->set_position(gui.last_mouse_pos); p_base->get_root_parent_control()->add_child(p_control); //add as child of viewport p_control->raise(); if (gui.drag_preview) { @@ -2347,7 +2385,7 @@ List<Control *>::Element *Viewport::_gui_show_modal(Control *p_control) { gui.modal_stack.push_back(p_control); if (gui.key_focus) - p_control->_modal_set_prev_focus_owner(gui.key_focus->get_instance_ID()); + p_control->_modal_set_prev_focus_owner(gui.key_focus->get_instance_id()); else p_control->_modal_set_prev_focus_owner(0); @@ -2365,33 +2403,30 @@ void Viewport::_gui_grab_click_focus(Control *p_control) { if (gui.mouse_focus == p_control) return; - InputEvent ie; - ie.type = InputEvent::MOUSE_BUTTON; - InputEventMouseButton &mb = ie.mouse_button; + Ref<InputEventMouseButton> mb; + mb.instance(); //send unclic Point2 click = gui.mouse_focus->get_global_transform_with_canvas().affine_inverse().xform(gui.last_mouse_pos); - mb.x = click.x; - mb.y = click.y; - mb.button_index = gui.mouse_focus_button; - mb.pressed = false; - gui.mouse_focus->call_deferred(SceneStringNames::get_singleton()->_gui_input, ie); + mb->set_position(click); + mb->set_button_index(gui.mouse_focus_button); + mb->set_pressed(false); + gui.mouse_focus->call_deferred(SceneStringNames::get_singleton()->_gui_input, mb); gui.mouse_focus = p_control; gui.focus_inv_xform = gui.mouse_focus->get_global_transform_with_canvas().affine_inverse(); click = gui.mouse_focus->get_global_transform_with_canvas().affine_inverse().xform(gui.last_mouse_pos); - mb.x = click.x; - mb.y = click.y; - mb.button_index = gui.mouse_focus_button; - mb.pressed = true; - gui.mouse_focus->call_deferred(SceneStringNames::get_singleton()->_gui_input, ie); + mb->set_position(click); + mb->set_button_index(gui.mouse_focus_button); + mb->set_pressed(true); + gui.mouse_focus->call_deferred(SceneStringNames::get_singleton()->_gui_input, mb); } } /////////////////////////////// -void Viewport::input(const InputEvent &p_event) { +void Viewport::input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(!is_inside_tree()); @@ -2400,20 +2435,20 @@ void Viewport::input(const InputEvent &p_event) { //get_tree()->call_group(SceneTree::GROUP_CALL_REVERSE|SceneTree::GROUP_CALL_REALTIME|SceneTree::GROUP_CALL_MULIILEVEL,gui_input_group,"_gui_input",p_event); //special one for GUI, as controls use their own process check } -void Viewport::unhandled_input(const InputEvent &p_event) { +void Viewport::unhandled_input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(!is_inside_tree()); get_tree()->_call_input_pause(unhandled_input_group, "_unhandled_input", p_event); //call_group(GROUP_CALL_REVERSE|GROUP_CALL_REALTIME|GROUP_CALL_MULIILEVEL,"unhandled_input","_unhandled_input",ev); - if (!get_tree()->input_handled && p_event.type == InputEvent::KEY) { + if (!get_tree()->input_handled && p_event->cast_to<InputEventKey>() != NULL) { get_tree()->_call_input_pause(unhandled_key_input_group, "_unhandled_key_input", p_event); //call_group(GROUP_CALL_REVERSE|GROUP_CALL_REALTIME|GROUP_CALL_MULIILEVEL,"unhandled_key_input","_unhandled_key_input",ev); } if (physics_object_picking && !get_tree()->input_handled) { - if (p_event.type == InputEvent::MOUSE_BUTTON || p_event.type == InputEvent::MOUSE_MOTION || p_event.type == InputEvent::SCREEN_DRAG || p_event.type == InputEvent::SCREEN_TOUCH) { + if (Input::get_singleton()->get_mouse_mode() != Input::MOUSE_MODE_CAPTURED && (p_event->cast_to<InputEventMouseButton>() || p_event->cast_to<InputEventMouseMotion>() || p_event->cast_to<InputEventScreenDrag>() || p_event->cast_to<InputEventScreenTouch>())) { physics_picking_events.push_back(p_event); } } @@ -2572,16 +2607,45 @@ bool Viewport::get_hdr() const { return hdr; } +void Viewport::set_usage(Usage p_usage) { + + usage = p_usage; + VS::get_singleton()->viewport_set_usage(viewport, VS::ViewportUsage(p_usage)); +} + +Viewport::Usage Viewport::get_usage() const { + return usage; +} + +void Viewport::set_debug_draw(DebugDraw p_debug_draw) { + + debug_draw = p_debug_draw; + VS::get_singleton()->viewport_set_debug_draw(viewport, VS::ViewportDebugDraw(p_debug_draw)); +} + +Viewport::DebugDraw Viewport::get_debug_draw() const { + + return debug_draw; +} + +int Viewport::get_render_info(RenderInfo p_info) { + + return VS::get_singleton()->viewport_get_render_info(viewport, VS::ViewportRenderInfo(p_info)); +} + void Viewport::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_use_arvr", "use"), &Viewport::set_use_arvr); + ClassDB::bind_method(D_METHOD("use_arvr"), &Viewport::use_arvr); + ClassDB::bind_method(D_METHOD("set_size", "size"), &Viewport::set_size); ClassDB::bind_method(D_METHOD("get_size"), &Viewport::get_size); - ClassDB::bind_method(D_METHOD("set_world_2d", "world_2d:World2D"), &Viewport::set_world_2d); - ClassDB::bind_method(D_METHOD("get_world_2d:World2D"), &Viewport::get_world_2d); - ClassDB::bind_method(D_METHOD("find_world_2d:World2D"), &Viewport::find_world_2d); - ClassDB::bind_method(D_METHOD("set_world", "world:World"), &Viewport::set_world); - ClassDB::bind_method(D_METHOD("get_world:World"), &Viewport::get_world); - ClassDB::bind_method(D_METHOD("find_world:World"), &Viewport::find_world); + ClassDB::bind_method(D_METHOD("set_world_2d", "world_2d"), &Viewport::set_world_2d); + ClassDB::bind_method(D_METHOD("get_world_2d"), &Viewport::get_world_2d); + ClassDB::bind_method(D_METHOD("find_world_2d"), &Viewport::find_world_2d); + ClassDB::bind_method(D_METHOD("set_world", "world"), &Viewport::set_world); + ClassDB::bind_method(D_METHOD("get_world"), &Viewport::get_world); + ClassDB::bind_method(D_METHOD("find_world"), &Viewport::find_world); ClassDB::bind_method(D_METHOD("set_canvas_transform", "xform"), &Viewport::set_canvas_transform); ClassDB::bind_method(D_METHOD("get_canvas_transform"), &Viewport::get_canvas_transform); @@ -2606,8 +2670,6 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("is_size_override_enabled"), &Viewport::is_size_override_enabled); ClassDB::bind_method(D_METHOD("set_size_override_stretch", "enabled"), &Viewport::set_size_override_stretch); ClassDB::bind_method(D_METHOD("is_size_override_stretch_enabled"), &Viewport::is_size_override_stretch_enabled); - ClassDB::bind_method(D_METHOD("queue_screen_capture"), &Viewport::queue_screen_capture); - ClassDB::bind_method(D_METHOD("get_screen_capture"), &Viewport::get_screen_capture); ClassDB::bind_method(D_METHOD("set_vflip", "enable"), &Viewport::set_vflip); ClassDB::bind_method(D_METHOD("get_vflip"), &Viewport::get_vflip); @@ -2625,7 +2687,15 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("set_hdr", "enable"), &Viewport::set_hdr); ClassDB::bind_method(D_METHOD("get_hdr"), &Viewport::get_hdr); - ClassDB::bind_method(D_METHOD("get_texture:ViewportTexture"), &Viewport::get_texture); + ClassDB::bind_method(D_METHOD("set_usage", "usage"), &Viewport::set_usage); + ClassDB::bind_method(D_METHOD("get_usage"), &Viewport::get_usage); + + ClassDB::bind_method(D_METHOD("set_debug_draw", "debug_draw"), &Viewport::set_debug_draw); + ClassDB::bind_method(D_METHOD("get_debug_draw"), &Viewport::get_debug_draw); + + ClassDB::bind_method(D_METHOD("get_render_info", "info"), &Viewport::get_render_info); + + ClassDB::bind_method(D_METHOD("get_texture"), &Viewport::get_texture); ClassDB::bind_method(D_METHOD("set_physics_object_picking", "enable"), &Viewport::set_physics_object_picking); ClassDB::bind_method(D_METHOD("get_physics_object_picking"), &Viewport::get_physics_object_picking); @@ -2639,20 +2709,20 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("set_use_own_world", "enable"), &Viewport::set_use_own_world); ClassDB::bind_method(D_METHOD("is_using_own_world"), &Viewport::is_using_own_world); - ClassDB::bind_method(D_METHOD("get_camera:Camera"), &Viewport::get_camera); + ClassDB::bind_method(D_METHOD("get_camera"), &Viewport::get_camera); ClassDB::bind_method(D_METHOD("set_as_audio_listener", "enable"), &Viewport::set_as_audio_listener); - ClassDB::bind_method(D_METHOD("is_audio_listener", "enable"), &Viewport::is_audio_listener); + ClassDB::bind_method(D_METHOD("is_audio_listener"), &Viewport::is_audio_listener); ClassDB::bind_method(D_METHOD("set_as_audio_listener_2d", "enable"), &Viewport::set_as_audio_listener_2d); - ClassDB::bind_method(D_METHOD("is_audio_listener_2d", "enable"), &Viewport::is_audio_listener_2d); + ClassDB::bind_method(D_METHOD("is_audio_listener_2d"), &Viewport::is_audio_listener_2d); ClassDB::bind_method(D_METHOD("set_attach_to_screen_rect", "rect"), &Viewport::set_attach_to_screen_rect); - ClassDB::bind_method(D_METHOD("get_mouse_pos"), &Viewport::get_mouse_pos); + ClassDB::bind_method(D_METHOD("get_mouse_position"), &Viewport::get_mouse_position); ClassDB::bind_method(D_METHOD("warp_mouse", "to_pos"), &Viewport::warp_mouse); ClassDB::bind_method(D_METHOD("gui_has_modal_stack"), &Viewport::gui_has_modal_stack); - ClassDB::bind_method(D_METHOD("gui_get_drag_data:Variant"), &Viewport::gui_get_drag_data); + ClassDB::bind_method(D_METHOD("gui_get_drag_data"), &Viewport::gui_get_drag_data); ClassDB::bind_method(D_METHOD("set_disable_input", "disable"), &Viewport::set_disable_input); ClassDB::bind_method(D_METHOD("is_input_disabled"), &Viewport::is_input_disabled); @@ -2669,6 +2739,8 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shadow_atlas_quadrant_subdiv", "quadrant", "subdiv"), &Viewport::set_shadow_atlas_quadrant_subdiv); ClassDB::bind_method(D_METHOD("get_shadow_atlas_quadrant_subdiv", "quadrant"), &Viewport::get_shadow_atlas_quadrant_subdiv); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "arvr"), "set_use_arvr", "use_arvr"); + ADD_PROPERTY(PropertyInfo(Variant::RECT2, "size"), "set_size", "get_size"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "own_world"), "set_use_own_world", "is_using_own_world"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world", PROPERTY_HINT_RESOURCE_TYPE, "World"), "set_world", "get_world"); @@ -2678,6 +2750,8 @@ void Viewport::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x"), "set_msaa", "get_msaa"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hdr"), "set_hdr", "get_hdr"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_3d"), "set_disable_3d", "is_3d_disabled"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "usage", PROPERTY_HINT_ENUM, "2D,2D No-Sampling,3D,3D No-Effects"), "set_usage", "get_usage"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "debug_draw", PROPERTY_HINT_ENUM, "Disabled,Unshaded,Overdraw,Wireframe"), "set_debug_draw", "get_debug_draw"); ADD_GROUP("Render Target", "render_target_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "render_target_v_flip"), "set_vflip", "get_vflip"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "render_target_clear_on_new_frame"), "set_clear_on_new_frame", "get_clear_on_new_frame"); @@ -2712,6 +2786,19 @@ void Viewport::_bind_methods() { BIND_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_1024); BIND_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_MAX); + BIND_CONSTANT(RENDER_INFO_OBJECTS_IN_FRAME); + BIND_CONSTANT(RENDER_INFO_VERTICES_IN_FRAME); + BIND_CONSTANT(RENDER_INFO_MATERIAL_CHANGES_IN_FRAME); + BIND_CONSTANT(RENDER_INFO_SHADER_CHANGES_IN_FRAME); + BIND_CONSTANT(RENDER_INFO_SURFACE_CHANGES_IN_FRAME); + BIND_CONSTANT(RENDER_INFO_DRAW_CALLS_IN_FRAME); + BIND_CONSTANT(RENDER_INFO_MAX); + + BIND_CONSTANT(DEBUG_DRAW_DISABLED); + BIND_CONSTANT(DEBUG_DRAW_UNSHADED); + BIND_CONSTANT(DEBUG_DRAW_OVERDRAW); + BIND_CONSTANT(DEBUG_DRAW_WIREFRAME); + BIND_CONSTANT(MSAA_DISABLED); BIND_CONSTANT(MSAA_2X); BIND_CONSTANT(MSAA_4X); @@ -2739,6 +2826,7 @@ Viewport::Viewport() { parent = NULL; listener = NULL; camera = NULL; + arvr = false; size_override = false; size_override_stretch = false; size_override_size = Size2(1, 1); @@ -2763,7 +2851,7 @@ Viewport::Viewport() { set_shadow_atlas_quadrant_subdiv(2, SHADOW_ATLAS_QUADRANT_SUBDIV_16); set_shadow_atlas_quadrant_subdiv(3, SHADOW_ATLAS_QUADRANT_SUBDIV_64); - String id = itos(get_instance_ID()); + String id = itos(get_instance_id()); input_group = "_vp_input" + id; gui_input_group = "_vp_gui_input" + id; unhandled_input_group = "_vp_unhandled_input" + id; @@ -2786,6 +2874,9 @@ Viewport::Viewport() { msaa = MSAA_DISABLED; hdr = false; + + usage = USAGE_3D; + debug_draw = DEBUG_DRAW_DISABLED; } Viewport::~Viewport() { diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 3fc781c62..83c989db5 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -76,6 +77,8 @@ public: virtual void set_flags(uint32_t p_flags); virtual uint32_t get_flags() const; + virtual Ref<Image> get_data() const; + ViewportTexture(); ~ViewportTexture(); }; @@ -112,6 +115,31 @@ public: MSAA_16X, }; + enum Usage { + USAGE_2D, + USAGE_2D_NO_SAMPLING, + USAGE_3D, + USAGE_3D_NO_EFFECTS, + }; + + enum RenderInfo { + + RENDER_INFO_OBJECTS_IN_FRAME, + RENDER_INFO_VERTICES_IN_FRAME, + RENDER_INFO_MATERIAL_CHANGES_IN_FRAME, + RENDER_INFO_SHADER_CHANGES_IN_FRAME, + RENDER_INFO_SURFACE_CHANGES_IN_FRAME, + RENDER_INFO_DRAW_CALLS_IN_FRAME, + RENDER_INFO_MAX + }; + + enum DebugDraw { + DEBUG_DRAW_DISABLED, + DEBUG_DRAW_UNSHADED, + DEBUG_DRAW_OVERDRAW, + DEBUG_DRAW_WIREFRAME, + }; + private: friend class ViewportTexture; @@ -120,6 +148,8 @@ private: Listener *listener; Set<Listener *> listeners; + bool arvr; + Camera *camera; Set<Camera *> cameras; @@ -157,7 +187,7 @@ private: bool gen_mipmaps; bool physics_object_picking; - List<InputEvent> physics_picking_events; + List<Ref<InputEvent> > physics_picking_events; ObjectID physics_object_capture; ObjectID physics_object_over; Vector2 physics_last_mousepos; @@ -194,6 +224,10 @@ private: RID texture_rid; uint32_t texture_flags; + DebugDraw debug_draw; + + Usage usage; + int shadow_atlas_size; ShadowAtlasQuadrantSubdiv shadow_atlas_quadrant_subdiv[4]; @@ -236,14 +270,14 @@ private: bool disable_input; - void _gui_call_input(Control *p_control, const InputEvent &p_input); + void _gui_call_input(Control *p_control, const Ref<InputEvent> &p_input); void _gui_sort_subwindows(); void _gui_sort_roots(); void _gui_sort_modal_stack(); Control *_gui_find_control(const Point2 &p_global); Control *_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_global, const Transform2D &p_xform, Transform2D &r_inv_xform); - void _gui_input_event(InputEvent p_event); + void _gui_input_event(Ref<InputEvent> p_event); void update_worlds(); @@ -252,10 +286,10 @@ private: void _vp_enter_tree(); void _vp_exit_tree(); - void _vp_input(const InputEvent &p_ev); + void _vp_input(const Ref<InputEvent> &p_ev); void _vp_input_text(const String &p_text); - void _vp_unhandled_input(const InputEvent &p_ev); - void _make_input_local(InputEvent &ev); + void _vp_unhandled_input(const Ref<InputEvent> &p_ev); + Ref<InputEvent> _make_input_local(const Ref<InputEvent> &ev); friend class Control; @@ -317,6 +351,9 @@ public: Listener *get_listener() const; Camera *get_camera() const; + void set_use_arvr(bool p_use_arvr); + bool use_arvr(); + void set_as_audio_listener(bool p_enable); bool is_audio_listener() const; @@ -381,14 +418,11 @@ public: Vector2 get_camera_coords(const Vector2 &p_viewport_coords) const; Vector2 get_camera_rect_size() const; - void queue_screen_capture(); - Image get_screen_capture() const; - void set_use_own_world(bool p_world); bool is_using_own_world() const; - void input(const InputEvent &p_event); - void unhandled_input(const InputEvent &p_event); + void input(const Ref<InputEvent> &p_event); + void unhandled_input(const Ref<InputEvent> &p_event); void set_disable_input(bool p_disable); bool is_input_disabled() const; @@ -399,7 +433,7 @@ public: void set_attach_to_screen_rect(const Rect2 &p_rect); Rect2 get_attach_to_screen_rect() const; - Vector2 get_mouse_pos() const; + Vector2 get_mouse_position() const; void warp_mouse(const Vector2 &p_pos); void set_physics_object_picking(bool p_enable); @@ -415,6 +449,14 @@ public: virtual String get_configuration_warning() const; + void set_usage(Usage p_usage); + Usage get_usage() const; + + void set_debug_draw(DebugDraw p_debug_draw); + DebugDraw get_debug_draw() const; + + int get_render_info(RenderInfo p_info); + Viewport(); ~Viewport(); }; @@ -422,5 +464,8 @@ public: VARIANT_ENUM_CAST(Viewport::UpdateMode); VARIANT_ENUM_CAST(Viewport::ShadowAtlasQuadrantSubdiv); VARIANT_ENUM_CAST(Viewport::MSAA); +VARIANT_ENUM_CAST(Viewport::Usage); +VARIANT_ENUM_CAST(Viewport::DebugDraw); +VARIANT_ENUM_CAST(Viewport::RenderInfo); #endif diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 06dae328f..3e6d80d31 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -27,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "register_scene_types.h" -#include "global_config.h" #include "os/os.h" +#include "project_settings.h" #include "scene/io/resource_format_image.h" #include "scene/io/resource_format_wav.h" @@ -41,7 +42,7 @@ #include "scene/2d/path_2d.h" #include "scene/gui/box_container.h" #include "scene/gui/button.h" -#include "scene/gui/button_array.h" + #include "scene/gui/button_group.h" #include "scene/gui/center_container.h" #include "scene/gui/check_box.h" @@ -73,7 +74,6 @@ #include "scene/gui/separator.h" #include "scene/gui/slider.h" #include "scene/gui/spin_box.h" -#include "scene/gui/spin_box.h" #include "scene/gui/split_container.h" #include "scene/gui/tab_container.h" #include "scene/gui/tabs.h" @@ -111,6 +111,7 @@ #include "scene/2d/ray_cast_2d.h" //#include "scene/2d/sound_player_2d.h" //#include "scene/2d/sample_player_2d.h" +#include "scene/2d/audio_stream_player_2d.h" #include "scene/2d/canvas_modulate.h" #include "scene/2d/navigation2d.h" #include "scene/2d/remote_transform_2d.h" @@ -128,8 +129,7 @@ #include "scene/animation/animation_tree_player.h" #include "scene/animation/tween.h" #include "scene/main/resource_preloader.h" -#include "scene/main/scene_main_loop.h" -#include "scene/main/scene_main_loop.h" +#include "scene/main/scene_tree.h" #include "scene/resources/packed_scene.h" #include "scene/resources/mesh_data_tool.h" @@ -164,13 +164,15 @@ #include "scene/resources/polygon_path_finder.h" //#include "scene/resources/sample.h" -//#include "scene/audio/sample_player.h" +#include "scene/3d/audio_stream_player_3d.h" #include "scene/resources/material.h" #include "scene/resources/mesh.h" #include "scene/resources/room.h" #include "scene/resources/sky_box.h" #include "scene/resources/texture.h" +#include "scene/resources/primitive_meshes.h" + #include "scene/resources/shader_graph.h" #include "scene/resources/world.h" @@ -197,6 +199,8 @@ #include "scene/3d/camera.h" #include "scene/3d/listener.h" +#include "scene/3d/arvr_nodes.h" + #include "scene/3d/gi_probe.h" #include "scene/3d/interpolated_camera.h" #include "scene/3d/light.h" @@ -205,14 +209,12 @@ #include "scene/3d/physics_body.h" #include "scene/3d/portal.h" #include "scene/3d/position_3d.h" -#include "scene/3d/quad.h" #include "scene/3d/reflection_probe.h" -#include "scene/3d/test_cube.h" #include "scene/resources/environment.h" #include "scene/3d/area.h" -#include "scene/3d/baked_light_instance.h" -#include "scene/3d/body_shape.h" + +#include "scene/3d/collision_shape.h" #include "scene/3d/immediate_geometry.h" #include "scene/3d/multimesh_instance.h" #include "scene/3d/physics_joint.h" @@ -271,11 +273,11 @@ void register_scene_types() { ResourceLoader::add_resource_format_loader(resource_loader_theme); bool default_theme_hidpi = GLOBAL_DEF("gui/theme/use_hidpi", false); - GlobalConfig::get_singleton()->set_custom_property_info("gui/theme/use_hidpi", PropertyInfo(Variant::BOOL, "gui/theme/use_hidpi", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); + ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/use_hidpi", PropertyInfo(Variant::BOOL, "gui/theme/use_hidpi", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); String theme_path = GLOBAL_DEF("gui/theme/custom", ""); - GlobalConfig::get_singleton()->set_custom_property_info("gui/theme/custom", PropertyInfo(Variant::STRING, "gui/theme/custom", PROPERTY_HINT_FILE, "*.tres,*.res", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); + ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom", PropertyInfo(Variant::STRING, "gui/theme/custom", PROPERTY_HINT_FILE, "*.tres,*.res", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); String font_path = GLOBAL_DEF("gui/theme/custom_font", ""); - GlobalConfig::get_singleton()->set_custom_property_info("gui/theme/custom_font", PropertyInfo(Variant::STRING, "gui/theme/custom_font", PROPERTY_HINT_FILE, "*.tres,*.res,*.fnt", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); + ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom_font", PropertyInfo(Variant::STRING, "gui/theme/custom_font", PROPERTY_HINT_FILE, "*.tres,*.res,*.font", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); if (theme_path != String()) { Ref<Theme> theme = ResourceLoader::load(theme_path); @@ -359,9 +361,6 @@ void register_scene_types() { OS::get_singleton()->yield(); //may take time to init - ClassDB::register_virtual_class<ButtonArray>(); - ClassDB::register_class<HButtonArray>(); - ClassDB::register_class<VButtonArray>(); ClassDB::register_class<TextureProgress>(); ClassDB::register_class<ItemList>(); @@ -408,8 +407,11 @@ void register_scene_types() { ClassDB::register_virtual_class<VisualInstance>(); ClassDB::register_class<Camera>(); ClassDB::register_class<Listener>(); + ClassDB::register_class<ARVRCamera>(); + ClassDB::register_class<ARVRController>(); + ClassDB::register_class<ARVRAnchor>(); + ClassDB::register_class<ARVROrigin>(); ClassDB::register_class<InterpolatedCamera>(); - ClassDB::register_class<TestCube>(); ClassDB::register_class<MeshInstance>(); ClassDB::register_class<ImmediateGeometry>(); ClassDB::register_class<Sprite3D>(); @@ -423,9 +425,8 @@ void register_scene_types() { ClassDB::register_class<GIProbeData>(); ClassDB::register_class<AnimationTreePlayer>(); ClassDB::register_class<Portal>(); - //ClassDB::register_type<Particles>(); + ClassDB::register_class<Particles>(); ClassDB::register_class<Position3D>(); - ClassDB::register_class<Quad>(); ClassDB::register_class<NavigationMeshInstance>(); ClassDB::register_class<NavigationMesh>(); ClassDB::register_class<Navigation>(); @@ -451,7 +452,7 @@ void register_scene_types() { ClassDB::register_class<PathFollow>(); ClassDB::register_class<VisibilityNotifier>(); ClassDB::register_class<VisibilityEnabler>(); - ClassDB::register_class<BakedLight>(); + // ClassDB::register_class<BakedLight>(); //ClassDB::register_type<BakedLightSampler>(); ClassDB::register_class<WorldEnvironment>(); ClassDB::register_class<RemoteTransform>(); @@ -471,11 +472,15 @@ void register_scene_types() { ClassDB::register_class<MeshLibrary>(); AcceptDialog::set_swap_ok_cancel(GLOBAL_DEF("gui/common/swap_ok_cancel", bool(OS::get_singleton()->get_swap_ok_cancel()))); - ClassDB::register_class<CanvasItemMaterial>(); + ClassDB::register_class<Shader>(); + ClassDB::register_class<ShaderMaterial>(); ClassDB::register_virtual_class<CanvasItem>(); + ClassDB::register_class<CanvasItemMaterial>(); + SceneTree::add_idle_callback(CanvasItemMaterial::flush_changes); + CanvasItemMaterial::init_shaders(); ClassDB::register_class<Node2D>(); ClassDB::register_class<Particles2D>(); - ClassDB::register_class<ParticleAttractor2D>(); + //ClassDB::register_class<ParticleAttractor2D>(); ClassDB::register_class<Sprite>(); //ClassDB::register_type<ViewportSprite>(); ClassDB::register_class<SpriteFrames>(); @@ -519,21 +524,29 @@ void register_scene_types() { /* REGISTER RESOURCES */ ClassDB::register_virtual_class<Shader>(); - //ClassDB::register_virtual_type<ShaderGraph>(); - ClassDB::register_class<CanvasItemShader>(); -//ClassDB::register_type<CanvasItemShaderGraph>(); #ifndef _3D_DISABLED - ClassDB::register_class<Mesh>(); + ClassDB::register_virtual_class<Mesh>(); + ClassDB::register_class<ArrayMesh>(); + ClassDB::register_virtual_class<PrimitiveMesh>(); + ClassDB::register_class<CapsuleMesh>(); + ClassDB::register_class<CubeMesh>(); + ClassDB::register_class<CylinderMesh>(); + ClassDB::register_class<PlaneMesh>(); + ClassDB::register_class<PrismMesh>(); + ClassDB::register_class<QuadMesh>(); + ClassDB::register_class<SphereMesh>(); ClassDB::register_virtual_class<Material>(); - ClassDB::register_class<FixedSpatialMaterial>(); - SceneTree::add_idle_callback(FixedSpatialMaterial::flush_changes); - FixedSpatialMaterial::init_shaders(); + ClassDB::register_class<SpatialMaterial>(); + SceneTree::add_idle_callback(SpatialMaterial::flush_changes); + SpatialMaterial::init_shaders(); + + ClassDB::register_class<ParticlesMaterial>(); + SceneTree::add_idle_callback(ParticlesMaterial::flush_changes); + ParticlesMaterial::init_shaders(); + //ClassDB::register_type<ShaderMaterial>(); ClassDB::register_class<RoomBounds>(); - //ClassDB::register_type<MaterialShaderGraph>(); - ClassDB::register_class<SpatialShader>(); - ClassDB::register_class<ParticlesShader>(); ClassDB::register_class<MultiMesh>(); ClassDB::register_class<MeshLibrary>(); @@ -553,21 +566,26 @@ void register_scene_types() { OS::get_singleton()->yield(); //may take time to init + ClassDB::register_class<SpatialVelocityTracker>(); #endif ClassDB::register_class<World>(); ClassDB::register_class<Environment>(); ClassDB::register_class<World2D>(); ClassDB::register_virtual_class<Texture>(); - ClassDB::register_virtual_class<SkyBox>(); - ClassDB::register_class<ImageSkyBox>(); + ClassDB::register_virtual_class<Sky>(); + ClassDB::register_class<PanoramaSky>(); + ClassDB::register_class<ProceduralSky>(); ClassDB::register_class<StreamTexture>(); ClassDB::register_class<ImageTexture>(); ClassDB::register_class<AtlasTexture>(); ClassDB::register_class<LargeTexture>(); + ClassDB::register_class<CurveTexture>(); + ClassDB::register_class<GradientTexture>(); ClassDB::register_class<CubeMap>(); ClassDB::register_class<Animation>(); ClassDB::register_virtual_class<Font>(); ClassDB::register_class<BitmapFont>(); + ClassDB::register_class<Curve>(); ClassDB::register_class<DynamicFontData>(); ClassDB::register_class<DynamicFont>(); @@ -579,11 +597,13 @@ void register_scene_types() { ClassDB::register_class<PolygonPathFinder>(); ClassDB::register_class<BitMap>(); - ClassDB::register_class<ColorRamp>(); + ClassDB::register_class<Gradient>(); OS::get_singleton()->yield(); //may take time to init - ClassDB::register_class<AudioPlayer>(); + ClassDB::register_class<AudioStreamPlayer>(); + ClassDB::register_class<AudioStreamPlayer2D>(); + ClassDB::register_class<AudioStreamPlayer3D>(); ClassDB::register_virtual_class<VideoStream>(); ClassDB::register_class<AudioStreamSample>(); @@ -614,6 +634,13 @@ void register_scene_types() { ClassDB::register_class<SceneTree>(); ClassDB::register_virtual_class<SceneTreeTimer>(); //sorry, you can't create it +#ifndef DISABLE_DEPRECATED + ClassDB::add_compatibility_class("ImageSkyBox", "PanoramaSky"); + ClassDB::add_compatibility_class("FixedSpatialMaterial", "SpatialMaterial"); + ClassDB::add_compatibility_class("Mesh", "ArrayMesh"); + +#endif + OS::get_singleton()->yield(); //may take time to init resource_saver_text = memnew(ResourceFormatSaverText); @@ -651,6 +678,8 @@ void unregister_scene_types() { memdelete(resource_loader_text); } - FixedSpatialMaterial::finish_shaders(); + SpatialMaterial::finish_shaders(); + ParticlesMaterial::finish_shaders(); + CanvasItemMaterial::finish_shaders(); SceneStringNames::free(); } diff --git a/scene/register_scene_types.h b/scene/register_scene_types.h index 090254c5f..dee0af906 100644 --- a/scene/register_scene_types.h +++ b/scene/register_scene_types.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/SCsub b/scene/resources/SCsub index 60b16cd0d..2ad90247a 100644 --- a/scene/resources/SCsub +++ b/scene/resources/SCsub @@ -3,7 +3,6 @@ Import('env') env.add_source_files(env.scene_sources, "*.cpp") -env.add_source_files(env.scene_sources, "*.c") Export('env') diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 4fddd55e2..a2ff45c62 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -732,7 +733,7 @@ int Animation::track_find_key(int p_track, float p_time, bool p_exact) const { return -1; } -void Animation::track_insert_key(int p_track, float p_time, const Variant &p_value, float p_transition) { +void Animation::track_insert_key(int p_track, float p_time, const Variant &p_key, float p_transition) { ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; @@ -741,7 +742,7 @@ void Animation::track_insert_key(int p_track, float p_time, const Variant &p_val case TYPE_TRANSFORM: { - Dictionary d = p_value; + Dictionary d = p_key; Vector3 loc; if (d.has("loc")) loc = d["loc"]; @@ -765,7 +766,7 @@ void Animation::track_insert_key(int p_track, float p_time, const Variant &p_val TKey<Variant> k; k.time = p_time; k.transition = p_transition; - k.value = p_value; + k.value = p_key; _insert(p_time, vt->values, k); } break; @@ -773,9 +774,9 @@ void Animation::track_insert_key(int p_track, float p_time, const Variant &p_val MethodTrack *mt = static_cast<MethodTrack *>(t); - ERR_FAIL_COND(p_value.get_type() != Variant::DICTIONARY); + ERR_FAIL_COND(p_key.get_type() != Variant::DICTIONARY); - Dictionary d = p_value; + Dictionary d = p_key; ERR_FAIL_COND(!d.has("method") || d["method"].get_type() != Variant::STRING); ERR_FAIL_COND(!d.has("args") || !d["args"].is_array()); @@ -1132,7 +1133,7 @@ Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a Rect2 pb = p_post_b; return Rect2( - a.pos.cubic_interpolate(b.pos, pa.pos, pb.pos, p_c), + a.position.cubic_interpolate(b.position, pa.position, pb.position, p_c), a.size.cubic_interpolate(b.size, pa.size, pb.size, p_c)); } break; @@ -1164,7 +1165,7 @@ Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a Rect3 pb = p_post_b; return Rect3( - a.pos.cubic_interpolate(b.pos, pa.pos, pb.pos, p_c), + a.position.cubic_interpolate(b.position, pa.position, pb.position, p_c), a.size.cubic_interpolate(b.size, pa.size, pb.size, p_c)); } break; default: { @@ -1760,8 +1761,8 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons Vector3 v02, v01; real_t a02, a01; - r02.get_axis_and_angle(v02, a02); - r01.get_axis_and_angle(v01, a01); + r02.get_axis_angle(v02, a02); + r01.get_axis_angle(v01, a01); if (Math::abs(a02) > p_max_optimizable_angle) return false; @@ -1870,7 +1871,7 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons return erase; } -void Animation::_transform_track_optimize(int p_idx, float p_alowed_linear_err, float p_alowed_angular_err, float p_max_optimizable_angle) { +void Animation::_transform_track_optimize(int p_idx, float p_allowed_linear_err, float p_allowed_angular_err, float p_max_optimizable_angle) { ERR_FAIL_INDEX(p_idx, tracks.size()); ERR_FAIL_COND(tracks[p_idx]->type != TYPE_TRANSFORM); @@ -1886,12 +1887,12 @@ void Animation::_transform_track_optimize(int p_idx, float p_alowed_linear_err, TKey<TransformKey> &t1 = tt->transforms[i]; TKey<TransformKey> &t2 = tt->transforms[i + 1]; - bool erase = _transform_track_optimize_key(t0, t1, t2, p_alowed_linear_err, p_alowed_angular_err, p_max_optimizable_angle, norm); + bool erase = _transform_track_optimize_key(t0, t1, t2, p_allowed_linear_err, p_allowed_angular_err, p_max_optimizable_angle, norm); if (erase && !prev_erased) { norm = (t2.value.loc - t1.value.loc).normalized(); } - if (prev_erased && !_transform_track_optimize_key(t0, first_erased, t2, p_alowed_linear_err, p_alowed_angular_err, p_max_optimizable_angle, norm)) { + if (prev_erased && !_transform_track_optimize_key(t0, first_erased, t2, p_allowed_linear_err, p_allowed_angular_err, p_max_optimizable_angle, norm)) { //avoid error to go beyond first erased key erase = false; } @@ -1913,12 +1914,12 @@ void Animation::_transform_track_optimize(int p_idx, float p_alowed_linear_err, } } -void Animation::optimize(float p_allowed_linear_err, float p_allowed_angular_err, float p_angle_max) { +void Animation::optimize(float p_allowed_linear_err, float p_allowed_angular_err, float p_max_optimizable_angle) { for (int i = 0; i < tracks.size(); i++) { if (tracks[i]->type == TYPE_TRANSFORM) - _transform_track_optimize(i, p_allowed_linear_err, p_allowed_angular_err, p_angle_max); + _transform_track_optimize(i, p_allowed_linear_err, p_allowed_angular_err, p_max_optimizable_angle); } } diff --git a/scene/resources/animation.h b/scene/resources/animation.h index 57ab8b282..27c58aba8 100644 --- a/scene/resources/animation.h +++ b/scene/resources/animation.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -36,7 +37,7 @@ class Animation : public Resource { GDCLASS(Animation, Resource); - RES_BASE_EXTENSION("anm"); + RES_BASE_EXTENSION("anim"); public: enum TrackType { @@ -211,7 +212,7 @@ private: } bool _transform_track_optimize_key(const TKey<TransformKey> &t0, const TKey<TransformKey> &t1, const TKey<TransformKey> &t2, float p_alowed_linear_err, float p_alowed_angular_err, float p_max_optimizable_angle, const Vector3 &p_norm); - void _transform_track_optimize(int p_idx, float p_allowed_err = 0.05, float p_alowed_angular_err = 0.01, float p_max_optimizable_angle = Math_PI * 0.125); + void _transform_track_optimize(int p_idx, float p_allowed_linear_err = 0.05, float p_allowed_angular_err = 0.01, float p_max_optimizable_angle = Math_PI * 0.125); protected: bool _set(const StringName &p_name, const Variant &p_value); diff --git a/scene/resources/audio_stream_resampled.cpp b/scene/resources/audio_stream_resampled.cpp index 1c0c725ef..1b1d6f858 100644 --- a/scene/resources/audio_stream_resampled.cpp +++ b/scene/resources/audio_stream_resampled.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -27,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "audio_stream_resampled.h" -#include "global_config.h" +#include "project_settings.h" #if 0 int AudioStreamResampled::get_channel_count() const { diff --git a/scene/resources/audio_stream_resampled.h b/scene/resources/audio_stream_resampled.h index 7ceb6cef8..53fa3bd0b 100644 --- a/scene/resources/audio_stream_resampled.h +++ b/scene/resources/audio_stream_resampled.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_sample.cpp index 8e4091188..c8f6007e6 100644 --- a/scene/resources/audio_stream_sample.cpp +++ b/scene/resources/audio_stream_sample.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -38,8 +39,6 @@ void AudioStreamPlaybackSample::start(float p_from_pos) { ima_adpcm[i].last_nibble = -1; ima_adpcm[i].loop_pos = 0x7FFFFFFF; ima_adpcm[i].window_ofs = 0; - ima_adpcm[i].ptr = (const uint8_t *)base->data; - ima_adpcm[i].ptr += AudioStreamSample::DATA_PAD; } seek_pos(p_from_pos); @@ -121,7 +120,8 @@ void AudioStreamPlaybackSample::do_resample(const Depth *p_src, AudioFrame *p_ds int16_t nibble, diff, step; ima_adpcm[i].last_nibble++; - const uint8_t *src_ptr = ima_adpcm[i].ptr; + const uint8_t *src_ptr = (const uint8_t *)base->data; + src_ptr += AudioStreamSample::DATA_PAD; uint8_t nbb = src_ptr[(ima_adpcm[i].last_nibble >> 1) * (is_stereo ? 2 : 1) + i]; nibble = (ima_adpcm[i].last_nibble & 1) ? (nbb >> 4) : (nbb & 0xF); @@ -231,7 +231,7 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in /* some 64-bit fixed point precaches */ - int64_t loop_begin_fp = ((int64_t)len << MIX_FRAC_BITS); + int64_t loop_begin_fp = ((int64_t)base->loop_begin << MIX_FRAC_BITS); int64_t loop_end_fp = ((int64_t)base->loop_end << MIX_FRAC_BITS); int64_t length_fp = ((int64_t)len << MIX_FRAC_BITS); int64_t begin_limit = (base->loop_mode != AudioStreamSample::LOOP_DISABLED) ? loop_begin_fp : 0; diff --git a/scene/resources/audio_stream_sample.h b/scene/resources/audio_stream_sample.h index d5d1ae79c..680f037f1 100644 --- a/scene/resources/audio_stream_sample.h +++ b/scene/resources/audio_stream_sample.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -52,7 +53,6 @@ class AudioStreamPlaybackSample : public AudioStreamPlayback { int32_t last_nibble; int32_t loop_pos; int32_t window_ofs; - const uint8_t *ptr; } ima_adpcm[2]; int64_t offset; @@ -83,7 +83,7 @@ public: class AudioStreamSample : public AudioStream { GDCLASS(AudioStreamSample, AudioStream) - RES_BASE_EXTENSION("smp") + RES_BASE_EXTENSION("sample") public: enum Format { diff --git a/scene/resources/baked_light.cpp b/scene/resources/baked_light.cpp deleted file mode 100644 index 7fa930fd5..000000000 --- a/scene/resources/baked_light.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/*************************************************************************/ -/* baked_light.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "baked_light.h" -#include "servers/visual_server.h" diff --git a/scene/resources/baked_light.h b/scene/resources/baked_light.h deleted file mode 100644 index 7dee40b34..000000000 --- a/scene/resources/baked_light.h +++ /dev/null @@ -1,35 +0,0 @@ -/*************************************************************************/ -/* baked_light.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef BAKED_LIGHT_H -#define BAKED_LIGHT_H - -#include "resource.h" -#include "scene/resources/texture.h" - -#endif // BAKED_LIGHT_H diff --git a/scene/resources/bit_mask.cpp b/scene/resources/bit_mask.cpp index 277acad90..a47306793 100644 --- a/scene/resources/bit_mask.cpp +++ b/scene/resources/bit_mask.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -40,16 +41,16 @@ void BitMap::create(const Size2 &p_size) { zeromem(bitmask.ptr(), bitmask.size()); } -void BitMap::create_from_image_alpha(const Image &p_image) { +void BitMap::create_from_image_alpha(const Ref<Image> &p_image) { - ERR_FAIL_COND(p_image.empty()); - Image img = p_image; - img.convert(Image::FORMAT_LA8); - ERR_FAIL_COND(img.get_format() != Image::FORMAT_LA8); + ERR_FAIL_COND(p_image.is_null() || p_image->empty()); + Ref<Image> img = p_image->duplicate(); + img->convert(Image::FORMAT_LA8); + ERR_FAIL_COND(img->get_format() != Image::FORMAT_LA8); - create(Size2(img.get_width(), img.get_height())); + create(Size2(img->get_width(), img->get_height())); - PoolVector<uint8_t>::Read r = img.get_data().read(); + PoolVector<uint8_t>::Read r = img->get_data().read(); uint8_t *w = bitmask.ptr(); for (int i = 0; i < width * height; i++) { @@ -66,9 +67,9 @@ void BitMap::set_bit_rect(const Rect2 &p_rect, bool p_value) { Rect2i current = Rect2i(0, 0, width, height).clip(p_rect); uint8_t *data = bitmask.ptr(); - for (int i = current.pos.x; i < current.pos.x + current.size.x; i++) { + for (int i = current.position.x; i < current.position.x + current.size.x; i++) { - for (int j = current.pos.y; j < current.pos.y + current.size.y; j++) { + for (int j = current.position.y; j < current.position.y + current.size.y; j++) { int ofs = width * j + i; int bbyte = ofs / 8; diff --git a/scene/resources/bit_mask.h b/scene/resources/bit_mask.h index 3cee2279b..5ab7a3134 100644 --- a/scene/resources/bit_mask.h +++ b/scene/resources/bit_mask.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,6 +30,7 @@ #ifndef BIT_MASK_H #define BIT_MASK_H +#include "image.h" #include "io/resource_loader.h" #include "resource.h" @@ -50,7 +52,7 @@ protected: public: void create(const Size2 &p_size); - void create_from_image_alpha(const Image &p_image); + void create_from_image_alpha(const Ref<Image> &p_image); void set_bit(const Point2 &p_pos, bool p_value); bool get_bit(const Point2 &p_pos) const; diff --git a/scene/resources/bounds.cpp b/scene/resources/bounds.cpp index 974ff76cd..b08842601 100644 --- a/scene/resources/bounds.cpp +++ b/scene/resources/bounds.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/bounds.h b/scene/resources/bounds.h index 62e1b8e0e..8c0d1dcf6 100644 --- a/scene/resources/bounds.h +++ b/scene/resources/bounds.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/box_shape.cpp b/scene/resources/box_shape.cpp index 1e9991d7d..d5c25b718 100644 --- a/scene/resources/box_shape.cpp +++ b/scene/resources/box_shape.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,8 +34,8 @@ Vector<Vector3> BoxShape::_gen_debug_mesh_lines() { Vector<Vector3> lines; Rect3 aabb; - aabb.pos = -get_extents(); - aabb.size = aabb.pos * -2; + aabb.position = -get_extents(); + aabb.size = aabb.position * -2; for (int i = 0; i < 12; i++) { Vector3 a, b; diff --git a/scene/resources/box_shape.h b/scene/resources/box_shape.h index 2bab6d9b8..fdf1e9802 100644 --- a/scene/resources/box_shape.h +++ b/scene/resources/box_shape.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/canvas.cpp b/scene/resources/canvas.cpp index dd0375b76..b6a909f3f 100644 --- a/scene/resources/canvas.cpp +++ b/scene/resources/canvas.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/canvas.h b/scene/resources/canvas.h index 1d3775c30..331a99791 100644 --- a/scene/resources/canvas.h +++ b/scene/resources/canvas.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/capsule_shape.cpp b/scene/resources/capsule_shape.cpp index 1aa3fee0c..1fcc9da5b 100644 --- a/scene/resources/capsule_shape.cpp +++ b/scene/resources/capsule_shape.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/capsule_shape.h b/scene/resources/capsule_shape.h index ecffdd8ce..2864e7e23 100644 --- a/scene/resources/capsule_shape.h +++ b/scene/resources/capsule_shape.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/capsule_shape_2d.cpp b/scene/resources/capsule_shape_2d.cpp index d24640e43..20177692a 100644 --- a/scene/resources/capsule_shape_2d.cpp +++ b/scene/resources/capsule_shape_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -79,7 +80,7 @@ Rect2 CapsuleShape2D::get_rect() const { Vector2 he = Point2(get_radius(), get_radius() + get_height() * 0.5); Rect2 rect; - rect.pos = -he; + rect.position = -he; rect.size = he * 2.0; return rect; } diff --git a/scene/resources/capsule_shape_2d.h b/scene/resources/capsule_shape_2d.h index 05d819c1d..93e7d846a 100644 --- a/scene/resources/capsule_shape_2d.h +++ b/scene/resources/capsule_shape_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/circle_shape_2d.cpp b/scene/resources/circle_shape_2d.cpp index 2271a3ad9..1b7e09ddf 100644 --- a/scene/resources/circle_shape_2d.cpp +++ b/scene/resources/circle_shape_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -57,7 +58,7 @@ void CircleShape2D::_bind_methods() { Rect2 CircleShape2D::get_rect() const { Rect2 rect; - rect.pos = -Point2(get_radius(), get_radius()); + rect.position = -Point2(get_radius(), get_radius()); rect.size = Point2(get_radius(), get_radius()) * 2.0; return rect; } diff --git a/scene/resources/circle_shape_2d.h b/scene/resources/circle_shape_2d.h index 11fdc51f0..a4a4601e6 100644 --- a/scene/resources/circle_shape_2d.h +++ b/scene/resources/circle_shape_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/color_ramp.cpp b/scene/resources/color_ramp.cpp index 2c20ad527..1825225ab 100644 --- a/scene/resources/color_ramp.cpp +++ b/scene/resources/color_ramp.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -35,7 +36,7 @@ #define COLOR_RAMP_SET_OFFSETS "set_offsets" #define COLOR_RAMP_SET_COLORS "set_colors" -ColorRamp::ColorRamp() { +Gradient::Gradient() { //Set initial color ramp transition from black to white points.resize(2); points[0].color = Color(0, 0, 0, 1); @@ -45,35 +46,35 @@ ColorRamp::ColorRamp() { is_sorted = true; } -ColorRamp::~ColorRamp() { +Gradient::~Gradient() { } -void ColorRamp::_bind_methods() { +void Gradient::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_point", "offset", "color"), &ColorRamp::add_point); - ClassDB::bind_method(D_METHOD("remove_point", "offset", "color"), &ColorRamp::remove_point); + ClassDB::bind_method(D_METHOD("add_point", "offset", "color"), &Gradient::add_point); + ClassDB::bind_method(D_METHOD("remove_point", "offset"), &Gradient::remove_point); - ClassDB::bind_method(D_METHOD("set_offset", "point", "offset"), &ColorRamp::set_offset); - ClassDB::bind_method(D_METHOD("get_offset", "point"), &ColorRamp::get_offset); + ClassDB::bind_method(D_METHOD("set_offset", "point", "offset"), &Gradient::set_offset); + ClassDB::bind_method(D_METHOD("get_offset", "point"), &Gradient::get_offset); - ClassDB::bind_method(D_METHOD("set_color", "point", "color"), &ColorRamp::set_color); - ClassDB::bind_method(D_METHOD("get_color", "point"), &ColorRamp::get_color); + ClassDB::bind_method(D_METHOD("set_color", "point", "color"), &Gradient::set_color); + ClassDB::bind_method(D_METHOD("get_color", "point"), &Gradient::get_color); - ClassDB::bind_method(D_METHOD("interpolate", "offset"), &ColorRamp::get_color_at_offset); + ClassDB::bind_method(D_METHOD("interpolate", "offset"), &Gradient::get_color_at_offset); - ClassDB::bind_method(D_METHOD("get_point_count"), &ColorRamp::get_points_count); + ClassDB::bind_method(D_METHOD("get_point_count"), &Gradient::get_points_count); - ClassDB::bind_method(D_METHOD(COLOR_RAMP_SET_OFFSETS, "offsets"), &ColorRamp::set_offsets); - ClassDB::bind_method(D_METHOD(COLOR_RAMP_GET_OFFSETS), &ColorRamp::get_offsets); + ClassDB::bind_method(D_METHOD(COLOR_RAMP_SET_OFFSETS, "offsets"), &Gradient::set_offsets); + ClassDB::bind_method(D_METHOD(COLOR_RAMP_GET_OFFSETS), &Gradient::get_offsets); - ClassDB::bind_method(D_METHOD(COLOR_RAMP_SET_COLORS, "colors"), &ColorRamp::set_colors); - ClassDB::bind_method(D_METHOD(COLOR_RAMP_GET_COLORS), &ColorRamp::get_colors); + ClassDB::bind_method(D_METHOD(COLOR_RAMP_SET_COLORS, "colors"), &Gradient::set_colors); + ClassDB::bind_method(D_METHOD(COLOR_RAMP_GET_COLORS), &Gradient::get_colors); ADD_PROPERTY(PropertyInfo(Variant::REAL, "offsets"), COLOR_RAMP_SET_OFFSETS, COLOR_RAMP_GET_OFFSETS); ADD_PROPERTY(PropertyInfo(Variant::REAL, "colors"), COLOR_RAMP_SET_COLORS, COLOR_RAMP_GET_COLORS); } -Vector<float> ColorRamp::get_offsets() const { +Vector<float> Gradient::get_offsets() const { Vector<float> offsets; offsets.resize(points.size()); for (int i = 0; i < points.size(); i++) { @@ -82,7 +83,7 @@ Vector<float> ColorRamp::get_offsets() const { return offsets; } -Vector<Color> ColorRamp::get_colors() const { +Vector<Color> Gradient::get_colors() const { Vector<Color> colors; colors.resize(points.size()); for (int i = 0; i < points.size(); i++) { @@ -91,7 +92,7 @@ Vector<Color> ColorRamp::get_colors() const { return colors; } -void ColorRamp::set_offsets(const Vector<float> &p_offsets) { +void Gradient::set_offsets(const Vector<float> &p_offsets) { points.resize(p_offsets.size()); for (int i = 0; i < points.size(); i++) { points[i].offset = p_offsets[i]; @@ -100,7 +101,7 @@ void ColorRamp::set_offsets(const Vector<float> &p_offsets) { emit_signal(CoreStringNames::get_singleton()->changed); } -void ColorRamp::set_colors(const Vector<Color> &p_colors) { +void Gradient::set_colors(const Vector<Color> &p_colors) { if (points.size() < p_colors.size()) is_sorted = false; points.resize(p_colors.size()); @@ -110,11 +111,11 @@ void ColorRamp::set_colors(const Vector<Color> &p_colors) { emit_signal(CoreStringNames::get_singleton()->changed); } -Vector<ColorRamp::Point> &ColorRamp::get_points() { +Vector<Gradient::Point> &Gradient::get_points() { return points; } -void ColorRamp::add_point(float p_offset, const Color &p_color) { +void Gradient::add_point(float p_offset, const Color &p_color) { Point p; p.offset = p_offset; @@ -125,7 +126,7 @@ void ColorRamp::add_point(float p_offset, const Color &p_color) { emit_signal(CoreStringNames::get_singleton()->changed); } -void ColorRamp::remove_point(int p_index) { +void Gradient::remove_point(int p_index) { ERR_FAIL_INDEX(p_index, points.size()); ERR_FAIL_COND(points.size() <= 2); @@ -133,13 +134,13 @@ void ColorRamp::remove_point(int p_index) { emit_signal(CoreStringNames::get_singleton()->changed); } -void ColorRamp::set_points(Vector<ColorRamp::Point> &p_points) { +void Gradient::set_points(Vector<Gradient::Point> &p_points) { points = p_points; is_sorted = false; emit_signal(CoreStringNames::get_singleton()->changed); } -void ColorRamp::set_offset(int pos, const float offset) { +void Gradient::set_offset(int pos, const float offset) { if (points.size() <= pos) points.resize(pos + 1); points[pos].offset = offset; @@ -147,13 +148,13 @@ void ColorRamp::set_offset(int pos, const float offset) { emit_signal(CoreStringNames::get_singleton()->changed); } -float ColorRamp::get_offset(int pos) const { +float Gradient::get_offset(int pos) const { if (points.size() > pos) return points[pos].offset; return 0; //TODO: Maybe throw some error instead? } -void ColorRamp::set_color(int pos, const Color &color) { +void Gradient::set_color(int pos, const Color &color) { if (points.size() <= pos) { points.resize(pos + 1); is_sorted = false; @@ -162,12 +163,12 @@ void ColorRamp::set_color(int pos, const Color &color) { emit_signal(CoreStringNames::get_singleton()->changed); } -Color ColorRamp::get_color(int pos) const { +Color Gradient::get_color(int pos) const { if (points.size() > pos) return points[pos].color; return Color(0, 0, 0, 1); //TODO: Maybe throw some error instead? } -int ColorRamp::get_points_count() const { +int Gradient::get_points_count() const { return points.size(); } diff --git a/scene/resources/color_ramp.h b/scene/resources/color_ramp.h index 78c88c327..d9f14205b 100644 --- a/scene/resources/color_ramp.h +++ b/scene/resources/color_ramp.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,9 +32,9 @@ #include "resource.h" -class ColorRamp : public Resource { - GDCLASS(ColorRamp, Resource); - OBJ_SAVE_TYPE(ColorRamp); +class Gradient : public Resource { + GDCLASS(Gradient, Resource); + OBJ_SAVE_TYPE(Gradient); public: struct Point { @@ -53,13 +54,13 @@ protected: static void _bind_methods(); public: - ColorRamp(); - virtual ~ColorRamp(); + Gradient(); + virtual ~Gradient(); void add_point(float p_offset, const Color &p_color); void remove_point(int p_index); - void set_points(Vector<Point> &points); + void set_points(Vector<Point> &p_points); Vector<Point> &get_points(); void set_offset(int pos, const float offset); @@ -68,10 +69,10 @@ public: void set_color(int pos, const Color &color); Color get_color(int pos) const; - void set_offsets(const Vector<float> &offsets); + void set_offsets(const Vector<float> &p_offsets); Vector<float> get_offsets() const; - void set_colors(const Vector<Color> &colors); + void set_colors(const Vector<Color> &p_colors); Vector<Color> get_colors() const; _FORCE_INLINE_ Color get_color_at_offset(float p_offset) { diff --git a/scene/resources/concave_polygon_shape.cpp b/scene/resources/concave_polygon_shape.cpp index 003158015..47cc49c63 100644 --- a/scene/resources/concave_polygon_shape.cpp +++ b/scene/resources/concave_polygon_shape.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/concave_polygon_shape.h b/scene/resources/concave_polygon_shape.h index f048a4d15..a8f9d5067 100644 --- a/scene/resources/concave_polygon_shape.h +++ b/scene/resources/concave_polygon_shape.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/concave_polygon_shape_2d.cpp b/scene/resources/concave_polygon_shape_2d.cpp index 04a69d9c8..b8c931421 100644 --- a/scene/resources/concave_polygon_shape_2d.cpp +++ b/scene/resources/concave_polygon_shape_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -67,7 +68,7 @@ Rect2 ConcavePolygonShape2D::get_rect() const { PoolVector<Vector2>::Read r = s.read(); for (int i = 0; i < len; i++) { if (i == 0) - rect.pos = r[i]; + rect.position = r[i]; else rect.expand_to(r[i]); } diff --git a/scene/resources/concave_polygon_shape_2d.h b/scene/resources/concave_polygon_shape_2d.h index 23c602980..d4c102e0d 100644 --- a/scene/resources/concave_polygon_shape_2d.h +++ b/scene/resources/concave_polygon_shape_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/convex_polygon_shape.cpp b/scene/resources/convex_polygon_shape.cpp index 350c4c2d8..10e92b43a 100644 --- a/scene/resources/convex_polygon_shape.cpp +++ b/scene/resources/convex_polygon_shape.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/convex_polygon_shape.h b/scene/resources/convex_polygon_shape.h index 6701c41f0..4340b0ef7 100644 --- a/scene/resources/convex_polygon_shape.h +++ b/scene/resources/convex_polygon_shape.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/convex_polygon_shape_2d.cpp b/scene/resources/convex_polygon_shape_2d.cpp index 311614b7c..e13f7faf7 100644 --- a/scene/resources/convex_polygon_shape_2d.cpp +++ b/scene/resources/convex_polygon_shape_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -77,7 +78,7 @@ Rect2 ConvexPolygonShape2D::get_rect() const { Rect2 rect; for (int i = 0; i < points.size(); i++) { if (i == 0) - rect.pos = points[i]; + rect.position = points[i]; else rect.expand_to(points[i]); } diff --git a/scene/resources/convex_polygon_shape_2d.h b/scene/resources/convex_polygon_shape_2d.h index edb302ba5..ba4a5ae8a 100644 --- a/scene/resources/convex_polygon_shape_2d.h +++ b/scene/resources/convex_polygon_shape_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index f85220ac2..fe0759fcb 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -379,6 +380,487 @@ Curve2D::Curve2D() #endif +const char *Curve::SIGNAL_RANGE_CHANGED = "range_changed"; + +Curve::Curve() { + _bake_resolution = 100; + _baked_cache_dirty = false; + _min_value = 0; + _max_value = 1; +} + +int Curve::add_point(Vector2 p_pos, real_t left_tangent, real_t right_tangent, TangentMode left_mode, TangentMode right_mode) { + // Add a point and preserve order + + // Curve bounds is in 0..1 + if (p_pos.x > MAX_X) + p_pos.x = MAX_X; + else if (p_pos.x < MIN_X) + p_pos.x = MIN_X; + + int ret = -1; + + if (_points.size() == 0) { + _points.push_back(Point(p_pos, left_tangent, right_tangent, left_mode, right_mode)); + ret = 0; + + } else if (_points.size() == 1) { + // TODO Is the `else` able to handle this block already? + + real_t diff = p_pos.x - _points[0].pos.x; + + if (diff > 0) { + _points.push_back(Point(p_pos, left_tangent, right_tangent, left_mode, right_mode)); + ret = 1; + } else { + _points.insert(0, Point(p_pos, left_tangent, right_tangent, left_mode, right_mode)); + ret = 0; + } + + } else { + + int i = get_index(p_pos.x); + + int nearest_index = i; + if (i + 1 < _points.size()) { + real_t diff0 = p_pos.x - _points[i].pos.x; + real_t diff1 = _points[i + 1].pos.x - p_pos.x; + + if (diff1 < diff0) + nearest_index = i + 1; + } + + if (i == 0 && p_pos.x < _points[0].pos.x) { + // Insert before anything else + _points.insert(0, Point(p_pos, left_tangent, right_tangent, left_mode, right_mode)); + ret = 0; + } else { + // Insert between i and i+1 + ++i; + _points.insert(i, Point(p_pos, left_tangent, right_tangent, left_mode, right_mode)); + ret = i; + } + } + + update_auto_tangents(ret); + + mark_dirty(); + + return ret; +} + +int Curve::get_index(real_t offset) const { + + // Lower-bound float binary search + + int imin = 0; + int imax = _points.size() - 1; + + while (imax - imin > 1) { + int m = (imin + imax) / 2; + + real_t a = _points[m].pos.x; + real_t b = _points[m + 1].pos.x; + + if (a < offset && b < offset) { + imin = m; + + } else if (a > offset) { + imax = m; + + } else { + return m; + } + } + + // Will happen if the offset is out of bounds + if (offset > _points[imax].pos.x) + return imax; + return imin; +} + +void Curve::clean_dupes() { + + bool dirty = false; + + for (int i = 1; i < _points.size(); ++i) { + real_t diff = _points[i - 1].pos.x - _points[i].pos.x; + if (diff <= CMP_EPSILON) { + _points.remove(i); + --i; + dirty = true; + } + } + + if (dirty) + mark_dirty(); +} + +void Curve::set_point_left_tangent(int i, real_t tangent) { + ERR_FAIL_INDEX(i, _points.size()); + _points[i].left_tangent = tangent; + _points[i].left_mode = TANGENT_FREE; + mark_dirty(); +} + +void Curve::set_point_right_tangent(int i, real_t tangent) { + ERR_FAIL_INDEX(i, _points.size()); + _points[i].right_tangent = tangent; + _points[i].right_mode = TANGENT_FREE; + mark_dirty(); +} + +void Curve::set_point_left_mode(int i, TangentMode p_mode) { + ERR_FAIL_INDEX(i, _points.size()); + _points[i].left_mode = p_mode; + if (i > 0) { + if (p_mode == TANGENT_LINEAR) { + Vector2 v = (_points[i - 1].pos - _points[i].pos).normalized(); + _points[i].left_tangent = v.y / v.x; + } + } + mark_dirty(); +} + +void Curve::set_point_right_mode(int i, TangentMode p_mode) { + ERR_FAIL_INDEX(i, _points.size()); + _points[i].right_mode = p_mode; + if (i + 1 < _points.size()) { + if (p_mode == TANGENT_LINEAR) { + Vector2 v = (_points[i + 1].pos - _points[i].pos).normalized(); + _points[i].right_tangent = v.y / v.x; + } + } + mark_dirty(); +} + +real_t Curve::get_point_left_tangent(int i) const { + ERR_FAIL_INDEX_V(i, _points.size(), 0); + return _points[i].left_tangent; +} + +real_t Curve::get_point_right_tangent(int i) const { + ERR_FAIL_INDEX_V(i, _points.size(), 0); + return _points[i].right_tangent; +} + +Curve::TangentMode Curve::get_point_left_mode(int i) const { + ERR_FAIL_INDEX_V(i, _points.size(), TANGENT_FREE); + return _points[i].left_mode; +} + +Curve::TangentMode Curve::get_point_right_mode(int i) const { + ERR_FAIL_INDEX_V(i, _points.size(), TANGENT_FREE); + return _points[i].right_mode; +} + +void Curve::remove_point(int p_index) { + ERR_FAIL_INDEX(p_index, _points.size()); + _points.remove(p_index); + mark_dirty(); +} + +void Curve::clear_points() { + _points.clear(); + mark_dirty(); +} + +void Curve::set_point_value(int p_index, real_t pos) { + ERR_FAIL_INDEX(p_index, _points.size()); + _points[p_index].pos.y = pos; + update_auto_tangents(p_index); + mark_dirty(); +} + +int Curve::set_point_offset(int p_index, float offset) { + ERR_FAIL_INDEX_V(p_index, _points.size(), -1); + Point p = _points[p_index]; + remove_point(p_index); + int i = add_point(Vector2(offset, p.pos.y)); + _points[i].left_tangent = p.left_tangent; + _points[i].right_tangent = p.right_tangent; + _points[i].left_mode = p.left_mode; + _points[i].right_mode = p.right_mode; + if (p_index != i) + update_auto_tangents(p_index); + update_auto_tangents(i); + return i; +} + +Vector2 Curve::get_point_pos(int p_index) const { + ERR_FAIL_INDEX_V(p_index, _points.size(), Vector2(0, 0)); + return _points[p_index].pos; +} + +Curve::Point Curve::get_point(int p_index) const { + ERR_FAIL_INDEX_V(p_index, _points.size(), Point()); + return _points[p_index]; +} + +void Curve::update_auto_tangents(int i) { + + Point &p = _points[i]; + + if (i > 0) { + if (p.left_mode == TANGENT_LINEAR) { + Vector2 v = (_points[i - 1].pos - p.pos).normalized(); + p.left_tangent = v.y / v.x; + } + if (_points[i - 1].right_mode == TANGENT_LINEAR) { + Vector2 v = (_points[i - 1].pos - p.pos).normalized(); + _points[i - 1].right_tangent = v.y / v.x; + } + } + + if (i + 1 < _points.size()) { + if (p.right_mode == TANGENT_LINEAR && i + 1 < _points.size()) { + Vector2 v = (_points[i + 1].pos - p.pos).normalized(); + p.right_tangent = v.y / v.x; + } + if (_points[i + 1].left_mode == TANGENT_LINEAR) { + Vector2 v = (_points[i + 1].pos - p.pos).normalized(); + _points[i + 1].left_tangent = v.y / v.x; + } + } +} + +#define MIN_Y_RANGE 0.01 + +void Curve::set_min_value(float p_min) { + if (p_min > _max_value - MIN_Y_RANGE) + _min_value = _max_value - MIN_Y_RANGE; + else + _min_value = p_min; + // Note: min and max are indicative values, + // it's still possible that existing points are out of range at this point. + emit_signal(SIGNAL_RANGE_CHANGED); +} + +void Curve::set_max_value(float p_max) { + if (p_max < _min_value + MIN_Y_RANGE) + _max_value = _min_value + MIN_Y_RANGE; + else + _max_value = p_max; + emit_signal(SIGNAL_RANGE_CHANGED); +} + +real_t Curve::interpolate(real_t offset) const { + if (_points.size() == 0) + return 0; + if (_points.size() == 1) + return _points[0].pos.y; + + int i = get_index(offset); + + if (i == _points.size() - 1) + return _points[i].pos.y; + + real_t local = offset - _points[i].pos.x; + + if (i == 0 && local <= 0) + return _points[0].pos.y; + + return interpolate_local_nocheck(i, local); +} + +real_t Curve::interpolate_local_nocheck(int index, real_t local_offset) const { + + const Point a = _points[index]; + const Point b = _points[index + 1]; + + // Cubic bezier + + // ac-----bc + // / \ + // / \ Here with a.right_tangent > 0 + // / \ and b.left_tangent < 0 + // / \ + // a b + // + // |-d1--|-d2--|-d3--| + // + // d1 == d2 == d3 == d / 3 + + // Control points are chosen at equal distances + real_t d = b.pos.x - a.pos.x; + if (Math::abs(d) <= CMP_EPSILON) + return b.pos.y; + local_offset /= d; + d /= 3.0; + real_t yac = a.pos.y + d * a.right_tangent; + real_t ybc = b.pos.y - d * b.left_tangent; + + real_t y = _bezier_interp(local_offset, a.pos.y, yac, ybc, b.pos.y); + + return y; +} + +void Curve::mark_dirty() { + _baked_cache_dirty = true; + emit_signal(CoreStringNames::get_singleton()->changed); +} + +Array Curve::get_data() const { + + Array output; + const unsigned int ELEMS = 5; + output.resize(_points.size() * ELEMS); + + for (int j = 0; j < _points.size(); ++j) { + + const Point p = _points[j]; + int i = j * ELEMS; + + output[i] = p.pos; + output[i + 1] = p.left_tangent; + output[i + 2] = p.right_tangent; + output[i + 3] = p.left_mode; + output[i + 4] = p.right_mode; + } + + return output; +} + +void Curve::set_data(Array input) { + const unsigned int ELEMS = 5; + ERR_FAIL_COND(input.size() % ELEMS != 0); + + _points.clear(); + + // Validate input + for (int i = 0; i < input.size(); i += ELEMS) { + ERR_FAIL_COND(input[i].get_type() != Variant::VECTOR2); + ERR_FAIL_COND(!input[i + 1].is_num()); + ERR_FAIL_COND(input[i + 2].get_type() != Variant::REAL); + + ERR_FAIL_COND(input[i + 3].get_type() != Variant::INT); + int left_mode = input[i + 3]; + ERR_FAIL_COND(left_mode < 0 || left_mode >= TANGENT_MODE_COUNT); + + ERR_FAIL_COND(input[i + 4].get_type() != Variant::INT); + int right_mode = input[i + 4]; + ERR_FAIL_COND(right_mode < 0 || right_mode >= TANGENT_MODE_COUNT); + } + + _points.resize(input.size() / ELEMS); + + for (int j = 0; j < _points.size(); ++j) { + + Point &p = _points[j]; + int i = j * ELEMS; + + p.pos = input[i]; + p.left_tangent = input[i + 1]; + p.right_tangent = input[i + 2]; + // TODO For some reason the compiler won't convert from Variant to enum + int left_mode = input[i + 3]; + int right_mode = input[i + 4]; + p.left_mode = (TangentMode)left_mode; + p.right_mode = (TangentMode)right_mode; + } + + mark_dirty(); +} + +void Curve::bake() { + _baked_cache.clear(); + + _baked_cache.resize(_bake_resolution); + + for (int i = 1; i < _bake_resolution - 1; ++i) { + real_t x = i / static_cast<real_t>(_bake_resolution); + real_t y = interpolate(x); + _baked_cache[i] = y; + } + + if (_points.size() != 0) { + _baked_cache[0] = _points[0].pos.y; + _baked_cache[_baked_cache.size() - 1] = _points[_points.size() - 1].pos.y; + } + + _baked_cache_dirty = false; +} + +void Curve::set_bake_resolution(int p_resolution) { + ERR_FAIL_COND(p_resolution < 1); + ERR_FAIL_COND(p_resolution > 1000); + _bake_resolution = p_resolution; + _baked_cache_dirty = true; +} + +real_t Curve::interpolate_baked(real_t offset) { + if (_baked_cache_dirty) { + // Last-second bake if not done already + bake(); + } + + // Special cases if the cache is too small + if (_baked_cache.size() == 0) { + if (_points.size() == 0) + return 0; + return _points[0].pos.y; + } else if (_baked_cache.size() == 1) { + return _baked_cache[0]; + } + + // Get interpolation index + real_t fi = offset * _baked_cache.size(); + int i = Math::floor(fi); + if (i < 0) { + i = 0; + fi = 0; + } else if (i >= _baked_cache.size()) { + i = _baked_cache.size() - 1; + fi = 0; + } + + // Interpolate + if (i + 1 < _baked_cache.size()) { + real_t t = fi - i; + return Math::lerp(_baked_cache[i], _baked_cache[i + 1], t); + } else { + return _baked_cache[_baked_cache.size() - 1]; + } +} + +void Curve::_bind_methods() { + + ClassDB::bind_method(D_METHOD("add_point", "pos", "left_tangent", "right_tangent", "left_mode", "right_mode"), + &Curve::add_point, DEFVAL(0), DEFVAL(0), DEFVAL(TANGENT_FREE), DEFVAL(TANGENT_FREE)); + ClassDB::bind_method(D_METHOD("remove_point", "index"), &Curve::remove_point); + ClassDB::bind_method(D_METHOD("clear_points"), &Curve::clear_points); + ClassDB::bind_method(D_METHOD("get_point_pos", "index"), &Curve::get_point_pos); + ClassDB::bind_method(D_METHOD("set_point_value", "index", "y"), &Curve::set_point_value); + ClassDB::bind_method(D_METHOD("set_point_offset", "index", "offset"), &Curve::set_point_value); + ClassDB::bind_method(D_METHOD("interpolate", "offset"), &Curve::interpolate); + ClassDB::bind_method(D_METHOD("interpolate_baked", "offset"), &Curve::interpolate_baked); + ClassDB::bind_method(D_METHOD("get_point_left_tangent", "index"), &Curve::get_point_left_tangent); + ClassDB::bind_method(D_METHOD("get_point_right_tangent", "index"), &Curve::get_point_left_tangent); + ClassDB::bind_method(D_METHOD("get_point_left_mode", "index"), &Curve::get_point_left_mode); + ClassDB::bind_method(D_METHOD("get_point_right_mode", "index"), &Curve::get_point_left_mode); + ClassDB::bind_method(D_METHOD("set_point_left_tangent", "index", "tangent"), &Curve::set_point_left_tangent); + ClassDB::bind_method(D_METHOD("set_point_right_tangent", "index", "tangent"), &Curve::set_point_left_tangent); + ClassDB::bind_method(D_METHOD("set_point_left_mode", "index", "mode"), &Curve::set_point_left_mode); + ClassDB::bind_method(D_METHOD("set_point_right_mode", "index", "mode"), &Curve::set_point_left_mode); + ClassDB::bind_method(D_METHOD("get_min_value"), &Curve::get_min_value); + ClassDB::bind_method(D_METHOD("set_min_value", "min"), &Curve::set_min_value); + ClassDB::bind_method(D_METHOD("get_max_value"), &Curve::get_max_value); + ClassDB::bind_method(D_METHOD("set_max_value", "max"), &Curve::set_max_value); + ClassDB::bind_method(D_METHOD("clean_dupes"), &Curve::clean_dupes); + ClassDB::bind_method(D_METHOD("bake"), &Curve::bake); + ClassDB::bind_method(D_METHOD("get_bake_resolution"), &Curve::get_bake_resolution); + ClassDB::bind_method(D_METHOD("set_bake_resolution", "resolution"), &Curve::set_bake_resolution); + ClassDB::bind_method(D_METHOD("_get_data"), &Curve::get_data); + ClassDB::bind_method(D_METHOD("_set_data", "data"), &Curve::set_data); + + ADD_PROPERTY(PropertyInfo(Variant::REAL, "min_value", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_min_value", "get_min_value"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_value", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_max_value", "get_max_value"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "bake_resolution", PROPERTY_HINT_RANGE, "1,1000,1"), "set_bake_resolution", "get_bake_resolution"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_data", "_get_data"); + + ADD_SIGNAL(MethodInfo(SIGNAL_RANGE_CHANGED)); +} + int Curve2D::get_point_count() const { return points.size(); @@ -706,7 +1188,7 @@ void Curve2D::_set_data(const Dictionary &p_data) { baked_cache_dirty = true; } -PoolVector2Array Curve2D::tesselate(int p_max_stages, float p_tolerance) const { +PoolVector2Array Curve2D::tessellate(int p_max_stages, float p_tolerance) const { PoolVector2Array tess; @@ -768,7 +1250,7 @@ void Curve2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_baked_length"), &Curve2D::get_baked_length); ClassDB::bind_method(D_METHOD("interpolate_baked", "offset", "cubic"), &Curve2D::interpolate_baked, DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_baked_points"), &Curve2D::get_baked_points); - ClassDB::bind_method(D_METHOD("tesselate", "max_stages", "tolerance_degrees"), &Curve2D::tesselate, DEFVAL(5), DEFVAL(4)); + ClassDB::bind_method(D_METHOD("tessellate", "max_stages", "tolerance_degrees"), &Curve2D::tessellate, DEFVAL(5), DEFVAL(4)); ClassDB::bind_method(D_METHOD("_get_data"), &Curve2D::_get_data); ClassDB::bind_method(D_METHOD("_set_data"), &Curve2D::_set_data); @@ -1201,7 +1683,7 @@ void Curve3D::_set_data(const Dictionary &p_data) { baked_cache_dirty = true; } -PoolVector3Array Curve3D::tesselate(int p_max_stages, float p_tolerance) const { +PoolVector3Array Curve3D::tessellate(int p_max_stages, float p_tolerance) const { PoolVector3Array tess; @@ -1266,7 +1748,7 @@ void Curve3D::_bind_methods() { ClassDB::bind_method(D_METHOD("interpolate_baked", "offset", "cubic"), &Curve3D::interpolate_baked, DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_baked_points"), &Curve3D::get_baked_points); ClassDB::bind_method(D_METHOD("get_baked_tilts"), &Curve3D::get_baked_tilts); - ClassDB::bind_method(D_METHOD("tesselate", "max_stages", "tolerance_degrees"), &Curve3D::tesselate, DEFVAL(5), DEFVAL(4)); + ClassDB::bind_method(D_METHOD("tessellate", "max_stages", "tolerance_degrees"), &Curve3D::tessellate, DEFVAL(5), DEFVAL(4)); ClassDB::bind_method(D_METHOD("_get_data"), &Curve3D::_get_data); ClassDB::bind_method(D_METHOD("_set_data"), &Curve3D::_set_data); diff --git a/scene/resources/curve.h b/scene/resources/curve.h index eae52d7bd..e302f1e0a 100644 --- a/scene/resources/curve.h +++ b/scene/resources/curve.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -81,6 +82,117 @@ public: #endif +// y(x) curve +class Curve : public Resource { + GDCLASS(Curve, Resource) +public: + static const int MIN_X = 0.f; + static const int MAX_X = 1.f; + + static const char *SIGNAL_RANGE_CHANGED; + + enum TangentMode { + TANGENT_FREE = 0, + TANGENT_LINEAR, + TANGENT_MODE_COUNT + }; + + struct Point { + Vector2 pos; + real_t left_tangent; + real_t right_tangent; + TangentMode left_mode; + TangentMode right_mode; + + Point() { + left_tangent = 0; + right_tangent = 0; + left_mode = TANGENT_FREE; + right_mode = TANGENT_FREE; + } + + Point(Vector2 p_pos, + real_t p_left = 0, + real_t p_right = 0, + TangentMode p_left_mode = TANGENT_FREE, + TangentMode p_right_mode = TANGENT_FREE) { + + pos = p_pos; + left_tangent = p_left; + right_tangent = p_right; + left_mode = p_left_mode; + right_mode = p_right_mode; + } + }; + + Curve(); + + int get_point_count() const { return _points.size(); } + + int add_point(Vector2 p_pos, + real_t left_tangent = 0, + real_t right_tangent = 0, + TangentMode left_mode = TANGENT_FREE, + TangentMode right_mode = TANGENT_FREE); + + void remove_point(int p_index); + void clear_points(); + + int get_index(real_t offset) const; + + void set_point_value(int p_index, real_t pos); + int set_point_offset(int p_index, float offset); + Vector2 get_point_pos(int p_index) const; + + Point get_point(int p_index) const; + + float get_min_value() const { return _min_value; } + void set_min_value(float p_min); + + float get_max_value() const { return _max_value; } + void set_max_value(float p_max); + + real_t interpolate(real_t offset) const; + real_t interpolate_local_nocheck(int index, real_t local_offset) const; + + void clean_dupes(); + + void set_point_left_tangent(int i, real_t tangent); + void set_point_right_tangent(int i, real_t tangent); + void set_point_left_mode(int i, TangentMode p_mode); + void set_point_right_mode(int i, TangentMode p_mode); + + real_t get_point_left_tangent(int i) const; + real_t get_point_right_tangent(int i) const; + TangentMode get_point_left_mode(int i) const; + TangentMode get_point_right_mode(int i) const; + + void update_auto_tangents(int i); + + Array get_data() const; + void set_data(Array input); + + void bake(); + int get_bake_resolution() const { return _bake_resolution; } + void set_bake_resolution(int p_resolution); + real_t interpolate_baked(real_t offset); + +protected: + static void _bind_methods(); + +private: + void mark_dirty(); + + Vector<Point> _points; + bool _baked_cache_dirty; + Vector<real_t> _baked_cache; + int _bake_resolution; + float _min_value; + float _max_value; +}; + +VARIANT_ENUM_CAST(Curve::TangentMode) + class Curve2D : public Resource { GDCLASS(Curve2D, Resource); @@ -130,14 +242,14 @@ public: Vector2 interpolate(int p_index, float p_offset) const; Vector2 interpolatef(real_t p_findex) const; - void set_bake_interval(float p_distance); + void set_bake_interval(float p_tolerance); float get_bake_interval() const; float get_baked_length() const; Vector2 interpolate_baked(float p_offset, bool p_cubic = false) const; PoolVector2Array get_baked_points() const; //useful for going through - PoolVector2Array tesselate(int p_max_stages = 5, float p_tolerance = 4) const; //useful for display + PoolVector2Array tessellate(int p_max_stages = 5, float p_tolerance = 4) const; //useful for display Curve2D(); }; @@ -197,7 +309,7 @@ public: Vector3 interpolate(int p_index, float p_offset) const; Vector3 interpolatef(real_t p_findex) const; - void set_bake_interval(float p_distance); + void set_bake_interval(float p_tolerance); float get_bake_interval() const; float get_baked_length() const; @@ -206,7 +318,7 @@ public: PoolVector3Array get_baked_points() const; //useful for going through PoolRealArray get_baked_tilts() const; //useful for going through - PoolVector3Array tesselate(int p_max_stages = 5, float p_tolerance = 4) const; //useful for display + PoolVector3Array tessellate(int p_max_stages = 5, float p_tolerance = 4) const; //useful for display Curve3D(); }; diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 60490d70c..03288e45b 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -52,20 +53,20 @@ static Ref<StyleBoxTexture> make_stylebox(T p_src, float p_left, float p_top, fl } else { texture = Ref<ImageTexture>(memnew(ImageTexture)); - Image img(p_src); + Ref<Image> img = memnew(Image(p_src)); if (scale > 1) { - Size2 orig_size = Size2(img.get_width(), img.get_height()); + Size2 orig_size = Size2(img->get_width(), img->get_height()); - img.convert(Image::FORMAT_RGBA8); - img.expand_x2_hq2x(); + img->convert(Image::FORMAT_RGBA8); + img->expand_x2_hq2x(); if (scale != 2.0) { - img.resize(orig_size.x * scale, orig_size.y * scale); + img->resize(orig_size.x * scale, orig_size.y * scale); } } else if (scale < 1) { - Size2 orig_size = Size2(img.get_width(), img.get_height()); - img.convert(Image::FORMAT_RGBA8); - img.resize(orig_size.x * scale, orig_size.y * scale); + Size2 orig_size = Size2(img->get_width(), img->get_height()); + img->convert(Image::FORMAT_RGBA8); + img->resize(orig_size.x * scale, orig_size.y * scale); } texture->create_from_image(img, ImageTexture::FLAG_FILTER); @@ -100,19 +101,19 @@ template <class T> static Ref<Texture> make_icon(T p_src) { Ref<ImageTexture> texture(memnew(ImageTexture)); - Image img = Image(p_src); + Ref<Image> img = memnew(Image(p_src)); if (scale > 1) { - Size2 orig_size = Size2(img.get_width(), img.get_height()); + Size2 orig_size = Size2(img->get_width(), img->get_height()); - img.convert(Image::FORMAT_RGBA8); - img.expand_x2_hq2x(); + img->convert(Image::FORMAT_RGBA8); + img->expand_x2_hq2x(); if (scale != 2.0) { - img.resize(orig_size.x * scale, orig_size.y * scale); + img->resize(orig_size.x * scale, orig_size.y * scale); } } else if (scale < 1) { - Size2 orig_size = Size2(img.get_width(), img.get_height()); - img.convert(Image::FORMAT_RGBA8); - img.resize(orig_size.x * scale, orig_size.y * scale); + Size2 orig_size = Size2(img->get_width(), img->get_height()); + img->convert(Image::FORMAT_RGBA8); + img->resize(orig_size.x * scale, orig_size.y * scale); } texture->create_from_image(img, ImageTexture::FLAG_FILTER); @@ -120,7 +121,7 @@ static Ref<Texture> make_icon(T p_src) { } static Ref<Shader> make_shader(const char *vertex_code, const char *fragment_code, const char *lighting_code) { - Ref<Shader> shader = (memnew(Shader(Shader::MODE_CANVAS_ITEM))); + Ref<Shader> shader = (memnew(Shader())); //shader->set_code(vertex_code, fragment_code, lighting_code); return shader; @@ -137,8 +138,8 @@ static Ref<BitmapFont> make_font(int p_height, int p_ascent, int p_valign, int p int chr = c[0]; Rect2 frect; - frect.pos.x = c[1]; - frect.pos.y = c[2]; + frect.position.x = c[1]; + frect.position.y = c[2]; frect.size.x = c[3]; frect.size.y = c[4]; Point2 align(c[5], c[6] + p_valign); @@ -157,7 +158,7 @@ static Ref<BitmapFont> make_font2(int p_height, int p_ascent, int p_charcount, c Ref<BitmapFont> font(memnew(BitmapFont)); - Image image(p_img); + Ref<Image> image = memnew(Image(p_img)); Ref<ImageTexture> tex = memnew(ImageTexture); tex->create_from_image(image); @@ -169,8 +170,8 @@ static Ref<BitmapFont> make_font2(int p_height, int p_ascent, int p_charcount, c int chr = c[0]; Rect2 frect; - frect.pos.x = c[1]; - frect.pos.y = c[2]; + frect.position.x = c[1]; + frect.position.y = c[2]; frect.size.x = c[3]; frect.size.y = c[4]; Point2 align(c[6], c[5]); @@ -202,7 +203,7 @@ static Ref<StyleBox> make_empty_stylebox(float p_margin_left = -1, float p_margi return style; } -void fill_default_theme(Ref<Theme> &t, const Ref<Font> &default_font, const Ref<Font> &large_font, Ref<Texture> &default_icon, Ref<StyleBox> &default_style, float p_scale) { +void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &large_font, Ref<Texture> &default_icon, Ref<StyleBox> &default_style, float p_scale) { scale = p_scale; @@ -222,7 +223,7 @@ void fill_default_theme(Ref<Theme> &t, const Ref<Font> &default_font, const Ref< // Panel - t->set_stylebox("panel", "Panel", make_stylebox(panel_bg_png, 0, 0, 0, 0)); + theme->set_stylebox("panel", "Panel", make_stylebox(panel_bg_png, 0, 0, 0, 0)); // Focus @@ -239,69 +240,63 @@ void fill_default_theme(Ref<Theme> &t, const Ref<Font> &default_font, const Ref< Ref<StyleBox> sb_button_disabled = sb_expand(make_stylebox(button_disabled_png, 4, 4, 4, 4, 6, 2, 6, 2), 2, 2, 2, 2); Ref<StyleBox> sb_button_focus = sb_expand(make_stylebox(button_focus_png, 4, 4, 4, 4, 6, 2, 6, 2), 2, 2, 2, 2); - t->set_stylebox("normal", "Button", sb_button_normal); - t->set_stylebox("pressed", "Button", sb_button_pressed); - t->set_stylebox("hover", "Button", sb_button_hover); - t->set_stylebox("disabled", "Button", sb_button_disabled); - t->set_stylebox("focus", "Button", sb_button_focus); + theme->set_stylebox("normal", "Button", sb_button_normal); + theme->set_stylebox("pressed", "Button", sb_button_pressed); + theme->set_stylebox("hover", "Button", sb_button_hover); + theme->set_stylebox("disabled", "Button", sb_button_disabled); + theme->set_stylebox("focus", "Button", sb_button_focus); - t->set_font("font", "Button", default_font); + theme->set_font("font", "Button", default_font); - t->set_color("font_color", "Button", control_font_color); - t->set_color("font_color_pressed", "Button", control_font_color_pressed); - t->set_color("font_color_hover", "Button", control_font_color_hover); - t->set_color("font_color_disabled", "Button", control_font_color_disabled); + theme->set_color("font_color", "Button", control_font_color); + theme->set_color("font_color_pressed", "Button", control_font_color_pressed); + theme->set_color("font_color_hover", "Button", control_font_color_hover); + theme->set_color("font_color_disabled", "Button", control_font_color_disabled); - t->set_constant("hseparation", "Button", 2 * scale); + theme->set_constant("hseparation", "Button", 2 * scale); // LinkButton - t->set_font("font", "LinkButton", default_font); + theme->set_font("font", "LinkButton", default_font); - t->set_color("font_color", "LinkButton", control_font_color); - t->set_color("font_color_pressed", "LinkButton", control_font_color_pressed); - t->set_color("font_color_hover", "LinkButton", control_font_color_hover); + theme->set_color("font_color", "LinkButton", control_font_color); + theme->set_color("font_color_pressed", "LinkButton", control_font_color_pressed); + theme->set_color("font_color_hover", "LinkButton", control_font_color_hover); - t->set_constant("underline_spacing", "LinkButton", 2 * scale); + theme->set_constant("underline_spacing", "LinkButton", 2 * scale); // ColorPickerButton - t->set_stylebox("normal", "ColorPickerButton", sb_button_normal); - t->set_stylebox("pressed", "ColorPickerButton", sb_button_pressed); - t->set_stylebox("hover", "ColorPickerButton", sb_button_hover); - t->set_stylebox("disabled", "ColorPickerButton", sb_button_disabled); - t->set_stylebox("focus", "ColorPickerButton", sb_button_focus); + theme->set_stylebox("normal", "ColorPickerButton", sb_button_normal); + theme->set_stylebox("pressed", "ColorPickerButton", sb_button_pressed); + theme->set_stylebox("hover", "ColorPickerButton", sb_button_hover); + theme->set_stylebox("disabled", "ColorPickerButton", sb_button_disabled); + theme->set_stylebox("focus", "ColorPickerButton", sb_button_focus); - t->set_font("font", "ColorPickerButton", default_font); + theme->set_font("font", "ColorPickerButton", default_font); - t->set_color("font_color", "ColorPickerButton", Color(1, 1, 1, 1)); - t->set_color("font_color_pressed", "ColorPickerButton", Color(0.8, 0.8, 0.8, 1)); - t->set_color("font_color_hover", "ColorPickerButton", Color(1, 1, 1, 1)); - t->set_color("font_color_disabled", "ColorPickerButton", Color(0.9, 0.9, 0.9, 0.3)); + theme->set_color("font_color", "ColorPickerButton", Color(1, 1, 1, 1)); + theme->set_color("font_color_pressed", "ColorPickerButton", Color(0.8, 0.8, 0.8, 1)); + theme->set_color("font_color_hover", "ColorPickerButton", Color(1, 1, 1, 1)); + theme->set_color("font_color_disabled", "ColorPickerButton", Color(0.9, 0.9, 0.9, 0.3)); - t->set_constant("hseparation", "ColorPickerButton", 2 * scale); + theme->set_constant("hseparation", "ColorPickerButton", 2 * scale); // ToolButton - Ref<StyleBox> tb_empty = memnew(StyleBoxEmpty); - tb_empty->set_default_margin(MARGIN_LEFT, 6 * scale); - tb_empty->set_default_margin(MARGIN_RIGHT, 6 * scale); - tb_empty->set_default_margin(MARGIN_TOP, 4 * scale); - tb_empty->set_default_margin(MARGIN_BOTTOM, 4 * scale); + theme->set_stylebox("normal", "ToolButton", make_empty_stylebox(6, 4, 6, 4)); + theme->set_stylebox("pressed", "ToolButton", make_stylebox(button_pressed_png, 4, 4, 4, 4, 6, 4, 6, 4)); + theme->set_stylebox("hover", "ToolButton", make_stylebox(button_normal_png, 4, 4, 4, 4, 6, 4, 6, 4)); + theme->set_stylebox("disabled", "ToolButton", make_empty_stylebox(6, 4, 6, 4)); + theme->set_stylebox("focus", "ToolButton", focus); + theme->set_font("font", "ToolButton", default_font); - t->set_stylebox("normal", "ToolButton", tb_empty); - t->set_stylebox("pressed", "ToolButton", make_stylebox(button_pressed_png, 4, 4, 4, 4)); - t->set_stylebox("hover", "ToolButton", make_stylebox(button_normal_png, 4, 4, 4, 4)); - t->set_stylebox("disabled", "ToolButton", make_empty_stylebox(4, 4, 4, 4)); - t->set_stylebox("focus", "ToolButton", focus); - t->set_font("font", "ToolButton", default_font); + theme->set_color("font_color", "ToolButton", control_font_color); + theme->set_color("font_color_pressed", "ToolButton", control_font_color_pressed); + theme->set_color("font_color_hover", "ToolButton", control_font_color_hover); + theme->set_color("font_color_disabled", "ToolButton", Color(0.9, 0.95, 1, 0.3)); - t->set_color("font_color", "ToolButton", control_font_color); - t->set_color("font_color_pressed", "ToolButton", control_font_color_pressed); - t->set_color("font_color_hover", "ToolButton", control_font_color_hover); - t->set_color("font_color_disabled", "ToolButton", Color(0.9, 0.95, 1, 0.3)); - - t->set_constant("hseparation", "ToolButton", 3); + theme->set_constant("hseparation", "ToolButton", 3); // OptionButton @@ -311,44 +306,44 @@ void fill_default_theme(Ref<Theme> &t, const Ref<Font> &default_font, const Ref< Ref<StyleBox> sb_optbutton_disabled = sb_expand(make_stylebox(option_button_disabled_png, 4, 4, 21, 4, 6, 2, 21, 2), 2, 2, 2, 2); Ref<StyleBox> sb_optbutton_focus = sb_expand(make_stylebox(button_focus_png, 4, 4, 4, 4, 6, 2, 6, 2), 2, 2, 2, 2); - t->set_stylebox("normal", "OptionButton", sb_optbutton_normal); - t->set_stylebox("pressed", "OptionButton", sb_optbutton_pressed); - t->set_stylebox("hover", "OptionButton", sb_optbutton_hover); - t->set_stylebox("disabled", "OptionButton", sb_optbutton_disabled); - t->set_stylebox("focus", "OptionButton", sb_button_focus); + theme->set_stylebox("normal", "OptionButton", sb_optbutton_normal); + theme->set_stylebox("pressed", "OptionButton", sb_optbutton_pressed); + theme->set_stylebox("hover", "OptionButton", sb_optbutton_hover); + theme->set_stylebox("disabled", "OptionButton", sb_optbutton_disabled); + theme->set_stylebox("focus", "OptionButton", sb_button_focus); - t->set_icon("arrow", "OptionButton", make_icon(option_arrow_png)); + theme->set_icon("arrow", "OptionButton", make_icon(option_arrow_png)); - t->set_font("font", "OptionButton", default_font); + theme->set_font("font", "OptionButton", default_font); - t->set_color("font_color", "OptionButton", control_font_color); - t->set_color("font_color_pressed", "OptionButton", control_font_color_pressed); - t->set_color("font_color_hover", "OptionButton", control_font_color_hover); - t->set_color("font_color_disabled", "OptionButton", control_font_color_disabled); + theme->set_color("font_color", "OptionButton", control_font_color); + theme->set_color("font_color_pressed", "OptionButton", control_font_color_pressed); + theme->set_color("font_color_hover", "OptionButton", control_font_color_hover); + theme->set_color("font_color_disabled", "OptionButton", control_font_color_disabled); - t->set_constant("hseparation", "OptionButton", 2 * scale); - t->set_constant("arrow_margin", "OptionButton", 2 * scale); + theme->set_constant("hseparation", "OptionButton", 2 * scale); + theme->set_constant("arrow_margin", "OptionButton", 2 * scale); // MenuButton - t->set_stylebox("normal", "MenuButton", sb_button_normal); - t->set_stylebox("pressed", "MenuButton", sb_button_pressed); - t->set_stylebox("hover", "MenuButton", sb_button_pressed); - t->set_stylebox("disabled", "MenuButton", make_empty_stylebox(0, 0, 0, 0)); - t->set_stylebox("focus", "MenuButton", sb_button_focus); + theme->set_stylebox("normal", "MenuButton", sb_button_normal); + theme->set_stylebox("pressed", "MenuButton", sb_button_pressed); + theme->set_stylebox("hover", "MenuButton", sb_button_pressed); + theme->set_stylebox("disabled", "MenuButton", make_empty_stylebox(0, 0, 0, 0)); + theme->set_stylebox("focus", "MenuButton", sb_button_focus); - t->set_font("font", "MenuButton", default_font); + theme->set_font("font", "MenuButton", default_font); - t->set_color("font_color", "MenuButton", control_font_color); - t->set_color("font_color_pressed", "MenuButton", control_font_color_pressed); - t->set_color("font_color_hover", "MenuButton", control_font_color_hover); - t->set_color("font_color_disabled", "MenuButton", Color(1, 1, 1, 0.3)); + theme->set_color("font_color", "MenuButton", control_font_color); + theme->set_color("font_color_pressed", "MenuButton", control_font_color_pressed); + theme->set_color("font_color_hover", "MenuButton", control_font_color_hover); + theme->set_color("font_color_disabled", "MenuButton", Color(1, 1, 1, 0.3)); - t->set_constant("hseparation", "MenuButton", 3 * scale); + theme->set_constant("hseparation", "MenuButton", 3 * scale); // ButtonGroup - t->set_stylebox("panel", "ButtonGroup", memnew(StyleBoxEmpty)); + theme->set_stylebox("panel", "ButtonGroup", memnew(StyleBoxEmpty)); // CheckBox @@ -363,26 +358,26 @@ void fill_default_theme(Ref<Theme> &t, const Ref<Font> &default_font, const Ref< cbx_focus->set_default_margin(MARGIN_TOP, 4 * scale); cbx_focus->set_default_margin(MARGIN_BOTTOM, 5 * scale); - t->set_stylebox("normal", "CheckBox", cbx_empty); - t->set_stylebox("pressed", "CheckBox", cbx_empty); - t->set_stylebox("disabled", "CheckBox", cbx_empty); - t->set_stylebox("hover", "CheckBox", cbx_empty); - t->set_stylebox("focus", "CheckBox", cbx_focus); + theme->set_stylebox("normal", "CheckBox", cbx_empty); + theme->set_stylebox("pressed", "CheckBox", cbx_empty); + theme->set_stylebox("disabled", "CheckBox", cbx_empty); + theme->set_stylebox("hover", "CheckBox", cbx_empty); + theme->set_stylebox("focus", "CheckBox", cbx_focus); - t->set_icon("checked", "CheckBox", make_icon(checked_png)); - t->set_icon("unchecked", "CheckBox", make_icon(unchecked_png)); - t->set_icon("radio_checked", "CheckBox", make_icon(radio_checked_png)); - t->set_icon("radio_unchecked", "CheckBox", make_icon(radio_unchecked_png)); + theme->set_icon("checked", "CheckBox", make_icon(checked_png)); + theme->set_icon("unchecked", "CheckBox", make_icon(unchecked_png)); + theme->set_icon("radio_checked", "CheckBox", make_icon(radio_checked_png)); + theme->set_icon("radio_unchecked", "CheckBox", make_icon(radio_unchecked_png)); - t->set_font("font", "CheckBox", default_font); + theme->set_font("font", "CheckBox", default_font); - t->set_color("font_color", "CheckBox", control_font_color); - t->set_color("font_color_pressed", "CheckBox", control_font_color_pressed); - t->set_color("font_color_hover", "CheckBox", control_font_color_hover); - t->set_color("font_color_disabled", "CheckBox", control_font_color_disabled); + theme->set_color("font_color", "CheckBox", control_font_color); + theme->set_color("font_color_pressed", "CheckBox", control_font_color_pressed); + theme->set_color("font_color_hover", "CheckBox", control_font_color_hover); + theme->set_color("font_color_disabled", "CheckBox", control_font_color_disabled); - t->set_constant("hseparation", "CheckBox", 4 * scale); - t->set_constant("check_vadjust", "CheckBox", 0 * scale); + theme->set_constant("hseparation", "CheckBox", 4 * scale); + theme->set_constant("check_vadjust", "CheckBox", 0 * scale); // CheckButton @@ -392,168 +387,172 @@ void fill_default_theme(Ref<Theme> &t, const Ref<Font> &default_font, const Ref< cb_empty->set_default_margin(MARGIN_TOP, 4 * scale); cb_empty->set_default_margin(MARGIN_BOTTOM, 4 * scale); - t->set_stylebox("normal", "CheckButton", cb_empty); - t->set_stylebox("pressed", "CheckButton", cb_empty); - t->set_stylebox("disabled", "CheckButton", cb_empty); - t->set_stylebox("hover", "CheckButton", cb_empty); - t->set_stylebox("focus", "CheckButton", focus); + theme->set_stylebox("normal", "CheckButton", cb_empty); + theme->set_stylebox("pressed", "CheckButton", cb_empty); + theme->set_stylebox("disabled", "CheckButton", cb_empty); + theme->set_stylebox("hover", "CheckButton", cb_empty); + theme->set_stylebox("focus", "CheckButton", focus); - t->set_icon("on", "CheckButton", make_icon(toggle_on_png)); - t->set_icon("off", "CheckButton", make_icon(toggle_off_png)); + theme->set_icon("on", "CheckButton", make_icon(toggle_on_png)); + theme->set_icon("off", "CheckButton", make_icon(toggle_off_png)); - t->set_font("font", "CheckButton", default_font); + theme->set_font("font", "CheckButton", default_font); - t->set_color("font_color", "CheckButton", control_font_color); - t->set_color("font_color_pressed", "CheckButton", control_font_color_pressed); - t->set_color("font_color_hover", "CheckButton", control_font_color_hover); - t->set_color("font_color_disabled", "CheckButton", control_font_color_disabled); + theme->set_color("font_color", "CheckButton", control_font_color); + theme->set_color("font_color_pressed", "CheckButton", control_font_color_pressed); + theme->set_color("font_color_hover", "CheckButton", control_font_color_hover); + theme->set_color("font_color_disabled", "CheckButton", control_font_color_disabled); - t->set_constant("hseparation", "CheckButton", 4 * scale); - t->set_constant("check_vadjust", "CheckButton", 0 * scale); + theme->set_constant("hseparation", "CheckButton", 4 * scale); + theme->set_constant("check_vadjust", "CheckButton", 0 * scale); // Label - t->set_font("font", "Label", default_font); + theme->set_font("font", "Label", default_font); - t->set_color("font_color", "Label", Color(1, 1, 1)); - t->set_color("font_color_shadow", "Label", Color(0, 0, 0, 0)); + theme->set_color("font_color", "Label", Color(1, 1, 1)); + theme->set_color("font_color_shadow", "Label", Color(0, 0, 0, 0)); - t->set_constant("shadow_offset_x", "Label", 1 * scale); - t->set_constant("shadow_offset_y", "Label", 1 * scale); - t->set_constant("shadow_as_outline", "Label", 0 * scale); - t->set_constant("line_spacing", "Label", 3 * scale); + theme->set_constant("shadow_offset_x", "Label", 1 * scale); + theme->set_constant("shadow_offset_y", "Label", 1 * scale); + theme->set_constant("shadow_as_outline", "Label", 0 * scale); + theme->set_constant("line_spacing", "Label", 3 * scale); // LineEdit - t->set_stylebox("normal", "LineEdit", make_stylebox(line_edit_png, 5, 5, 5, 5)); - t->set_stylebox("focus", "LineEdit", focus); - t->set_stylebox("read_only", "LineEdit", make_stylebox(line_edit_disabled_png, 6, 6, 6, 6)); + theme->set_stylebox("normal", "LineEdit", make_stylebox(line_edit_png, 5, 5, 5, 5)); + theme->set_stylebox("focus", "LineEdit", focus); + theme->set_stylebox("read_only", "LineEdit", make_stylebox(line_edit_disabled_png, 6, 6, 6, 6)); - t->set_font("font", "LineEdit", default_font); + theme->set_font("font", "LineEdit", default_font); - t->set_color("font_color", "LineEdit", control_font_color); - t->set_color("font_color_selected", "LineEdit", Color(0, 0, 0)); - t->set_color("cursor_color", "LineEdit", control_font_color_hover); - t->set_color("selection_color", "LineEdit", font_color_selection); + theme->set_color("font_color", "LineEdit", control_font_color); + theme->set_color("font_color_selected", "LineEdit", Color(0, 0, 0)); + theme->set_color("cursor_color", "LineEdit", control_font_color_hover); + theme->set_color("selection_color", "LineEdit", font_color_selection); - t->set_constant("minimum_spaces", "LineEdit", 12 * scale); + theme->set_constant("minimum_spaces", "LineEdit", 12 * scale); // ProgressBar - t->set_stylebox("bg", "ProgressBar", make_stylebox(progress_bar_png, 4, 4, 4, 4, 0, 0, 0, 0)); - t->set_stylebox("fg", "ProgressBar", make_stylebox(progress_fill_png, 6, 6, 6, 6, 2, 1, 2, 1)); + theme->set_stylebox("bg", "ProgressBar", make_stylebox(progress_bar_png, 4, 4, 4, 4, 0, 0, 0, 0)); + theme->set_stylebox("fg", "ProgressBar", make_stylebox(progress_fill_png, 6, 6, 6, 6, 2, 1, 2, 1)); - t->set_font("font", "ProgressBar", default_font); + theme->set_font("font", "ProgressBar", default_font); - t->set_color("font_color", "ProgressBar", control_font_color_hover); - t->set_color("font_color_shadow", "ProgressBar", Color(0, 0, 0)); + theme->set_color("font_color", "ProgressBar", control_font_color_hover); + theme->set_color("font_color_shadow", "ProgressBar", Color(0, 0, 0)); // TextEdit - t->set_stylebox("normal", "TextEdit", make_stylebox(tree_bg_png, 3, 3, 3, 3)); - t->set_stylebox("focus", "TextEdit", focus); - t->set_stylebox("completion", "TextEdit", make_stylebox(tree_bg_png, 3, 3, 3, 3)); + theme->set_stylebox("normal", "TextEdit", make_stylebox(tree_bg_png, 3, 3, 3, 3)); + theme->set_stylebox("focus", "TextEdit", focus); + theme->set_stylebox("completion", "TextEdit", make_stylebox(tree_bg_png, 3, 3, 3, 3)); - t->set_icon("tab", "TextEdit", make_icon(tab_png)); + theme->set_icon("tab", "TextEdit", make_icon(tab_png)); - t->set_font("font", "TextEdit", default_font); + theme->set_font("font", "TextEdit", default_font); - t->set_color("background_color", "TextEdit", Color(0, 0, 0, 0)); - t->set_color("completion_background_color", "TextEdit", Color::html("2C2A32")); - t->set_color("completion_selected_color", "TextEdit", Color::html("434244")); - t->set_color("completion_existing_color", "TextEdit", Color::html("21dfdfdf")); - t->set_color("completion_scroll_color", "TextEdit", control_font_color_pressed); - t->set_color("completion_font_color", "TextEdit", Color::html("aaaaaa")); - t->set_color("font_color", "TextEdit", control_font_color); - t->set_color("font_color_selected", "TextEdit", Color(0, 0, 0)); - t->set_color("selection_color", "TextEdit", font_color_selection); - t->set_color("mark_color", "TextEdit", Color(1.0, 0.4, 0.4, 0.4)); - t->set_color("breakpoint_color", "TextEdit", Color(0.8, 0.8, 0.4, 0.2)); - t->set_color("current_line_color", "TextEdit", Color(0.25, 0.25, 0.26, 0.8)); - t->set_color("caret_color", "TextEdit", control_font_color); - t->set_color("caret_background_color", "TextEdit", Color::html("000000")); - t->set_color("symbol_color", "TextEdit", control_font_color_hover); - t->set_color("brace_mismatch_color", "TextEdit", Color(1, 0.2, 0.2)); - t->set_color("line_number_color", "TextEdit", Color::html("66aaaaaa")); - t->set_color("function_color", "TextEdit", Color::html("66a2ce")); - t->set_color("member_variable_color", "TextEdit", Color::html("e64e59")); - t->set_color("number_color", "TextEdit", Color::html("EB9532")); - t->set_color("word_highlighted_color", "TextEdit", Color(0.8, 0.9, 0.9, 0.15)); + theme->set_color("background_color", "TextEdit", Color(0, 0, 0, 0)); + theme->set_color("completion_background_color", "TextEdit", Color::html("2C2A32")); + theme->set_color("completion_selected_color", "TextEdit", Color::html("434244")); + theme->set_color("completion_existing_color", "TextEdit", Color::html("21dfdfdf")); + theme->set_color("completion_scroll_color", "TextEdit", control_font_color_pressed); + theme->set_color("completion_font_color", "TextEdit", Color::html("aaaaaa")); + theme->set_color("font_color", "TextEdit", control_font_color); + theme->set_color("font_color_selected", "TextEdit", Color(0, 0, 0)); + theme->set_color("selection_color", "TextEdit", font_color_selection); + theme->set_color("mark_color", "TextEdit", Color(1.0, 0.4, 0.4, 0.4)); + theme->set_color("breakpoint_color", "TextEdit", Color(0.8, 0.8, 0.4, 0.2)); + theme->set_color("current_line_color", "TextEdit", Color(0.25, 0.25, 0.26, 0.8)); + theme->set_color("caret_color", "TextEdit", control_font_color); + theme->set_color("caret_background_color", "TextEdit", Color::html("000000")); + theme->set_color("symbol_color", "TextEdit", control_font_color_hover); + theme->set_color("brace_mismatch_color", "TextEdit", Color(1, 0.2, 0.2)); + theme->set_color("line_number_color", "TextEdit", Color::html("66aaaaaa")); + theme->set_color("function_color", "TextEdit", Color::html("66a2ce")); + theme->set_color("member_variable_color", "TextEdit", Color::html("e64e59")); + theme->set_color("number_color", "TextEdit", Color::html("EB9532")); + theme->set_color("word_highlighted_color", "TextEdit", Color(0.8, 0.9, 0.9, 0.15)); - t->set_constant("completion_lines", "TextEdit", 7); - t->set_constant("completion_max_width", "TextEdit", 50); - t->set_constant("completion_scroll_width", "TextEdit", 3); - t->set_constant("line_spacing", "TextEdit", 4 * scale); + theme->set_constant("completion_lines", "TextEdit", 7); + theme->set_constant("completion_max_width", "TextEdit", 50); + theme->set_constant("completion_scroll_width", "TextEdit", 3); + theme->set_constant("line_spacing", "TextEdit", 4 * scale); Ref<Texture> empty_icon = memnew(ImageTexture); // HScrollBar - t->set_stylebox("scroll", "HScrollBar", make_stylebox(scroll_bg_png, 5, 5, 5, 5, 0, 0, 0, 0)); - t->set_stylebox("scroll_focus", "HScrollBar", make_stylebox(scroll_bg_png, 5, 5, 5, 5, 0, 0, 0, 0)); - t->set_stylebox("grabber", "HScrollBar", make_stylebox(scroll_grabber_png, 5, 5, 5, 5, 2, 2, 2, 2)); - t->set_stylebox("grabber_hilite", "HScrollBar", make_stylebox(scroll_grabber_hl_png, 5, 5, 5, 5, 2, 2, 2, 2)); + theme->set_stylebox("scroll", "HScrollBar", make_stylebox(scroll_bg_png, 5, 5, 5, 5, 0, 0, 0, 0)); + theme->set_stylebox("scroll_focus", "HScrollBar", make_stylebox(scroll_bg_png, 5, 5, 5, 5, 0, 0, 0, 0)); + theme->set_stylebox("grabber", "HScrollBar", make_stylebox(scroll_grabber_png, 5, 5, 5, 5, 2, 2, 2, 2)); + theme->set_stylebox("grabber_highlight", "HScrollBar", make_stylebox(scroll_grabber_hl_png, 5, 5, 5, 5, 2, 2, 2, 2)); + theme->set_stylebox("grabber_pressed", "HScrollBar", make_stylebox(scroll_grabber_pressed_png, 5, 5, 5, 5, 2, 2, 2, 2)); - t->set_icon("increment", "HScrollBar", empty_icon); - t->set_icon("increment_hilite", "HScrollBar", empty_icon); - t->set_icon("decrement", "HScrollBar", empty_icon); - t->set_icon("decrement_hilite", "HScrollBar", empty_icon); + theme->set_icon("increment", "HScrollBar", empty_icon); + theme->set_icon("increment_highlight", "HScrollBar", empty_icon); + theme->set_icon("decrement", "HScrollBar", empty_icon); + theme->set_icon("decrement_highlight", "HScrollBar", empty_icon); // VScrollBar - t->set_stylebox("scroll", "VScrollBar", make_stylebox(scroll_bg_png, 5, 5, 5, 5, 0, 0, 0, 0)); - t->set_stylebox("scroll_focus", "VScrollBar", make_stylebox(scroll_bg_png, 5, 5, 5, 5, 0, 0, 0, 0)); - t->set_stylebox("grabber", "VScrollBar", make_stylebox(scroll_grabber_png, 5, 5, 5, 5, 2, 2, 2, 2)); - t->set_stylebox("grabber_hilite", "VScrollBar", make_stylebox(scroll_grabber_hl_png, 5, 5, 5, 5, 2, 2, 2, 2)); + theme->set_stylebox("scroll", "VScrollBar", make_stylebox(scroll_bg_png, 5, 5, 5, 5, 0, 0, 0, 0)); + theme->set_stylebox("scroll_focus", "VScrollBar", make_stylebox(scroll_bg_png, 5, 5, 5, 5, 0, 0, 0, 0)); + theme->set_stylebox("grabber", "VScrollBar", make_stylebox(scroll_grabber_png, 5, 5, 5, 5, 2, 2, 2, 2)); + theme->set_stylebox("grabber_highlight", "VScrollBar", make_stylebox(scroll_grabber_hl_png, 5, 5, 5, 5, 2, 2, 2, 2)); + theme->set_stylebox("grabber_pressed", "VScrollBar", make_stylebox(scroll_grabber_pressed_png, 5, 5, 5, 5, 2, 2, 2, 2)); - t->set_icon("increment", "VScrollBar", empty_icon); - t->set_icon("increment_hilite", "VScrollBar", empty_icon); - t->set_icon("decrement", "VScrollBar", empty_icon); - t->set_icon("decrement_hilite", "VScrollBar", empty_icon); + theme->set_icon("increment", "VScrollBar", empty_icon); + theme->set_icon("increment_highlight", "VScrollBar", empty_icon); + theme->set_icon("decrement", "VScrollBar", empty_icon); + theme->set_icon("decrement_highlight", "VScrollBar", empty_icon); // HSlider - t->set_stylebox("slider", "HSlider", make_stylebox(hslider_bg_png, 4, 4, 4, 4)); - t->set_stylebox("grabber_hilite", "HSlider", make_stylebox(hslider_grabber_hl_png, 6, 6, 6, 6)); - t->set_stylebox("focus", "HSlider", focus); + theme->set_stylebox("slider", "HSlider", make_stylebox(hslider_bg_png, 4, 4, 4, 4)); + theme->set_stylebox("grabber_highlight", "HSlider", make_stylebox(hslider_grabber_hl_png, 6, 6, 6, 6)); + theme->set_stylebox("grabber_disabled", "HSlider", make_stylebox(hslider_grabber_disabled_png, 6, 6, 6, 6)); + theme->set_stylebox("focus", "HSlider", focus); - t->set_icon("grabber", "HSlider", make_icon(hslider_grabber_png)); - t->set_icon("grabber_hilite", "HSlider", make_icon(hslider_grabber_hl_png)); - t->set_icon("tick", "HSlider", make_icon(hslider_tick_png)); + theme->set_icon("grabber", "HSlider", make_icon(hslider_grabber_png)); + theme->set_icon("grabber_highlight", "HSlider", make_icon(hslider_grabber_hl_png)); + theme->set_icon("grabber_disabled", "HSlider", make_icon(hslider_grabber_disabled_png)); + theme->set_icon("tick", "HSlider", make_icon(hslider_tick_png)); // VSlider - t->set_stylebox("slider", "VSlider", make_stylebox(vslider_bg_png, 4, 4, 4, 4)); - t->set_stylebox("grabber_hilite", "VSlider", make_stylebox(vslider_grabber_hl_png, 6, 6, 6, 6)); - t->set_stylebox("focus", "HSlider", focus); + theme->set_stylebox("slider", "VSlider", make_stylebox(vslider_bg_png, 4, 4, 4, 4)); + theme->set_stylebox("grabber_highlight", "VSlider", make_stylebox(vslider_grabber_hl_png, 6, 6, 6, 6)); + theme->set_stylebox("grabber_disabled", "VSlider", make_stylebox(vslider_grabber_disabled_png, 6, 6, 6, 6)); + theme->set_stylebox("focus", "HSlider", focus); - t->set_icon("grabber", "VSlider", make_icon(vslider_grabber_png)); - t->set_icon("grabber_hilite", "VSlider", make_icon(vslider_grabber_hl_png)); - t->set_icon("tick", "VSlider", make_icon(vslider_tick_png)); + theme->set_icon("grabber", "VSlider", make_icon(vslider_grabber_png)); + theme->set_icon("grabber_highlight", "VSlider", make_icon(vslider_grabber_hl_png)); + theme->set_icon("grabber_disabled", "VSlider", make_icon(vslider_grabber_disabled_png)); + theme->set_icon("tick", "VSlider", make_icon(vslider_tick_png)); // SpinBox - t->set_icon("updown", "SpinBox", make_icon(spinbox_updown_png)); + theme->set_icon("updown", "SpinBox", make_icon(spinbox_updown_png)); // WindowDialog - Ref<StyleBoxTexture> style_pp_win = sb_expand(make_stylebox(popup_window_png, 10, 26, 10, 8), 8, 24, 8, 6); - t->set_stylebox("panel", "WindowDialog", style_pp_win); - t->set_constant("titlebar_height", "WindowDialog", 20 * scale); - t->set_constant("scaleborder_size", "WindowDialog", 4); + theme->set_stylebox("panel", "WindowDialog", sb_expand(make_stylebox(popup_window_png, 10, 26, 10, 8), 8, 24, 8, 6)); + theme->set_constant("scaleborder_size", "WindowDialog", 4 * scale); - t->set_font("title_font", "WindowDialog", large_font); - t->set_color("title_color", "WindowDialog", Color(0, 0, 0)); - t->set_constant("title_height", "WindowDialog", 18 * scale); + theme->set_font("title_font", "WindowDialog", large_font); + theme->set_color("title_color", "WindowDialog", Color(0, 0, 0)); + theme->set_constant("title_height", "WindowDialog", 20 * scale); - t->set_icon("close", "WindowDialog", make_icon(close_png)); - t->set_icon("close_hilite", "WindowDialog", make_icon(close_hl_png)); - t->set_constant("close_h_ofs", "WindowDialog", 18 * scale); - t->set_constant("close_v_ofs", "WindowDialog", 18 * scale); + theme->set_icon("close", "WindowDialog", make_icon(close_png)); + theme->set_icon("close_highlight", "WindowDialog", make_icon(close_hl_png)); + theme->set_constant("close_h_ofs", "WindowDialog", 18 * scale); + theme->set_constant("close_v_ofs", "WindowDialog", 18 * scale); // File Dialog - t->set_icon("reload", "FileDialog", make_icon(icon_reload_png)); + theme->set_icon("reload", "FileDialog", make_icon(icon_reload_png)); // Popup @@ -564,28 +563,28 @@ void fill_default_theme(Ref<Theme> &t, const Ref<Font> &default_font, const Ref< selected->set_expand_margin_size(Margin(i), 2 * scale); } - t->set_stylebox("panel", "PopupPanel", style_pp); + theme->set_stylebox("panel", "PopupPanel", style_pp); // PopupMenu - t->set_stylebox("panel", "PopupMenu", make_stylebox(popup_bg_png, 4, 4, 4, 4, 10, 10, 10, 10)); - t->set_stylebox("panel_disabled", "PopupMenu", make_stylebox(popup_bg_disabled_png, 4, 4, 4, 4)); - t->set_stylebox("hover", "PopupMenu", selected); - t->set_stylebox("separator", "PopupMenu", make_stylebox(vseparator_png, 3, 3, 3, 3)); + theme->set_stylebox("panel", "PopupMenu", make_stylebox(popup_bg_png, 4, 4, 4, 4, 10, 10, 10, 10)); + theme->set_stylebox("panel_disabled", "PopupMenu", make_stylebox(popup_bg_disabled_png, 4, 4, 4, 4)); + theme->set_stylebox("hover", "PopupMenu", selected); + theme->set_stylebox("separator", "PopupMenu", make_stylebox(vseparator_png, 3, 3, 3, 3)); - t->set_icon("checked", "PopupMenu", make_icon(checked_png)); - t->set_icon("unchecked", "PopupMenu", make_icon(unchecked_png)); - t->set_icon("submenu", "PopupMenu", make_icon(submenu_png)); + theme->set_icon("checked", "PopupMenu", make_icon(checked_png)); + theme->set_icon("unchecked", "PopupMenu", make_icon(unchecked_png)); + theme->set_icon("submenu", "PopupMenu", make_icon(submenu_png)); - t->set_font("font", "PopupMenu", default_font); + theme->set_font("font", "PopupMenu", default_font); - t->set_color("font_color", "PopupMenu", control_font_color); - t->set_color("font_color_accel", "PopupMenu", Color(0.7, 0.7, 0.7, 0.8)); - t->set_color("font_color_disabled", "PopupMenu", Color(0.4, 0.4, 0.4, 0.8)); - t->set_color("font_color_hover", "PopupMenu", control_font_color); + theme->set_color("font_color", "PopupMenu", control_font_color); + theme->set_color("font_color_accel", "PopupMenu", Color(0.7, 0.7, 0.7, 0.8)); + theme->set_color("font_color_disabled", "PopupMenu", Color(0.4, 0.4, 0.4, 0.8)); + theme->set_color("font_color_hover", "PopupMenu", control_font_color); - t->set_constant("hseparation", "PopupMenu", 4 * scale); - t->set_constant("vseparation", "PopupMenu", 4 * scale); + theme->set_constant("hseparation", "PopupMenu", 4 * scale); + theme->set_constant("vseparation", "PopupMenu", 4 * scale); // GraphNode @@ -600,86 +599,90 @@ void fill_default_theme(Ref<Theme> &t, const Ref<Font> &default_font, const Ref< //graphsb->set_expand_margin_size(MARGIN_LEFT,10); //graphsb->set_expand_margin_size(MARGIN_RIGHT,10); - t->set_stylebox("frame", "GraphNode", graphsb); - t->set_stylebox("selectedframe", "GraphNode", graphsbselected); - t->set_stylebox("defaultframe", "GraphNode", graphsbdefault); - t->set_stylebox("defaultfocus", "GraphNode", graphsbdeffocus); - t->set_stylebox("comment", "GraphNode", graphsbcomment); - t->set_stylebox("commentfocus", "GraphNode", graphsbcommentselected); - t->set_stylebox("breakpoint", "GraphNode", graph_bpoint); - t->set_stylebox("position", "GraphNode", graph_position); - t->set_constant("separation", "GraphNode", 1 * scale); - t->set_icon("port", "GraphNode", make_icon(graph_port_png)); - t->set_icon("close", "GraphNode", make_icon(graph_node_close_png)); - t->set_icon("resizer", "GraphNode", make_icon(window_resizer_png)); - t->set_font("title_font", "GraphNode", default_font); - t->set_color("title_color", "GraphNode", Color(0, 0, 0, 1)); - t->set_constant("title_offset", "GraphNode", 20 * scale); - t->set_constant("close_offset", "GraphNode", 18 * scale); - t->set_constant("port_offset", "GraphNode", 3 * scale); + theme->set_stylebox("frame", "GraphNode", graphsb); + theme->set_stylebox("selectedframe", "GraphNode", graphsbselected); + theme->set_stylebox("defaultframe", "GraphNode", graphsbdefault); + theme->set_stylebox("defaultfocus", "GraphNode", graphsbdeffocus); + theme->set_stylebox("comment", "GraphNode", graphsbcomment); + theme->set_stylebox("commentfocus", "GraphNode", graphsbcommentselected); + theme->set_stylebox("breakpoint", "GraphNode", graph_bpoint); + theme->set_stylebox("position", "GraphNode", graph_position); + theme->set_constant("separation", "GraphNode", 1 * scale); + theme->set_icon("port", "GraphNode", make_icon(graph_port_png)); + theme->set_icon("close", "GraphNode", make_icon(graph_node_close_png)); + theme->set_icon("resizer", "GraphNode", make_icon(window_resizer_png)); + theme->set_font("title_font", "GraphNode", default_font); + theme->set_color("title_color", "GraphNode", Color(0, 0, 0, 1)); + theme->set_constant("title_offset", "GraphNode", 20 * scale); + theme->set_constant("close_offset", "GraphNode", 18 * scale); + theme->set_constant("port_offset", "GraphNode", 3 * scale); // Tree Ref<StyleBoxTexture> tree_selected = make_stylebox(selection_png, 4, 4, 4, 4, 8, 0, 8, 0); Ref<StyleBoxTexture> tree_selected_oof = make_stylebox(selection_oof_png, 4, 4, 4, 4, 8, 0, 8, 0); - t->set_stylebox("bg", "Tree", make_stylebox(tree_bg_png, 4, 4, 4, 5)); - t->set_stylebox("bg_focus", "Tree", focus); - t->set_stylebox("selected", "Tree", tree_selected_oof); - t->set_stylebox("selected_focus", "Tree", tree_selected); - t->set_stylebox("cursor", "Tree", focus); - t->set_stylebox("cursor_unfocused", "Tree", focus); - t->set_stylebox("button_pressed", "Tree", make_stylebox(button_pressed_png, 4, 4, 4, 4)); - t->set_stylebox("title_button_normal", "Tree", make_stylebox(tree_title_png, 4, 4, 4, 4)); - t->set_stylebox("title_button_pressed", "Tree", make_stylebox(tree_title_pressed_png, 4, 4, 4, 4)); - t->set_stylebox("title_button_hover", "Tree", make_stylebox(tree_title_png, 4, 4, 4, 4)); + theme->set_stylebox("bg", "Tree", make_stylebox(tree_bg_png, 4, 4, 4, 5)); + theme->set_stylebox("bg_focus", "Tree", focus); + theme->set_stylebox("selected", "Tree", tree_selected_oof); + theme->set_stylebox("selected_focus", "Tree", tree_selected); + theme->set_stylebox("cursor", "Tree", focus); + theme->set_stylebox("cursor_unfocused", "Tree", focus); + theme->set_stylebox("button_pressed", "Tree", make_stylebox(button_pressed_png, 4, 4, 4, 4)); + theme->set_stylebox("title_button_normal", "Tree", make_stylebox(tree_title_png, 4, 4, 4, 4)); + theme->set_stylebox("title_button_pressed", "Tree", make_stylebox(tree_title_pressed_png, 4, 4, 4, 4)); + theme->set_stylebox("title_button_hover", "Tree", make_stylebox(tree_title_png, 4, 4, 4, 4)); + theme->set_stylebox("custom_button", "Tree", sb_button_normal); + theme->set_stylebox("custom_button_pressed", "Tree", sb_button_pressed); + theme->set_stylebox("custom_button_hover", "Tree", sb_button_hover); - t->set_icon("checked", "Tree", make_icon(checked_png)); - t->set_icon("unchecked", "Tree", make_icon(unchecked_png)); - t->set_icon("updown", "Tree", make_icon(updown_png)); - t->set_icon("select_arrow", "Tree", make_icon(dropdown_png)); - t->set_icon("arrow", "Tree", make_icon(arrow_down_png)); - t->set_icon("arrow_collapsed", "Tree", make_icon(arrow_right_png)); + theme->set_icon("checked", "Tree", make_icon(checked_png)); + theme->set_icon("unchecked", "Tree", make_icon(unchecked_png)); + theme->set_icon("updown", "Tree", make_icon(updown_png)); + theme->set_icon("select_arrow", "Tree", make_icon(dropdown_png)); + theme->set_icon("arrow", "Tree", make_icon(arrow_down_png)); + theme->set_icon("arrow_collapsed", "Tree", make_icon(arrow_right_png)); - t->set_font("title_button_font", "Tree", default_font); - t->set_font("font", "Tree", default_font); + theme->set_font("title_button_font", "Tree", default_font); + theme->set_font("font", "Tree", default_font); - t->set_color("title_button_color", "Tree", control_font_color); - t->set_color("font_color", "Tree", control_font_color_low); - t->set_color("font_color_selected", "Tree", control_font_color_pressed); - t->set_color("selection_color", "Tree", Color(0.1, 0.1, 1, 0.8)); - t->set_color("cursor_color", "Tree", Color(0, 0, 0)); - t->set_color("guide_color", "Tree", Color(0, 0, 0, 0.1)); - t->set_color("drop_position_color", "Tree", Color(1, 0.3, 0.2)); - t->set_color("relationship_line_color", "Tree", Color::html("464646")); + theme->set_color("title_button_color", "Tree", control_font_color); + theme->set_color("font_color", "Tree", control_font_color_low); + theme->set_color("font_color_selected", "Tree", control_font_color_pressed); + theme->set_color("selection_color", "Tree", Color(0.1, 0.1, 1, 0.8)); + theme->set_color("cursor_color", "Tree", Color(0, 0, 0)); + theme->set_color("guide_color", "Tree", Color(0, 0, 0, 0.1)); + theme->set_color("drop_position_color", "Tree", Color(1, 0.3, 0.2)); + theme->set_color("relationship_line_color", "Tree", Color::html("464646")); + theme->set_color("custom_button_font_highlight", "Tree", control_font_color_hover); - t->set_constant("hseparation", "Tree", 4 * scale); - t->set_constant("vseparation", "Tree", 4 * scale); - t->set_constant("guide_width", "Tree", 2 * scale); - t->set_constant("item_margin", "Tree", 12 * scale); - t->set_constant("button_margin", "Tree", 4 * scale); - t->set_constant("draw_relationship_lines", "Tree", 0); - t->set_constant("scroll_border", "Tree", 4); - t->set_constant("scroll_speed", "Tree", 12); + theme->set_constant("hseparation", "Tree", 4 * scale); + theme->set_constant("vseparation", "Tree", 4 * scale); + theme->set_constant("guide_width", "Tree", 2 * scale); + theme->set_constant("item_margin", "Tree", 12 * scale); + theme->set_constant("button_margin", "Tree", 4 * scale); + theme->set_constant("draw_relationship_lines", "Tree", 0); + theme->set_constant("scroll_border", "Tree", 4); + theme->set_constant("scroll_speed", "Tree", 12); // ItemList Ref<StyleBoxTexture> item_selected = make_stylebox(selection_png, 4, 4, 4, 4, 8, 2, 8, 2); Ref<StyleBoxTexture> item_selected_oof = make_stylebox(selection_oof_png, 4, 4, 4, 4, 8, 2, 8, 2); - t->set_stylebox("bg", "ItemList", make_stylebox(tree_bg_png, 4, 4, 4, 5)); - t->set_stylebox("bg_focus", "ItemList", focus); - t->set_constant("hseparation", "ItemList", 4); - t->set_constant("vseparation", "ItemList", 2); - t->set_constant("icon_margin", "ItemList", 4); - t->set_constant("line_separation", "ItemList", 2 * scale); - t->set_font("font", "ItemList", default_font); - t->set_color("font_color", "ItemList", control_font_color_lower); - t->set_color("font_color_selected", "ItemList", control_font_color_pressed); - t->set_color("guide_color", "ItemList", Color(0, 0, 0, 0.1)); - t->set_stylebox("selected", "ItemList", item_selected_oof); - t->set_stylebox("selected_focus", "ItemList", item_selected); - t->set_stylebox("cursor", "ItemList", focus); - t->set_stylebox("cursor_unfocused", "ItemList", focus); + theme->set_stylebox("bg", "ItemList", make_stylebox(tree_bg_png, 4, 4, 4, 5)); + theme->set_stylebox("bg_focus", "ItemList", focus); + theme->set_constant("hseparation", "ItemList", 4); + theme->set_constant("vseparation", "ItemList", 2); + theme->set_constant("icon_margin", "ItemList", 4); + theme->set_constant("line_separation", "ItemList", 2 * scale); + theme->set_font("font", "ItemList", default_font); + theme->set_color("font_color", "ItemList", control_font_color_lower); + theme->set_color("font_color_selected", "ItemList", control_font_color_pressed); + theme->set_color("guide_color", "ItemList", Color(0, 0, 0, 0.1)); + theme->set_stylebox("selected", "ItemList", item_selected_oof); + theme->set_stylebox("selected_focus", "ItemList", item_selected); + theme->set_stylebox("cursor", "ItemList", focus); + theme->set_stylebox("cursor_unfocused", "ItemList", focus); // TabContainer @@ -688,90 +691,88 @@ void fill_default_theme(Ref<Theme> &t, const Ref<Font> &default_font, const Ref< tc_sb->set_expand_margin_size(MARGIN_TOP, 2 * scale); tc_sb->set_default_margin(MARGIN_TOP, 8 * scale); - t->set_stylebox("tab_fg", "TabContainer", sb_expand(make_stylebox(tab_current_png, 4, 4, 4, 1, 16, 4, 16, 4), 2, 2, 2, 2)); - t->set_stylebox("tab_bg", "TabContainer", sb_expand(make_stylebox(tab_behind_png, 5, 5, 5, 1, 16, 6, 16, 4), 3, 0, 3, 3)); - t->set_stylebox("tab_disabled", "TabContainer", sb_expand(make_stylebox(tab_disabled_png, 5, 5, 5, 1, 16, 6, 16, 4), 3, 0, 3, 3)); - t->set_stylebox("panel", "TabContainer", tc_sb); + theme->set_stylebox("tab_fg", "TabContainer", sb_expand(make_stylebox(tab_current_png, 4, 4, 4, 1, 16, 4, 16, 4), 2, 2, 2, 2)); + theme->set_stylebox("tab_bg", "TabContainer", sb_expand(make_stylebox(tab_behind_png, 5, 5, 5, 1, 16, 6, 16, 4), 3, 0, 3, 3)); + theme->set_stylebox("panel", "TabContainer", tc_sb); - t->set_icon("increment", "TabContainer", make_icon(scroll_button_right_png)); - t->set_icon("increment_hilite", "TabContainer", make_icon(scroll_button_right_hl_png)); - t->set_icon("decrement", "TabContainer", make_icon(scroll_button_left_png)); - t->set_icon("decrement_hilite", "TabContainer", make_icon(scroll_button_left_hl_png)); - t->set_icon("menu", "TabContainer", make_icon(tab_menu_png)); - t->set_icon("menu_hilite", "TabContainer", make_icon(tab_menu_hl_png)); + theme->set_icon("increment", "TabContainer", make_icon(scroll_button_right_png)); + theme->set_icon("increment_highlight", "TabContainer", make_icon(scroll_button_right_hl_png)); + theme->set_icon("decrement", "TabContainer", make_icon(scroll_button_left_png)); + theme->set_icon("decrement_highlight", "TabContainer", make_icon(scroll_button_left_hl_png)); + theme->set_icon("menu", "TabContainer", make_icon(tab_menu_png)); + theme->set_icon("menu_highlight", "TabContainer", make_icon(tab_menu_hl_png)); - t->set_font("font", "TabContainer", default_font); + theme->set_font("font", "TabContainer", default_font); - t->set_color("font_color_fg", "TabContainer", control_font_color_hover); - t->set_color("font_color_bg", "TabContainer", control_font_color_low); - t->set_color("font_color_disabled", "TabContainer", control_font_color_disabled); + theme->set_color("font_color_fg", "TabContainer", control_font_color_hover); + theme->set_color("font_color_bg", "TabContainer", control_font_color_low); + theme->set_color("font_color_disabled", "TabContainer", control_font_color_disabled); - t->set_constant("side_margin", "TabContainer", 8 * scale); - t->set_constant("top_margin", "TabContainer", 24 * scale); - t->set_constant("label_valign_fg", "TabContainer", 0 * scale); - t->set_constant("label_valign_bg", "TabContainer", 2 * scale); - t->set_constant("hseparation", "TabContainer", 4 * scale); + theme->set_constant("side_margin", "TabContainer", 8 * scale); + theme->set_constant("top_margin", "TabContainer", 24 * scale); + theme->set_constant("label_valign_fg", "TabContainer", 0 * scale); + theme->set_constant("label_valign_bg", "TabContainer", 2 * scale); + theme->set_constant("hseparation", "TabContainer", 4 * scale); // Tabs - t->set_stylebox("tab_fg", "Tabs", sb_expand(make_stylebox(tab_current_png, 4, 3, 4, 1, 16, 3, 16, 2), 2, 2, 2, 2)); - t->set_stylebox("tab_bg", "Tabs", sb_expand(make_stylebox(tab_behind_png, 5, 4, 5, 1, 16, 5, 16, 2), 3, 3, 3, 3)); - t->set_stylebox("tab_disabled", "Tabs", sb_expand(make_stylebox(tab_disabled_png, 5, 4, 5, 1, 16, 5, 16, 2), 3, 3, 3, 3)); - t->set_stylebox("panel", "Tabs", tc_sb); - t->set_stylebox("button_pressed", "Tabs", make_stylebox(button_pressed_png, 4, 4, 4, 4)); - t->set_stylebox("button", "Tabs", make_stylebox(button_normal_png, 4, 4, 4, 4)); + theme->set_stylebox("tab_fg", "Tabs", sb_expand(make_stylebox(tab_current_png, 4, 3, 4, 1, 16, 3, 16, 2), 2, 2, 2, 2)); + theme->set_stylebox("tab_bg", "Tabs", sb_expand(make_stylebox(tab_behind_png, 5, 4, 5, 1, 16, 5, 16, 2), 3, 3, 3, 3)); + theme->set_stylebox("panel", "Tabs", tc_sb); + theme->set_stylebox("button_pressed", "Tabs", make_stylebox(button_pressed_png, 4, 4, 4, 4)); + theme->set_stylebox("button", "Tabs", make_stylebox(button_normal_png, 4, 4, 4, 4)); - t->set_icon("increment", "Tabs", make_icon(scroll_button_right_png)); - t->set_icon("increment_hilite", "Tabs", make_icon(scroll_button_right_hl_png)); - t->set_icon("decrement", "Tabs", make_icon(scroll_button_left_png)); - t->set_icon("decrement_hilite", "Tabs", make_icon(scroll_button_left_hl_png)); - t->set_icon("close", "Tabs", make_icon(tab_close_png)); + theme->set_icon("increment", "Tabs", make_icon(scroll_button_right_png)); + theme->set_icon("increment_highlight", "Tabs", make_icon(scroll_button_right_hl_png)); + theme->set_icon("decrement", "Tabs", make_icon(scroll_button_left_png)); + theme->set_icon("decrement_highlight", "Tabs", make_icon(scroll_button_left_hl_png)); + theme->set_icon("close", "Tabs", make_icon(tab_close_png)); - t->set_font("font", "Tabs", default_font); + theme->set_font("font", "Tabs", default_font); - t->set_color("font_color_fg", "Tabs", control_font_color_hover); - t->set_color("font_color_bg", "Tabs", control_font_color_low); - t->set_color("font_color_disabled", "Tabs", control_font_color_disabled); + theme->set_color("font_color_fg", "Tabs", control_font_color_hover); + theme->set_color("font_color_bg", "Tabs", control_font_color_low); + theme->set_color("font_color_disabled", "Tabs", control_font_color_disabled); - t->set_constant("top_margin", "Tabs", 24 * scale); - t->set_constant("label_valign_fg", "Tabs", 0 * scale); - t->set_constant("label_valign_bg", "Tabs", 2 * scale); - t->set_constant("hseparation", "Tabs", 4 * scale); + theme->set_constant("top_margin", "Tabs", 24 * scale); + theme->set_constant("label_valign_fg", "Tabs", 0 * scale); + theme->set_constant("label_valign_bg", "Tabs", 2 * scale); + theme->set_constant("hseparation", "Tabs", 4 * scale); // Separators - t->set_stylebox("separator", "HSeparator", make_stylebox(vseparator_png, 3, 3, 3, 3)); - t->set_stylebox("separator", "VSeparator", make_stylebox(hseparator_png, 3, 3, 3, 3)); + theme->set_stylebox("separator", "HSeparator", make_stylebox(vseparator_png, 3, 3, 3, 3)); + theme->set_stylebox("separator", "VSeparator", make_stylebox(hseparator_png, 3, 3, 3, 3)); - t->set_icon("close", "Icons", make_icon(icon_close_png)); - t->set_font("normal", "Fonts", default_font); - t->set_font("large", "Fonts", large_font); + theme->set_icon("close", "Icons", make_icon(icon_close_png)); + theme->set_font("normal", "Fonts", default_font); + theme->set_font("large", "Fonts", large_font); - t->set_constant("separation", "HSeparator", 4 * scale); - t->set_constant("separation", "VSeparator", 4 * scale); + theme->set_constant("separation", "HSeparator", 4 * scale); + theme->set_constant("separation", "VSeparator", 4 * scale); // Dialogs - t->set_constant("margin", "Dialogs", 8 * scale); - t->set_constant("button_margin", "Dialogs", 32 * scale); + theme->set_constant("margin", "Dialogs", 8 * scale); + theme->set_constant("button_margin", "Dialogs", 32 * scale); // FileDialog - t->set_icon("folder", "FileDialog", make_icon(icon_folder_png)); - t->set_color("files_disabled", "FileDialog", Color(0, 0, 0, 0.7)); + theme->set_icon("folder", "FileDialog", make_icon(icon_folder_png)); + theme->set_color("files_disabled", "FileDialog", Color(0, 0, 0, 0.7)); // colorPicker - t->set_constant("value_height", "ColorPicker", 23 * scale); - t->set_constant("value_width", "ColorPicker", 50 * scale); - t->set_constant("color_width", "ColorPicker", 100 * scale); - t->set_constant("label_width", "ColorPicker", 20 * scale); - t->set_constant("hseparator", "ColorPicker", 4 * scale); + theme->set_constant("margin", "ColorPicker", 4 * scale); + theme->set_constant("sv_width", "ColorPicker", 256 * scale); + theme->set_constant("sv_height", "ColorPicker", 256 * scale); + theme->set_constant("h_width", "ColorPicker", 30 * scale); + theme->set_constant("label_width", "ColorPicker", 10 * scale); - t->set_icon("screen_picker", "ColorPicker", make_icon(icon_color_pick_png)); - t->set_icon("add_preset", "ColorPicker", make_icon(icon_add_png)); - t->set_icon("color_hue", "ColorPicker", make_icon(color_picker_hue_png)); - t->set_icon("color_sample", "ColorPicker", make_icon(color_picker_sample_png)); + theme->set_icon("screen_picker", "ColorPicker", make_icon(icon_color_pick_png)); + theme->set_icon("add_preset", "ColorPicker", make_icon(icon_add_png)); + theme->set_icon("color_hue", "ColorPicker", make_icon(color_picker_hue_png)); + theme->set_icon("color_sample", "ColorPicker", make_icon(color_picker_sample_png)); // TooltipPanel @@ -779,111 +780,111 @@ void fill_default_theme(Ref<Theme> &t, const Ref<Font> &default_font, const Ref< for (int i = 0; i < 4; i++) style_tt->set_expand_margin_size((Margin)i, 4 * scale); - t->set_stylebox("panel", "TooltipPanel", style_tt); + theme->set_stylebox("panel", "TooltipPanel", style_tt); - t->set_font("font", "TooltipLabel", default_font); + theme->set_font("font", "TooltipLabel", default_font); - t->set_color("font_color", "TooltipLabel", Color(0, 0, 0)); - t->set_color("font_color_shadow", "TooltipLabel", Color(0, 0, 0, 0.1)); + theme->set_color("font_color", "TooltipLabel", Color(0, 0, 0)); + theme->set_color("font_color_shadow", "TooltipLabel", Color(0, 0, 0, 0.1)); - t->set_constant("shadow_offset_x", "TooltipLabel", 1); - t->set_constant("shadow_offset_y", "TooltipLabel", 1); + theme->set_constant("shadow_offset_x", "TooltipLabel", 1); + theme->set_constant("shadow_offset_y", "TooltipLabel", 1); // RichTextLabel - t->set_stylebox("focus", "RichTextLabel", focus); + theme->set_stylebox("focus", "RichTextLabel", focus); - t->set_font("normal_font", "RichTextLabel", default_font); - t->set_font("bold_font", "RichTextLabel", default_font); - t->set_font("italics_font", "RichTextLabel", default_font); - t->set_font("bold_italics_font", "RichTextLabel", default_font); - t->set_font("mono_font", "RichTextLabel", default_font); + theme->set_font("normal_font", "RichTextLabel", default_font); + theme->set_font("bold_font", "RichTextLabel", default_font); + theme->set_font("italics_font", "RichTextLabel", default_font); + theme->set_font("bold_italics_font", "RichTextLabel", default_font); + theme->set_font("mono_font", "RichTextLabel", default_font); - t->set_color("default_color", "RichTextLabel", control_font_color); - t->set_color("font_color_selected", "RichTextLabel", font_color_selection); - t->set_color("selection_color", "RichTextLabel", Color(0.1, 0.1, 1, 0.8)); + theme->set_color("default_color", "RichTextLabel", control_font_color); + theme->set_color("font_color_selected", "RichTextLabel", font_color_selection); + theme->set_color("selection_color", "RichTextLabel", Color(0.1, 0.1, 1, 0.8)); - t->set_constant("line_separation", "RichTextLabel", 1 * scale); - t->set_constant("table_hseparation", "RichTextLabel", 3 * scale); - t->set_constant("table_vseparation", "RichTextLabel", 3 * scale); + theme->set_constant("line_separation", "RichTextLabel", 1 * scale); + theme->set_constant("table_hseparation", "RichTextLabel", 3 * scale); + theme->set_constant("table_vseparation", "RichTextLabel", 3 * scale); // Containers - t->set_stylebox("bg", "VSplitContainer", make_stylebox(vsplit_bg_png, 1, 1, 1, 1)); - t->set_stylebox("bg", "HSplitContainer", make_stylebox(hsplit_bg_png, 1, 1, 1, 1)); + theme->set_stylebox("bg", "VSplitContainer", make_stylebox(vsplit_bg_png, 1, 1, 1, 1)); + theme->set_stylebox("bg", "HSplitContainer", make_stylebox(hsplit_bg_png, 1, 1, 1, 1)); - t->set_icon("grabber", "VSplitContainer", make_icon(vsplitter_png)); - t->set_icon("grabber", "HSplitContainer", make_icon(hsplitter_png)); + theme->set_icon("grabber", "VSplitContainer", make_icon(vsplitter_png)); + theme->set_icon("grabber", "HSplitContainer", make_icon(hsplitter_png)); - t->set_constant("separation", "HBoxContainer", 4 * scale); - t->set_constant("separation", "VBoxContainer", 4 * scale); - t->set_constant("margin_left", "MarginContainer", 8 * scale); - t->set_constant("margin_top", "MarginContainer", 0 * scale); - t->set_constant("margin_right", "MarginContainer", 0 * scale); - t->set_constant("margin_bottom", "MarginContainer", 0 * scale); - t->set_constant("hseparation", "GridContainer", 4 * scale); - t->set_constant("vseparation", "GridContainer", 4 * scale); - t->set_constant("separation", "HSplitContainer", 12 * scale); - t->set_constant("separation", "VSplitContainer", 12 * scale); - t->set_constant("autohide", "HSplitContainer", 1 * scale); - t->set_constant("autohide", "VSplitContainer", 1 * scale); + theme->set_constant("separation", "HBoxContainer", 4 * scale); + theme->set_constant("separation", "VBoxContainer", 4 * scale); + theme->set_constant("margin_left", "MarginContainer", 8 * scale); + theme->set_constant("margin_top", "MarginContainer", 0 * scale); + theme->set_constant("margin_right", "MarginContainer", 0 * scale); + theme->set_constant("margin_bottom", "MarginContainer", 0 * scale); + theme->set_constant("hseparation", "GridContainer", 4 * scale); + theme->set_constant("vseparation", "GridContainer", 4 * scale); + theme->set_constant("separation", "HSplitContainer", 12 * scale); + theme->set_constant("separation", "VSplitContainer", 12 * scale); + theme->set_constant("autohide", "HSplitContainer", 1 * scale); + theme->set_constant("autohide", "VSplitContainer", 1 * scale); // HButtonArray - t->set_stylebox("normal", "HButtonArray", sb_button_normal); - t->set_stylebox("selected", "HButtonArray", sb_button_pressed); - t->set_stylebox("hover", "HButtonArray", sb_button_hover); + theme->set_stylebox("normal", "HButtonArray", sb_button_normal); + theme->set_stylebox("selected", "HButtonArray", sb_button_pressed); + theme->set_stylebox("hover", "HButtonArray", sb_button_hover); - t->set_font("font", "HButtonArray", default_font); - t->set_font("font_selected", "HButtonArray", default_font); + theme->set_font("font", "HButtonArray", default_font); + theme->set_font("font_selected", "HButtonArray", default_font); - t->set_color("font_color", "HButtonArray", control_font_color_low); - t->set_color("font_color_selected", "HButtonArray", control_font_color_hover); + theme->set_color("font_color", "HButtonArray", control_font_color_low); + theme->set_color("font_color_selected", "HButtonArray", control_font_color_hover); - t->set_constant("icon_separator", "HButtonArray", 2 * scale); - t->set_constant("button_separator", "HButtonArray", 4 * scale); + theme->set_constant("icon_separator", "HButtonArray", 2 * scale); + theme->set_constant("button_separator", "HButtonArray", 4 * scale); - t->set_stylebox("focus", "HButtonArray", focus); + theme->set_stylebox("focus", "HButtonArray", focus); // VButtonArray - t->set_stylebox("normal", "VButtonArray", sb_button_normal); - t->set_stylebox("selected", "VButtonArray", sb_button_pressed); - t->set_stylebox("hover", "VButtonArray", sb_button_hover); + theme->set_stylebox("normal", "VButtonArray", sb_button_normal); + theme->set_stylebox("selected", "VButtonArray", sb_button_pressed); + theme->set_stylebox("hover", "VButtonArray", sb_button_hover); - t->set_font("font", "VButtonArray", default_font); - t->set_font("font_selected", "VButtonArray", default_font); + theme->set_font("font", "VButtonArray", default_font); + theme->set_font("font_selected", "VButtonArray", default_font); - t->set_color("font_color", "VButtonArray", control_font_color_low); - t->set_color("font_color_selected", "VButtonArray", control_font_color_hover); + theme->set_color("font_color", "VButtonArray", control_font_color_low); + theme->set_color("font_color_selected", "VButtonArray", control_font_color_hover); - t->set_constant("icon_separator", "VButtonArray", 2 * scale); - t->set_constant("button_separator", "VButtonArray", 4 * scale); + theme->set_constant("icon_separator", "VButtonArray", 2 * scale); + theme->set_constant("button_separator", "VButtonArray", 4 * scale); - t->set_stylebox("focus", "VButtonArray", focus); + theme->set_stylebox("focus", "VButtonArray", focus); // ReferenceRect Ref<StyleBoxTexture> ttnc = make_stylebox(full_panel_bg_png, 8, 8, 8, 8); ttnc->set_draw_center(false); - t->set_stylebox("border", "ReferenceRect", make_stylebox(reference_border_png, 4, 4, 4, 4)); - t->set_stylebox("panelnc", "Panel", ttnc); - t->set_stylebox("panelf", "Panel", tc_sb); + theme->set_stylebox("border", "ReferenceRect", make_stylebox(reference_border_png, 4, 4, 4, 4)); + theme->set_stylebox("panelnc", "Panel", ttnc); + theme->set_stylebox("panelf", "Panel", tc_sb); Ref<StyleBoxTexture> sb_pc = make_stylebox(tab_container_bg_png, 4, 4, 4, 4, 7, 7, 7, 7); - t->set_stylebox("panel", "PanelContainer", sb_pc); + theme->set_stylebox("panel", "PanelContainer", sb_pc); - t->set_icon("minus", "GraphEdit", make_icon(icon_zoom_less_png)); - t->set_icon("reset", "GraphEdit", make_icon(icon_zoom_reset_png)); - t->set_icon("more", "GraphEdit", make_icon(icon_zoom_more_png)); - t->set_icon("snap", "GraphEdit", make_icon(icon_snap_png)); - t->set_stylebox("bg", "GraphEdit", make_stylebox(tree_bg_png, 4, 4, 4, 5)); - t->set_color("grid_minor", "GraphEdit", Color(1, 1, 1, 0.05)); - t->set_color("grid_major", "GraphEdit", Color(1, 1, 1, 0.2)); - t->set_constant("bezier_len_pos", "GraphEdit", 80 * scale); - t->set_constant("bezier_len_neg", "GraphEdit", 160 * scale); + theme->set_icon("minus", "GraphEdit", make_icon(icon_zoom_less_png)); + theme->set_icon("reset", "GraphEdit", make_icon(icon_zoom_reset_png)); + theme->set_icon("more", "GraphEdit", make_icon(icon_zoom_more_png)); + theme->set_icon("snap", "GraphEdit", make_icon(icon_snap_png)); + theme->set_stylebox("bg", "GraphEdit", make_stylebox(tree_bg_png, 4, 4, 4, 5)); + theme->set_color("grid_minor", "GraphEdit", Color(1, 1, 1, 0.05)); + theme->set_color("grid_major", "GraphEdit", Color(1, 1, 1, 0.2)); + theme->set_constant("bezier_len_pos", "GraphEdit", 80 * scale); + theme->set_constant("bezier_len_neg", "GraphEdit", 160 * scale); - t->set_icon("logo", "Icons", make_icon(logo_png)); + theme->set_icon("logo", "Icons", make_icon(logo_png)); // Theme diff --git a/scene/resources/default_theme/default_theme.h b/scene/resources/default_theme/default_theme.h index fc557e427..6fd57b6f2 100644 --- a/scene/resources/default_theme/default_theme.h +++ b/scene/resources/default_theme/default_theme.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/default_theme/hslider_grabber_disabled.png b/scene/resources/default_theme/hslider_grabber_disabled.png Binary files differnew file mode 100644 index 000000000..0d75182b8 --- /dev/null +++ b/scene/resources/default_theme/hslider_grabber_disabled.png diff --git a/scene/resources/default_theme/make_header.py b/scene/resources/default_theme/make_header.py index 03c2c9be4..db449f941 100755 --- a/scene/resources/default_theme/make_header.py +++ b/scene/resources/default_theme/make_header.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python import os import glob @@ -10,21 +11,17 @@ f = open("theme_data.h", "wb") f.write("// THIS FILE HAS BEEN AUTOGENERATED, DON'T EDIT!!\n") -f.write("\n\n") - # Generate png image block +f.write("\n// png image block\n"); pixmaps = glob.glob("*.png") - pixmaps.sort() -f.write("\n\n\n") - for x in pixmaps: var_str = x[:-4] + "_png" - f.write("static const unsigned char " + var_str + "[]={\n") + f.write("\nstatic const unsigned char " + var_str + "[] = {\n\t") pngf = open(x, "rb") @@ -33,24 +30,22 @@ for x in pixmaps: f.write(hex(ord(b))) b = pngf.read(1) if (len(b) == 1): - f.write(",") + f.write(", ") - f.write("\n};\n\n\n") + f.write("\n};\n") pngf.close() # Generate shaders block +f.write("\n// shaders block\n"); shaders = glob.glob("*.gsl") - shaders.sort() -f.write("\n\n\n") - for x in shaders: var_str = x[:-4] + "_shader_code" - f.write("static const char *" + var_str + "=\n") + f.write("\nstatic const char *" + var_str + " = \n") sf = open(x, "rb") @@ -65,7 +60,7 @@ for x in shaders: if (b != ""): f.write("\"\n") - f.write("\";\n\n\n") + f.write("\";\n") sf.close() f.close() diff --git a/scene/resources/default_theme/scroll_grabber_pressed.png b/scene/resources/default_theme/scroll_grabber_pressed.png Binary files differnew file mode 100644 index 000000000..a46d242dd --- /dev/null +++ b/scene/resources/default_theme/scroll_grabber_pressed.png diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h index 394cfaf42..bed4bdb76 100644 --- a/scene/resources/default_theme/theme_data.h +++ b/scene/resources/default_theme/theme_data.h @@ -1,578 +1,469 @@ -// THIS FILE HAS BEEN AUTOGENERATED, DONT EDIT!! +// THIS FILE HAS BEEN AUTOGENERATED, DON'T EDIT!! +// png image block - - - -static const unsigned char arrow_down_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0xc,0x8,0x6,0x0,0x0,0x0,0x56,0x75,0x5c,0xe7,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x6d,0x49,0x44,0x41,0x54,0x28,0x91,0x63,0x60,0x18,0x74,0x80,0x11,0xc6,0x78,0xf0,0xe0,0xc1,0x7f,0x7c,0xa,0x15,0x14,0x14,0x18,0x19,0x18,0x18,0x18,0x98,0x48,0xb5,0x81,0x7c,0xd,0x8c,0x8c,0x8c,0xf1,0xc,0xc,0xc,0x5f,0xb1,0xa8,0xf9,0xce,0xc8,0xc8,0x98,0xe,0x57,0x87,0x2c,0x73,0xff,0xfe,0x7d,0xd,0x6,0x6,0x86,0x55,0x8c,0x8c,0x8c,0xba,0x50,0xa1,0x1b,0xcc,0xcc,0xcc,0x61,0xb2,0xb2,0xb2,0x97,0xb1,0x6a,0x60,0x60,0x60,0x60,0x78,0xf1,0xe2,0x5,0xf7,0xcf,0x9f,0x3f,0xa7,0x30,0x30,0x30,0x30,0xb0,0xb3,0xb3,0xe7,0x48,0x48,0x48,0x60,0xb3,0x75,0x30,0x1,0x0,0x28,0x20,0x14,0xc2,0x1b,0xd0,0x7c,0xca,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char arrow_down_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x6, 0x0, 0x0, 0x0, 0x56, 0x75, 0x5c, 0xe7, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0x6d, 0x49, 0x44, 0x41, 0x54, 0x28, 0x91, 0x63, 0x60, 0x18, 0x74, 0x80, 0x11, 0xc6, 0x78, 0xf0, 0xe0, 0xc1, 0x7f, 0x7c, 0xa, 0x15, 0x14, 0x14, 0x18, 0x19, 0x18, 0x18, 0x18, 0x98, 0x48, 0xb5, 0x81, 0x7c, 0xd, 0x8c, 0x8c, 0x8c, 0xf1, 0xc, 0xc, 0xc, 0x5f, 0xb1, 0xa8, 0xf9, 0xce, 0xc8, 0xc8, 0x98, 0xe, 0x57, 0x87, 0x2c, 0x73, 0xff, 0xfe, 0x7d, 0xd, 0x6, 0x6, 0x86, 0x55, 0x8c, 0x8c, 0x8c, 0xba, 0x50, 0xa1, 0x1b, 0xcc, 0xcc, 0xcc, 0x61, 0xb2, 0xb2, 0xb2, 0x97, 0xb1, 0x6a, 0x60, 0x60, 0x60, 0x60, 0x78, 0xf1, 0xe2, 0x5, 0xf7, 0xcf, 0x9f, 0x3f, 0xa7, 0x30, 0x30, 0x30, 0x30, 0xb0, 0xb3, 0xb3, 0xe7, 0x48, 0x48, 0x48, 0x60, 0xb3, 0x75, 0x30, 0x1, 0x0, 0x28, 0x20, 0x14, 0xc2, 0x1b, 0xd0, 0x7c, 0xca, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char arrow_right_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0xc,0x8,0x6,0x0,0x0,0x0,0x56,0x75,0x5c,0xe7,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x6c,0x49,0x44,0x41,0x54,0x28,0x91,0x63,0x60,0xa0,0x35,0x60,0x44,0xe6,0x3c,0x78,0xf0,0xe0,0x3f,0x8c,0xfd,0xff,0xff,0xff,0x44,0x45,0x45,0xc5,0x5,0xe8,0x1a,0x98,0x70,0x9a,0xc4,0xc8,0x38,0xe5,0xe1,0xc3,0x87,0xda,0x44,0x6b,0x60,0x60,0x60,0xe0,0xfe,0xff,0xff,0xff,0xaa,0x17,0x2f,0x5e,0x70,0x13,0xab,0x81,0x81,0x81,0x81,0x41,0xeb,0xe7,0xcf,0x9f,0x53,0x48,0xd1,0x80,0x1,0x8,0x69,0xb8,0xc6,0xce,0xce,0x9e,0x43,0xac,0x86,0xaf,0x8c,0x8c,0x8c,0x61,0x12,0x12,0x12,0x5f,0x89,0xd2,0xf0,0xff,0xff,0xff,0x1c,0x79,0x79,0xf9,0xab,0x84,0x1d,0x49,0x6d,0x0,0x0,0x8f,0x30,0x1e,0x10,0x6e,0x79,0xda,0xf9,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char arrow_right_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x6, 0x0, 0x0, 0x0, 0x56, 0x75, 0x5c, 0xe7, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0x6c, 0x49, 0x44, 0x41, 0x54, 0x28, 0x91, 0x63, 0x60, 0xa0, 0x35, 0x60, 0x44, 0xe6, 0x3c, 0x78, 0xf0, 0xe0, 0x3f, 0x8c, 0xfd, 0xff, 0xff, 0xff, 0x44, 0x45, 0x45, 0xc5, 0x5, 0xe8, 0x1a, 0x98, 0x70, 0x9a, 0xc4, 0xc8, 0x38, 0xe5, 0xe1, 0xc3, 0x87, 0xda, 0x44, 0x6b, 0x60, 0x60, 0x60, 0xe0, 0xfe, 0xff, 0xff, 0xff, 0xaa, 0x17, 0x2f, 0x5e, 0x70, 0x13, 0xab, 0x81, 0x81, 0x81, 0x81, 0x41, 0xeb, 0xe7, 0xcf, 0x9f, 0x53, 0x48, 0xd1, 0x80, 0x1, 0x8, 0x69, 0xb8, 0xc6, 0xce, 0xce, 0x9e, 0x43, 0xac, 0x86, 0xaf, 0x8c, 0x8c, 0x8c, 0x61, 0x12, 0x12, 0x12, 0x5f, 0x89, 0xd2, 0xf0, 0xff, 0xff, 0xff, 0x1c, 0x79, 0x79, 0xf9, 0xab, 0x84, 0x1d, 0x49, 0x6d, 0x0, 0x0, 0x8f, 0x30, 0x1e, 0x10, 0x6e, 0x79, 0xda, 0xf9, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char background_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x20,0x8,0x3,0x0,0x0,0x0,0x44,0xa4,0x8a,0xc6,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x1,0x11,0x50,0x4c,0x54,0x45,0x91,0xc9,0xab,0x90,0xc9,0xab,0x90,0xc9,0xaa,0x90,0xc8,0xab,0x91,0xc9,0xaa,0x91,0xc8,0xab,0x90,0xc8,0xaa,0x8f,0xc8,0xab,0x8f,0xc9,0xab,0x8f,0xc8,0xaa,0x90,0xc7,0xaa,0x90,0xc7,0xab,0x8f,0xc7,0xaa,0x8f,0xc7,0xab,0x8e,0xc7,0xab,0x8e,0xc6,0xab,0x8f,0xc6,0xab,0x8e,0xc6,0xaa,0x8f,0xc6,0xaa,0x8e,0xc7,0xaa,0x8e,0xc5,0xaa,0x8e,0xc5,0xab,0x8d,0xc5,0xaa,0x8d,0xc5,0xab,0x8d,0xc6,0xaa,0x8d,0xc6,0xab,0x8d,0xc4,0xaa,0x8e,0xc4,0xab,0x8d,0xc4,0xab,0x8e,0xc4,0xaa,0x8c,0xc4,0xaa,0x8c,0xc5,0xaa,0x8d,0xc3,0xab,0x8d,0xc3,0xaa,0x8c,0xc3,0xaa,0x8c,0xc4,0xab,0x8c,0xc3,0xab,0x8c,0xc2,0xab,0x8b,0xc2,0xaa,0x8b,0xc3,0xaa,0x8b,0xc3,0xab,0x8c,0xc2,0xaa,0x8b,0xc2,0xab,0x8b,0xc1,0xaa,0x8b,0xc1,0xab,0x8a,0xc2,0xaa,0x8a,0xc1,0xaa,0x8a,0xc0,0xaa,0x8b,0xc0,0xaa,0x8a,0xc1,0xa9,0x8a,0xc0,0xa9,0x89,0xc0,0xaa,0x8a,0xbf,0xaa,0x89,0xbf,0xaa,0x89,0xbf,0xa9,0x8a,0xbf,0xa9,0x88,0xbf,0xaa,0x89,0xbe,0xaa,0x89,0xbe,0xa9,0x88,0xbf,0xa9,0x88,0xbe,0xa9,0x88,0xbe,0xaa,0x88,0xbd,0xaa,0x88,0xbd,0xa9,0x89,0xbd,0xaa,0x89,0xbd,0xa9,0x87,0xbe,0xa9,0x87,0xbd,0xaa,0x87,0xbe,0xaa,0x87,0xbd,0xa9,0x87,0xbc,0xaa,0x88,0xbc,0xa9,0x88,0xbc,0xaa,0x87,0xbc,0xa9,0x86,0xbc,0xa9,0x87,0xbb,0xaa,0x87,0xbb,0xa9,0x86,0xbb,0xa9,0x86,0xbc,0xaa,0x86,0xbb,0xaa,0x86,0xba,0xaa,0x86,0xba,0xa9,0x85,0xba,0xa9,0x85,0xbb,0xaa,0x85,0xbb,0xa9,0x85,0xba,0xaa,0x85,0xb9,0xa9,0x86,0xb9,0xa9,0x86,0xb9,0xaa,0x85,0xb9,0xaa,0xff,0xff,0xff,0x25,0xe,0xc5,0xe1,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x5a,0x3,0xbb,0xa5,0xa2,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x2,0xaa,0x49,0x44,0x41,0x54,0x38,0xcb,0x45,0x4b,0xd,0x63,0x9a,0x56,0x14,0xbd,0x86,0x2d,0x24,0x2b,0xf8,0x8a,0x1,0xcc,0x18,0x23,0xcd,0x8b,0xc5,0x2a,0xa9,0x6e,0x51,0x98,0x58,0x3e,0xda,0x52,0x69,0x9e,0x4a,0x10,0xba,0xb8,0xec,0xff,0xff,0x91,0x9d,0x47,0xd2,0xf5,0xbc,0xcb,0x3d,0x1f,0xf7,0x40,0xd4,0x23,0x4c,0x4f,0x2,0x9b,0xa8,0x93,0x27,0x9d,0xa3,0xe7,0x50,0xe9,0xc9,0x79,0x69,0x74,0xf7,0x9f,0x7a,0x8a,0xd2,0xfb,0xf9,0xf4,0x25,0x53,0xd5,0x33,0xf4,0xcf,0xce,0x90,0x9d,0xa8,0xa,0x80,0x75,0xaa,0xc8,0xca,0xa9,0xa2,0x9c,0xf4,0x54,0x52,0x91,0x9c,0xab,0x2a,0x46,0x42,0xf9,0xe5,0xb4,0x2b,0xa9,0xe7,0xca,0xab,0x57,0xc8,0x15,0x8d,0x74,0x4d,0xd5,0x25,0x40,0x8a,0xae,0xea,0xda,0xb9,0xd6,0x59,0x55,0x12,0xfe,0xd0,0x49,0xef,0xb3,0xbe,0xfe,0x5a,0x37,0x34,0x66,0x30,0x5d,0xd3,0xfb,0xfa,0x80,0x69,0x3,0x7d,0x70,0xd1,0xd5,0xfa,0x9a,0x4e,0x3,0xe3,0x62,0xd0,0xd7,0xd,0xd6,0x37,0x98,0xd1,0xef,0xf,0xc0,0x9a,0xc1,0x2e,0xc,0xc6,0x2e,0xd8,0xeb,0x1,0x86,0x98,0x61,0x32,0x13,0x7f,0x33,0x66,0x49,0x36,0xba,0x41,0x68,0x18,0xdd,0x66,0x64,0x5b,0x96,0x69,0x59,0x90,0xd6,0xf0,0x72,0x68,0x9a,0x43,0xd3,0xfa,0xd5,0x32,0x2f,0x6d,0xe3,0xd2,0xb2,0x98,0x65,0x30,0x93,0x1c,0x7b,0x88,0x67,0xdb,0xa6,0xd,0x72,0x7e,0x1b,0xba,0xa8,0xc0,0xda,0xbf,0xf,0x91,0xba,0xb6,0x4b,0x8e,0xe7,0x78,0xee,0xd0,0x75,0x87,0x1e,0xac,0xe3,0x60,0x5f,0x39,0x57,0xe,0x84,0xe7,0xd8,0xb6,0x63,0x5f,0xd1,0x1b,0xe7,0x9a,0xcb,0x92,0xe7,0xba,0xae,0xe7,0xf0,0x1b,0xc7,0xb9,0x76,0x3c,0x8e,0xb3,0x87,0x16,0xbf,0xf1,0x88,0x73,0xee,0x8c,0x46,0xd8,0xd7,0x7c,0xe4,0xf1,0xef,0x18,0x79,0x37,0x9c,0x7b,0x6f,0xbc,0x11,0x27,0xfe,0xd6,0xf7,0xf9,0x98,0xf3,0x77,0x13,0xfe,0x96,0x8f,0xb8,0x3f,0x96,0x65,0x9f,0x4f,0x38,0x1f,0x4f,0xf8,0x68,0xc2,0xc9,0x7f,0xc6,0x74,0xea,0x73,0x49,0x13,0xcc,0x78,0xe2,0xfb,0x13,0x59,0xf2,0xdf,0xf9,0x63,0xa,0xa6,0xfe,0x34,0xf0,0xf1,0xba,0xe9,0x20,0x39,0xf0,0x6f,0x83,0xdb,0x69,0x10,0x4c,0x29,0x78,0x3f,0xb,0x50,0x91,0xe7,0xc0,0x9f,0x61,0xdd,0x6,0xb3,0xd9,0xcc,0xf7,0xdf,0x83,0xe0,0x2,0x9a,0xcd,0x67,0xcf,0x98,0x77,0xea,0xf,0x29,0xe4,0xfc,0x9,0x13,0x40,0xd0,0x1c,0x87,0x1f,0xb8,0x93,0xab,0xb,0xee,0x5e,0x62,0x5a,0x2c,0xe7,0x21,0x78,0xb9,0x58,0x2e,0xb1,0xd1,0xb8,0x5b,0x84,0x4b,0xd8,0xf9,0x7c,0x81,0xef,0x2e,0xa4,0xc5,0x22,0xc,0x97,0x61,0x18,0x85,0x12,0x51,0x4,0x5e,0x46,0x61,0xf4,0x97,0x74,0xb,0xb9,0xa8,0x3b,0xad,0xe2,0x38,0xa,0xd7,0xab,0x28,0x4,0x85,0x1f,0xe2,0x10,0x1c,0xc5,0xe1,0x2a,0x5c,0x25,0x2b,0x4a,0xe3,0x38,0x49,0x93,0x24,0x4d,0xe3,0x34,0x4e,0xe2,0x68,0xd,0x1f,0xad,0x93,0x24,0x59,0x23,0xfa,0xb0,0x4e,0x53,0xca,0xf2,0x2c,0xfb,0xf8,0xf1,0x13,0x6c,0x92,0x42,0xa7,0x49,0x9e,0xe6,0x69,0x92,0x49,0xd3,0x65,0x94,0x7d,0xce,0xb2,0x2c,0xc9,0xd2,0xa2,0xf8,0x92,0xe7,0x59,0x51,0xc0,0x7d,0xce,0xb,0xc8,0x1c,0xc8,0x36,0x5,0x95,0x5f,0xb3,0x72,0x53,0x66,0xf7,0x5f,0x37,0x70,0xf7,0x79,0x51,0x88,0xfb,0x12,0x3d,0x91,0xdd,0x8b,0x4d,0x99,0x8b,0x92,0x44,0x59,0xa,0x51,0x8a,0x72,0xb,0x2e,0x37,0x2,0x1a,0xa2,0x0,0x8b,0xd,0x62,0x21,0x48,0xec,0x76,0x7b,0x21,0xaa,0x52,0xec,0xb6,0xa2,0xaa,0xb6,0xf,0xfb,0x7d,0x2d,0xc4,0xf6,0xa1,0x7a,0x10,0xdb,0x9d,0x28,0x77,0x15,0x55,0xbb,0xba,0x92,0xd8,0x57,0xbb,0xaa,0xaa,0xeb,0x7d,0x2d,0xed,0xff,0xdf,0xbe,0xa6,0x43,0xd5,0x34,0x75,0xd3,0x54,0xcd,0xa1,0xaa,0xf,0x75,0x83,0xbc,0xae,0x5a,0xb4,0x64,0xf6,0xd,0x1d,0x6a,0x25,0x9a,0xa6,0x6d,0xab,0x43,0x3,0xfc,0x2d,0x57,0x8b,0xf7,0xf8,0xd8,0xb4,0x87,0xb6,0x6e,0xe9,0xb1,0x6d,0x8e,0x6d,0x7b,0x6c,0xff,0x39,0x3e,0x1d,0x9f,0x20,0x8f,0xd2,0x1d,0xff,0x45,0xa,0xdd,0xb6,0x4f,0xff,0x1,0xbe,0xd3,0xa6,0xf7,0x55,0x9e,0xe1,0xf0,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char background_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x20, 0x8, 0x3, 0x0, 0x0, 0x0, 0x44, 0xa4, 0x8a, 0xc6, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x1, 0x11, 0x50, 0x4c, 0x54, 0x45, 0x91, 0xc9, 0xab, 0x90, 0xc9, 0xab, 0x90, 0xc9, 0xaa, 0x90, 0xc8, 0xab, 0x91, 0xc9, 0xaa, 0x91, 0xc8, 0xab, 0x90, 0xc8, 0xaa, 0x8f, 0xc8, 0xab, 0x8f, 0xc9, 0xab, 0x8f, 0xc8, 0xaa, 0x90, 0xc7, 0xaa, 0x90, 0xc7, 0xab, 0x8f, 0xc7, 0xaa, 0x8f, 0xc7, 0xab, 0x8e, 0xc7, 0xab, 0x8e, 0xc6, 0xab, 0x8f, 0xc6, 0xab, 0x8e, 0xc6, 0xaa, 0x8f, 0xc6, 0xaa, 0x8e, 0xc7, 0xaa, 0x8e, 0xc5, 0xaa, 0x8e, 0xc5, 0xab, 0x8d, 0xc5, 0xaa, 0x8d, 0xc5, 0xab, 0x8d, 0xc6, 0xaa, 0x8d, 0xc6, 0xab, 0x8d, 0xc4, 0xaa, 0x8e, 0xc4, 0xab, 0x8d, 0xc4, 0xab, 0x8e, 0xc4, 0xaa, 0x8c, 0xc4, 0xaa, 0x8c, 0xc5, 0xaa, 0x8d, 0xc3, 0xab, 0x8d, 0xc3, 0xaa, 0x8c, 0xc3, 0xaa, 0x8c, 0xc4, 0xab, 0x8c, 0xc3, 0xab, 0x8c, 0xc2, 0xab, 0x8b, 0xc2, 0xaa, 0x8b, 0xc3, 0xaa, 0x8b, 0xc3, 0xab, 0x8c, 0xc2, 0xaa, 0x8b, 0xc2, 0xab, 0x8b, 0xc1, 0xaa, 0x8b, 0xc1, 0xab, 0x8a, 0xc2, 0xaa, 0x8a, 0xc1, 0xaa, 0x8a, 0xc0, 0xaa, 0x8b, 0xc0, 0xaa, 0x8a, 0xc1, 0xa9, 0x8a, 0xc0, 0xa9, 0x89, 0xc0, 0xaa, 0x8a, 0xbf, 0xaa, 0x89, 0xbf, 0xaa, 0x89, 0xbf, 0xa9, 0x8a, 0xbf, 0xa9, 0x88, 0xbf, 0xaa, 0x89, 0xbe, 0xaa, 0x89, 0xbe, 0xa9, 0x88, 0xbf, 0xa9, 0x88, 0xbe, 0xa9, 0x88, 0xbe, 0xaa, 0x88, 0xbd, 0xaa, 0x88, 0xbd, 0xa9, 0x89, 0xbd, 0xaa, 0x89, 0xbd, 0xa9, 0x87, 0xbe, 0xa9, 0x87, 0xbd, 0xaa, 0x87, 0xbe, 0xaa, 0x87, 0xbd, 0xa9, 0x87, 0xbc, 0xaa, 0x88, 0xbc, 0xa9, 0x88, 0xbc, 0xaa, 0x87, 0xbc, 0xa9, 0x86, 0xbc, 0xa9, 0x87, 0xbb, 0xaa, 0x87, 0xbb, 0xa9, 0x86, 0xbb, 0xa9, 0x86, 0xbc, 0xaa, 0x86, 0xbb, 0xaa, 0x86, 0xba, 0xaa, 0x86, 0xba, 0xa9, 0x85, 0xba, 0xa9, 0x85, 0xbb, 0xaa, 0x85, 0xbb, 0xa9, 0x85, 0xba, 0xaa, 0x85, 0xb9, 0xa9, 0x86, 0xb9, 0xa9, 0x86, 0xb9, 0xaa, 0x85, 0xb9, 0xaa, 0xff, 0xff, 0xff, 0x25, 0xe, 0xc5, 0xe1, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x5a, 0x3, 0xbb, 0xa5, 0xa2, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x2, 0xaa, 0x49, 0x44, 0x41, 0x54, 0x38, 0xcb, 0x45, 0x4b, 0xd, 0x63, 0x9a, 0x56, 0x14, 0xbd, 0x86, 0x2d, 0x24, 0x2b, 0xf8, 0x8a, 0x1, 0xcc, 0x18, 0x23, 0xcd, 0x8b, 0xc5, 0x2a, 0xa9, 0x6e, 0x51, 0x98, 0x58, 0x3e, 0xda, 0x52, 0x69, 0x9e, 0x4a, 0x10, 0xba, 0xb8, 0xec, 0xff, 0xff, 0x91, 0x9d, 0x47, 0xd2, 0xf5, 0xbc, 0xcb, 0x3d, 0x1f, 0xf7, 0x40, 0xd4, 0x23, 0x4c, 0x4f, 0x2, 0x9b, 0xa8, 0x93, 0x27, 0x9d, 0xa3, 0xe7, 0x50, 0xe9, 0xc9, 0x79, 0x69, 0x74, 0xf7, 0x9f, 0x7a, 0x8a, 0xd2, 0xfb, 0xf9, 0xf4, 0x25, 0x53, 0xd5, 0x33, 0xf4, 0xcf, 0xce, 0x90, 0x9d, 0xa8, 0xa, 0x80, 0x75, 0xaa, 0xc8, 0xca, 0xa9, 0xa2, 0x9c, 0xf4, 0x54, 0x52, 0x91, 0x9c, 0xab, 0x2a, 0x46, 0x42, 0xf9, 0xe5, 0xb4, 0x2b, 0xa9, 0xe7, 0xca, 0xab, 0x57, 0xc8, 0x15, 0x8d, 0x74, 0x4d, 0xd5, 0x25, 0x40, 0x8a, 0xae, 0xea, 0xda, 0xb9, 0xd6, 0x59, 0x55, 0x12, 0xfe, 0xd0, 0x49, 0xef, 0xb3, 0xbe, 0xfe, 0x5a, 0x37, 0x34, 0x66, 0x30, 0x5d, 0xd3, 0xfb, 0xfa, 0x80, 0x69, 0x3, 0x7d, 0x70, 0xd1, 0xd5, 0xfa, 0x9a, 0x4e, 0x3, 0xe3, 0x62, 0xd0, 0xd7, 0xd, 0xd6, 0x37, 0x98, 0xd1, 0xef, 0xf, 0xc0, 0x9a, 0xc1, 0x2e, 0xc, 0xc6, 0x2e, 0xd8, 0xeb, 0x1, 0x86, 0x98, 0x61, 0x32, 0x13, 0x7f, 0x33, 0x66, 0x49, 0x36, 0xba, 0x41, 0x68, 0x18, 0xdd, 0x66, 0x64, 0x5b, 0x96, 0x69, 0x59, 0x90, 0xd6, 0xf0, 0x72, 0x68, 0x9a, 0x43, 0xd3, 0xfa, 0xd5, 0x32, 0x2f, 0x6d, 0xe3, 0xd2, 0xb2, 0x98, 0x65, 0x30, 0x93, 0x1c, 0x7b, 0x88, 0x67, 0xdb, 0xa6, 0xd, 0x72, 0x7e, 0x1b, 0xba, 0xa8, 0xc0, 0xda, 0xbf, 0xf, 0x91, 0xba, 0xb6, 0x4b, 0x8e, 0xe7, 0x78, 0xee, 0xd0, 0x75, 0x87, 0x1e, 0xac, 0xe3, 0x60, 0x5f, 0x39, 0x57, 0xe, 0x84, 0xe7, 0xd8, 0xb6, 0x63, 0x5f, 0xd1, 0x1b, 0xe7, 0x9a, 0xcb, 0x92, 0xe7, 0xba, 0xae, 0xe7, 0xf0, 0x1b, 0xc7, 0xb9, 0x76, 0x3c, 0x8e, 0xb3, 0x87, 0x16, 0xbf, 0xf1, 0x88, 0x73, 0xee, 0x8c, 0x46, 0xd8, 0xd7, 0x7c, 0xe4, 0xf1, 0xef, 0x18, 0x79, 0x37, 0x9c, 0x7b, 0x6f, 0xbc, 0x11, 0x27, 0xfe, 0xd6, 0xf7, 0xf9, 0x98, 0xf3, 0x77, 0x13, 0xfe, 0x96, 0x8f, 0xb8, 0x3f, 0x96, 0x65, 0x9f, 0x4f, 0x38, 0x1f, 0x4f, 0xf8, 0x68, 0xc2, 0xc9, 0x7f, 0xc6, 0x74, 0xea, 0x73, 0x49, 0x13, 0xcc, 0x78, 0xe2, 0xfb, 0x13, 0x59, 0xf2, 0xdf, 0xf9, 0x63, 0xa, 0xa6, 0xfe, 0x34, 0xf0, 0xf1, 0xba, 0xe9, 0x20, 0x39, 0xf0, 0x6f, 0x83, 0xdb, 0x69, 0x10, 0x4c, 0x29, 0x78, 0x3f, 0xb, 0x50, 0x91, 0xe7, 0xc0, 0x9f, 0x61, 0xdd, 0x6, 0xb3, 0xd9, 0xcc, 0xf7, 0xdf, 0x83, 0xe0, 0x2, 0x9a, 0xcd, 0x67, 0xcf, 0x98, 0x77, 0xea, 0xf, 0x29, 0xe4, 0xfc, 0x9, 0x13, 0x40, 0xd0, 0x1c, 0x87, 0x1f, 0xb8, 0x93, 0xab, 0xb, 0xee, 0x5e, 0x62, 0x5a, 0x2c, 0xe7, 0x21, 0x78, 0xb9, 0x58, 0x2e, 0xb1, 0xd1, 0xb8, 0x5b, 0x84, 0x4b, 0xd8, 0xf9, 0x7c, 0x81, 0xef, 0x2e, 0xa4, 0xc5, 0x22, 0xc, 0x97, 0x61, 0x18, 0x85, 0x12, 0x51, 0x4, 0x5e, 0x46, 0x61, 0xf4, 0x97, 0x74, 0xb, 0xb9, 0xa8, 0x3b, 0xad, 0xe2, 0x38, 0xa, 0xd7, 0xab, 0x28, 0x4, 0x85, 0x1f, 0xe2, 0x10, 0x1c, 0xc5, 0xe1, 0x2a, 0x5c, 0x25, 0x2b, 0x4a, 0xe3, 0x38, 0x49, 0x93, 0x24, 0x4d, 0xe3, 0x34, 0x4e, 0xe2, 0x68, 0xd, 0x1f, 0xad, 0x93, 0x24, 0x59, 0x23, 0xfa, 0xb0, 0x4e, 0x53, 0xca, 0xf2, 0x2c, 0xfb, 0xf8, 0xf1, 0x13, 0x6c, 0x92, 0x42, 0xa7, 0x49, 0x9e, 0xe6, 0x69, 0x92, 0x49, 0xd3, 0x65, 0x94, 0x7d, 0xce, 0xb2, 0x2c, 0xc9, 0xd2, 0xa2, 0xf8, 0x92, 0xe7, 0x59, 0x51, 0xc0, 0x7d, 0xce, 0xb, 0xc8, 0x1c, 0xc8, 0x36, 0x5, 0x95, 0x5f, 0xb3, 0x72, 0x53, 0x66, 0xf7, 0x5f, 0x37, 0x70, 0xf7, 0x79, 0x51, 0x88, 0xfb, 0x12, 0x3d, 0x91, 0xdd, 0x8b, 0x4d, 0x99, 0x8b, 0x92, 0x44, 0x59, 0xa, 0x51, 0x8a, 0x72, 0xb, 0x2e, 0x37, 0x2, 0x1a, 0xa2, 0x0, 0x8b, 0xd, 0x62, 0x21, 0x48, 0xec, 0x76, 0x7b, 0x21, 0xaa, 0x52, 0xec, 0xb6, 0xa2, 0xaa, 0xb6, 0xf, 0xfb, 0x7d, 0x2d, 0xc4, 0xf6, 0xa1, 0x7a, 0x10, 0xdb, 0x9d, 0x28, 0x77, 0x15, 0x55, 0xbb, 0xba, 0x92, 0xd8, 0x57, 0xbb, 0xaa, 0xaa, 0xeb, 0x7d, 0x2d, 0xed, 0xff, 0xdf, 0xbe, 0xa6, 0x43, 0xd5, 0x34, 0x75, 0xd3, 0x54, 0xcd, 0xa1, 0xaa, 0xf, 0x75, 0x83, 0xbc, 0xae, 0x5a, 0xb4, 0x64, 0xf6, 0xd, 0x1d, 0x6a, 0x25, 0x9a, 0xa6, 0x6d, 0xab, 0x43, 0x3, 0xfc, 0x2d, 0x57, 0x8b, 0xf7, 0xf8, 0xd8, 0xb4, 0x87, 0xb6, 0x6e, 0xe9, 0xb1, 0x6d, 0x8e, 0x6d, 0x7b, 0x6c, 0xff, 0x39, 0x3e, 0x1d, 0x9f, 0x20, 0x8f, 0xd2, 0x1d, 0xff, 0x45, 0xa, 0xdd, 0xb6, 0x4f, 0xff, 0x1, 0xbe, 0xd3, 0xa6, 0xf7, 0x55, 0x9e, 0xe1, 0xf0, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char base_green_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x20,0x1,0x3,0x0,0x0,0x0,0x49,0xb4,0xe8,0xb7,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x6,0x50,0x4c,0x54,0x45,0x90,0xc9,0xab,0xff,0xff,0xff,0xc6,0xd0,0x9d,0x30,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x1,0xff,0x2,0x2d,0xde,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0xc,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0x18,0xdc,0x0,0x0,0x0,0xa0,0x0,0x1,0x61,0x25,0x7d,0x47,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char base_green_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x20, 0x1, 0x3, 0x0, 0x0, 0x0, 0x49, 0xb4, 0xe8, 0xb7, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x6, 0x50, 0x4c, 0x54, 0x45, 0x90, 0xc9, 0xab, 0xff, 0xff, 0xff, 0xc6, 0xd0, 0x9d, 0x30, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x1, 0xff, 0x2, 0x2d, 0xde, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0xc, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x18, 0xdc, 0x0, 0x0, 0x0, 0xa0, 0x0, 0x1, 0x61, 0x25, 0x7d, 0x47, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char button_disabled_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x4,0x0,0x0,0x0,0xb5,0xfa,0x37,0xea,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0xd9,0x49,0x44,0x41,0x54,0x28,0xcf,0x7d,0x91,0x41,0x4e,0xc3,0x30,0x14,0x44,0x9f,0xed,0x8f,0x6d,0x35,0x8b,0x9a,0x6d,0xb9,0x6,0xfb,0xde,0x81,0xd3,0xe4,0x8,0xf4,0x32,0xbd,0x1,0xb,0x6e,0xc0,0x25,0x60,0x83,0xa8,0x2,0x6a,0xa4,0xc6,0x49,0xfc,0xbb,0x88,0x54,0x11,0x94,0x30,0xb3,0xf9,0xd2,0x9f,0x19,0x8d,0x34,0x6,0xc1,0x13,0x88,0x78,0x1c,0x96,0x9,0x85,0x91,0xcc,0x85,0x8e,0x2c,0x78,0x2a,0x12,0x5b,0x2a,0x2,0x6,0x3,0x28,0x4a,0x47,0xcb,0x37,0xd,0x8,0x81,0xb4,0x7f,0x7a,0xa8,0x87,0xc4,0xc,0xd2,0xbc,0x3f,0xbf,0x1e,0x19,0x84,0xc8,0x76,0x57,0x9f,0xd2,0x80,0xfe,0x7a,0x1b,0x24,0xed,0x6a,0x5e,0x38,0xb,0x9e,0xaa,0x4f,0xfd,0xdc,0x8e,0xd2,0xd3,0x27,0x2a,0xbc,0xe0,0x8,0x65,0xe6,0xe6,0xd6,0x94,0x80,0x13,0x2c,0x46,0x29,0xb,0x2,0x5,0x83,0x15,0xc0,0xac,0x26,0x18,0x90,0xe9,0x5c,0x11,0x30,0x9,0x54,0x17,0x5,0xa,0xa,0x42,0x41,0xcb,0x62,0x87,0x2,0x4a,0x11,0x46,0xba,0xd5,0x84,0x8e,0xd1,0x92,0x69,0x6d,0xe3,0xd0,0x3f,0x74,0xd8,0x86,0x96,0xec,0xb8,0xc3,0xa5,0xaf,0xfb,0x47,0x1f,0x3d,0xe1,0xc6,0x48,0x3c,0x7d,0x1e,0x3e,0xde,0xf8,0x31,0x6c,0xfe,0x1d,0xab,0x15,0x32,0x30,0x70,0x5e,0x9b,0xfb,0xa,0xbb,0x7c,0x61,0xa2,0x50,0x44,0x45,0xca,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char button_disabled_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0xd9, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x7d, 0x91, 0x41, 0x4e, 0xc3, 0x30, 0x14, 0x44, 0x9f, 0xed, 0x8f, 0x6d, 0x35, 0x8b, 0x9a, 0x6d, 0xb9, 0x6, 0xfb, 0xde, 0x81, 0xd3, 0xe4, 0x8, 0xf4, 0x32, 0xbd, 0x1, 0xb, 0x6e, 0xc0, 0x25, 0x60, 0x83, 0xa8, 0x2, 0x6a, 0xa4, 0xc6, 0x49, 0xfc, 0xbb, 0x88, 0x54, 0x11, 0x94, 0x30, 0xb3, 0xf9, 0xd2, 0x9f, 0x19, 0x8d, 0x34, 0x6, 0xc1, 0x13, 0x88, 0x78, 0x1c, 0x96, 0x9, 0x85, 0x91, 0xcc, 0x85, 0x8e, 0x2c, 0x78, 0x2a, 0x12, 0x5b, 0x2a, 0x2, 0x6, 0x3, 0x28, 0x4a, 0x47, 0xcb, 0x37, 0xd, 0x8, 0x81, 0xb4, 0x7f, 0x7a, 0xa8, 0x87, 0xc4, 0xc, 0xd2, 0xbc, 0x3f, 0xbf, 0x1e, 0x19, 0x84, 0xc8, 0x76, 0x57, 0x9f, 0xd2, 0x80, 0xfe, 0x7a, 0x1b, 0x24, 0xed, 0x6a, 0x5e, 0x38, 0xb, 0x9e, 0xaa, 0x4f, 0xfd, 0xdc, 0x8e, 0xd2, 0xd3, 0x27, 0x2a, 0xbc, 0xe0, 0x8, 0x65, 0xe6, 0xe6, 0xd6, 0x94, 0x80, 0x13, 0x2c, 0x46, 0x29, 0xb, 0x2, 0x5, 0x83, 0x15, 0xc0, 0xac, 0x26, 0x18, 0x90, 0xe9, 0x5c, 0x11, 0x30, 0x9, 0x54, 0x17, 0x5, 0xa, 0xa, 0x42, 0x41, 0xcb, 0x62, 0x87, 0x2, 0x4a, 0x11, 0x46, 0xba, 0xd5, 0x84, 0x8e, 0xd1, 0x92, 0x69, 0x6d, 0xe3, 0xd0, 0x3f, 0x74, 0xd8, 0x86, 0x96, 0xec, 0xb8, 0xc3, 0xa5, 0xaf, 0xfb, 0x47, 0x1f, 0x3d, 0xe1, 0xc6, 0x48, 0x3c, 0x7d, 0x1e, 0x3e, 0xde, 0xf8, 0x31, 0x6c, 0xfe, 0x1d, 0xab, 0x15, 0x32, 0x30, 0x70, 0x5e, 0x9b, 0xfb, 0xa, 0xbb, 0x7c, 0x61, 0xa2, 0x50, 0x44, 0x45, 0xca, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char button_focus_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x4,0x3,0x0,0x0,0x0,0xed,0xdd,0xe2,0x52,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x30,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0xff,0xff,0xff,0xb9,0xa2,0x9b,0xc9,0x0,0x0,0x0,0xf,0x74,0x52,0x4e,0x53,0x0,0xe,0x39,0x68,0x7a,0x7b,0x3a,0x74,0x10,0x8,0x69,0xf,0x6,0x75,0x11,0xb8,0x16,0x0,0x1,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0xf,0x18,0xba,0x0,0xd9,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x3f,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0xc0,0x4,0x42,0x26,0xa1,0xa1,0xce,0x8a,0x40,0x46,0x7a,0xe7,0xcc,0x99,0x33,0xca,0x80,0x8c,0xd5,0x20,0xe1,0x5d,0x40,0x1c,0x3,0x62,0x1c,0x5,0xe2,0x48,0x10,0x63,0x2a,0x7e,0x6,0x5c,0x31,0x58,0xbb,0x14,0x10,0xe7,0xee,0x9c,0x39,0x73,0x1e,0xc8,0x40,0x31,0x98,0x15,0xe8,0x0,0x0,0xec,0xe0,0x11,0x6d,0x2c,0x6f,0x45,0x2b,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char button_focus_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x30, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0xff, 0xff, 0xff, 0xb9, 0xa2, 0x9b, 0xc9, 0x0, 0x0, 0x0, 0xf, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xe, 0x39, 0x68, 0x7a, 0x7b, 0x3a, 0x74, 0x10, 0x8, 0x69, 0xf, 0x6, 0x75, 0x11, 0xb8, 0x16, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0xf, 0x18, 0xba, 0x0, 0xd9, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x3f, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0xc0, 0x4, 0x42, 0x26, 0xa1, 0xa1, 0xce, 0x8a, 0x40, 0x46, 0x7a, 0xe7, 0xcc, 0x99, 0x33, 0xca, 0x80, 0x8c, 0xd5, 0x20, 0xe1, 0x5d, 0x40, 0x1c, 0x3, 0x62, 0x1c, 0x5, 0xe2, 0x48, 0x10, 0x63, 0x2a, 0x7e, 0x6, 0x5c, 0x31, 0x58, 0xbb, 0x14, 0x10, 0xe7, 0xee, 0x9c, 0x39, 0x73, 0x1e, 0xc8, 0x40, 0x31, 0x98, 0x15, 0xe8, 0x0, 0x0, 0xec, 0xe0, 0x11, 0x6d, 0x2c, 0x6f, 0x45, 0x2b, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char button_hover_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x8d,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x42,0x40,0x4b,0x5f,0x5a,0x6c,0x5f,0x5a,0x6b,0x56,0x53,0x64,0x57,0x53,0x64,0x3e,0x3b,0x46,0x57,0x53,0x63,0x57,0x53,0x63,0x5b,0x57,0x68,0x5a,0x56,0x67,0x4d,0x4a,0x57,0x49,0x46,0x52,0x48,0x45,0x51,0x5b,0x57,0x66,0x59,0x55,0x64,0x47,0x44,0x50,0x58,0x54,0x64,0x46,0x43,0x50,0x56,0x53,0x63,0x45,0x42,0x4f,0x56,0x53,0x62,0x45,0x42,0x4e,0x55,0x51,0x62,0x44,0x41,0x4e,0x55,0x51,0x60,0x44,0x41,0x4d,0x43,0x40,0x4c,0x47,0x43,0x51,0x43,0x3f,0x4d,0x42,0x3f,0x4c,0x53,0x50,0x5f,0x53,0x4f,0x5e,0xff,0xff,0xff,0x99,0x8b,0x2e,0x55,0x0,0x0,0x0,0x16,0x74,0x52,0x4e,0x53,0x4,0xa,0x11,0x19,0x1f,0x22,0x24,0x15,0x25,0x34,0x3f,0x46,0x47,0x48,0x77,0xef,0xef,0xef,0xef,0x77,0xef,0xed,0x6b,0x28,0x52,0x7a,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x2e,0x54,0xd3,0x10,0x87,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x97,0x49,0x44,0x41,0x54,0x18,0xd3,0x65,0xcf,0x49,0x12,0x82,0x30,0x10,0x5,0xd0,0xce,0x48,0x46,0x40,0x51,0x4,0x41,0x45,0xc4,0x20,0x88,0xf7,0xbf,0x9e,0x21,0x45,0x65,0xa1,0x6f,0xd7,0xbf,0xaa,0x27,0x0,0x84,0x9,0x65,0xdc,0x63,0x94,0x60,0x4,0x80,0x12,0x21,0x95,0x36,0xd6,0x1a,0xad,0xa4,0x48,0x10,0x60,0x91,0x66,0xe5,0x29,0x28,0xb3,0x54,0x60,0x20,0x32,0xaf,0xea,0x73,0x50,0x57,0xb9,0x24,0x40,0x55,0xb3,0xd5,0x3e,0x69,0x14,0x5,0xa6,0xdb,0x4b,0xd4,0x6a,0x6,0xdc,0x5c,0x6f,0xd1,0xd5,0x70,0xe0,0xb6,0xbb,0x47,0x9d,0x5d,0x83,0xfe,0x11,0xf5,0x6b,0x60,0x86,0x67,0x34,0xf8,0x16,0xa6,0xdd,0x18,0x39,0x3f,0x94,0x2a,0x37,0xbe,0x36,0xa3,0xf3,0x6b,0x89,0xdc,0x4d,0xf3,0x3b,0x98,0xa7,0xbd,0x3f,0xc,0x8b,0xe2,0xb0,0x7c,0x82,0xe5,0x58,0xf8,0xd3,0xff,0x9e,0xfb,0x7d,0xff,0xb,0x74,0xeb,0x15,0x11,0xe1,0xa7,0x60,0xfc,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char button_hover_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x8d, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x42, 0x40, 0x4b, 0x5f, 0x5a, 0x6c, 0x5f, 0x5a, 0x6b, 0x56, 0x53, 0x64, 0x57, 0x53, 0x64, 0x3e, 0x3b, 0x46, 0x57, 0x53, 0x63, 0x57, 0x53, 0x63, 0x5b, 0x57, 0x68, 0x5a, 0x56, 0x67, 0x4d, 0x4a, 0x57, 0x49, 0x46, 0x52, 0x48, 0x45, 0x51, 0x5b, 0x57, 0x66, 0x59, 0x55, 0x64, 0x47, 0x44, 0x50, 0x58, 0x54, 0x64, 0x46, 0x43, 0x50, 0x56, 0x53, 0x63, 0x45, 0x42, 0x4f, 0x56, 0x53, 0x62, 0x45, 0x42, 0x4e, 0x55, 0x51, 0x62, 0x44, 0x41, 0x4e, 0x55, 0x51, 0x60, 0x44, 0x41, 0x4d, 0x43, 0x40, 0x4c, 0x47, 0x43, 0x51, 0x43, 0x3f, 0x4d, 0x42, 0x3f, 0x4c, 0x53, 0x50, 0x5f, 0x53, 0x4f, 0x5e, 0xff, 0xff, 0xff, 0x99, 0x8b, 0x2e, 0x55, 0x0, 0x0, 0x0, 0x16, 0x74, 0x52, 0x4e, 0x53, 0x4, 0xa, 0x11, 0x19, 0x1f, 0x22, 0x24, 0x15, 0x25, 0x34, 0x3f, 0x46, 0x47, 0x48, 0x77, 0xef, 0xef, 0xef, 0xef, 0x77, 0xef, 0xed, 0x6b, 0x28, 0x52, 0x7a, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x2e, 0x54, 0xd3, 0x10, 0x87, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x97, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x65, 0xcf, 0x49, 0x12, 0x82, 0x30, 0x10, 0x5, 0xd0, 0xce, 0x48, 0x46, 0x40, 0x51, 0x4, 0x41, 0x45, 0xc4, 0x20, 0x88, 0xf7, 0xbf, 0x9e, 0x21, 0x45, 0x65, 0xa1, 0x6f, 0xd7, 0xbf, 0xaa, 0x27, 0x0, 0x84, 0x9, 0x65, 0xdc, 0x63, 0x94, 0x60, 0x4, 0x80, 0x12, 0x21, 0x95, 0x36, 0xd6, 0x1a, 0xad, 0xa4, 0x48, 0x10, 0x60, 0x91, 0x66, 0xe5, 0x29, 0x28, 0xb3, 0x54, 0x60, 0x20, 0x32, 0xaf, 0xea, 0x73, 0x50, 0x57, 0xb9, 0x24, 0x40, 0x55, 0xb3, 0xd5, 0x3e, 0x69, 0x14, 0x5, 0xa6, 0xdb, 0x4b, 0xd4, 0x6a, 0x6, 0xdc, 0x5c, 0x6f, 0xd1, 0xd5, 0x70, 0xe0, 0xb6, 0xbb, 0x47, 0x9d, 0x5d, 0x83, 0xfe, 0x11, 0xf5, 0x6b, 0x60, 0x86, 0x67, 0x34, 0xf8, 0x16, 0xa6, 0xdd, 0x18, 0x39, 0x3f, 0x94, 0x2a, 0x37, 0xbe, 0x36, 0xa3, 0xf3, 0x6b, 0x89, 0xdc, 0x4d, 0xf3, 0x3b, 0x98, 0xa7, 0xbd, 0x3f, 0xc, 0x8b, 0xe2, 0xb0, 0x7c, 0x82, 0xe5, 0x58, 0xf8, 0xd3, 0xff, 0x9e, 0xfb, 0x7d, 0xff, 0xb, 0x74, 0xeb, 0x15, 0x11, 0xe1, 0xa7, 0x60, 0xfc, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char button_normal_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x8a,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c,0x3a,0x44,0x56,0x53,0x61,0x56,0x52,0x60,0x47,0x44,0x52,0x33,0x31,0x39,0x47,0x44,0x50,0x47,0x44,0x51,0x52,0x50,0x5d,0x51,0x4f,0x5d,0x46,0x42,0x4e,0x42,0x3e,0x4a,0x41,0x3e,0x49,0x51,0x4e,0x5b,0x40,0x3e,0x48,0x4f,0x4c,0x59,0x3f,0x3d,0x47,0x4e,0x4a,0x58,0x3e,0x3b,0x46,0x4b,0x49,0x55,0x3c,0x3a,0x44,0x4a,0x47,0x54,0x3b,0x39,0x43,0x49,0x46,0x53,0x3a,0x38,0x42,0x47,0x45,0x50,0x39,0x37,0x40,0x47,0x43,0x50,0x38,0x35,0x3f,0x36,0x34,0x3e,0x44,0x42,0x4d,0x44,0x41,0x4c,0xff,0xff,0xff,0xe5,0x37,0x10,0x78,0x0,0x0,0x0,0x15,0x74,0x52,0x4e,0x53,0x4,0xa,0x11,0x19,0x1f,0x22,0x24,0x15,0x25,0x34,0x3f,0x46,0x47,0x48,0x77,0xef,0xef,0xef,0x77,0xef,0xed,0xe8,0xff,0x76,0xed,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x2d,0xcd,0xda,0x41,0x3d,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x93,0x49,0x44,0x41,0x54,0x18,0xd3,0x65,0xcf,0x47,0x12,0x82,0x40,0x10,0x5,0xd0,0x9e,0xc8,0x44,0x92,0x22,0x41,0x54,0x44,0x40,0x14,0xef,0x7f,0x3e,0x7,0x8a,0xea,0x85,0xbe,0xe5,0xaf,0xea,0xf0,0x1,0x8,0x65,0x5c,0xc8,0x40,0x70,0x46,0x9,0x0,0x89,0x94,0x36,0xd6,0x79,0xef,0xac,0xd1,0x2a,0x22,0x40,0x55,0x9c,0x14,0xa7,0x4d,0x91,0xc4,0x8a,0x2,0xd3,0x69,0x59,0xd5,0x9b,0xaa,0x4c,0x35,0x3,0x6e,0x9a,0xfa,0xbc,0xab,0x1b,0xc3,0x41,0xd8,0xf6,0x82,0x5a,0x2b,0x40,0xba,0xeb,0xd,0x5d,0x9d,0x4,0xe9,0xbb,0x3b,0xea,0xfc,0x1a,0xf4,0xf,0xd4,0xaf,0x81,0x1b,0x46,0x34,0x84,0x11,0x61,0xa7,0x27,0x9a,0xc2,0x52,0x6e,0xe6,0x17,0x9a,0xc3,0x59,0xa6,0xb3,0xf1,0xbd,0x1b,0xb3,0xf0,0x18,0x55,0xf9,0x61,0xf9,0x6c,0x96,0x63,0x1e,0x5e,0xff,0x2b,0xf7,0x5b,0xff,0xb,0x69,0x5a,0x14,0xfa,0x84,0xf6,0xc2,0x8,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char button_normal_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x8a, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x3a, 0x44, 0x56, 0x53, 0x61, 0x56, 0x52, 0x60, 0x47, 0x44, 0x52, 0x33, 0x31, 0x39, 0x47, 0x44, 0x50, 0x47, 0x44, 0x51, 0x52, 0x50, 0x5d, 0x51, 0x4f, 0x5d, 0x46, 0x42, 0x4e, 0x42, 0x3e, 0x4a, 0x41, 0x3e, 0x49, 0x51, 0x4e, 0x5b, 0x40, 0x3e, 0x48, 0x4f, 0x4c, 0x59, 0x3f, 0x3d, 0x47, 0x4e, 0x4a, 0x58, 0x3e, 0x3b, 0x46, 0x4b, 0x49, 0x55, 0x3c, 0x3a, 0x44, 0x4a, 0x47, 0x54, 0x3b, 0x39, 0x43, 0x49, 0x46, 0x53, 0x3a, 0x38, 0x42, 0x47, 0x45, 0x50, 0x39, 0x37, 0x40, 0x47, 0x43, 0x50, 0x38, 0x35, 0x3f, 0x36, 0x34, 0x3e, 0x44, 0x42, 0x4d, 0x44, 0x41, 0x4c, 0xff, 0xff, 0xff, 0xe5, 0x37, 0x10, 0x78, 0x0, 0x0, 0x0, 0x15, 0x74, 0x52, 0x4e, 0x53, 0x4, 0xa, 0x11, 0x19, 0x1f, 0x22, 0x24, 0x15, 0x25, 0x34, 0x3f, 0x46, 0x47, 0x48, 0x77, 0xef, 0xef, 0xef, 0x77, 0xef, 0xed, 0xe8, 0xff, 0x76, 0xed, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x2d, 0xcd, 0xda, 0x41, 0x3d, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x93, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x65, 0xcf, 0x47, 0x12, 0x82, 0x40, 0x10, 0x5, 0xd0, 0x9e, 0xc8, 0x44, 0x92, 0x22, 0x41, 0x54, 0x44, 0x40, 0x14, 0xef, 0x7f, 0x3e, 0x7, 0x8a, 0xea, 0x85, 0xbe, 0xe5, 0xaf, 0xea, 0xf0, 0x1, 0x8, 0x65, 0x5c, 0xc8, 0x40, 0x70, 0x46, 0x9, 0x0, 0x89, 0x94, 0x36, 0xd6, 0x79, 0xef, 0xac, 0xd1, 0x2a, 0x22, 0x40, 0x55, 0x9c, 0x14, 0xa7, 0x4d, 0x91, 0xc4, 0x8a, 0x2, 0xd3, 0x69, 0x59, 0xd5, 0x9b, 0xaa, 0x4c, 0x35, 0x3, 0x6e, 0x9a, 0xfa, 0xbc, 0xab, 0x1b, 0xc3, 0x41, 0xd8, 0xf6, 0x82, 0x5a, 0x2b, 0x40, 0xba, 0xeb, 0xd, 0x5d, 0x9d, 0x4, 0xe9, 0xbb, 0x3b, 0xea, 0xfc, 0x1a, 0xf4, 0xf, 0xd4, 0xaf, 0x81, 0x1b, 0x46, 0x34, 0x84, 0x11, 0x61, 0xa7, 0x27, 0x9a, 0xc2, 0x52, 0x6e, 0xe6, 0x17, 0x9a, 0xc3, 0x59, 0xa6, 0xb3, 0xf1, 0xbd, 0x1b, 0xb3, 0xf0, 0x18, 0x55, 0xf9, 0x61, 0xf9, 0x6c, 0x96, 0x63, 0x1e, 0x5e, 0xff, 0x2b, 0xf7, 0x5b, 0xff, 0xb, 0x69, 0x5a, 0x14, 0xfa, 0x84, 0xf6, 0xc2, 0x8, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char button_pressed_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x7,0x1c,0xc,0x14,0x2b,0xf9,0x77,0x52,0x64,0x0,0x0,0x1,0x92,0x49,0x44,0x41,0x54,0x38,0xcb,0x8d,0x93,0x4d,0x4e,0x1b,0x41,0x10,0x85,0xbf,0xea,0xaa,0x1e,0x20,0x83,0xf9,0x9,0x36,0xb2,0x85,0x72,0x84,0x8,0x65,0x11,0xe5,0xc,0x9c,0x80,0x73,0x10,0xee,0xc1,0x41,0x38,0x1,0xab,0xec,0xa3,0x2c,0x2,0x8a,0xe0,0x2,0x51,0xc2,0x48,0x46,0x42,0x64,0xc6,0x91,0x21,0xf4,0x74,0x16,0x2e,0xb0,0x71,0x2,0xf2,0x93,0x9e,0xba,0x16,0xdd,0xaf,0x5e,0xa9,0x5f,0x9,0x60,0x40,0x1,0x2c,0x1,0xcb,0x5e,0x2b,0x10,0x78,0x8a,0x16,0x48,0xc0,0x1d,0x30,0x6,0x6e,0x81,0x3b,0xf3,0x87,0x25,0xb0,0x9,0xac,0x7b,0xbd,0xc,0x88,0x13,0x20,0x3b,0xc7,0xc0,0x8,0xb8,0x1,0xae,0x81,0x91,0xf9,0xe5,0xad,0x77,0xbb,0x1f,0xf6,0x7b,0xdd,0xfe,0x41,0x4a,0x69,0x2d,0x93,0xf9,0x1f,0x4,0x41,0x55,0x7f,0xd,0xaf,0xaa,0xa3,0xaf,0x67,0x9f,0x8f,0x81,0x64,0xde,0xb1,0xbb,0xdd,0x1b,0x7c,0xac,0x9b,0x9b,0xce,0xd9,0xb7,0x2f,0xfc,0xf3,0x5e,0xa6,0xe5,0xee,0xdb,0xf7,0x6b,0xdb,0xbd,0xc1,0x21,0xf0,0x9,0x18,0x5,0x60,0x5,0xd8,0x48,0x6d,0xdb,0x39,0xbf,0x38,0xc5,0x34,0x62,0x36,0x47,0x9d,0xf2,0xfc,0xe2,0x94,0xd4,0xb6,0x1d,0x60,0x3,0x58,0x31,0x20,0x2,0x65,0x40,0x88,0x31,0x92,0xbd,0xbb,0x8,0xe4,0x3c,0x39,0x67,0x91,0x33,0x84,0x89,0xa5,0x12,0x88,0xf,0x3f,0x10,0x45,0x5,0xb3,0xc8,0x73,0x10,0x11,0xb2,0xab,0x8b,0xa,0xde,0xb8,0x30,0x9f,0xb0,0x8,0xa2,0xc4,0x58,0xb0,0x8,0x82,0x28,0xde,0x58,0xcc,0xff,0x5c,0x45,0x64,0x61,0x1,0x99,0xcc,0xa5,0x80,0x4e,0x5,0xc2,0xcb,0x2,0xe2,0x41,0x10,0x40,0xc2,0x53,0x81,0xc,0xa8,0x8a,0x52,0x2c,0xe8,0x40,0x27,0x23,0x28,0x90,0xcd,0xe3,0x79,0x1b,0x34,0x50,0x14,0x4b,0xf0,0x4c,0x88,0x66,0xbd,0x4,0xd,0x78,0x94,0x93,0x79,0x3c,0x9b,0x18,0x63,0x7a,0xbd,0xb9,0xa5,0xcd,0xa8,0x7e,0xb4,0x3a,0x2f,0x15,0x10,0xca,0x72,0x95,0x18,0x8b,0x4,0x34,0xc0,0xd8,0x80,0x1a,0x18,0x56,0xd5,0xcf,0x93,0x41,0x7f,0x67,0xaf,0xb3,0xba,0x1e,0x5e,0x8a,0xb2,0x99,0xb5,0x97,0xd5,0x8f,0x13,0x60,0x8,0xd4,0x2,0x74,0x9d,0x6f,0x80,0xbe,0x2f,0x55,0xe9,0x26,0xc2,0xcc,0x26,0x66,0x5f,0xa4,0x6b,0xa0,0x2,0xbe,0x3,0x57,0xe6,0x56,0x1e,0x66,0x1a,0x2,0xaf,0x3c,0x24,0x36,0x67,0xe0,0x1e,0xf8,0x3,0xfc,0xf6,0x6d,0xac,0x81,0xe6,0x2f,0x7c,0x22,0x6d,0x74,0x25,0xb,0xb3,0xa2,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char button_pressed_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x7, 0x1c, 0xc, 0x14, 0x2b, 0xf9, 0x77, 0x52, 0x64, 0x0, 0x0, 0x1, 0x92, 0x49, 0x44, 0x41, 0x54, 0x38, 0xcb, 0x8d, 0x93, 0x4d, 0x4e, 0x1b, 0x41, 0x10, 0x85, 0xbf, 0xea, 0xaa, 0x1e, 0x20, 0x83, 0xf9, 0x9, 0x36, 0xb2, 0x85, 0x72, 0x84, 0x8, 0x65, 0x11, 0xe5, 0xc, 0x9c, 0x80, 0x73, 0x10, 0xee, 0xc1, 0x41, 0x38, 0x1, 0xab, 0xec, 0xa3, 0x2c, 0x2, 0x8a, 0xe0, 0x2, 0x51, 0xc2, 0x48, 0x46, 0x42, 0x64, 0xc6, 0x91, 0x21, 0xf4, 0x74, 0x16, 0x2e, 0xb0, 0x71, 0x2, 0xf2, 0x93, 0x9e, 0xba, 0x16, 0xdd, 0xaf, 0x5e, 0xa9, 0x5f, 0x9, 0x60, 0x40, 0x1, 0x2c, 0x1, 0xcb, 0x5e, 0x2b, 0x10, 0x78, 0x8a, 0x16, 0x48, 0xc0, 0x1d, 0x30, 0x6, 0x6e, 0x81, 0x3b, 0xf3, 0x87, 0x25, 0xb0, 0x9, 0xac, 0x7b, 0xbd, 0xc, 0x88, 0x13, 0x20, 0x3b, 0xc7, 0xc0, 0x8, 0xb8, 0x1, 0xae, 0x81, 0x91, 0xf9, 0xe5, 0xad, 0x77, 0xbb, 0x1f, 0xf6, 0x7b, 0xdd, 0xfe, 0x41, 0x4a, 0x69, 0x2d, 0x93, 0xf9, 0x1f, 0x4, 0x41, 0x55, 0x7f, 0xd, 0xaf, 0xaa, 0xa3, 0xaf, 0x67, 0x9f, 0x8f, 0x81, 0x64, 0xde, 0xb1, 0xbb, 0xdd, 0x1b, 0x7c, 0xac, 0x9b, 0x9b, 0xce, 0xd9, 0xb7, 0x2f, 0xfc, 0xf3, 0x5e, 0xa6, 0xe5, 0xee, 0xdb, 0xf7, 0x6b, 0xdb, 0xbd, 0xc1, 0x21, 0xf0, 0x9, 0x18, 0x5, 0x60, 0x5, 0xd8, 0x48, 0x6d, 0xdb, 0x39, 0xbf, 0x38, 0xc5, 0x34, 0x62, 0x36, 0x47, 0x9d, 0xf2, 0xfc, 0xe2, 0x94, 0xd4, 0xb6, 0x1d, 0x60, 0x3, 0x58, 0x31, 0x20, 0x2, 0x65, 0x40, 0x88, 0x31, 0x92, 0xbd, 0xbb, 0x8, 0xe4, 0x3c, 0x39, 0x67, 0x91, 0x33, 0x84, 0x89, 0xa5, 0x12, 0x88, 0xf, 0x3f, 0x10, 0x45, 0x5, 0xb3, 0xc8, 0x73, 0x10, 0x11, 0xb2, 0xab, 0x8b, 0xa, 0xde, 0xb8, 0x30, 0x9f, 0xb0, 0x8, 0xa2, 0xc4, 0x58, 0xb0, 0x8, 0x82, 0x28, 0xde, 0x58, 0xcc, 0xff, 0x5c, 0x45, 0x64, 0x61, 0x1, 0x99, 0xcc, 0xa5, 0x80, 0x4e, 0x5, 0xc2, 0xcb, 0x2, 0xe2, 0x41, 0x10, 0x40, 0xc2, 0x53, 0x81, 0xc, 0xa8, 0x8a, 0x52, 0x2c, 0xe8, 0x40, 0x27, 0x23, 0x28, 0x90, 0xcd, 0xe3, 0x79, 0x1b, 0x34, 0x50, 0x14, 0x4b, 0xf0, 0x4c, 0x88, 0x66, 0xbd, 0x4, 0xd, 0x78, 0x94, 0x93, 0x79, 0x3c, 0x9b, 0x18, 0x63, 0x7a, 0xbd, 0xb9, 0xa5, 0xcd, 0xa8, 0x7e, 0xb4, 0x3a, 0x2f, 0x15, 0x10, 0xca, 0x72, 0x95, 0x18, 0x8b, 0x4, 0x34, 0xc0, 0xd8, 0x80, 0x1a, 0x18, 0x56, 0xd5, 0xcf, 0x93, 0x41, 0x7f, 0x67, 0xaf, 0xb3, 0xba, 0x1e, 0x5e, 0x8a, 0xb2, 0x99, 0xb5, 0x97, 0xd5, 0x8f, 0x13, 0x60, 0x8, 0xd4, 0x2, 0x74, 0x9d, 0x6f, 0x80, 0xbe, 0x2f, 0x55, 0xe9, 0x26, 0xc2, 0xcc, 0x26, 0x66, 0x5f, 0xa4, 0x6b, 0xa0, 0x2, 0xbe, 0x3, 0x57, 0xe6, 0x56, 0x1e, 0x66, 0x1a, 0x2, 0xaf, 0x3c, 0x24, 0x36, 0x67, 0xe0, 0x1e, 0xf8, 0x3, 0xfc, 0xf6, 0x6d, 0xac, 0x81, 0xe6, 0x2f, 0x7c, 0x22, 0x6d, 0x74, 0x25, 0xb, 0xb3, 0xa2, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char checked_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x8d,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x58,0x56,0x63,0xb0,0xaf,0xb5,0x38,0x37,0x40,0x20,0x20,0x24,0xb6,0xb6,0xb9,0x57,0x57,0x5a,0x20,0x20,0x24,0x38,0x36,0x40,0x20,0x20,0x25,0x1e,0x1e,0x22,0x1f,0x1f,0x23,0x8b,0x8b,0x8d,0xff,0xff,0xff,0x20,0x20,0x24,0x22,0x22,0x27,0x23,0x23,0x28,0x42,0x42,0x47,0xf8,0xf8,0xf8,0xfe,0xfe,0xfe,0x25,0x25,0x2a,0x4e,0x4e,0x52,0x26,0x26,0x2b,0xc5,0xc5,0xc7,0xaa,0xaa,0xab,0xb8,0xb8,0xba,0x5f,0x5f,0x63,0x74,0x74,0x77,0xed,0xed,0xed,0x33,0x33,0x38,0x8d,0x8d,0x8f,0xb8,0xb8,0xb9,0x35,0x35,0x39,0x3a,0x3a,0x3e,0xfb,0xfb,0xfb,0xfa,0xfa,0xfa,0xb2,0xb2,0xb4,0x45,0x45,0x49,0x61,0x61,0x65,0x8f,0x8f,0x92,0x63,0x63,0x66,0x2a,0x2a,0x2f,0x40,0x82,0xb,0xf6,0x0,0x0,0x0,0xf,0x74,0x52,0x4e,0x53,0x0,0x7,0x27,0x50,0x66,0x68,0x6a,0x81,0xb4,0xfa,0xdd,0xfb,0xfb,0xb4,0xfa,0xb8,0xf0,0x7f,0x59,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x12,0x7b,0xbc,0x6c,0x0,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x4,0x4e,0x1d,0x2,0xaf,0x0,0x0,0x0,0x8e,0x49,0x44,0x41,0x54,0x18,0xd3,0x65,0xcf,0x5b,0x12,0x82,0x30,0xc,0x40,0x51,0x48,0x5b,0x15,0x5,0x5b,0x42,0x2b,0x4,0x50,0x40,0xc5,0xb7,0xee,0x7f,0x79,0x96,0x8a,0x88,0x7a,0x3f,0xcf,0x4c,0x26,0x89,0xe7,0xfd,0xe5,0x3,0xe3,0xc2,0x35,0x99,0x82,0x6f,0x1,0x66,0x81,0x54,0xae,0x18,0xe7,0x60,0x81,0x5,0x89,0x36,0x5d,0xab,0x34,0x5b,0x30,0xb,0x5c,0x6a,0xa2,0xbc,0x20,0x2a,0x71,0x2d,0xb9,0x5,0xa1,0xc,0x6d,0xb0,0xa2,0x1a,0x9b,0xad,0x12,0x3d,0xec,0x70,0xdf,0x36,0x58,0x9b,0x1,0xe,0xc7,0xd3,0x19,0x4b,0xfa,0x80,0x9d,0xc9,0xd2,0xcb,0x18,0xae,0x88,0x37,0x1a,0x43,0x91,0xdf,0x1f,0x6f,0x70,0x6b,0x5f,0x69,0xb7,0x76,0x38,0xcc,0xe8,0x24,0xec,0xe,0x83,0x28,0xec,0x4f,0x97,0xcb,0x8,0xbe,0x9e,0xe3,0xcc,0x3d,0xf7,0xd3,0x13,0x10,0x58,0xd,0x44,0xd4,0xa5,0x38,0x3e,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char checked_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x8d, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x58, 0x56, 0x63, 0xb0, 0xaf, 0xb5, 0x38, 0x37, 0x40, 0x20, 0x20, 0x24, 0xb6, 0xb6, 0xb9, 0x57, 0x57, 0x5a, 0x20, 0x20, 0x24, 0x38, 0x36, 0x40, 0x20, 0x20, 0x25, 0x1e, 0x1e, 0x22, 0x1f, 0x1f, 0x23, 0x8b, 0x8b, 0x8d, 0xff, 0xff, 0xff, 0x20, 0x20, 0x24, 0x22, 0x22, 0x27, 0x23, 0x23, 0x28, 0x42, 0x42, 0x47, 0xf8, 0xf8, 0xf8, 0xfe, 0xfe, 0xfe, 0x25, 0x25, 0x2a, 0x4e, 0x4e, 0x52, 0x26, 0x26, 0x2b, 0xc5, 0xc5, 0xc7, 0xaa, 0xaa, 0xab, 0xb8, 0xb8, 0xba, 0x5f, 0x5f, 0x63, 0x74, 0x74, 0x77, 0xed, 0xed, 0xed, 0x33, 0x33, 0x38, 0x8d, 0x8d, 0x8f, 0xb8, 0xb8, 0xb9, 0x35, 0x35, 0x39, 0x3a, 0x3a, 0x3e, 0xfb, 0xfb, 0xfb, 0xfa, 0xfa, 0xfa, 0xb2, 0xb2, 0xb4, 0x45, 0x45, 0x49, 0x61, 0x61, 0x65, 0x8f, 0x8f, 0x92, 0x63, 0x63, 0x66, 0x2a, 0x2a, 0x2f, 0x40, 0x82, 0xb, 0xf6, 0x0, 0x0, 0x0, 0xf, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x7, 0x27, 0x50, 0x66, 0x68, 0x6a, 0x81, 0xb4, 0xfa, 0xdd, 0xfb, 0xfb, 0xb4, 0xfa, 0xb8, 0xf0, 0x7f, 0x59, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x12, 0x7b, 0xbc, 0x6c, 0x0, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x4, 0x4e, 0x1d, 0x2, 0xaf, 0x0, 0x0, 0x0, 0x8e, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x65, 0xcf, 0x5b, 0x12, 0x82, 0x30, 0xc, 0x40, 0x51, 0x48, 0x5b, 0x15, 0x5, 0x5b, 0x42, 0x2b, 0x4, 0x50, 0x40, 0xc5, 0xb7, 0xee, 0x7f, 0x79, 0x96, 0x8a, 0x88, 0x7a, 0x3f, 0xcf, 0x4c, 0x26, 0x89, 0xe7, 0xfd, 0xe5, 0x3, 0xe3, 0xc2, 0x35, 0x99, 0x82, 0x6f, 0x1, 0x66, 0x81, 0x54, 0xae, 0x18, 0xe7, 0x60, 0x81, 0x5, 0x89, 0x36, 0x5d, 0xab, 0x34, 0x5b, 0x30, 0xb, 0x5c, 0x6a, 0xa2, 0xbc, 0x20, 0x2a, 0x71, 0x2d, 0xb9, 0x5, 0xa1, 0xc, 0x6d, 0xb0, 0xa2, 0x1a, 0x9b, 0xad, 0x12, 0x3d, 0xec, 0x70, 0xdf, 0x36, 0x58, 0x9b, 0x1, 0xe, 0xc7, 0xd3, 0x19, 0x4b, 0xfa, 0x80, 0x9d, 0xc9, 0xd2, 0xcb, 0x18, 0xae, 0x88, 0x37, 0x1a, 0x43, 0x91, 0xdf, 0x1f, 0x6f, 0x70, 0x6b, 0x5f, 0x69, 0xb7, 0x76, 0x38, 0xcc, 0xe8, 0x24, 0xec, 0xe, 0x83, 0x28, 0xec, 0x4f, 0x97, 0xcb, 0x8, 0xbe, 0x9e, 0xe3, 0xcc, 0x3d, 0xf7, 0xd3, 0x13, 0x10, 0x58, 0xd, 0x44, 0xd4, 0xa5, 0x38, 0x3e, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char checker_bg_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x0,0x0,0x0,0x0,0xe1,0x64,0xe1,0x57,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xe,0xc4,0x0,0x0,0xe,0xc4,0x1,0x95,0x2b,0xe,0x1b,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x1a,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0xfc,0xcf,0xc0,0xc0,0xd0,0xc0,0xc0,0xc0,0xc0,0xc4,0x0,0x5,0x98,0xc,0xc6,0x7a,0xc2,0x6a,0x0,0x8b,0x7a,0x2,0x8d,0x68,0x67,0xe3,0xa,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char checker_bg_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x8, 0x0, 0x0, 0x0, 0x0, 0xe1, 0x64, 0xe1, 0x57, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xe, 0xc4, 0x0, 0x0, 0xe, 0xc4, 0x1, 0x95, 0x2b, 0xe, 0x1b, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x1a, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0xfc, 0xcf, 0xc0, 0xc0, 0xd0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc4, 0x0, 0x5, 0x98, 0xc, 0xc6, 0x7a, 0xc2, 0x6a, 0x0, 0x8b, 0x7a, 0x2, 0x8d, 0x68, 0x67, 0xe3, 0xa, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char close_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9b,0x49,0x44,0x41,0x54,0x38,0x8d,0xcd,0x92,0x31,0xe,0xc2,0x30,0x10,0x4,0x17,0xaa,0x3d,0x67,0xdb,0x58,0xd0,0xd3,0xf0,0xa3,0x7c,0x36,0x3c,0x82,0x48,0x44,0x22,0x6f,0xb1,0x4d,0x85,0x14,0x81,0xf,0x2c,0x28,0xe0,0xda,0xd5,0x8c,0x4e,0x77,0xb,0xfc,0xd5,0x98,0xd9,0x20,0x29,0x7a,0xb9,0xa4,0x68,0x66,0x83,0xb,0x93,0xcc,0x24,0xa7,0x9a,0x44,0x52,0x24,0x39,0x91,0xcc,0x55,0x89,0xa4,0xde,0xcc,0xce,0x24,0xb,0xc9,0x39,0x84,0xb0,0xf7,0xb2,0xae,0xeb,0x76,0xde,0x8a,0x4f,0x92,0x66,0xd8,0x91,0x5c,0x49,0x5e,0x9a,0xe1,0xb5,0x64,0x5,0x16,0x92,0x8b,0x7,0x6f,0x9b,0x8c,0x0,0x4a,0x29,0x9b,0x26,0x81,0xa4,0x3e,0xa5,0x34,0x2,0x38,0x2,0x58,0x0,0xcc,0x0,0xe,0x39,0xe7,0xd3,0xfa,0xb0,0xee,0xea,0x8f,0x7,0x7b,0xf5,0x9d,0xb7,0xb0,0x97,0x55,0x25,0x5f,0x17,0xe9,0x2e,0xf9,0xb8,0xca,0x3f,0x9b,0x1b,0x1a,0xe3,0x40,0x47,0xa0,0xda,0xda,0x61,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char close_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0x9b, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xcd, 0x92, 0x31, 0xe, 0xc2, 0x30, 0x10, 0x4, 0x17, 0xaa, 0x3d, 0x67, 0xdb, 0x58, 0xd0, 0xd3, 0xf0, 0xa3, 0x7c, 0x36, 0x3c, 0x82, 0x48, 0x44, 0x22, 0x6f, 0xb1, 0x4d, 0x85, 0x14, 0x81, 0xf, 0x2c, 0x28, 0xe0, 0xda, 0xd5, 0x8c, 0x4e, 0x77, 0xb, 0xfc, 0xd5, 0x98, 0xd9, 0x20, 0x29, 0x7a, 0xb9, 0xa4, 0x68, 0x66, 0x83, 0xb, 0x93, 0xcc, 0x24, 0xa7, 0x9a, 0x44, 0x52, 0x24, 0x39, 0x91, 0xcc, 0x55, 0x89, 0xa4, 0xde, 0xcc, 0xce, 0x24, 0xb, 0xc9, 0x39, 0x84, 0xb0, 0xf7, 0xb2, 0xae, 0xeb, 0x76, 0xde, 0x8a, 0x4f, 0x92, 0x66, 0xd8, 0x91, 0x5c, 0x49, 0x5e, 0x9a, 0xe1, 0xb5, 0x64, 0x5, 0x16, 0x92, 0x8b, 0x7, 0x6f, 0x9b, 0x8c, 0x0, 0x4a, 0x29, 0x9b, 0x26, 0x81, 0xa4, 0x3e, 0xa5, 0x34, 0x2, 0x38, 0x2, 0x58, 0x0, 0xcc, 0x0, 0xe, 0x39, 0xe7, 0xd3, 0xfa, 0xb0, 0xee, 0xea, 0x8f, 0x7, 0x7b, 0xf5, 0x9d, 0xb7, 0xb0, 0x97, 0x55, 0x25, 0x5f, 0x17, 0xe9, 0x2e, 0xf9, 0xb8, 0xca, 0x3f, 0x9b, 0x1b, 0x1a, 0xe3, 0x40, 0x47, 0xa0, 0xda, 0xda, 0x61, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char close_hl_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9b,0x49,0x44,0x41,0x54,0x38,0x8d,0xcd,0x92,0x31,0xe,0xc2,0x30,0x10,0x4,0x17,0xaa,0x3d,0x67,0xdb,0x58,0xd0,0xd3,0xf0,0xa3,0x7c,0x36,0x3c,0x82,0x48,0x44,0x22,0x6f,0xb1,0x4d,0x85,0x14,0x81,0xf,0x2c,0x28,0xe0,0xda,0xd5,0x8c,0x4e,0x77,0xb,0xfc,0xd5,0x98,0xd9,0x20,0x29,0x7a,0xb9,0xa4,0x68,0x66,0x83,0xb,0x93,0xcc,0x24,0xa7,0x9a,0x44,0x52,0x24,0x39,0x91,0xcc,0x55,0x89,0xa4,0xde,0xcc,0xce,0x24,0xb,0xc9,0x39,0x84,0xb0,0xf7,0xb2,0xae,0xeb,0x76,0xde,0x8a,0x4f,0x92,0x66,0xd8,0x91,0x5c,0x49,0x5e,0x9a,0xe1,0xb5,0x64,0x5,0x16,0x92,0x8b,0x7,0x6f,0x9b,0x8c,0x0,0x4a,0x29,0x9b,0x26,0x81,0xa4,0x3e,0xa5,0x34,0x2,0x38,0x2,0x58,0x0,0xcc,0x0,0xe,0x39,0xe7,0xd3,0xfa,0xb0,0xee,0xea,0x8f,0x7,0x7b,0xf5,0x9d,0xb7,0xb0,0x97,0x55,0x25,0x5f,0x17,0xe9,0x2e,0xf9,0xb8,0xca,0x3f,0x9b,0x1b,0x1a,0xe3,0x40,0x47,0xa0,0xda,0xda,0x61,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char close_hl_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0x9b, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xcd, 0x92, 0x31, 0xe, 0xc2, 0x30, 0x10, 0x4, 0x17, 0xaa, 0x3d, 0x67, 0xdb, 0x58, 0xd0, 0xd3, 0xf0, 0xa3, 0x7c, 0x36, 0x3c, 0x82, 0x48, 0x44, 0x22, 0x6f, 0xb1, 0x4d, 0x85, 0x14, 0x81, 0xf, 0x2c, 0x28, 0xe0, 0xda, 0xd5, 0x8c, 0x4e, 0x77, 0xb, 0xfc, 0xd5, 0x98, 0xd9, 0x20, 0x29, 0x7a, 0xb9, 0xa4, 0x68, 0x66, 0x83, 0xb, 0x93, 0xcc, 0x24, 0xa7, 0x9a, 0x44, 0x52, 0x24, 0x39, 0x91, 0xcc, 0x55, 0x89, 0xa4, 0xde, 0xcc, 0xce, 0x24, 0xb, 0xc9, 0x39, 0x84, 0xb0, 0xf7, 0xb2, 0xae, 0xeb, 0x76, 0xde, 0x8a, 0x4f, 0x92, 0x66, 0xd8, 0x91, 0x5c, 0x49, 0x5e, 0x9a, 0xe1, 0xb5, 0x64, 0x5, 0x16, 0x92, 0x8b, 0x7, 0x6f, 0x9b, 0x8c, 0x0, 0x4a, 0x29, 0x9b, 0x26, 0x81, 0xa4, 0x3e, 0xa5, 0x34, 0x2, 0x38, 0x2, 0x58, 0x0, 0xcc, 0x0, 0xe, 0x39, 0xe7, 0xd3, 0xfa, 0xb0, 0xee, 0xea, 0x8f, 0x7, 0x7b, 0xf5, 0x9d, 0xb7, 0xb0, 0x97, 0x55, 0x25, 0x5f, 0x17, 0xe9, 0x2e, 0xf9, 0xb8, 0xca, 0x3f, 0x9b, 0x1b, 0x1a, 0xe3, 0x40, 0x47, 0xa0, 0xda, 0xda, 0x61, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char color_picker_hue_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x1,0x0,0x0,0x1,0x0,0x8,0x2,0x0,0x0,0x0,0xfd,0x5c,0x8b,0xcf,0x0,0x0,0x0,0x59,0x49,0x44,0x41,0x54,0x28,0x91,0xcd,0xd0,0x31,0xa,0x3,0x31,0x10,0x43,0xd1,0x87,0xc0,0xf6,0xfd,0x8f,0x1b,0xdb,0x30,0x69,0x76,0x21,0x65,0xd8,0x14,0x71,0xf1,0xf9,0x8c,0x84,0x9a,0x51,0x44,0x13,0xfd,0x21,0xe3,0x87,0xed,0xf7,0xa8,0xcd,0x2a,0x99,0x8e,0x46,0x2b,0x94,0xd0,0x43,0xb,0xe3,0x64,0xb3,0x2a,0xa6,0x93,0xb9,0x9f,0x9a,0x4e,0x3a,0x69,0x97,0xc7,0xe5,0x3b,0x1b,0xff,0xef,0x6d,0xa5,0xec,0x30,0xc3,0xeb,0xf2,0xc,0xeb,0xe3,0x5e,0x27,0xf4,0x8a,0x37,0x75,0x7b,0x8a,0xe5,0x90,0x9a,0xab,0x81,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char color_picker_hue_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1, 0x0, 0x8, 0x2, 0x0, 0x0, 0x0, 0xfd, 0x5c, 0x8b, 0xcf, 0x0, 0x0, 0x0, 0x59, 0x49, 0x44, 0x41, 0x54, 0x28, 0x91, 0xcd, 0xd0, 0x31, 0xa, 0x3, 0x31, 0x10, 0x43, 0xd1, 0x87, 0xc0, 0xf6, 0xfd, 0x8f, 0x1b, 0xdb, 0x30, 0x69, 0x76, 0x21, 0x65, 0xd8, 0x14, 0x71, 0xf1, 0xf9, 0x8c, 0x84, 0x9a, 0x51, 0x44, 0x13, 0xfd, 0x21, 0xe3, 0x87, 0xed, 0xf7, 0xa8, 0xcd, 0x2a, 0x99, 0x8e, 0x46, 0x2b, 0x94, 0xd0, 0x43, 0xb, 0xe3, 0x64, 0xb3, 0x2a, 0xa6, 0x93, 0xb9, 0x9f, 0x9a, 0x4e, 0x3a, 0x69, 0x97, 0xc7, 0xe5, 0x3b, 0x1b, 0xff, 0xef, 0x6d, 0xa5, 0xec, 0x30, 0xc3, 0xeb, 0xf2, 0xc, 0xeb, 0xe3, 0x5e, 0x27, 0xf4, 0x8a, 0x37, 0x75, 0x7b, 0x8a, 0xe5, 0x90, 0x9a, 0xab, 0x81, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char color_picker_sample_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x14,0x8,0x2,0x0,0x0,0x0,0xed,0x20,0x74,0x8,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x9,0x18,0xc,0x27,0x37,0x29,0x4f,0x42,0x2d,0x0,0x0,0x0,0x61,0x49,0x44,0x41,0x54,0x68,0xde,0xed,0xd9,0xb1,0xd,0x0,0x21,0xc,0x3,0x40,0x40,0xbf,0x5f,0x66,0xcd,0x84,0xf9,0x96,0x19,0xf0,0x5d,0x87,0x5c,0x5b,0x9,0xca,0x9e,0x99,0x75,0xe9,0xee,0xfb,0x59,0x55,0x52,0xe9,0xc3,0xe9,0x59,0x10,0x4c,0x1,0x50,0x0,0x50,0x0,0x8,0xf4,0xf9,0x15,0x49,0x93,0x53,0x13,0x0,0x2b,0x10,0x28,0x0,0x28,0x0,0x64,0xd9,0x2e,0xc1,0xd2,0xe4,0xd4,0x4,0xc0,0xa,0x4,0xa,0x0,0xa,0x0,0x59,0x5c,0x82,0xa5,0xd1,0xa9,0x9,0x80,0x15,0x8,0x14,0x0,0x14,0x0,0xb2,0xfc,0x5b,0xb2,0x3c,0x5a,0x4,0xa1,0xf3,0x57,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char color_picker_sample_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x14, 0x8, 0x2, 0x0, 0x0, 0x0, 0xed, 0x20, 0x74, 0x8, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x9, 0x18, 0xc, 0x27, 0x37, 0x29, 0x4f, 0x42, 0x2d, 0x0, 0x0, 0x0, 0x61, 0x49, 0x44, 0x41, 0x54, 0x68, 0xde, 0xed, 0xd9, 0xb1, 0xd, 0x0, 0x21, 0xc, 0x3, 0x40, 0x40, 0xbf, 0x5f, 0x66, 0xcd, 0x84, 0xf9, 0x96, 0x19, 0xf0, 0x5d, 0x87, 0x5c, 0x5b, 0x9, 0xca, 0x9e, 0x99, 0x75, 0xe9, 0xee, 0xfb, 0x59, 0x55, 0x52, 0xe9, 0xc3, 0xe9, 0x59, 0x10, 0x4c, 0x1, 0x50, 0x0, 0x50, 0x0, 0x8, 0xf4, 0xf9, 0x15, 0x49, 0x93, 0x53, 0x13, 0x0, 0x2b, 0x10, 0x28, 0x0, 0x28, 0x0, 0x64, 0xd9, 0x2e, 0xc1, 0xd2, 0xe4, 0xd4, 0x4, 0xc0, 0xa, 0x4, 0xa, 0x0, 0xa, 0x0, 0x59, 0x5c, 0x82, 0xa5, 0xd1, 0xa9, 0x9, 0x80, 0x15, 0x8, 0x14, 0x0, 0x14, 0x0, 0xb2, 0xfc, 0x5b, 0xb2, 0x3c, 0x5a, 0x4, 0xa1, 0xf3, 0x57, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char dosfont_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x80,0x0,0x0,0x0,0x80,0x1,0x0,0x0,0x0,0x0,0xeb,0x45,0x5c,0x66,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x74,0x52,0x4e,0x53,0x0,0x0,0x76,0x93,0xcd,0x38,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0x1,0xdd,0x8a,0x13,0xa4,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x89,0x0,0x0,0xb,0x89,0x1,0x37,0xc9,0xcb,0xad,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x2,0x83,0x49,0x44,0x41,0x54,0x48,0xc7,0xed,0xd4,0xb1,0x6e,0xdb,0x30,0x10,0x0,0x50,0x22,0x3,0x27,0x22,0xc8,0x78,0x83,0x91,0xa9,0x1f,0xc0,0xa9,0x10,0xa,0x7e,0xc,0x11,0x14,0x87,0xc,0x1c,0x32,0x9,0x1a,0xe,0x46,0xa6,0xfc,0x43,0xff,0x86,0xb5,0x80,0x9b,0x88,0x8e,0x5d,0x64,0x18,0x9e,0xdc,0xd5,0x53,0x91,0xc1,0xa0,0x7a,0xa4,0xe4,0xd4,0x31,0xd2,0x25,0x70,0x97,0xa2,0x37,0x48,0xe6,0x33,0x45,0xdd,0x51,0x24,0x95,0x7a,0x23,0xe0,0x75,0x13,0xb,0xd8,0x93,0xbf,0x51,0x51,0xa3,0xac,0x99,0xc9,0x29,0x87,0x81,0x83,0xb2,0x0,0xc7,0xfe,0xee,0x43,0x58,0x85,0x95,0xb7,0xa6,0xb6,0xaf,0x7a,0xe9,0x93,0x63,0xc3,0xf2,0xc,0x96,0x3e,0xba,0x97,0x11,0x3,0xb5,0x46,0xc0,0x15,0x30,0x43,0x1,0xbd,0x6,0x81,0x71,0xa9,0xb2,0x82,0x9,0x92,0x3d,0xf6,0xb0,0xbd,0x5c,0xf2,0x53,0xf2,0x75,0xc,0x11,0x5f,0xc7,0xe0,0xc4,0xaa,0xb4,0x40,0x41,0xc4,0x69,0xd0,0x27,0x55,0x12,0x13,0x78,0x74,0xa7,0xb5,0xd8,0x3f,0x14,0x77,0x81,0x0,0x22,0x93,0x9b,0x4c,0x54,0x5b,0x72,0x6d,0x98,0x17,0xd1,0x33,0xb3,0x94,0xaa,0x3c,0x93,0xea,0xb4,0x76,0x31,0x6a,0x66,0x0,0xa9,0x59,0x1c,0x8c,0xe,0x33,0xc0,0x12,0x4c,0x29,0xc2,0xa5,0xc3,0xc1,0xd0,0xb2,0x64,0x6a,0x60,0xa3,0xc0,0xea,0xac,0x19,0x58,0x4b,0xa9,0x4a,0x17,0xf0,0xda,0x68,0xb6,0x5,0xec,0xb2,0xf6,0x88,0x33,0xc8,0x18,0x52,0xd5,0x5a,0x1,0xb3,0x61,0x1,0x53,0xdf,0x2,0x51,0x2d,0x33,0xdd,0x12,0x59,0xea,0x94,0x95,0x3c,0x80,0x2e,0x5e,0xf9,0xdb,0x71,0x73,0x70,0xcf,0x39,0x3b,0x76,0xb7,0xbb,0x7d,0xcf,0x74,0x50,0xd,0x62,0x40,0x44,0x6,0x83,0xfe,0xc7,0x8e,0x51,0x5,0x5c,0xe1,0xdd,0xdd,0xaa,0xc2,0xf8,0x53,0x80,0x31,0xe2,0xfd,0x7d,0x14,0x8,0x7e,0xcc,0x5,0x28,0x62,0xd7,0xc5,0xc,0xa6,0xf3,0xc3,0x46,0xa6,0x30,0xd7,0x1e,0x1b,0x2e,0xd0,0x7f,0x63,0x5f,0x1f,0xf1,0x32,0xc9,0x90,0x82,0xef,0xb9,0x82,0xc,0x5a,0x1,0xef,0x66,0x90,0xd7,0x7a,0x2c,0x80,0x13,0x94,0xc4,0xf6,0x9f,0xd8,0x75,0xbb,0x2c,0x89,0xed,0xff,0x42,0xe9,0xa7,0xfb,0xa4,0x84,0xec,0x13,0x45,0x7,0x1a,0xb9,0x97,0x18,0x65,0xab,0x4,0xf9,0x54,0x8c,0x3c,0x54,0xe8,0xed,0xa3,0x7c,0x7b,0x55,0xe0,0x8b,0x0,0xf6,0x4f,0x36,0xd6,0x3d,0xc3,0xe8,0x41,0xc0,0xa1,0xb1,0xdb,0x9,0xa8,0x29,0x0,0xe,0xec,0xc3,0x4,0xc1,0x8,0xc,0x0,0xd6,0x36,0xf3,0x23,0xba,0x80,0x3,0x6f,0x17,0x15,0xbe,0x4b,0xe5,0x8c,0x23,0xc2,0x57,0x7b,0x5d,0x61,0x53,0xc0,0x61,0xf,0xbd,0xd5,0x15,0x68,0x47,0x8e,0x0,0x7b,0x37,0xba,0xab,0xba,0x59,0xcc,0x79,0x3d,0xd7,0xaf,0x5a,0xe3,0x85,0x66,0x69,0xab,0x16,0x32,0x31,0x5b,0xd0,0xdb,0x66,0x2,0x2f,0x6f,0xe,0xb2,0x42,0xb5,0x87,0xdf,0xf0,0x59,0xae,0x6a,0x86,0xae,0x93,0x4c,0x7d,0x1b,0x9a,0x6b,0x84,0xdd,0x9a,0xd6,0xca,0xc8,0x89,0xc3,0xfb,0xd4,0x82,0xe,0x30,0xa2,0x2c,0x18,0xc2,0x98,0xb2,0x4f,0x8,0xba,0x83,0xa1,0x40,0x12,0x88,0x6f,0x43,0x38,0x82,0x1c,0x1f,0x15,0x70,0x82,0x96,0xa8,0xa5,0x3d,0xed,0x9c,0xde,0xb9,0x1,0xe9,0xb8,0x5f,0x4c,0x39,0xd2,0xa6,0xac,0xa6,0x48,0xe7,0xd0,0x95,0x53,0xb0,0xc4,0x7b,0x97,0xd4,0xcd,0x3c,0xdd,0xf0,0xd0,0x4e,0xbf,0xe6,0x65,0x24,0x5b,0x7b,0x7d,0xe,0xe5,0xd6,0xae,0xe9,0x90,0x64,0xfd,0x70,0x9e,0x21,0xb5,0x6c,0x5,0xa4,0xa2,0x87,0xe9,0xa3,0x25,0xf4,0x5,0x5c,0x39,0x61,0xa6,0x1e,0xbe,0x11,0x18,0x80,0xed,0xb,0x18,0x9b,0x70,0x70,0xec,0x5f,0x80,0x3f,0x26,0x27,0xb3,0xc9,0x33,0xc8,0x5c,0x2c,0x5a,0x59,0x1f,0xcb,0x2c,0x89,0x9d,0xae,0xf,0x7d,0xcc,0xdb,0x9c,0xdd,0xd5,0xed,0x7c,0x7f,0xbe,0xd0,0x52,0xf9,0x1f,0xff,0x76,0xfc,0x2,0x24,0x3a,0x65,0x42,0xf6,0x41,0x91,0x95,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char dosfont_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x80, 0x1, 0x0, 0x0, 0x0, 0x0, 0xeb, 0x45, 0x5c, 0x66, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x2, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x76, 0x93, 0xcd, 0x38, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0x1, 0xdd, 0x8a, 0x13, 0xa4, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x89, 0x0, 0x0, 0xb, 0x89, 0x1, 0x37, 0xc9, 0xcb, 0xad, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x2, 0x83, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xed, 0xd4, 0xb1, 0x6e, 0xdb, 0x30, 0x10, 0x0, 0x50, 0x22, 0x3, 0x27, 0x22, 0xc8, 0x78, 0x83, 0x91, 0xa9, 0x1f, 0xc0, 0xa9, 0x10, 0xa, 0x7e, 0xc, 0x11, 0x14, 0x87, 0xc, 0x1c, 0x32, 0x9, 0x1a, 0xe, 0x46, 0xa6, 0xfc, 0x43, 0xff, 0x86, 0xb5, 0x80, 0x9b, 0x88, 0x8e, 0x5d, 0x64, 0x18, 0x9e, 0xdc, 0xd5, 0x53, 0x91, 0xc1, 0xa0, 0x7a, 0xa4, 0xe4, 0xd4, 0x31, 0xd2, 0x25, 0x70, 0x97, 0xa2, 0x37, 0x48, 0xe6, 0x33, 0x45, 0xdd, 0x51, 0x24, 0x95, 0x7a, 0x23, 0xe0, 0x75, 0x13, 0xb, 0xd8, 0x93, 0xbf, 0x51, 0x51, 0xa3, 0xac, 0x99, 0xc9, 0x29, 0x87, 0x81, 0x83, 0xb2, 0x0, 0xc7, 0xfe, 0xee, 0x43, 0x58, 0x85, 0x95, 0xb7, 0xa6, 0xb6, 0xaf, 0x7a, 0xe9, 0x93, 0x63, 0xc3, 0xf2, 0xc, 0x96, 0x3e, 0xba, 0x97, 0x11, 0x3, 0xb5, 0x46, 0xc0, 0x15, 0x30, 0x43, 0x1, 0xbd, 0x6, 0x81, 0x71, 0xa9, 0xb2, 0x82, 0x9, 0x92, 0x3d, 0xf6, 0xb0, 0xbd, 0x5c, 0xf2, 0x53, 0xf2, 0x75, 0xc, 0x11, 0x5f, 0xc7, 0xe0, 0xc4, 0xaa, 0xb4, 0x40, 0x41, 0xc4, 0x69, 0xd0, 0x27, 0x55, 0x12, 0x13, 0x78, 0x74, 0xa7, 0xb5, 0xd8, 0x3f, 0x14, 0x77, 0x81, 0x0, 0x22, 0x93, 0x9b, 0x4c, 0x54, 0x5b, 0x72, 0x6d, 0x98, 0x17, 0xd1, 0x33, 0xb3, 0x94, 0xaa, 0x3c, 0x93, 0xea, 0xb4, 0x76, 0x31, 0x6a, 0x66, 0x0, 0xa9, 0x59, 0x1c, 0x8c, 0xe, 0x33, 0xc0, 0x12, 0x4c, 0x29, 0xc2, 0xa5, 0xc3, 0xc1, 0xd0, 0xb2, 0x64, 0x6a, 0x60, 0xa3, 0xc0, 0xea, 0xac, 0x19, 0x58, 0x4b, 0xa9, 0x4a, 0x17, 0xf0, 0xda, 0x68, 0xb6, 0x5, 0xec, 0xb2, 0xf6, 0x88, 0x33, 0xc8, 0x18, 0x52, 0xd5, 0x5a, 0x1, 0xb3, 0x61, 0x1, 0x53, 0xdf, 0x2, 0x51, 0x2d, 0x33, 0xdd, 0x12, 0x59, 0xea, 0x94, 0x95, 0x3c, 0x80, 0x2e, 0x5e, 0xf9, 0xdb, 0x71, 0x73, 0x70, 0xcf, 0x39, 0x3b, 0x76, 0xb7, 0xbb, 0x7d, 0xcf, 0x74, 0x50, 0xd, 0x62, 0x40, 0x44, 0x6, 0x83, 0xfe, 0xc7, 0x8e, 0x51, 0x5, 0x5c, 0xe1, 0xdd, 0xdd, 0xaa, 0xc2, 0xf8, 0x53, 0x80, 0x31, 0xe2, 0xfd, 0x7d, 0x14, 0x8, 0x7e, 0xcc, 0x5, 0x28, 0x62, 0xd7, 0xc5, 0xc, 0xa6, 0xf3, 0xc3, 0x46, 0xa6, 0x30, 0xd7, 0x1e, 0x1b, 0x2e, 0xd0, 0x7f, 0x63, 0x5f, 0x1f, 0xf1, 0x32, 0xc9, 0x90, 0x82, 0xef, 0xb9, 0x82, 0xc, 0x5a, 0x1, 0xef, 0x66, 0x90, 0xd7, 0x7a, 0x2c, 0x80, 0x13, 0x94, 0xc4, 0xf6, 0x9f, 0xd8, 0x75, 0xbb, 0x2c, 0x89, 0xed, 0xff, 0x42, 0xe9, 0xa7, 0xfb, 0xa4, 0x84, 0xec, 0x13, 0x45, 0x7, 0x1a, 0xb9, 0x97, 0x18, 0x65, 0xab, 0x4, 0xf9, 0x54, 0x8c, 0x3c, 0x54, 0xe8, 0xed, 0xa3, 0x7c, 0x7b, 0x55, 0xe0, 0x8b, 0x0, 0xf6, 0x4f, 0x36, 0xd6, 0x3d, 0xc3, 0xe8, 0x41, 0xc0, 0xa1, 0xb1, 0xdb, 0x9, 0xa8, 0x29, 0x0, 0xe, 0xec, 0xc3, 0x4, 0xc1, 0x8, 0xc, 0x0, 0xd6, 0x36, 0xf3, 0x23, 0xba, 0x80, 0x3, 0x6f, 0x17, 0x15, 0xbe, 0x4b, 0xe5, 0x8c, 0x23, 0xc2, 0x57, 0x7b, 0x5d, 0x61, 0x53, 0xc0, 0x61, 0xf, 0xbd, 0xd5, 0x15, 0x68, 0x47, 0x8e, 0x0, 0x7b, 0x37, 0xba, 0xab, 0xba, 0x59, 0xcc, 0x79, 0x3d, 0xd7, 0xaf, 0x5a, 0xe3, 0x85, 0x66, 0x69, 0xab, 0x16, 0x32, 0x31, 0x5b, 0xd0, 0xdb, 0x66, 0x2, 0x2f, 0x6f, 0xe, 0xb2, 0x42, 0xb5, 0x87, 0xdf, 0xf0, 0x59, 0xae, 0x6a, 0x86, 0xae, 0x93, 0x4c, 0x7d, 0x1b, 0x9a, 0x6b, 0x84, 0xdd, 0x9a, 0xd6, 0xca, 0xc8, 0x89, 0xc3, 0xfb, 0xd4, 0x82, 0xe, 0x30, 0xa2, 0x2c, 0x18, 0xc2, 0x98, 0xb2, 0x4f, 0x8, 0xba, 0x83, 0xa1, 0x40, 0x12, 0x88, 0x6f, 0x43, 0x38, 0x82, 0x1c, 0x1f, 0x15, 0x70, 0x82, 0x96, 0xa8, 0xa5, 0x3d, 0xed, 0x9c, 0xde, 0xb9, 0x1, 0xe9, 0xb8, 0x5f, 0x4c, 0x39, 0xd2, 0xa6, 0xac, 0xa6, 0x48, 0xe7, 0xd0, 0x95, 0x53, 0xb0, 0xc4, 0x7b, 0x97, 0xd4, 0xcd, 0x3c, 0xdd, 0xf0, 0xd0, 0x4e, 0xbf, 0xe6, 0x65, 0x24, 0x5b, 0x7b, 0x7d, 0xe, 0xe5, 0xd6, 0xae, 0xe9, 0x90, 0x64, 0xfd, 0x70, 0x9e, 0x21, 0xb5, 0x6c, 0x5, 0xa4, 0xa2, 0x87, 0xe9, 0xa3, 0x25, 0xf4, 0x5, 0x5c, 0x39, 0x61, 0xa6, 0x1e, 0xbe, 0x11, 0x18, 0x80, 0xed, 0xb, 0x18, 0x9b, 0x70, 0x70, 0xec, 0x5f, 0x80, 0x3f, 0x26, 0x27, 0xb3, 0xc9, 0x33, 0xc8, 0x5c, 0x2c, 0x5a, 0x59, 0x1f, 0xcb, 0x2c, 0x89, 0x9d, 0xae, 0xf, 0x7d, 0xcc, 0xdb, 0x9c, 0xdd, 0xd5, 0xed, 0x7c, 0x7f, 0xbe, 0xd0, 0x52, 0xf9, 0x1f, 0xff, 0x76, 0xfc, 0x2, 0x24, 0x3a, 0x65, 0x42, 0xf6, 0x41, 0x91, 0x95, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char dropdown_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x4,0x0,0x0,0x0,0x6e,0x6,0x76,0x0,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x64,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0x60,0xf8,0xc0,0xcc,0x0,0x5,0x1f,0x98,0x19,0x18,0x18,0x3f,0x30,0xff,0xd3,0x83,0x70,0xff,0x33,0x33,0x30,0x8,0x9f,0x61,0xf9,0x6b,0xff,0x65,0x2f,0x3,0x1c,0xbc,0xea,0x66,0x62,0xbc,0xcf,0xc0,0xc0,0xf0,0x7,0x26,0xc0,0x74,0x89,0x89,0xe9,0x29,0x9f,0x14,0x3,0xb,0xc3,0x5f,0x6,0x6,0x6,0x6,0xee,0x38,0x91,0x25,0xc,0xc,0xc,0x1f,0xd8,0xde,0x4b,0x3e,0xfc,0xff,0xf0,0xff,0x9b,0x58,0xb8,0xce,0xf,0x6c,0xef,0xe4,0xde,0xa4,0x32,0x20,0x83,0xf,0x4c,0x30,0x16,0x0,0x75,0xad,0x1b,0x7f,0x65,0xec,0x78,0x4c,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char dropdown_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x8, 0x4, 0x0, 0x0, 0x0, 0x6e, 0x6, 0x76, 0x0, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x64, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x60, 0xf8, 0xc0, 0xcc, 0x0, 0x5, 0x1f, 0x98, 0x19, 0x18, 0x18, 0x3f, 0x30, 0xff, 0xd3, 0x83, 0x70, 0xff, 0x33, 0x33, 0x30, 0x8, 0x9f, 0x61, 0xf9, 0x6b, 0xff, 0x65, 0x2f, 0x3, 0x1c, 0xbc, 0xea, 0x66, 0x62, 0xbc, 0xcf, 0xc0, 0xc0, 0xf0, 0x7, 0x26, 0xc0, 0x74, 0x89, 0x89, 0xe9, 0x29, 0x9f, 0x14, 0x3, 0xb, 0xc3, 0x5f, 0x6, 0x6, 0x6, 0x6, 0xee, 0x38, 0x91, 0x25, 0xc, 0xc, 0xc, 0x1f, 0xd8, 0xde, 0x4b, 0x3e, 0xfc, 0xff, 0xf0, 0xff, 0x9b, 0x58, 0xb8, 0xce, 0xf, 0x6c, 0xef, 0xe4, 0xde, 0xa4, 0x32, 0x20, 0x83, 0xf, 0x4c, 0x30, 0x16, 0x0, 0x75, 0xad, 0x1b, 0x7f, 0x65, 0xec, 0x78, 0x4c, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char error_icon_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x20,0x8,0x4,0x0,0x0,0x0,0xd9,0x73,0xb2,0x7f,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x5d,0x49,0x44,0x41,0x54,0x48,0xc7,0xed,0x94,0xc1,0xe,0x80,0x20,0xc,0x43,0x5b,0xe3,0xff,0xff,0x72,0x3d,0xcc,0x85,0xa1,0xbb,0x18,0xf4,0x62,0xca,0xa9,0x74,0xe3,0x65,0xd,0x1,0xa,0x6b,0x6b,0x5b,0x3c,0x6f,0x80,0x1,0x7f,0x1,0xec,0x29,0x78,0xbe,0x2a,0x31,0x94,0x98,0x9e,0x98,0xf5,0xab,0x37,0x1,0xaa,0x19,0x8d,0xe2,0x50,0xb1,0x9b,0xbd,0xb7,0x23,0x8c,0x21,0x7b,0xd5,0xf5,0x3d,0x88,0x50,0x1,0xdf,0x46,0xb8,0xf,0x5c,0xef,0xa6,0xab,0xd1,0x7f,0xa2,0x1,0x6,0x0,0x0,0xe,0x62,0x6,0x31,0x47,0xb6,0x7f,0xdd,0x14,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char error_icon_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x20, 0x8, 0x4, 0x0, 0x0, 0x0, 0xd9, 0x73, 0xb2, 0x7f, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x5d, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xed, 0x94, 0xc1, 0xe, 0x80, 0x20, 0xc, 0x43, 0x5b, 0xe3, 0xff, 0xff, 0x72, 0x3d, 0xcc, 0x85, 0xa1, 0xbb, 0x18, 0xf4, 0x62, 0xca, 0xa9, 0x74, 0xe3, 0x65, 0xd, 0x1, 0xa, 0x6b, 0x6b, 0x5b, 0x3c, 0x6f, 0x80, 0x1, 0x7f, 0x1, 0xec, 0x29, 0x78, 0xbe, 0x2a, 0x31, 0x94, 0x98, 0x9e, 0x98, 0xf5, 0xab, 0x37, 0x1, 0xaa, 0x19, 0x8d, 0xe2, 0x50, 0xb1, 0x9b, 0xbd, 0xb7, 0x23, 0x8c, 0x21, 0x7b, 0xd5, 0xf5, 0x3d, 0x88, 0x50, 0x1, 0xdf, 0x46, 0xb8, 0xf, 0x5c, 0xef, 0xa6, 0xab, 0xd1, 0x7f, 0xa2, 0x1, 0x6, 0x0, 0x0, 0xe, 0x62, 0x6, 0x31, 0x47, 0xb6, 0x7f, 0xdd, 0x14, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char focus_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0xc,0x4,0x3,0x0,0x0,0x0,0xa4,0x5b,0x41,0xd4,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x30,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0xff,0xff,0xff,0xb9,0xa2,0x9b,0xc9,0x0,0x0,0x0,0xf,0x74,0x52,0x4e,0x53,0x0,0xe,0x39,0x68,0x7a,0x7b,0x3a,0x74,0x10,0x8,0x69,0xf,0x6,0x75,0x11,0xb8,0x16,0x0,0x1,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0xf,0x18,0xba,0x0,0xd9,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x38,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x10,0x32,0x9,0xd,0x75,0x56,0x64,0x48,0xef,0x9c,0x39,0x73,0x46,0x19,0xc3,0x6a,0x6,0x20,0xd8,0xc5,0x10,0x3,0xa2,0x8e,0x32,0x44,0x82,0xa8,0xa9,0xd8,0x29,0xa8,0x12,0xb0,0x6,0x29,0x86,0xdc,0x9d,0x33,0x67,0xce,0x2b,0x63,0x10,0x3,0x1b,0x6,0x0,0xdf,0xc6,0x11,0x6d,0xb8,0xf4,0x9c,0xac,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char focus_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x4, 0x3, 0x0, 0x0, 0x0, 0xa4, 0x5b, 0x41, 0xd4, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x30, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0xff, 0xff, 0xff, 0xb9, 0xa2, 0x9b, 0xc9, 0x0, 0x0, 0x0, 0xf, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xe, 0x39, 0x68, 0x7a, 0x7b, 0x3a, 0x74, 0x10, 0x8, 0x69, 0xf, 0x6, 0x75, 0x11, 0xb8, 0x16, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0xf, 0x18, 0xba, 0x0, 0xd9, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x38, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x10, 0x32, 0x9, 0xd, 0x75, 0x56, 0x64, 0x48, 0xef, 0x9c, 0x39, 0x73, 0x46, 0x19, 0xc3, 0x6a, 0x6, 0x20, 0xd8, 0xc5, 0x10, 0x3, 0xa2, 0x8e, 0x32, 0x44, 0x82, 0xa8, 0xa9, 0xd8, 0x29, 0xa8, 0x12, 0xb0, 0x6, 0x29, 0x86, 0xdc, 0x9d, 0x33, 0x67, 0xce, 0x2b, 0x63, 0x10, 0x3, 0x1b, 0x6, 0x0, 0xdf, 0xc6, 0x11, 0x6d, 0xb8, 0xf4, 0x9c, 0xac, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char frame_focus_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0xc,0x4,0x3,0x0,0x0,0x0,0xa4,0x5b,0x41,0xd4,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x30,0x50,0x4c,0x54,0x45,0xff,0xff,0xff,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0x47,0x8c,0xbf,0xff,0xff,0xff,0xcc,0x40,0x27,0xb9,0x0,0x0,0x0,0xf,0x74,0x52,0x4e,0x53,0x0,0xe,0x39,0x68,0x7a,0x7b,0x3a,0x74,0x10,0x8,0x69,0xf,0x6,0x75,0x11,0xb8,0x16,0x0,0x1,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x0,0x88,0x5,0x1d,0x48,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x4,0x4e,0x1d,0x2,0xaf,0x0,0x0,0x0,0x38,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x10,0x32,0x9,0xd,0x75,0x56,0x64,0x48,0xef,0x9c,0x39,0x73,0x46,0x19,0xc3,0x6a,0x6,0x20,0xd8,0xc5,0x10,0x3,0xa2,0x8e,0x32,0x44,0x82,0xa8,0xa9,0xd8,0x29,0xa8,0x12,0xb0,0x6,0x29,0x86,0xdc,0x9d,0x33,0x67,0xce,0x2b,0x63,0x10,0x3,0x1b,0x6,0x0,0xdf,0xc6,0x11,0x6d,0xb8,0xf4,0x9c,0xac,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char frame_focus_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x4, 0x3, 0x0, 0x0, 0x0, 0xa4, 0x5b, 0x41, 0xd4, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x30, 0x50, 0x4c, 0x54, 0x45, 0xff, 0xff, 0xff, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0xff, 0xff, 0xff, 0xcc, 0x40, 0x27, 0xb9, 0x0, 0x0, 0x0, 0xf, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xe, 0x39, 0x68, 0x7a, 0x7b, 0x3a, 0x74, 0x10, 0x8, 0x69, 0xf, 0x6, 0x75, 0x11, 0xb8, 0x16, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x0, 0x88, 0x5, 0x1d, 0x48, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x4, 0x4e, 0x1d, 0x2, 0xaf, 0x0, 0x0, 0x0, 0x38, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x10, 0x32, 0x9, 0xd, 0x75, 0x56, 0x64, 0x48, 0xef, 0x9c, 0x39, 0x73, 0x46, 0x19, 0xc3, 0x6a, 0x6, 0x20, 0xd8, 0xc5, 0x10, 0x3, 0xa2, 0x8e, 0x32, 0x44, 0x82, 0xa8, 0xa9, 0xd8, 0x29, 0xa8, 0x12, 0xb0, 0x6, 0x29, 0x86, 0xdc, 0x9d, 0x33, 0x67, 0xce, 0x2b, 0x63, 0x10, 0x3, 0x1b, 0x6, 0x0, 0xdf, 0xc6, 0x11, 0x6d, 0xb8, 0xf4, 0x9c, 0xac, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char full_panel_bg_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x20,0x8,0x3,0x0,0x0,0x0,0x44,0xa4,0x8a,0xc6,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x33,0x50,0x4c,0x54,0x45,0x27,0x27,0x29,0x26,0x26,0x28,0x25,0x25,0x27,0x24,0x24,0x26,0x23,0x23,0x25,0x22,0x22,0x24,0x21,0x21,0x23,0x1e,0x1e,0x20,0x1d,0x1d,0x1f,0x1c,0x1c,0x1e,0x31,0x30,0x32,0x50,0x4e,0x54,0x4e,0x4c,0x50,0x4c,0x4a,0x4e,0x3d,0x3b,0x3f,0x38,0x36,0x3a,0xff,0xff,0xff,0x4,0xb3,0x69,0x9b,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x10,0x95,0xb2,0xd,0x2c,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x63,0x49,0x44,0x41,0x54,0x38,0xcb,0xed,0x93,0x29,0x12,0xc0,0x30,0xc,0xc4,0x7c,0x3b,0x67,0xf3,0xff,0xdf,0xb6,0xe1,0xce,0x98,0x15,0x45,0x58,0xb3,0x68,0x5,0x0,0x80,0x48,0x21,0x88,0xb0,0x41,0x62,0x51,0xb,0x50,0x61,0xda,0xa,0xb1,0x79,0xa9,0x1,0xc5,0x8d,0xe9,0x1b,0x60,0x6b,0x7d,0xcc,0x80,0xd1,0x9b,0x31,0x2,0x8a,0xf7,0x67,0x85,0x3c,0xdd,0x5,0x81,0xb4,0x8c,0x75,0x60,0x14,0x25,0x20,0xab,0xf3,0x24,0xcc,0x6a,0x57,0xb8,0xc2,0xff,0x42,0x76,0xda,0xf4,0xf6,0x69,0x38,0x69,0x7a,0x79,0xbc,0x49,0xfe,0x2f,0x65,0xd3,0x2d,0x45,0xb,0x5e,0xbc,0x3b,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char full_panel_bg_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x20, 0x8, 0x3, 0x0, 0x0, 0x0, 0x44, 0xa4, 0x8a, 0xc6, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x33, 0x50, 0x4c, 0x54, 0x45, 0x27, 0x27, 0x29, 0x26, 0x26, 0x28, 0x25, 0x25, 0x27, 0x24, 0x24, 0x26, 0x23, 0x23, 0x25, 0x22, 0x22, 0x24, 0x21, 0x21, 0x23, 0x1e, 0x1e, 0x20, 0x1d, 0x1d, 0x1f, 0x1c, 0x1c, 0x1e, 0x31, 0x30, 0x32, 0x50, 0x4e, 0x54, 0x4e, 0x4c, 0x50, 0x4c, 0x4a, 0x4e, 0x3d, 0x3b, 0x3f, 0x38, 0x36, 0x3a, 0xff, 0xff, 0xff, 0x4, 0xb3, 0x69, 0x9b, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x10, 0x95, 0xb2, 0xd, 0x2c, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x63, 0x49, 0x44, 0x41, 0x54, 0x38, 0xcb, 0xed, 0x93, 0x29, 0x12, 0xc0, 0x30, 0xc, 0xc4, 0x7c, 0x3b, 0x67, 0xf3, 0xff, 0xdf, 0xb6, 0xe1, 0xce, 0x98, 0x15, 0x45, 0x58, 0xb3, 0x68, 0x5, 0x0, 0x80, 0x48, 0x21, 0x88, 0xb0, 0x41, 0x62, 0x51, 0xb, 0x50, 0x61, 0xda, 0xa, 0xb1, 0x79, 0xa9, 0x1, 0xc5, 0x8d, 0xe9, 0x1b, 0x60, 0x6b, 0x7d, 0xcc, 0x80, 0xd1, 0x9b, 0x31, 0x2, 0x8a, 0xf7, 0x67, 0x85, 0x3c, 0xdd, 0x5, 0x81, 0xb4, 0x8c, 0x75, 0x60, 0x14, 0x25, 0x20, 0xab, 0xf3, 0x24, 0xcc, 0x6a, 0x57, 0xb8, 0xc2, 0xff, 0x42, 0x76, 0xda, 0xf4, 0xf6, 0x69, 0x38, 0x69, 0x7a, 0x79, 0xbc, 0x49, 0xfe, 0x2f, 0x65, 0xd3, 0x2d, 0x45, 0xb, 0x5e, 0xbc, 0x3b, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char graph_node_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x13,0x7d,0xf7,0x96,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x8,0x17,0xd,0x5,0x12,0xa1,0x38,0x83,0x9b,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x2,0x74,0x49,0x44,0x41,0x54,0x58,0xc3,0xed,0x97,0x3d,0x6f,0xd3,0x60,0x10,0xc7,0x7f,0x17,0x9b,0x26,0x25,0x22,0xad,0xa,0x8,0xf1,0x52,0x75,0x0,0x16,0x24,0x90,0x2a,0x96,0x7c,0x1,0x6,0xc4,0xce,0xc4,0x17,0x0,0x31,0xb0,0x30,0x0,0x23,0x82,0x85,0x5,0x9,0x4,0x5f,0x80,0x89,0x1d,0x31,0xf0,0x5,0x58,0x50,0x25,0x50,0x59,0x80,0xa1,0xe2,0xad,0x28,0x34,0x4a,0x3,0x25,0x76,0xea,0xe7,0x39,0x6,0x3f,0x76,0x6d,0xc7,0x49,0x5f,0xd8,0x90,0x6f,0xb1,0xf5,0xe4,0xb9,0xdf,0xdd,0xfd,0xef,0x22,0xf9,0x84,0x2d,0x13,0xa0,0x6,0x78,0xee,0x29,0xe4,0x4d,0x1,0xb,0x18,0xf7,0x54,0x32,0x97,0x6a,0xc0,0x7e,0x60,0xe,0x38,0xc,0xb4,0x80,0x7d,0x5,0xc0,0x26,0xd0,0x7,0x3a,0x40,0x17,0xf8,0x3,0xd8,0x24,0x6a,0x13,0x38,0x35,0x73,0x60,0xf6,0x6a,0xa3,0xde,0xb8,0x38,0x35,0x55,0x3f,0x41,0x89,0xd,0x87,0xe1,0x97,0x20,0xc,0x5e,0xae,0xff,0xea,0x3d,0x5,0x3e,0x2,0x1b,0xe2,0x22,0x2d,0xcc,0xcd,0x1e,0x7c,0x78,0x72,0xe1,0xf4,0xa5,0x7b,0xb7,0x1f,0x7c,0x9e,0x6e,0x35,0xca,0xfc,0x19,0xf4,0x3,0xee,0xdc,0xbf,0x39,0xff,0x69,0xe5,0xc3,0x8b,0x6e,0x6f,0xed,0x6,0xb0,0x22,0x40,0x3,0x58,0x3c,0x7a,0xe4,0xf8,0xab,0x67,0x4f,0x9e,0x77,0xa3,0xc8,0x12,0xd,0xa3,0x52,0x80,0x3f,0xe5,0xe3,0xfb,0x35,0xae,0x5c,0xbb,0x3c,0xf7,0xfd,0xc7,0xd7,0xb,0xc0,0x92,0xef,0x74,0x68,0xfa,0x9e,0xdf,0x1c,0xfc,0xe,0xbb,0x88,0xc6,0x47,0xa,0x2a,0x59,0x85,0x95,0x61,0xb8,0xc9,0x30,0x4,0xdf,0xf3,0x9b,0xae,0x6c,0x49,0x0,0x1e,0x80,0x51,0x1b,0xfb,0xc7,0x2,0xc7,0x5a,0x3b,0x88,0x66,0xcf,0x63,0xf3,0x12,0x80,0x26,0xbf,0xa8,0xb5,0xa8,0xa,0x88,0x22,0x8,0x8a,0x22,0x2a,0x19,0x37,0x1d,0xe9,0xad,0x9f,0x6b,0xb4,0x55,0x14,0x5,0x55,0x44,0xe2,0x32,0x6c,0xe2,0x24,0x71,0x18,0x9d,0x4,0xb0,0x6a,0xd3,0x1b,0x2a,0xe9,0x4b,0xfc,0xae,0xe4,0x45,0x19,0x9f,0x81,0x2b,0xdb,0x15,0xa6,0xa2,0x19,0x2d,0xec,0x8,0x24,0x7,0x30,0xd6,0x16,0xf8,0x82,0xa8,0xc6,0x45,0x68,0x52,0xbf,0x4e,0xce,0x60,0xeb,0x42,0x5c,0xb4,0x66,0x9c,0x6c,0xc9,0x1f,0xa4,0x0,0xb0,0x39,0xc5,0xc9,0xa1,0x28,0x89,0x5f,0x14,0xd1,0x5a,0x37,0x32,0x89,0xf2,0x82,0xc6,0x3,0xe0,0xda,0xa,0x22,0x3a,0xa9,0xb,0x9a,0x26,0xaa,0xf1,0x41,0x9a,0x42,0x2,0xb2,0xb2,0x6d,0x6,0x5b,0xa3,0xab,0x23,0xd5,0x48,0x32,0x92,0xe3,0x33,0x10,0x37,0xb7,0x2a,0xea,0xee,0x4a,0x2a,0x42,0xe,0x5a,0x2a,0xa2,0x51,0x37,0x40,0x85,0x48,0x96,0xb4,0x23,0xdb,0x88,0x68,0x5c,0xc4,0xcc,0x3c,0x14,0xa7,0x6f,0xa2,0x6,0xaa,0xb1,0x7c,0xd9,0x30,0xaa,0x79,0xc7,0x49,0x93,0x78,0xf7,0xd1,0xad,0x79,0x76,0x69,0x29,0x20,0xda,0x34,0x2c,0x9e,0x3d,0xff,0x7a,0x27,0x4e,0x4b,0xef,0xde,0xb4,0x4b,0x33,0x58,0xef,0xf7,0x76,0x9b,0x0,0x35,0xfe,0xd1,0x2a,0x40,0x5,0xa8,0x0,0x15,0xa0,0x2,0x54,0x80,0xa,0xf0,0x5f,0x2,0xa4,0xe4,0x13,0x78,0xd7,0x19,0xd8,0x3d,0xf8,0xda,0x4,0x60,0x81,0xc0,0x18,0x13,0xda,0x68,0x7,0x5e,0x11,0x18,0x63,0x42,0x20,0x0,0x6c,0xcd,0xad,0xb2,0x6b,0x41,0x38,0x58,0xee,0x74,0x57,0xdb,0x93,0x20,0x36,0x82,0x4e,0x77,0xb5,0x1d,0x84,0x83,0x65,0x60,0xd,0x30,0xc9,0xe6,0x3a,0x3,0x9c,0x6b,0x35,0x67,0x1f,0x37,0xea,0xd3,0x67,0x3c,0xcf,0x2b,0x15,0xd7,0x18,0x63,0x83,0x70,0xf0,0xbe,0xbf,0xd1,0xbb,0xe,0xbc,0x5,0xd6,0x25,0xb3,0xc2,0xb5,0x80,0x63,0xc0,0x21,0xa0,0x3e,0x66,0xf9,0xe,0x81,0x9f,0xc0,0x37,0xb7,0x47,0x1b,0x29,0x8,0xea,0x27,0xfb,0xe0,0x98,0x2a,0xd4,0x95,0x1c,0xed,0x51,0xf8,0x51,0xfb,0xb,0x1,0xbe,0x20,0x9f,0x90,0x81,0x17,0xaa,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char graph_node_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x40, 0x8, 0x6, 0x0, 0x0, 0x0, 0x13, 0x7d, 0xf7, 0x96, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x8, 0x17, 0xd, 0x5, 0x12, 0xa1, 0x38, 0x83, 0x9b, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x2, 0x74, 0x49, 0x44, 0x41, 0x54, 0x58, 0xc3, 0xed, 0x97, 0x3d, 0x6f, 0xd3, 0x60, 0x10, 0xc7, 0x7f, 0x17, 0x9b, 0x26, 0x25, 0x22, 0xad, 0xa, 0x8, 0xf1, 0x52, 0x75, 0x0, 0x16, 0x24, 0x90, 0x2a, 0x96, 0x7c, 0x1, 0x6, 0xc4, 0xce, 0xc4, 0x17, 0x0, 0x31, 0xb0, 0x30, 0x0, 0x23, 0x82, 0x85, 0x5, 0x9, 0x4, 0x5f, 0x80, 0x89, 0x1d, 0x31, 0xf0, 0x5, 0x58, 0x50, 0x25, 0x50, 0x59, 0x80, 0xa1, 0xe2, 0xad, 0x28, 0x34, 0x4a, 0x3, 0x25, 0x76, 0xea, 0xe7, 0x39, 0x6, 0x3f, 0x76, 0x6d, 0xc7, 0x49, 0x5f, 0xd8, 0x90, 0x6f, 0xb1, 0xf5, 0xe4, 0xb9, 0xdf, 0xdd, 0xfd, 0xef, 0x22, 0xf9, 0x84, 0x2d, 0x13, 0xa0, 0x6, 0x78, 0xee, 0x29, 0xe4, 0x4d, 0x1, 0xb, 0x18, 0xf7, 0x54, 0x32, 0x97, 0x6a, 0xc0, 0x7e, 0x60, 0xe, 0x38, 0xc, 0xb4, 0x80, 0x7d, 0x5, 0xc0, 0x26, 0xd0, 0x7, 0x3a, 0x40, 0x17, 0xf8, 0x3, 0xd8, 0x24, 0x6a, 0x13, 0x38, 0x35, 0x73, 0x60, 0xf6, 0x6a, 0xa3, 0xde, 0xb8, 0x38, 0x35, 0x55, 0x3f, 0x41, 0x89, 0xd, 0x87, 0xe1, 0x97, 0x20, 0xc, 0x5e, 0xae, 0xff, 0xea, 0x3d, 0x5, 0x3e, 0x2, 0x1b, 0xe2, 0x22, 0x2d, 0xcc, 0xcd, 0x1e, 0x7c, 0x78, 0x72, 0xe1, 0xf4, 0xa5, 0x7b, 0xb7, 0x1f, 0x7c, 0x9e, 0x6e, 0x35, 0xca, 0xfc, 0x19, 0xf4, 0x3, 0xee, 0xdc, 0xbf, 0x39, 0xff, 0x69, 0xe5, 0xc3, 0x8b, 0x6e, 0x6f, 0xed, 0x6, 0xb0, 0x22, 0x40, 0x3, 0x58, 0x3c, 0x7a, 0xe4, 0xf8, 0xab, 0x67, 0x4f, 0x9e, 0x77, 0xa3, 0xc8, 0x12, 0xd, 0xa3, 0x52, 0x80, 0x3f, 0xe5, 0xe3, 0xfb, 0x35, 0xae, 0x5c, 0xbb, 0x3c, 0xf7, 0xfd, 0xc7, 0xd7, 0xb, 0xc0, 0x92, 0xef, 0x74, 0x68, 0xfa, 0x9e, 0xdf, 0x1c, 0xfc, 0xe, 0xbb, 0x88, 0xc6, 0x47, 0xa, 0x2a, 0x59, 0x85, 0x95, 0x61, 0xb8, 0xc9, 0x30, 0x4, 0xdf, 0xf3, 0x9b, 0xae, 0x6c, 0x49, 0x0, 0x1e, 0x80, 0x51, 0x1b, 0xfb, 0xc7, 0x2, 0xc7, 0x5a, 0x3b, 0x88, 0x66, 0xcf, 0x63, 0xf3, 0x12, 0x80, 0x26, 0xbf, 0xa8, 0xb5, 0xa8, 0xa, 0x88, 0x22, 0x8, 0x8a, 0x22, 0x2a, 0x19, 0x37, 0x1d, 0xe9, 0xad, 0x9f, 0x6b, 0xb4, 0x55, 0x14, 0x5, 0x55, 0x44, 0xe2, 0x32, 0x6c, 0xe2, 0x24, 0x71, 0x18, 0x9d, 0x4, 0xb0, 0x6a, 0xd3, 0x1b, 0x2a, 0xe9, 0x4b, 0xfc, 0xae, 0xe4, 0x45, 0x19, 0x9f, 0x81, 0x2b, 0xdb, 0x15, 0xa6, 0xa2, 0x19, 0x2d, 0xec, 0x8, 0x24, 0x7, 0x30, 0xd6, 0x16, 0xf8, 0x82, 0xa8, 0xc6, 0x45, 0x68, 0x52, 0xbf, 0x4e, 0xce, 0x60, 0xeb, 0x42, 0x5c, 0xb4, 0x66, 0x9c, 0x6c, 0xc9, 0x1f, 0xa4, 0x0, 0xb0, 0x39, 0xc5, 0xc9, 0xa1, 0x28, 0x89, 0x5f, 0x14, 0xd1, 0x5a, 0x37, 0x32, 0x89, 0xf2, 0x82, 0xc6, 0x3, 0xe0, 0xda, 0xa, 0x22, 0x3a, 0xa9, 0xb, 0x9a, 0x26, 0xaa, 0xf1, 0x41, 0x9a, 0x42, 0x2, 0xb2, 0xb2, 0x6d, 0x6, 0x5b, 0xa3, 0xab, 0x23, 0xd5, 0x48, 0x32, 0x92, 0xe3, 0x33, 0x10, 0x37, 0xb7, 0x2a, 0xea, 0xee, 0x4a, 0x2a, 0x42, 0xe, 0x5a, 0x2a, 0xa2, 0x51, 0x37, 0x40, 0x85, 0x48, 0x96, 0xb4, 0x23, 0xdb, 0x88, 0x68, 0x5c, 0xc4, 0xcc, 0x3c, 0x14, 0xa7, 0x6f, 0xa2, 0x6, 0xaa, 0xb1, 0x7c, 0xd9, 0x30, 0xaa, 0x79, 0xc7, 0x49, 0x93, 0x78, 0xf7, 0xd1, 0xad, 0x79, 0x76, 0x69, 0x29, 0x20, 0xda, 0x34, 0x2c, 0x9e, 0x3d, 0xff, 0x7a, 0x27, 0x4e, 0x4b, 0xef, 0xde, 0xb4, 0x4b, 0x33, 0x58, 0xef, 0xf7, 0x76, 0x9b, 0x0, 0x35, 0xfe, 0xd1, 0x2a, 0x40, 0x5, 0xa8, 0x0, 0x15, 0xa0, 0x2, 0x54, 0x80, 0xa, 0xf0, 0x5f, 0x2, 0xa4, 0xe4, 0x13, 0x78, 0xd7, 0x19, 0xd8, 0x3d, 0xf8, 0xda, 0x4, 0x60, 0x81, 0xc0, 0x18, 0x13, 0xda, 0x68, 0x7, 0x5e, 0x11, 0x18, 0x63, 0x42, 0x20, 0x0, 0x6c, 0xcd, 0xad, 0xb2, 0x6b, 0x41, 0x38, 0x58, 0xee, 0x74, 0x57, 0xdb, 0x93, 0x20, 0x36, 0x82, 0x4e, 0x77, 0xb5, 0x1d, 0x84, 0x83, 0x65, 0x60, 0xd, 0x30, 0xc9, 0xe6, 0x3a, 0x3, 0x9c, 0x6b, 0x35, 0x67, 0x1f, 0x37, 0xea, 0xd3, 0x67, 0x3c, 0xcf, 0x2b, 0x15, 0xd7, 0x18, 0x63, 0x83, 0x70, 0xf0, 0xbe, 0xbf, 0xd1, 0xbb, 0xe, 0xbc, 0x5, 0xd6, 0x25, 0xb3, 0xc2, 0xb5, 0x80, 0x63, 0xc0, 0x21, 0xa0, 0x3e, 0x66, 0xf9, 0xe, 0x81, 0x9f, 0xc0, 0x37, 0xb7, 0x47, 0x1b, 0x29, 0x8, 0xea, 0x27, 0xfb, 0xe0, 0x98, 0x2a, 0xd4, 0x95, 0x1c, 0xed, 0x51, 0xf8, 0x51, 0xfb, 0xb, 0x1, 0xbe, 0x20, 0x9f, 0x90, 0x81, 0x17, 0xaa, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char graph_node_breakpoint_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x13,0x7d,0xf7,0x96,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x8,0x6,0xf,0x3b,0x1c,0xec,0x64,0x51,0x75,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x8f,0x49,0x44,0x41,0x54,0x58,0xc3,0xed,0xd7,0xbd,0x9,0xc0,0x20,0x10,0x5,0xe0,0x53,0x2c,0x5d,0x40,0x74,0x4,0xf7,0x9f,0xc4,0x11,0x22,0x2e,0x60,0x6f,0x9a,0x13,0x4e,0x21,0x41,0x50,0x48,0x91,0x77,0x95,0xf8,0xf3,0x79,0x62,0xf5,0x88,0x36,0x4b,0xf5,0x41,0x2d,0xf1,0x22,0x22,0xbf,0x78,0x2e,0x5b,0x97,0x2,0xc9,0xc3,0xc,0x2c,0x95,0xdc,0x6f,0x78,0xce,0x5b,0x97,0xd4,0x42,0x27,0xd9,0xba,0x14,0xac,0x4b,0xa1,0x96,0xd8,0x24,0x20,0x9f,0x41,0x1d,0x7b,0xba,0x59,0xb6,0xaf,0xa7,0x3d,0x7e,0x78,0xdb,0x54,0xbc,0x36,0x74,0xa7,0x77,0x7f,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7e,0x4,0xe4,0xb7,0xfc,0xc8,0x6b,0x59,0xce,0x99,0x39,0x95,0x71,0xb4,0x6b,0x4b,0x89,0xf5,0x44,0x72,0x3d,0x93,0x9d,0x3f,0xad,0x1b,0x54,0xed,0x49,0xd3,0x36,0x45,0x4f,0x1f,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char graph_node_breakpoint_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x40, 0x8, 0x6, 0x0, 0x0, 0x0, 0x13, 0x7d, 0xf7, 0x96, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x8, 0x6, 0xf, 0x3b, 0x1c, 0xec, 0x64, 0x51, 0x75, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x8f, 0x49, 0x44, 0x41, 0x54, 0x58, 0xc3, 0xed, 0xd7, 0xbd, 0x9, 0xc0, 0x20, 0x10, 0x5, 0xe0, 0x53, 0x2c, 0x5d, 0x40, 0x74, 0x4, 0xf7, 0x9f, 0xc4, 0x11, 0x22, 0x2e, 0x60, 0x6f, 0x9a, 0x13, 0x4e, 0x21, 0x41, 0x50, 0x48, 0x91, 0x77, 0x95, 0xf8, 0xf3, 0x79, 0x62, 0xf5, 0x88, 0x36, 0x4b, 0xf5, 0x41, 0x2d, 0xf1, 0x22, 0x22, 0xbf, 0x78, 0x2e, 0x5b, 0x97, 0x2, 0xc9, 0xc3, 0xc, 0x2c, 0x95, 0xdc, 0x6f, 0x78, 0xce, 0x5b, 0x97, 0xd4, 0x42, 0x27, 0xd9, 0xba, 0x14, 0xac, 0x4b, 0xa1, 0x96, 0xd8, 0x24, 0x20, 0x9f, 0x41, 0x1d, 0x7b, 0xba, 0x59, 0xb6, 0xaf, 0xa7, 0x3d, 0x7e, 0x78, 0xdb, 0x54, 0xbc, 0x36, 0x74, 0xa7, 0x77, 0x7f, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7e, 0x4, 0xe4, 0xb7, 0xfc, 0xc8, 0x6b, 0x59, 0xce, 0x99, 0x39, 0x95, 0x71, 0xb4, 0x6b, 0x4b, 0x89, 0xf5, 0x44, 0x72, 0x3d, 0x93, 0x9d, 0x3f, 0xad, 0x1b, 0x54, 0xed, 0x49, 0xd3, 0x36, 0x45, 0x4f, 0x1f, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char graph_node_close_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0xc,0x8,0x6,0x0,0x0,0x0,0x56,0x75,0x5c,0xe7,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x93,0x49,0x44,0x41,0x54,0x28,0x91,0x95,0x92,0x31,0xe,0xc2,0x30,0x10,0x4,0x17,0xaa,0x3d,0x7b,0xdb,0x58,0xa4,0xa7,0xe1,0x47,0xfe,0x2c,0x3c,0x82,0x48,0x44,0x22,0x6f,0xb1,0x4d,0x15,0xc9,0x20,0x1f,0x52,0xae,0xdd,0xd9,0x2b,0xe6,0xe,0x0,0x60,0x66,0x59,0x52,0x82,0x33,0x92,0x92,0x99,0x65,0xec,0x30,0xc9,0x4a,0x72,0x19,0x95,0x24,0x25,0x92,0xb,0xc9,0x6a,0x66,0x19,0x92,0x26,0x33,0x7b,0x92,0x6c,0x24,0xd7,0x10,0xc2,0xdc,0xc1,0x5f,0x59,0x8c,0xf1,0x32,0xc,0x42,0x8,0xb3,0xb,0x3b,0xdb,0xde,0x24,0x5f,0x2e,0xdc,0x97,0x3a,0xb0,0x91,0xdc,0x7e,0xe1,0xb3,0x67,0x66,0x9f,0xd6,0xda,0x69,0x58,0x90,0x34,0x95,0x52,0xee,0x0,0x6e,0x0,0x36,0x0,0x2b,0x80,0x6b,0xad,0xf5,0xd1,0x8b,0x70,0x6d,0xb8,0xf6,0xfe,0xd9,0x18,0x96,0xe,0x1f,0xe,0x38,0xf6,0x1a,0x1f,0x9f,0xec,0x40,0x47,0x56,0x51,0x84,0x77,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char graph_node_close_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x6, 0x0, 0x0, 0x0, 0x56, 0x75, 0x5c, 0xe7, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0x93, 0x49, 0x44, 0x41, 0x54, 0x28, 0x91, 0x95, 0x92, 0x31, 0xe, 0xc2, 0x30, 0x10, 0x4, 0x17, 0xaa, 0x3d, 0x7b, 0xdb, 0x58, 0xa4, 0xa7, 0xe1, 0x47, 0xfe, 0x2c, 0x3c, 0x82, 0x48, 0x44, 0x22, 0x6f, 0xb1, 0x4d, 0x15, 0xc9, 0x20, 0x1f, 0x52, 0xae, 0xdd, 0xd9, 0x2b, 0xe6, 0xe, 0x0, 0x60, 0x66, 0x59, 0x52, 0x82, 0x33, 0x92, 0x92, 0x99, 0x65, 0xec, 0x30, 0xc9, 0x4a, 0x72, 0x19, 0x95, 0x24, 0x25, 0x92, 0xb, 0xc9, 0x6a, 0x66, 0x19, 0x92, 0x26, 0x33, 0x7b, 0x92, 0x6c, 0x24, 0xd7, 0x10, 0xc2, 0xdc, 0xc1, 0x5f, 0x59, 0x8c, 0xf1, 0x32, 0xc, 0x42, 0x8, 0xb3, 0xb, 0x3b, 0xdb, 0xde, 0x24, 0x5f, 0x2e, 0xdc, 0x97, 0x3a, 0xb0, 0x91, 0xdc, 0x7e, 0xe1, 0xb3, 0x67, 0x66, 0x9f, 0xd6, 0xda, 0x69, 0x58, 0x90, 0x34, 0x95, 0x52, 0xee, 0x0, 0x6e, 0x0, 0x36, 0x0, 0x2b, 0x80, 0x6b, 0xad, 0xf5, 0xd1, 0x8b, 0x70, 0x6d, 0xb8, 0xf6, 0xfe, 0xd9, 0x18, 0x96, 0xe, 0x1f, 0xe, 0x38, 0xf6, 0x1a, 0x1f, 0x9f, 0xec, 0x40, 0x47, 0x56, 0x51, 0x84, 0x77, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char graph_node_comment_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x13,0x7d,0xf7,0x96,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x8,0x19,0x11,0x2a,0x1d,0xd6,0x78,0x8b,0x40,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x74,0x49,0x44,0x41,0x54,0x58,0xc3,0xed,0x97,0xbf,0x4e,0xc2,0x50,0x14,0xc6,0x7f,0x6d,0x91,0x56,0x1b,0x90,0x80,0x2c,0x44,0xc2,0xa0,0x2e,0xe,0x3e,0x3,0x89,0x93,0xf1,0x1d,0x4c,0x18,0x4d,0x1c,0x7c,0xb,0x57,0x7,0x13,0x47,0x13,0x77,0x46,0xe3,0xc4,0x4b,0x98,0x60,0x4c,0xd4,0x81,0x60,0x58,0x94,0xff,0x22,0x2d,0xd0,0xd6,0xe5,0xde,0x88,0x8,0x2,0x35,0x6e,0xf7,0x5b,0x6e,0x9a,0x9c,0xef,0x77,0xee,0x39,0x37,0x1d,0x3e,0x8d,0x2f,0x69,0x80,0xe,0x18,0xe2,0xd4,0xf8,0xae,0x0,0xf0,0x1,0x4f,0x9c,0x1,0x63,0x45,0x3a,0xb0,0x6,0x24,0x81,0x34,0x10,0x7,0x56,0x26,0x0,0x43,0xa0,0x3,0xbc,0x2,0xd,0xe0,0x3,0xf0,0x65,0x57,0x1b,0xd8,0x5e,0x8f,0x25,0x8e,0x2d,0xd3,0x3a,0x88,0x46,0xcd,0x4d,0xa6,0x68,0x30,0x70,0x5f,0x1c,0xd7,0xb9,0x6d,0x77,0x5b,0x97,0xc0,0x13,0xd0,0xd3,0x44,0xa7,0x5c,0x32,0x91,0x3a,0xdf,0xca,0xed,0x1c,0x16,0x52,0xdd,0x2a,0xbf,0xe8,0xaa,0x1e,0xcb,0x3e,0x57,0x1e,0x6f,0x1a,0xad,0xfa,0x29,0x50,0x91,0x33,0xa7,0x4d,0xd3,0xca,0xcf,0x33,0x3,0x14,0x52,0xdd,0xaa,0x69,0x5a,0x79,0x31,0xaa,0x21,0x97,0x65,0x47,0x8c,0x88,0xcd,0x82,0x12,0xb5,0x36,0xa0,0x49,0x80,0xc1,0xf2,0x32,0x24,0x20,0x90,0x4f,0x12,0x46,0x3a,0x7f,0x94,0x2,0x28,0x80,0x2,0x88,0x5f,0x7b,0xfc,0xe3,0xec,0xe1,0x3d,0x1b,0x1a,0x30,0x1a,0x7a,0x1c,0x65,0xd8,0x5f,0xc4,0x74,0x5d,0xa3,0xa4,0x5e,0x41,0x1,0x14,0x40,0x1,0x14,0x40,0x1,0x14,0x40,0x1,0xfe,0x15,0xa0,0x4d,0xc9,0x88,0x4b,0xdf,0xc0,0xf,0xe1,0xf5,0x25,0xc0,0x7,0x1c,0xcf,0xf3,0xdc,0x45,0x9d,0xa2,0xd6,0x1,0x7c,0x5d,0x44,0xd9,0xba,0xe3,0xf6,0xcb,0xc5,0xa6,0x5d,0x9a,0x67,0x2e,0x36,0xed,0x92,0xe3,0xf6,0xcb,0x40,0x1d,0xf0,0x64,0x72,0x5d,0x7,0xf6,0xe2,0x76,0xe2,0xc2,0x32,0x57,0x77,0xd,0xc3,0xd0,0x67,0x74,0xf6,0x1d,0xb7,0x7f,0xdf,0xe9,0xb5,0x4e,0x80,0x3b,0xa0,0xad,0x8d,0x45,0xb8,0x38,0x90,0x1,0x36,0x0,0x73,0x46,0xf8,0x76,0x81,0x37,0xa0,0x26,0x72,0xb4,0xa7,0x4d,0x2c,0x34,0x22,0xf3,0xe0,0x8c,0x9,0x2,0x31,0xf2,0x28,0xe4,0xe2,0x7f,0xea,0x13,0x64,0x47,0x6c,0x83,0x36,0x6d,0xd2,0x40,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char graph_node_comment_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x40, 0x8, 0x6, 0x0, 0x0, 0x0, 0x13, 0x7d, 0xf7, 0x96, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x8, 0x19, 0x11, 0x2a, 0x1d, 0xd6, 0x78, 0x8b, 0x40, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x1, 0x74, 0x49, 0x44, 0x41, 0x54, 0x58, 0xc3, 0xed, 0x97, 0xbf, 0x4e, 0xc2, 0x50, 0x14, 0xc6, 0x7f, 0x6d, 0x91, 0x56, 0x1b, 0x90, 0x80, 0x2c, 0x44, 0xc2, 0xa0, 0x2e, 0xe, 0x3e, 0x3, 0x89, 0x93, 0xf1, 0x1d, 0x4c, 0x18, 0x4d, 0x1c, 0x7c, 0xb, 0x57, 0x7, 0x13, 0x47, 0x13, 0x77, 0x46, 0xe3, 0xc4, 0x4b, 0x98, 0x60, 0x4c, 0xd4, 0x81, 0x60, 0x58, 0x94, 0xff, 0x22, 0x2d, 0xd0, 0xd6, 0xe5, 0xde, 0x88, 0x8, 0x2, 0x35, 0x6e, 0xf7, 0x5b, 0x6e, 0x9a, 0x9c, 0xef, 0x77, 0xee, 0x39, 0x37, 0x1d, 0x3e, 0x8d, 0x2f, 0x69, 0x80, 0xe, 0x18, 0xe2, 0xd4, 0xf8, 0xae, 0x0, 0xf0, 0x1, 0x4f, 0x9c, 0x1, 0x63, 0x45, 0x3a, 0xb0, 0x6, 0x24, 0x81, 0x34, 0x10, 0x7, 0x56, 0x26, 0x0, 0x43, 0xa0, 0x3, 0xbc, 0x2, 0xd, 0xe0, 0x3, 0xf0, 0x65, 0x57, 0x1b, 0xd8, 0x5e, 0x8f, 0x25, 0x8e, 0x2d, 0xd3, 0x3a, 0x88, 0x46, 0xcd, 0x4d, 0xa6, 0x68, 0x30, 0x70, 0x5f, 0x1c, 0xd7, 0xb9, 0x6d, 0x77, 0x5b, 0x97, 0xc0, 0x13, 0xd0, 0xd3, 0x44, 0xa7, 0x5c, 0x32, 0x91, 0x3a, 0xdf, 0xca, 0xed, 0x1c, 0x16, 0x52, 0xdd, 0x2a, 0xbf, 0xe8, 0xaa, 0x1e, 0xcb, 0x3e, 0x57, 0x1e, 0x6f, 0x1a, 0xad, 0xfa, 0x29, 0x50, 0x91, 0x33, 0xa7, 0x4d, 0xd3, 0xca, 0xcf, 0x33, 0x3, 0x14, 0x52, 0xdd, 0xaa, 0x69, 0x5a, 0x79, 0x31, 0xaa, 0x21, 0x97, 0x65, 0x47, 0x8c, 0x88, 0xcd, 0x82, 0x12, 0xb5, 0x36, 0xa0, 0x49, 0x80, 0xc1, 0xf2, 0x32, 0x24, 0x20, 0x90, 0x4f, 0x12, 0x46, 0x3a, 0x7f, 0x94, 0x2, 0x28, 0x80, 0x2, 0x88, 0x5f, 0x7b, 0xfc, 0xe3, 0xec, 0xe1, 0x3d, 0x1b, 0x1a, 0x30, 0x1a, 0x7a, 0x1c, 0x65, 0xd8, 0x5f, 0xc4, 0x74, 0x5d, 0xa3, 0xa4, 0x5e, 0x41, 0x1, 0x14, 0x40, 0x1, 0x14, 0x40, 0x1, 0x14, 0x40, 0x1, 0xfe, 0x15, 0xa0, 0x4d, 0xc9, 0x88, 0x4b, 0xdf, 0xc0, 0xf, 0xe1, 0xf5, 0x25, 0xc0, 0x7, 0x1c, 0xcf, 0xf3, 0xdc, 0x45, 0x9d, 0xa2, 0xd6, 0x1, 0x7c, 0x5d, 0x44, 0xd9, 0xba, 0xe3, 0xf6, 0xcb, 0xc5, 0xa6, 0x5d, 0x9a, 0x67, 0x2e, 0x36, 0xed, 0x92, 0xe3, 0xf6, 0xcb, 0x40, 0x1d, 0xf0, 0x64, 0x72, 0x5d, 0x7, 0xf6, 0xe2, 0x76, 0xe2, 0xc2, 0x32, 0x57, 0x77, 0xd, 0xc3, 0xd0, 0x67, 0x74, 0xf6, 0x1d, 0xb7, 0x7f, 0xdf, 0xe9, 0xb5, 0x4e, 0x80, 0x3b, 0xa0, 0xad, 0x8d, 0x45, 0xb8, 0x38, 0x90, 0x1, 0x36, 0x0, 0x73, 0x46, 0xf8, 0x76, 0x81, 0x37, 0xa0, 0x26, 0x72, 0xb4, 0xa7, 0x4d, 0x2c, 0x34, 0x22, 0xf3, 0xe0, 0x8c, 0x9, 0x2, 0x31, 0xf2, 0x28, 0xe4, 0xe2, 0x7f, 0xea, 0x13, 0x64, 0x47, 0x6c, 0x83, 0x36, 0x6d, 0xd2, 0x40, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char graph_node_comment_focus_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x13,0x7d,0xf7,0x96,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x0,0x0,0x0,0x0,0x0,0xf9,0x43,0xbb,0x7f,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x9,0x2,0xe,0x16,0x22,0xbe,0xef,0xc2,0xe1,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x4a,0x49,0x44,0x41,0x54,0x58,0xc3,0xed,0xd7,0xbf,0x4b,0xdb,0x41,0x1c,0xc6,0xf1,0xd7,0x37,0x51,0x4,0x3,0xa,0xa2,0x20,0xd2,0xe2,0xe2,0x64,0x41,0xdc,0xdc,0xac,0xe0,0x54,0xdc,0xb2,0xe6,0x2f,0x10,0x1a,0xf0,0x4f,0x11,0x22,0xf8,0x17,0x64,0xcd,0x26,0x9d,0x1c,0x74,0x73,0x13,0x21,0x4e,0x2e,0xa5,0xa5,0x14,0xac,0x82,0x82,0x62,0xd0,0x7c,0xd3,0xa1,0x77,0x18,0x35,0xfe,0x48,0xa4,0xdb,0x3d,0x70,0xdc,0xf2,0x79,0xde,0x77,0xf7,0x39,0x38,0xee,0xc9,0xdc,0x2b,0x43,0x1,0xc5,0x30,0x67,0x1e,0xaa,0x83,0x1c,0xed,0x30,0x77,0x74,0x15,0x15,0x30,0x8a,0x9,0x4c,0x61,0xc,0xc3,0x8f,0x0,0xb7,0xb8,0xc4,0x29,0xce,0x71,0x8d,0x3c,0xae,0x5a,0xc2,0x5c,0xa3,0x5a,0x59,0xc7,0x17,0x7c,0xd0,0x5b,0x3f,0xf1,0xad,0x5c,0xab,0x6f,0xe3,0x4,0x57,0x59,0x58,0x69,0xb6,0x51,0xad,0x6c,0x62,0xed,0x77,0xf3,0xf0,0x87,0x17,0x34,0xfd,0x69,0xf1,0x23,0x76,0xca,0xb5,0xfa,0x6,0xbe,0xc7,0x33,0x4f,0x61,0xe5,0x35,0x33,0x84,0x9a,0x95,0xe0,0x29,0xc6,0x66,0x95,0xc2,0x78,0xab,0x62,0x7d,0x16,0x1,0x45,0xfd,0xab,0x18,0x1,0x9d,0x78,0x25,0x83,0xa8,0xe0,0x9d,0x4a,0x80,0x4,0x48,0x80,0x7f,0x1a,0xea,0xf1,0xda,0xc,0xe,0x38,0xd8,0xdf,0x5b,0x7d,0x8b,0x69,0x69,0xf9,0xf3,0x6e,0xba,0x85,0x4,0x48,0x80,0x4,0x48,0x80,0x4,0x48,0x80,0x4,0xf8,0xaf,0x80,0xac,0x47,0x46,0xec,0x7b,0x7,0xf9,0x0,0xde,0x3c,0x2,0x72,0xdc,0xa0,0xd5,0x87,0xb9,0x15,0x3c,0x79,0x21,0x44,0xd9,0x33,0x34,0xbb,0x3f,0x4f,0xaf,0x7c,0xb0,0x9a,0xc1,0xd3,0x8e,0xc9,0x75,0x1c,0xb,0x8d,0x6a,0x65,0xb,0xf3,0x2f,0x34,0x37,0xc7,0x71,0xb9,0x56,0xff,0x8a,0x23,0x5c,0x64,0x5d,0x11,0x6e,0xc,0x33,0x98,0xc4,0xc8,0x33,0xe1,0xbb,0x85,0x3f,0xf8,0x15,0x72,0x74,0x3b,0x7b,0xd4,0xd0,0xa1,0x98,0x7,0x9f,0xd9,0x41,0x27,0x1c,0xf9,0x6e,0xc0,0xc6,0x3f,0xd5,0x5f,0x9d,0x54,0x4e,0x15,0xfd,0xeb,0xb4,0x4f,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char graph_node_comment_focus_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x40, 0x8, 0x6, 0x0, 0x0, 0x0, 0x13, 0x7d, 0xf7, 0x96, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf9, 0x43, 0xbb, 0x7f, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x9, 0x2, 0xe, 0x16, 0x22, 0xbe, 0xef, 0xc2, 0xe1, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x1, 0x4a, 0x49, 0x44, 0x41, 0x54, 0x58, 0xc3, 0xed, 0xd7, 0xbf, 0x4b, 0xdb, 0x41, 0x1c, 0xc6, 0xf1, 0xd7, 0x37, 0x51, 0x4, 0x3, 0xa, 0xa2, 0x20, 0xd2, 0xe2, 0xe2, 0x64, 0x41, 0xdc, 0xdc, 0xac, 0xe0, 0x54, 0xdc, 0xb2, 0xe6, 0x2f, 0x10, 0x1a, 0xf0, 0x4f, 0x11, 0x22, 0xf8, 0x17, 0x64, 0xcd, 0x26, 0x9d, 0x1c, 0x74, 0x73, 0x13, 0x21, 0x4e, 0x2e, 0xa5, 0xa5, 0x14, 0xac, 0x82, 0x82, 0x62, 0xd0, 0x7c, 0xd3, 0xa1, 0x77, 0x18, 0x35, 0xfe, 0x48, 0xa4, 0xdb, 0x3d, 0x70, 0xdc, 0xf2, 0x79, 0xde, 0x77, 0xf7, 0x39, 0x38, 0xee, 0xc9, 0xdc, 0x2b, 0x43, 0x1, 0xc5, 0x30, 0x67, 0x1e, 0xaa, 0x83, 0x1c, 0xed, 0x30, 0x77, 0x74, 0x15, 0x15, 0x30, 0x8a, 0x9, 0x4c, 0x61, 0xc, 0xc3, 0x8f, 0x0, 0xb7, 0xb8, 0xc4, 0x29, 0xce, 0x71, 0x8d, 0x3c, 0xae, 0x5a, 0xc2, 0x5c, 0xa3, 0x5a, 0x59, 0xc7, 0x17, 0x7c, 0xd0, 0x5b, 0x3f, 0xf1, 0xad, 0x5c, 0xab, 0x6f, 0xe3, 0x4, 0x57, 0x59, 0x58, 0x69, 0xb6, 0x51, 0xad, 0x6c, 0x62, 0xed, 0x77, 0xf3, 0xf0, 0x87, 0x17, 0x34, 0xfd, 0x69, 0xf1, 0x23, 0x76, 0xca, 0xb5, 0xfa, 0x6, 0xbe, 0xc7, 0x33, 0x4f, 0x61, 0xe5, 0x35, 0x33, 0x84, 0x9a, 0x95, 0xe0, 0x29, 0xc6, 0x66, 0x95, 0xc2, 0x78, 0xab, 0x62, 0x7d, 0x16, 0x1, 0x45, 0xfd, 0xab, 0x18, 0x1, 0x9d, 0x78, 0x25, 0x83, 0xa8, 0xe0, 0x9d, 0x4a, 0x80, 0x4, 0x48, 0x80, 0x7f, 0x1a, 0xea, 0xf1, 0xda, 0xc, 0xe, 0x38, 0xd8, 0xdf, 0x5b, 0x7d, 0x8b, 0x69, 0x69, 0xf9, 0xf3, 0x6e, 0xba, 0x85, 0x4, 0x48, 0x80, 0x4, 0x48, 0x80, 0x4, 0x48, 0x80, 0x4, 0xf8, 0xaf, 0x80, 0xac, 0x47, 0x46, 0xec, 0x7b, 0x7, 0xf9, 0x0, 0xde, 0x3c, 0x2, 0x72, 0xdc, 0xa0, 0xd5, 0x87, 0xb9, 0x15, 0x3c, 0x79, 0x21, 0x44, 0xd9, 0x33, 0x34, 0xbb, 0x3f, 0x4f, 0xaf, 0x7c, 0xb0, 0x9a, 0xc1, 0xd3, 0x8e, 0xc9, 0x75, 0x1c, 0xb, 0x8d, 0x6a, 0x65, 0xb, 0xf3, 0x2f, 0x34, 0x37, 0xc7, 0x71, 0xb9, 0x56, 0xff, 0x8a, 0x23, 0x5c, 0x64, 0x5d, 0x11, 0x6e, 0xc, 0x33, 0x98, 0xc4, 0xc8, 0x33, 0xe1, 0xbb, 0x85, 0x3f, 0xf8, 0x15, 0x72, 0x74, 0x3b, 0x7b, 0xd4, 0xd0, 0xa1, 0x98, 0x7, 0x9f, 0xd9, 0x41, 0x27, 0x1c, 0xf9, 0x6e, 0xc0, 0xc6, 0x3f, 0xd5, 0x5f, 0x9d, 0x54, 0x4e, 0x15, 0xfd, 0xeb, 0xb4, 0x4f, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char graph_node_default_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x39,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x16,0x12,0x19,0xe,0xb,0x10,0xe,0xb,0x10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x16,0x12,0x19,0x0,0x0,0x0,0x19,0x15,0x1c,0x24,0x1e,0x27,0x16,0x12,0x19,0xff,0xff,0xff,0x2b,0x4d,0xfd,0x66,0x0,0x0,0x0,0xf,0x74,0x52,0x4e,0x53,0x0,0x46,0x47,0x3f,0x2b,0x11,0x3,0xfd,0xd3,0xcd,0x2a,0x73,0x45,0xf8,0x3d,0x3f,0x57,0xda,0x84,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x12,0x7b,0xbc,0x6c,0x0,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x4,0x4e,0x1d,0x2,0xaf,0x0,0x0,0x0,0x38,0x49,0x44,0x41,0x54,0x18,0xd3,0x63,0x60,0x64,0x2,0x2,0x46,0x8,0xc9,0xcc,0xc2,0xca,0xc6,0xc0,0x8f,0x4,0xd8,0x39,0x98,0x59,0x19,0x50,0x80,0x0,0x27,0x17,0xaa,0x0,0x83,0x20,0x37,0x9a,0x0,0x3f,0xd3,0xc0,0x8,0xf0,0xa0,0x9,0xf0,0xf2,0x61,0x3a,0x1d,0xc3,0x73,0xe8,0xde,0x7,0x0,0x89,0x4d,0x2,0xf2,0x16,0xd3,0x74,0x45,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char graph_node_default_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x39, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0x12, 0x19, 0xe, 0xb, 0x10, 0xe, 0xb, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0x12, 0x19, 0x0, 0x0, 0x0, 0x19, 0x15, 0x1c, 0x24, 0x1e, 0x27, 0x16, 0x12, 0x19, 0xff, 0xff, 0xff, 0x2b, 0x4d, 0xfd, 0x66, 0x0, 0x0, 0x0, 0xf, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x46, 0x47, 0x3f, 0x2b, 0x11, 0x3, 0xfd, 0xd3, 0xcd, 0x2a, 0x73, 0x45, 0xf8, 0x3d, 0x3f, 0x57, 0xda, 0x84, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x12, 0x7b, 0xbc, 0x6c, 0x0, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x4, 0x4e, 0x1d, 0x2, 0xaf, 0x0, 0x0, 0x0, 0x38, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x63, 0x60, 0x64, 0x2, 0x2, 0x46, 0x8, 0xc9, 0xcc, 0xc2, 0xca, 0xc6, 0xc0, 0x8f, 0x4, 0xd8, 0x39, 0x98, 0x59, 0x19, 0x50, 0x80, 0x0, 0x27, 0x17, 0xaa, 0x0, 0x83, 0x20, 0x37, 0x9a, 0x0, 0x3f, 0xd3, 0xc0, 0x8, 0xf0, 0xa0, 0x9, 0xf0, 0xf2, 0x61, 0x3a, 0x1d, 0xc3, 0x73, 0xe8, 0xde, 0x7, 0x0, 0x89, 0x4d, 0x2, 0xf2, 0x16, 0xd3, 0x74, 0x45, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char graph_node_default_focus_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x4,0x0,0x0,0x0,0xb5,0xfa,0x37,0xea,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0xb7,0x49,0x44,0x41,0x54,0x28,0xcf,0x9d,0x91,0x3d,0x6a,0x42,0x61,0x10,0x45,0xcf,0x8c,0x4f,0x22,0x7c,0x58,0x84,0x14,0x2e,0xc0,0xf5,0x64,0x17,0xba,0x3,0x2d,0x4,0x41,0x17,0x96,0x2a,0x65,0x5c,0x43,0x7a,0xb,0x53,0xfa,0xc3,0x63,0x9c,0x6b,0xf1,0x4,0xf9,0x24,0x31,0x21,0xb7,0x1b,0xe6,0x14,0x33,0xe7,0x1a,0x80,0xc,0xc7,0x1,0xa7,0x4b,0x2,0x49,0x9a,0xc0,0x34,0xc2,0xbb,0x11,0xae,0x58,0x92,0x4,0x2d,0x2d,0x61,0xb2,0x99,0xf8,0x26,0xfd,0xaf,0xe1,0xdb,0x62,0xca,0x89,0x40,0x88,0x35,0x13,0xb6,0x15,0xb0,0x7d,0x99,0x68,0xfd,0xae,0xa2,0x1e,0x42,0xcc,0x9,0x4a,0x5,0x94,0x71,0xd8,0xfc,0xa8,0x67,0xf5,0x1d,0x40,0x34,0xec,0x2b,0x60,0xff,0xd9,0x48,0x3,0x1a,0xdc,0x79,0x14,0xbf,0x3d,0xf6,0x4f,0x80,0xdf,0x80,0xfc,0x2b,0x60,0x77,0x16,0x3a,0x13,0x76,0x24,0x48,0x7,0x28,0x2c,0x89,0x6a,0x1d,0xc3,0xe5,0xae,0x7c,0xd0,0x92,0x3f,0xa8,0xb6,0x53,0xd9,0xac,0x5e,0x39,0x10,0x8f,0xcb,0x4a,0x3b,0x5b,0x67,0x12,0x80,0xa7,0xea,0xbc,0x6b,0xdd,0x17,0xbe,0x3f,0x4f,0x23,0x27,0x82,0x63,0x73,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char graph_node_default_focus_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0xb7, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x9d, 0x91, 0x3d, 0x6a, 0x42, 0x61, 0x10, 0x45, 0xcf, 0x8c, 0x4f, 0x22, 0x7c, 0x58, 0x84, 0x14, 0x2e, 0xc0, 0xf5, 0x64, 0x17, 0xba, 0x3, 0x2d, 0x4, 0x41, 0x17, 0x96, 0x2a, 0x65, 0x5c, 0x43, 0x7a, 0xb, 0x53, 0xfa, 0xc3, 0x63, 0x9c, 0x6b, 0xf1, 0x4, 0xf9, 0x24, 0x31, 0x21, 0xb7, 0x1b, 0xe6, 0x14, 0x33, 0xe7, 0x1a, 0x80, 0xc, 0xc7, 0x1, 0xa7, 0x4b, 0x2, 0x49, 0x9a, 0xc0, 0x34, 0xc2, 0xbb, 0x11, 0xae, 0x58, 0x92, 0x4, 0x2d, 0x2d, 0x61, 0xb2, 0x99, 0xf8, 0x26, 0xfd, 0xaf, 0xe1, 0xdb, 0x62, 0xca, 0x89, 0x40, 0x88, 0x35, 0x13, 0xb6, 0x15, 0xb0, 0x7d, 0x99, 0x68, 0xfd, 0xae, 0xa2, 0x1e, 0x42, 0xcc, 0x9, 0x4a, 0x5, 0x94, 0x71, 0xd8, 0xfc, 0xa8, 0x67, 0xf5, 0x1d, 0x40, 0x34, 0xec, 0x2b, 0x60, 0xff, 0xd9, 0x48, 0x3, 0x1a, 0xdc, 0x79, 0x14, 0xbf, 0x3d, 0xf6, 0x4f, 0x80, 0xdf, 0x80, 0xfc, 0x2b, 0x60, 0x77, 0x16, 0x3a, 0x13, 0x76, 0x24, 0x48, 0x7, 0x28, 0x2c, 0x89, 0x6a, 0x1d, 0xc3, 0xe5, 0xae, 0x7c, 0xd0, 0x92, 0x3f, 0xa8, 0xb6, 0x53, 0xd9, 0xac, 0x5e, 0x39, 0x10, 0x8f, 0xcb, 0x4a, 0x3b, 0x5b, 0x67, 0x12, 0x80, 0xa7, 0xea, 0xbc, 0x6b, 0xdd, 0x17, 0xbe, 0x3f, 0x4f, 0x23, 0x27, 0x82, 0x63, 0x73, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char graph_node_position_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x13,0x7d,0xf7,0x96,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x8,0x6,0xf,0x3b,0x3b,0x49,0x6e,0xe4,0x1e,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x90,0x49,0x44,0x41,0x54,0x58,0xc3,0xed,0xd7,0xbd,0x9,0xc0,0x20,0x10,0x5,0xe0,0x53,0x2c,0xdd,0x40,0x47,0x70,0x7,0x67,0x77,0x7,0x47,0x88,0x1b,0xd8,0x9b,0xe6,0x84,0x53,0x48,0x10,0x14,0x52,0xe4,0x5d,0x25,0xfe,0x7c,0x9e,0x58,0x3d,0xa2,0xcd,0x52,0x7d,0x50,0x63,0xb8,0x88,0xc8,0x2d,0x9e,0x2b,0x36,0x65,0x4f,0xf2,0x30,0x3,0x4b,0x25,0xf7,0x1b,0x9e,0x73,0x36,0x65,0xb5,0xd0,0x49,0xb1,0x29,0x7b,0x9b,0xb2,0xaf,0x31,0x34,0x9,0xc8,0x67,0x50,0xc7,0x9e,0x6e,0x96,0xed,0xeb,0x69,0x8f,0x1b,0xde,0x36,0x15,0xaf,0xd,0xdd,0xe9,0xdd,0x5f,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0x1f,0x1,0xe5,0x2d,0x3f,0xf2,0x5a,0x91,0x73,0x66,0x4e,0x65,0x1c,0xed,0xda,0x52,0x62,0x3d,0x91,0x5c,0xcf,0x64,0xe7,0x4f,0xeb,0x6,0x80,0xff,0x44,0x93,0xd4,0xd9,0xea,0x7e,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char graph_node_position_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x40, 0x8, 0x6, 0x0, 0x0, 0x0, 0x13, 0x7d, 0xf7, 0x96, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x8, 0x6, 0xf, 0x3b, 0x3b, 0x49, 0x6e, 0xe4, 0x1e, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x90, 0x49, 0x44, 0x41, 0x54, 0x58, 0xc3, 0xed, 0xd7, 0xbd, 0x9, 0xc0, 0x20, 0x10, 0x5, 0xe0, 0x53, 0x2c, 0xdd, 0x40, 0x47, 0x70, 0x7, 0x67, 0x77, 0x7, 0x47, 0x88, 0x1b, 0xd8, 0x9b, 0xe6, 0x84, 0x53, 0x48, 0x10, 0x14, 0x52, 0xe4, 0x5d, 0x25, 0xfe, 0x7c, 0x9e, 0x58, 0x3d, 0xa2, 0xcd, 0x52, 0x7d, 0x50, 0x63, 0xb8, 0x88, 0xc8, 0x2d, 0x9e, 0x2b, 0x36, 0x65, 0x4f, 0xf2, 0x30, 0x3, 0x4b, 0x25, 0xf7, 0x1b, 0x9e, 0x73, 0x36, 0x65, 0xb5, 0xd0, 0x49, 0xb1, 0x29, 0x7b, 0x9b, 0xb2, 0xaf, 0x31, 0x34, 0x9, 0xc8, 0x67, 0x50, 0xc7, 0x9e, 0x6e, 0x96, 0xed, 0xeb, 0x69, 0x8f, 0x1b, 0xde, 0x36, 0x15, 0xaf, 0xd, 0xdd, 0xe9, 0xdd, 0x5f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x1f, 0x1, 0xe5, 0x2d, 0x3f, 0xf2, 0x5a, 0x91, 0x73, 0x66, 0x4e, 0x65, 0x1c, 0xed, 0xda, 0x52, 0x62, 0x3d, 0x91, 0x5c, 0xcf, 0x64, 0xe7, 0x4f, 0xeb, 0x6, 0x80, 0xff, 0x44, 0x93, 0xd4, 0xd9, 0xea, 0x7e, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char graph_node_selected_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x13,0x7d,0xf7,0x96,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x8,0x17,0xd,0x4,0x3b,0xfa,0x91,0x2a,0xb6,0x0,0x0,0x3,0x44,0x49,0x44,0x41,0x54,0x58,0xc3,0xed,0x97,0x3f,0x68,0xdc,0x76,0x14,0xc7,0xbf,0xef,0xa7,0x9f,0x7e,0x3a,0xdd,0x39,0xf6,0xdd,0x95,0xb3,0x3,0xc1,0x75,0x1b,0x70,0xa,0xe9,0x98,0x25,0x93,0x87,0x52,0x3a,0x4,0x2,0xce,0xe0,0xd2,0x34,0x35,0x94,0x8e,0x1d,0xbc,0xd5,0x4b,0xc7,0x2e,0x25,0x63,0x2,0x5d,0xa,0xa5,0xb1,0x1b,0x2,0xf5,0xd0,0x40,0xa0,0x90,0x10,0x3a,0x64,0xca,0x92,0x31,0x81,0x24,0xd0,0xd2,0x9a,0x40,0x2f,0x17,0xdf,0x1f,0xfb,0x74,0xf2,0xe9,0x27,0xfd,0x5e,0x7,0x49,0xb6,0x4e,0xe7,0xea,0x86,0x6e,0xe5,0x1e,0xdc,0x49,0x42,0xef,0x7d,0xde,0xf7,0x7d,0xf5,0x13,0xe8,0x47,0xcc,0x4c,0x0,0xc4,0xbd,0x7b,0x4f,0x9c,0xb0,0xdd,0x71,0xdb,0xfb,0x2d,0xc7,0xb0,0x11,0x5a,0x7,0x84,0x4c,0xd8,0xb6,0x62,0x41,0xc2,0xd4,0x67,0x1b,0x43,0x59,0xaf,0xf9,0x97,0x2f,0x5f,0x18,0x2,0x30,0xc4,0xcc,0xd6,0xdd,0x1f,0xef,0x9e,0xea,0x79,0x83,0x33,0xed,0x6e,0xf7,0x6c,0xaf,0xd7,0x59,0xe8,0x7b,0xfd,0x72,0x10,0x4,0x32,0xb,0x50,0x4a,0x85,0x33,0x95,0x99,0xc1,0xdc,0x5c,0xad,0x59,0xaf,0x56,0x7f,0x9f,0xab,0x94,0x5f,0xad,0x7e,0xbe,0x7a,0x40,0x5b,0x5b,0xf7,0x2b,0x41,0xbb,0xf9,0x6e,0xa7,0xd7,0x5e,0xb9,0x72,0x75,0xe5,0x86,0x72,0xa4,0x85,0x82,0x8,0x86,0x61,0xf4,0xcb,0x9d,0x47,0x1b,0xb5,0xb9,0xfa,0x23,0x55,0x5f,0xf8,0x43,0xea,0x4e,0xb7,0xdc,0x7c,0xf3,0xfa,0xdc,0xc7,0xeb,0x1f,0xdc,0x64,0x66,0x71,0xb8,0x37,0xbb,0x2b,0x1d,0xb,0x44,0x23,0x13,0x80,0x99,0x11,0xe,0x23,0x50,0x65,0x6f,0x71,0xf5,0x93,0x95,0x9b,0x3f,0x6f,0xff,0xb6,0x76,0x9a,0x9c,0xa6,0x8,0x42,0x5f,0x79,0xfd,0x83,0x79,0xa7,0x24,0x5,0xfc,0xfa,0x2e,0x9,0x42,0xa8,0xd,0xc2,0x20,0x1a,0xfd,0x69,0x3,0x12,0x4,0xf8,0xf5,0x5d,0xa7,0x24,0x85,0xd7,0x3f,0x98,0xf,0x42,0x5f,0x9,0xc3,0x46,0xc,0xfc,0x81,0xb,0x0,0x91,0x66,0x30,0x1b,0x10,0x0,0x98,0x6c,0x7b,0x80,0xc0,0x60,0x66,0x44,0x21,0x3,0x0,0x6,0xfe,0xc0,0x35,0x6c,0x84,0xd0,0x5a,0x53,0x84,0x88,0x0,0x80,0x13,0xd9,0xcc,0xc,0x88,0xb8,0x10,0x0,0x40,0x0,0x1b,0x0,0xcc,0x0,0xc7,0x39,0x11,0x22,0xd2,0x5a,0x93,0xb4,0x6d,0x9b,0x11,0x25,0x89,0x86,0xc1,0x20,0x80,0x18,0xa0,0xe3,0xee,0x47,0xd0,0xcc,0x31,0xad,0x91,0x79,0xa3,0x40,0x4,0x80,0x91,0xe6,0xe5,0x83,0x73,0x37,0x64,0xee,0x2e,0xd8,0x24,0x9,0xc4,0xc7,0xa,0xb2,0x6a,0x8a,0x0,0x1c,0xf7,0xce,0x5e,0xc4,0xc5,0xe6,0x18,0x92,0x57,0x36,0x2,0x30,0x26,0x33,0x7b,0xe2,0x1e,0x71,0xe2,0xb,0x33,0x68,0xf2,0x8,0xd9,0x16,0x94,0xd1,0x13,0xff,0x9b,0x49,0xa,0xc0,0x6,0x6c,0x72,0xf6,0x8f,0xbb,0x58,0xe0,0x41,0x32,0x77,0x22,0x1a,0xc9,0xf2,0x49,0x87,0x89,0xcf,0x8a,0x14,0xc4,0x0,0x93,0x14,0x66,0xba,0xd1,0xf1,0xec,0xa6,0x18,0x60,0xe2,0xfa,0x91,0xde,0xd9,0xae,0x34,0xf9,0x31,0x52,0xba,0x1e,0x28,0x5d,0x4c,0x94,0xfa,0x99,0xbc,0xf,0x45,0xa,0x4c,0x5c,0x38,0xd6,0xc9,0xe0,0xe8,0x89,0xe4,0xad,0x1d,0x5f,0xca,0x9c,0x7f,0x15,0x8b,0x63,0xdc,0xc4,0x7c,0x8f,0x8c,0x91,0xb9,0x93,0x71,0xc0,0xd7,0xdf,0x7c,0xf5,0xea,0xd9,0x8b,0xa7,0x85,0x1d,0xcf,0x9f,0x7b,0x1f,0xdf,0xdf,0xfa,0x76,0xf1,0x44,0xc0,0xd9,0xa5,0x65,0x58,0xc2,0x2e,0x4,0x2c,0x2d,0xbe,0xf3,0xef,0xa,0x3c,0xaf,0x8f,0xde,0x7e,0xb7,0x10,0xe0,0x79,0xfd,0x91,0x6b,0x81,0xff,0x18,0x53,0xc0,0x14,0x30,0x5,0x4c,0x1,0x53,0xc0,0x14,0x30,0x5,0xfc,0xff,0x0,0x5a,0x6b,0x82,0x75,0xe2,0xe7,0xcf,0xc9,0x91,0xe6,0x58,0x19,0x5,0x16,0x2c,0x6,0x0,0x5b,0xca,0x89,0xf5,0x69,0x4e,0x5a,0x23,0x1c,0xe5,0x44,0x8e,0x52,0x1,0x0,0x94,0xdd,0x99,0x89,0x80,0x34,0xc7,0x51,0x2a,0x70,0x94,0x13,0x49,0x25,0xdd,0xa0,0xe4,0x96,0x5b,0xc3,0x43,0xcd,0x1b,0x9b,0x9f,0x5e,0xbc,0x71,0x9d,0x1e,0xf,0xfc,0x3,0xe8,0x30,0x1c,0xd9,0x74,0xd9,0x52,0xa2,0xec,0x9e,0xc2,0xc6,0xe6,0xd5,0x8b,0xc3,0x43,0xcd,0x25,0xb7,0xdc,0x52,0xd2,0xd,0x68,0x6b,0xeb,0x7e,0x65,0xef,0xaf,0x97,0xcb,0xdd,0xfd,0xce,0x87,0x9f,0x7d,0x71,0xe9,0xba,0xe3,0xda,0x85,0x4e,0xc,0x7d,0xcd,0x3f,0xfd,0xf0,0xeb,0x66,0x75,0xb6,0xf6,0xf0,0xad,0xb7,0x97,0x5f,0x12,0x33,0x5b,0xb7,0xbf,0xbb,0x3d,0xdb,0xea,0x74,0x97,0x3a,0xdd,0xee,0x7b,0x3,0xdf,0x9b,0xd7,0x5a,0xdb,0xc6,0x8c,0x7e,0xad,0xa,0x21,0x60,0xdb,0xb6,0x2e,0xbb,0x95,0xd7,0xb5,0x6a,0xf5,0x79,0xa3,0x56,0xfd,0xf3,0xda,0x97,0xd7,0xf6,0x29,0xdd,0xbd,0x6f,0x6f,0x3f,0x28,0xf5,0xff,0x6e,0x56,0xb4,0x19,0x2a,0x66,0x73,0xe2,0xe3,0x25,0x12,0xc6,0x16,0x4e,0x30,0x73,0x7a,0xc1,0x5b,0x5f,0xff,0xe8,0x10,0xc0,0xd1,0xf6,0x4,0xcc,0x4c,0x3b,0x3b,0x3b,0xa2,0xd1,0x68,0x14,0x8e,0xd0,0x6a,0xb5,0x78,0x6d,0x6d,0xcd,0x10,0xc5,0xdb,0xba,0x7f,0x0,0xb2,0x1f,0xaf,0x82,0x62,0x7a,0x69,0xbb,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char graph_node_selected_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x40, 0x8, 0x6, 0x0, 0x0, 0x0, 0x13, 0x7d, 0xf7, 0x96, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x8, 0x17, 0xd, 0x4, 0x3b, 0xfa, 0x91, 0x2a, 0xb6, 0x0, 0x0, 0x3, 0x44, 0x49, 0x44, 0x41, 0x54, 0x58, 0xc3, 0xed, 0x97, 0x3f, 0x68, 0xdc, 0x76, 0x14, 0xc7, 0xbf, 0xef, 0xa7, 0x9f, 0x7e, 0x3a, 0xdd, 0x39, 0xf6, 0xdd, 0x95, 0xb3, 0x3, 0xc1, 0x75, 0x1b, 0x70, 0xa, 0xe9, 0x98, 0x25, 0x93, 0x87, 0x52, 0x3a, 0x4, 0x2, 0xce, 0xe0, 0xd2, 0x34, 0x35, 0x94, 0x8e, 0x1d, 0xbc, 0xd5, 0x4b, 0xc7, 0x2e, 0x25, 0x63, 0x2, 0x5d, 0xa, 0xa5, 0xb1, 0x1b, 0x2, 0xf5, 0xd0, 0x40, 0xa0, 0x90, 0x10, 0x3a, 0x64, 0xca, 0x92, 0x31, 0x81, 0x24, 0xd0, 0xd2, 0x9a, 0x40, 0x2f, 0x17, 0xdf, 0x1f, 0xfb, 0x74, 0xf2, 0xe9, 0x27, 0xfd, 0x5e, 0x7, 0x49, 0xb6, 0x4e, 0xe7, 0xea, 0x86, 0x6e, 0xe5, 0x1e, 0xdc, 0x49, 0x42, 0xef, 0x7d, 0xde, 0xf7, 0x7d, 0xf5, 0x13, 0xe8, 0x47, 0xcc, 0x4c, 0x0, 0xc4, 0xbd, 0x7b, 0x4f, 0x9c, 0xb0, 0xdd, 0x71, 0xdb, 0xfb, 0x2d, 0xc7, 0xb0, 0x11, 0x5a, 0x7, 0x84, 0x4c, 0xd8, 0xb6, 0x62, 0x41, 0xc2, 0xd4, 0x67, 0x1b, 0x43, 0x59, 0xaf, 0xf9, 0x97, 0x2f, 0x5f, 0x18, 0x2, 0x30, 0xc4, 0xcc, 0xd6, 0xdd, 0x1f, 0xef, 0x9e, 0xea, 0x79, 0x83, 0x33, 0xed, 0x6e, 0xf7, 0x6c, 0xaf, 0xd7, 0x59, 0xe8, 0x7b, 0xfd, 0x72, 0x10, 0x4, 0x32, 0xb, 0x50, 0x4a, 0x85, 0x33, 0x95, 0x99, 0xc1, 0xdc, 0x5c, 0xad, 0x59, 0xaf, 0x56, 0x7f, 0x9f, 0xab, 0x94, 0x5f, 0xad, 0x7e, 0xbe, 0x7a, 0x40, 0x5b, 0x5b, 0xf7, 0x2b, 0x41, 0xbb, 0xf9, 0x6e, 0xa7, 0xd7, 0x5e, 0xb9, 0x72, 0x75, 0xe5, 0x86, 0x72, 0xa4, 0x85, 0x82, 0x8, 0x86, 0x61, 0xf4, 0xcb, 0x9d, 0x47, 0x1b, 0xb5, 0xb9, 0xfa, 0x23, 0x55, 0x5f, 0xf8, 0x43, 0xea, 0x4e, 0xb7, 0xdc, 0x7c, 0xf3, 0xfa, 0xdc, 0xc7, 0xeb, 0x1f, 0xdc, 0x64, 0x66, 0x71, 0xb8, 0x37, 0xbb, 0x2b, 0x1d, 0xb, 0x44, 0x23, 0x13, 0x80, 0x99, 0x11, 0xe, 0x23, 0x50, 0x65, 0x6f, 0x71, 0xf5, 0x93, 0x95, 0x9b, 0x3f, 0x6f, 0xff, 0xb6, 0x76, 0x9a, 0x9c, 0xa6, 0x8, 0x42, 0x5f, 0x79, 0xfd, 0x83, 0x79, 0xa7, 0x24, 0x5, 0xfc, 0xfa, 0x2e, 0x9, 0x42, 0xa8, 0xd, 0xc2, 0x20, 0x1a, 0xfd, 0x69, 0x3, 0x12, 0x4, 0xf8, 0xf5, 0x5d, 0xa7, 0x24, 0x85, 0xd7, 0x3f, 0x98, 0xf, 0x42, 0x5f, 0x9, 0xc3, 0x46, 0xc, 0xfc, 0x81, 0xb, 0x0, 0x91, 0x66, 0x30, 0x1b, 0x10, 0x0, 0x98, 0x6c, 0x7b, 0x80, 0xc0, 0x60, 0x66, 0x44, 0x21, 0x3, 0x0, 0x6, 0xfe, 0xc0, 0x35, 0x6c, 0x84, 0xd0, 0x5a, 0x53, 0x84, 0x88, 0x0, 0x80, 0x13, 0xd9, 0xcc, 0xc, 0x88, 0xb8, 0x10, 0x0, 0x40, 0x0, 0x1b, 0x0, 0xcc, 0x0, 0xc7, 0x39, 0x11, 0x22, 0xd2, 0x5a, 0x93, 0xb4, 0x6d, 0x9b, 0x11, 0x25, 0x89, 0x86, 0xc1, 0x20, 0x80, 0x18, 0xa0, 0xe3, 0xee, 0x47, 0xd0, 0xcc, 0x31, 0xad, 0x91, 0x79, 0xa3, 0x40, 0x4, 0x80, 0x91, 0xe6, 0xe5, 0x83, 0x73, 0x37, 0x64, 0xee, 0x2e, 0xd8, 0x24, 0x9, 0xc4, 0xc7, 0xa, 0xb2, 0x6a, 0x8a, 0x0, 0x1c, 0xf7, 0xce, 0x5e, 0xc4, 0xc5, 0xe6, 0x18, 0x92, 0x57, 0x36, 0x2, 0x30, 0x26, 0x33, 0x7b, 0xe2, 0x1e, 0x71, 0xe2, 0xb, 0x33, 0x68, 0xf2, 0x8, 0xd9, 0x16, 0x94, 0xd1, 0x13, 0xff, 0x9b, 0x49, 0xa, 0xc0, 0x6, 0x6c, 0x72, 0xf6, 0x8f, 0xbb, 0x58, 0xe0, 0x41, 0x32, 0x77, 0x22, 0x1a, 0xc9, 0xf2, 0x49, 0x87, 0x89, 0xcf, 0x8a, 0x14, 0xc4, 0x0, 0x93, 0x14, 0x66, 0xba, 0xd1, 0xf1, 0xec, 0xa6, 0x18, 0x60, 0xe2, 0xfa, 0x91, 0xde, 0xd9, 0xae, 0x34, 0xf9, 0x31, 0x52, 0xba, 0x1e, 0x28, 0x5d, 0x4c, 0x94, 0xfa, 0x99, 0xbc, 0xf, 0x45, 0xa, 0x4c, 0x5c, 0x38, 0xd6, 0xc9, 0xe0, 0xe8, 0x89, 0xe4, 0xad, 0x1d, 0x5f, 0xca, 0x9c, 0x7f, 0x15, 0x8b, 0x63, 0xdc, 0xc4, 0x7c, 0x8f, 0x8c, 0x91, 0xb9, 0x93, 0x71, 0xc0, 0xd7, 0xdf, 0x7c, 0xf5, 0xea, 0xd9, 0x8b, 0xa7, 0x85, 0x1d, 0xcf, 0x9f, 0x7b, 0x1f, 0xdf, 0xdf, 0xfa, 0x76, 0xf1, 0x44, 0xc0, 0xd9, 0xa5, 0x65, 0x58, 0xc2, 0x2e, 0x4, 0x2c, 0x2d, 0xbe, 0xf3, 0xef, 0xa, 0x3c, 0xaf, 0x8f, 0xde, 0x7e, 0xb7, 0x10, 0xe0, 0x79, 0xfd, 0x91, 0x6b, 0x81, 0xff, 0x18, 0x53, 0xc0, 0x14, 0x30, 0x5, 0x4c, 0x1, 0x53, 0xc0, 0x14, 0x30, 0x5, 0xfc, 0xff, 0x0, 0x5a, 0x6b, 0x82, 0x75, 0xe2, 0xe7, 0xcf, 0xc9, 0x91, 0xe6, 0x58, 0x19, 0x5, 0x16, 0x2c, 0x6, 0x0, 0x5b, 0xca, 0x89, 0xf5, 0x69, 0x4e, 0x5a, 0x23, 0x1c, 0xe5, 0x44, 0x8e, 0x52, 0x1, 0x0, 0x94, 0xdd, 0x99, 0x89, 0x80, 0x34, 0xc7, 0x51, 0x2a, 0x70, 0x94, 0x13, 0x49, 0x25, 0xdd, 0xa0, 0xe4, 0x96, 0x5b, 0xc3, 0x43, 0xcd, 0x1b, 0x9b, 0x9f, 0x5e, 0xbc, 0x71, 0x9d, 0x1e, 0xf, 0xfc, 0x3, 0xe8, 0x30, 0x1c, 0xd9, 0x74, 0xd9, 0x52, 0xa2, 0xec, 0x9e, 0xc2, 0xc6, 0xe6, 0xd5, 0x8b, 0xc3, 0x43, 0xcd, 0x25, 0xb7, 0xdc, 0x52, 0xd2, 0xd, 0x68, 0x6b, 0xeb, 0x7e, 0x65, 0xef, 0xaf, 0x97, 0xcb, 0xdd, 0xfd, 0xce, 0x87, 0x9f, 0x7d, 0x71, 0xe9, 0xba, 0xe3, 0xda, 0x85, 0x4e, 0xc, 0x7d, 0xcd, 0x3f, 0xfd, 0xf0, 0xeb, 0x66, 0x75, 0xb6, 0xf6, 0xf0, 0xad, 0xb7, 0x97, 0x5f, 0x12, 0x33, 0x5b, 0xb7, 0xbf, 0xbb, 0x3d, 0xdb, 0xea, 0x74, 0x97, 0x3a, 0xdd, 0xee, 0x7b, 0x3, 0xdf, 0x9b, 0xd7, 0x5a, 0xdb, 0xc6, 0x8c, 0x7e, 0xad, 0xa, 0x21, 0x60, 0xdb, 0xb6, 0x2e, 0xbb, 0x95, 0xd7, 0xb5, 0x6a, 0xf5, 0x79, 0xa3, 0x56, 0xfd, 0xf3, 0xda, 0x97, 0xd7, 0xf6, 0x29, 0xdd, 0xbd, 0x6f, 0x6f, 0x3f, 0x28, 0xf5, 0xff, 0x6e, 0x56, 0xb4, 0x19, 0x2a, 0x66, 0x73, 0xe2, 0xe3, 0x25, 0x12, 0xc6, 0x16, 0x4e, 0x30, 0x73, 0x7a, 0xc1, 0x5b, 0x5f, 0xff, 0xe8, 0x10, 0xc0, 0xd1, 0xf6, 0x4, 0xcc, 0x4c, 0x3b, 0x3b, 0x3b, 0xa2, 0xd1, 0x68, 0x14, 0x8e, 0xd0, 0x6a, 0xb5, 0x78, 0x6d, 0x6d, 0xcd, 0x10, 0xc5, 0xdb, 0xba, 0x7f, 0x0, 0xb2, 0x1f, 0xaf, 0x82, 0x62, 0x7a, 0x69, 0xbb, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char graph_port_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xa,0x0,0x0,0x0,0xa,0x8,0x6,0x0,0x0,0x0,0x8d,0x32,0xcf,0xbd,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0xc6,0x49,0x44,0x41,0x54,0x18,0x95,0x6d,0x90,0x3d,0x4e,0xc4,0x30,0x14,0x84,0xbf,0xb1,0xa8,0x92,0x48,0x39,0x46,0xe2,0x9a,0x9f,0x12,0xc1,0xbd,0x16,0x25,0x4b,0x41,0xb,0x67,0xa1,0xa7,0xa2,0x63,0xa1,0x76,0x94,0x5b,0x58,0x72,0x52,0x3e,0xd3,0xc4,0x11,0xda,0xe5,0xab,0x46,0xa3,0xd1,0x68,0xde,0x13,0x1b,0x21,0x84,0x7,0x49,0x3,0x70,0xbb,0x59,0x5f,0xc0,0x5b,0xdf,0xf7,0xef,0x0,0x2,0x98,0xa6,0xe9,0x0,0x1c,0x1,0xc7,0x19,0x39,0xe7,0x67,0xef,0xfd,0xa0,0xad,0xe9,0x3,0x70,0x6d,0xdb,0x52,0xd7,0x35,0x0,0xcb,0xb2,0x10,0x63,0x4,0x30,0xe7,0xdc,0xe3,0x95,0xa4,0xb1,0x84,0x9a,0xa6,0xd9,0x9b,0x8a,0x8e,0x31,0x3a,0x33,0x1b,0x1d,0x70,0xd,0xec,0x4d,0x7f,0xa9,0xaa,0xaa,0xc8,0x1b,0x7,0xe4,0x8b,0xc4,0x25,0xd9,0x1,0x3f,0x65,0xd3,0x39,0xeb,0xba,0x16,0xf9,0xed,0x80,0xd7,0x6d,0xb,0x29,0x25,0xcc,0xc,0x33,0x23,0xa5,0xb4,0x1f,0x23,0x69,0x14,0x40,0x8,0xe1,0x28,0xe9,0xf0,0xcf,0x7b,0x2c,0xe7,0xfc,0xe4,0xbd,0x7f,0x51,0x71,0xe6,0x79,0xbe,0x37,0xb3,0x1,0xb8,0xdb,0x76,0x9f,0x24,0x8d,0x5d,0xd7,0x7d,0x2,0xfc,0x2,0xfb,0x83,0x50,0x87,0x89,0x31,0xee,0x78,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char graph_port_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0xa, 0x8, 0x6, 0x0, 0x0, 0x0, 0x8d, 0x32, 0xcf, 0xbd, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0xc6, 0x49, 0x44, 0x41, 0x54, 0x18, 0x95, 0x6d, 0x90, 0x3d, 0x4e, 0xc4, 0x30, 0x14, 0x84, 0xbf, 0xb1, 0xa8, 0x92, 0x48, 0x39, 0x46, 0xe2, 0x9a, 0x9f, 0x12, 0xc1, 0xbd, 0x16, 0x25, 0x4b, 0x41, 0xb, 0x67, 0xa1, 0xa7, 0xa2, 0x63, 0xa1, 0x76, 0x94, 0x5b, 0x58, 0x72, 0x52, 0x3e, 0xd3, 0xc4, 0x11, 0xda, 0xe5, 0xab, 0x46, 0xa3, 0xd1, 0x68, 0xde, 0x13, 0x1b, 0x21, 0x84, 0x7, 0x49, 0x3, 0x70, 0xbb, 0x59, 0x5f, 0xc0, 0x5b, 0xdf, 0xf7, 0xef, 0x0, 0x2, 0x98, 0xa6, 0xe9, 0x0, 0x1c, 0x1, 0xc7, 0x19, 0x39, 0xe7, 0x67, 0xef, 0xfd, 0xa0, 0xad, 0xe9, 0x3, 0x70, 0x6d, 0xdb, 0x52, 0xd7, 0x35, 0x0, 0xcb, 0xb2, 0x10, 0x63, 0x4, 0x30, 0xe7, 0xdc, 0xe3, 0x95, 0xa4, 0xb1, 0x84, 0x9a, 0xa6, 0xd9, 0x9b, 0x8a, 0x8e, 0x31, 0x3a, 0x33, 0x1b, 0x1d, 0x70, 0xd, 0xec, 0x4d, 0x7f, 0xa9, 0xaa, 0xaa, 0xc8, 0x1b, 0x7, 0xe4, 0x8b, 0xc4, 0x25, 0xd9, 0x1, 0x3f, 0x65, 0xd3, 0x39, 0xeb, 0xba, 0x16, 0xf9, 0xed, 0x80, 0xd7, 0x6d, 0xb, 0x29, 0x25, 0xcc, 0xc, 0x33, 0x23, 0xa5, 0xb4, 0x1f, 0x23, 0x69, 0x14, 0x40, 0x8, 0xe1, 0x28, 0xe9, 0xf0, 0xcf, 0x7b, 0x2c, 0xe7, 0xfc, 0xe4, 0xbd, 0x7f, 0x51, 0x71, 0xe6, 0x79, 0xbe, 0x37, 0xb3, 0x1, 0xb8, 0xdb, 0x76, 0x9f, 0x24, 0x8d, 0x5d, 0xd7, 0x7d, 0x2, 0xfc, 0x2, 0xfb, 0x83, 0x50, 0x87, 0x89, 0x31, 0xee, 0x78, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char hseparator_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x2,0x3,0x0,0x0,0x0,0xb9,0x61,0x56,0x18,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0xc,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x73,0x9b,0xaa,0xce,0xdc,0xe1,0xff,0xff,0xff,0x64,0x6c,0x1,0xd2,0x0,0x0,0x0,0x3,0x74,0x52,0x4e,0x53,0x0,0xb3,0xb3,0x67,0xf6,0xdb,0x93,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x3,0x11,0xc,0x4c,0xf2,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x10,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0x64,0x60,0x60,0xc2,0x40,0x8c,0xc,0x0,0x0,0xc7,0x0,0xf,0xf5,0x92,0x2f,0xa7,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char hseparator_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x2, 0x3, 0x0, 0x0, 0x0, 0xb9, 0x61, 0x56, 0x18, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0xc, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x73, 0x9b, 0xaa, 0xce, 0xdc, 0xe1, 0xff, 0xff, 0xff, 0x64, 0x6c, 0x1, 0xd2, 0x0, 0x0, 0x0, 0x3, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xb3, 0xb3, 0x67, 0xf6, 0xdb, 0x93, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x3, 0x11, 0xc, 0x4c, 0xf2, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x10, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x64, 0x60, 0x60, 0xc2, 0x40, 0x8c, 0xc, 0x0, 0x0, 0xc7, 0x0, 0xf, 0xf5, 0x92, 0x2f, 0xa7, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char hslider_bg_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x4e,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x40,0x3e,0x4a,0x2a,0x29,0x2f,0x20,0x20,0x24,0x3f,0x3e,0x49,0x1f,0x1f,0x24,0x20,0x20,0x24,0x4d,0x4b,0x59,0x3f,0x3e,0x49,0x3f,0x3e,0x49,0x1e,0x1e,0x23,0x1f,0x1f,0x23,0x20,0x20,0x25,0x22,0x22,0x27,0x23,0x23,0x27,0x23,0x23,0x28,0x25,0x25,0x2a,0xff,0xff,0xff,0x5f,0xd6,0x94,0x4d,0x0,0x0,0x0,0x12,0x74,0x52,0x4e,0x53,0x0,0x0,0x4,0x19,0x40,0x5d,0x66,0x68,0x28,0x93,0xf0,0xfc,0x94,0xfc,0xfd,0x1a,0x96,0x95,0x6b,0xe2,0xd5,0x49,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x19,0xec,0x6e,0xb5,0x88,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x65,0x49,0x44,0x41,0x54,0x18,0xd3,0x85,0xce,0xdd,0xe,0x80,0x20,0x8,0x5,0x60,0x54,0xb4,0x22,0xb5,0x34,0x7f,0x7a,0xff,0x27,0x8d,0xad,0xd6,0x6a,0x5c,0xf8,0xdd,0xc1,0x6,0xe7,0x0,0x8c,0xa9,0x1f,0x9e,0xb5,0x41,0xeb,0x26,0xe6,0x2c,0x1a,0xad,0x40,0xcf,0xb,0xad,0xf9,0x60,0x79,0xa5,0x65,0xd6,0x60,0x7c,0x28,0xb5,0x75,0xd6,0x6a,0x9,0xde,0x0,0x52,0xe9,0xe7,0xa3,0x17,0x42,0xb0,0xb1,0x9e,0xaf,0x1a,0xad,0x5c,0x88,0x93,0x6d,0xff,0x3e,0xdd,0x37,0x8e,0x4d,0x14,0xef,0xd8,0x48,0x89,0x63,0x45,0x31,0x51,0x7d,0xe8,0x2,0xf5,0xf,0x9,0x67,0xd9,0x88,0x8f,0x5b,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char hslider_bg_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x4e, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x40, 0x3e, 0x4a, 0x2a, 0x29, 0x2f, 0x20, 0x20, 0x24, 0x3f, 0x3e, 0x49, 0x1f, 0x1f, 0x24, 0x20, 0x20, 0x24, 0x4d, 0x4b, 0x59, 0x3f, 0x3e, 0x49, 0x3f, 0x3e, 0x49, 0x1e, 0x1e, 0x23, 0x1f, 0x1f, 0x23, 0x20, 0x20, 0x25, 0x22, 0x22, 0x27, 0x23, 0x23, 0x27, 0x23, 0x23, 0x28, 0x25, 0x25, 0x2a, 0xff, 0xff, 0xff, 0x5f, 0xd6, 0x94, 0x4d, 0x0, 0x0, 0x0, 0x12, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x4, 0x19, 0x40, 0x5d, 0x66, 0x68, 0x28, 0x93, 0xf0, 0xfc, 0x94, 0xfc, 0xfd, 0x1a, 0x96, 0x95, 0x6b, 0xe2, 0xd5, 0x49, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x19, 0xec, 0x6e, 0xb5, 0x88, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x65, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x85, 0xce, 0xdd, 0xe, 0x80, 0x20, 0x8, 0x5, 0x60, 0x54, 0xb4, 0x22, 0xb5, 0x34, 0x7f, 0x7a, 0xff, 0x27, 0x8d, 0xad, 0xd6, 0x6a, 0x5c, 0xf8, 0xdd, 0xc1, 0x6, 0xe7, 0x0, 0x8c, 0xa9, 0x1f, 0x9e, 0xb5, 0x41, 0xeb, 0x26, 0xe6, 0x2c, 0x1a, 0xad, 0x40, 0xcf, 0xb, 0xad, 0xf9, 0x60, 0x79, 0xa5, 0x65, 0xd6, 0x60, 0x7c, 0x28, 0xb5, 0x75, 0xd6, 0x6a, 0x9, 0xde, 0x0, 0x52, 0xe9, 0xe7, 0xa3, 0x17, 0x42, 0xb0, 0xb1, 0x9e, 0xaf, 0x1a, 0xad, 0x5c, 0x88, 0x93, 0x6d, 0xff, 0x3e, 0xdd, 0x37, 0x8e, 0x4d, 0x14, 0xef, 0xd8, 0x48, 0x89, 0x63, 0x45, 0x31, 0x51, 0x7d, 0xe8, 0x2, 0xf5, 0xf, 0x9, 0x67, 0xd9, 0x88, 0x8f, 0x5b, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char hslider_grabber_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x4,0x0,0x0,0x0,0xb5,0xfa,0x37,0xea,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x1,0x1d,0x49,0x44,0x41,0x54,0x28,0xcf,0x85,0xd1,0x3f,0x4b,0xc3,0x40,0x18,0xc7,0xf1,0xef,0x25,0xad,0x89,0xa9,0x70,0x83,0x43,0x5d,0xc4,0x21,0x6e,0x4a,0x7,0x47,0xdf,0x83,0x53,0x16,0x17,0xd7,0x4e,0xbe,0x2,0x5f,0x85,0x83,0xa0,0xb8,0x38,0xb8,0x88,0xd0,0x51,0x5d,0x1c,0x1c,0x1c,0x1c,0x2a,0xa2,0xe8,0x22,0x2d,0x82,0x2d,0x88,0x54,0xed,0x3f,0x1b,0x9a,0x78,0x49,0x1c,0x9a,0x54,0x4f,0x5,0x6f,0x3a,0xee,0xf9,0xf0,0x3c,0x3f,0x9e,0x83,0x7f,0x8e,0x18,0xdf,0x4c,0x1c,0x24,0x5,0x60,0x40,0x17,0x9f,0x48,0x7,0x26,0xd3,0xe5,0x55,0xd7,0x93,0x25,0xe8,0xde,0xd4,0x2b,0xbb,0x7,0xbc,0x8e,0x88,0x99,0x82,0xa9,0xf2,0xda,0xe2,0x86,0x58,0x78,0xb7,0x87,0xf6,0xc4,0xdc,0xcc,0xd2,0x6c,0xfb,0xf2,0x8e,0x10,0xc0,0x48,0x81,0x74,0x3d,0x55,0xf4,0x51,0x28,0x7c,0x54,0xd1,0xf5,0x90,0xa3,0x42,0x6,0xa,0xb2,0x14,0x90,0x0,0x90,0x10,0x20,0x4b,0x14,0x74,0x20,0x62,0xf1,0x3d,0x7b,0x24,0xb2,0x74,0x19,0x8,0x83,0x96,0x39,0x2e,0xb,0x82,0x37,0x94,0xe,0x6,0xbd,0xdb,0xfc,0x18,0xe4,0x49,0x9e,0xf0,0x75,0xd0,0xbf,0x3e,0xb6,0x22,0x23,0x7d,0x9a,0x4c,0xce,0xf6,0xe8,0xe9,0x20,0xb8,0xaa,0x6,0xcd,0x1c,0x0,0x39,0x3e,0x1e,0x4f,0xce,0x7f,0x76,0x88,0x1f,0x1a,0xcf,0xa7,0xe,0x6,0x6,0xe,0x8d,0x23,0xd5,0x22,0xd6,0x41,0x42,0x77,0x6b,0x33,0xaa,0x59,0x58,0xc4,0xf5,0x9d,0xed,0x6c,0xc0,0xd7,0x26,0x21,0xe,0x7,0x9d,0xda,0xf2,0x8a,0x1d,0x1f,0xae,0xdf,0x57,0x19,0xfe,0x6,0xa0,0x9a,0x2f,0xf3,0xed,0xfe,0xc5,0x7e,0x85,0xce,0x5f,0xbf,0x39,0xca,0x67,0x21,0x18,0x66,0x3b,0x0,0xf8,0x4,0x7e,0x5c,0x62,0x33,0x51,0xf0,0xbb,0xff,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char hslider_grabber_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x1, 0x1d, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x85, 0xd1, 0x3f, 0x4b, 0xc3, 0x40, 0x18, 0xc7, 0xf1, 0xef, 0x25, 0xad, 0x89, 0xa9, 0x70, 0x83, 0x43, 0x5d, 0xc4, 0x21, 0x6e, 0x4a, 0x7, 0x47, 0xdf, 0x83, 0x53, 0x16, 0x17, 0xd7, 0x4e, 0xbe, 0x2, 0x5f, 0x85, 0x83, 0xa0, 0xb8, 0x38, 0xb8, 0x88, 0xd0, 0x51, 0x5d, 0x1c, 0x1c, 0x1c, 0x1c, 0x2a, 0xa2, 0xe8, 0x22, 0x2d, 0x82, 0x2d, 0x88, 0x54, 0xed, 0x3f, 0x1b, 0x9a, 0x78, 0x49, 0x1c, 0x9a, 0x54, 0x4f, 0x5, 0x6f, 0x3a, 0xee, 0xf9, 0xf0, 0x3c, 0x3f, 0x9e, 0x83, 0x7f, 0x8e, 0x18, 0xdf, 0x4c, 0x1c, 0x24, 0x5, 0x60, 0x40, 0x17, 0x9f, 0x48, 0x7, 0x26, 0xd3, 0xe5, 0x55, 0xd7, 0x93, 0x25, 0xe8, 0xde, 0xd4, 0x2b, 0xbb, 0x7, 0xbc, 0x8e, 0x88, 0x99, 0x82, 0xa9, 0xf2, 0xda, 0xe2, 0x86, 0x58, 0x78, 0xb7, 0x87, 0xf6, 0xc4, 0xdc, 0xcc, 0xd2, 0x6c, 0xfb, 0xf2, 0x8e, 0x10, 0xc0, 0x48, 0x81, 0x74, 0x3d, 0x55, 0xf4, 0x51, 0x28, 0x7c, 0x54, 0xd1, 0xf5, 0x90, 0xa3, 0x42, 0x6, 0xa, 0xb2, 0x14, 0x90, 0x0, 0x90, 0x10, 0x20, 0x4b, 0x14, 0x74, 0x20, 0x62, 0xf1, 0x3d, 0x7b, 0x24, 0xb2, 0x74, 0x19, 0x8, 0x83, 0x96, 0x39, 0x2e, 0xb, 0x82, 0x37, 0x94, 0xe, 0x6, 0xbd, 0xdb, 0xfc, 0x18, 0xe4, 0x49, 0x9e, 0xf0, 0x75, 0xd0, 0xbf, 0x3e, 0xb6, 0x22, 0x23, 0x7d, 0x9a, 0x4c, 0xce, 0xf6, 0xe8, 0xe9, 0x20, 0xb8, 0xaa, 0x6, 0xcd, 0x1c, 0x0, 0x39, 0x3e, 0x1e, 0x4f, 0xce, 0x7f, 0x76, 0x88, 0x1f, 0x1a, 0xcf, 0xa7, 0xe, 0x6, 0x6, 0xe, 0x8d, 0x23, 0xd5, 0x22, 0xd6, 0x41, 0x42, 0x77, 0x6b, 0x33, 0xaa, 0x59, 0x58, 0xc4, 0xf5, 0x9d, 0xed, 0x6c, 0xc0, 0xd7, 0x26, 0x21, 0xe, 0x7, 0x9d, 0xda, 0xf2, 0x8a, 0x1d, 0x1f, 0xae, 0xdf, 0x57, 0x19, 0xfe, 0x6, 0xa0, 0x9a, 0x2f, 0xf3, 0xed, 0xfe, 0xc5, 0x7e, 0x85, 0xce, 0x5f, 0xbf, 0x39, 0xca, 0x67, 0x21, 0x18, 0x66, 0x3b, 0x0, 0xf8, 0x4, 0x7e, 0x5c, 0x62, 0x33, 0x51, 0xf0, 0xbb, 0xff, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char hslider_grabber_hl_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0xc6,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x48,0x83,0x83,0x60,0xaf,0xb1,0x65,0xbb,0xca,0x61,0xb3,0xc2,0x0,0x0,0x0,0x63,0xb7,0xc8,0x63,0xb7,0xc7,0x0,0x0,0x0,0x61,0xb3,0xbc,0x60,0xb1,0xbc,0x0,0x0,0x0,0x0,0x0,0x0,0x5b,0xa6,0xa5,0x63,0xb4,0xb6,0x0,0x0,0x0,0x0,0x0,0x0,0x3a,0x69,0x69,0x5e,0xb1,0xcd,0x5e,0xb0,0xcd,0x36,0x63,0x63,0x0,0x0,0x0,0x17,0x2a,0x29,0x60,0xb2,0xbd,0x62,0xb3,0xbf,0x3,0x5,0x5,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x55,0x9b,0x9a,0x52,0x96,0x95,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0xf,0xf,0x62,0xb4,0xbd,0x63,0xb7,0xbf,0x0,0x0,0x0,0x27,0x48,0x47,0x68,0xc0,0xcf,0x68,0xc1,0xcf,0x2d,0x52,0x52,0x51,0x93,0x92,0x56,0x9d,0x9c,0x0,0x0,0x0,0x54,0xa2,0xc8,0x4c,0x94,0xc2,0x48,0x8e,0xc0,0x47,0x8c,0xbf,0x4b,0x93,0xc2,0x4b,0x92,0xc2,0x4f,0x98,0xc4,0x4d,0x96,0xc3,0x55,0xa3,0xc8,0x53,0x9f,0xc7,0x49,0x8f,0xc0,0x4e,0x97,0xc4,0x5a,0xab,0xcb,0x5a,0xac,0xcc,0x52,0x9e,0xc6,0x51,0x9d,0xc6,0xff,0xff,0xff,0x6b,0x1e,0xb5,0x61,0x0,0x0,0x0,0x31,0x74,0x52,0x4e,0x53,0x0,0x3,0xd,0x1c,0x27,0x16,0x6e,0xc1,0xef,0xe8,0x28,0xf0,0xf0,0x22,0xdb,0xde,0x24,0x17,0xaf,0xc5,0x1a,0xa,0x65,0xfc,0xfe,0x64,0xc,0x31,0xe0,0xe0,0x28,0x2,0x1,0x14,0x9c,0x95,0x13,0x5,0x2c,0xdb,0xdc,0xb,0x4f,0xf4,0xf7,0x55,0x73,0x7d,0x4,0x28,0xf1,0xfd,0xa1,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x41,0x89,0xde,0x6c,0x4e,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x4,0x4e,0x1d,0x2,0xaf,0x0,0x0,0x0,0x9e,0x49,0x44,0x41,0x54,0x18,0xd3,0x6d,0xcf,0xd7,0x12,0x82,0x30,0x10,0x5,0x50,0x48,0x42,0x12,0xb0,0x77,0x8d,0xd,0xb,0x28,0x56,0x12,0x62,0xd,0x96,0xff,0xff,0x2a,0x61,0xc,0xe0,0x83,0xfb,0xb4,0xf7,0xcc,0xec,0xcc,0x5d,0xc3,0xf8,0x37,0x26,0x80,0x8,0x41,0x60,0xe6,0xd9,0xc2,0x84,0x52,0x82,0xad,0x4c,0x0,0xb6,0xb9,0x10,0xdc,0xc6,0x40,0x3,0x24,0x3c,0x92,0x32,0xe2,0x4,0x6a,0x40,0x54,0xc8,0x64,0x4,0x45,0x1a,0x9c,0xd2,0x29,0x85,0x73,0xd9,0xd1,0x50,0xa9,0x5e,0x52,0xb8,0xd6,0xea,0x1a,0x1a,0xcd,0x5b,0xa,0xf7,0x56,0x5b,0x43,0xa7,0xdb,0x53,0x52,0xaa,0xfe,0x80,0x65,0x3d,0x86,0xa3,0x58,0xca,0x78,0x3c,0x99,0x6a,0x70,0x67,0xf3,0x87,0x52,0xcf,0xc5,0x32,0xaf,0xee,0xf9,0xab,0xd7,0x7b,0xed,0x7b,0xc5,0x33,0xc1,0x66,0xbb,0xdb,0xb3,0x22,0x27,0x47,0x87,0xa3,0xe5,0xfe,0xfe,0x1b,0x6,0x2c,0xfc,0x6e,0x1f,0x93,0x2a,0x10,0x62,0x3,0x21,0x32,0x75,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char hslider_grabber_disabled_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe1, 0x7, 0xa, 0x13, 0x2f, 0x7, 0x5e, 0x49, 0xee, 0x14, 0x0, 0x0, 0x0, 0x1d, 0x69, 0x54, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x0, 0x0, 0x0, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x64, 0x2e, 0x65, 0x7, 0x0, 0x0, 0x0, 0xea, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x63, 0x60, 0x20, 0x1a, 0x30, 0x33, 0xf0, 0x32, 0xc8, 0x30, 0xa8, 0x3, 0xa1, 0xc, 0x90, 0xc5, 0x8c, 0x29, 0x2d, 0x66, 0x9c, 0xe7, 0x7a, 0xd0, 0xe7, 0xbd, 0xcf, 0x7b, 0xd7, 0x83, 0xc6, 0x79, 0xc, 0x62, 0xe8, 0x4a, 0x78, 0x8d, 0xf3, 0x3c, 0x5f, 0xb8, 0xff, 0x77, 0x1, 0x42, 0xf7, 0xff, 0x9e, 0x2f, 0x80, 0x4a, 0x78, 0x51, 0x15, 0xc8, 0xb8, 0x1e, 0x74, 0xff, 0xef, 0x4, 0x85, 0xee, 0xff, 0x5d, 0xf, 0x2, 0x2d, 0x42, 0x1, 0xea, 0x3e, 0xef, 0x5d, 0xe0, 0xa, 0x5c, 0xfe, 0xfb, 0xbc, 0x7, 0xba, 0x5, 0x5, 0x68, 0x78, 0x7f, 0x40, 0x56, 0xe0, 0xfd, 0x81, 0x41, 0x3, 0x55, 0x81, 0x92, 0xc7, 0x6d, 0x57, 0x24, 0x5, 0xee, 0xf7, 0x18, 0x54, 0x50, 0x15, 0x88, 0x3b, 0xae, 0xf7, 0x40, 0x72, 0x83, 0xfb, 0x51, 0x6, 0x29, 0x54, 0x5, 0x5c, 0x9a, 0xa9, 0xde, 0x7f, 0x9c, 0xc1, 0xd2, 0xce, 0xff, 0xbd, 0xff, 0xa9, 0xa7, 0x30, 0xf0, 0xa0, 0x85, 0x83, 0xa0, 0xa1, 0xc7, 0x3, 0x88, 0x25, 0xae, 0xff, 0x3d, 0x1f, 0x30, 0x69, 0x30, 0x30, 0xa1, 0x2a, 0x60, 0x64, 0x10, 0xb1, 0x99, 0xe3, 0x5, 0xd4, 0xed, 0xfc, 0xdf, 0xeb, 0xbf, 0xd5, 0x54, 0x6, 0x61, 0xcc, 0xa0, 0x66, 0x65, 0xd3, 0xf1, 0xb8, 0xed, 0xf6, 0xdf, 0xed, 0xbf, 0xe7, 0x1d, 0x36, 0x1d, 0x6, 0x56, 0x6c, 0xb1, 0xc1, 0x2d, 0xe3, 0xef, 0xf7, 0xc5, 0xef, 0xbb, 0x42, 0x28, 0xba, 0xfd, 0x48, 0xd6, 0x58, 0x16, 0xdb, 0xd6, 0x2, 0xe3, 0x81, 0x11, 0x57, 0x8c, 0xb2, 0x30, 0x70, 0x3, 0x75, 0xb3, 0x20, 0xb, 0x1, 0x0, 0x4, 0x5c, 0x63, 0x9b, 0x17, 0x86, 0x76, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char hslider_tick_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x10,0x4,0x3,0x0,0x0,0x0,0xc3,0x98,0xc3,0xc0,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x1e,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x38,0x55,0x5f,0x8c,0xac,0xb8,0x81,0xa2,0xad,0x98,0x98,0x98,0x4e,0x4e,0x4e,0x8d,0x8d,0x8d,0x82,0x82,0x82,0x4e,0x4e,0x4e,0xff,0xff,0xff,0xc1,0xc9,0xb1,0x80,0x0,0x0,0x0,0x9,0x74,0x52,0x4e,0x53,0x0,0x0,0x0,0x0,0x79,0x31,0x79,0x79,0x1c,0x7e,0xed,0x4b,0xf4,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x9,0xf1,0xd9,0xa5,0xec,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x21,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0x9,0x60,0x60,0xb,0x60,0x60,0xf,0x60,0x60,0x6d,0x60,0x60,0x14,0x60,0xc0,0x4,0x4c,0x2,0xc,0xcc,0x2,0xc,0x30,0x65,0x0,0x46,0x9d,0x2,0xbe,0x9f,0x3a,0x6c,0xab,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char hslider_grabber_hl_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0xc6, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x48, 0x83, 0x83, 0x60, 0xaf, 0xb1, 0x65, 0xbb, 0xca, 0x61, 0xb3, 0xc2, 0x0, 0x0, 0x0, 0x63, 0xb7, 0xc8, 0x63, 0xb7, 0xc7, 0x0, 0x0, 0x0, 0x61, 0xb3, 0xbc, 0x60, 0xb1, 0xbc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5b, 0xa6, 0xa5, 0x63, 0xb4, 0xb6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0x69, 0x69, 0x5e, 0xb1, 0xcd, 0x5e, 0xb0, 0xcd, 0x36, 0x63, 0x63, 0x0, 0x0, 0x0, 0x17, 0x2a, 0x29, 0x60, 0xb2, 0xbd, 0x62, 0xb3, 0xbf, 0x3, 0x5, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55, 0x9b, 0x9a, 0x52, 0x96, 0x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0xf, 0xf, 0x62, 0xb4, 0xbd, 0x63, 0xb7, 0xbf, 0x0, 0x0, 0x0, 0x27, 0x48, 0x47, 0x68, 0xc0, 0xcf, 0x68, 0xc1, 0xcf, 0x2d, 0x52, 0x52, 0x51, 0x93, 0x92, 0x56, 0x9d, 0x9c, 0x0, 0x0, 0x0, 0x54, 0xa2, 0xc8, 0x4c, 0x94, 0xc2, 0x48, 0x8e, 0xc0, 0x47, 0x8c, 0xbf, 0x4b, 0x93, 0xc2, 0x4b, 0x92, 0xc2, 0x4f, 0x98, 0xc4, 0x4d, 0x96, 0xc3, 0x55, 0xa3, 0xc8, 0x53, 0x9f, 0xc7, 0x49, 0x8f, 0xc0, 0x4e, 0x97, 0xc4, 0x5a, 0xab, 0xcb, 0x5a, 0xac, 0xcc, 0x52, 0x9e, 0xc6, 0x51, 0x9d, 0xc6, 0xff, 0xff, 0xff, 0x6b, 0x1e, 0xb5, 0x61, 0x0, 0x0, 0x0, 0x31, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x3, 0xd, 0x1c, 0x27, 0x16, 0x6e, 0xc1, 0xef, 0xe8, 0x28, 0xf0, 0xf0, 0x22, 0xdb, 0xde, 0x24, 0x17, 0xaf, 0xc5, 0x1a, 0xa, 0x65, 0xfc, 0xfe, 0x64, 0xc, 0x31, 0xe0, 0xe0, 0x28, 0x2, 0x1, 0x14, 0x9c, 0x95, 0x13, 0x5, 0x2c, 0xdb, 0xdc, 0xb, 0x4f, 0xf4, 0xf7, 0x55, 0x73, 0x7d, 0x4, 0x28, 0xf1, 0xfd, 0xa1, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x41, 0x89, 0xde, 0x6c, 0x4e, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x4, 0x4e, 0x1d, 0x2, 0xaf, 0x0, 0x0, 0x0, 0x9e, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x6d, 0xcf, 0xd7, 0x12, 0x82, 0x30, 0x10, 0x5, 0x50, 0x48, 0x42, 0x12, 0xb0, 0x77, 0x8d, 0xd, 0xb, 0x28, 0x56, 0x12, 0x62, 0xd, 0x96, 0xff, 0xff, 0x2a, 0x61, 0xc, 0xe0, 0x83, 0xfb, 0xb4, 0xf7, 0xcc, 0xec, 0xcc, 0x5d, 0xc3, 0xf8, 0x37, 0x26, 0x80, 0x8, 0x41, 0x60, 0xe6, 0xd9, 0xc2, 0x84, 0x52, 0x82, 0xad, 0x4c, 0x0, 0xb6, 0xb9, 0x10, 0xdc, 0xc6, 0x40, 0x3, 0x24, 0x3c, 0x92, 0x32, 0xe2, 0x4, 0x6a, 0x40, 0x54, 0xc8, 0x64, 0x4, 0x45, 0x1a, 0x9c, 0xd2, 0x29, 0x85, 0x73, 0xd9, 0xd1, 0x50, 0xa9, 0x5e, 0x52, 0xb8, 0xd6, 0xea, 0x1a, 0x1a, 0xcd, 0x5b, 0xa, 0xf7, 0x56, 0x5b, 0x43, 0xa7, 0xdb, 0x53, 0x52, 0xaa, 0xfe, 0x80, 0x65, 0x3d, 0x86, 0xa3, 0x58, 0xca, 0x78, 0x3c, 0x99, 0x6a, 0x70, 0x67, 0xf3, 0x87, 0x52, 0xcf, 0xc5, 0x32, 0xaf, 0xee, 0xf9, 0xab, 0xd7, 0x7b, 0xed, 0x7b, 0xc5, 0x33, 0xc1, 0x66, 0xbb, 0xdb, 0xb3, 0x22, 0x27, 0x47, 0x87, 0xa3, 0xe5, 0xfe, 0xfe, 0x1b, 0x6, 0x2c, 0xfc, 0x6e, 0x1f, 0x93, 0x2a, 0x10, 0x62, 0x3, 0x21, 0x32, 0x75, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char hsplit_bg_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x1,0x3,0x0,0x0,0x0,0xfe,0xc1,0x2c,0xc8,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x6,0x50,0x4c,0x54,0x45,0x27,0x27,0x29,0xff,0xff,0xff,0x11,0xab,0xb9,0xf3,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x1,0xff,0x2,0x2d,0xde,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0xb,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0x40,0x5,0x0,0x0,0x10,0x0,0x1,0xa1,0xc5,0x21,0xc1,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char hslider_tick_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xc3, 0x98, 0xc3, 0xc0, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x1e, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x38, 0x55, 0x5f, 0x8c, 0xac, 0xb8, 0x81, 0xa2, 0xad, 0x98, 0x98, 0x98, 0x4e, 0x4e, 0x4e, 0x8d, 0x8d, 0x8d, 0x82, 0x82, 0x82, 0x4e, 0x4e, 0x4e, 0xff, 0xff, 0xff, 0xc1, 0xc9, 0xb1, 0x80, 0x0, 0x0, 0x0, 0x9, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x0, 0x0, 0x79, 0x31, 0x79, 0x79, 0x1c, 0x7e, 0xed, 0x4b, 0xf4, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x9, 0xf1, 0xd9, 0xa5, 0xec, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x21, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x9, 0x60, 0x60, 0xb, 0x60, 0x60, 0xf, 0x60, 0x60, 0x6d, 0x60, 0x60, 0x14, 0x60, 0xc0, 0x4, 0x4c, 0x2, 0xc, 0xcc, 0x2, 0xc, 0x30, 0x65, 0x0, 0x46, 0x9d, 0x2, 0xbe, 0x9f, 0x3a, 0x6c, 0xab, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char hsplitter_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x40,0x8,0x0,0x0,0x0,0x0,0x2,0x6f,0x69,0x56,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x74,0x52,0x4e,0x53,0x0,0x0,0x76,0x93,0xcd,0x38,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x4,0x4e,0x1d,0x2,0xaf,0x0,0x0,0x0,0x27,0x49,0x44,0x41,0x54,0x28,0xcf,0x63,0x60,0x80,0x2,0x66,0x86,0x5,0xa2,0xe7,0x18,0x16,0x88,0x9e,0x63,0x66,0x10,0xbd,0xf6,0x98,0x41,0xf4,0xda,0x63,0x6,0xc,0x30,0xaa,0x66,0x54,0xd,0x9a,0x1a,0x0,0x5c,0x29,0x6a,0x81,0x90,0x8f,0x52,0x12,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char hsplit_bg_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x1, 0x3, 0x0, 0x0, 0x0, 0xfe, 0xc1, 0x2c, 0xc8, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x6, 0x50, 0x4c, 0x54, 0x45, 0x27, 0x27, 0x29, 0xff, 0xff, 0xff, 0x11, 0xab, 0xb9, 0xf3, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x1, 0xff, 0x2, 0x2d, 0xde, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0xb, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x40, 0x5, 0x0, 0x0, 0x10, 0x0, 0x1, 0xa1, 0xc5, 0x21, 0xc1, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char icon_add_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x36,0x49,0x44,0x41,0x54,0x38,0x8d,0x63,0x60,0xa0,0x25,0x78,0xf0,0xe0,0xc1,0xff,0x7,0xf,0x1e,0xfc,0xc7,0xa7,0x86,0x89,0x52,0x4b,0x46,0xd,0x60,0x60,0x60,0x64,0x60,0x80,0x84,0x36,0x39,0x9a,0x15,0x14,0x14,0x18,0x29,0x76,0x1,0x5e,0x30,0x9a,0xe,0xe8,0x64,0x0,0xc5,0x0,0x0,0xc7,0x6e,0x12,0x94,0xf9,0x26,0x2e,0xdb,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char hsplitter_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x40, 0x8, 0x0, 0x0, 0x0, 0x0, 0x2, 0x6f, 0x69, 0x56, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x2, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x76, 0x93, 0xcd, 0x38, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x4, 0x4e, 0x1d, 0x2, 0xaf, 0x0, 0x0, 0x0, 0x27, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x63, 0x60, 0x80, 0x2, 0x66, 0x86, 0x5, 0xa2, 0xe7, 0x18, 0x16, 0x88, 0x9e, 0x63, 0x66, 0x10, 0xbd, 0xf6, 0x98, 0x41, 0xf4, 0xda, 0x63, 0x6, 0xc, 0x30, 0xaa, 0x66, 0x54, 0xd, 0x9a, 0x1a, 0x0, 0x5c, 0x29, 0x6a, 0x81, 0x90, 0x8f, 0x52, 0x12, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char icon_close_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9b,0x49,0x44,0x41,0x54,0x38,0x8d,0xcd,0x92,0x31,0xe,0xc2,0x30,0x10,0x4,0x17,0xaa,0x3d,0x67,0xdb,0x58,0xd0,0xd3,0xf0,0xa3,0x7c,0x36,0x3c,0x82,0x48,0x44,0x22,0x6f,0xb1,0x4d,0x85,0x14,0x81,0xf,0x2c,0x28,0xe0,0xda,0xd5,0x8c,0x4e,0x77,0xb,0xfc,0xd5,0x98,0xd9,0x20,0x29,0x7a,0xb9,0xa4,0x68,0x66,0x83,0xb,0x93,0xcc,0x24,0xa7,0x9a,0x44,0x52,0x24,0x39,0x91,0xcc,0x55,0x89,0xa4,0xde,0xcc,0xce,0x24,0xb,0xc9,0x39,0x84,0xb0,0xf7,0xb2,0xae,0xeb,0x76,0xde,0x8a,0x4f,0x92,0x66,0xd8,0x91,0x5c,0x49,0x5e,0x9a,0xe1,0xb5,0x64,0x5,0x16,0x92,0x8b,0x7,0x6f,0x9b,0x8c,0x0,0x4a,0x29,0x9b,0x26,0x81,0xa4,0x3e,0xa5,0x34,0x2,0x38,0x2,0x58,0x0,0xcc,0x0,0xe,0x39,0xe7,0xd3,0xfa,0xb0,0xee,0xea,0x8f,0x7,0x7b,0xf5,0x9d,0xb7,0xb0,0x97,0x55,0x25,0x5f,0x17,0xe9,0x2e,0xf9,0xb8,0xca,0x3f,0x9b,0x1b,0x1a,0xe3,0x40,0x47,0xa0,0xda,0xda,0x61,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char icon_add_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0x36, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0x63, 0x60, 0xa0, 0x25, 0x78, 0xf0, 0xe0, 0xc1, 0xff, 0x7, 0xf, 0x1e, 0xfc, 0xc7, 0xa7, 0x86, 0x89, 0x52, 0x4b, 0x46, 0xd, 0x60, 0x60, 0x60, 0x64, 0x60, 0x80, 0x84, 0x36, 0x39, 0x9a, 0x15, 0x14, 0x14, 0x18, 0x29, 0x76, 0x1, 0x5e, 0x30, 0x9a, 0xe, 0xe8, 0x64, 0x0, 0xc5, 0x0, 0x0, 0xc7, 0x6e, 0x12, 0x94, 0xf9, 0x26, 0x2e, 0xdb, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char icon_color_pick_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x1,0x55,0x49,0x44,0x41,0x54,0x38,0x8d,0xb5,0x92,0xb1,0x4a,0x3,0x41,0x14,0x45,0xef,0xdb,0x6c,0xac,0xf2,0x1,0xda,0xcd,0x40,0x4,0x25,0x11,0x4,0x8b,0x80,0x8d,0x20,0x88,0x5d,0x20,0x88,0x90,0x22,0x9d,0x9d,0xa0,0x85,0x58,0xeb,0x7,0x88,0xe0,0x7,0x58,0x8b,0x36,0x5a,0x88,0xa0,0xa5,0x85,0xa5,0x60,0x61,0xb0,0x70,0xb2,0xef,0x8d,0x44,0x41,0x21,0x1f,0x20,0x6c,0xf2,0x2c,0xcc,0xc2,0x12,0x92,0x8d,0x45,0xbc,0xe5,0xdc,0xb9,0x67,0xee,0xbc,0x19,0xe0,0xbf,0xe5,0xbd,0x2f,0x35,0x9b,0xcd,0x29,0x0,0x10,0x91,0x9a,0x88,0x7c,0x88,0xc8,0xa7,0x88,0xd4,0x0,0x80,0xb2,0xc2,0xcc,0x5c,0x21,0xa2,0x5b,0x22,0xba,0xef,0x76,0xbb,0x97,0x44,0x74,0x4a,0x44,0x61,0xdf,0xfe,0x32,0xc6,0x4c,0x87,0x59,0x0,0x0,0xdf,0x0,0x62,0x55,0xad,0x6,0x41,0x50,0x1d,0xf0,0x62,0x0,0x8,0xb2,0xd2,0xd6,0xda,0x27,0x0,0x27,0x83,0xeb,0xaa,0x1a,0x3,0xd8,0x19,0xb,0x60,0xe6,0x3a,0x80,0x6d,0x0,0xd,0x0,0x9d,0x14,0x60,0xcb,0x18,0x73,0x95,0x9,0x60,0xe6,0x3a,0x11,0x1d,0xc7,0x71,0xbc,0x6e,0x8c,0x39,0x53,0xd5,0xdd,0xc4,0xcb,0xe5,0x72,0x1b,0xc9,0x60,0x87,0x2,0xd2,0xe1,0x62,0xb1,0xf8,0xec,0xbd,0x2f,0x11,0xd1,0x51,0xaf,0xd7,0x3b,0x0,0xd0,0x51,0xd5,0x95,0x42,0xa1,0x30,0x3b,0xf2,0x64,0x11,0x79,0x77,0xce,0x95,0x81,0xdf,0x67,0x14,0x91,0x76,0xff,0x3a,0x60,0xe6,0x45,0x66,0xae,0xc,0xd,0x47,0x51,0xb4,0x29,0x22,0xed,0x56,0xab,0xb5,0xd0,0xdf,0x3c,0xe7,0xbd,0x7f,0x8b,0xa2,0xa8,0x31,0x7a,0x52,0x93,0x8,0x8b,0xc8,0x72,0xba,0xb6,0x73,0xae,0x9c,0xae,0x9d,0xa5,0x0,0x0,0x88,0x68,0xd,0xc0,0x8b,0xaa,0xbe,0x3a,0xe7,0xca,0x61,0x18,0xde,0xa9,0xea,0xbe,0xb5,0xf6,0x7c,0x1c,0x20,0xf9,0x89,0x4b,0x0,0x56,0xf3,0xf9,0xfc,0xd,0x80,0x79,0x55,0xdd,0xb3,0xd6,0x5e,0x8c,0xad,0x9e,0x0,0x54,0x75,0x86,0x88,0xae,0x1,0x3c,0x2,0x38,0x34,0xc6,0x3c,0xfc,0x25,0x3c,0x11,0xfd,0x0,0x28,0x54,0xbb,0xfe,0xad,0x99,0xe5,0xb8,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char icon_close_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0x9b, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xcd, 0x92, 0x31, 0xe, 0xc2, 0x30, 0x10, 0x4, 0x17, 0xaa, 0x3d, 0x67, 0xdb, 0x58, 0xd0, 0xd3, 0xf0, 0xa3, 0x7c, 0x36, 0x3c, 0x82, 0x48, 0x44, 0x22, 0x6f, 0xb1, 0x4d, 0x85, 0x14, 0x81, 0xf, 0x2c, 0x28, 0xe0, 0xda, 0xd5, 0x8c, 0x4e, 0x77, 0xb, 0xfc, 0xd5, 0x98, 0xd9, 0x20, 0x29, 0x7a, 0xb9, 0xa4, 0x68, 0x66, 0x83, 0xb, 0x93, 0xcc, 0x24, 0xa7, 0x9a, 0x44, 0x52, 0x24, 0x39, 0x91, 0xcc, 0x55, 0x89, 0xa4, 0xde, 0xcc, 0xce, 0x24, 0xb, 0xc9, 0x39, 0x84, 0xb0, 0xf7, 0xb2, 0xae, 0xeb, 0x76, 0xde, 0x8a, 0x4f, 0x92, 0x66, 0xd8, 0x91, 0x5c, 0x49, 0x5e, 0x9a, 0xe1, 0xb5, 0x64, 0x5, 0x16, 0x92, 0x8b, 0x7, 0x6f, 0x9b, 0x8c, 0x0, 0x4a, 0x29, 0x9b, 0x26, 0x81, 0xa4, 0x3e, 0xa5, 0x34, 0x2, 0x38, 0x2, 0x58, 0x0, 0xcc, 0x0, 0xe, 0x39, 0xe7, 0xd3, 0xfa, 0xb0, 0xee, 0xea, 0x8f, 0x7, 0x7b, 0xf5, 0x9d, 0xb7, 0xb0, 0x97, 0x55, 0x25, 0x5f, 0x17, 0xe9, 0x2e, 0xf9, 0xb8, 0xca, 0x3f, 0x9b, 0x1b, 0x1a, 0xe3, 0x40, 0x47, 0xa0, 0xda, 0xda, 0x61, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char icon_folder_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x5f,0x49,0x44,0x41,0x54,0x38,0x8d,0xed,0x8f,0xc1,0xd,0x80,0x30,0x8,0x45,0x9f,0x9d,0x84,0x39,0x4c,0x3b,0xbd,0x75,0x8f,0x32,0x9,0x5e,0xec,0xa5,0x9,0xa4,0xc6,0x26,0x5e,0x7c,0x17,0xe,0xc0,0xe3,0x3,0x5f,0xb3,0x1,0xb4,0xd6,0x4e,0x60,0x77,0x66,0xaa,0x88,0x14,0x4f,0x90,0xee,0xea,0x2d,0x3,0xe4,0x28,0x41,0x8a,0x9a,0x1d,0x55,0x75,0x25,0xfd,0x5,0x9b,0x11,0xd,0x54,0x11,0x29,0x53,0x9,0x1c,0x32,0x4c,0xbe,0x10,0xf1,0xb,0x16,0xa,0xea,0xd3,0x45,0x33,0x3b,0xde,0x1e,0x5f,0xc3,0x5,0x1f,0xc5,0x12,0x2c,0xc5,0x88,0xe1,0xb4,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char icon_color_pick_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x1, 0x55, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xb5, 0x92, 0xb1, 0x4a, 0x3, 0x41, 0x14, 0x45, 0xef, 0xdb, 0x6c, 0xac, 0xf2, 0x1, 0xda, 0xcd, 0x40, 0x4, 0x25, 0x11, 0x4, 0x8b, 0x80, 0x8d, 0x20, 0x88, 0x5d, 0x20, 0x88, 0x90, 0x22, 0x9d, 0x9d, 0xa0, 0x85, 0x58, 0xeb, 0x7, 0x88, 0xe0, 0x7, 0x58, 0x8b, 0x36, 0x5a, 0x88, 0xa0, 0xa5, 0x85, 0xa5, 0x60, 0x61, 0xb0, 0x70, 0xb2, 0xef, 0x8d, 0x44, 0x41, 0x21, 0x1f, 0x20, 0x6c, 0xf2, 0x2c, 0xcc, 0xc2, 0x12, 0x92, 0x8d, 0x45, 0xbc, 0xe5, 0xdc, 0xb9, 0x67, 0xee, 0xbc, 0x19, 0xe0, 0xbf, 0xe5, 0xbd, 0x2f, 0x35, 0x9b, 0xcd, 0x29, 0x0, 0x10, 0x91, 0x9a, 0x88, 0x7c, 0x88, 0xc8, 0xa7, 0x88, 0xd4, 0x0, 0x80, 0xb2, 0xc2, 0xcc, 0x5c, 0x21, 0xa2, 0x5b, 0x22, 0xba, 0xef, 0x76, 0xbb, 0x97, 0x44, 0x74, 0x4a, 0x44, 0x61, 0xdf, 0xfe, 0x32, 0xc6, 0x4c, 0x87, 0x59, 0x0, 0x0, 0xdf, 0x0, 0x62, 0x55, 0xad, 0x6, 0x41, 0x50, 0x1d, 0xf0, 0x62, 0x0, 0x8, 0xb2, 0xd2, 0xd6, 0xda, 0x27, 0x0, 0x27, 0x83, 0xeb, 0xaa, 0x1a, 0x3, 0xd8, 0x19, 0xb, 0x60, 0xe6, 0x3a, 0x80, 0x6d, 0x0, 0xd, 0x0, 0x9d, 0x14, 0x60, 0xcb, 0x18, 0x73, 0x95, 0x9, 0x60, 0xe6, 0x3a, 0x11, 0x1d, 0xc7, 0x71, 0xbc, 0x6e, 0x8c, 0x39, 0x53, 0xd5, 0xdd, 0xc4, 0xcb, 0xe5, 0x72, 0x1b, 0xc9, 0x60, 0x87, 0x2, 0xd2, 0xe1, 0x62, 0xb1, 0xf8, 0xec, 0xbd, 0x2f, 0x11, 0xd1, 0x51, 0xaf, 0xd7, 0x3b, 0x0, 0xd0, 0x51, 0xd5, 0x95, 0x42, 0xa1, 0x30, 0x3b, 0xf2, 0x64, 0x11, 0x79, 0x77, 0xce, 0x95, 0x81, 0xdf, 0x67, 0x14, 0x91, 0x76, 0xff, 0x3a, 0x60, 0xe6, 0x45, 0x66, 0xae, 0xc, 0xd, 0x47, 0x51, 0xb4, 0x29, 0x22, 0xed, 0x56, 0xab, 0xb5, 0xd0, 0xdf, 0x3c, 0xe7, 0xbd, 0x7f, 0x8b, 0xa2, 0xa8, 0x31, 0x7a, 0x52, 0x93, 0x8, 0x8b, 0xc8, 0x72, 0xba, 0xb6, 0x73, 0xae, 0x9c, 0xae, 0x9d, 0xa5, 0x0, 0x0, 0x88, 0x68, 0xd, 0xc0, 0x8b, 0xaa, 0xbe, 0x3a, 0xe7, 0xca, 0x61, 0x18, 0xde, 0xa9, 0xea, 0xbe, 0xb5, 0xf6, 0x7c, 0x1c, 0x20, 0xf9, 0x89, 0x4b, 0x0, 0x56, 0xf3, 0xf9, 0xfc, 0xd, 0x80, 0x79, 0x55, 0xdd, 0xb3, 0xd6, 0x5e, 0x8c, 0xad, 0x9e, 0x0, 0x54, 0x75, 0x86, 0x88, 0xae, 0x1, 0x3c, 0x2, 0x38, 0x34, 0xc6, 0x3c, 0xfc, 0x25, 0x3c, 0x11, 0xfd, 0x0, 0x28, 0x54, 0xbb, 0xfe, 0xad, 0x99, 0xe5, 0xb8, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char icon_play_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0xa2,0x49,0x44,0x41,0x54,0x38,0x8d,0x63,0x60,0x18,0xf2,0x80,0x11,0x99,0xf3,0xe0,0xc1,0x83,0xc3,0xc,0xc,0xc,0xc2,0xc,0xc,0xc,0xa5,0xa,0xa,0xa,0x5b,0xc9,0x31,0xe0,0x3f,0x5c,0x82,0x91,0x71,0x27,0x3,0x3,0x43,0x91,0xbc,0xbc,0xfc,0x35,0x7c,0x6,0x30,0xe1,0x92,0xf8,0xff,0xff,0xbf,0xfb,0xff,0xff,0xff,0x2f,0x3e,0x78,0xf0,0x60,0xca,0x93,0x27,0x4f,0x84,0x49,0x76,0x1,0x1a,0xf8,0xc0,0xc8,0xc8,0xd8,0xf1,0xeb,0xd7,0xaf,0x9,0xaa,0xaa,0xaa,0x3f,0x89,0x72,0x1,0x1a,0x10,0xf8,0xff,0xff,0x7f,0x7,0x2b,0x2b,0xeb,0x1e,0x74,0x9,0x62,0xd,0xc0,0x9,0x88,0x35,0xe0,0x3d,0x23,0x23,0x63,0xc5,0xef,0xdf,0xbf,0x5d,0xd0,0x25,0x58,0x8,0x68,0xfc,0xc3,0xc0,0xc0,0x30,0x93,0x85,0x85,0xa5,0x5e,0x46,0x46,0xe6,0x2d,0x36,0x5,0x38,0xd,0x20,0x36,0x1a,0xd1,0xd,0x38,0xc2,0x0,0x4d,0x48,0xf2,0xf2,0xf2,0x44,0x25,0xa4,0x61,0x0,0x0,0x1e,0x57,0x33,0x3c,0xcc,0xe7,0x34,0x69,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char icon_folder_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0x5f, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xed, 0x8f, 0xc1, 0xd, 0x80, 0x30, 0x8, 0x45, 0x9f, 0x9d, 0x84, 0x39, 0x4c, 0x3b, 0xbd, 0x75, 0x8f, 0x32, 0x9, 0x5e, 0xec, 0xa5, 0x9, 0xa4, 0xc6, 0x26, 0x5e, 0x7c, 0x17, 0xe, 0xc0, 0xe3, 0x3, 0x5f, 0xb3, 0x1, 0xb4, 0xd6, 0x4e, 0x60, 0x77, 0x66, 0xaa, 0x88, 0x14, 0x4f, 0x90, 0xee, 0xea, 0x2d, 0x3, 0xe4, 0x28, 0x41, 0x8a, 0x9a, 0x1d, 0x55, 0x75, 0x25, 0xfd, 0x5, 0x9b, 0x11, 0xd, 0x54, 0x11, 0x29, 0x53, 0x9, 0x1c, 0x32, 0x4c, 0xbe, 0x10, 0xf1, 0xb, 0x16, 0xa, 0xea, 0xd3, 0x45, 0x33, 0x3b, 0xde, 0x1e, 0x5f, 0xc3, 0x5, 0x1f, 0xc5, 0x12, 0x2c, 0xc5, 0x88, 0xe1, 0xb4, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char icon_reload_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x1,0x59,0x49,0x44,0x41,0x54,0x38,0x8d,0xcd,0x92,0x31,0x4b,0x3,0x31,0x18,0x86,0x9f,0x5c,0xe,0xec,0x20,0x76,0x70,0x39,0xd0,0xe3,0xba,0x74,0x51,0x41,0xdd,0xfc,0x7,0xba,0xb8,0x8,0x52,0xec,0x2e,0x4e,0x3a,0x88,0x3f,0xa3,0xa3,0x53,0x7,0x47,0x67,0x41,0x17,0xdd,0x9c,0x5c,0x3b,0xd8,0x82,0x64,0x68,0xca,0xd5,0x55,0x11,0x3c,0x1a,0x87,0x24,0x2e,0xd7,0x72,0x9e,0x9e,0xab,0xbe,0xd3,0xc7,0x1b,0x9e,0x37,0xf9,0xbe,0x7c,0xf0,0xd7,0x12,0x3f,0x99,0x4a,0xa9,0xb9,0x30,0xc,0x8f,0x84,0x10,0x7,0xc0,0x5a,0x6e,0x3f,0x3a,0xe7,0x2e,0xad,0xb5,0xdd,0x66,0xb3,0xf9,0x51,0x19,0x90,0xa6,0xe9,0x92,0xb5,0xf6,0x6,0x58,0xaf,0xb8,0xb4,0x27,0xa5,0xdc,0x8d,0xe3,0xf8,0x19,0x20,0x28,0xdf,0x5c,0x80,0x53,0x60,0xdf,0x18,0x53,0x37,0xc6,0xd4,0xbd,0xf7,0x7b,0xc0,0x13,0xb0,0x61,0xad,0xbd,0x56,0x4a,0xcd,0x1,0x84,0xc5,0x80,0x30,0xc,0x8f,0xa6,0xb0,0x94,0x72,0x33,0x8e,0xe3,0x97,0xc2,0xf1,0xd5,0x68,0x34,0xba,0xf7,0xde,0xf7,0x80,0xd,0x29,0xe5,0x21,0x70,0xfe,0xe5,0x5,0x42,0x88,0x76,0x5e,0x9e,0x96,0x60,0x0,0x92,0x24,0x79,0x75,0xce,0x9d,0x1,0x4,0x41,0xd0,0xfe,0xd6,0x2,0xb0,0x2,0x60,0x8c,0xb9,0xab,0xe8,0x1f,0x6b,0xed,0x6d,0x5e,0xae,0xce,0x2,0xb4,0xd6,0x17,0x5a,0x6b,0x7,0xcc,0x3,0xd4,0x6a,0xb5,0x37,0xad,0xf5,0xc5,0x4f,0x1,0x41,0x10,0x7c,0x19,0x7c,0x90,0x3,0xc7,0xc0,0xa0,0xe0,0xf,0x72,0xef,0x9b,0x84,0x10,0xdb,0x79,0xd9,0x9f,0x5,0x44,0x51,0x94,0x9,0x21,0x5a,0x40,0x6,0x64,0x42,0x88,0x56,0x14,0x45,0x59,0x19,0x1e,0x8f,0xc7,0x8b,0x52,0xca,0xe,0x80,0x73,0xee,0x12,0xa,0xbf,0x90,0x24,0x49,0x7f,0x38,0x1c,0x1e,0x3,0x34,0x1a,0x8d,0x7e,0x11,0x54,0x4a,0x2d,0x48,0x29,0x77,0xac,0xb5,0x1d,0xef,0xfd,0x32,0xd0,0x9b,0x4c,0x26,0x5d,0xa8,0xd8,0xc4,0xb2,0xf2,0xf9,0x4c,0x55,0xbd,0x48,0xbf,0xe8,0x1d,0x78,0x70,0xce,0x9d,0x64,0x59,0xb6,0x35,0x85,0xff,0x87,0x3e,0x1,0x53,0x7,0x87,0x11,0xd3,0x3a,0x9b,0x9e,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char icon_play_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0xa2, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0x63, 0x60, 0x18, 0xf2, 0x80, 0x11, 0x99, 0xf3, 0xe0, 0xc1, 0x83, 0xc3, 0xc, 0xc, 0xc, 0xc2, 0xc, 0xc, 0xc, 0xa5, 0xa, 0xa, 0xa, 0x5b, 0xc9, 0x31, 0xe0, 0x3f, 0x5c, 0x82, 0x91, 0x71, 0x27, 0x3, 0x3, 0x43, 0x91, 0xbc, 0xbc, 0xfc, 0x35, 0x7c, 0x6, 0x30, 0xe1, 0x92, 0xf8, 0xff, 0xff, 0xbf, 0xfb, 0xff, 0xff, 0xff, 0x2f, 0x3e, 0x78, 0xf0, 0x60, 0xca, 0x93, 0x27, 0x4f, 0x84, 0x49, 0x76, 0x1, 0x1a, 0xf8, 0xc0, 0xc8, 0xc8, 0xd8, 0xf1, 0xeb, 0xd7, 0xaf, 0x9, 0xaa, 0xaa, 0xaa, 0x3f, 0x89, 0x72, 0x1, 0x1a, 0x10, 0xf8, 0xff, 0xff, 0x7f, 0x7, 0x2b, 0x2b, 0xeb, 0x1e, 0x74, 0x9, 0x62, 0xd, 0xc0, 0x9, 0x88, 0x35, 0xe0, 0x3d, 0x23, 0x23, 0x63, 0xc5, 0xef, 0xdf, 0xbf, 0x5d, 0xd0, 0x25, 0x58, 0x8, 0x68, 0xfc, 0xc3, 0xc0, 0xc0, 0x30, 0x93, 0x85, 0x85, 0xa5, 0x5e, 0x46, 0x46, 0xe6, 0x2d, 0x36, 0x5, 0x38, 0xd, 0x20, 0x36, 0x1a, 0xd1, 0xd, 0x38, 0xc2, 0x0, 0x4d, 0x48, 0xf2, 0xf2, 0xf2, 0x44, 0x25, 0xa4, 0x61, 0x0, 0x0, 0x1e, 0x57, 0x33, 0x3c, 0xcc, 0xe7, 0x34, 0x69, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char icon_snap_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0xc2,0x49,0x44,0x41,0x54,0x38,0x8d,0xad,0x90,0xbd,0xa,0xc2,0x30,0x14,0x85,0xbf,0x5b,0x5c,0x23,0xe8,0x6c,0x9f,0xc1,0xb7,0xd0,0x47,0xd1,0x47,0x70,0x48,0xa1,0x43,0x57,0xe9,0xd3,0x88,0x93,0xef,0xe0,0xea,0x5c,0x9d,0x1d,0xb2,0x96,0xc6,0xa1,0x9,0xd4,0xd8,0xd8,0x4a,0xfd,0x20,0x10,0xee,0xcf,0xe1,0xdc,0x3,0x1d,0x8c,0x31,0xd6,0x18,0x63,0x9,0x88,0xd5,0x1,0x92,0xbe,0xe2,0x2f,0x4c,0x16,0x90,0x98,0xb5,0x21,0x94,0x52,0xf2,0x17,0x7,0x6f,0x7c,0xb,0x2b,0xc6,0x64,0x7,0xb3,0xa1,0x1,0x5b,0x14,0x29,0x50,0x2,0x1b,0x0,0x44,0x2e,0x34,0xcd,0x41,0xb2,0xec,0x6,0x20,0xdd,0x61,0x6f,0xdf,0x7,0xe4,0x96,0xaf,0xc0,0x32,0xd0,0x7d,0x2,0x6b,0xd1,0xba,0x4a,0xfc,0xdd,0x91,0xdb,0x4b,0xb7,0x7c,0x2,0x56,0xd4,0x75,0xa,0x9c,0x81,0x5,0x70,0x84,0xe1,0xc,0x5a,0xdb,0x75,0xbd,0x17,0xad,0x1f,0x92,0xe7,0x77,0x60,0xe7,0x7a,0x5b,0x80,0x44,0x29,0x25,0xfe,0xf5,0x8,0x28,0x0,0xb7,0xd8,0x46,0xa0,0x75,0xe5,0xbe,0xf3,0x31,0xe,0x7e,0x23,0xcc,0xc2,0x3a,0xc2,0xb9,0x58,0xfd,0x83,0xc9,0x2,0x63,0x78,0x1,0x4a,0x50,0x70,0x86,0xcc,0x86,0x2,0x4,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char icon_reload_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x1, 0x59, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xcd, 0x92, 0x31, 0x4b, 0x3, 0x31, 0x18, 0x86, 0x9f, 0x5c, 0xe, 0xec, 0x20, 0x76, 0x70, 0x39, 0xd0, 0xe3, 0xba, 0x74, 0x51, 0x41, 0xdd, 0xfc, 0x7, 0xba, 0xb8, 0x8, 0x52, 0xec, 0x2e, 0x4e, 0x3a, 0x88, 0x3f, 0xa3, 0xa3, 0x53, 0x7, 0x47, 0x67, 0x41, 0x17, 0xdd, 0x9c, 0x5c, 0x3b, 0xd8, 0x82, 0x64, 0x68, 0xca, 0xd5, 0x55, 0x11, 0x3c, 0x1a, 0x87, 0x24, 0x2e, 0xd7, 0x72, 0x9e, 0x9e, 0xab, 0xbe, 0xd3, 0xc7, 0x1b, 0x9e, 0x37, 0xf9, 0xbe, 0x7c, 0xf0, 0xd7, 0x12, 0x3f, 0x99, 0x4a, 0xa9, 0xb9, 0x30, 0xc, 0x8f, 0x84, 0x10, 0x7, 0xc0, 0x5a, 0x6e, 0x3f, 0x3a, 0xe7, 0x2e, 0xad, 0xb5, 0xdd, 0x66, 0xb3, 0xf9, 0x51, 0x19, 0x90, 0xa6, 0xe9, 0x92, 0xb5, 0xf6, 0x6, 0x58, 0xaf, 0xb8, 0xb4, 0x27, 0xa5, 0xdc, 0x8d, 0xe3, 0xf8, 0x19, 0x20, 0x28, 0xdf, 0x5c, 0x80, 0x53, 0x60, 0xdf, 0x18, 0x53, 0x37, 0xc6, 0xd4, 0xbd, 0xf7, 0x7b, 0xc0, 0x13, 0xb0, 0x61, 0xad, 0xbd, 0x56, 0x4a, 0xcd, 0x1, 0x84, 0xc5, 0x80, 0x30, 0xc, 0x8f, 0xa6, 0xb0, 0x94, 0x72, 0x33, 0x8e, 0xe3, 0x97, 0xc2, 0xf1, 0xd5, 0x68, 0x34, 0xba, 0xf7, 0xde, 0xf7, 0x80, 0xd, 0x29, 0xe5, 0x21, 0x70, 0xfe, 0xe5, 0x5, 0x42, 0x88, 0x76, 0x5e, 0x9e, 0x96, 0x60, 0x0, 0x92, 0x24, 0x79, 0x75, 0xce, 0x9d, 0x1, 0x4, 0x41, 0xd0, 0xfe, 0xd6, 0x2, 0xb0, 0x2, 0x60, 0x8c, 0xb9, 0xab, 0xe8, 0x1f, 0x6b, 0xed, 0x6d, 0x5e, 0xae, 0xce, 0x2, 0xb4, 0xd6, 0x17, 0x5a, 0x6b, 0x7, 0xcc, 0x3, 0xd4, 0x6a, 0xb5, 0x37, 0xad, 0xf5, 0xc5, 0x4f, 0x1, 0x41, 0x10, 0x7c, 0x19, 0x7c, 0x90, 0x3, 0xc7, 0xc0, 0xa0, 0xe0, 0xf, 0x72, 0xef, 0x9b, 0x84, 0x10, 0xdb, 0x79, 0xd9, 0x9f, 0x5, 0x44, 0x51, 0x94, 0x9, 0x21, 0x5a, 0x40, 0x6, 0x64, 0x42, 0x88, 0x56, 0x14, 0x45, 0x59, 0x19, 0x1e, 0x8f, 0xc7, 0x8b, 0x52, 0xca, 0xe, 0x80, 0x73, 0xee, 0x12, 0xa, 0xbf, 0x90, 0x24, 0x49, 0x7f, 0x38, 0x1c, 0x1e, 0x3, 0x34, 0x1a, 0x8d, 0x7e, 0x11, 0x54, 0x4a, 0x2d, 0x48, 0x29, 0x77, 0xac, 0xb5, 0x1d, 0xef, 0xfd, 0x32, 0xd0, 0x9b, 0x4c, 0x26, 0x5d, 0xa8, 0xd8, 0xc4, 0xb2, 0xf2, 0xf9, 0x4c, 0x55, 0xbd, 0x48, 0xbf, 0xe8, 0x1d, 0x78, 0x70, 0xce, 0x9d, 0x64, 0x59, 0xb6, 0x35, 0x85, 0xff, 0x87, 0x3e, 0x1, 0x53, 0x7, 0x87, 0x11, 0xd3, 0x3a, 0x9b, 0x9e, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char icon_stop_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x4,0x0,0x0,0x0,0xb5,0xfa,0x37,0xea,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x4,0x4e,0x1d,0x2,0xaf,0x0,0x0,0x0,0x2b,0x49,0x44,0x41,0x54,0x28,0xcf,0x63,0x60,0x20,0xc,0x3e,0x30,0xe3,0x93,0x61,0x64,0x60,0x60,0x60,0x78,0xf8,0x1f,0xbb,0x2,0x79,0x46,0x6,0x6,0x26,0x42,0xe6,0x8f,0x2a,0xa0,0x96,0x2,0x6,0x42,0x91,0x45,0x10,0x0,0x0,0x95,0x31,0x5,0xe4,0xe,0x1,0x8e,0x3,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char icon_snap_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0xc2, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xad, 0x90, 0xbd, 0xa, 0xc2, 0x30, 0x14, 0x85, 0xbf, 0x5b, 0x5c, 0x23, 0xe8, 0x6c, 0x9f, 0xc1, 0xb7, 0xd0, 0x47, 0xd1, 0x47, 0x70, 0x48, 0xa1, 0x43, 0x57, 0xe9, 0xd3, 0x88, 0x93, 0xef, 0xe0, 0xea, 0x5c, 0x9d, 0x1d, 0xb2, 0x96, 0xc6, 0xa1, 0x9, 0xd4, 0xd8, 0xd8, 0x4a, 0xfd, 0x20, 0x10, 0xee, 0xcf, 0xe1, 0xdc, 0x3, 0x1d, 0x8c, 0x31, 0xd6, 0x18, 0x63, 0x9, 0x88, 0xd5, 0x1, 0x92, 0xbe, 0xe2, 0x2f, 0x4c, 0x16, 0x90, 0x98, 0xb5, 0x21, 0x94, 0x52, 0xf2, 0x17, 0x7, 0x6f, 0x7c, 0xb, 0x2b, 0xc6, 0x64, 0x7, 0xb3, 0xa1, 0x1, 0x5b, 0x14, 0x29, 0x50, 0x2, 0x1b, 0x0, 0x44, 0x2e, 0x34, 0xcd, 0x41, 0xb2, 0xec, 0x6, 0x20, 0xdd, 0x61, 0x6f, 0xdf, 0x7, 0xe4, 0x96, 0xaf, 0xc0, 0x32, 0xd0, 0x7d, 0x2, 0x6b, 0xd1, 0xba, 0x4a, 0xfc, 0xdd, 0x91, 0xdb, 0x4b, 0xb7, 0x7c, 0x2, 0x56, 0xd4, 0x75, 0xa, 0x9c, 0x81, 0x5, 0x70, 0x84, 0xe1, 0xc, 0x5a, 0xdb, 0x75, 0xbd, 0x17, 0xad, 0x1f, 0x92, 0xe7, 0x77, 0x60, 0xe7, 0x7a, 0x5b, 0x80, 0x44, 0x29, 0x25, 0xfe, 0xf5, 0x8, 0x28, 0x0, 0xb7, 0xd8, 0x46, 0xa0, 0x75, 0xe5, 0xbe, 0xf3, 0x31, 0xe, 0x7e, 0x23, 0xcc, 0xc2, 0x3a, 0xc2, 0xb9, 0x58, 0xfd, 0x83, 0xc9, 0x2, 0x63, 0x78, 0x1, 0x4a, 0x50, 0x70, 0x86, 0xcc, 0x86, 0x2, 0x4, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char icon_zoom_less_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x25,0x49,0x44,0x41,0x54,0x38,0x8d,0x63,0x60,0x18,0x5,0xc3,0x0,0x30,0x32,0x30,0x30,0x30,0x3c,0x78,0xf0,0xe0,0x3f,0x39,0x9a,0x15,0x14,0x14,0x18,0x99,0xa8,0xeb,0x9e,0x51,0x30,0x44,0x1,0x0,0xff,0xa9,0x4,0x4,0x4a,0xae,0x20,0xfa,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char icon_stop_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x4, 0x4e, 0x1d, 0x2, 0xaf, 0x0, 0x0, 0x0, 0x2b, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x63, 0x60, 0x20, 0xc, 0x3e, 0x30, 0xe3, 0x93, 0x61, 0x64, 0x60, 0x60, 0x60, 0x78, 0xf8, 0x1f, 0xbb, 0x2, 0x79, 0x46, 0x6, 0x6, 0x26, 0x42, 0xe6, 0x8f, 0x2a, 0xa0, 0x96, 0x2, 0x6, 0x42, 0x91, 0x45, 0x10, 0x0, 0x0, 0x95, 0x31, 0x5, 0xe4, 0xe, 0x1, 0x8e, 0x3, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char icon_zoom_more_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x36,0x49,0x44,0x41,0x54,0x38,0x8d,0x63,0x60,0xa0,0x25,0x78,0xf0,0xe0,0xc1,0xff,0x7,0xf,0x1e,0xfc,0xc7,0xa7,0x86,0x89,0x52,0x4b,0x46,0xd,0x60,0x60,0x60,0x64,0x60,0x80,0x84,0x36,0x39,0x9a,0x15,0x14,0x14,0x18,0x29,0x76,0x1,0x5e,0x30,0x9a,0xe,0xe8,0x64,0x0,0xc5,0x0,0x0,0xc7,0x6e,0x12,0x94,0xf9,0x26,0x2e,0xdb,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char icon_zoom_less_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0x25, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0x63, 0x60, 0x18, 0x5, 0xc3, 0x0, 0x30, 0x32, 0x30, 0x30, 0x30, 0x3c, 0x78, 0xf0, 0xe0, 0x3f, 0x39, 0x9a, 0x15, 0x14, 0x14, 0x18, 0x99, 0xa8, 0xeb, 0x9e, 0x51, 0x30, 0x44, 0x1, 0x0, 0xff, 0xa9, 0x4, 0x4, 0x4a, 0xae, 0x20, 0xfa, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char icon_zoom_reset_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x6f,0x49,0x44,0x41,0x54,0x38,0x8d,0xdd,0x91,0xbb,0xd,0x80,0x30,0x10,0x43,0x1f,0x11,0x23,0x20,0xea,0x4c,0xc5,0x62,0x48,0xec,0xc0,0x56,0x97,0x26,0x43,0xa4,0x31,0x15,0x12,0x45,0x72,0x8a,0x14,0xa,0x84,0xab,0xfb,0x58,0x3e,0xeb,0xc,0x83,0x98,0xee,0x22,0xa5,0xb4,0x49,0x3a,0x1,0x62,0x8c,0x53,0x8d,0x5c,0xe3,0x4,0x80,0x9c,0xf3,0x22,0x69,0xf7,0x2e,0xb5,0x38,0x1,0xa0,0x94,0x72,0x0,0xab,0x27,0xd0,0xc3,0xc1,0xcc,0x64,0x66,0x6a,0xf5,0xb5,0x59,0x70,0x15,0x3b,0x30,0x7b,0xcb,0xd6,0x33,0x9f,0x18,0x76,0xf0,0x71,0x81,0x5a,0xa,0xaf,0x3b,0xf8,0x41,0xa,0xc3,0xb8,0x0,0x6c,0x9c,0x3f,0xb8,0x84,0xfc,0x5b,0x85,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char icon_zoom_more_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0x36, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0x63, 0x60, 0xa0, 0x25, 0x78, 0xf0, 0xe0, 0xc1, 0xff, 0x7, 0xf, 0x1e, 0xfc, 0xc7, 0xa7, 0x86, 0x89, 0x52, 0x4b, 0x46, 0xd, 0x60, 0x60, 0x60, 0x64, 0x60, 0x80, 0x84, 0x36, 0x39, 0x9a, 0x15, 0x14, 0x14, 0x18, 0x29, 0x76, 0x1, 0x5e, 0x30, 0x9a, 0xe, 0xe8, 0x64, 0x0, 0xc5, 0x0, 0x0, 0xc7, 0x6e, 0x12, 0x94, 0xf9, 0x26, 0x2e, 0xdb, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char line_edit_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xa,0x0,0x0,0x0,0xa,0x4,0x3,0x0,0x0,0x0,0x7f,0x1c,0xd2,0x8e,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2a,0x50,0x4c,0x54,0x45,0x17,0x16,0x1a,0x1d,0x1c,0x21,0x20,0x1e,0x24,0x21,0x1f,0x25,0x1d,0x1c,0x21,0x20,0x1e,0x24,0x1d,0x1c,0x21,0x1d,0x1c,0x21,0x24,0x22,0x29,0x28,0x26,0x2d,0x28,0x26,0x2e,0x2b,0x2a,0x31,0x2c,0x2a,0x32,0xff,0xff,0xff,0xb9,0x11,0x56,0x3e,0x0,0x0,0x0,0x8,0x74,0x52,0x4e,0x53,0x6f,0xef,0xf7,0xf7,0xf0,0xf9,0xf1,0xee,0xcf,0x21,0xd2,0xdf,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0xd,0xf6,0xb4,0x61,0xf5,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x4,0x4e,0x1d,0x2,0xaf,0x0,0x0,0x0,0x2d,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0x54,0x36,0x36,0x12,0x60,0xf0,0x98,0xb5,0x6a,0x65,0xb,0x43,0xe4,0x9e,0x33,0xa7,0xa7,0x32,0x58,0x9d,0x39,0x73,0x66,0x31,0x16,0x12,0x22,0xb,0x52,0xd9,0xc6,0xc0,0x2,0xd4,0x55,0x0,0x0,0xc,0x14,0x1a,0x90,0x55,0x1a,0xec,0xdb,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char icon_zoom_reset_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0x6f, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xdd, 0x91, 0xbb, 0xd, 0x80, 0x30, 0x10, 0x43, 0x1f, 0x11, 0x23, 0x20, 0xea, 0x4c, 0xc5, 0x62, 0x48, 0xec, 0xc0, 0x56, 0x97, 0x26, 0x43, 0xa4, 0x31, 0x15, 0x12, 0x45, 0x72, 0x8a, 0x14, 0xa, 0x84, 0xab, 0xfb, 0x58, 0x3e, 0xeb, 0xc, 0x83, 0x98, 0xee, 0x22, 0xa5, 0xb4, 0x49, 0x3a, 0x1, 0x62, 0x8c, 0x53, 0x8d, 0x5c, 0xe3, 0x4, 0x80, 0x9c, 0xf3, 0x22, 0x69, 0xf7, 0x2e, 0xb5, 0x38, 0x1, 0xa0, 0x94, 0x72, 0x0, 0xab, 0x27, 0xd0, 0xc3, 0xc1, 0xcc, 0x64, 0x66, 0x6a, 0xf5, 0xb5, 0x59, 0x70, 0x15, 0x3b, 0x30, 0x7b, 0xcb, 0xd6, 0x33, 0x9f, 0x18, 0x76, 0xf0, 0x71, 0x81, 0x5a, 0xa, 0xaf, 0x3b, 0xf8, 0x41, 0xa, 0xc3, 0xb8, 0x0, 0x6c, 0x9c, 0x3f, 0xb8, 0x84, 0xfc, 0x5b, 0x85, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char line_edit_disabled_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xa,0x0,0x0,0x0,0xa,0x8,0x4,0x0,0x0,0x0,0x27,0x3b,0x7,0x36,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x64,0x49,0x44,0x41,0x54,0x8,0xd7,0x95,0xce,0x31,0x12,0x2,0x21,0x10,0x44,0xd1,0x3f,0x40,0xa1,0x44,0xa6,0x46,0xde,0x63,0x4f,0xe5,0x15,0x38,0xb2,0xd6,0x6,0xb0,0xc8,0x30,0x6,0x96,0xac,0x56,0x99,0xf8,0xb3,0x7e,0x51,0xcb,0xf9,0x1a,0xb3,0x3f,0xa,0xaf,0xc,0xad,0x2d,0xcb,0xe5,0x76,0x38,0x5,0x76,0xec,0x6c,0xf7,0xe0,0x53,0xe0,0x13,0xa1,0x27,0x27,0x43,0x26,0x81,0x20,0xc8,0x70,0xfc,0xe8,0xf,0x34,0x67,0xd8,0x9c,0x86,0x61,0x2e,0x68,0xe9,0x91,0xaf,0x4b,0x5a,0x7d,0x2a,0x2c,0x3,0xed,0xef,0x1e,0x6b,0xcb,0x4f,0xa6,0x66,0x2b,0x25,0x6,0x1,0x37,0x40,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char line_edit_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0xa, 0x4, 0x3, 0x0, 0x0, 0x0, 0x7f, 0x1c, 0xd2, 0x8e, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x2a, 0x50, 0x4c, 0x54, 0x45, 0x17, 0x16, 0x1a, 0x1d, 0x1c, 0x21, 0x20, 0x1e, 0x24, 0x21, 0x1f, 0x25, 0x1d, 0x1c, 0x21, 0x20, 0x1e, 0x24, 0x1d, 0x1c, 0x21, 0x1d, 0x1c, 0x21, 0x24, 0x22, 0x29, 0x28, 0x26, 0x2d, 0x28, 0x26, 0x2e, 0x2b, 0x2a, 0x31, 0x2c, 0x2a, 0x32, 0xff, 0xff, 0xff, 0xb9, 0x11, 0x56, 0x3e, 0x0, 0x0, 0x0, 0x8, 0x74, 0x52, 0x4e, 0x53, 0x6f, 0xef, 0xf7, 0xf7, 0xf0, 0xf9, 0xf1, 0xee, 0xcf, 0x21, 0xd2, 0xdf, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0xd, 0xf6, 0xb4, 0x61, 0xf5, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x4, 0x4e, 0x1d, 0x2, 0xaf, 0x0, 0x0, 0x0, 0x2d, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x54, 0x36, 0x36, 0x12, 0x60, 0xf0, 0x98, 0xb5, 0x6a, 0x65, 0xb, 0x43, 0xe4, 0x9e, 0x33, 0xa7, 0xa7, 0x32, 0x58, 0x9d, 0x39, 0x73, 0x66, 0x31, 0x16, 0x12, 0x22, 0xb, 0x52, 0xd9, 0xc6, 0xc0, 0x2, 0xd4, 0x55, 0x0, 0x0, 0xc, 0x14, 0x1a, 0x90, 0x55, 0x1a, 0xec, 0xdb, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char line_edit_focus_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0xab,0x50,0x4c,0x54,0x45,0x1b,0x17,0x18,0x1b,0x17,0x18,0x1b,0x17,0x18,0xc8,0x68,0x12,0xef,0xed,0xe7,0xef,0xed,0xe8,0xf0,0xed,0xe8,0xf0,0xee,0xe8,0xf0,0xed,0xe7,0xed,0xeb,0xe5,0xee,0xeb,0xe5,0xee,0xeb,0xe6,0xec,0xe9,0xe3,0xeb,0xe9,0xe3,0xeb,0xe9,0xe2,0xec,0xe9,0xe2,0xe9,0xe6,0xe0,0xea,0xe7,0xe0,0xea,0xe7,0xe1,0xe8,0xe4,0xdd,0xe8,0xe5,0xde,0xe8,0xe5,0xdd,0xe8,0xe4,0xde,0xe6,0xe2,0xdb,0xe6,0xe3,0xdb,0xe6,0xe3,0xdc,0xe7,0xe2,0xdb,0xe7,0xe3,0xdb,0xe4,0xe0,0xd8,0xe5,0xe0,0xd8,0xe5,0xe1,0xd9,0xe5,0xe0,0xd9,0xe4,0xe1,0xd9,0xe5,0xe1,0xd8,0xe4,0xe0,0xd9,0xe2,0xdf,0xd6,0xe3,0xdf,0xd6,0xe3,0xde,0xd6,0xe2,0xde,0xd6,0xe1,0xdc,0xd4,0xe1,0xdc,0xd3,0xe0,0xdc,0xd3,0xe1,0xdd,0xd3,0xe1,0xdd,0xd4,0xdf,0xda,0xd0,0xdf,0xda,0xd1,0xdf,0xdb,0xd1,0xe0,0xda,0xd1,0xdd,0xd8,0xcf,0xdd,0xd8,0xce,0xde,0xd9,0xce,0xde,0xd8,0xce,0xdd,0xd9,0xce,0xdc,0xd6,0xcc,0xdb,0xd6,0xcc,0xdc,0xd6,0xcb,0xff,0xff,0xff,0x73,0x72,0x65,0x6f,0x0,0x0,0x0,0x2,0x74,0x52,0x4e,0x53,0x36,0x61,0xc5,0x3a,0xd,0x83,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x38,0xa0,0x7,0xa5,0xd6,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x9e,0x49,0x44,0x41,0x54,0x18,0xd3,0x5d,0xcf,0xdb,0x16,0x82,0x20,0x10,0x85,0x61,0xb4,0xb4,0x13,0x1d,0x28,0x14,0xcb,0x4a,0x33,0xf,0x59,0x52,0x98,0x62,0xef,0xff,0x66,0xd1,0xf6,0xca,0xfe,0x19,0xd6,0x62,0x7d,0x77,0x43,0x88,0x3d,0x88,0x10,0x7b,0x34,0xc8,0x36,0x30,0x76,0x1c,0x77,0xe2,0x3a,0xee,0xd4,0x7c,0x0,0xb3,0x79,0x3f,0xa6,0x5,0x80,0xa2,0x25,0xa5,0xab,0x35,0x5,0x6c,0x18,0x63,0x5b,0xd6,0x7,0xd8,0x71,0xcf,0xe3,0x9c,0xfb,0x9c,0x7b,0x3e,0x40,0x4,0xfb,0xe0,0x10,0x84,0xa1,0x8,0x85,0x0,0x1c,0x4f,0xe7,0x28,0xbe,0x44,0x71,0x9c,0x24,0x67,0xc0,0x35,0x4d,0xb3,0x2c,0xcb,0xcd,0x4b,0x73,0x40,0x71,0x33,0x15,0xe5,0xfd,0x51,0x16,0x25,0xa0,0x92,0xf2,0xf9,0x92,0xbf,0x2a,0x9,0x50,0xaa,0x56,0xef,0x46,0xb5,0x4d,0x5b,0x37,0x0,0xdd,0x7d,0xb4,0x36,0xdb,0x69,0xad,0x1,0x7f,0xc7,0x59,0xc3,0xf3,0xad,0x2f,0x30,0x4f,0x11,0x50,0x3e,0x12,0x48,0xdb,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char line_edit_disabled_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0xa, 0x8, 0x4, 0x0, 0x0, 0x0, 0x27, 0x3b, 0x7, 0x36, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x64, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x95, 0xce, 0x31, 0x12, 0x2, 0x21, 0x10, 0x44, 0xd1, 0x3f, 0x40, 0xa1, 0x44, 0xa6, 0x46, 0xde, 0x63, 0x4f, 0xe5, 0x15, 0x38, 0xb2, 0xd6, 0x6, 0xb0, 0xc8, 0x30, 0x6, 0x96, 0xac, 0x56, 0x99, 0xf8, 0xb3, 0x7e, 0x51, 0xcb, 0xf9, 0x1a, 0xb3, 0x3f, 0xa, 0xaf, 0xc, 0xad, 0x2d, 0xcb, 0xe5, 0x76, 0x38, 0x5, 0x76, 0xec, 0x6c, 0xf7, 0xe0, 0x53, 0xe0, 0x13, 0xa1, 0x27, 0x27, 0x43, 0x26, 0x81, 0x20, 0xc8, 0x70, 0xfc, 0xe8, 0xf, 0x34, 0x67, 0xd8, 0x9c, 0x86, 0x61, 0x2e, 0x68, 0xe9, 0x91, 0xaf, 0x4b, 0x5a, 0x7d, 0x2a, 0x2c, 0x3, 0xed, 0xef, 0x1e, 0x6b, 0xcb, 0x4f, 0xa6, 0x66, 0x2b, 0x25, 0x6, 0x1, 0x37, 0x40, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char logo_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x80,0x0,0x0,0x0,0x80,0x8,0x6,0x0,0x0,0x0,0xc3,0x3e,0x61,0xcb,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0x2e,0x23,0x0,0x0,0x2e,0x23,0x1,0x78,0xa5,0x3f,0x76,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdc,0x9,0x7,0x13,0x2,0x0,0x15,0xb9,0x53,0x97,0x0,0x0,0x21,0x58,0x49,0x44,0x41,0x54,0x78,0xda,0xed,0x7d,0x79,0x9c,0x1c,0x55,0xb5,0xff,0xf7,0x7b,0xab,0x7b,0x66,0x48,0x8,0x61,0xd1,0x90,0xb0,0x88,0x91,0x27,0x24,0x24,0x21,0x3b,0x8,0x4,0x42,0x58,0x54,0xe0,0x91,0x80,0x24,0x1,0x2,0x9,0x42,0x80,0x4,0x11,0x90,0x9f,0xf2,0xd3,0xa7,0xcf,0xe7,0xf3,0x3d,0x1f,0x1f,0x7f,0xea,0xd3,0x48,0x4c,0x8,0x61,0xd,0x49,0x64,0x89,0x82,0x40,0x58,0x4,0x64,0xb,0x44,0x25,0x9b,0xd9,0x51,0x14,0x41,0x3,0xc8,0x16,0x20,0xfb,0x4c,0x77,0xdd,0xef,0xef,0x8f,0xaa,0xea,0xae,0xee,0xa9,0xea,0x9e,0xee,0xae,0x99,0xe9,0xe0,0x9c,0xf9,0xd4,0x74,0xd5,0xad,0x5b,0x77,0x39,0xe7,0xdc,0x7b,0xcf,0x39,0xf7,0xdc,0x7b,0x81,0x2e,0xe8,0x82,0x2e,0xe8,0x82,0x2e,0xe8,0x82,0x2e,0xe8,0x82,0x2e,0xe8,0x82,0x2e,0xf8,0xe7,0x2,0x76,0x76,0x1,0xea,0x1,0xe,0xff,0xc2,0xcc,0xbd,0x60,0x5b,0x6e,0xb6,0xd6,0xf6,0x2,0xb8,0x8d,0xc6,0x6c,0x36,0x34,0x6f,0x81,0x7c,0x43,0x30,0x7f,0x27,0xcd,0xdf,0x8c,0xe3,0x6c,0xda,0x70,0xef,0xf4,0x37,0x3b,0xbb,0xac,0x49,0x43,0xaa,0xb3,0xb,0x50,0xf,0x20,0x9b,0xfd,0x96,0xcd,0xb6,0x4c,0x40,0xd0,0x20,0x2c,0xac,0x4b,0xb3,0x3,0xc0,0x36,0x80,0x5b,0x41,0x6c,0x75,0x5b,0xb8,0xed,0xb0,0x71,0xff,0xbb,0x83,0xc6,0x6c,0x26,0x9d,0x65,0x74,0xd2,0x4f,0x6e,0x5c,0x74,0xc5,0xba,0xce,0x2e,0x7b,0xad,0xf0,0x4f,0xdf,0x3,0xf4,0x9f,0x38,0xb7,0x5b,0x76,0xd7,0x7,0x2f,0xcb,0xda,0x3,0xc8,0x42,0x94,0x48,0x6a,0x15,0x9f,0x24,0x0,0xbe,0x43,0xe3,0xfc,0xc1,0x49,0x37,0x4d,0xdd,0xf8,0x8b,0x2b,0xff,0xde,0xd9,0x75,0xa8,0x5,0x76,0x2b,0x6,0xe8,0x37,0x7e,0xf6,0x18,0xeb,0xb6,0x9c,0x6,0x69,0xf,0x1a,0xf3,0xc1,0x1f,0xef,0xbb,0xe6,0xdb,0xb5,0xa4,0x37,0xf2,0x9a,0xa5,0xdc,0xb2,0x69,0xe5,0x69,0xca,0xec,0xf8,0xa5,0xa4,0x26,0x48,0xf2,0x29,0x8c,0x82,0x7b,0x40,0x3e,0xae,0xfc,0x5f,0x41,0x82,0x4d,0x37,0xf5,0x18,0xb7,0xd7,0xc1,0xc3,0x1f,0xfe,0xfd,0x4f,0x3e,0xa3,0x2a,0x8b,0xd0,0xe9,0x50,0xf7,0xc,0x70,0xf8,0x39,0xb3,0x3e,0x9,0xb9,0xa7,0x48,0xf6,0x70,0xb9,0xd9,0xd1,0x90,0x3b,0xd2,0x2b,0x39,0x9b,0x4d,0xaa,0x69,0xfa,0x1f,0xef,0xbb,0xfa,0x8e,0x5a,0xd2,0x3f,0x6c,0xdc,0x8f,0x9f,0x91,0xcd,0x8c,0x2,0xe9,0xe4,0x43,0x3,0x7a,0xc7,0x80,0x4,0x80,0xbb,0x9c,0x74,0xd3,0x77,0xdd,0xcc,0xce,0x1f,0xbc,0xfc,0xd0,0xd7,0x6d,0x67,0xe3,0xa9,0x5a,0xa8,0x5b,0x19,0xa0,0xdf,0xf8,0xd9,0x47,0x42,0xee,0x51,0x72,0x5b,0x3e,0x6b,0xdd,0xcc,0x69,0x0,0xf6,0xf4,0x8,0xe3,0x75,0xc3,0x92,0x1a,0x6d,0x66,0xd7,0x8f,0xfa,0x8d,0x9f,0xf5,0xe7,0x97,0x7e,0x71,0xe5,0xf3,0x55,0xe5,0x31,0xe1,0xc6,0x83,0xdc,0x5d,0x5b,0x46,0x3,0x7e,0xb3,0xce,0x51,0xbd,0x74,0xbb,0xf0,0x9b,0xbb,0x23,0xd9,0x23,0x59,0xf7,0x4d,0xa8,0x34,0xd4,0x1d,0x3,0xf4,0x3b,0x67,0xf6,0x20,0xc0,0x1d,0x65,0xb3,0xcd,0x67,0xc9,0xcd,0x9c,0xa,0x9f,0x1a,0xfe,0xd8,0x5b,0xd0,0x15,0xb,0xda,0xcf,0x66,0x9a,0x7f,0xd8,0x7f,0xc2,0x9c,0xb1,0x1b,0x17,0x4d,0x7f,0xa7,0x92,0x7c,0xe,0xff,0xc2,0xd,0x69,0x58,0x77,0x1c,0x40,0x17,0x84,0x3,0x54,0x48,0x4a,0xd2,0x91,0x75,0x7,0x38,0x4d,0x7b,0xef,0xd6,0x2c,0x50,0x37,0xc,0xd0,0x7f,0xc2,0x8d,0x7,0x3,0x1a,0x65,0x33,0xcd,0x97,0x58,0x9b,0x3d,0x5,0x0,0x40,0xe6,0x5a,0xa6,0x82,0x47,0xbf,0x13,0x0,0x21,0x82,0x90,0xdc,0xcf,0xc8,0x66,0xbe,0xd6,0x6f,0xfc,0xac,0xef,0xbc,0xf4,0x8b,0x2b,0x77,0xb5,0x35,0x3f,0x93,0x6a,0xb4,0x36,0xb3,0xe3,0x7c,0x1a,0xe3,0x8f,0xe9,0xe1,0x21,0x3f,0x4,0xe1,0xd1,0x40,0x80,0x24,0xd1,0x90,0x10,0x8c,0x64,0xf,0x31,0xa9,0xa6,0x2e,0x6,0x48,0x2,0x64,0xb3,0xdf,0xb0,0xd9,0xe6,0x2f,0x1,0x41,0x6b,0xf7,0x9,0x2f,0x91,0x1e,0x23,0x78,0x40,0x9f,0x8,0x34,0x41,0x90,0x75,0x33,0xbb,0xfe,0xaf,0xd3,0xd0,0x7d,0xd9,0x61,0xe3,0x7e,0x78,0xdf,0x9f,0x1e,0xb8,0x2e,0x72,0x3c,0x1e,0x30,0xe9,0xce,0x94,0xdb,0xb2,0x7d,0x1f,0xd2,0xf4,0x0,0x6c,0x1a,0xb2,0xbd,0x65,0xdd,0xcf,0x0,0x30,0x0,0x41,0x42,0x91,0xbd,0x0,0xb,0xef,0x49,0x52,0x9e,0x7a,0x40,0x48,0x7b,0xee,0x6,0x62,0x54,0x49,0xa8,0x1b,0x6,0xb0,0xd9,0xcc,0x39,0x7e,0x6b,0xb,0xda,0x5c,0xa8,0xeb,0x2f,0x4,0x7a,0x81,0x41,0x3c,0x3,0x10,0x36,0xbb,0xeb,0xc7,0x4e,0x43,0x8f,0xd7,0xfa,0x4f,0xb8,0x71,0x3,0x68,0xf6,0x7,0xb0,0x37,0x81,0x34,0x8,0xca,0xda,0x46,0xb7,0x65,0xeb,0x27,0x20,0x3b,0xd8,0x75,0xdd,0xbe,0x4,0xf6,0x83,0x74,0x30,0x80,0x40,0xf0,0x53,0x25,0x43,0x0,0xfd,0xff,0x22,0xad,0xcd,0xee,0xac,0x59,0x3,0xe8,0x7f,0xee,0x2d,0xdd,0x36,0xde,0x73,0xe9,0x8e,0xce,0xc0,0x7b,0xdd,0x30,0x0,0x8d,0xf3,0xb2,0xac,0x3e,0xe,0xc0,0x20,0x4e,0xc,0xf,0xc8,0x1e,0x3c,0xf9,0x8a,0x3a,0x49,0x40,0xf6,0x60,0xeb,0xb6,0xfc,0x1f,0xd2,0xac,0xb3,0xb6,0xf9,0x24,0x78,0xad,0xbb,0x9b,0x17,0xb5,0x90,0x46,0xca,0x25,0x46,0x85,0x52,0x8e,0xcb,0xa7,0x30,0xdc,0x4a,0xa0,0x21,0xe8,0x7d,0xed,0x36,0x6f,0xad,0x89,0x1,0x8e,0x38,0x77,0x6e,0x5f,0xeb,0xb6,0x9c,0xde,0x7f,0xc2,0x9c,0xe7,0x36,0x2e,0x9a,0xbe,0xb6,0xc3,0xf1,0xde,0xd1,0x19,0xc6,0x41,0xff,0x9,0xb3,0xbf,0x67,0x33,0xcd,0x5f,0x96,0x6c,0xcf,0x70,0xab,0x8f,0xa3,0x43,0x41,0xb8,0x4,0x90,0x16,0x80,0x41,0xd8,0x78,0x43,0x6,0xef,0x8a,0xf4,0x7a,0x9,0xf2,0xfa,0x7d,0xff,0xb1,0x40,0x0,0x60,0x51,0xde,0xc5,0xf9,0x11,0x39,0x23,0x51,0xd6,0x69,0xdc,0xf3,0x18,0xc9,0xbe,0x61,0x9c,0x86,0xad,0x1b,0xee,0x9e,0xba,0xb5,0xad,0xf5,0x3d,0xe2,0xbc,0x5b,0xbb,0xc1,0xba,0x9f,0xc8,0x66,0xb6,0x2f,0x86,0x74,0x28,0x80,0xb7,0x4d,0xba,0xdb,0xb9,0xc6,0x38,0x4b,0x37,0xdc,0x73,0x59,0x4b,0x47,0xe1,0xbd,0x6e,0x18,0xa0,0xdf,0x84,0x39,0xa7,0x2b,0xb3,0x73,0x2e,0xa0,0x3,0x81,0x60,0x9c,0x6f,0x73,0xb7,0x1c,0xc8,0xb,0x20,0xf3,0xad,0x3a,0xf4,0x9c,0x78,0x3d,0x95,0x37,0x13,0x92,0xc6,0xf9,0xb,0x9d,0xf4,0x22,0x63,0x52,0xb7,0x3,0x78,0x3d,0xdb,0xbc,0x6d,0xe7,0x9f,0x1e,0xf8,0x6a,0xac,0x6d,0xa0,0xff,0x84,0x39,0xfb,0x4b,0xee,0x14,0x9b,0x69,0xfe,0x41,0x90,0x9a,0x2f,0x5b,0xc0,0xa4,0x9b,0xfe,0xcd,0x18,0xe7,0x96,0xd,0xf7,0x4e,0x7f,0xb7,0x23,0xf0,0x5e,0x37,0xc,0xd0,0xff,0xdc,0x9b,0x3f,0x65,0x5b,0xb6,0x3f,0x21,0xd9,0x4f,0x41,0x8,0x24,0xed,0xb6,0x95,0x56,0x65,0xde,0x25,0x55,0x53,0x3f,0xad,0x9c,0x26,0xe0,0x3f,0x14,0xf4,0x1e,0x26,0x75,0x3f,0x9d,0x86,0x9f,0xd2,0x49,0xaf,0xec,0xd1,0xfb,0x88,0x6d,0xc5,0x56,0xc2,0xfe,0x13,0x6f,0x3a,0xcc,0x66,0x9b,0xe7,0x40,0xee,0x18,0x0,0x5e,0xaf,0x15,0x24,0x3,0x8,0x24,0x8d,0xd3,0x70,0x13,0x4c,0xea,0xfb,0x1b,0xef,0x9d,0xf6,0x6a,0x7b,0xe3,0xdd,0xb4,0x77,0x6,0x6d,0x85,0x8d,0xf7,0x5c,0xf6,0xa,0x69,0x9a,0x3d,0x51,0x3b,0xc0,0x26,0xfd,0xb,0xa5,0x9,0x58,0xaa,0xa3,0x28,0xf7,0x6d,0x25,0xe0,0xa7,0x95,0x27,0x3e,0x94,0xcf,0xc0,0xd3,0x26,0xad,0x9b,0x3d,0xdb,0x6d,0xd9,0xf1,0x8c,0x6d,0xd9,0xfe,0xdc,0x96,0xd7,0x57,0x9f,0x11,0xfe,0xfc,0x88,0x73,0xe7,0x9e,0xec,0xb6,0xec,0xd8,0x28,0xeb,0x8e,0xf1,0xbe,0xf5,0xf1,0x2f,0x88,0xa0,0xcf,0x48,0xb4,0xd6,0x6d,0x99,0x66,0xb3,0x2d,0xf3,0xfb,0x4f,0x9c,0x7b,0x5c,0x7b,0xe3,0xbd,0x6e,0x7a,0x0,0x0,0xe8,0x77,0xce,0xcf,0x9e,0xb3,0x6e,0xe6,0x78,0x20,0x5a,0xfa,0xaf,0x3f,0x8,0x86,0x81,0x7c,0x61,0xfd,0x91,0x41,0x64,0xa0,0x5a,0x38,0x2b,0x4c,0xba,0xf1,0x3b,0x4,0x7a,0x66,0x5b,0x76,0x2c,0xf4,0xf8,0xbb,0xd5,0xb0,0x54,0xd0,0x4f,0x5,0x6a,0x26,0x8d,0x79,0x8d,0x4e,0xd3,0xbf,0xbd,0xb4,0x68,0xda,0x5d,0xed,0x55,0x3,0xa7,0xf6,0x24,0x92,0x83,0x8f,0xf,0x1c,0x9b,0x2,0x34,0x9c,0x40,0x8f,0x78,0xcb,0x4c,0x3d,0x41,0xd0,0x45,0xf9,0xe0,0xcb,0x2d,0xbe,0xd5,0x92,0x14,0x24,0xa2,0xb7,0x6c,0x76,0x82,0xac,0x7b,0x16,0x29,0x27,0x50,0x21,0x1,0x85,0xba,0xba,0x5c,0x37,0xe2,0xdb,0xbb,0x72,0x36,0xb0,0xbd,0x61,0xdd,0x13,0xf7,0x3f,0xf2,0xec,0x96,0x77,0xd6,0x2f,0xfe,0x5d,0x7b,0xd4,0xa0,0x6e,0x86,0x0,0xaf,0x34,0xce,0x12,0x0,0xef,0x7b,0xf7,0x86,0xf9,0x21,0x60,0x37,0xb9,0x8c,0xf1,0x94,0xc3,0x80,0x71,0x69,0x40,0xd2,0x90,0x6c,0x0,0xd4,0x0,0x18,0x79,0x17,0x8,0x18,0x45,0xa4,0xe1,0x31,0x81,0x31,0xfe,0x7b,0x3,0x40,0xfb,0x65,0x33,0xbb,0xbe,0xde,0x6f,0xc2,0x9c,0xaf,0xb4,0x7,0xca,0xeb,0xa6,0x7,0xe8,0x3f,0x71,0xee,0x4,0x4f,0x38,0x52,0x3f,0xf8,0xb6,0x9e,0xd0,0xe8,0xba,0xfb,0x5c,0x44,0xae,0xfd,0xe7,0xee,0x1,0xbf,0x67,0x80,0x7f,0x11,0xa1,0x77,0x45,0xdf,0x93,0xa1,0x74,0x82,0x1e,0x61,0x4f,0xca,0xe,0xea,0x35,0xe8,0x2c,0xe7,0x9d,0xf5,0x8b,0x97,0x26,0x89,0xf7,0xba,0x30,0x4,0xf5,0x9f,0x78,0xd3,0x2c,0x9b,0xdd,0x75,0x36,0xa0,0x3e,0xde,0x18,0x69,0x24,0x28,0x6c,0x0,0xde,0x1d,0x81,0x31,0xf7,0x6d,0x6,0x6f,0x14,0xf4,0x70,0x21,0xb0,0x1b,0xc8,0xee,0x49,0x17,0xb2,0xd3,0x19,0xe0,0xf0,0x73,0x66,0x3d,0xad,0x6c,0xcb,0x48,0x0,0xdd,0xbd,0x39,0x1e,0xdf,0x74,0x53,0xef,0xc3,0x7f,0x87,0x40,0xce,0xe4,0xd,0x1a,0x67,0xb5,0x71,0xd2,0xd7,0x27,0x9d,0x43,0x62,0xc,0x70,0xc4,0xb9,0x73,0x7f,0x24,0x61,0x1b,0x8d,0xf3,0xd3,0xd,0x77,0x4f,0x7d,0xbf,0x5c,0xfc,0x81,0x93,0xee,0xd8,0x23,0xdb,0xb2,0xe3,0x31,0xd9,0xec,0x9,0x5e,0x3f,0x97,0x13,0x80,0xbb,0x88,0xef,0x83,0x6f,0xc0,0x24,0xe9,0xbc,0x63,0x9c,0xf4,0xe2,0x75,0x3f,0xbf,0x38,0x71,0xb,0x61,0x22,0x98,0x3e,0xe2,0xbc,0x5b,0x47,0xd8,0xcc,0xce,0x7,0x25,0x75,0xa3,0x71,0xd6,0x80,0xe6,0x75,0xd2,0xfc,0x99,0xc6,0x99,0xb7,0xe1,0xee,0xa9,0x7f,0x2e,0x8e,0xdf,0xff,0xdc,0x5b,0xe,0x95,0xdb,0x72,0x87,0x6c,0x76,0x14,0xe9,0xab,0xc2,0x5e,0x4d,0xe1,0x49,0xc7,0x51,0xc5,0x8c,0x33,0xb9,0x87,0xe7,0x85,0x54,0xe2,0x9b,0x62,0x3,0x6f,0xb9,0xb4,0x63,0xb5,0xb4,0x88,0xf0,0xa8,0xef,0x2a,0x29,0x6f,0xeb,0x6f,0x72,0xbe,0x67,0x0,0x41,0xe7,0x91,0x74,0xd3,0x9e,0xe3,0xd7,0x2e,0x98,0xb2,0xb3,0x1a,0xfa,0x94,0x82,0x9a,0x19,0xe0,0x88,0xf3,0xe7,0xf5,0x50,0x76,0xc7,0xc3,0xb2,0xee,0x71,0x80,0x42,0x5a,0x85,0xd9,0x42,0x63,0xd6,0x80,0xce,0x4a,0x1a,0xe7,0x77,0x26,0x95,0x7e,0x74,0xdd,0x82,0x29,0x1f,0x1c,0x71,0xfe,0x6d,0x43,0x6c,0x66,0xd7,0x4d,0x90,0x7b,0x54,0xa8,0x18,0xc2,0x6e,0x3e,0xe0,0x27,0xa,0xca,0xd9,0x1c,0x9,0x3a,0xaf,0x9a,0x54,0xc3,0xbf,0x6f,0xb8,0xfb,0xd2,0x85,0xed,0x91,0x55,0xcd,0x43,0x80,0xdc,0xe6,0x1f,0xcb,0xba,0xbe,0xf1,0xc6,0x84,0xed,0xf0,0x7b,0xc9,0xba,0xa3,0x0,0x77,0x94,0xac,0x73,0x86,0xac,0x3b,0xae,0xff,0xc4,0xb9,0x7f,0x57,0xb6,0x79,0x38,0x64,0x8f,0xf2,0x6c,0xf4,0xb9,0x7e,0xdf,0x17,0xf8,0xca,0xb5,0xe0,0xb6,0x98,0xf5,0x2b,0x69,0x95,0xc5,0x3e,0x9f,0xe1,0xfb,0x72,0x71,0xdb,0x52,0xd6,0xf0,0x77,0x71,0xe5,0x2c,0xec,0x11,0x3c,0xe9,0x97,0xb9,0xf9,0x26,0x1a,0xe7,0xa9,0xc6,0x6e,0x3d,0xef,0xa9,0x95,0x4e,0x71,0x50,0x53,0xab,0x1b,0x70,0xfe,0x6d,0x5f,0xb0,0x99,0x9d,0xbf,0x90,0x37,0x8b,0x9f,0xa3,0x62,0x48,0x82,0x97,0x82,0x3c,0xa,0x3c,0xee,0x68,0x25,0x85,0xad,0xfd,0x5d,0xad,0x3f,0x4,0x9e,0x25,0x90,0x34,0x4e,0xea,0x45,0x3a,0xd,0xd7,0xad,0xbf,0xeb,0xe2,0xe7,0xda,0x2b,0xaf,0xaa,0x7b,0x80,0x81,0x93,0xee,0x38,0xd8,0xcd,0xec,0xfc,0xbe,0x2,0xa3,0x95,0xef,0x58,0xc5,0x90,0xff,0x4e,0xce,0x98,0x27,0x8,0x26,0x4f,0x64,0x8f,0xf8,0x7e,0xb7,0x5f,0xcd,0x5c,0x5d,0x12,0xf3,0x7b,0xd5,0xb0,0x5e,0xa9,0x6f,0x8a,0x1c,0xc7,0x2b,0xae,0x47,0xe1,0x77,0xde,0x9d,0x71,0xee,0x69,0x4f,0xe2,0x3,0x55,0x5a,0x2,0x7,0x4c,0x9a,0xd7,0x60,0x6d,0xf6,0x5a,0x59,0xfb,0x69,0x7f,0xf2,0xc6,0x9b,0x5d,0x2f,0x12,0xdf,0x73,0xcf,0x45,0xe3,0xbb,0x37,0xe7,0x91,0x73,0xac,0xa9,0x1c,0x2a,0xfc,0x46,0x2a,0xe8,0x9f,0x15,0xfc,0x13,0x50,0xe0,0x3e,0x20,0x95,0x49,0xa8,0xd4,0xc4,0x12,0x8b,0x7e,0x2b,0xad,0x7,0x8b,0x5f,0x30,0x5e,0x8e,0x4c,0x10,0x2a,0x66,0x80,0x81,0x17,0xce,0x77,0x20,0x3b,0xda,0x66,0x5b,0xae,0xcd,0x9b,0xc1,0xc3,0x53,0x76,0x9d,0x7b,0x29,0x34,0x43,0xe7,0xdf,0xfb,0x73,0xed,0x1e,0x81,0x25,0xd0,0x37,0x34,0xe4,0xae,0xe0,0x1d,0xa3,0x6d,0x73,0xf2,0xd3,0xca,0xdd,0xb7,0xff,0xe5,0x33,0xa9,0xdc,0x2f,0xc,0x98,0x74,0xc7,0xf1,0xed,0xc9,0x0,0x15,0xb7,0xbf,0x41,0x17,0xce,0xef,0x93,0x6d,0xd9,0xf9,0x0,0xac,0x3b,0xd2,0xeb,0xc0,0xe3,0x54,0xb7,0x4a,0x8a,0x50,0x4a,0x65,0x2,0x4a,0xb,0x5c,0x39,0xc8,0x77,0xa2,0xa,0xd4,0xa7,0x82,0xb4,0x3e,0x0,0xf9,0x3e,0x80,0x6d,0x0,0x76,0x92,0xdc,0x5,0xd2,0x42,0x8,0xe4,0x91,0x14,0x80,0x26,0x9,0xdd,0x20,0xbb,0xf,0xa0,0x5e,0x90,0x6f,0x2a,0x67,0x4c,0x1e,0x35,0x6b,0x2e,0x11,0xf5,0x93,0xe7,0x13,0x0,0xc2,0x42,0x32,0x34,0xce,0x93,0x26,0xd5,0x78,0xd9,0xba,0x85,0x17,0xbd,0x5a,0x5b,0x5e,0xa5,0x4b,0xd0,0x26,0x18,0x7c,0xc5,0x33,0xcc,0x7e,0xf8,0xea,0x19,0x36,0xb3,0xf3,0x21,0x0,0x16,0x81,0x12,0x1f,0xae,0x8a,0xe2,0x13,0x2d,0x18,0xf2,0x22,0x4,0xe7,0x3c,0xef,0x7,0xe6,0xaf,0xfc,0x87,0xad,0xc8,0xee,0x8b,0x1d,0xa,0xd6,0x8a,0x84,0xe6,0x66,0xfd,0x98,0x2d,0x34,0xce,0x3f,0x24,0xbc,0x4d,0x9a,0x4d,0x30,0x66,0x1d,0xc0,0x97,0x48,0xfe,0x15,0xe0,0x3b,0x20,0xdf,0x23,0xd4,0xec,0x5a,0x65,0xd2,0xe9,0x86,0x46,0xeb,0x66,0xba,0x1,0xd8,0xd7,0x5a,0xdb,0x7,0xd2,0x0,0xc9,0x8e,0x24,0x74,0xb0,0xa4,0x8f,0x1,0x3a,0x0,0xb2,0xfb,0x86,0xab,0xc2,0x90,0xcf,0x7a,0x1,0x33,0xa8,0x75,0x7d,0xa,0xe4,0xfd,0x8,0x33,0x40,0x41,0x13,0xa,0x3b,0xc6,0x7a,0x35,0xb2,0x74,0x1a,0xe6,0x34,0xef,0xdc,0x7e,0xd5,0x5f,0x1e,0xb8,0x3a,0xf1,0x15,0x48,0x15,0x9,0x81,0xee,0x96,0xbf,0xd,0x92,0xdb,0xf2,0x7d,0x80,0xa0,0x6f,0xb0,0xf7,0xb0,0x9f,0x9b,0xb7,0x40,0xde,0x23,0xab,0x88,0x82,0xb9,0xa7,0xd0,0xff,0x1c,0xc5,0x43,0x2c,0xc3,0xa8,0xc6,0xdb,0x2a,0x2c,0xb0,0x93,0x4,0x62,0x86,0xfc,0x29,0x78,0x80,0x7c,0xf,0x30,0x9b,0x4,0xb3,0x96,0x4e,0x6a,0x71,0x3a,0xd5,0xf0,0xe0,0xea,0x3b,0x27,0x95,0x33,0xa0,0xb4,0x0,0xd8,0xa,0xe0,0x2d,0x0,0x1b,0x1,0x3c,0x15,0xbc,0x18,0x30,0xe9,0xce,0x7e,0xb2,0x99,0x89,0x80,0x8e,0x83,0xec,0xa1,0x92,0x3d,0x8,0x42,0x63,0xa0,0xc1,0x7a,0x79,0x2a,0x50,0x79,0x42,0x66,0xcc,0xbc,0xab,0x40,0x58,0xd,0xca,0xd7,0x3b,0xa8,0x17,0xfc,0x70,0xbf,0x4a,0xfe,0xa,0x88,0xc0,0x30,0x26,0xc1,0x48,0xee,0x99,0x4d,0xdd,0xf7,0x5a,0xe,0xe0,0xf6,0xa4,0x19,0xa0,0xa2,0x1e,0x60,0xe0,0x5,0x77,0x9e,0xea,0x66,0x76,0x3e,0x26,0xc9,0x84,0xb1,0xdf,0x91,0x10,0xb2,0x15,0xcb,0xd7,0x32,0x7c,0xe,0xe0,0xfb,0x24,0xdf,0xa2,0x49,0xdd,0x6c,0x1c,0x67,0xf6,0xda,0x5,0x53,0xda,0xbc,0x48,0xa4,0xad,0x30,0x60,0xd2,0xbc,0x43,0x21,0xf7,0xbb,0x92,0x1d,0x29,0xeb,0x7e,0x2,0x52,0x93,0xbf,0x4c,0x2d,0xd4,0x10,0x12,0xad,0x6b,0xde,0xa7,0x91,0xce,0x12,0xa6,0xf6,0x38,0x75,0xfd,0xc2,0xb,0x9a,0x93,0xcc,0xa3,0x32,0x6,0x98,0x7c,0x57,0xa3,0xcd,0x36,0x9f,0x23,0xb7,0xe5,0x4e,0x40,0x4e,0xe0,0x80,0xd9,0x51,0xf6,0xfb,0x80,0xf8,0x61,0x84,0x4b,0xd8,0x49,0x60,0x87,0x49,0x37,0x7e,0x7b,0xdd,0xc2,0x8b,0x6e,0x6c,0xf7,0x42,0x0,0x18,0x30,0xf9,0xee,0x94,0x32,0xdb,0xe7,0xca,0xba,0xa7,0x1,0xda,0x3f,0xb7,0x78,0x25,0xef,0x26,0x98,0x38,0x42,0x24,0xb9,0x34,0xa9,0x7b,0x36,0xdc,0x3d,0xf5,0x82,0x24,0xd3,0xad,0x5c,0x8,0x9c,0xbc,0x70,0xf,0xeb,0x66,0x2f,0xb3,0xd9,0xe6,0x19,0xf0,0xc7,0x5b,0x4f,0x14,0xc8,0x69,0x57,0x25,0xd2,0x2c,0x67,0x15,0xb,0xc7,0x29,0xf2,0xe5,0xf7,0xa7,0x46,0xe1,0x59,0x19,0xe1,0x79,0xd2,0x3a,0x5b,0x61,0x9c,0xdb,0x68,0x52,0x5f,0x5f,0xbf,0x70,0x72,0x87,0xb9,0x52,0x7,0x30,0x70,0xf2,0xcf,0xbb,0xb9,0x2d,0xdb,0x97,0x41,0xb6,0x2f,0xc0,0x3d,0x2,0xe7,0x64,0x32,0xf0,0x48,0xe,0x44,0xa4,0x52,0xe,0xe6,0xc5,0x78,0x88,0x14,0x72,0x25,0x89,0xa0,0x59,0xed,0xa4,0x1a,0x3f,0xb7,0x6e,0xe1,0x94,0xb7,0xc2,0x2f,0x47,0x5e,0xb3,0x94,0x3b,0xdf,0x7b,0xc5,0xd0,0x69,0xa0,0xcd,0x6c,0x27,0x4d,0x9a,0x0,0xdd,0x75,0xb,0x2e,0x70,0xcb,0xd5,0xa1,0x2a,0x2e,0x1d,0x34,0xf9,0xe7,0x7b,0x58,0xb7,0xe5,0xdb,0x36,0xdb,0xf2,0x75,0x2,0x26,0x34,0xf0,0x33,0x69,0x57,0xae,0x70,0x97,0xf,0x8f,0xf8,0x2,0x0,0x63,0xcc,0x66,0xa6,0x1a,0xc7,0xae,0x5b,0x30,0x39,0x51,0x7,0x89,0x6a,0x60,0xc0,0xa4,0x79,0xd7,0xd9,0x6c,0xf3,0x37,0x0,0xed,0xcb,0xb0,0x47,0x50,0x72,0x26,0xab,0x80,0xe9,0x41,0x93,0x7a,0x7e,0xc3,0xdd,0x53,0x8f,0x1f,0x34,0xe5,0xee,0x46,0x9b,0x6d,0xa6,0x71,0x1a,0x9a,0x24,0xb7,0x2f,0xa4,0x8f,0x9,0xea,0x49,0xa0,0x87,0xa4,0x3,0x69,0x9c,0x17,0x20,0xf7,0xf9,0x75,0xb,0x2f,0xca,0x94,0x4a,0xbc,0xea,0xc2,0xd,0xbc,0x70,0x61,0x83,0x6c,0xf6,0xdf,0xe5,0xb6,0x7c,0x13,0x64,0xb0,0x20,0x23,0xbf,0xd8,0x22,0x49,0x8,0x98,0x4a,0x82,0xa4,0xac,0x71,0x52,0xcf,0x3b,0xd,0xdd,0xce,0x5e,0x33,0xef,0xbc,0xf,0x92,0xcf,0xac,0x5a,0x7c,0x2c,0x18,0x63,0xb3,0xbb,0xe6,0xc9,0xda,0x83,0x3d,0x43,0x17,0x3,0x49,0xbe,0xf6,0x6,0x91,0x5f,0xdc,0x2,0x1,0xbb,0x48,0xf3,0x1a,0xa4,0xde,0x80,0x7a,0x2,0x28,0xd2,0x81,0x82,0x7b,0xae,0x34,0xa9,0xc6,0xeb,0xd6,0x2d,0x9c,0xfc,0x54,0xa9,0xa4,0xab,0xf6,0x9,0x5c,0xb7,0xe0,0x82,0x16,0xa7,0xb1,0xfb,0x7f,0x99,0x54,0xe3,0x75,0x4,0xb2,0x8,0x69,0x33,0x89,0x9b,0x45,0x7c,0x24,0x90,0xcc,0x1a,0x27,0xfd,0xf0,0xfa,0xbb,0x2e,0x19,0x53,0x4f,0xc4,0xf7,0xf0,0x71,0xe1,0xd3,0x26,0xd5,0x78,0xa,0xe9,0x6c,0x40,0x41,0xd9,0x6b,0x77,0x6d,0x43,0xe1,0x6f,0x23,0x64,0xf,0x3,0xb4,0x17,0x8a,0xde,0x15,0xde,0x6b,0x88,0xa0,0x7f,0x29,0x57,0xee,0x9a,0x9c,0x42,0xd7,0xdc,0x3e,0x3e,0xeb,0x34,0x74,0x9f,0x69,0x52,0x4d,0x53,0x4,0xbe,0xdf,0x76,0x8b,0x60,0x18,0x4a,0x85,0x31,0xc7,0xd6,0x5e,0xbf,0x9f,0x7a,0x72,0xfd,0x5d,0x17,0x9f,0x95,0x18,0xd5,0x12,0x86,0x75,0xb,0x26,0xff,0xc9,0x34,0x34,0x9d,0x49,0xe3,0x2c,0xf7,0x2d,0x8e,0xfe,0xf0,0x15,0x26,0x63,0x31,0x59,0x4b,0x85,0x79,0xcf,0x7e,0x7,0x2b,0xd2,0xc8,0xf3,0x31,0xd,0x2e,0x8a,0x34,0xc1,0xd4,0x51,0x51,0x47,0x6c,0xc,0x81,0x4f,0x7e,0xea,0xc2,0x87,0x4a,0xf6,0x3e,0x35,0x7b,0x5,0xaf,0xbe,0xfd,0x9c,0x2c,0x53,0xd,0xf7,0x93,0xdc,0x51,0x64,0xa,0x29,0x1,0x51,0xcc,0x50,0x18,0x26,0xbf,0x1f,0x83,0xe7,0x2b,0x0,0xe3,0xa4,0x9f,0x6c,0x49,0xf7,0x3a,0xbd,0xdd,0xa8,0x97,0x10,0xac,0x9b,0x7f,0xc1,0x2b,0x26,0xd5,0x38,0x85,0xc6,0x59,0x82,0xfc,0xec,0x28,0xa2,0x99,0x1c,0x65,0xc2,0xf2,0xcf,0xcc,0xdb,0xa9,0xc3,0xef,0x99,0x7f,0x95,0x8b,0x27,0x4f,0x39,0x12,0xac,0xcd,0x9e,0xd7,0x9d,0x1f,0x4e,0x2c,0x55,0xde,0x44,0xdc,0xc2,0x6d,0x36,0xd3,0xf,0x40,0xda,0xa3,0x17,0x13,0x71,0xe7,0x26,0xd,0x5,0x58,0x6f,0x4a,0x3c,0xfd,0xa8,0x93,0x6e,0x1a,0xff,0xf2,0xbc,0xd3,0x77,0x8b,0xcd,0x98,0xd6,0xce,0xbf,0x60,0x23,0x4c,0x6a,0x16,0xe9,0xbc,0xec,0x4d,0x31,0x18,0xc9,0x53,0x97,0x6a,0xc6,0x4b,0x1b,0x2e,0x6,0xb3,0x6d,0x90,0xfa,0xca,0xaa,0x7f,0xfb,0x33,0x80,0x9b,0x99,0x1,0x70,0xdf,0x9a,0x13,0x2a,0x4,0x1,0x34,0x34,0xce,0x5a,0x9a,0xf4,0xd,0x6b,0xe6,0x9d,0xf7,0x61,0x7b,0x11,0xac,0x3d,0x60,0xfd,0xc2,0xc9,0xf7,0xc0,0xa4,0x6e,0x7,0xb9,0xcd,0xb7,0x57,0x75,0x98,0xd1,0x2c,0xbc,0x48,0x56,0x50,0x8f,0x52,0x71,0x6b,0x66,0x80,0x23,0xa7,0xdc,0xb5,0x17,0x60,0x87,0x92,0x48,0xe5,0xf5,0xde,0x44,0xc4,0x1e,0x92,0xdc,0x42,0x93,0x5a,0xb0,0x76,0xfe,0xa4,0xc7,0x3a,0xa,0x79,0x49,0x82,0x31,0xce,0x2c,0x9a,0xd4,0xbd,0xbe,0x8d,0x3a,0x98,0x25,0x69,0xf7,0x19,0xc5,0x80,0xf8,0xbe,0xf6,0x7c,0xe4,0xc0,0xc9,0xb,0x87,0xc4,0x96,0xb1,0x96,0xa,0x1e,0x7d,0xed,0xef,0x8,0x72,0x38,0x80,0xb4,0x97,0xa1,0xd7,0xcd,0xd5,0xd2,0x83,0xf9,0x5,0xf7,0x2a,0xe0,0xa4,0x1e,0x0,0x4d,0xe2,0xf6,0xef,0x8e,0x82,0xb5,0xf3,0x27,0x6d,0x31,0x4e,0xfa,0x36,0x18,0x67,0x29,0xfc,0x3e,0xd9,0x9f,0xe9,0xab,0xc,0x27,0x11,0xf7,0x88,0x9,0xf7,0x47,0x1,0xff,0x3f,0x1,0x6b,0x4f,0x80,0x74,0x76,0x5c,0x19,0x6b,0x62,0x80,0x6d,0xff,0xd8,0x48,0xeb,0x66,0xcf,0x25,0x4d,0xca,0x2f,0x51,0xcd,0xeb,0x79,0x7c,0x75,0x9f,0xa0,0x79,0x15,0x30,0xf7,0xaf,0x9b,0x3f,0xa9,0xa2,0xdd,0xbf,0xea,0xd,0xd6,0xde,0x79,0xfe,0xb,0x34,0xa9,0xc5,0x0,0x0,0x1a,0x11,0xac,0x58,0x31,0x64,0xc4,0x3d,0x63,0xc2,0x8b,0xf0,0x28,0x92,0xd,0x24,0xfa,0xc6,0x95,0xaf,0x26,0x6,0x58,0x7f,0xd7,0xc5,0x56,0x6e,0x76,0x2c,0xa0,0x34,0x69,0xc2,0x5b,0xaf,0x54,0x7e,0x91,0x81,0xe4,0xef,0xf5,0x22,0xc6,0x59,0x44,0x63,0x1e,0xef,0x6c,0x2,0x26,0x1,0xa4,0x59,0x4c,0x93,0x7a,0x12,0xfe,0x7e,0x46,0x28,0x35,0xc,0xb0,0xb6,0x6,0x54,0x98,0x16,0x82,0x6e,0xb5,0xf1,0xd3,0xe3,0xe7,0x46,0xd2,0xba,0x26,0x6,0x18,0x74,0xd1,0x3d,0x7d,0x41,0xf4,0xf6,0xc4,0x76,0x28,0xa7,0xf2,0x56,0x39,0xec,0xfb,0x92,0x3f,0x49,0xf3,0x16,0x8d,0xf3,0xd4,0xda,0x3b,0xcf,0xdf,0xde,0xd9,0xc4,0x4b,0x2,0xd6,0xde,0x79,0xfe,0x5a,0x3a,0xa9,0xf9,0x5e,0x25,0x73,0xe,0x1f,0x25,0xc4,0x9f,0xda,0x2f,0xcf,0xaf,0xc4,0x50,0x9e,0xf5,0xb4,0x67,0x63,0xb7,0x1e,0x7,0x46,0x95,0xad,0x6a,0x6,0x18,0x7c,0xc9,0xfd,0x29,0x59,0x3b,0xa,0xa0,0x4d,0xa2,0xe4,0x81,0x1,0x3,0x20,0x68,0x9c,0xf9,0x34,0xce,0x8a,0xce,0x26,0x5c,0xa2,0x40,0xf3,0x57,0xd2,0xbc,0x8b,0x76,0x76,0x9f,0xb,0x5c,0xe2,0xfc,0x1d,0x67,0xe0,0x73,0xc3,0xc1,0x10,0x3e,0x1d,0x55,0xac,0xaa,0x19,0x60,0xf5,0x6d,0x67,0x67,0x9,0x7d,0x26,0x34,0xd3,0x55,0x93,0x9a,0xc3,0xdc,0x46,0x4e,0x0,0x4d,0x6a,0xd9,0x9a,0x3b,0x26,0xee,0xd6,0x63,0x7f,0x31,0x18,0x63,0xd6,0x9b,0x54,0xc3,0x6c,0xff,0x51,0x91,0x5b,0x91,0xd7,0x0,0x85,0x3e,0x9,0x9e,0x22,0xe8,0xd,0xa5,0xe6,0x15,0x3a,0xa9,0xfb,0x49,0xf3,0x46,0xd4,0x77,0x6d,0xf6,0x8,0x1a,0x74,0xd1,0xdd,0x4d,0xa4,0xb3,0xbf,0xac,0xed,0x2b,0xe8,0x40,0x2,0x7b,0x43,0xee,0x98,0xdc,0x86,0x8d,0xc9,0xa8,0xb9,0x24,0xb9,0x9,0xe0,0xa6,0x24,0x91,0x53,0xf,0xb0,0xfa,0xf6,0x9,0x9b,0x7,0x7f,0x71,0xd1,0x43,0x0,0xfe,0x3,0x0,0x61,0x12,0x30,0xc1,0x84,0x26,0x80,0x48,0x12,0xb2,0xca,0xeb,0x1,0x7c,0x97,0xc6,0x79,0x96,0x74,0x16,0x64,0x65,0x16,0x6f,0xb8,0x73,0x42,0x36,0x2a,0x89,0x58,0x6,0x18,0x74,0xd1,0xbd,0x3d,0x21,0x1d,0xe,0xe8,0x40,0x90,0x7b,0x41,0xea,0x25,0x65,0x8f,0x90,0x75,0x8f,0x83,0xf4,0xe9,0x60,0xe1,0x7a,0x68,0x51,0x67,0xad,0x1e,0x31,0x9e,0x3b,0x21,0x53,0x33,0x4,0xac,0x69,0x2f,0x42,0x74,0x26,0x8,0xb0,0xa0,0x79,0x1f,0xd2,0x3e,0x9,0x35,0x97,0xc0,0x21,0xc7,0x73,0x8e,0x1,0x29,0x70,0x33,0xc9,0x55,0x34,0xa9,0x87,0x8c,0x93,0x9a,0xbf,0xfa,0xf6,0xf1,0x9b,0x4b,0x25,0x11,0xc9,0x0,0x83,0xbf,0xb8,0x68,0x7f,0x2b,0xf7,0x7c,0x59,0x77,0x3a,0x64,0xf,0x2f,0xcc,0x33,0xa7,0xb0,0x7b,0x4e,0xa,0xf0,0xf9,0xad,0xb6,0x1e,0x20,0x67,0x2c,0x37,0x8e,0xf3,0xfc,0x9a,0x3b,0x26,0x6e,0x4b,0x8,0xe7,0x75,0x5,0x92,0xb6,0x3,0xf8,0x33,0x80,0x91,0x40,0xa2,0xdb,0xd7,0x51,0xe0,0x3f,0xe8,0x38,0xaf,0x11,0xe6,0x41,0x90,0x3f,0x5d,0x3b,0xef,0xdc,0x36,0x9,0xd0,0x31,0x3d,0x80,0xc6,0xcb,0x75,0xbf,0x5,0xe8,0x63,0x60,0xd8,0xf1,0xb3,0xc0,0x41,0x23,0x34,0x3f,0xd1,0x26,0xb7,0xed,0x92,0x15,0xc8,0xff,0x7c,0x74,0xd7,0x86,0x93,0x7c,0x1b,0x26,0xf5,0x88,0x6c,0x76,0x24,0x22,0x5d,0xca,0x83,0xa0,0x72,0x4b,0x90,0x82,0x77,0xca,0xe1,0x8d,0x4e,0xfa,0x47,0xae,0xab,0x19,0x1b,0x16,0x9c,0x57,0xd6,0xb,0x28,0xc,0x91,0x3,0x91,0x80,0x5e,0x0,0x1a,0xbc,0x42,0x7b,0x53,0x8f,0x79,0xe9,0xd2,0x14,0x49,0xb1,0x40,0xe9,0xe7,0x8a,0x6c,0x1,0xbb,0x4,0x54,0x54,0x81,0xdd,0x9,0xd6,0xdc,0x31,0xe1,0x7d,0x1a,0xe7,0x49,0x1f,0x47,0x11,0xb6,0x80,0x0,0x8a,0x9f,0x11,0xf3,0x2e,0xf7,0xed,0x7,0x80,0xb9,0xad,0x52,0xe2,0x3,0x31,0x3d,0x80,0x64,0xf,0x0,0xb0,0x97,0x37,0xbf,0xac,0xfc,0xc6,0x36,0xde,0x5b,0x54,0xd6,0x73,0xb5,0x69,0x95,0x6c,0xb0,0x2e,0xe7,0x1d,0x82,0x1d,0xee,0xdb,0xd7,0x91,0x40,0xf2,0x3d,0x1f,0xaf,0x3e,0x46,0x8b,0x5b,0x7d,0x2e,0x66,0x4c,0xa,0xa1,0xb5,0x29,0xc1,0xa2,0x8,0xc3,0xb4,0xe3,0x38,0x4d,0xd5,0x94,0x27,0x7a,0x8,0x10,0x7a,0xe6,0xed,0xcb,0xc5,0x63,0x55,0xa5,0x3d,0x74,0xb9,0xf8,0x61,0x2c,0xf0,0x75,0x10,0x89,0xbb,0x73,0xd7,0x15,0xd0,0x8,0x84,0x65,0x68,0x51,0x4d,0x8,0xf,0x6d,0x49,0x20,0x7f,0x97,0x1f,0x2d,0x53,0x81,0x3c,0x56,0x29,0x44,0x32,0x0,0x8d,0x69,0x90,0x6b,0xbd,0x1d,0x2c,0x3b,0x60,0x1a,0x33,0xe7,0xf2,0x47,0xf3,0x6,0xc0,0x8f,0x34,0x3,0x10,0x70,0x9,0xbe,0x2f,0x69,0xbf,0x4,0x51,0x9b,0xaa,0x56,0x9c,0x4c,0x68,0x9f,0xc0,0x72,0xe3,0x15,0x4b,0xbe,0xf3,0x1a,0x3,0x41,0xf2,0x4d,0x48,0x1f,0x69,0x6,0x10,0xe0,0xa,0xfc,0xb0,0xd0,0xc1,0x27,0x6a,0xfc,0x8f,0xc3,0x1d,0xc3,0x69,0xe5,0xce,0x2f,0xaa,0xd6,0x1b,0x37,0x46,0xb,0xc8,0xa9,0x7a,0x68,0xd5,0xfb,0xc7,0xa,0xf8,0x8c,0x7e,0x9f,0xb,0x63,0xc9,0xef,0xe5,0x2f,0xa2,0xfb,0xe8,0xea,0x0,0x7e,0x3d,0x73,0xf5,0x67,0xcc,0x6f,0x14,0xc4,0x31,0x41,0x58,0xbe,0xaa,0xe,0x71,0xd1,0x43,0x0,0x0,0x5,0xd4,0x8a,0xcc,0x3b,0x1c,0xa8,0x88,0xf7,0x25,0xca,0xcf,0xf0,0x4d,0x78,0x55,0x2c,0x1,0xe0,0x0,0xd0,0x54,0x25,0xcc,0xec,0x2e,0x40,0xd2,0x11,0xb0,0x77,0x69,0x7a,0x85,0x9,0x1c,0x77,0xf,0xd0,0x3f,0x5b,0x43,0x82,0x6b,0xad,0xad,0xca,0xb4,0x1c,0xad,0x5,0x0,0x2d,0x79,0xcb,0x5e,0x39,0x83,0x45,0x2d,0x4d,0xb6,0x90,0x91,0x8,0xf4,0x21,0xf9,0x91,0x67,0x0,0x92,0xfb,0xb4,0x6d,0xb9,0x0,0xdb,0x78,0xaf,0x6c,0xb5,0x64,0x88,0x1e,0x2,0xc8,0xf,0x19,0xd8,0xaa,0xb,0x8e,0xef,0x8,0xfa,0xe8,0xfc,0x26,0x56,0x5e,0x9c,0x10,0x8f,0x94,0xdd,0x46,0xa5,0x88,0x9f,0x7c,0x63,0xa6,0x9f,0xcf,0x81,0x0,0x1a,0x13,0xc1,0x74,0xdd,0x82,0xf2,0x7b,0xa9,0x28,0x68,0x5f,0xc5,0x50,0xac,0x71,0x17,0xf5,0x94,0x2c,0x5a,0x73,0xe,0x66,0x43,0x1b,0x74,0x55,0x4,0x91,0x42,0x20,0x61,0xde,0x20,0xb8,0x85,0xe1,0x15,0x27,0x40,0x91,0x5c,0x10,0xb2,0x7,0x15,0xcb,0x9,0xa5,0x64,0xc2,0xe2,0x97,0x21,0x9b,0xa2,0xa4,0x8f,0xeb,0x23,0xcf,0x0,0xec,0x5,0x20,0xd8,0x53,0x0,0x28,0x25,0xf4,0x15,0xc,0x97,0x21,0x9c,0x7,0x32,0x9a,0x2f,0x48,0x12,0xcc,0x0,0xa8,0xea,0xd0,0xa9,0x18,0x4b,0xa0,0xde,0x2,0xd9,0x82,0x60,0xc1,0x81,0xc7,0xb6,0x8,0x76,0x44,0x60,0x3b,0xfc,0xf9,0x5a,0x40,0x13,0xeb,0x68,0x3,0xeb,0xa4,0x61,0xf0,0xd4,0x5f,0xed,0x6b,0xad,0x7b,0x8a,0x8f,0x57,0x26,0x85,0x3b,0x49,0x7b,0x3,0xfa,0xe6,0xe0,0x8b,0x7f,0x51,0xb1,0x56,0x17,0xed,0x26,0xe4,0xa4,0x1e,0x4,0x9d,0x6f,0xd3,0x38,0xcf,0x6,0x3e,0x5a,0xde,0xaf,0xaf,0xaf,0x3,0x40,0xfe,0x8,0xc7,0x3c,0x37,0x16,0x34,0xee,0x98,0x6e,0x20,0x1c,0x3f,0xb0,0x68,0x41,0xa2,0x31,0x5,0x61,0x1f,0x45,0x20,0x4d,0x2f,0x40,0xa7,0xe5,0x10,0x17,0x65,0xd5,0xcd,0xbd,0x63,0x99,0x9e,0x34,0x7f,0x43,0x43,0xc8,0xba,0x97,0x3,0x7c,0x7a,0xf0,0x25,0xf7,0xfd,0xf7,0xe0,0xa9,0xf,0xec,0xdd,0xe6,0x32,0xc5,0xbd,0x18,0x3c,0xf5,0x57,0xdd,0x1,0xf6,0x85,0xec,0x41,0x20,0x7a,0x43,0x38,0x4,0xd0,0x27,0x25,0x7b,0x24,0x81,0x81,0xf0,0xe7,0xa,0x80,0xf0,0x36,0xaf,0x35,0x51,0xcf,0x3f,0xf,0x32,0xf5,0x75,0xe3,0xa4,0x6f,0x5c,0x75,0xf3,0xbf,0xb6,0xf9,0x4,0xae,0xdd,0x5,0x86,0x5c,0xfa,0xc0,0x30,0x9b,0x6d,0xf9,0xd,0x80,0xbd,0x93,0x30,0x2,0x85,0xf6,0xc7,0x9,0x6f,0xba,0xb9,0x85,0x34,0x2b,0x5,0x3e,0x44,0x63,0xee,0x5c,0x7d,0xeb,0x59,0x25,0xf,0x9f,0x6a,0x73,0x29,0x86,0x5d,0xfe,0x70,0xf,0x6b,0xdd,0x7d,0x65,0xed,0x1,0x34,0x66,0x7f,0x59,0xdb,0xb,0x72,0xaf,0x96,0x6c,0xff,0xd6,0x66,0xcd,0x1a,0x2a,0x44,0xbe,0xe9,0x38,0xd,0x13,0x56,0xdd,0x32,0xf6,0x85,0x24,0xd2,0xac,0x27,0x18,0x3c,0xf5,0x57,0x23,0xe5,0x66,0x5e,0xf4,0x77,0x15,0x49,0x62,0x15,0x7d,0xab,0xa3,0x66,0x82,0xd3,0xc7,0x4,0x6c,0x26,0xcd,0xb,0x34,0xce,0x42,0xc7,0x98,0xfb,0x56,0xde,0x3c,0x36,0x72,0x99,0x78,0x9b,0x3d,0x82,0x56,0xce,0x3d,0x63,0x2b,0xbc,0x7d,0x74,0x5e,0xb,0x55,0x68,0x20,0x2d,0xfa,0x79,0x25,0x49,0x64,0xd3,0x2c,0x1,0xe8,0x63,0xa5,0x83,0x6a,0xc5,0x4c,0xbd,0xc1,0xd0,0xcb,0x16,0xef,0x67,0x6d,0x76,0x9c,0x3f,0xcc,0x55,0x61,0x62,0x8f,0xd4,0xc6,0xb,0xf4,0xe8,0xd0,0xbe,0x8c,0x22,0xb0,0x2f,0xa0,0x33,0x61,0xdd,0xc1,0x2e,0x30,0x74,0xf0,0xd4,0x7,0x17,0xac,0xbe,0x75,0xec,0xba,0xe2,0x4,0xaa,0x6e,0xb9,0xc3,0xa6,0x3f,0x96,0x32,0x34,0xbf,0xf7,0x48,0xef,0x2f,0x45,0xaa,0x68,0xf6,0x37,0x34,0xce,0xf9,0xaa,0x65,0xde,0xb1,0x44,0x9f,0x19,0x7a,0xd9,0x83,0xfb,0x77,0x14,0x71,0x3a,0x6,0x34,0x0,0xd6,0x9d,0xee,0xf,0x94,0x2c,0xa8,0x7b,0x9b,0xfc,0x44,0x59,0x6,0x87,0x41,0xfb,0xcb,0x9d,0x5b,0x24,0x6f,0x22,0x4f,0x9f,0x80,0xec,0x38,0x52,0x7d,0xa2,0x4a,0x55,0x35,0x3,0xac,0x9c,0xf3,0xf9,0xac,0x80,0x17,0xe0,0x9f,0xa3,0x5a,0x9d,0xdc,0x9f,0x2f,0xb7,0xa7,0x6d,0x4,0x9a,0x86,0xbd,0x40,0xc2,0x88,0xce,0x26,0x59,0x92,0x20,0xd9,0x43,0x1,0xec,0x7,0x50,0x85,0xcb,0x3b,0xc2,0x78,0xa8,0x1c,0x87,0x28,0xfe,0xb6,0x50,0xbb,0xa0,0xdf,0xad,0xbe,0x4a,0xe3,0x6c,0x8c,0x2a,0x57,0x4d,0x63,0xf7,0x1f,0x6e,0x19,0xfb,0x2a,0x8d,0x79,0x33,0x98,0x32,0x8e,0x76,0x74,0x8d,0x9a,0xf4,0x88,0xb3,0x6d,0x53,0x0,0x5,0xe9,0xe3,0xb2,0xf6,0xe4,0x21,0x97,0x2d,0xee,0xd9,0xb9,0x64,0x4b,0x6,0x6,0x5f,0xfa,0xe0,0x60,0x59,0x4d,0xf6,0x55,0xdd,0xdc,0x36,0x37,0x49,0x40,0xac,0xd7,0x40,0xce,0x96,0xf,0x10,0xdc,0xd2,0xd0,0xfd,0x63,0xaf,0x47,0xc5,0xab,0x89,0x1,0x6,0x5f,0x72,0x9f,0x1,0xcc,0x3,0x2,0x32,0x2,0x90,0x53,0xe5,0xa,0x2e,0x14,0x75,0x61,0xc5,0x5d,0x5f,0x41,0x78,0x9e,0x71,0xa1,0xf1,0xb2,0xf6,0xd4,0xc4,0xa9,0xd1,0x9,0x40,0xe0,0xc,0xc0,0x8e,0xf1,0x1c,0xab,0x0,0x76,0xc0,0x89,0x68,0x34,0x39,0x5f,0x3e,0x90,0x66,0x57,0xf1,0x9,0xa6,0x1,0xd4,0xc4,0x0,0xd,0x3d,0x7a,0xb,0x34,0xf7,0x4a,0xc8,0xfa,0x54,0x8c,0x98,0x19,0x2a,0x35,0x25,0x5c,0x1c,0xb7,0x60,0x37,0xb0,0x83,0x49,0x9d,0x3d,0xe4,0xd2,0x87,0x7a,0x77,0x36,0x1,0x6b,0x81,0x21,0x97,0x3e,0x74,0x2,0x64,0xc7,0xe6,0x25,0xff,0xf0,0xa,0xea,0xb6,0xe0,0xaa,0x54,0x58,0xdc,0xb7,0x61,0x13,0x2d,0x77,0xd1,0x98,0x57,0xe2,0xca,0x57,0x13,0x3,0x2c,0xfb,0xe9,0xb1,0xa2,0x71,0x56,0x80,0x39,0x37,0x2e,0x86,0x57,0xf8,0xb4,0x86,0x52,0x52,0x8e,0xf7,0x3e,0xef,0x2e,0x45,0x48,0x1a,0x7,0xe0,0x92,0x76,0xa0,0x4b,0x87,0xc0,0xb0,0x69,0x8f,0xf4,0x4,0xf4,0x45,0x49,0x47,0x7b,0x92,0xbf,0x9,0x26,0x4f,0x22,0xf0,0x11,0x87,0xab,0x52,0x61,0xb1,0xd,0xcb,0x77,0x15,0x20,0x40,0x2e,0x91,0x70,0x7f,0x5c,0x19,0x6b,0xd6,0xdf,0x57,0xcd,0x3d,0x7d,0xab,0x31,0xce,0x8b,0x20,0x4b,0xc,0x3,0x95,0x76,0x5f,0x26,0x30,0x3e,0x76,0x87,0xec,0x85,0x43,0x2e,0x7d,0x68,0x6c,0x47,0x10,0x2c,0x69,0x90,0xb5,0x57,0x49,0xf6,0xdc,0xd0,0xce,0x1d,0x55,0xe2,0x4,0x95,0xc6,0xb,0xe5,0x65,0x56,0xff,0xe1,0x96,0x33,0x63,0xd7,0x59,0x24,0x62,0xc0,0x31,0x4e,0xea,0x1a,0x0,0x9b,0xdb,0xd2,0xc9,0xc7,0x89,0x7f,0x45,0xcf,0x7e,0x55,0x68,0x25,0xdb,0x1f,0xd0,0x15,0xc3,0xa7,0x3f,0xba,0x17,0x76,0x23,0x18,0x7a,0xf9,0xc3,0x17,0xc9,0xba,0x97,0x90,0xec,0xe6,0x1f,0x22,0xdb,0xca,0x15,0x24,0xa,0x3f,0xa5,0xde,0xb0,0x8d,0xf1,0x82,0x85,0x96,0xfe,0x53,0xc9,0x35,0x16,0xc9,0x30,0x80,0x49,0xfd,0x15,0x60,0x16,0x2c,0xa7,0xb4,0xb4,0x56,0x78,0xe2,0x9e,0x7d,0x7f,0x44,0x43,0x1a,0x40,0xfa,0xbc,0xeb,0x66,0xef,0x4e,0x88,0x36,0xed,0xe,0xc3,0xa6,0x3d,0x72,0x34,0x64,0xaf,0x4,0xd1,0x97,0x9e,0xda,0xc7,0xb0,0x7a,0x86,0x12,0xf8,0x29,0x3b,0x61,0x56,0x3e,0x9e,0x48,0xe3,0xef,0x4b,0x65,0x5e,0x26,0xcd,0xba,0x52,0x65,0xad,0x99,0x1,0x86,0x5f,0xf1,0x44,0xca,0x75,0x33,0x17,0x93,0xdc,0xb3,0x60,0x82,0xa3,0xc6,0x8b,0x86,0x14,0x4,0x1a,0x7a,0x9b,0x2b,0xc9,0x9e,0x36,0xf4,0xf2,0xc5,0x8b,0x3b,0x9b,0xb8,0xe5,0x60,0xd8,0xb4,0x47,0x87,0x59,0xd7,0x9d,0x2b,0xd9,0x91,0xb9,0x63,0x71,0x88,0xa,0x8d,0x64,0x85,0x97,0x2,0xa5,0x2e,0x3e,0x9d,0x70,0x78,0x4e,0x93,0x22,0x9d,0x7b,0xff,0x70,0xf3,0xbf,0xfe,0xb2,0x54,0x79,0x6b,0x62,0x80,0x61,0x57,0x3c,0x9e,0x92,0xcd,0x5c,0x27,0xeb,0xde,0x0,0xa0,0x67,0xc1,0x92,0xe4,0x4,0x2e,0x7f,0xdf,0x3b,0xfa,0x27,0x8c,0xc1,0xba,0xf6,0xb3,0x43,0x2e,0x5b,0x7c,0x7f,0x65,0xa5,0xec,0x38,0x18,0x7a,0xf9,0xa3,0x43,0x25,0xf7,0x2e,0x40,0x47,0xfa,0x36,0xd,0x86,0x7e,0x6b,0xc1,0x3,0xbd,0x65,0xfe,0x8,0x7e,0xc3,0x57,0xee,0x14,0x94,0xf0,0x5,0xc0,0xa5,0xe1,0xdf,0xca,0x95,0xb9,0x6a,0x6,0x18,0x7a,0xf9,0xa3,0xd,0x72,0x33,0xdf,0xb3,0xae,0xfb,0xdf,0x0,0xd3,0x5e,0x68,0xb4,0x64,0x5f,0x9d,0x2a,0xd3,0x3a,0xdc,0x18,0xa6,0x21,0x9d,0x39,0xe4,0xd2,0x87,0x7e,0x3b,0xf4,0xf2,0x47,0x92,0xde,0x95,0xac,0x26,0x18,0x36,0xed,0xb1,0x93,0xad,0xcd,0x3c,0x28,0xab,0xc3,0xa,0xd7,0x52,0x94,0xd2,0x7a,0xe2,0x70,0x81,0xd6,0x71,0xf3,0x9a,0xdd,0x2e,0x92,0x1b,0x40,0xf3,0xa6,0x84,0x5d,0xa,0xb6,0x53,0x4,0x43,0x62,0x86,0x27,0xfc,0x9,0x6c,0x75,0x68,0x67,0x31,0x54,0xc5,0x0,0xc3,0xaf,0x78,0xbc,0x1b,0xa0,0x1f,0x59,0x6b,0xaf,0x3,0xe1,0xd0,0x10,0xc1,0x21,0xc7,0x85,0x2b,0xc7,0xa2,0x18,0x9f,0x45,0xe1,0xcc,0x8b,0x2b,0x5,0x78,0x8,0xb8,0x9f,0xa1,0x74,0x9,0x10,0x46,0xd0,0xd1,0xd6,0xba,0x2f,0xf,0xb9,0xfc,0x91,0xe3,0x3a,0x8c,0xc2,0x25,0x60,0xc8,0x65,0xf,0xff,0xa7,0xb5,0xd9,0x45,0x24,0xf,0xa,0xd4,0x6f,0x1a,0xe3,0xf9,0x39,0x17,0x8a,0x3f,0x85,0xf5,0x46,0xc,0x2e,0xa,0xf1,0x26,0x3f,0x2e,0x7d,0x7c,0xac,0x5c,0x75,0xf3,0x99,0x3,0x8d,0x93,0xfe,0x94,0x49,0x35,0xee,0x63,0x52,0x4d,0x4d,0x26,0x95,0xee,0x63,0x9c,0xf4,0x20,0x3a,0xe9,0xd1,0x74,0xd2,0x67,0xd1,0x38,0x5f,0xa6,0x71,0xbe,0x44,0xf0,0xd9,0x72,0x65,0x2f,0x27,0xb8,0x47,0x10,0xff,0xd7,0x7b,0xca,0xda,0xaf,0x4a,0xf6,0x3b,0x8,0x56,0xa3,0xb0,0xd2,0x95,0xae,0x55,0x2d,0x8c,0xf5,0xd8,0x5b,0x62,0xc8,0xb9,0x70,0x2b,0x68,0x1e,0x4b,0x77,0xdb,0xe7,0xbc,0x17,0x67,0x1c,0xd3,0xe1,0x9b,0x48,0xe,0xbf,0xe2,0x89,0x46,0xeb,0x66,0xd6,0xca,0xba,0x7,0x91,0xdc,0x23,0x98,0x92,0x87,0xc4,0x44,0x71,0x12,0x78,0xe8,0x92,0xab,0x40,0xe7,0xe4,0x95,0x73,0x3e,0xf7,0x7e,0x71,0x94,0xa3,0xbe,0xf2,0x5b,0xb6,0x6c,0x7b,0x97,0x4e,0xba,0x81,0xb2,0xd6,0x48,0xd6,0x5d,0x35,0xf7,0x8c,0xb2,0x47,0xcc,0x54,0x44,0x85,0xa1,0xd3,0x1e,0xed,0xe,0x60,0x32,0xac,0x9d,0x5,0xf8,0x67,0xff,0xa1,0xe3,0xf,0x8c,0x40,0xe1,0x3c,0x78,0xb,0xc8,0xb7,0x4,0xde,0xea,0x66,0xb3,0xd7,0xaf,0xb9,0xf5,0xcc,0x4c,0xd,0x59,0xb4,0x9,0x86,0x5c,0xfe,0x48,0x9a,0xc0,0x22,0x12,0x47,0xc9,0xda,0xdc,0x2c,0x1b,0x2b,0x26,0x7a,0x25,0x55,0x46,0x56,0xe0,0x5d,0xab,0xe6,0x9e,0x3e,0x25,0xc9,0xba,0x54,0x54,0xd8,0x61,0xd3,0x1e,0x3b,0x49,0x72,0x7f,0xe3,0x89,0xb5,0x1e,0x9b,0xb7,0x4a,0x2d,0xee,0xec,0x87,0x70,0xcc,0xb8,0xc5,0x23,0x2c,0x8a,0xab,0xc8,0x38,0x91,0xa7,0x83,0x49,0xda,0x4a,0x9a,0xd7,0x40,0x2e,0x2,0xcc,0x4f,0x56,0xce,0xf9,0x6c,0xe2,0x1e,0x45,0xc3,0xaf,0x78,0x7c,0xa8,0xb5,0xee,0xb5,0xde,0xde,0x48,0x3a,0x88,0xa4,0xbf,0x3f,0x62,0x20,0xaa,0x7b,0xc7,0x27,0xb6,0xaa,0x53,0xb8,0x2e,0x51,0x38,0x2a,0xf6,0xa4,0x2e,0xc4,0x97,0xbf,0xf,0x3,0x9f,0x4d,0x35,0x34,0x7d,0x6e,0xd9,0xcf,0x4e,0x4a,0xf4,0xc8,0x98,0x8a,0xe,0x8d,0x12,0xf0,0x16,0xc0,0x55,0x20,0x86,0x12,0x85,0x47,0xb7,0x14,0x54,0xa8,0x18,0xca,0x59,0x7f,0xc2,0x61,0x2c,0xfb,0x5d,0x1e,0xb5,0xb9,0x19,0x70,0x89,0x64,0xf,0xc9,0xe,0x84,0x78,0x10,0xa9,0xb,0x87,0x4e,0x7b,0x74,0x29,0xc0,0xc5,0x0,0x9f,0x58,0x75,0xd3,0xe7,0x3e,0xac,0x16,0x41,0x43,0xa7,0x3d,0x76,0x24,0x81,0x33,0x41,0x9c,0x62,0xdd,0xec,0x27,0x1,0xf4,0x26,0xd1,0xe4,0x17,0x26,0xe7,0xa,0x17,0xb9,0x8c,0x92,0x6d,0xb8,0x8f,0x7f,0xe,0xed,0xba,0xc2,0xd7,0x68,0xcc,0x6d,0x49,0x13,0x3f,0x8e,0x14,0x25,0x61,0xd8,0xf4,0x5f,0x9f,0x2e,0xeb,0x3e,0xc,0x44,0xad,0x70,0xed,0x70,0x28,0x68,0x57,0xa1,0x1d,0x4b,0x20,0xa9,0x19,0xe4,0x3f,0x0,0xbc,0xb,0xe0,0x6d,0x80,0x7f,0x34,0xc6,0xbc,0x28,0x61,0x83,0x64,0x37,0x1b,0x63,0xb6,0x9,0xcc,0x2,0x70,0x8d,0x31,0x8e,0x9b,0xcd,0x34,0x2,0xec,0x66,0xc,0xf,0x4,0x74,0x8c,0xb5,0x3a,0xe,0xd0,0x1,0x0,0x7a,0xc8,0xda,0xde,0x24,0xf7,0xcb,0x21,0x2d,0x7c,0x42,0xa,0xa,0xfb,0xe9,0x44,0x2a,0x15,0x4a,0x4f,0x92,0x5,0xcd,0x8d,0x3d,0xf7,0xeb,0x73,0xd5,0x33,0xd7,0xf,0x4e,0x5c,0xce,0xa9,0xf8,0xec,0x60,0x9,0x2b,0x40,0xf3,0x2,0xa0,0xe3,0x2,0x4f,0x9e,0xf0,0x69,0xd1,0xed,0xf,0x5,0x63,0x49,0xee,0xc1,0x3b,0x69,0x3b,0x68,0x3a,0x10,0xd,0x1b,0x25,0x1c,0x2,0xe0,0x10,0x3f,0xc6,0x9,0x92,0x1d,0x27,0xe1,0x7d,0x48,0xcd,0x90,0xcd,0x10,0xb4,0x0,0xe4,0x66,0xb2,0x24,0xe9,0x0,0x4a,0x59,0xab,0xee,0x80,0xf6,0x7,0x90,0xf3,0x48,0xa,0x16,0xc9,0xf8,0xe,0xd1,0x2c,0x76,0xe7,0xab,0x9c,0xf8,0xc5,0xe3,0x40,0x1,0x7e,0x45,0x43,0x4a,0xb0,0x0,0xc,0x69,0x9e,0x14,0xf9,0x83,0xf6,0x20,0x3e,0x50,0x5,0x3,0x90,0x7c,0x17,0xe4,0x77,0x64,0xdd,0x27,0xdb,0xeb,0xb8,0xb4,0xa,0x4a,0x13,0x2a,0x57,0x48,0x81,0x24,0xc2,0x4e,0x97,0xc1,0x88,0xda,0x1d,0x40,0x5f,0x40,0x7d,0xc1,0x9c,0x4a,0x91,0x4b,0x26,0x70,0x79,0xf,0x8c,0x6e,0xc8,0x7f,0x9b,0xcb,0x28,0xbf,0x59,0x46,0xb2,0x65,0x2f,0xc4,0x6f,0xee,0x5c,0x24,0x43,0x72,0x9,0x8d,0xf3,0x5f,0x2b,0x67,0x9f,0x5a,0xd6,0xa0,0x53,0x2d,0x54,0xdc,0x85,0xaf,0x9c,0xf3,0x59,0x57,0x56,0xcf,0x1,0xe6,0x7,0xcc,0x4f,0x3b,0x29,0xce,0xae,0xf,0xc4,0xdb,0xb2,0x11,0x11,0x16,0xf5,0x1e,0x31,0xdf,0x44,0x7d,0xe7,0x3f,0x33,0x58,0x72,0xe,0x7f,0x5b,0x4e,0x7f,0x7e,0x1,0x86,0x6,0x86,0x26,0xbf,0xb6,0xda,0xf,0xf3,0xe6,0x1c,0x20,0xd2,0x0,0xfe,0x7d,0xb1,0x52,0x5e,0x6c,0xcf,0x47,0x4c,0x19,0x4b,0xc5,0x61,0x89,0xfa,0x86,0x5d,0xb9,0xe8,0x19,0x73,0x1e,0x58,0x31,0xfb,0xd4,0x76,0xf5,0x8e,0xae,0x6a,0xc,0x5f,0x75,0xd3,0xe7,0x32,0xc6,0x71,0x66,0xd0,0x98,0x3f,0x7a,0x1e,0x81,0xf0,0x14,0x83,0xbc,0xcd,0x1a,0xa0,0x77,0x94,0x27,0x3,0x79,0x3d,0xf8,0xf1,0xc3,0xe4,0x1b,0x11,0x7c,0xbb,0x49,0x7e,0x4d,0x8,0xb,0xc3,0xa,0xec,0x61,0x21,0x3b,0x49,0x2e,0x6e,0x48,0x78,0x6c,0x65,0x53,0x2a,0x8e,0x1b,0x32,0x52,0x79,0xc6,0x2b,0x22,0xbc,0xcd,0xa1,0x77,0xa,0x8b,0x1f,0x25,0x7c,0x5f,0x9c,0x6f,0x51,0x18,0x23,0xca,0x15,0x67,0xe3,0x29,0x28,0x77,0x44,0x1d,0xa,0x3b,0x6,0x56,0xdc,0x43,0x77,0x8,0x3,0x0,0xc0,0x8a,0xd9,0xa7,0xbc,0x9,0x98,0x6f,0x48,0xb0,0xc1,0x4a,0x97,0x90,0xcd,0x3a,0xa8,0x72,0x40,0x71,0xff,0x40,0x54,0x13,0xd8,0xaa,0x3d,0xd3,0x5e,0xb0,0xb5,0x1d,0x22,0x30,0x57,0x80,0xc5,0x8,0xec,0xc6,0xc5,0x47,0x1b,0xe2,0x17,0x7f,0xc7,0x32,0xf9,0x97,0xcb,0xaf,0x5c,0x1e,0x95,0x94,0xc5,0xbb,0xf7,0x27,0xc0,0x34,0x61,0xd8,0x15,0x4f,0x8c,0xa9,0x4b,0x6,0x0,0x80,0x15,0x37,0x9e,0xf2,0x2b,0x81,0x73,0xfd,0x59,0x89,0xe0,0xbc,0xdb,0x9c,0xdf,0xa3,0x1f,0x6,0x1,0xaf,0xd0,0x38,0xf3,0x40,0xf3,0x3d,0x90,0x8f,0xa3,0x50,0x4b,0x66,0x72,0x3e,0x92,0x9d,0x24,0x8a,0x24,0x8,0x61,0x1c,0x2,0x1a,0xe,0x60,0xca,0x51,0x57,0x3d,0x9d,0x6e,0xaf,0xfc,0x6a,0x56,0xe3,0x68,0x9c,0xaf,0xd2,0x38,0xbf,0x1,0xe8,0x2,0xc,0x66,0xa5,0x8,0xf0,0x3,0x81,0x4f,0x1,0x9c,0x4d,0x9a,0xff,0x30,0xc6,0x4c,0x5f,0x31,0xfb,0x94,0x6f,0x3,0xe6,0x6b,0xa0,0xf9,0x6d,0x28,0xae,0xef,0x27,0x17,0xb5,0x6d,0x5a,0xa5,0x17,0x6a,0xfc,0xbe,0xf3,0x2f,0x7f,0xd2,0x43,0x79,0xbc,0x68,0x8c,0x9b,0x75,0xcf,0x6b,0x2f,0x6,0x48,0xa4,0xc9,0x8c,0xb8,0xf2,0xa9,0x23,0x24,0xfb,0x6b,0x49,0x69,0x49,0x1b,0xc,0xb9,0x95,0xc6,0xac,0x0,0x78,0xf3,0xf2,0x59,0x27,0xbd,0x19,0x11,0xff,0x13,0xd6,0xba,0xf3,0x25,0x9d,0x60,0x72,0xaa,0x5b,0xe8,0xa0,0xe4,0x92,0xc5,0x6d,0x4b,0x6f,0xd1,0xd6,0x78,0x51,0x71,0xc3,0xcf,0x95,0xa4,0x53,0xd,0x4,0x55,0x8d,0xcd,0x43,0x5e,0x2f,0xca,0x47,0x68,0xcc,0xf8,0x95,0xb3,0x4f,0x2e,0x77,0xa,0x7a,0xd5,0x25,0xa8,0x19,0x46,0x5c,0xf9,0xd4,0xf5,0x92,0x5e,0x7,0x39,0x6f,0xc5,0xac,0x93,0xca,0x6e,0xf5,0x3a,0xfc,0x4b,0x4f,0x35,0x42,0xf6,0x69,0x41,0xc7,0x78,0x2,0x1e,0x73,0x15,0x66,0x58,0xa7,0x8b,0x41,0x51,0x78,0xc,0x29,0x45,0x22,0x96,0xf9,0xbe,0x38,0x4e,0x71,0xfc,0x28,0x4,0x29,0x26,0x8d,0xf6,0x60,0x15,0x7f,0x78,0x7c,0x97,0x34,0x3f,0x58,0x31,0xfb,0xe4,0x1f,0x26,0x9d,0x7e,0xa7,0xe,0x9a,0x23,0xaf,0x59,0x4a,0xb7,0x65,0xfb,0xe3,0x24,0x8e,0x6,0xd0,0xc3,0xdb,0x3c,0x23,0xd8,0x87,0x24,0x8a,0x5,0x18,0xf1,0x5c,0xe9,0xe4,0x43,0x5c,0xba,0xa5,0x58,0x24,0xa,0x65,0xc5,0xdf,0x95,0xcb,0x2f,0xae,0x4c,0x8c,0xf9,0x46,0xc1,0x7a,0x4b,0xff,0xe0,0x68,0x3e,0x63,0x85,0xcf,0xaf,0xba,0xf1,0x94,0x44,0xcd,0xc1,0x9d,0x6a,0xca,0x5d,0xf6,0xd3,0x63,0xb5,0xf2,0xc6,0x53,0x4f,0x25,0x53,0xb7,0x4a,0x7c,0xc3,0x57,0xd5,0x19,0xbd,0xce,0x90,0x31,0xcf,0x61,0x4d,0xa1,0x54,0xdc,0x8,0xbd,0x32,0x36,0x9d,0xb8,0x30,0x96,0xf8,0xae,0x5c,0x7e,0x71,0x71,0xe2,0xbe,0xf1,0xe4,0xe3,0x90,0x6e,0x3b,0x84,0xe4,0xb7,0x92,0xa6,0x41,0x67,0xdb,0xf2,0x1,0x0,0xcb,0x67,0x8d,0xb9,0x16,0x34,0xd7,0x4a,0x58,0xf,0xef,0x4,0x92,0x28,0x4a,0xed,0x56,0x57,0xb0,0xb7,0x72,0xb9,0xb0,0x52,0xdf,0x6,0x2e,0x71,0x7e,0xf8,0x36,0x0,0x1f,0x24,0x8d,0xfb,0xba,0xd2,0x9b,0x86,0x7f,0xe9,0xe9,0xde,0xa0,0x1e,0x25,0x30,0x24,0x5f,0xbc,0xb8,0x3d,0x74,0x6b,0x19,0x71,0x4b,0xa5,0xd1,0x16,0xa9,0x22,0x4e,0x7a,0xc8,0x7d,0x17,0xac,0x95,0xf4,0x67,0x2d,0x73,0x5d,0x9b,0xef,0xc9,0x62,0x5b,0x4f,0xa5,0x7,0xdd,0xbe,0xb7,0x4b,0x46,0xfe,0x5b,0x0,0x92,0x5e,0x27,0xf9,0xff,0x56,0xcc,0x3e,0x69,0x66,0xd2,0x38,0x6f,0x77,0x4b,0x53,0x25,0x60,0xc,0xcf,0x12,0xb0,0x7f,0xa1,0x46,0x10,0xc7,0xa3,0x49,0xf0,0x6e,0xb5,0x69,0xb3,0xd5,0x73,0x89,0x19,0x41,0x17,0x40,0xd6,0x6f,0xdc,0x8d,0x3e,0x81,0x63,0x36,0x88,0x28,0xdc,0x37,0xc0,0x8f,0xf3,0xf,0xc7,0x38,0xd7,0x2f,0xfb,0xd9,0x89,0xb3,0xd1,0xe,0x50,0x17,0x43,0x40,0x0,0x56,0x9a,0x2,0xb0,0x4f,0xcc,0xa0,0x19,0x46,0x54,0x95,0x57,0xf8,0xfb,0xa8,0xb4,0xa2,0xde,0x17,0x43,0x41,0x9a,0xf2,0xaf,0x90,0x15,0x34,0x6c,0x14,0x33,0x24,0xcd,0x12,0x63,0x9c,0x13,0x49,0x73,0xa9,0xf2,0x7b,0x39,0xd2,0x5b,0xff,0x58,0xd0,0xe5,0xe7,0xbc,0x87,0x83,0xd6,0xef,0xf9,0xf4,0xf3,0xb2,0xf6,0x22,0x3e,0x50,0x6f,0x3d,0x0,0xb9,0xb7,0x7f,0xab,0xe8,0xa6,0x5f,0x6b,0xab,0x2f,0x47,0xe4,0x36,0x30,0x41,0x99,0x11,0x42,0xc1,0xc6,0xf7,0xc4,0x12,0x49,0xff,0x43,0xf2,0xe9,0x65,0x33,0x47,0x67,0x0,0xfc,0x6e,0xe4,0x55,0xcf,0xbe,0x2d,0x6b,0x7f,0x9,0x61,0xcf,0x12,0xbe,0x23,0x16,0xa0,0x1,0xf9,0x24,0xc9,0x6f,0x2e,0x9b,0x39,0x7a,0x59,0x72,0x18,0x6e,0xd,0x75,0xd3,0x3,0xc,0xbf,0xf2,0x99,0x43,0xad,0xd4,0xd8,0x7a,0x7d,0x21,0x4a,0x48,0xe2,0x40,0xbc,0x74,0x8f,0x98,0x6f,0xa3,0x24,0x7d,0xc4,0xe4,0x17,0x91,0x6,0x10,0x78,0xfb,0x22,0x98,0xb4,0xb,0xc9,0x76,0xa4,0x31,0xf,0xd2,0x38,0xa3,0x40,0xf3,0x79,0x3a,0xd,0x4f,0x2c,0xff,0xd9,0x89,0x39,0x1f,0xc5,0x65,0x33,0x47,0x3f,0xe,0x9a,0xa1,0x2,0x7e,0xed,0x37,0x79,0x81,0x94,0x37,0xc9,0xc8,0x60,0x1,0x89,0x1,0x79,0x9b,0x80,0x69,0xed,0x4d,0x7c,0xa0,0x9e,0x7a,0x0,0xa2,0x1f,0xc1,0xc6,0xdc,0x53,0x4e,0xb2,0x2a,0xd7,0x52,0x5b,0x79,0xd0,0xf8,0xdd,0x27,0x83,0x77,0x88,0x77,0x57,0x60,0x44,0x7a,0xe5,0x7b,0x89,0xfc,0x9c,0x7d,0xe0,0xe,0x61,0xfe,0xa,0x70,0x11,0xa8,0x5b,0x1,0xbc,0xe,0x68,0xe7,0xf2,0x99,0xa3,0x23,0x3d,0x72,0x97,0xff,0x6c,0xf4,0x9f,0x47,0x5c,0xf5,0xec,0x64,0x8,0x93,0x24,0x3b,0x23,0xa8,0x82,0xef,0xdc,0x42,0x80,0x5f,0x3,0x79,0xc7,0x8a,0x99,0x27,0xbc,0xd7,0x11,0x68,0xaf,0x1f,0x6,0x0,0x8e,0x5,0xd8,0xc3,0xf7,0xc9,0xa8,0xc8,0xc9,0xc4,0x9f,0x7d,0xa,0x3c,0x68,0x2,0x46,0x0,0x80,0xd0,0x92,0x6c,0x0,0x21,0x71,0xbd,0x48,0x66,0xab,0xc6,0x9b,0x97,0x0,0xb2,0x20,0x7,0x81,0xdc,0x22,0x69,0xeb,0xf2,0x99,0xa3,0xdb,0xe4,0x88,0xba,0x7c,0xe6,0xe8,0x77,0x46,0x5e,0xbd,0x64,0x2e,0xc4,0xc5,0x90,0x9e,0x5,0x70,0xa0,0xa4,0x77,0x40,0x4e,0x4,0xf4,0xc2,0xa,0x6f,0xc8,0xe8,0x10,0xa8,0x1b,0x35,0x70,0xf8,0x97,0x9f,0x7d,0x9e,0xc4,0x31,0xbe,0x27,0x47,0x5b,0x9,0x92,0xd7,0xbb,0x3c,0xcf,0xd9,0xdb,0x1,0x2c,0x5,0x70,0x32,0xa0,0xb3,0x51,0x62,0xdb,0xd9,0x90,0xb7,0x50,0x45,0x6e,0xed,0x45,0xbd,0x4d,0x66,0xf9,0xcc,0xd1,0xd,0x6d,0xfa,0x30,0x6,0x46,0x5e,0xbd,0xe4,0x50,0x49,0xc3,0x0,0xac,0x5f,0x3e,0xf3,0x84,0xd,0xed,0x89,0xe3,0x48,0x3c,0x74,0x74,0x86,0x71,0x30,0xe2,0xaa,0xe7,0xde,0x2,0xd0,0x2b,0xbc,0xdf,0x50,0x29,0xa2,0x14,0xbf,0x97,0xf4,0x17,0x80,0x13,0x1,0xac,0xa1,0x77,0x9e,0x71,0x2f,0x0,0x7b,0x4a,0x6a,0x80,0x77,0xbc,0x7d,0xf,0x0,0x9f,0x2,0xd4,0x17,0xc0,0xbe,0x0,0x3e,0x9,0x78,0x1b,0x51,0x55,0xea,0xcf,0x1f,0xc,0x33,0x92,0x32,0xa4,0xe9,0xb6,0x7c,0xe6,0xf1,0xd9,0xb6,0x7e,0x1b,0x5,0x47,0x7f,0x65,0x69,0xea,0xf7,0x33,0x8e,0xad,0x29,0x8d,0x6a,0xa1,0x6e,0x86,0x0,0x82,0x3f,0x17,0xf4,0x15,0xf9,0xb,0xa1,0x3c,0xbf,0x48,0x8f,0x28,0x11,0x94,0xf1,0x37,0x44,0xf4,0x5,0x32,0x6f,0x14,0xb8,0xce,0xcd,0xba,0x7f,0x58,0x39,0xfb,0x44,0xb,0x60,0x93,0x7f,0xe5,0x60,0xc4,0xd5,0x2f,0x90,0xb0,0x3d,0x0,0xee,0x9,0x8f,0x21,0xfa,0xc8,0x6a,0x89,0x31,0x74,0x0,0x6f,0x71,0x65,0x5,0x83,0x8e,0x7f,0xca,0x6d,0x32,0xde,0x81,0x9d,0x45,0x7c,0xa0,0x8e,0x18,0x40,0xc0,0x8f,0x48,0xb3,0x44,0xb2,0x97,0x82,0x3c,0x2d,0x24,0x4,0x14,0xf4,0xba,0x7e,0x80,0xbf,0xf,0x1e,0x20,0x6b,0x9,0xe0,0xfb,0x12,0x1f,0xf5,0x89,0x1f,0x9,0xcb,0x6f,0x38,0x4e,0x0,0xb6,0xf8,0x17,0x46,0x5c,0xb5,0xe4,0x75,0x92,0xbf,0x15,0x70,0x1c,0x80,0x22,0x51,0xa1,0x75,0xe1,0x42,0x5c,0xa8,0xd0,0x9e,0x8c,0xdb,0xea,0xa8,0x13,0xad,0xa,0xea,0x46,0xd,0x5c,0x3e,0xf3,0xf8,0xd7,0x97,0xdd,0x30,0xea,0x3e,0x80,0xd7,0x1,0xbc,0x58,0xc2,0xaf,0x3,0xe7,0x92,0x22,0x87,0x11,0x92,0x46,0xa1,0x77,0xbf,0x7,0xf8,0xbf,0xcb,0x67,0x1e,0x5f,0xd1,0x59,0x43,0xc6,0x18,0xd2,0x98,0xbb,0x42,0xf6,0xf9,0x78,0x3b,0x7d,0xa1,0x4b,0x97,0x6f,0xac,0x81,0x5,0xf8,0x1a,0xda,0xd7,0x61,0xa0,0xdd,0xa1,0x6e,0xd9,0x77,0xc4,0x55,0x4b,0x8e,0x4,0x30,0x82,0xe4,0x89,0x0,0xc6,0x1,0x8,0x6f,0x11,0x13,0x8c,0xc1,0x9b,0x1,0x9c,0xb5,0x7c,0xe6,0xf1,0x4b,0xaa,0xc9,0x63,0xe4,0xd5,0x2f,0x1c,0x28,0xd9,0x4d,0xfe,0xb9,0x88,0xa5,0x5c,0x0,0xa,0xc0,0xd7,0x30,0x32,0x92,0x16,0x1,0x98,0xbc,0x7c,0xe6,0xf1,0x65,0x17,0x61,0xd6,0x2b,0xd4,0x2d,0x3,0x4,0x30,0xe2,0xea,0xe7,0xfb,0x0,0x38,0x3,0xc0,0xbf,0x10,0x3c,0xa,0xc0,0x18,0xdf,0x4a,0xb0,0x43,0xd0,0x95,0xcb,0x6f,0x18,0x75,0x47,0x8d,0xe9,0x3f,0x65,0x68,0x8e,0x87,0x77,0xf6,0x9e,0xe7,0x25,0x1c,0xc3,0xa,0xb2,0x5,0xea,0xc2,0x2e,0x2b,0xfb,0x9f,0x0,0x7e,0xb8,0xfc,0x86,0x51,0x5d,0xc,0xd0,0x11,0x70,0xd4,0x57,0x96,0xe,0x7,0x30,0x9,0x5e,0x6f,0xb0,0xe9,0xc5,0x19,0xc7,0x7e,0xb7,0x96,0xf4,0x46,0x5e,0xb3,0x94,0x92,0x3d,0x95,0xe4,0xaf,0x0,0xec,0x11,0xee,0x5,0x22,0xb4,0x90,0x9c,0xfc,0xe1,0x3f,0x5b,0x0,0x63,0x49,0xf3,0x48,0x67,0x2c,0x4d,0x4f,0xa,0x76,0x2b,0x6,0x68,0xf,0x18,0x79,0xcd,0xd2,0x3d,0x24,0xbd,0x4c,0xf2,0xc0,0x62,0xb5,0x33,0xce,0x5b,0x59,0xd2,0x26,0x92,0x2f,0x91,0xbc,0xf8,0xc5,0x19,0xc7,0x6c,0x6a,0x4b,0x3e,0xf5,0xa,0xff,0xf4,0xc,0x0,0x0,0x23,0xaf,0x7e,0xe1,0x7a,0x1a,0x5e,0x7,0x20,0xe5,0xfb,0x61,0x65,0x0,0xec,0x82,0xb0,0xb,0xc4,0xe,0x0,0x5b,0x24,0x6d,0x26,0xb9,0xd,0xc2,0x66,0x41,0x4b,0x8c,0x31,0xbf,0xfb,0xfd,0x4f,0x8e,0x59,0x57,0x63,0xd6,0x9d,0xe,0x75,0xa3,0x6,0x76,0x26,0xd0,0x98,0xff,0x91,0x74,0x8,0x80,0x1e,0x24,0xb7,0xc0,0xdb,0x5b,0x6f,0x33,0xd,0xdf,0x3,0xf0,0xb6,0xa4,0x57,0x1,0xbc,0xf4,0xe2,0x8c,0x63,0xdf,0xe9,0xec,0xb2,0x76,0x41,0x17,0x74,0x41,0x17,0x74,0x41,0x17,0x74,0x41,0x17,0x74,0x41,0x17,0x74,0x41,0x17,0xd4,0x6,0xff,0x1f,0x32,0x68,0x5,0x7e,0x99,0xd5,0x97,0x49,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char line_edit_focus_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0xab, 0x50, 0x4c, 0x54, 0x45, 0x1b, 0x17, 0x18, 0x1b, 0x17, 0x18, 0x1b, 0x17, 0x18, 0xc8, 0x68, 0x12, 0xef, 0xed, 0xe7, 0xef, 0xed, 0xe8, 0xf0, 0xed, 0xe8, 0xf0, 0xee, 0xe8, 0xf0, 0xed, 0xe7, 0xed, 0xeb, 0xe5, 0xee, 0xeb, 0xe5, 0xee, 0xeb, 0xe6, 0xec, 0xe9, 0xe3, 0xeb, 0xe9, 0xe3, 0xeb, 0xe9, 0xe2, 0xec, 0xe9, 0xe2, 0xe9, 0xe6, 0xe0, 0xea, 0xe7, 0xe0, 0xea, 0xe7, 0xe1, 0xe8, 0xe4, 0xdd, 0xe8, 0xe5, 0xde, 0xe8, 0xe5, 0xdd, 0xe8, 0xe4, 0xde, 0xe6, 0xe2, 0xdb, 0xe6, 0xe3, 0xdb, 0xe6, 0xe3, 0xdc, 0xe7, 0xe2, 0xdb, 0xe7, 0xe3, 0xdb, 0xe4, 0xe0, 0xd8, 0xe5, 0xe0, 0xd8, 0xe5, 0xe1, 0xd9, 0xe5, 0xe0, 0xd9, 0xe4, 0xe1, 0xd9, 0xe5, 0xe1, 0xd8, 0xe4, 0xe0, 0xd9, 0xe2, 0xdf, 0xd6, 0xe3, 0xdf, 0xd6, 0xe3, 0xde, 0xd6, 0xe2, 0xde, 0xd6, 0xe1, 0xdc, 0xd4, 0xe1, 0xdc, 0xd3, 0xe0, 0xdc, 0xd3, 0xe1, 0xdd, 0xd3, 0xe1, 0xdd, 0xd4, 0xdf, 0xda, 0xd0, 0xdf, 0xda, 0xd1, 0xdf, 0xdb, 0xd1, 0xe0, 0xda, 0xd1, 0xdd, 0xd8, 0xcf, 0xdd, 0xd8, 0xce, 0xde, 0xd9, 0xce, 0xde, 0xd8, 0xce, 0xdd, 0xd9, 0xce, 0xdc, 0xd6, 0xcc, 0xdb, 0xd6, 0xcc, 0xdc, 0xd6, 0xcb, 0xff, 0xff, 0xff, 0x73, 0x72, 0x65, 0x6f, 0x0, 0x0, 0x0, 0x2, 0x74, 0x52, 0x4e, 0x53, 0x36, 0x61, 0xc5, 0x3a, 0xd, 0x83, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x38, 0xa0, 0x7, 0xa5, 0xd6, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x9e, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x5d, 0xcf, 0xdb, 0x16, 0x82, 0x20, 0x10, 0x85, 0x61, 0xb4, 0xb4, 0x13, 0x1d, 0x28, 0x14, 0xcb, 0x4a, 0x33, 0xf, 0x59, 0x52, 0x98, 0x62, 0xef, 0xff, 0x66, 0xd1, 0xf6, 0xca, 0xfe, 0x19, 0xd6, 0x62, 0x7d, 0x77, 0x43, 0x88, 0x3d, 0x88, 0x10, 0x7b, 0x34, 0xc8, 0x36, 0x30, 0x76, 0x1c, 0x77, 0xe2, 0x3a, 0xee, 0xd4, 0x7c, 0x0, 0xb3, 0x79, 0x3f, 0xa6, 0x5, 0x80, 0xa2, 0x25, 0xa5, 0xab, 0x35, 0x5, 0x6c, 0x18, 0x63, 0x5b, 0xd6, 0x7, 0xd8, 0x71, 0xcf, 0xe3, 0x9c, 0xfb, 0x9c, 0x7b, 0x3e, 0x40, 0x4, 0xfb, 0xe0, 0x10, 0x84, 0xa1, 0x8, 0x85, 0x0, 0x1c, 0x4f, 0xe7, 0x28, 0xbe, 0x44, 0x71, 0x9c, 0x24, 0x67, 0xc0, 0x35, 0x4d, 0xb3, 0x2c, 0xcb, 0xcd, 0x4b, 0x73, 0x40, 0x71, 0x33, 0x15, 0xe5, 0xfd, 0x51, 0x16, 0x25, 0xa0, 0x92, 0xf2, 0xf9, 0x92, 0xbf, 0x2a, 0x9, 0x50, 0xaa, 0x56, 0xef, 0x46, 0xb5, 0x4d, 0x5b, 0x37, 0x0, 0xdd, 0x7d, 0xb4, 0x36, 0xdb, 0x69, 0xad, 0x1, 0x7f, 0xc7, 0x59, 0xc3, 0xf3, 0xad, 0x2f, 0x30, 0x4f, 0x11, 0x50, 0x3e, 0x12, 0x48, 0xdb, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char option_arrow_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0xc,0x8,0x6,0x0,0x0,0x0,0x56,0x75,0x5c,0xe7,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x98,0x49,0x44,0x41,0x54,0x28,0x91,0xbd,0x91,0xb1,0xd,0xc2,0x30,0x10,0x45,0xdf,0xd1,0xb8,0xf0,0x2,0xee,0xdc,0x87,0x1,0xd8,0x24,0xb5,0xe9,0x19,0x87,0x1e,0xea,0x6c,0xc2,0x0,0xa4,0xb5,0xdc,0x79,0x1,0x17,0xae,0x8e,0x26,0x48,0x76,0x14,0x40,0x48,0x88,0xdf,0xfd,0xf7,0xef,0x4b,0x77,0x3a,0xf8,0x85,0x62,0x8c,0x21,0xc6,0x18,0xb6,0x32,0x59,0x83,0x94,0xd2,0x5e,0x55,0x6f,0x0,0x22,0x72,0xf0,0xde,0xdf,0xdb,0x7c,0xd7,0x9a,0x9c,0xb3,0x55,0xd5,0x9,0xb0,0x80,0x55,0xd5,0x29,0xe7,0x6c,0x5f,0x16,0x6a,0xad,0x67,0x60,0x68,0xd0,0xb0,0xb0,0x3f,0xaa,0x3b,0x3a,0xa5,0x74,0x51,0xd5,0xd0,0xd,0x88,0x5c,0xbd,0xf7,0xc7,0xa7,0xef,0x6e,0x30,0xc6,0x9c,0x80,0xb9,0x41,0xf3,0xc2,0xd8,0x2c,0x38,0xe7,0x8a,0x88,0x8c,0x40,0x1,0x8a,0x88,0x8c,0xce,0xb9,0xf2,0x71,0xcf,0x77,0x8f,0xfb,0x5a,0xf,0x28,0x4a,0x37,0xff,0x58,0x46,0x7b,0x50,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char logo_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x80, 0x8, 0x6, 0x0, 0x0, 0x0, 0xc3, 0x3e, 0x61, 0xcb, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0x2e, 0x23, 0x0, 0x0, 0x2e, 0x23, 0x1, 0x78, 0xa5, 0x3f, 0x76, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xdc, 0x9, 0x7, 0x13, 0x2, 0x0, 0x15, 0xb9, 0x53, 0x97, 0x0, 0x0, 0x21, 0x58, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xed, 0x7d, 0x79, 0x9c, 0x1c, 0x55, 0xb5, 0xff, 0xf7, 0x7b, 0xab, 0x7b, 0x66, 0x48, 0x8, 0x61, 0xd1, 0x90, 0xb0, 0x88, 0x91, 0x27, 0x24, 0x24, 0x21, 0x3b, 0x8, 0x4, 0x42, 0x58, 0x54, 0xe0, 0x91, 0x80, 0x24, 0x1, 0x2, 0x9, 0x42, 0x80, 0x4, 0x11, 0x90, 0x9f, 0xf2, 0xd3, 0xa7, 0xcf, 0xe7, 0xf3, 0x3d, 0x1f, 0x1f, 0x7f, 0xea, 0xd3, 0x48, 0x4c, 0x8, 0x61, 0xd, 0x49, 0x64, 0x89, 0x82, 0x40, 0x58, 0x4, 0x64, 0xb, 0x44, 0x25, 0x9b, 0xd9, 0x51, 0x14, 0x41, 0x3, 0xc8, 0x16, 0x20, 0xfb, 0x4c, 0x77, 0xdd, 0xef, 0xef, 0x8f, 0xaa, 0xea, 0xae, 0xee, 0xa9, 0xea, 0x9e, 0xee, 0xae, 0x99, 0xe9, 0xe0, 0x9c, 0xf9, 0xd4, 0x74, 0xd5, 0xad, 0x5b, 0x77, 0x39, 0xe7, 0xdc, 0x7b, 0xcf, 0x39, 0xf7, 0xdc, 0x7b, 0x81, 0x2e, 0xe8, 0x82, 0x2e, 0xe8, 0x82, 0x2e, 0xe8, 0x82, 0x2e, 0xe8, 0x82, 0x2e, 0xe8, 0x82, 0x2e, 0xf8, 0xe7, 0x2, 0x76, 0x76, 0x1, 0xea, 0x1, 0xe, 0xff, 0xc2, 0xcc, 0xbd, 0x60, 0x5b, 0x6e, 0xb6, 0xd6, 0xf6, 0x2, 0xb8, 0x8d, 0xc6, 0x6c, 0x36, 0x34, 0x6f, 0x81, 0x7c, 0x43, 0x30, 0x7f, 0x27, 0xcd, 0xdf, 0x8c, 0xe3, 0x6c, 0xda, 0x70, 0xef, 0xf4, 0x37, 0x3b, 0xbb, 0xac, 0x49, 0x43, 0xaa, 0xb3, 0xb, 0x50, 0xf, 0x20, 0x9b, 0xfd, 0x96, 0xcd, 0xb6, 0x4c, 0x40, 0xd0, 0x20, 0x2c, 0xac, 0x4b, 0xb3, 0x3, 0xc0, 0x36, 0x80, 0x5b, 0x41, 0x6c, 0x75, 0x5b, 0xb8, 0xed, 0xb0, 0x71, 0xff, 0xbb, 0x83, 0xc6, 0x6c, 0x26, 0x9d, 0x65, 0x74, 0xd2, 0x4f, 0x6e, 0x5c, 0x74, 0xc5, 0xba, 0xce, 0x2e, 0x7b, 0xad, 0xf0, 0x4f, 0xdf, 0x3, 0xf4, 0x9f, 0x38, 0xb7, 0x5b, 0x76, 0xd7, 0x7, 0x2f, 0xcb, 0xda, 0x3, 0xc8, 0x42, 0x94, 0x48, 0x6a, 0x15, 0x9f, 0x24, 0x0, 0xbe, 0x43, 0xe3, 0xfc, 0xc1, 0x49, 0x37, 0x4d, 0xdd, 0xf8, 0x8b, 0x2b, 0xff, 0xde, 0xd9, 0x75, 0xa8, 0x5, 0x76, 0x2b, 0x6, 0xe8, 0x37, 0x7e, 0xf6, 0x18, 0xeb, 0xb6, 0x9c, 0x6, 0x69, 0xf, 0x1a, 0xf3, 0xc1, 0x1f, 0xef, 0xbb, 0xe6, 0xdb, 0xb5, 0xa4, 0x37, 0xf2, 0x9a, 0xa5, 0xdc, 0xb2, 0x69, 0xe5, 0x69, 0xca, 0xec, 0xf8, 0xa5, 0xa4, 0x26, 0x48, 0xf2, 0x29, 0x8c, 0x82, 0x7b, 0x40, 0x3e, 0xae, 0xfc, 0x5f, 0x41, 0x82, 0x4d, 0x37, 0xf5, 0x18, 0xb7, 0xd7, 0xc1, 0xc3, 0x1f, 0xfe, 0xfd, 0x4f, 0x3e, 0xa3, 0x2a, 0x8b, 0xd0, 0xe9, 0x50, 0xf7, 0xc, 0x70, 0xf8, 0x39, 0xb3, 0x3e, 0x9, 0xb9, 0xa7, 0x48, 0xf6, 0x70, 0xb9, 0xd9, 0xd1, 0x90, 0x3b, 0xd2, 0x2b, 0x39, 0x9b, 0x4d, 0xaa, 0x69, 0xfa, 0x1f, 0xef, 0xbb, 0xfa, 0x8e, 0x5a, 0xd2, 0x3f, 0x6c, 0xdc, 0x8f, 0x9f, 0x91, 0xcd, 0x8c, 0x2, 0xe9, 0xe4, 0x43, 0x3, 0x7a, 0xc7, 0x80, 0x4, 0x80, 0xbb, 0x9c, 0x74, 0xd3, 0x77, 0xdd, 0xcc, 0xce, 0x1f, 0xbc, 0xfc, 0xd0, 0xd7, 0x6d, 0x67, 0xe3, 0xa9, 0x5a, 0xa8, 0x5b, 0x19, 0xa0, 0xdf, 0xf8, 0xd9, 0x47, 0x42, 0xee, 0x51, 0x72, 0x5b, 0x3e, 0x6b, 0xdd, 0xcc, 0x69, 0x0, 0xf6, 0xf4, 0x8, 0xe3, 0x75, 0xc3, 0x92, 0x1a, 0x6d, 0x66, 0xd7, 0x8f, 0xfa, 0x8d, 0x9f, 0xf5, 0xe7, 0x97, 0x7e, 0x71, 0xe5, 0xf3, 0x55, 0xe5, 0x31, 0xe1, 0xc6, 0x83, 0xdc, 0x5d, 0x5b, 0x46, 0x3, 0x7e, 0xb3, 0xce, 0x51, 0xbd, 0x74, 0xbb, 0xf0, 0x9b, 0xbb, 0x23, 0xd9, 0x23, 0x59, 0xf7, 0x4d, 0xa8, 0x34, 0xd4, 0x1d, 0x3, 0xf4, 0x3b, 0x67, 0xf6, 0x20, 0xc0, 0x1d, 0x65, 0xb3, 0xcd, 0x67, 0xc9, 0xcd, 0x9c, 0xa, 0x9f, 0x1a, 0xfe, 0xd8, 0x5b, 0xd0, 0x15, 0xb, 0xda, 0xcf, 0x66, 0x9a, 0x7f, 0xd8, 0x7f, 0xc2, 0x9c, 0xb1, 0x1b, 0x17, 0x4d, 0x7f, 0xa7, 0x92, 0x7c, 0xe, 0xff, 0xc2, 0xd, 0x69, 0x58, 0x77, 0x1c, 0x40, 0x17, 0x84, 0x3, 0x54, 0x48, 0x4a, 0xd2, 0x91, 0x75, 0x7, 0x38, 0x4d, 0x7b, 0xef, 0xd6, 0x2c, 0x50, 0x37, 0xc, 0xd0, 0x7f, 0xc2, 0x8d, 0x7, 0x3, 0x1a, 0x65, 0x33, 0xcd, 0x97, 0x58, 0x9b, 0x3d, 0x5, 0x0, 0x40, 0xe6, 0x5a, 0xa6, 0x82, 0x47, 0xbf, 0x13, 0x0, 0x21, 0x82, 0x90, 0xdc, 0xcf, 0xc8, 0x66, 0xbe, 0xd6, 0x6f, 0xfc, 0xac, 0xef, 0xbc, 0xf4, 0x8b, 0x2b, 0x77, 0xb5, 0x35, 0x3f, 0x93, 0x6a, 0xb4, 0x36, 0xb3, 0xe3, 0x7c, 0x1a, 0xe3, 0x8f, 0xe9, 0xe1, 0x21, 0x3f, 0x4, 0xe1, 0xd1, 0x40, 0x80, 0x24, 0xd1, 0x90, 0x10, 0x8c, 0x64, 0xf, 0x31, 0xa9, 0xa6, 0x2e, 0x6, 0x48, 0x2, 0x64, 0xb3, 0xdf, 0xb0, 0xd9, 0xe6, 0x2f, 0x1, 0x41, 0x6b, 0xf7, 0x9, 0x2f, 0x91, 0x1e, 0x23, 0x78, 0x40, 0x9f, 0x8, 0x34, 0x41, 0x90, 0x75, 0x33, 0xbb, 0xfe, 0xaf, 0xd3, 0xd0, 0x7d, 0xd9, 0x61, 0xe3, 0x7e, 0x78, 0xdf, 0x9f, 0x1e, 0xb8, 0x2e, 0x72, 0x3c, 0x1e, 0x30, 0xe9, 0xce, 0x94, 0xdb, 0xb2, 0x7d, 0x1f, 0xd2, 0xf4, 0x0, 0x6c, 0x1a, 0xb2, 0xbd, 0x65, 0xdd, 0xcf, 0x0, 0x30, 0x0, 0x41, 0x42, 0x91, 0xbd, 0x0, 0xb, 0xef, 0x49, 0x52, 0x9e, 0x7a, 0x40, 0x48, 0x7b, 0xee, 0x6, 0x62, 0x54, 0x49, 0xa8, 0x1b, 0x6, 0xb0, 0xd9, 0xcc, 0x39, 0x7e, 0x6b, 0xb, 0xda, 0x5c, 0xa8, 0xeb, 0x2f, 0x4, 0x7a, 0x81, 0x41, 0x3c, 0x3, 0x10, 0x36, 0xbb, 0xeb, 0xc7, 0x4e, 0x43, 0x8f, 0xd7, 0xfa, 0x4f, 0xb8, 0x71, 0x3, 0x68, 0xf6, 0x7, 0xb0, 0x37, 0x81, 0x34, 0x8, 0xca, 0xda, 0x46, 0xb7, 0x65, 0xeb, 0x27, 0x20, 0x3b, 0xd8, 0x75, 0xdd, 0xbe, 0x4, 0xf6, 0x83, 0x74, 0x30, 0x80, 0x40, 0xf0, 0x53, 0x25, 0x43, 0x0, 0xfd, 0xff, 0x22, 0xad, 0xcd, 0xee, 0xac, 0x59, 0x3, 0xe8, 0x7f, 0xee, 0x2d, 0xdd, 0x36, 0xde, 0x73, 0xe9, 0x8e, 0xce, 0xc0, 0x7b, 0xdd, 0x30, 0x0, 0x8d, 0xf3, 0xb2, 0xac, 0x3e, 0xe, 0xc0, 0x20, 0x4e, 0xc, 0xf, 0xc8, 0x1e, 0x3c, 0xf9, 0x8a, 0x3a, 0x49, 0x40, 0xf6, 0x60, 0xeb, 0xb6, 0xfc, 0x1f, 0xd2, 0xac, 0xb3, 0xb6, 0xf9, 0x24, 0x78, 0xad, 0xbb, 0x9b, 0x17, 0xb5, 0x90, 0x46, 0xca, 0x25, 0x46, 0x85, 0x52, 0x8e, 0xcb, 0xa7, 0x30, 0xdc, 0x4a, 0xa0, 0x21, 0xe8, 0x7d, 0xed, 0x36, 0x6f, 0xad, 0x89, 0x1, 0x8e, 0x38, 0x77, 0x6e, 0x5f, 0xeb, 0xb6, 0x9c, 0xde, 0x7f, 0xc2, 0x9c, 0xe7, 0x36, 0x2e, 0x9a, 0xbe, 0xb6, 0xc3, 0xf1, 0xde, 0xd1, 0x19, 0xc6, 0x41, 0xff, 0x9, 0xb3, 0xbf, 0x67, 0x33, 0xcd, 0x5f, 0x96, 0x6c, 0xcf, 0x70, 0xab, 0x8f, 0xa3, 0x43, 0x41, 0xb8, 0x4, 0x90, 0x16, 0x80, 0x41, 0xd8, 0x78, 0x43, 0x6, 0xef, 0x8a, 0xf4, 0x7a, 0x9, 0xf2, 0xfa, 0x7d, 0xff, 0xb1, 0x40, 0x0, 0x60, 0x51, 0xde, 0xc5, 0xf9, 0x11, 0x39, 0x23, 0x51, 0xd6, 0x69, 0xdc, 0xf3, 0x18, 0xc9, 0xbe, 0x61, 0x9c, 0x86, 0xad, 0x1b, 0xee, 0x9e, 0xba, 0xb5, 0xad, 0xf5, 0x3d, 0xe2, 0xbc, 0x5b, 0xbb, 0xc1, 0xba, 0x9f, 0xc8, 0x66, 0xb6, 0x2f, 0x86, 0x74, 0x28, 0x80, 0xb7, 0x4d, 0xba, 0xdb, 0xb9, 0xc6, 0x38, 0x4b, 0x37, 0xdc, 0x73, 0x59, 0x4b, 0x47, 0xe1, 0xbd, 0x6e, 0x18, 0xa0, 0xdf, 0x84, 0x39, 0xa7, 0x2b, 0xb3, 0x73, 0x2e, 0xa0, 0x3, 0x81, 0x60, 0x9c, 0x6f, 0x73, 0xb7, 0x1c, 0xc8, 0xb, 0x20, 0xf3, 0xad, 0x3a, 0xf4, 0x9c, 0x78, 0x3d, 0x95, 0x37, 0x13, 0x92, 0xc6, 0xf9, 0xb, 0x9d, 0xf4, 0x22, 0x63, 0x52, 0xb7, 0x3, 0x78, 0x3d, 0xdb, 0xbc, 0x6d, 0xe7, 0x9f, 0x1e, 0xf8, 0x6a, 0xac, 0x6d, 0xa0, 0xff, 0x84, 0x39, 0xfb, 0x4b, 0xee, 0x14, 0x9b, 0x69, 0xfe, 0x41, 0x90, 0x9a, 0x2f, 0x5b, 0xc0, 0xa4, 0x9b, 0xfe, 0xcd, 0x18, 0xe7, 0x96, 0xd, 0xf7, 0x4e, 0x7f, 0xb7, 0x23, 0xf0, 0x5e, 0x37, 0xc, 0xd0, 0xff, 0xdc, 0x9b, 0x3f, 0x65, 0x5b, 0xb6, 0x3f, 0x21, 0xd9, 0x4f, 0x41, 0x8, 0x24, 0xed, 0xb6, 0x95, 0x56, 0x65, 0xde, 0x25, 0x55, 0x53, 0x3f, 0xad, 0x9c, 0x26, 0xe0, 0x3f, 0x14, 0xf4, 0x1e, 0x26, 0x75, 0x3f, 0x9d, 0x86, 0x9f, 0xd2, 0x49, 0xaf, 0xec, 0xd1, 0xfb, 0x88, 0x6d, 0xc5, 0x56, 0xc2, 0xfe, 0x13, 0x6f, 0x3a, 0xcc, 0x66, 0x9b, 0xe7, 0x40, 0xee, 0x18, 0x0, 0x5e, 0xaf, 0x15, 0x24, 0x3, 0x8, 0x24, 0x8d, 0xd3, 0x70, 0x13, 0x4c, 0xea, 0xfb, 0x1b, 0xef, 0x9d, 0xf6, 0x6a, 0x7b, 0xe3, 0xdd, 0xb4, 0x77, 0x6, 0x6d, 0x85, 0x8d, 0xf7, 0x5c, 0xf6, 0xa, 0x69, 0x9a, 0x3d, 0x51, 0x3b, 0xc0, 0x26, 0xfd, 0xb, 0xa5, 0x9, 0x58, 0xaa, 0xa3, 0x28, 0xf7, 0x6d, 0x25, 0xe0, 0xa7, 0x95, 0x27, 0x3e, 0x94, 0xcf, 0xc0, 0xd3, 0x26, 0xad, 0x9b, 0x3d, 0xdb, 0x6d, 0xd9, 0xf1, 0x8c, 0x6d, 0xd9, 0xfe, 0xdc, 0x96, 0xd7, 0x57, 0x9f, 0x11, 0xfe, 0xfc, 0x88, 0x73, 0xe7, 0x9e, 0xec, 0xb6, 0xec, 0xd8, 0x28, 0xeb, 0x8e, 0xf1, 0xbe, 0xf5, 0xf1, 0x2f, 0x88, 0xa0, 0xcf, 0x48, 0xb4, 0xd6, 0x6d, 0x99, 0x66, 0xb3, 0x2d, 0xf3, 0xfb, 0x4f, 0x9c, 0x7b, 0x5c, 0x7b, 0xe3, 0xbd, 0x6e, 0x7a, 0x0, 0x0, 0xe8, 0x77, 0xce, 0xcf, 0x9e, 0xb3, 0x6e, 0xe6, 0x78, 0x20, 0x5a, 0xfa, 0xaf, 0x3f, 0x8, 0x86, 0x81, 0x7c, 0x61, 0xfd, 0x91, 0x41, 0x64, 0xa0, 0x5a, 0x38, 0x2b, 0x4c, 0xba, 0xf1, 0x3b, 0x4, 0x7a, 0x66, 0x5b, 0x76, 0x2c, 0xf4, 0xf8, 0xbb, 0xd5, 0xb0, 0x54, 0xd0, 0x4f, 0x5, 0x6a, 0x26, 0x8d, 0x79, 0x8d, 0x4e, 0xd3, 0xbf, 0xbd, 0xb4, 0x68, 0xda, 0x5d, 0xed, 0x55, 0x3, 0xa7, 0xf6, 0x24, 0x92, 0x83, 0x8f, 0xf, 0x1c, 0x9b, 0x2, 0x34, 0x9c, 0x40, 0x8f, 0x78, 0xcb, 0x4c, 0x3d, 0x41, 0xd0, 0x45, 0xf9, 0xe0, 0xcb, 0x2d, 0xbe, 0xd5, 0x92, 0x14, 0x24, 0xa2, 0xb7, 0x6c, 0x76, 0x82, 0xac, 0x7b, 0x16, 0x29, 0x27, 0x50, 0x21, 0x1, 0x85, 0xba, 0xba, 0x5c, 0x37, 0xe2, 0xdb, 0xbb, 0x72, 0x36, 0xb0, 0xbd, 0x61, 0xdd, 0x13, 0xf7, 0x3f, 0xf2, 0xec, 0x96, 0x77, 0xd6, 0x2f, 0xfe, 0x5d, 0x7b, 0xd4, 0xa0, 0x6e, 0x86, 0x0, 0xaf, 0x34, 0xce, 0x12, 0x0, 0xef, 0x7b, 0xf7, 0x86, 0xf9, 0x21, 0x60, 0x37, 0xb9, 0x8c, 0xf1, 0x94, 0xc3, 0x80, 0x71, 0x69, 0x40, 0xd2, 0x90, 0x6c, 0x0, 0xd4, 0x0, 0x18, 0x79, 0x17, 0x8, 0x18, 0x45, 0xa4, 0xe1, 0x31, 0x81, 0x31, 0xfe, 0x7b, 0x3, 0x40, 0xfb, 0x65, 0x33, 0xbb, 0xbe, 0xde, 0x6f, 0xc2, 0x9c, 0xaf, 0xb4, 0x7, 0xca, 0xeb, 0xa6, 0x7, 0xe8, 0x3f, 0x71, 0xee, 0x4, 0x4f, 0x38, 0x52, 0x3f, 0xf8, 0xb6, 0x9e, 0xd0, 0xe8, 0xba, 0xfb, 0x5c, 0x44, 0xae, 0xfd, 0xe7, 0xee, 0x1, 0xbf, 0x67, 0x80, 0x7f, 0x11, 0xa1, 0x77, 0x45, 0xdf, 0x93, 0xa1, 0x74, 0x82, 0x1e, 0x61, 0x4f, 0xca, 0xe, 0xea, 0x35, 0xe8, 0x2c, 0xe7, 0x9d, 0xf5, 0x8b, 0x97, 0x26, 0x89, 0xf7, 0xba, 0x30, 0x4, 0xf5, 0x9f, 0x78, 0xd3, 0x2c, 0x9b, 0xdd, 0x75, 0x36, 0xa0, 0x3e, 0xde, 0x18, 0x69, 0x24, 0x28, 0x6c, 0x0, 0xde, 0x1d, 0x81, 0x31, 0xf7, 0x6d, 0x6, 0x6f, 0x14, 0xf4, 0x70, 0x21, 0xb0, 0x1b, 0xc8, 0xee, 0x49, 0x17, 0xb2, 0xd3, 0x19, 0xe0, 0xf0, 0x73, 0x66, 0x3d, 0xad, 0x6c, 0xcb, 0x48, 0x0, 0xdd, 0xbd, 0x39, 0x1e, 0xdf, 0x74, 0x53, 0xef, 0xc3, 0x7f, 0x87, 0x40, 0xce, 0xe4, 0xd, 0x1a, 0x67, 0xb5, 0x71, 0xd2, 0xd7, 0x27, 0x9d, 0x43, 0x62, 0xc, 0x70, 0xc4, 0xb9, 0x73, 0x7f, 0x24, 0x61, 0x1b, 0x8d, 0xf3, 0xd3, 0xd, 0x77, 0x4f, 0x7d, 0xbf, 0x5c, 0xfc, 0x81, 0x93, 0xee, 0xd8, 0x23, 0xdb, 0xb2, 0xe3, 0x31, 0xd9, 0xec, 0x9, 0x5e, 0x3f, 0x97, 0x13, 0x80, 0xbb, 0x88, 0xef, 0x83, 0x6f, 0xc0, 0x24, 0xe9, 0xbc, 0x63, 0x9c, 0xf4, 0xe2, 0x75, 0x3f, 0xbf, 0x38, 0x71, 0xb, 0x61, 0x22, 0x98, 0x3e, 0xe2, 0xbc, 0x5b, 0x47, 0xd8, 0xcc, 0xce, 0x7, 0x25, 0x75, 0xa3, 0x71, 0xd6, 0x80, 0xe6, 0x75, 0xd2, 0xfc, 0x99, 0xc6, 0x99, 0xb7, 0xe1, 0xee, 0xa9, 0x7f, 0x2e, 0x8e, 0xdf, 0xff, 0xdc, 0x5b, 0xe, 0x95, 0xdb, 0x72, 0x87, 0x6c, 0x76, 0x14, 0xe9, 0xab, 0xc2, 0x5e, 0x4d, 0xe1, 0x49, 0xc7, 0x51, 0xc5, 0x8c, 0x33, 0xb9, 0x87, 0xe7, 0x85, 0x54, 0xe2, 0x9b, 0x62, 0x3, 0x6f, 0xb9, 0xb4, 0x63, 0xb5, 0xb4, 0x88, 0xf0, 0xa8, 0xef, 0x2a, 0x29, 0x6f, 0xeb, 0x6f, 0x72, 0xbe, 0x67, 0x0, 0x41, 0xe7, 0x91, 0x74, 0xd3, 0x9e, 0xe3, 0xd7, 0x2e, 0x98, 0xb2, 0xb3, 0x1a, 0xfa, 0x94, 0x82, 0x9a, 0x19, 0xe0, 0x88, 0xf3, 0xe7, 0xf5, 0x50, 0x76, 0xc7, 0xc3, 0xb2, 0xee, 0x71, 0x80, 0x42, 0x5a, 0x85, 0xd9, 0x42, 0x63, 0xd6, 0x80, 0xce, 0x4a, 0x1a, 0xe7, 0x77, 0x26, 0x95, 0x7e, 0x74, 0xdd, 0x82, 0x29, 0x1f, 0x1c, 0x71, 0xfe, 0x6d, 0x43, 0x6c, 0x66, 0xd7, 0x4d, 0x90, 0x7b, 0x54, 0xa8, 0x18, 0xc2, 0x6e, 0x3e, 0xe0, 0x27, 0xa, 0xca, 0xd9, 0x1c, 0x9, 0x3a, 0xaf, 0x9a, 0x54, 0xc3, 0xbf, 0x6f, 0xb8, 0xfb, 0xd2, 0x85, 0xed, 0x91, 0x55, 0xcd, 0x43, 0x80, 0xdc, 0xe6, 0x1f, 0xcb, 0xba, 0xbe, 0xf1, 0xc6, 0x84, 0xed, 0xf0, 0x7b, 0xc9, 0xba, 0xa3, 0x0, 0x77, 0x94, 0xac, 0x73, 0x86, 0xac, 0x3b, 0xae, 0xff, 0xc4, 0xb9, 0x7f, 0x57, 0xb6, 0x79, 0x38, 0x64, 0x8f, 0xf2, 0x6c, 0xf4, 0xb9, 0x7e, 0xdf, 0x17, 0xf8, 0xca, 0xb5, 0xe0, 0xb6, 0x98, 0xf5, 0x2b, 0x69, 0x95, 0xc5, 0x3e, 0x9f, 0xe1, 0xfb, 0x72, 0x71, 0xdb, 0x52, 0xd6, 0xf0, 0x77, 0x71, 0xe5, 0x2c, 0xec, 0x11, 0x3c, 0xe9, 0x97, 0xb9, 0xf9, 0x26, 0x1a, 0xe7, 0xa9, 0xc6, 0x6e, 0x3d, 0xef, 0xa9, 0x95, 0x4e, 0x71, 0x50, 0x53, 0xab, 0x1b, 0x70, 0xfe, 0x6d, 0x5f, 0xb0, 0x99, 0x9d, 0xbf, 0x90, 0x37, 0x8b, 0x9f, 0xa3, 0x62, 0x48, 0x82, 0x97, 0x82, 0x3c, 0xa, 0x3c, 0xee, 0x68, 0x25, 0x85, 0xad, 0xfd, 0x5d, 0xad, 0x3f, 0x4, 0x9e, 0x25, 0x90, 0x34, 0x4e, 0xea, 0x45, 0x3a, 0xd, 0xd7, 0xad, 0xbf, 0xeb, 0xe2, 0xe7, 0xda, 0x2b, 0xaf, 0xaa, 0x7b, 0x80, 0x81, 0x93, 0xee, 0x38, 0xd8, 0xcd, 0xec, 0xfc, 0xbe, 0x2, 0xa3, 0x95, 0xef, 0x58, 0xc5, 0x90, 0xff, 0x4e, 0xce, 0x98, 0x27, 0x8, 0x26, 0x4f, 0x64, 0x8f, 0xf8, 0x7e, 0xb7, 0x5f, 0xcd, 0x5c, 0x5d, 0x12, 0xf3, 0x7b, 0xd5, 0xb0, 0x5e, 0xa9, 0x6f, 0x8a, 0x1c, 0xc7, 0x2b, 0xae, 0x47, 0xe1, 0x77, 0xde, 0x9d, 0x71, 0xee, 0x69, 0x4f, 0xe2, 0x3, 0x55, 0x5a, 0x2, 0x7, 0x4c, 0x9a, 0xd7, 0x60, 0x6d, 0xf6, 0x5a, 0x59, 0xfb, 0x69, 0x7f, 0xf2, 0xc6, 0x9b, 0x5d, 0x2f, 0x12, 0xdf, 0x73, 0xcf, 0x45, 0xe3, 0xbb, 0x37, 0xe7, 0x91, 0x73, 0xac, 0xa9, 0x1c, 0x2a, 0xfc, 0x46, 0x2a, 0xe8, 0x9f, 0x15, 0xfc, 0x13, 0x50, 0xe0, 0x3e, 0x20, 0x95, 0x49, 0xa8, 0xd4, 0xc4, 0x12, 0x8b, 0x7e, 0x2b, 0xad, 0x7, 0x8b, 0x5f, 0x30, 0x5e, 0x8e, 0x4c, 0x10, 0x2a, 0x66, 0x80, 0x81, 0x17, 0xce, 0x77, 0x20, 0x3b, 0xda, 0x66, 0x5b, 0xae, 0xcd, 0x9b, 0xc1, 0xc3, 0x53, 0x76, 0x9d, 0x7b, 0x29, 0x34, 0x43, 0xe7, 0xdf, 0xfb, 0x73, 0xed, 0x1e, 0x81, 0x25, 0xd0, 0x37, 0x34, 0xe4, 0xae, 0xe0, 0x1d, 0xa3, 0x6d, 0x73, 0xf2, 0xd3, 0xca, 0xdd, 0xb7, 0xff, 0xe5, 0x33, 0xa9, 0xdc, 0x2f, 0xc, 0x98, 0x74, 0xc7, 0xf1, 0xed, 0xc9, 0x0, 0x15, 0xb7, 0xbf, 0x41, 0x17, 0xce, 0xef, 0x93, 0x6d, 0xd9, 0xf9, 0x0, 0xac, 0x3b, 0xd2, 0xeb, 0xc0, 0xe3, 0x54, 0xb7, 0x4a, 0x8a, 0x50, 0x4a, 0x65, 0x2, 0x4a, 0xb, 0x5c, 0x39, 0xc8, 0x77, 0xa2, 0xa, 0xd4, 0xa7, 0x82, 0xb4, 0x3e, 0x0, 0xf9, 0x3e, 0x80, 0x6d, 0x0, 0x76, 0x92, 0xdc, 0x5, 0xd2, 0x42, 0x8, 0xe4, 0x91, 0x14, 0x80, 0x26, 0x9, 0xdd, 0x20, 0xbb, 0xf, 0xa0, 0x5e, 0x90, 0x6f, 0x2a, 0x67, 0x4c, 0x1e, 0x35, 0x6b, 0x2e, 0x11, 0xf5, 0x93, 0xe7, 0x13, 0x0, 0xc2, 0x42, 0x32, 0x34, 0xce, 0x93, 0x26, 0xd5, 0x78, 0xd9, 0xba, 0x85, 0x17, 0xbd, 0x5a, 0x5b, 0x5e, 0xa5, 0x4b, 0xd0, 0x26, 0x18, 0x7c, 0xc5, 0x33, 0xcc, 0x7e, 0xf8, 0xea, 0x19, 0x36, 0xb3, 0xf3, 0x21, 0x0, 0x16, 0x81, 0x12, 0x1f, 0xae, 0x8a, 0xe2, 0x13, 0x2d, 0x18, 0xf2, 0x22, 0x4, 0xe7, 0x3c, 0xef, 0x7, 0xe6, 0xaf, 0xfc, 0x87, 0xad, 0xc8, 0xee, 0x8b, 0x1d, 0xa, 0xd6, 0x8a, 0x84, 0xe6, 0x66, 0xfd, 0x98, 0x2d, 0x34, 0xce, 0x3f, 0x24, 0xbc, 0x4d, 0x9a, 0x4d, 0x30, 0x66, 0x1d, 0xc0, 0x97, 0x48, 0xfe, 0x15, 0xe0, 0x3b, 0x20, 0xdf, 0x23, 0xd4, 0xec, 0x5a, 0x65, 0xd2, 0xe9, 0x86, 0x46, 0xeb, 0x66, 0xba, 0x1, 0xd8, 0xd7, 0x5a, 0xdb, 0x7, 0xd2, 0x0, 0xc9, 0x8e, 0x24, 0x74, 0xb0, 0xa4, 0x8f, 0x1, 0x3a, 0x0, 0xb2, 0xfb, 0x86, 0xab, 0xc2, 0x90, 0xcf, 0x7a, 0x1, 0x33, 0xa8, 0x75, 0x7d, 0xa, 0xe4, 0xfd, 0x8, 0x33, 0x40, 0x41, 0x13, 0xa, 0x3b, 0xc6, 0x7a, 0x35, 0xb2, 0x74, 0x1a, 0xe6, 0x34, 0xef, 0xdc, 0x7e, 0xd5, 0x5f, 0x1e, 0xb8, 0x3a, 0xf1, 0x15, 0x48, 0x15, 0x9, 0x81, 0xee, 0x96, 0xbf, 0xd, 0x92, 0xdb, 0xf2, 0x7d, 0x80, 0xa0, 0x6f, 0xb0, 0xf7, 0xb0, 0x9f, 0x9b, 0xb7, 0x40, 0xde, 0x23, 0xab, 0x88, 0x82, 0xb9, 0xa7, 0xd0, 0xff, 0x1c, 0xc5, 0x43, 0x2c, 0xc3, 0xa8, 0xc6, 0xdb, 0x2a, 0x2c, 0xb0, 0x93, 0x4, 0x62, 0x86, 0xfc, 0x29, 0x78, 0x80, 0x7c, 0xf, 0x30, 0x9b, 0x4, 0xb3, 0x96, 0x4e, 0x6a, 0x71, 0x3a, 0xd5, 0xf0, 0xe0, 0xea, 0x3b, 0x27, 0x95, 0x33, 0xa0, 0xb4, 0x0, 0xd8, 0xa, 0xe0, 0x2d, 0x0, 0x1b, 0x1, 0x3c, 0x15, 0xbc, 0x18, 0x30, 0xe9, 0xce, 0x7e, 0xb2, 0x99, 0x89, 0x80, 0x8e, 0x83, 0xec, 0xa1, 0x92, 0x3d, 0x8, 0x42, 0x63, 0xa0, 0xc1, 0x7a, 0x79, 0x2a, 0x50, 0x79, 0x42, 0x66, 0xcc, 0xbc, 0xab, 0x40, 0x58, 0xd, 0xca, 0xd7, 0x3b, 0xa8, 0x17, 0xfc, 0x70, 0xbf, 0x4a, 0xfe, 0xa, 0x88, 0xc0, 0x30, 0x26, 0xc1, 0x48, 0xee, 0x99, 0x4d, 0xdd, 0xf7, 0x5a, 0xe, 0xe0, 0xf6, 0xa4, 0x19, 0xa0, 0xa2, 0x1e, 0x60, 0xe0, 0x5, 0x77, 0x9e, 0xea, 0x66, 0x76, 0x3e, 0x26, 0xc9, 0x84, 0xb1, 0xdf, 0x91, 0x10, 0xb2, 0x15, 0xcb, 0xd7, 0x32, 0x7c, 0xe, 0xe0, 0xfb, 0x24, 0xdf, 0xa2, 0x49, 0xdd, 0x6c, 0x1c, 0x67, 0xf6, 0xda, 0x5, 0x53, 0xda, 0xbc, 0x48, 0xa4, 0xad, 0x30, 0x60, 0xd2, 0xbc, 0x43, 0x21, 0xf7, 0xbb, 0x92, 0x1d, 0x29, 0xeb, 0x7e, 0x2, 0x52, 0x93, 0xbf, 0x4c, 0x2d, 0xd4, 0x10, 0x12, 0xad, 0x6b, 0xde, 0xa7, 0x91, 0xce, 0x12, 0xa6, 0xf6, 0x38, 0x75, 0xfd, 0xc2, 0xb, 0x9a, 0x93, 0xcc, 0xa3, 0x32, 0x6, 0x98, 0x7c, 0x57, 0xa3, 0xcd, 0x36, 0x9f, 0x23, 0xb7, 0xe5, 0x4e, 0x40, 0x4e, 0xe0, 0x80, 0xd9, 0x51, 0xf6, 0xfb, 0x80, 0xf8, 0x61, 0x84, 0x4b, 0xd8, 0x49, 0x60, 0x87, 0x49, 0x37, 0x7e, 0x7b, 0xdd, 0xc2, 0x8b, 0x6e, 0x6c, 0xf7, 0x42, 0x0, 0x18, 0x30, 0xf9, 0xee, 0x94, 0x32, 0xdb, 0xe7, 0xca, 0xba, 0xa7, 0x1, 0xda, 0x3f, 0xb7, 0x78, 0x25, 0xef, 0x26, 0x98, 0x38, 0x42, 0x24, 0xb9, 0x34, 0xa9, 0x7b, 0x36, 0xdc, 0x3d, 0xf5, 0x82, 0x24, 0xd3, 0xad, 0x5c, 0x8, 0x9c, 0xbc, 0x70, 0xf, 0xeb, 0x66, 0x2f, 0xb3, 0xd9, 0xe6, 0x19, 0xf0, 0xc7, 0x5b, 0x4f, 0x14, 0xc8, 0x69, 0x57, 0x25, 0xd2, 0x2c, 0x67, 0x15, 0xb, 0xc7, 0x29, 0xf2, 0xe5, 0xf7, 0xa7, 0x46, 0xe1, 0x59, 0x19, 0xe1, 0x79, 0xd2, 0x3a, 0x5b, 0x61, 0x9c, 0xdb, 0x68, 0x52, 0x5f, 0x5f, 0xbf, 0x70, 0x72, 0x87, 0xb9, 0x52, 0x7, 0x30, 0x70, 0xf2, 0xcf, 0xbb, 0xb9, 0x2d, 0xdb, 0x97, 0x41, 0xb6, 0x2f, 0xc0, 0x3d, 0x2, 0xe7, 0x64, 0x32, 0xf0, 0x48, 0xe, 0x44, 0xa4, 0x52, 0xe, 0xe6, 0xc5, 0x78, 0x88, 0x14, 0x72, 0x25, 0x89, 0xa0, 0x59, 0xed, 0xa4, 0x1a, 0x3f, 0xb7, 0x6e, 0xe1, 0x94, 0xb7, 0xc2, 0x2f, 0x47, 0x5e, 0xb3, 0x94, 0x3b, 0xdf, 0x7b, 0xc5, 0xd0, 0x69, 0xa0, 0xcd, 0x6c, 0x27, 0x4d, 0x9a, 0x0, 0xdd, 0x75, 0xb, 0x2e, 0x70, 0xcb, 0xd5, 0xa1, 0x2a, 0x2e, 0x1d, 0x34, 0xf9, 0xe7, 0x7b, 0x58, 0xb7, 0xe5, 0xdb, 0x36, 0xdb, 0xf2, 0x75, 0x2, 0x26, 0x34, 0xf0, 0x33, 0x69, 0x57, 0xae, 0x70, 0x97, 0xf, 0x8f, 0xf8, 0x2, 0x0, 0x63, 0xcc, 0x66, 0xa6, 0x1a, 0xc7, 0xae, 0x5b, 0x30, 0x39, 0x51, 0x7, 0x89, 0x6a, 0x60, 0xc0, 0xa4, 0x79, 0xd7, 0xd9, 0x6c, 0xf3, 0x37, 0x0, 0xed, 0xcb, 0xb0, 0x47, 0x50, 0x72, 0x26, 0xab, 0x80, 0xe9, 0x41, 0x93, 0x7a, 0x7e, 0xc3, 0xdd, 0x53, 0x8f, 0x1f, 0x34, 0xe5, 0xee, 0x46, 0x9b, 0x6d, 0xa6, 0x71, 0x1a, 0x9a, 0x24, 0xb7, 0x2f, 0xa4, 0x8f, 0x9, 0xea, 0x49, 0xa0, 0x87, 0xa4, 0x3, 0x69, 0x9c, 0x17, 0x20, 0xf7, 0xf9, 0x75, 0xb, 0x2f, 0xca, 0x94, 0x4a, 0xbc, 0xea, 0xc2, 0xd, 0xbc, 0x70, 0x61, 0x83, 0x6c, 0xf6, 0xdf, 0xe5, 0xb6, 0x7c, 0x13, 0x64, 0xb0, 0x20, 0x23, 0xbf, 0xd8, 0x22, 0x49, 0x8, 0x98, 0x4a, 0x82, 0xa4, 0xac, 0x71, 0x52, 0xcf, 0x3b, 0xd, 0xdd, 0xce, 0x5e, 0x33, 0xef, 0xbc, 0xf, 0x92, 0xcf, 0xac, 0x5a, 0x7c, 0x2c, 0x18, 0x63, 0xb3, 0xbb, 0xe6, 0xc9, 0xda, 0x83, 0x3d, 0x43, 0x17, 0x3, 0x49, 0xbe, 0xf6, 0x6, 0x91, 0x5f, 0xdc, 0x2, 0x1, 0xbb, 0x48, 0xf3, 0x1a, 0xa4, 0xde, 0x80, 0x7a, 0x2, 0x28, 0xd2, 0x81, 0x82, 0x7b, 0xae, 0x34, 0xa9, 0xc6, 0xeb, 0xd6, 0x2d, 0x9c, 0xfc, 0x54, 0xa9, 0xa4, 0xab, 0xf6, 0x9, 0x5c, 0xb7, 0xe0, 0x82, 0x16, 0xa7, 0xb1, 0xfb, 0x7f, 0x99, 0x54, 0xe3, 0x75, 0x4, 0xb2, 0x8, 0x69, 0x33, 0x89, 0x9b, 0x45, 0x7c, 0x24, 0x90, 0xcc, 0x1a, 0x27, 0xfd, 0xf0, 0xfa, 0xbb, 0x2e, 0x19, 0x53, 0x4f, 0xc4, 0xf7, 0xf0, 0x71, 0xe1, 0xd3, 0x26, 0xd5, 0x78, 0xa, 0xe9, 0x6c, 0x40, 0x41, 0xd9, 0x6b, 0x77, 0x6d, 0x43, 0xe1, 0x6f, 0x23, 0x64, 0xf, 0x3, 0xb4, 0x17, 0x8a, 0xde, 0x15, 0xde, 0x6b, 0x88, 0xa0, 0x7f, 0x29, 0x57, 0xee, 0x9a, 0x9c, 0x42, 0xd7, 0xdc, 0x3e, 0x3e, 0xeb, 0x34, 0x74, 0x9f, 0x69, 0x52, 0x4d, 0x53, 0x4, 0xbe, 0xdf, 0x76, 0x8b, 0x60, 0x18, 0x4a, 0x85, 0x31, 0xc7, 0xd6, 0x5e, 0xbf, 0x9f, 0x7a, 0x72, 0xfd, 0x5d, 0x17, 0x9f, 0x95, 0x18, 0xd5, 0x12, 0x86, 0x75, 0xb, 0x26, 0xff, 0xc9, 0x34, 0x34, 0x9d, 0x49, 0xe3, 0x2c, 0xf7, 0x2d, 0x8e, 0xfe, 0xf0, 0x15, 0x26, 0x63, 0x31, 0x59, 0x4b, 0x85, 0x79, 0xcf, 0x7e, 0x7, 0x2b, 0xd2, 0xc8, 0xf3, 0x31, 0xd, 0x2e, 0x8a, 0x34, 0xc1, 0xd4, 0x51, 0x51, 0x47, 0x6c, 0xc, 0x81, 0x4f, 0x7e, 0xea, 0xc2, 0x87, 0x4a, 0xf6, 0x3e, 0x35, 0x7b, 0x5, 0xaf, 0xbe, 0xfd, 0x9c, 0x2c, 0x53, 0xd, 0xf7, 0x93, 0xdc, 0x51, 0x64, 0xa, 0x29, 0x1, 0x51, 0xcc, 0x50, 0x18, 0x26, 0xbf, 0x1f, 0x83, 0xe7, 0x2b, 0x0, 0xe3, 0xa4, 0x9f, 0x6c, 0x49, 0xf7, 0x3a, 0xbd, 0xdd, 0xa8, 0x97, 0x10, 0xac, 0x9b, 0x7f, 0xc1, 0x2b, 0x26, 0xd5, 0x38, 0x85, 0xc6, 0x59, 0x82, 0xfc, 0xec, 0x28, 0xa2, 0x99, 0x1c, 0x65, 0xc2, 0xf2, 0xcf, 0xcc, 0xdb, 0xa9, 0xc3, 0xef, 0x99, 0x7f, 0x95, 0x8b, 0x27, 0x4f, 0x39, 0x12, 0xac, 0xcd, 0x9e, 0xd7, 0x9d, 0x1f, 0x4e, 0x2c, 0x55, 0xde, 0x44, 0xdc, 0xc2, 0x6d, 0x36, 0xd3, 0xf, 0x40, 0xda, 0xa3, 0x17, 0x13, 0x71, 0xe7, 0x26, 0xd, 0x5, 0x58, 0x6f, 0x4a, 0x3c, 0xfd, 0xa8, 0x93, 0x6e, 0x1a, 0xff, 0xf2, 0xbc, 0xd3, 0x77, 0x8b, 0xcd, 0x98, 0xd6, 0xce, 0xbf, 0x60, 0x23, 0x4c, 0x6a, 0x16, 0xe9, 0xbc, 0xec, 0x4d, 0x31, 0x18, 0xc9, 0x53, 0x97, 0x6a, 0xc6, 0x4b, 0x1b, 0x2e, 0x6, 0xb3, 0x6d, 0x90, 0xfa, 0xca, 0xaa, 0x7f, 0xfb, 0x33, 0x80, 0x9b, 0x99, 0x1, 0x70, 0xdf, 0x9a, 0x13, 0x2a, 0x4, 0x1, 0x34, 0x34, 0xce, 0x5a, 0x9a, 0xf4, 0xd, 0x6b, 0xe6, 0x9d, 0xf7, 0x61, 0x7b, 0x11, 0xac, 0x3d, 0x60, 0xfd, 0xc2, 0xc9, 0xf7, 0xc0, 0xa4, 0x6e, 0x7, 0xb9, 0xcd, 0xb7, 0x57, 0x75, 0x98, 0xd1, 0x2c, 0xbc, 0x48, 0x56, 0x50, 0x8f, 0x52, 0x71, 0x6b, 0x66, 0x80, 0x23, 0xa7, 0xdc, 0xb5, 0x17, 0x60, 0x87, 0x92, 0x48, 0xe5, 0xf5, 0xde, 0x44, 0xc4, 0x1e, 0x92, 0xdc, 0x42, 0x93, 0x5a, 0xb0, 0x76, 0xfe, 0xa4, 0xc7, 0x3a, 0xa, 0x79, 0x49, 0x82, 0x31, 0xce, 0x2c, 0x9a, 0xd4, 0xbd, 0xbe, 0x8d, 0x3a, 0x98, 0x25, 0x69, 0xf7, 0x19, 0xc5, 0x80, 0xf8, 0xbe, 0xf6, 0x7c, 0xe4, 0xc0, 0xc9, 0xb, 0x87, 0xc4, 0x96, 0xb1, 0x96, 0xa, 0x1e, 0x7d, 0xed, 0xef, 0x8, 0x72, 0x38, 0x80, 0xb4, 0x97, 0xa1, 0xd7, 0xcd, 0xd5, 0xd2, 0x83, 0xf9, 0x5, 0xf7, 0x2a, 0xe0, 0xa4, 0x1e, 0x0, 0x4d, 0xe2, 0xf6, 0xef, 0x8e, 0x82, 0xb5, 0xf3, 0x27, 0x6d, 0x31, 0x4e, 0xfa, 0x36, 0x18, 0x67, 0x29, 0xfc, 0x3e, 0xd9, 0x9f, 0xe9, 0xab, 0xc, 0x27, 0x11, 0xf7, 0x88, 0x9, 0xf7, 0x47, 0x1, 0xff, 0x3f, 0x1, 0x6b, 0x4f, 0x80, 0x74, 0x76, 0x5c, 0x19, 0x6b, 0x62, 0x80, 0x6d, 0xff, 0xd8, 0x48, 0xeb, 0x66, 0xcf, 0x25, 0x4d, 0xca, 0x2f, 0x51, 0xcd, 0xeb, 0x79, 0x7c, 0x75, 0x9f, 0xa0, 0x79, 0x15, 0x30, 0xf7, 0xaf, 0x9b, 0x3f, 0xa9, 0xa2, 0xdd, 0xbf, 0xea, 0xd, 0xd6, 0xde, 0x79, 0xfe, 0xb, 0x34, 0xa9, 0xc5, 0x0, 0x0, 0x1a, 0x11, 0xac, 0x58, 0x31, 0x64, 0xc4, 0x3d, 0x63, 0xc2, 0x8b, 0xf0, 0x28, 0x92, 0xd, 0x24, 0xfa, 0xc6, 0x95, 0xaf, 0x26, 0x6, 0x58, 0x7f, 0xd7, 0xc5, 0x56, 0x6e, 0x76, 0x2c, 0xa0, 0x34, 0x69, 0xc2, 0x5b, 0xaf, 0x54, 0x7e, 0x91, 0x81, 0xe4, 0xef, 0xf5, 0x22, 0xc6, 0x59, 0x44, 0x63, 0x1e, 0xef, 0x6c, 0x2, 0x26, 0x1, 0xa4, 0x59, 0x4c, 0x93, 0x7a, 0x12, 0xfe, 0x7e, 0x46, 0x28, 0x35, 0xc, 0xb0, 0xb6, 0x6, 0x54, 0x98, 0x16, 0x82, 0x6e, 0xb5, 0xf1, 0xd3, 0xe3, 0xe7, 0x46, 0xd2, 0xba, 0x26, 0x6, 0x18, 0x74, 0xd1, 0x3d, 0x7d, 0x41, 0xf4, 0xf6, 0xc4, 0x76, 0x28, 0xa7, 0xf2, 0x56, 0x39, 0xec, 0xfb, 0x92, 0x3f, 0x49, 0xf3, 0x16, 0x8d, 0xf3, 0xd4, 0xda, 0x3b, 0xcf, 0xdf, 0xde, 0xd9, 0xc4, 0x4b, 0x2, 0xd6, 0xde, 0x79, 0xfe, 0x5a, 0x3a, 0xa9, 0xf9, 0x5e, 0x25, 0x73, 0xe, 0x1f, 0x25, 0xc4, 0x9f, 0xda, 0x2f, 0xcf, 0xaf, 0xc4, 0x50, 0x9e, 0xf5, 0xb4, 0x67, 0x63, 0xb7, 0x1e, 0x7, 0x46, 0x95, 0xad, 0x6a, 0x6, 0x18, 0x7c, 0xc9, 0xfd, 0x29, 0x59, 0x3b, 0xa, 0xa0, 0x4d, 0xa2, 0xe4, 0x81, 0x1, 0x3, 0x20, 0x68, 0x9c, 0xf9, 0x34, 0xce, 0x8a, 0xce, 0x26, 0x5c, 0xa2, 0x40, 0xf3, 0x57, 0xd2, 0xbc, 0x8b, 0x76, 0x76, 0x9f, 0xb, 0x5c, 0xe2, 0xfc, 0x1d, 0x67, 0xe0, 0x73, 0xc3, 0xc1, 0x10, 0x3e, 0x1d, 0x55, 0xac, 0xaa, 0x19, 0x60, 0xf5, 0x6d, 0x67, 0x67, 0x9, 0x7d, 0x26, 0x34, 0xd3, 0x55, 0x93, 0x9a, 0xc3, 0xdc, 0x46, 0x4e, 0x0, 0x4d, 0x6a, 0xd9, 0x9a, 0x3b, 0x26, 0xee, 0xd6, 0x63, 0x7f, 0x31, 0x18, 0x63, 0xd6, 0x9b, 0x54, 0xc3, 0x6c, 0xff, 0x51, 0x91, 0x5b, 0x91, 0xd7, 0x0, 0x85, 0x3e, 0x9, 0x9e, 0x22, 0xe8, 0xd, 0xa5, 0xe6, 0x15, 0x3a, 0xa9, 0xfb, 0x49, 0xf3, 0x46, 0xd4, 0x77, 0x6d, 0xf6, 0x8, 0x1a, 0x74, 0xd1, 0xdd, 0x4d, 0xa4, 0xb3, 0xbf, 0xac, 0xed, 0x2b, 0xe8, 0x40, 0x2, 0x7b, 0x43, 0xee, 0x98, 0xdc, 0x86, 0x8d, 0xc9, 0xa8, 0xb9, 0x24, 0xb9, 0x9, 0xe0, 0xa6, 0x24, 0x91, 0x53, 0xf, 0xb0, 0xfa, 0xf6, 0x9, 0x9b, 0x7, 0x7f, 0x71, 0xd1, 0x43, 0x0, 0xfe, 0x3, 0x0, 0x61, 0x12, 0x30, 0xc1, 0x84, 0x26, 0x80, 0x48, 0x12, 0xb2, 0xca, 0xeb, 0x1, 0x7c, 0x97, 0xc6, 0x79, 0x96, 0x74, 0x16, 0x64, 0x65, 0x16, 0x6f, 0xb8, 0x73, 0x42, 0x36, 0x2a, 0x89, 0x58, 0x6, 0x18, 0x74, 0xd1, 0xbd, 0x3d, 0x21, 0x1d, 0xe, 0xe8, 0x40, 0x90, 0x7b, 0x41, 0xea, 0x25, 0x65, 0x8f, 0x90, 0x75, 0x8f, 0x83, 0xf4, 0xe9, 0x60, 0xe1, 0x7a, 0x68, 0x51, 0x67, 0xad, 0x1e, 0x31, 0x9e, 0x3b, 0x21, 0x53, 0x33, 0x4, 0xac, 0x69, 0x2f, 0x42, 0x74, 0x26, 0x8, 0xb0, 0xa0, 0x79, 0x1f, 0xd2, 0x3e, 0x9, 0x35, 0x97, 0xc0, 0x21, 0xc7, 0x73, 0x8e, 0x1, 0x29, 0x70, 0x33, 0xc9, 0x55, 0x34, 0xa9, 0x87, 0x8c, 0x93, 0x9a, 0xbf, 0xfa, 0xf6, 0xf1, 0x9b, 0x4b, 0x25, 0x11, 0xc9, 0x0, 0x83, 0xbf, 0xb8, 0x68, 0x7f, 0x2b, 0xf7, 0x7c, 0x59, 0x77, 0x3a, 0x64, 0xf, 0x2f, 0xcc, 0x33, 0xa7, 0xb0, 0x7b, 0x4e, 0xa, 0xf0, 0xf9, 0xad, 0xb6, 0x1e, 0x20, 0x67, 0x2c, 0x37, 0x8e, 0xf3, 0xfc, 0x9a, 0x3b, 0x26, 0x6e, 0x4b, 0x8, 0xe7, 0x75, 0x5, 0x92, 0xb6, 0x3, 0xf8, 0x33, 0x80, 0x91, 0x40, 0xa2, 0xdb, 0xd7, 0x51, 0xe0, 0x3f, 0xe8, 0x38, 0xaf, 0x11, 0xe6, 0x41, 0x90, 0x3f, 0x5d, 0x3b, 0xef, 0xdc, 0x36, 0x9, 0xd0, 0x31, 0x3d, 0x80, 0xc6, 0xcb, 0x75, 0xbf, 0x5, 0xe8, 0x63, 0x60, 0xd8, 0xf1, 0xb3, 0xc0, 0x41, 0x23, 0x34, 0x3f, 0xd1, 0x26, 0xb7, 0xed, 0x92, 0x15, 0xc8, 0xff, 0x7c, 0x74, 0xd7, 0x86, 0x93, 0x7c, 0x1b, 0x26, 0xf5, 0x88, 0x6c, 0x76, 0x24, 0x22, 0x5d, 0xca, 0x83, 0xa0, 0x72, 0x4b, 0x90, 0x82, 0x77, 0xca, 0xe1, 0x8d, 0x4e, 0xfa, 0x47, 0xae, 0xab, 0x19, 0x1b, 0x16, 0x9c, 0x57, 0xd6, 0xb, 0x28, 0xc, 0x91, 0x3, 0x91, 0x80, 0x5e, 0x0, 0x1a, 0xbc, 0x42, 0x7b, 0x53, 0x8f, 0x79, 0xe9, 0xd2, 0x14, 0x49, 0xb1, 0x40, 0xe9, 0xe7, 0x8a, 0x6c, 0x1, 0xbb, 0x4, 0x54, 0x54, 0x81, 0xdd, 0x9, 0xd6, 0xdc, 0x31, 0xe1, 0x7d, 0x1a, 0xe7, 0x49, 0x1f, 0x47, 0x11, 0xb6, 0x80, 0x0, 0x8a, 0x9f, 0x11, 0xf3, 0x2e, 0xf7, 0xed, 0x7, 0x80, 0xb9, 0xad, 0x52, 0xe2, 0x3, 0x31, 0x3d, 0x80, 0x64, 0xf, 0x0, 0xb0, 0x97, 0x37, 0xbf, 0xac, 0xfc, 0xc6, 0x36, 0xde, 0x5b, 0x54, 0xd6, 0x73, 0xb5, 0x69, 0x95, 0x6c, 0xb0, 0x2e, 0xe7, 0x1d, 0x82, 0x1d, 0xee, 0xdb, 0xd7, 0x91, 0x40, 0xf2, 0x3d, 0x1f, 0xaf, 0x3e, 0x46, 0x8b, 0x5b, 0x7d, 0x2e, 0x66, 0x4c, 0xa, 0xa1, 0xb5, 0x29, 0xc1, 0xa2, 0x8, 0xc3, 0xb4, 0xe3, 0x38, 0x4d, 0xd5, 0x94, 0x27, 0x7a, 0x8, 0x10, 0x7a, 0xe6, 0xed, 0xcb, 0xc5, 0x63, 0x55, 0xa5, 0x3d, 0x74, 0xb9, 0xf8, 0x61, 0x2c, 0xf0, 0x75, 0x10, 0x89, 0xbb, 0x73, 0xd7, 0x15, 0xd0, 0x8, 0x84, 0x65, 0x68, 0x51, 0x4d, 0x8, 0xf, 0x6d, 0x49, 0x20, 0x7f, 0x97, 0x1f, 0x2d, 0x53, 0x81, 0x3c, 0x56, 0x29, 0x44, 0x32, 0x0, 0x8d, 0x69, 0x90, 0x6b, 0xbd, 0x1d, 0x2c, 0x3b, 0x60, 0x1a, 0x33, 0xe7, 0xf2, 0x47, 0xf3, 0x6, 0xc0, 0x8f, 0x34, 0x3, 0x10, 0x70, 0x9, 0xbe, 0x2f, 0x69, 0xbf, 0x4, 0x51, 0x9b, 0xaa, 0x56, 0x9c, 0x4c, 0x68, 0x9f, 0xc0, 0x72, 0xe3, 0x15, 0x4b, 0xbe, 0xf3, 0x1a, 0x3, 0x41, 0xf2, 0x4d, 0x48, 0x1f, 0x69, 0x6, 0x10, 0xe0, 0xa, 0xfc, 0xb0, 0xd0, 0xc1, 0x27, 0x6a, 0xfc, 0x8f, 0xc3, 0x1d, 0xc3, 0x69, 0xe5, 0xce, 0x2f, 0xaa, 0xd6, 0x1b, 0x37, 0x46, 0xb, 0xc8, 0xa9, 0x7a, 0x68, 0xd5, 0xfb, 0xc7, 0xa, 0xf8, 0x8c, 0x7e, 0x9f, 0xb, 0x63, 0xc9, 0xef, 0xe5, 0x2f, 0xa2, 0xfb, 0xe8, 0xea, 0x0, 0x7e, 0x3d, 0x73, 0xf5, 0x67, 0xcc, 0x6f, 0x14, 0xc4, 0x31, 0x41, 0x58, 0xbe, 0xaa, 0xe, 0x71, 0xd1, 0x43, 0x0, 0x0, 0x5, 0xd4, 0x8a, 0xcc, 0x3b, 0x1c, 0xa8, 0x88, 0xf7, 0x25, 0xca, 0xcf, 0xf0, 0x4d, 0x78, 0x55, 0x2c, 0x1, 0xe0, 0x0, 0xd0, 0x54, 0x25, 0xcc, 0xec, 0x2e, 0x40, 0xd2, 0x11, 0xb0, 0x77, 0x69, 0x7a, 0x85, 0x9, 0x1c, 0x77, 0xf, 0xd0, 0x3f, 0x5b, 0x43, 0x82, 0x6b, 0xad, 0xad, 0xca, 0xb4, 0x1c, 0xad, 0x5, 0x0, 0x2d, 0x79, 0xcb, 0x5e, 0x39, 0x83, 0x45, 0x2d, 0x4d, 0xb6, 0x90, 0x91, 0x8, 0xf4, 0x21, 0xf9, 0x91, 0x67, 0x0, 0x92, 0xfb, 0xb4, 0x6d, 0xb9, 0x0, 0xdb, 0x78, 0xaf, 0x6c, 0xb5, 0x64, 0x88, 0x1e, 0x2, 0xc8, 0xf, 0x19, 0xd8, 0xaa, 0xb, 0x8e, 0xef, 0x8, 0xfa, 0xe8, 0xfc, 0x26, 0x56, 0x5e, 0x9c, 0x10, 0x8f, 0x94, 0xdd, 0x46, 0xa5, 0x88, 0x9f, 0x7c, 0x63, 0xa6, 0x9f, 0xcf, 0x81, 0x0, 0x1a, 0x13, 0xc1, 0x74, 0xdd, 0x82, 0xf2, 0x7b, 0xa9, 0x28, 0x68, 0x5f, 0xc5, 0x50, 0xac, 0x71, 0x17, 0xf5, 0x94, 0x2c, 0x5a, 0x73, 0xe, 0x66, 0x43, 0x1b, 0x74, 0x55, 0x4, 0x91, 0x42, 0x20, 0x61, 0xde, 0x20, 0xb8, 0x85, 0xe1, 0x15, 0x27, 0x40, 0x91, 0x5c, 0x10, 0xb2, 0x7, 0x15, 0xcb, 0x9, 0xa5, 0x64, 0xc2, 0xe2, 0x97, 0x21, 0x9b, 0xa2, 0xa4, 0x8f, 0xeb, 0x23, 0xcf, 0x0, 0xec, 0x5, 0x20, 0xd8, 0x53, 0x0, 0x28, 0x25, 0xf4, 0x15, 0xc, 0x97, 0x21, 0x9c, 0x7, 0x32, 0x9a, 0x2f, 0x48, 0x12, 0xcc, 0x0, 0xa8, 0xea, 0xd0, 0xa9, 0x18, 0x4b, 0xa0, 0xde, 0x2, 0xd9, 0x82, 0x60, 0xc1, 0x81, 0xc7, 0xb6, 0x8, 0x76, 0x44, 0x60, 0x3b, 0xfc, 0xf9, 0x5a, 0x40, 0x13, 0xeb, 0x68, 0x3, 0xeb, 0xa4, 0x61, 0xf0, 0xd4, 0x5f, 0xed, 0x6b, 0xad, 0x7b, 0x8a, 0x8f, 0x57, 0x26, 0x85, 0x3b, 0x49, 0x7b, 0x3, 0xfa, 0xe6, 0xe0, 0x8b, 0x7f, 0x51, 0xb1, 0x56, 0x17, 0xed, 0x26, 0xe4, 0xa4, 0x1e, 0x4, 0x9d, 0x6f, 0xd3, 0x38, 0xcf, 0x6, 0x3e, 0x5a, 0xde, 0xaf, 0xaf, 0xaf, 0x3, 0x40, 0xfe, 0x8, 0xc7, 0x3c, 0x37, 0x16, 0x34, 0xee, 0x98, 0x6e, 0x20, 0x1c, 0x3f, 0xb0, 0x68, 0x41, 0xa2, 0x31, 0x5, 0x61, 0x1f, 0x45, 0x20, 0x4d, 0x2f, 0x40, 0xa7, 0xe5, 0x10, 0x17, 0x65, 0xd5, 0xcd, 0xbd, 0x63, 0x99, 0x9e, 0x34, 0x7f, 0x43, 0x43, 0xc8, 0xba, 0x97, 0x3, 0x7c, 0x7a, 0xf0, 0x25, 0xf7, 0xfd, 0xf7, 0xe0, 0xa9, 0xf, 0xec, 0xdd, 0xe6, 0x32, 0xc5, 0xbd, 0x18, 0x3c, 0xf5, 0x57, 0xdd, 0x1, 0xf6, 0x85, 0xec, 0x41, 0x20, 0x7a, 0x43, 0x38, 0x4, 0xd0, 0x27, 0x25, 0x7b, 0x24, 0x81, 0x81, 0xf0, 0xe7, 0xa, 0x80, 0xf0, 0x36, 0xaf, 0x35, 0x51, 0xcf, 0x3f, 0xf, 0x32, 0xf5, 0x75, 0xe3, 0xa4, 0x6f, 0x5c, 0x75, 0xf3, 0xbf, 0xb6, 0xf9, 0x4, 0xae, 0xdd, 0x5, 0x86, 0x5c, 0xfa, 0xc0, 0x30, 0x9b, 0x6d, 0xf9, 0xd, 0x80, 0xbd, 0x93, 0x30, 0x2, 0x85, 0xf6, 0xc7, 0x9, 0x6f, 0xba, 0xb9, 0x85, 0x34, 0x2b, 0x5, 0x3e, 0x44, 0x63, 0xee, 0x5c, 0x7d, 0xeb, 0x59, 0x25, 0xf, 0x9f, 0x6a, 0x73, 0x29, 0x86, 0x5d, 0xfe, 0x70, 0xf, 0x6b, 0xdd, 0x7d, 0x65, 0xed, 0x1, 0x34, 0x66, 0x7f, 0x59, 0xdb, 0xb, 0x72, 0xaf, 0x96, 0x6c, 0xff, 0xd6, 0x66, 0xcd, 0x1a, 0x2a, 0x44, 0xbe, 0xe9, 0x38, 0xd, 0x13, 0x56, 0xdd, 0x32, 0xf6, 0x85, 0x24, 0xd2, 0xac, 0x27, 0x18, 0x3c, 0xf5, 0x57, 0x23, 0xe5, 0x66, 0x5e, 0xf4, 0x77, 0x15, 0x49, 0x62, 0x15, 0x7d, 0xab, 0xa3, 0x66, 0x82, 0xd3, 0xc7, 0x4, 0x6c, 0x26, 0xcd, 0xb, 0x34, 0xce, 0x42, 0xc7, 0x98, 0xfb, 0x56, 0xde, 0x3c, 0x36, 0x72, 0x99, 0x78, 0x9b, 0x3d, 0x82, 0x56, 0xce, 0x3d, 0x63, 0x2b, 0xbc, 0x7d, 0x74, 0x5e, 0xb, 0x55, 0x68, 0x20, 0x2d, 0xfa, 0x79, 0x25, 0x49, 0x64, 0xd3, 0x2c, 0x1, 0xe8, 0x63, 0xa5, 0x83, 0x6a, 0xc5, 0x4c, 0xbd, 0xc1, 0xd0, 0xcb, 0x16, 0xef, 0x67, 0x6d, 0x76, 0x9c, 0x3f, 0xcc, 0x55, 0x61, 0x62, 0x8f, 0xd4, 0xc6, 0xb, 0xf4, 0xe8, 0xd0, 0xbe, 0x8c, 0x22, 0xb0, 0x2f, 0xa0, 0x33, 0x61, 0xdd, 0xc1, 0x2e, 0x30, 0x74, 0xf0, 0xd4, 0x7, 0x17, 0xac, 0xbe, 0x75, 0xec, 0xba, 0xe2, 0x4, 0xaa, 0x6e, 0xb9, 0xc3, 0xa6, 0x3f, 0x96, 0x32, 0x34, 0xbf, 0xf7, 0x48, 0xef, 0x2f, 0x45, 0xaa, 0x68, 0xf6, 0x37, 0x34, 0xce, 0xf9, 0xaa, 0x65, 0xde, 0xb1, 0x44, 0x9f, 0x19, 0x7a, 0xd9, 0x83, 0xfb, 0x77, 0x14, 0x71, 0x3a, 0x6, 0x34, 0x0, 0xd6, 0x9d, 0xee, 0xf, 0x94, 0x2c, 0xa8, 0x7b, 0x9b, 0xfc, 0x44, 0x59, 0x6, 0x87, 0x41, 0xfb, 0xcb, 0x9d, 0x5b, 0x24, 0x6f, 0x22, 0x4f, 0x9f, 0x80, 0xec, 0x38, 0x52, 0x7d, 0xa2, 0x4a, 0x55, 0x35, 0x3, 0xac, 0x9c, 0xf3, 0xf9, 0xac, 0x80, 0x17, 0xe0, 0x9f, 0xa3, 0x5a, 0x9d, 0xdc, 0x9f, 0x2f, 0xb7, 0xa7, 0x6d, 0x4, 0x9a, 0x86, 0xbd, 0x40, 0xc2, 0x88, 0xce, 0x26, 0x59, 0x92, 0x20, 0xd9, 0x43, 0x1, 0xec, 0x7, 0x50, 0x85, 0xcb, 0x3b, 0xc2, 0x78, 0xa8, 0x1c, 0x87, 0x28, 0xfe, 0xb6, 0x50, 0xbb, 0xa0, 0xdf, 0xad, 0xbe, 0x4a, 0xe3, 0x6c, 0x8c, 0x2a, 0x57, 0x4d, 0x63, 0xf7, 0x1f, 0x6e, 0x19, 0xfb, 0x2a, 0x8d, 0x79, 0x33, 0x98, 0x32, 0x8e, 0x76, 0x74, 0x8d, 0x9a, 0xf4, 0x88, 0xb3, 0x6d, 0x53, 0x0, 0x5, 0xe9, 0xe3, 0xb2, 0xf6, 0xe4, 0x21, 0x97, 0x2d, 0xee, 0xd9, 0xb9, 0x64, 0x4b, 0x6, 0x6, 0x5f, 0xfa, 0xe0, 0x60, 0x59, 0x4d, 0xf6, 0x55, 0xdd, 0xdc, 0x36, 0x37, 0x49, 0x40, 0xac, 0xd7, 0x40, 0xce, 0x96, 0xf, 0x10, 0xdc, 0xd2, 0xd0, 0xfd, 0x63, 0xaf, 0x47, 0xc5, 0xab, 0x89, 0x1, 0x6, 0x5f, 0x72, 0x9f, 0x1, 0xcc, 0x3, 0x2, 0x32, 0x2, 0x90, 0x53, 0xe5, 0xa, 0x2e, 0x14, 0x75, 0x61, 0xc5, 0x5d, 0x5f, 0x41, 0x78, 0x9e, 0x71, 0xa1, 0xf1, 0xb2, 0xf6, 0xd4, 0xc4, 0xa9, 0xd1, 0x9, 0x40, 0xe0, 0xc, 0xc0, 0x8e, 0xf1, 0x1c, 0xab, 0x0, 0x76, 0xc0, 0x89, 0x68, 0x34, 0x39, 0x5f, 0x3e, 0x90, 0x66, 0x57, 0xf1, 0x9, 0xa6, 0x1, 0xd4, 0xc4, 0x0, 0xd, 0x3d, 0x7a, 0xb, 0x34, 0xf7, 0x4a, 0xc8, 0xfa, 0x54, 0x8c, 0x98, 0x19, 0x2a, 0x35, 0x25, 0x5c, 0x1c, 0xb7, 0x60, 0x37, 0xb0, 0x83, 0x49, 0x9d, 0x3d, 0xe4, 0xd2, 0x87, 0x7a, 0x77, 0x36, 0x1, 0x6b, 0x81, 0x21, 0x97, 0x3e, 0x74, 0x2, 0x64, 0xc7, 0xe6, 0x25, 0xff, 0xf0, 0xa, 0xea, 0xb6, 0xe0, 0xaa, 0x54, 0x58, 0xdc, 0xb7, 0x61, 0x13, 0x2d, 0x77, 0xd1, 0x98, 0x57, 0xe2, 0xca, 0x57, 0x13, 0x3, 0x2c, 0xfb, 0xe9, 0xb1, 0xa2, 0x71, 0x56, 0x80, 0x39, 0x37, 0x2e, 0x86, 0x57, 0xf8, 0xb4, 0x86, 0x52, 0x52, 0x8e, 0xf7, 0x3e, 0xef, 0x2e, 0x45, 0x48, 0x1a, 0x7, 0xe0, 0x92, 0x76, 0xa0, 0x4b, 0x87, 0xc0, 0xb0, 0x69, 0x8f, 0xf4, 0x4, 0xf4, 0x45, 0x49, 0x47, 0x7b, 0x92, 0xbf, 0x9, 0x26, 0x4f, 0x22, 0xf0, 0x11, 0x87, 0xab, 0x52, 0x61, 0xb1, 0xd, 0xcb, 0x77, 0x15, 0x20, 0x40, 0x2e, 0x91, 0x70, 0x7f, 0x5c, 0x19, 0x6b, 0xd6, 0xdf, 0x57, 0xcd, 0x3d, 0x7d, 0xab, 0x31, 0xce, 0x8b, 0x20, 0x4b, 0xc, 0x3, 0x95, 0x76, 0x5f, 0x26, 0x30, 0x3e, 0x76, 0x87, 0xec, 0x85, 0x43, 0x2e, 0x7d, 0x68, 0x6c, 0x47, 0x10, 0x2c, 0x69, 0x90, 0xb5, 0x57, 0x49, 0xf6, 0xdc, 0xd0, 0xce, 0x1d, 0x55, 0xe2, 0x4, 0x95, 0xc6, 0xb, 0xe5, 0x65, 0x56, 0xff, 0xe1, 0x96, 0x33, 0x63, 0xd7, 0x59, 0x24, 0x62, 0xc0, 0x31, 0x4e, 0xea, 0x1a, 0x0, 0x9b, 0xdb, 0xd2, 0xc9, 0xc7, 0x89, 0x7f, 0x45, 0xcf, 0x7e, 0x55, 0x68, 0x25, 0xdb, 0x1f, 0xd0, 0x15, 0xc3, 0xa7, 0x3f, 0xba, 0x17, 0x76, 0x23, 0x18, 0x7a, 0xf9, 0xc3, 0x17, 0xc9, 0xba, 0x97, 0x90, 0xec, 0xe6, 0x1f, 0x22, 0xdb, 0xca, 0x15, 0x24, 0xa, 0x3f, 0xa5, 0xde, 0xb0, 0x8d, 0xf1, 0x82, 0x85, 0x96, 0xfe, 0x53, 0xc9, 0x35, 0x16, 0xc9, 0x30, 0x80, 0x49, 0xfd, 0x15, 0x60, 0x16, 0x2c, 0xa7, 0xb4, 0xb4, 0x56, 0x78, 0xe2, 0x9e, 0x7d, 0x7f, 0x44, 0x43, 0x1a, 0x40, 0xfa, 0xbc, 0xeb, 0x66, 0xef, 0x4e, 0x88, 0x36, 0xed, 0xe, 0xc3, 0xa6, 0x3d, 0x72, 0x34, 0x64, 0xaf, 0x4, 0xd1, 0x97, 0x9e, 0xda, 0xc7, 0xb0, 0x7a, 0x86, 0x12, 0xf8, 0x29, 0x3b, 0x61, 0x56, 0x3e, 0x9e, 0x48, 0xe3, 0xef, 0x4b, 0x65, 0x5e, 0x26, 0xcd, 0xba, 0x52, 0x65, 0xad, 0x99, 0x1, 0x86, 0x5f, 0xf1, 0x44, 0xca, 0x75, 0x33, 0x17, 0x93, 0xdc, 0xb3, 0x60, 0x82, 0xa3, 0xc6, 0x8b, 0x86, 0x14, 0x4, 0x1a, 0x7a, 0x9b, 0x2b, 0xc9, 0x9e, 0x36, 0xf4, 0xf2, 0xc5, 0x8b, 0x3b, 0x9b, 0xb8, 0xe5, 0x60, 0xd8, 0xb4, 0x47, 0x87, 0x59, 0xd7, 0x9d, 0x2b, 0xd9, 0x91, 0xb9, 0x63, 0x71, 0x88, 0xa, 0x8d, 0x64, 0x85, 0x97, 0x2, 0xa5, 0x2e, 0x3e, 0x9d, 0x70, 0x78, 0x4e, 0x93, 0x22, 0x9d, 0x7b, 0xff, 0x70, 0xf3, 0xbf, 0xfe, 0xb2, 0x54, 0x79, 0x6b, 0x62, 0x80, 0x61, 0x57, 0x3c, 0x9e, 0x92, 0xcd, 0x5c, 0x27, 0xeb, 0xde, 0x0, 0xa0, 0x67, 0xc1, 0x92, 0xe4, 0x4, 0x2e, 0x7f, 0xdf, 0x3b, 0xfa, 0x27, 0x8c, 0xc1, 0xba, 0xf6, 0xb3, 0x43, 0x2e, 0x5b, 0x7c, 0x7f, 0x65, 0xa5, 0xec, 0x38, 0x18, 0x7a, 0xf9, 0xa3, 0x43, 0x25, 0xf7, 0x2e, 0x40, 0x47, 0xfa, 0x36, 0xd, 0x86, 0x7e, 0x6b, 0xc1, 0x3, 0xbd, 0x65, 0xfe, 0x8, 0x7e, 0xc3, 0x57, 0xee, 0x14, 0x94, 0xf0, 0x5, 0xc0, 0xa5, 0xe1, 0xdf, 0xca, 0x95, 0xb9, 0x6a, 0x6, 0x18, 0x7a, 0xf9, 0xa3, 0xd, 0x72, 0x33, 0xdf, 0xb3, 0xae, 0xfb, 0xdf, 0x0, 0xd3, 0x5e, 0x68, 0xb4, 0x64, 0x5f, 0x9d, 0x2a, 0xd3, 0x3a, 0xdc, 0x18, 0xa6, 0x21, 0x9d, 0x39, 0xe4, 0xd2, 0x87, 0x7e, 0x3b, 0xf4, 0xf2, 0x47, 0x92, 0xde, 0x95, 0xac, 0x26, 0x18, 0x36, 0xed, 0xb1, 0x93, 0xad, 0xcd, 0x3c, 0x28, 0xab, 0xc3, 0xa, 0xd7, 0x52, 0x94, 0xd2, 0x7a, 0xe2, 0x70, 0x81, 0xd6, 0x71, 0xf3, 0x9a, 0xdd, 0x2e, 0x92, 0x1b, 0x40, 0xf3, 0xa6, 0x84, 0x5d, 0xa, 0xb6, 0x53, 0x4, 0x43, 0x62, 0x86, 0x27, 0xfc, 0x9, 0x6c, 0x75, 0x68, 0x67, 0x31, 0x54, 0xc5, 0x0, 0xc3, 0xaf, 0x78, 0xbc, 0x1b, 0xa0, 0x1f, 0x59, 0x6b, 0xaf, 0x3, 0xe1, 0xd0, 0x10, 0xc1, 0x21, 0xc7, 0x85, 0x2b, 0xc7, 0xa2, 0x18, 0x9f, 0x45, 0xe1, 0xcc, 0x8b, 0x2b, 0x5, 0x78, 0x8, 0xb8, 0x9f, 0xa1, 0x74, 0x9, 0x10, 0x46, 0xd0, 0xd1, 0xd6, 0xba, 0x2f, 0xf, 0xb9, 0xfc, 0x91, 0xe3, 0x3a, 0x8c, 0xc2, 0x25, 0x60, 0xc8, 0x65, 0xf, 0xff, 0xa7, 0xb5, 0xd9, 0x45, 0x24, 0xf, 0xa, 0xd4, 0x6f, 0x1a, 0xe3, 0xf9, 0x39, 0x17, 0x8a, 0x3f, 0x85, 0xf5, 0x46, 0xc, 0x2e, 0xa, 0xf1, 0x26, 0x3f, 0x2e, 0x7d, 0x7c, 0xac, 0x5c, 0x75, 0xf3, 0x99, 0x3, 0x8d, 0x93, 0xfe, 0x94, 0x49, 0x35, 0xee, 0x63, 0x52, 0x4d, 0x4d, 0x26, 0x95, 0xee, 0x63, 0x9c, 0xf4, 0x20, 0x3a, 0xe9, 0xd1, 0x74, 0xd2, 0x67, 0xd1, 0x38, 0x5f, 0xa6, 0x71, 0xbe, 0x44, 0xf0, 0xd9, 0x72, 0x65, 0x2f, 0x27, 0xb8, 0x47, 0x10, 0xff, 0xd7, 0x7b, 0xca, 0xda, 0xaf, 0x4a, 0xf6, 0x3b, 0x8, 0x56, 0xa3, 0xb0, 0xd2, 0x95, 0xae, 0x55, 0x2d, 0x8c, 0xf5, 0xd8, 0x5b, 0x62, 0xc8, 0xb9, 0x70, 0x2b, 0x68, 0x1e, 0x4b, 0x77, 0xdb, 0xe7, 0xbc, 0x17, 0x67, 0x1c, 0xd3, 0xe1, 0x9b, 0x48, 0xe, 0xbf, 0xe2, 0x89, 0x46, 0xeb, 0x66, 0xd6, 0xca, 0xba, 0x7, 0x91, 0xdc, 0x23, 0x98, 0x92, 0x87, 0xc4, 0x44, 0x71, 0x12, 0x78, 0xe8, 0x92, 0xab, 0x40, 0xe7, 0xe4, 0x95, 0x73, 0x3e, 0xf7, 0x7e, 0x71, 0x94, 0xa3, 0xbe, 0xf2, 0x5b, 0xb6, 0x6c, 0x7b, 0x97, 0x4e, 0xba, 0x81, 0xb2, 0xd6, 0x48, 0xd6, 0x5d, 0x35, 0xf7, 0x8c, 0xb2, 0x47, 0xcc, 0x54, 0x44, 0x85, 0xa1, 0xd3, 0x1e, 0xed, 0xe, 0x60, 0x32, 0xac, 0x9d, 0x5, 0xf8, 0x67, 0xff, 0xa1, 0xe3, 0xf, 0x8c, 0x40, 0xe1, 0x3c, 0x78, 0xb, 0xc8, 0xb7, 0x4, 0xde, 0xea, 0x66, 0xb3, 0xd7, 0xaf, 0xb9, 0xf5, 0xcc, 0x4c, 0xd, 0x59, 0xb4, 0x9, 0x86, 0x5c, 0xfe, 0x48, 0x9a, 0xc0, 0x22, 0x12, 0x47, 0xc9, 0xda, 0xdc, 0x2c, 0x1b, 0x2b, 0x26, 0x7a, 0x25, 0x55, 0x46, 0x56, 0xe0, 0x5d, 0xab, 0xe6, 0x9e, 0x3e, 0x25, 0xc9, 0xba, 0x54, 0x54, 0xd8, 0x61, 0xd3, 0x1e, 0x3b, 0x49, 0x72, 0x7f, 0xe3, 0x89, 0xb5, 0x1e, 0x9b, 0xb7, 0x4a, 0x2d, 0xee, 0xec, 0x87, 0x70, 0xcc, 0xb8, 0xc5, 0x23, 0x2c, 0x8a, 0xab, 0xc8, 0x38, 0x91, 0xa7, 0x83, 0x49, 0xda, 0x4a, 0x9a, 0xd7, 0x40, 0x2e, 0x2, 0xcc, 0x4f, 0x56, 0xce, 0xf9, 0x6c, 0xe2, 0x1e, 0x45, 0xc3, 0xaf, 0x78, 0x7c, 0xa8, 0xb5, 0xee, 0xb5, 0xde, 0xde, 0x48, 0x3a, 0x88, 0xa4, 0xbf, 0x3f, 0x62, 0x20, 0xaa, 0x7b, 0xc7, 0x27, 0xb6, 0xaa, 0x53, 0xb8, 0x2e, 0x51, 0x38, 0x2a, 0xf6, 0xa4, 0x2e, 0xc4, 0x97, 0xbf, 0xf, 0x3, 0x9f, 0x4d, 0x35, 0x34, 0x7d, 0x6e, 0xd9, 0xcf, 0x4e, 0x4a, 0xf4, 0xc8, 0x98, 0x8a, 0xe, 0x8d, 0x12, 0xf0, 0x16, 0xc0, 0x55, 0x20, 0x86, 0x12, 0x85, 0x47, 0xb7, 0x14, 0x54, 0xa8, 0x18, 0xca, 0x59, 0x7f, 0xc2, 0x61, 0x2c, 0xfb, 0x5d, 0x1e, 0xb5, 0xb9, 0x19, 0x70, 0x89, 0x64, 0xf, 0xc9, 0xe, 0x84, 0x78, 0x10, 0xa9, 0xb, 0x87, 0x4e, 0x7b, 0x74, 0x29, 0xc0, 0xc5, 0x0, 0x9f, 0x58, 0x75, 0xd3, 0xe7, 0x3e, 0xac, 0x16, 0x41, 0x43, 0xa7, 0x3d, 0x76, 0x24, 0x81, 0x33, 0x41, 0x9c, 0x62, 0xdd, 0xec, 0x27, 0x1, 0xf4, 0x26, 0xd1, 0xe4, 0x17, 0x26, 0xe7, 0xa, 0x17, 0xb9, 0x8c, 0x92, 0x6d, 0xb8, 0x8f, 0x7f, 0xe, 0xed, 0xba, 0xc2, 0xd7, 0x68, 0xcc, 0x6d, 0x49, 0x13, 0x3f, 0x8e, 0x14, 0x25, 0x61, 0xd8, 0xf4, 0x5f, 0x9f, 0x2e, 0xeb, 0x3e, 0xc, 0x44, 0xad, 0x70, 0xed, 0x70, 0x28, 0x68, 0x57, 0xa1, 0x1d, 0x4b, 0x20, 0xa9, 0x19, 0xe4, 0x3f, 0x0, 0xbc, 0xb, 0xe0, 0x6d, 0x80, 0x7f, 0x34, 0xc6, 0xbc, 0x28, 0x61, 0x83, 0x64, 0x37, 0x1b, 0x63, 0xb6, 0x9, 0xcc, 0x2, 0x70, 0x8d, 0x31, 0x8e, 0x9b, 0xcd, 0x34, 0x2, 0xec, 0x66, 0xc, 0xf, 0x4, 0x74, 0x8c, 0xb5, 0x3a, 0xe, 0xd0, 0x1, 0x0, 0x7a, 0xc8, 0xda, 0xde, 0x24, 0xf7, 0xcb, 0x21, 0x2d, 0x7c, 0x42, 0xa, 0xa, 0xfb, 0xe9, 0x44, 0x2a, 0x15, 0x4a, 0x4f, 0x92, 0x5, 0xcd, 0x8d, 0x3d, 0xf7, 0xeb, 0x73, 0xd5, 0x33, 0xd7, 0xf, 0x4e, 0x5c, 0xce, 0xa9, 0xf8, 0xec, 0x60, 0x9, 0x2b, 0x40, 0xf3, 0x2, 0xa0, 0xe3, 0x2, 0x4f, 0x9e, 0xf0, 0x69, 0xd1, 0xed, 0xf, 0x5, 0x63, 0x49, 0xee, 0xc1, 0x3b, 0x69, 0x3b, 0x68, 0x3a, 0x10, 0xd, 0x1b, 0x25, 0x1c, 0x2, 0xe0, 0x10, 0x3f, 0xc6, 0x9, 0x92, 0x1d, 0x27, 0xe1, 0x7d, 0x48, 0xcd, 0x90, 0xcd, 0x10, 0xb4, 0x0, 0xe4, 0x66, 0xb2, 0x24, 0xe9, 0x0, 0x4a, 0x59, 0xab, 0xee, 0x80, 0xf6, 0x7, 0x90, 0xf3, 0x48, 0xa, 0x16, 0xc9, 0xf8, 0xe, 0xd1, 0x2c, 0x76, 0xe7, 0xab, 0x9c, 0xf8, 0xc5, 0xe3, 0x40, 0x1, 0x7e, 0x45, 0x43, 0x4a, 0xb0, 0x0, 0xc, 0x69, 0x9e, 0x14, 0xf9, 0x83, 0xf6, 0x20, 0x3e, 0x50, 0x5, 0x3, 0x90, 0x7c, 0x17, 0xe4, 0x77, 0x64, 0xdd, 0x27, 0xdb, 0xeb, 0xb8, 0xb4, 0xa, 0x4a, 0x13, 0x2a, 0x57, 0x48, 0x81, 0x24, 0xc2, 0x4e, 0x97, 0xc1, 0x88, 0xda, 0x1d, 0x40, 0x5f, 0x40, 0x7d, 0xc1, 0x9c, 0x4a, 0x91, 0x4b, 0x26, 0x70, 0x79, 0xf, 0x8c, 0x6e, 0xc8, 0x7f, 0x9b, 0xcb, 0x28, 0xbf, 0x59, 0x46, 0xb2, 0x65, 0x2f, 0xc4, 0x6f, 0xee, 0x5c, 0x24, 0x43, 0x72, 0x9, 0x8d, 0xf3, 0x5f, 0x2b, 0x67, 0x9f, 0x5a, 0xd6, 0xa0, 0x53, 0x2d, 0x54, 0xdc, 0x85, 0xaf, 0x9c, 0xf3, 0x59, 0x57, 0x56, 0xcf, 0x1, 0xe6, 0x7, 0xcc, 0x4f, 0x3b, 0x29, 0xce, 0xae, 0xf, 0xc4, 0xdb, 0xb2, 0x11, 0x11, 0x16, 0xf5, 0x1e, 0x31, 0xdf, 0x44, 0x7d, 0xe7, 0x3f, 0x33, 0x58, 0x72, 0xe, 0x7f, 0x5b, 0x4e, 0x7f, 0x7e, 0x1, 0x86, 0x6, 0x86, 0x26, 0xbf, 0xb6, 0xda, 0xf, 0xf3, 0xe6, 0x1c, 0x20, 0xd2, 0x0, 0xfe, 0x7d, 0xb1, 0x52, 0x5e, 0x6c, 0xcf, 0x47, 0x4c, 0x19, 0x4b, 0xc5, 0x61, 0x89, 0xfa, 0x86, 0x5d, 0xb9, 0xe8, 0x19, 0x73, 0x1e, 0x58, 0x31, 0xfb, 0xd4, 0x76, 0xf5, 0x8e, 0xae, 0x6a, 0xc, 0x5f, 0x75, 0xd3, 0xe7, 0x32, 0xc6, 0x71, 0x66, 0xd0, 0x98, 0x3f, 0x7a, 0x1e, 0x81, 0xf0, 0x14, 0x83, 0xbc, 0xcd, 0x1a, 0xa0, 0x77, 0x94, 0x27, 0x3, 0x79, 0x3d, 0xf8, 0xf1, 0xc3, 0xe4, 0x1b, 0x11, 0x7c, 0xbb, 0x49, 0x7e, 0x4d, 0x8, 0xb, 0xc3, 0xa, 0xec, 0x61, 0x21, 0x3b, 0x49, 0x2e, 0x6e, 0x48, 0x78, 0x6c, 0x65, 0x53, 0x2a, 0x8e, 0x1b, 0x32, 0x52, 0x79, 0xc6, 0x2b, 0x22, 0xbc, 0xcd, 0xa1, 0x77, 0xa, 0x8b, 0x1f, 0x25, 0x7c, 0x5f, 0x9c, 0x6f, 0x51, 0x18, 0x23, 0xca, 0x15, 0x67, 0xe3, 0x29, 0x28, 0x77, 0x44, 0x1d, 0xa, 0x3b, 0x6, 0x56, 0xdc, 0x43, 0x77, 0x8, 0x3, 0x0, 0xc0, 0x8a, 0xd9, 0xa7, 0xbc, 0x9, 0x98, 0x6f, 0x48, 0xb0, 0xc1, 0x4a, 0x97, 0x90, 0xcd, 0x3a, 0xa8, 0x72, 0x40, 0x71, 0xff, 0x40, 0x54, 0x13, 0xd8, 0xaa, 0x3d, 0xd3, 0x5e, 0xb0, 0xb5, 0x1d, 0x22, 0x30, 0x57, 0x80, 0xc5, 0x8, 0xec, 0xc6, 0xc5, 0x47, 0x1b, 0xe2, 0x17, 0x7f, 0xc7, 0x32, 0xf9, 0x97, 0xcb, 0xaf, 0x5c, 0x1e, 0x95, 0x94, 0xc5, 0xbb, 0xf7, 0x27, 0xc0, 0x34, 0x61, 0xd8, 0x15, 0x4f, 0x8c, 0xa9, 0x4b, 0x6, 0x0, 0x80, 0x15, 0x37, 0x9e, 0xf2, 0x2b, 0x81, 0x73, 0xfd, 0x59, 0x89, 0xe0, 0xbc, 0xdb, 0x9c, 0xdf, 0xa3, 0x1f, 0x6, 0x1, 0xaf, 0xd0, 0x38, 0xf3, 0x40, 0xf3, 0x3d, 0x90, 0x8f, 0xa3, 0x50, 0x4b, 0x66, 0x72, 0x3e, 0x92, 0x9d, 0x24, 0x8a, 0x24, 0x8, 0x61, 0x1c, 0x2, 0x1a, 0xe, 0x60, 0xca, 0x51, 0x57, 0x3d, 0x9d, 0x6e, 0xaf, 0xfc, 0x6a, 0x56, 0xe3, 0x68, 0x9c, 0xaf, 0xd2, 0x38, 0xbf, 0x1, 0xe8, 0x2, 0xc, 0x66, 0xa5, 0x8, 0xf0, 0x3, 0x81, 0x4f, 0x1, 0x9c, 0x4d, 0x9a, 0xff, 0x30, 0xc6, 0x4c, 0x5f, 0x31, 0xfb, 0x94, 0x6f, 0x3, 0xe6, 0x6b, 0xa0, 0xf9, 0x6d, 0x28, 0xae, 0xef, 0x27, 0x17, 0xb5, 0x6d, 0x5a, 0xa5, 0x17, 0x6a, 0xfc, 0xbe, 0xf3, 0x2f, 0x7f, 0xd2, 0x43, 0x79, 0xbc, 0x68, 0x8c, 0x9b, 0x75, 0xcf, 0x6b, 0x2f, 0x6, 0x48, 0xa4, 0xc9, 0x8c, 0xb8, 0xf2, 0xa9, 0x23, 0x24, 0xfb, 0x6b, 0x49, 0x69, 0x49, 0x1b, 0xc, 0xb9, 0x95, 0xc6, 0xac, 0x0, 0x78, 0xf3, 0xf2, 0x59, 0x27, 0xbd, 0x19, 0x11, 0xff, 0x13, 0xd6, 0xba, 0xf3, 0x25, 0x9d, 0x60, 0x72, 0xaa, 0x5b, 0xe8, 0xa0, 0xe4, 0x92, 0xc5, 0x6d, 0x4b, 0x6f, 0xd1, 0xd6, 0x78, 0x51, 0x71, 0xc3, 0xcf, 0x95, 0xa4, 0x53, 0xd, 0x4, 0x55, 0x8d, 0xcd, 0x43, 0x5e, 0x2f, 0xca, 0x47, 0x68, 0xcc, 0xf8, 0x95, 0xb3, 0x4f, 0x2e, 0x77, 0xa, 0x7a, 0xd5, 0x25, 0xa8, 0x19, 0x46, 0x5c, 0xf9, 0xd4, 0xf5, 0x92, 0x5e, 0x7, 0x39, 0x6f, 0xc5, 0xac, 0x93, 0xca, 0x6e, 0xf5, 0x3a, 0xfc, 0x4b, 0x4f, 0x35, 0x42, 0xf6, 0x69, 0x41, 0xc7, 0x78, 0x2, 0x1e, 0x73, 0x15, 0x66, 0x58, 0xa7, 0x8b, 0x41, 0x51, 0x78, 0xc, 0x29, 0x45, 0x22, 0x96, 0xf9, 0xbe, 0x38, 0x4e, 0x71, 0xfc, 0x28, 0x4, 0x29, 0x26, 0x8d, 0xf6, 0x60, 0x15, 0x7f, 0x78, 0x7c, 0x97, 0x34, 0x3f, 0x58, 0x31, 0xfb, 0xe4, 0x1f, 0x26, 0x9d, 0x7e, 0xa7, 0xe, 0x9a, 0x23, 0xaf, 0x59, 0x4a, 0xb7, 0x65, 0xfb, 0xe3, 0x24, 0x8e, 0x6, 0xd0, 0xc3, 0xdb, 0x3c, 0x23, 0xd8, 0x87, 0x24, 0x8a, 0x5, 0x18, 0xf1, 0x5c, 0xe9, 0xe4, 0x43, 0x5c, 0xba, 0xa5, 0x58, 0x24, 0xa, 0x65, 0xc5, 0xdf, 0x95, 0xcb, 0x2f, 0xae, 0x4c, 0x8c, 0xf9, 0x46, 0xc1, 0x7a, 0x4b, 0xff, 0xe0, 0x68, 0x3e, 0x63, 0x85, 0xcf, 0xaf, 0xba, 0xf1, 0x94, 0x44, 0xcd, 0xc1, 0x9d, 0x6a, 0xca, 0x5d, 0xf6, 0xd3, 0x63, 0xb5, 0xf2, 0xc6, 0x53, 0x4f, 0x25, 0x53, 0xb7, 0x4a, 0x7c, 0xc3, 0x57, 0xd5, 0x19, 0xbd, 0xce, 0x90, 0x31, 0xcf, 0x61, 0x4d, 0xa1, 0x54, 0xdc, 0x8, 0xbd, 0x32, 0x36, 0x9d, 0xb8, 0x30, 0x96, 0xf8, 0xae, 0x5c, 0x7e, 0x71, 0x71, 0xe2, 0xbe, 0xf1, 0xe4, 0xe3, 0x90, 0x6e, 0x3b, 0x84, 0xe4, 0xb7, 0x92, 0xa6, 0x41, 0x67, 0xdb, 0xf2, 0x1, 0x0, 0xcb, 0x67, 0x8d, 0xb9, 0x16, 0x34, 0xd7, 0x4a, 0x58, 0xf, 0xef, 0x4, 0x92, 0x28, 0x4a, 0xed, 0x56, 0x57, 0xb0, 0xb7, 0x72, 0xb9, 0xb0, 0x52, 0xdf, 0x6, 0x2e, 0x71, 0x7e, 0xf8, 0x36, 0x0, 0x1f, 0x24, 0x8d, 0xfb, 0xba, 0xd2, 0x9b, 0x86, 0x7f, 0xe9, 0xe9, 0xde, 0xa0, 0x1e, 0x25, 0x30, 0x24, 0x5f, 0xbc, 0xb8, 0x3d, 0x74, 0x6b, 0x19, 0x71, 0x4b, 0xa5, 0xd1, 0x16, 0xa9, 0x22, 0x4e, 0x7a, 0xc8, 0x7d, 0x17, 0xac, 0x95, 0xf4, 0x67, 0x2d, 0x73, 0x5d, 0x9b, 0xef, 0xc9, 0x62, 0x5b, 0x4f, 0xa5, 0x7, 0xdd, 0xbe, 0xb7, 0x4b, 0x46, 0xfe, 0x5b, 0x0, 0x92, 0x5e, 0x27, 0xf9, 0xff, 0x56, 0xcc, 0x3e, 0x69, 0x66, 0xd2, 0x38, 0x6f, 0x77, 0x4b, 0x53, 0x25, 0x60, 0xc, 0xcf, 0x12, 0xb0, 0x7f, 0xa1, 0x46, 0x10, 0xc7, 0xa3, 0x49, 0xf0, 0x6e, 0xb5, 0x69, 0xb3, 0xd5, 0x73, 0x89, 0x19, 0x41, 0x17, 0x40, 0xd6, 0x6f, 0xdc, 0x8d, 0x3e, 0x81, 0x63, 0x36, 0x88, 0x28, 0xdc, 0x37, 0xc0, 0x8f, 0xf3, 0xf, 0xc7, 0x38, 0xd7, 0x2f, 0xfb, 0xd9, 0x89, 0xb3, 0xd1, 0xe, 0x50, 0x17, 0x43, 0x40, 0x0, 0x56, 0x9a, 0x2, 0xb0, 0x4f, 0xcc, 0xa0, 0x19, 0x46, 0x54, 0x95, 0x57, 0xf8, 0xfb, 0xa8, 0xb4, 0xa2, 0xde, 0x17, 0x43, 0x41, 0x9a, 0xf2, 0xaf, 0x90, 0x15, 0x34, 0x6c, 0x14, 0x33, 0x24, 0xcd, 0x12, 0x63, 0x9c, 0x13, 0x49, 0x73, 0xa9, 0xf2, 0x7b, 0x39, 0xd2, 0x5b, 0xff, 0x58, 0xd0, 0xe5, 0xe7, 0xbc, 0x87, 0x83, 0xd6, 0xef, 0xf9, 0xf4, 0xf3, 0xb2, 0xf6, 0x22, 0x3e, 0x50, 0x6f, 0x3d, 0x0, 0xb9, 0xb7, 0x7f, 0xab, 0xe8, 0xa6, 0x5f, 0x6b, 0xab, 0x2f, 0x47, 0xe4, 0x36, 0x30, 0x41, 0x99, 0x11, 0x42, 0xc1, 0xc6, 0xf7, 0xc4, 0x12, 0x49, 0xff, 0x43, 0xf2, 0xe9, 0x65, 0x33, 0x47, 0x67, 0x0, 0xfc, 0x6e, 0xe4, 0x55, 0xcf, 0xbe, 0x2d, 0x6b, 0x7f, 0x9, 0x61, 0xcf, 0x12, 0xbe, 0x23, 0x16, 0xa0, 0x1, 0xf9, 0x24, 0xc9, 0x6f, 0x2e, 0x9b, 0x39, 0x7a, 0x59, 0x72, 0x18, 0x6e, 0xd, 0x75, 0xd3, 0x3, 0xc, 0xbf, 0xf2, 0x99, 0x43, 0xad, 0xd4, 0xd8, 0x7a, 0x7d, 0x21, 0x4a, 0x48, 0xe2, 0x40, 0xbc, 0x74, 0x8f, 0x98, 0x6f, 0xa3, 0x24, 0x7d, 0xc4, 0xe4, 0x17, 0x91, 0x6, 0x10, 0x78, 0xfb, 0x22, 0x98, 0xb4, 0xb, 0xc9, 0x76, 0xa4, 0x31, 0xf, 0xd2, 0x38, 0xa3, 0x40, 0xf3, 0x79, 0x3a, 0xd, 0x4f, 0x2c, 0xff, 0xd9, 0x89, 0x39, 0x1f, 0xc5, 0x65, 0x33, 0x47, 0x3f, 0xe, 0x9a, 0xa1, 0x2, 0x7e, 0xed, 0x37, 0x79, 0x81, 0x94, 0x37, 0xc9, 0xc8, 0x60, 0x1, 0x89, 0x1, 0x79, 0x9b, 0x80, 0x69, 0xed, 0x4d, 0x7c, 0xa0, 0x9e, 0x7a, 0x0, 0xa2, 0x1f, 0xc1, 0xc6, 0xdc, 0x53, 0x4e, 0xb2, 0x2a, 0xd7, 0x52, 0x5b, 0x79, 0xd0, 0xf8, 0xdd, 0x27, 0x83, 0x77, 0x88, 0x77, 0x57, 0x60, 0x44, 0x7a, 0xe5, 0x7b, 0x89, 0xfc, 0x9c, 0x7d, 0xe0, 0xe, 0x61, 0xfe, 0xa, 0x70, 0x11, 0xa8, 0x5b, 0x1, 0xbc, 0xe, 0x68, 0xe7, 0xf2, 0x99, 0xa3, 0x23, 0x3d, 0x72, 0x97, 0xff, 0x6c, 0xf4, 0x9f, 0x47, 0x5c, 0xf5, 0xec, 0x64, 0x8, 0x93, 0x24, 0x3b, 0x23, 0xa8, 0x82, 0xef, 0xdc, 0x42, 0x80, 0x5f, 0x3, 0x79, 0xc7, 0x8a, 0x99, 0x27, 0xbc, 0xd7, 0x11, 0x68, 0xaf, 0x1f, 0x6, 0x0, 0x8e, 0x5, 0xd8, 0xc3, 0xf7, 0xc9, 0xa8, 0xc8, 0xc9, 0xc4, 0x9f, 0x7d, 0xa, 0x3c, 0x68, 0x2, 0x46, 0x0, 0x80, 0xd0, 0x92, 0x6c, 0x0, 0x21, 0x71, 0xbd, 0x48, 0x66, 0xab, 0xc6, 0x9b, 0x97, 0x0, 0xb2, 0x20, 0x7, 0x81, 0xdc, 0x22, 0x69, 0xeb, 0xf2, 0x99, 0xa3, 0xdb, 0xe4, 0x88, 0xba, 0x7c, 0xe6, 0xe8, 0x77, 0x46, 0x5e, 0xbd, 0x64, 0x2e, 0xc4, 0xc5, 0x90, 0x9e, 0x5, 0x70, 0xa0, 0xa4, 0x77, 0x40, 0x4e, 0x4, 0xf4, 0xc2, 0xa, 0x6f, 0xc8, 0xe8, 0x10, 0xa8, 0x1b, 0x35, 0x70, 0xf8, 0x97, 0x9f, 0x7d, 0x9e, 0xc4, 0x31, 0xbe, 0x27, 0x47, 0x5b, 0x9, 0x92, 0xd7, 0xbb, 0x3c, 0xcf, 0xd9, 0xdb, 0x1, 0x2c, 0x5, 0x70, 0x32, 0xa0, 0xb3, 0x51, 0x62, 0xdb, 0xd9, 0x90, 0xb7, 0x50, 0x45, 0x6e, 0xed, 0x45, 0xbd, 0x4d, 0x66, 0xf9, 0xcc, 0xd1, 0xd, 0x6d, 0xfa, 0x30, 0x6, 0x46, 0x5e, 0xbd, 0xe4, 0x50, 0x49, 0xc3, 0x0, 0xac, 0x5f, 0x3e, 0xf3, 0x84, 0xd, 0xed, 0x89, 0xe3, 0x48, 0x3c, 0x74, 0x74, 0x86, 0x71, 0x30, 0xe2, 0xaa, 0xe7, 0xde, 0x2, 0xd0, 0x2b, 0xbc, 0xdf, 0x50, 0x29, 0xa2, 0x14, 0xbf, 0x97, 0xf4, 0x17, 0x80, 0x13, 0x1, 0xac, 0xa1, 0x77, 0x9e, 0x71, 0x2f, 0x0, 0x7b, 0x4a, 0x6a, 0x80, 0x77, 0xbc, 0x7d, 0xf, 0x0, 0x9f, 0x2, 0xd4, 0x17, 0xc0, 0xbe, 0x0, 0x3e, 0x9, 0x78, 0x1b, 0x51, 0x55, 0xea, 0xcf, 0x1f, 0xc, 0x33, 0x92, 0x32, 0xa4, 0xe9, 0xb6, 0x7c, 0xe6, 0xf1, 0xd9, 0xb6, 0x7e, 0x1b, 0x5, 0x47, 0x7f, 0x65, 0x69, 0xea, 0xf7, 0x33, 0x8e, 0xad, 0x29, 0x8d, 0x6a, 0xa1, 0x6e, 0x86, 0x0, 0x82, 0x3f, 0x17, 0xf4, 0x15, 0xf9, 0xb, 0xa1, 0x3c, 0xbf, 0x48, 0x8f, 0x28, 0x11, 0x94, 0xf1, 0x37, 0x44, 0xf4, 0x5, 0x32, 0x6f, 0x14, 0xb8, 0xce, 0xcd, 0xba, 0x7f, 0x58, 0x39, 0xfb, 0x44, 0xb, 0x60, 0x93, 0x7f, 0xe5, 0x60, 0xc4, 0xd5, 0x2f, 0x90, 0xb0, 0x3d, 0x0, 0xee, 0x9, 0x8f, 0x21, 0xfa, 0xc8, 0x6a, 0x89, 0x31, 0x74, 0x0, 0x6f, 0x71, 0x65, 0x5, 0x83, 0x8e, 0x7f, 0xca, 0x6d, 0x32, 0xde, 0x81, 0x9d, 0x45, 0x7c, 0xa0, 0x8e, 0x18, 0x40, 0xc0, 0x8f, 0x48, 0xb3, 0x44, 0xb2, 0x97, 0x82, 0x3c, 0x2d, 0x24, 0x4, 0x14, 0xf4, 0xba, 0x7e, 0x80, 0xbf, 0xf, 0x1e, 0x20, 0x6b, 0x9, 0xe0, 0xfb, 0x12, 0x1f, 0xf5, 0x89, 0x1f, 0x9, 0xcb, 0x6f, 0x38, 0x4e, 0x0, 0xb6, 0xf8, 0x17, 0x46, 0x5c, 0xb5, 0xe4, 0x75, 0x92, 0xbf, 0x15, 0x70, 0x1c, 0x80, 0x22, 0x51, 0xa1, 0x75, 0xe1, 0x42, 0x5c, 0xa8, 0xd0, 0x9e, 0x8c, 0xdb, 0xea, 0xa8, 0x13, 0xad, 0xa, 0xea, 0x46, 0xd, 0x5c, 0x3e, 0xf3, 0xf8, 0xd7, 0x97, 0xdd, 0x30, 0xea, 0x3e, 0x80, 0xd7, 0x1, 0xbc, 0x58, 0xc2, 0xaf, 0x3, 0xe7, 0x92, 0x22, 0x87, 0x11, 0x92, 0x46, 0xa1, 0x77, 0xbf, 0x7, 0xf8, 0xbf, 0xcb, 0x67, 0x1e, 0x5f, 0xd1, 0x59, 0x43, 0xc6, 0x18, 0xd2, 0x98, 0xbb, 0x42, 0xf6, 0xf9, 0x78, 0x3b, 0x7d, 0xa1, 0x4b, 0x97, 0x6f, 0xac, 0x81, 0x5, 0xf8, 0x1a, 0xda, 0xd7, 0x61, 0xa0, 0xdd, 0xa1, 0x6e, 0xd9, 0x77, 0xc4, 0x55, 0x4b, 0x8e, 0x4, 0x30, 0x82, 0xe4, 0x89, 0x0, 0xc6, 0x1, 0x8, 0x6f, 0x11, 0x13, 0x8c, 0xc1, 0x9b, 0x1, 0x9c, 0xb5, 0x7c, 0xe6, 0xf1, 0x4b, 0xaa, 0xc9, 0x63, 0xe4, 0xd5, 0x2f, 0x1c, 0x28, 0xd9, 0x4d, 0xfe, 0xb9, 0x88, 0xa5, 0x5c, 0x0, 0xa, 0xc0, 0xd7, 0x30, 0x32, 0x92, 0x16, 0x1, 0x98, 0xbc, 0x7c, 0xe6, 0xf1, 0x65, 0x17, 0x61, 0xd6, 0x2b, 0xd4, 0x2d, 0x3, 0x4, 0x30, 0xe2, 0xea, 0xe7, 0xfb, 0x0, 0x38, 0x3, 0xc0, 0xbf, 0x10, 0x3c, 0xa, 0xc0, 0x18, 0xdf, 0x4a, 0xb0, 0x43, 0xd0, 0x95, 0xcb, 0x6f, 0x18, 0x75, 0x47, 0x8d, 0xe9, 0x3f, 0x65, 0x68, 0x8e, 0x87, 0x77, 0xf6, 0x9e, 0xe7, 0x25, 0x1c, 0xc3, 0xa, 0xb2, 0x5, 0xea, 0xc2, 0x2e, 0x2b, 0xfb, 0x9f, 0x0, 0x7e, 0xb8, 0xfc, 0x86, 0x51, 0x5d, 0xc, 0xd0, 0x11, 0x70, 0xd4, 0x57, 0x96, 0xe, 0x7, 0x30, 0x9, 0x5e, 0x6f, 0xb0, 0xe9, 0xc5, 0x19, 0xc7, 0x7e, 0xb7, 0x96, 0xf4, 0x46, 0x5e, 0xb3, 0x94, 0x92, 0x3d, 0x95, 0xe4, 0xaf, 0x0, 0xec, 0x11, 0xee, 0x5, 0x22, 0xb4, 0x90, 0x9c, 0xfc, 0xe1, 0x3f, 0x5b, 0x0, 0x63, 0x49, 0xf3, 0x48, 0x67, 0x2c, 0x4d, 0x4f, 0xa, 0x76, 0x2b, 0x6, 0x68, 0xf, 0x18, 0x79, 0xcd, 0xd2, 0x3d, 0x24, 0xbd, 0x4c, 0xf2, 0xc0, 0x62, 0xb5, 0x33, 0xce, 0x5b, 0x59, 0xd2, 0x26, 0x92, 0x2f, 0x91, 0xbc, 0xf8, 0xc5, 0x19, 0xc7, 0x6c, 0x6a, 0x4b, 0x3e, 0xf5, 0xa, 0xff, 0xf4, 0xc, 0x0, 0x0, 0x23, 0xaf, 0x7e, 0xe1, 0x7a, 0x1a, 0x5e, 0x7, 0x20, 0xe5, 0xfb, 0x61, 0x65, 0x0, 0xec, 0x82, 0xb0, 0xb, 0xc4, 0xe, 0x0, 0x5b, 0x24, 0x6d, 0x26, 0xb9, 0xd, 0xc2, 0x66, 0x41, 0x4b, 0x8c, 0x31, 0xbf, 0xfb, 0xfd, 0x4f, 0x8e, 0x59, 0x57, 0x63, 0xd6, 0x9d, 0xe, 0x75, 0xa3, 0x6, 0x76, 0x26, 0xd0, 0x98, 0xff, 0x91, 0x74, 0x8, 0x80, 0x1e, 0x24, 0xb7, 0xc0, 0xdb, 0x5b, 0x6f, 0x33, 0xd, 0xdf, 0x3, 0xf0, 0xb6, 0xa4, 0x57, 0x1, 0xbc, 0xf4, 0xe2, 0x8c, 0x63, 0xdf, 0xe9, 0xec, 0xb2, 0x76, 0x41, 0x17, 0x74, 0x41, 0x17, 0x74, 0x41, 0x17, 0x74, 0x41, 0x17, 0x74, 0x41, 0x17, 0x74, 0x41, 0x17, 0xd4, 0x6, 0xff, 0x1f, 0x32, 0x68, 0x5, 0x7e, 0x99, 0xd5, 0x97, 0x49, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char option_button_disabled_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x40,0xde,0x8d,0x6b,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x1,0x32,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3f,0x3f,0x3f,0x5a,0x5a,0x5a,0x2b,0x2b,0x31,0x2e,0x2e,0x34,0x59,0x59,0x59,0x2a,0x2a,0x30,0x4b,0x4b,0x4b,0x22,0x22,0x27,0x35,0x35,0x35,0x4a,0x4a,0x4a,0x24,0x24,0x28,0x24,0x24,0x29,0x56,0x56,0x56,0x62,0x62,0x62,0x2a,0x2a,0x31,0x2a,0x2a,0x30,0x2d,0x2d,0x34,0x2f,0x2f,0x36,0x2e,0x2e,0x35,0x2c,0x2c,0x32,0x48,0x48,0x48,0x44,0x44,0x44,0x43,0x43,0x43,0x54,0x54,0x54,0x26,0x26,0x2b,0x24,0x24,0x28,0x27,0x27,0x2d,0x29,0x29,0x2f,0x28,0x28,0x2e,0x25,0x25,0x2b,0x23,0x23,0x28,0x26,0x26,0x2c,0x25,0x25,0x2a,0x2a,0x2a,0x2f,0x2b,0x2b,0x31,0x22,0x22,0x26,0x52,0x52,0x52,0x42,0x42,0x42,0x2d,0x2d,0x33,0x22,0x22,0x27,0x51,0x51,0x51,0x40,0x40,0x40,0x27,0x27,0x2b,0x2e,0x2e,0x34,0x2c,0x2c,0x31,0x29,0x29,0x2e,0x4f,0x4f,0x4f,0x3f,0x3f,0x3f,0x4d,0x4d,0x4d,0x3e,0x3e,0x3e,0x24,0x24,0x2a,0x24,0x24,0x29,0x20,0x20,0x25,0x4c,0x4c,0x4c,0x3d,0x3d,0x3d,0x28,0x28,0x2d,0x2b,0x2b,0x30,0x29,0x29,0x2d,0x20,0x20,0x23,0x4a,0x4a,0x4a,0x3b,0x3b,0x3b,0x22,0x22,0x28,0x27,0x27,0x2c,0x1e,0x1e,0x22,0x49,0x49,0x49,0x3a,0x3a,0x3a,0x21,0x21,0x26,0x21,0x21,0x25,0x23,0x23,0x27,0x20,0x20,0x24,0x1d,0x1d,0x21,0x39,0x39,0x39,0x47,0x47,0x47,0x1f,0x1f,0x24,0x1f,0x1f,0x23,0x1e,0x1e,0x21,0x46,0x46,0x46,0xff,0xff,0xff,0xbd,0x3f,0x83,0xbb,0x0,0x0,0x0,0x24,0x74,0x52,0x4e,0x53,0x0,0x4,0xa,0x11,0x19,0x1f,0x22,0x24,0x1d,0x16,0xd,0x7,0x2,0x15,0x25,0x34,0x3f,0x46,0x47,0x48,0x43,0x3a,0x2d,0x1b,0x77,0xef,0xe6,0x49,0xef,0xe6,0xef,0xe7,0x77,0xef,0xe4,0x4a,0xba,0xea,0xc1,0xeb,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x65,0xb5,0xdd,0x88,0x9f,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x1,0xb,0x49,0x44,0x41,0x54,0x28,0xcf,0x8d,0xd1,0xd9,0x56,0xc2,0x30,0x10,0x80,0x61,0xd6,0xa2,0xa8,0x6c,0x75,0xdf,0x10,0x54,0xa8,0x82,0x74,0xd2,0x4a,0x49,0x5b,0xa4,0xb5,0x5a,0x44,0x10,0x5c,0xd0,0xaa,0x80,0x8a,0xcb,0xfb,0x3f,0x83,0x21,0x24,0x1c,0x8e,0x5e,0xe8,0x77,0xfd,0x9f,0x93,0x99,0x89,0xcf,0x1f,0x8,0x86,0xc2,0x42,0x84,0x10,0x66,0x66,0xa3,0x73,0xf3,0xbe,0x9f,0x2,0xb,0xb1,0x78,0x22,0x99,0x12,0x45,0x71,0x71,0x69,0x79,0x25,0xea,0xff,0x15,0x4,0x63,0xab,0x6b,0x7b,0xcc,0x7e,0x2e,0x2f,0x1d,0x30,0x87,0x52,0x21,0xbf,0xbe,0x41,0x82,0x50,0x7c,0xb3,0x78,0x54,0x1a,0x93,0x1,0x29,0x2a,0x73,0xac,0x94,0x35,0x6d,0x8b,0x4,0xe1,0x84,0x5c,0xe2,0xe4,0xa,0xd6,0xb,0x8c,0xa1,0x2b,0xd8,0x54,0x48,0x20,0x24,0xab,0x27,0x5c,0xb5,0x2,0x39,0x89,0xa9,0x19,0x2a,0x58,0xa3,0x20,0x92,0xb2,0x4f,0x39,0xdb,0x1,0xe3,0x8c,0xa9,0x9d,0xbb,0x60,0x3a,0xa3,0x40,0xac,0x5f,0x70,0xf5,0xe9,0xc0,0x20,0x1,0xd0,0xa0,0x71,0xc9,0x35,0xca,0x4d,0x75,0x6a,0x86,0xd6,0x15,0xa6,0x4f,0xb4,0x3b,0x5c,0x1b,0xa1,0xeb,0x1b,0x46,0xbf,0x5,0xed,0xe,0xd1,0x21,0xbb,0xf7,0x5c,0xf7,0xc1,0xf2,0x26,0x6b,0x7a,0x4d,0xeb,0xd1,0xa2,0x6b,0x3e,0x3d,0x73,0xc5,0x5e,0x1f,0x7b,0xc,0xe0,0xc1,0xcb,0xab,0x49,0xf,0xb5,0xdd,0x79,0x63,0x86,0xbd,0x77,0xd,0x33,0xad,0x41,0xff,0xe3,0x33,0x4d,0x4f,0xbd,0x93,0x19,0x7e,0x8d,0xd9,0x0,0xee,0x64,0x6,0xd7,0x41,0xd9,0xdd,0xff,0x7c,0xd6,0x5f,0xdf,0xfd,0xd,0xbf,0xaa,0x55,0xdf,0x7c,0xb2,0x44,0x90,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char option_arrow_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x6, 0x0, 0x0, 0x0, 0x56, 0x75, 0x5c, 0xe7, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0x98, 0x49, 0x44, 0x41, 0x54, 0x28, 0x91, 0xbd, 0x91, 0xb1, 0xd, 0xc2, 0x30, 0x10, 0x45, 0xdf, 0xd1, 0xb8, 0xf0, 0x2, 0xee, 0xdc, 0x87, 0x1, 0xd8, 0x24, 0xb5, 0xe9, 0x19, 0x87, 0x1e, 0xea, 0x6c, 0xc2, 0x0, 0xa4, 0xb5, 0xdc, 0x79, 0x1, 0x17, 0xae, 0x8e, 0x26, 0x48, 0x76, 0x14, 0x40, 0x48, 0x88, 0xdf, 0xfd, 0xf7, 0xef, 0x4b, 0x77, 0x3a, 0xf8, 0x85, 0x62, 0x8c, 0x21, 0xc6, 0x18, 0xb6, 0x32, 0x59, 0x83, 0x94, 0xd2, 0x5e, 0x55, 0x6f, 0x0, 0x22, 0x72, 0xf0, 0xde, 0xdf, 0xdb, 0x7c, 0xd7, 0x9a, 0x9c, 0xb3, 0x55, 0xd5, 0x9, 0xb0, 0x80, 0x55, 0xd5, 0x29, 0xe7, 0x6c, 0x5f, 0x16, 0x6a, 0xad, 0x67, 0x60, 0x68, 0xd0, 0xb0, 0xb0, 0x3f, 0xaa, 0x3b, 0x3a, 0xa5, 0x74, 0x51, 0xd5, 0xd0, 0xd, 0x88, 0x5c, 0xbd, 0xf7, 0xc7, 0xa7, 0xef, 0x6e, 0x30, 0xc6, 0x9c, 0x80, 0xb9, 0x41, 0xf3, 0xc2, 0xd8, 0x2c, 0x38, 0xe7, 0x8a, 0x88, 0x8c, 0x40, 0x1, 0x8a, 0x88, 0x8c, 0xce, 0xb9, 0xf2, 0x71, 0xcf, 0x77, 0x8f, 0xfb, 0x5a, 0xf, 0x28, 0x4a, 0x37, 0xff, 0x58, 0x46, 0x7b, 0x50, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char option_button_focus_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0xb4,0x50,0x4c,0x54,0x45,0x95,0xa9,0xb0,0x92,0xa7,0xae,0x8e,0xa2,0xa9,0x8a,0x9d,0xa4,0x85,0x98,0x9f,0x80,0x93,0x9b,0x7b,0x8f,0x96,0x77,0x8a,0x92,0x72,0x86,0x8c,0x6e,0x80,0x88,0x69,0x7c,0x84,0x64,0x77,0x7f,0x60,0x72,0x7a,0x5b,0x6e,0x75,0x56,0x69,0x71,0xc8,0xe3,0xe7,0xc8,0xe2,0xe7,0xca,0xe3,0xe7,0xce,0xe6,0xe9,0xce,0xe6,0xea,0xd0,0xe6,0xe9,0xce,0xe5,0xea,0xd0,0xe6,0xea,0xce,0xe5,0xe9,0xd0,0xe5,0xe9,0xd3,0xe7,0xeb,0xd4,0xe7,0xeb,0xd9,0xea,0xed,0xd7,0xe9,0xed,0xd7,0xea,0xed,0xdc,0xec,0xef,0xdc,0xeb,0xef,0xe0,0xed,0xf1,0xdf,0xee,0xf1,0xdf,0xed,0xf1,0xe0,0xee,0xf1,0xe3,0xf0,0xf2,0xe2,0xef,0xf2,0xe3,0xef,0xf2,0xe6,0xf1,0xf3,0xe8,0xf2,0xf5,0xe8,0xf3,0xf4,0xe8,0xf2,0xf4,0xe8,0xf3,0xf5,0xd6,0x5a,0x5b,0xd4,0x57,0x58,0xe5,0x89,0x89,0xd5,0x57,0x59,0xd5,0x58,0x59,0xd5,0x59,0x5a,0xd6,0x59,0x5a,0xd6,0x5a,0x5c,0xd7,0x5b,0x5c,0xd7,0x5b,0x5d,0xd8,0x5c,0x5d,0xd8,0x5c,0x5e,0xd8,0x5d,0x5f,0xd9,0x5d,0x5f,0xe8,0x6c,0x6e,0xff,0xff,0xff,0xa1,0xe,0x37,0x8c,0x0,0x0,0x0,0x2c,0x74,0x52,0x4e,0x53,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0xac,0x80,0x68,0x47,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x3b,0x39,0xe,0xf4,0x6c,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0xa3,0x49,0x44,0x41,0x54,0x18,0xd3,0x5d,0xce,0xdb,0x16,0x42,0x60,0x18,0x84,0xe1,0x4f,0x8,0x65,0x57,0x2a,0x45,0xd9,0x15,0xf9,0xa3,0x89,0x28,0xea,0xfe,0x2f,0x2c,0x4e,0x2c,0x79,0xd6,0xbc,0xe7,0x43,0x34,0xc5,0xe5,0x7f,0x38,0x9a,0xdd,0x31,0x72,0x9f,0x11,0xff,0x80,0x61,0x18,0xa6,0x69,0xac,0xba,0x50,0xf0,0x24,0x14,0x58,0x5b,0x9b,0xed,0xce,0xb6,0x6d,0x6b,0x8f,0x42,0x20,0xb1,0xc4,0xc1,0x71,0xe,0x7d,0x8e,0x83,0x52,0xa4,0xf9,0x13,0xae,0x7b,0x74,0x7b,0xa7,0x13,0x9e,0x73,0x92,0x72,0x78,0xbe,0xef,0x75,0x7c,0xcf,0x47,0x2e,0x91,0x5c,0x21,0x8,0xc2,0x20,0x8c,0x82,0x73,0x18,0xa1,0x92,0x49,0xa9,0x71,0x89,0xe3,0x38,0x49,0xba,0x25,0xa8,0x15,0x5a,0xbc,0x70,0x1d,0xe0,0xb5,0xa0,0xe5,0x1b,0x69,0xca,0xd8,0x8d,0x31,0x96,0x65,0x68,0x96,0xa4,0x36,0x60,0x3,0x34,0x2a,0x69,0xed,0xf8,0x7a,0xab,0x91,0xfe,0xf9,0x8e,0x7c,0x74,0xd2,0x27,0x7e,0x7e,0x46,0x20,0x17,0xe,0x2d,0x4e,0x9,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char option_button_disabled_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x40, 0xde, 0x8d, 0x6b, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x1, 0x32, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x3f, 0x3f, 0x5a, 0x5a, 0x5a, 0x2b, 0x2b, 0x31, 0x2e, 0x2e, 0x34, 0x59, 0x59, 0x59, 0x2a, 0x2a, 0x30, 0x4b, 0x4b, 0x4b, 0x22, 0x22, 0x27, 0x35, 0x35, 0x35, 0x4a, 0x4a, 0x4a, 0x24, 0x24, 0x28, 0x24, 0x24, 0x29, 0x56, 0x56, 0x56, 0x62, 0x62, 0x62, 0x2a, 0x2a, 0x31, 0x2a, 0x2a, 0x30, 0x2d, 0x2d, 0x34, 0x2f, 0x2f, 0x36, 0x2e, 0x2e, 0x35, 0x2c, 0x2c, 0x32, 0x48, 0x48, 0x48, 0x44, 0x44, 0x44, 0x43, 0x43, 0x43, 0x54, 0x54, 0x54, 0x26, 0x26, 0x2b, 0x24, 0x24, 0x28, 0x27, 0x27, 0x2d, 0x29, 0x29, 0x2f, 0x28, 0x28, 0x2e, 0x25, 0x25, 0x2b, 0x23, 0x23, 0x28, 0x26, 0x26, 0x2c, 0x25, 0x25, 0x2a, 0x2a, 0x2a, 0x2f, 0x2b, 0x2b, 0x31, 0x22, 0x22, 0x26, 0x52, 0x52, 0x52, 0x42, 0x42, 0x42, 0x2d, 0x2d, 0x33, 0x22, 0x22, 0x27, 0x51, 0x51, 0x51, 0x40, 0x40, 0x40, 0x27, 0x27, 0x2b, 0x2e, 0x2e, 0x34, 0x2c, 0x2c, 0x31, 0x29, 0x29, 0x2e, 0x4f, 0x4f, 0x4f, 0x3f, 0x3f, 0x3f, 0x4d, 0x4d, 0x4d, 0x3e, 0x3e, 0x3e, 0x24, 0x24, 0x2a, 0x24, 0x24, 0x29, 0x20, 0x20, 0x25, 0x4c, 0x4c, 0x4c, 0x3d, 0x3d, 0x3d, 0x28, 0x28, 0x2d, 0x2b, 0x2b, 0x30, 0x29, 0x29, 0x2d, 0x20, 0x20, 0x23, 0x4a, 0x4a, 0x4a, 0x3b, 0x3b, 0x3b, 0x22, 0x22, 0x28, 0x27, 0x27, 0x2c, 0x1e, 0x1e, 0x22, 0x49, 0x49, 0x49, 0x3a, 0x3a, 0x3a, 0x21, 0x21, 0x26, 0x21, 0x21, 0x25, 0x23, 0x23, 0x27, 0x20, 0x20, 0x24, 0x1d, 0x1d, 0x21, 0x39, 0x39, 0x39, 0x47, 0x47, 0x47, 0x1f, 0x1f, 0x24, 0x1f, 0x1f, 0x23, 0x1e, 0x1e, 0x21, 0x46, 0x46, 0x46, 0xff, 0xff, 0xff, 0xbd, 0x3f, 0x83, 0xbb, 0x0, 0x0, 0x0, 0x24, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x4, 0xa, 0x11, 0x19, 0x1f, 0x22, 0x24, 0x1d, 0x16, 0xd, 0x7, 0x2, 0x15, 0x25, 0x34, 0x3f, 0x46, 0x47, 0x48, 0x43, 0x3a, 0x2d, 0x1b, 0x77, 0xef, 0xe6, 0x49, 0xef, 0xe6, 0xef, 0xe7, 0x77, 0xef, 0xe4, 0x4a, 0xba, 0xea, 0xc1, 0xeb, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x65, 0xb5, 0xdd, 0x88, 0x9f, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x1, 0xb, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x8d, 0xd1, 0xd9, 0x56, 0xc2, 0x30, 0x10, 0x80, 0x61, 0xd6, 0xa2, 0xa8, 0x6c, 0x75, 0xdf, 0x10, 0x54, 0xa8, 0x82, 0x74, 0xd2, 0x4a, 0x49, 0x5b, 0xa4, 0xb5, 0x5a, 0x44, 0x10, 0x5c, 0xd0, 0xaa, 0x80, 0x8a, 0xcb, 0xfb, 0x3f, 0x83, 0x21, 0x24, 0x1c, 0x8e, 0x5e, 0xe8, 0x77, 0xfd, 0x9f, 0x93, 0x99, 0x89, 0xcf, 0x1f, 0x8, 0x86, 0xc2, 0x42, 0x84, 0x10, 0x66, 0x66, 0xa3, 0x73, 0xf3, 0xbe, 0x9f, 0x2, 0xb, 0xb1, 0x78, 0x22, 0x99, 0x12, 0x45, 0x71, 0x71, 0x69, 0x79, 0x25, 0xea, 0xff, 0x15, 0x4, 0x63, 0xab, 0x6b, 0x7b, 0xcc, 0x7e, 0x2e, 0x2f, 0x1d, 0x30, 0x87, 0x52, 0x21, 0xbf, 0xbe, 0x41, 0x82, 0x50, 0x7c, 0xb3, 0x78, 0x54, 0x1a, 0x93, 0x1, 0x29, 0x2a, 0x73, 0xac, 0x94, 0x35, 0x6d, 0x8b, 0x4, 0xe1, 0x84, 0x5c, 0xe2, 0xe4, 0xa, 0xd6, 0xb, 0x8c, 0xa1, 0x2b, 0xd8, 0x54, 0x48, 0x20, 0x24, 0xab, 0x27, 0x5c, 0xb5, 0x2, 0x39, 0x89, 0xa9, 0x19, 0x2a, 0x58, 0xa3, 0x20, 0x92, 0xb2, 0x4f, 0x39, 0xdb, 0x1, 0xe3, 0x8c, 0xa9, 0x9d, 0xbb, 0x60, 0x3a, 0xa3, 0x40, 0xac, 0x5f, 0x70, 0xf5, 0xe9, 0xc0, 0x20, 0x1, 0xd0, 0xa0, 0x71, 0xc9, 0x35, 0xca, 0x4d, 0x75, 0x6a, 0x86, 0xd6, 0x15, 0xa6, 0x4f, 0xb4, 0x3b, 0x5c, 0x1b, 0xa1, 0xeb, 0x1b, 0x46, 0xbf, 0x5, 0xed, 0xe, 0xd1, 0x21, 0xbb, 0xf7, 0x5c, 0xf7, 0xc1, 0xf2, 0x26, 0x6b, 0x7a, 0x4d, 0xeb, 0xd1, 0xa2, 0x6b, 0x3e, 0x3d, 0x73, 0xc5, 0x5e, 0x1f, 0x7b, 0xc, 0xe0, 0xc1, 0xcb, 0xab, 0x49, 0xf, 0xb5, 0xdd, 0x79, 0x63, 0x86, 0xbd, 0x77, 0xd, 0x33, 0xad, 0x41, 0xff, 0xe3, 0x33, 0x4d, 0x4f, 0xbd, 0x93, 0x19, 0x7e, 0x8d, 0xd9, 0x0, 0xee, 0x64, 0x6, 0xd7, 0x41, 0xd9, 0xdd, 0xff, 0x7c, 0xd6, 0x5f, 0xdf, 0xfd, 0xd, 0xbf, 0xaa, 0x55, 0xdf, 0x7c, 0xb2, 0x44, 0x90, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char option_button_hover_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x40,0xde,0x8d,0x6b,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x1,0x44,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x42,0x40,0x4b,0x5f,0x5a,0x6c,0x2b,0x2b,0x31,0x2e,0x2e,0x34,0x5f,0x5a,0x6b,0x2a,0x2a,0x30,0x56,0x53,0x64,0x22,0x22,0x27,0x3e,0x3b,0x46,0x57,0x53,0x63,0x24,0x24,0x28,0x24,0x24,0x29,0x5b,0x57,0x68,0x5a,0x56,0x67,0x67,0x63,0x76,0x2a,0x2a,0x31,0x2a,0x2a,0x30,0x2d,0x2d,0x34,0x2f,0x2f,0x36,0x2e,0x2e,0x35,0x2c,0x2c,0x32,0x4d,0x4a,0x57,0x49,0x46,0x52,0x48,0x45,0x51,0x5a,0x56,0x65,0x26,0x26,0x2b,0x24,0x24,0x28,0x27,0x27,0x2d,0x29,0x29,0x2f,0x28,0x28,0x2e,0x25,0x25,0x2b,0x23,0x23,0x28,0x5b,0x57,0x66,0x26,0x26,0x2c,0x25,0x25,0x2a,0x2a,0x2a,0x2f,0x2b,0x2b,0x31,0x22,0x22,0x26,0x59,0x55,0x64,0x47,0x44,0x50,0x2d,0x2d,0x33,0x22,0x22,0x27,0x58,0x54,0x64,0x46,0x43,0x50,0x27,0x27,0x2b,0x2e,0x2e,0x34,0x2c,0x2c,0x31,0x29,0x29,0x2e,0x56,0x53,0x63,0x45,0x42,0x4f,0x56,0x53,0x62,0x45,0x42,0x4e,0x24,0x24,0x2a,0x24,0x24,0x29,0x20,0x20,0x25,0x55,0x51,0x62,0x44,0x41,0x4e,0x28,0x28,0x2d,0x2b,0x2b,0x30,0x29,0x29,0x2d,0x20,0x20,0x23,0x55,0x51,0x60,0x44,0x41,0x4d,0x22,0x22,0x28,0x27,0x27,0x2c,0x1e,0x1e,0x22,0x43,0x40,0x4c,0x54,0x50,0x5f,0x21,0x21,0x26,0x21,0x21,0x25,0x23,0x23,0x27,0x20,0x20,0x24,0x1d,0x1d,0x21,0x47,0x43,0x51,0x43,0x3f,0x4d,0x42,0x3f,0x4c,0x53,0x4f,0x5f,0x1f,0x1f,0x24,0x1f,0x1f,0x23,0x1e,0x1e,0x21,0x53,0x50,0x5f,0x53,0x4f,0x5e,0x5f,0x5a,0x6c,0xff,0xff,0xff,0xd1,0x85,0xc5,0x5,0x0,0x0,0x0,0x24,0x74,0x52,0x4e,0x53,0x0,0x4,0xa,0x11,0x19,0x1f,0x22,0x24,0x1d,0x16,0xd,0x7,0x2,0x15,0x25,0x34,0x3f,0x46,0x47,0x48,0x43,0x3a,0x2d,0x1b,0x77,0xef,0xe6,0x49,0xef,0xe6,0xef,0xe7,0x77,0xef,0xe4,0x4a,0xba,0xea,0xc1,0xeb,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x6b,0x52,0x65,0xa5,0x98,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x1,0x10,0x49,0x44,0x41,0x54,0x28,0xcf,0x8d,0xd1,0xd9,0x52,0xc2,0x30,0x14,0x80,0x61,0xd6,0xa2,0xa8,0x6c,0x75,0xdf,0x77,0xa8,0xa2,0x70,0xd2,0x4a,0x25,0x6d,0x81,0x62,0xa1,0x88,0x20,0x6e,0xc5,0xaa,0x80,0xfb,0xfa,0xfe,0xf,0x60,0x49,0x13,0x86,0xd1,0xb,0xfd,0x6e,0xf3,0xcf,0xe4,0x24,0xc7,0xe3,0xf5,0xf9,0x3,0x41,0x2e,0xe4,0xe0,0x46,0x46,0xc3,0x63,0xe3,0x9e,0x9f,0x7c,0x13,0x91,0x68,0x2c,0x9e,0xe0,0x79,0x7e,0x72,0x6a,0x7a,0x26,0xec,0xfd,0x15,0xf8,0x23,0xb3,0x73,0x9b,0x5b,0xae,0xed,0x64,0x4a,0xd8,0xa1,0x76,0x85,0x74,0x6a,0x7e,0xc1,0x9,0x2,0xd1,0xc5,0xbd,0xfd,0x8c,0x2b,0xb,0x48,0x94,0xa8,0x3,0x31,0x27,0xcb,0x4b,0x4e,0x10,0x8c,0x1d,0xb2,0xf3,0x4c,0x36,0x8f,0x95,0x34,0xa5,0x2a,0x22,0xd6,0x44,0x27,0xe0,0xe2,0x85,0x22,0x53,0xc8,0x43,0x52,0xa0,0x4a,0xaa,0x4,0x7a,0x3f,0x8,0x25,0xca,0x47,0x4c,0xd9,0x0,0xb5,0x42,0x95,0xaa,0x26,0x68,0x46,0x3f,0xe0,0x6b,0xc7,0x4c,0x6d,0x38,0x50,0x9d,0x0,0x48,0x50,0x3f,0x61,0xea,0xb9,0x86,0x34,0x34,0x43,0xf3,0x14,0x93,0x2b,0x5a,0x67,0x4c,0xb,0xa1,0xf3,0xb,0x4a,0xb9,0x4,0xf9,0xa,0x91,0x21,0xad,0x36,0x63,0x5d,0xeb,0xf6,0xe0,0x99,0x76,0x43,0xbf,0xd1,0xc9,0x33,0xad,0xf6,0x2d,0x75,0xd7,0xe9,0x62,0x9b,0x2,0xdc,0xbb,0x7f,0xd0,0xc8,0x47,0x2d,0x3f,0x3e,0x3d,0xbb,0x5e,0x3a,0xaf,0x32,0xa6,0x9a,0xbd,0xee,0xdb,0xfb,0xa,0xf9,0xea,0xd5,0xb5,0x8f,0x4f,0xd7,0x17,0x80,0x39,0x98,0xc1,0x34,0xd0,0xfa,0xc6,0x7f,0x96,0xf5,0xd7,0xba,0xbf,0x1,0xfe,0x22,0x58,0x7c,0xf4,0xd2,0xd1,0x68,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char option_button_focus_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0xb4, 0x50, 0x4c, 0x54, 0x45, 0x95, 0xa9, 0xb0, 0x92, 0xa7, 0xae, 0x8e, 0xa2, 0xa9, 0x8a, 0x9d, 0xa4, 0x85, 0x98, 0x9f, 0x80, 0x93, 0x9b, 0x7b, 0x8f, 0x96, 0x77, 0x8a, 0x92, 0x72, 0x86, 0x8c, 0x6e, 0x80, 0x88, 0x69, 0x7c, 0x84, 0x64, 0x77, 0x7f, 0x60, 0x72, 0x7a, 0x5b, 0x6e, 0x75, 0x56, 0x69, 0x71, 0xc8, 0xe3, 0xe7, 0xc8, 0xe2, 0xe7, 0xca, 0xe3, 0xe7, 0xce, 0xe6, 0xe9, 0xce, 0xe6, 0xea, 0xd0, 0xe6, 0xe9, 0xce, 0xe5, 0xea, 0xd0, 0xe6, 0xea, 0xce, 0xe5, 0xe9, 0xd0, 0xe5, 0xe9, 0xd3, 0xe7, 0xeb, 0xd4, 0xe7, 0xeb, 0xd9, 0xea, 0xed, 0xd7, 0xe9, 0xed, 0xd7, 0xea, 0xed, 0xdc, 0xec, 0xef, 0xdc, 0xeb, 0xef, 0xe0, 0xed, 0xf1, 0xdf, 0xee, 0xf1, 0xdf, 0xed, 0xf1, 0xe0, 0xee, 0xf1, 0xe3, 0xf0, 0xf2, 0xe2, 0xef, 0xf2, 0xe3, 0xef, 0xf2, 0xe6, 0xf1, 0xf3, 0xe8, 0xf2, 0xf5, 0xe8, 0xf3, 0xf4, 0xe8, 0xf2, 0xf4, 0xe8, 0xf3, 0xf5, 0xd6, 0x5a, 0x5b, 0xd4, 0x57, 0x58, 0xe5, 0x89, 0x89, 0xd5, 0x57, 0x59, 0xd5, 0x58, 0x59, 0xd5, 0x59, 0x5a, 0xd6, 0x59, 0x5a, 0xd6, 0x5a, 0x5c, 0xd7, 0x5b, 0x5c, 0xd7, 0x5b, 0x5d, 0xd8, 0x5c, 0x5d, 0xd8, 0x5c, 0x5e, 0xd8, 0x5d, 0x5f, 0xd9, 0x5d, 0x5f, 0xe8, 0x6c, 0x6e, 0xff, 0xff, 0xff, 0xa1, 0xe, 0x37, 0x8c, 0x0, 0x0, 0x0, 0x2c, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0xac, 0x80, 0x68, 0x47, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x3b, 0x39, 0xe, 0xf4, 0x6c, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0xa3, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x5d, 0xce, 0xdb, 0x16, 0x42, 0x60, 0x18, 0x84, 0xe1, 0x4f, 0x8, 0x65, 0x57, 0x2a, 0x45, 0xd9, 0x15, 0xf9, 0xa3, 0x89, 0x28, 0xea, 0xfe, 0x2f, 0x2c, 0x4e, 0x2c, 0x79, 0xd6, 0xbc, 0xe7, 0x43, 0x34, 0xc5, 0xe5, 0x7f, 0x38, 0x9a, 0xdd, 0x31, 0x72, 0x9f, 0x11, 0xff, 0x80, 0x61, 0x18, 0xa6, 0x69, 0xac, 0xba, 0x50, 0xf0, 0x24, 0x14, 0x58, 0x5b, 0x9b, 0xed, 0xce, 0xb6, 0x6d, 0x6b, 0x8f, 0x42, 0x20, 0xb1, 0xc4, 0xc1, 0x71, 0xe, 0x7d, 0x8e, 0x83, 0x52, 0xa4, 0xf9, 0x13, 0xae, 0x7b, 0x74, 0x7b, 0xa7, 0x13, 0x9e, 0x73, 0x92, 0x72, 0x78, 0xbe, 0xef, 0x75, 0x7c, 0xcf, 0x47, 0x2e, 0x91, 0x5c, 0x21, 0x8, 0xc2, 0x20, 0x8c, 0x82, 0x73, 0x18, 0xa1, 0x92, 0x49, 0xa9, 0x71, 0x89, 0xe3, 0x38, 0x49, 0xba, 0x25, 0xa8, 0x15, 0x5a, 0xbc, 0x70, 0x1d, 0xe0, 0xb5, 0xa0, 0xe5, 0x1b, 0x69, 0xca, 0xd8, 0x8d, 0x31, 0x96, 0x65, 0x68, 0x96, 0xa4, 0x36, 0x60, 0x3, 0x34, 0x2a, 0x69, 0xed, 0xf8, 0x7a, 0xab, 0x91, 0xfe, 0xf9, 0x8e, 0x7c, 0x74, 0xd2, 0x27, 0x7e, 0x7e, 0x46, 0x20, 0x17, 0xe, 0x2d, 0x4e, 0x9, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char option_button_normal_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x40,0xde,0x8d,0x6b,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x1,0x44,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c,0x3a,0x44,0x56,0x53,0x61,0x2b,0x2b,0x31,0x2e,0x2e,0x34,0x56,0x52,0x60,0x2a,0x2a,0x30,0x47,0x44,0x52,0x22,0x22,0x27,0x33,0x31,0x39,0x47,0x44,0x50,0x24,0x24,0x28,0x24,0x24,0x29,0x52,0x50,0x5d,0x51,0x4f,0x5d,0x5d,0x5a,0x6a,0x2a,0x2a,0x31,0x2a,0x2a,0x30,0x2d,0x2d,0x34,0x2f,0x2f,0x36,0x2e,0x2e,0x35,0x2c,0x2c,0x32,0x46,0x42,0x4e,0x42,0x3e,0x4a,0x41,0x3e,0x49,0x51,0x4e,0x5b,0x26,0x26,0x2b,0x24,0x24,0x28,0x27,0x27,0x2d,0x29,0x29,0x2f,0x28,0x28,0x2e,0x25,0x25,0x2b,0x23,0x23,0x28,0x40,0x3e,0x48,0x50,0x4e,0x5a,0x26,0x26,0x2c,0x25,0x25,0x2a,0x2a,0x2a,0x2f,0x2b,0x2b,0x31,0x22,0x22,0x26,0x4f,0x4c,0x59,0x3f,0x3d,0x47,0x2d,0x2d,0x33,0x22,0x22,0x27,0x4e,0x4a,0x58,0x3e,0x3b,0x46,0x27,0x27,0x2b,0x2e,0x2e,0x34,0x2c,0x2c,0x31,0x29,0x29,0x2e,0x4b,0x49,0x55,0x3c,0x3a,0x44,0x4a,0x47,0x54,0x3b,0x39,0x43,0x24,0x24,0x2a,0x24,0x24,0x29,0x20,0x20,0x25,0x49,0x46,0x53,0x3a,0x38,0x42,0x28,0x28,0x2d,0x2b,0x2b,0x30,0x29,0x29,0x2d,0x20,0x20,0x23,0x47,0x45,0x50,0x39,0x37,0x40,0x22,0x22,0x28,0x27,0x27,0x2c,0x1e,0x1e,0x22,0x47,0x43,0x50,0x38,0x35,0x3f,0x46,0x42,0x4f,0x21,0x21,0x26,0x21,0x21,0x25,0x23,0x23,0x27,0x20,0x20,0x24,0x1d,0x1d,0x21,0x36,0x34,0x3e,0x44,0x41,0x4e,0x1f,0x1f,0x24,0x1f,0x1f,0x23,0x1e,0x1e,0x21,0x44,0x42,0x4d,0x44,0x41,0x4c,0x4e,0x4b,0x58,0xff,0xff,0xff,0xd7,0xc8,0xfe,0x88,0x0,0x0,0x0,0x24,0x74,0x52,0x4e,0x53,0x0,0x4,0xa,0x11,0x19,0x1f,0x22,0x24,0x1d,0x16,0xd,0x7,0x2,0x15,0x25,0x34,0x3f,0x46,0x47,0x48,0x43,0x3a,0x2d,0x1b,0x77,0xef,0xe6,0x49,0xef,0xe6,0xef,0xe7,0x77,0xef,0xe4,0x4a,0xba,0xea,0xc1,0xeb,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x6b,0x52,0x65,0xa5,0x98,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x4,0x4e,0x1d,0x2,0xaf,0x0,0x0,0x1,0xe,0x49,0x44,0x41,0x54,0x28,0xcf,0x8d,0xd1,0xd7,0x56,0xc2,0x40,0x10,0x80,0x61,0x6a,0x50,0x54,0x5a,0xec,0xbd,0x43,0x14,0x85,0xdd,0x44,0xa2,0x6c,0x12,0x20,0x18,0xd,0x22,0x8,0x16,0x34,0x16,0xc0,0x5e,0xde,0xff,0x1,0x5c,0x36,0xb3,0x1c,0x8e,0x5e,0xe8,0x77,0xfd,0x9f,0xb3,0x33,0xb3,0x1e,0xaf,0xcf,0x1f,0x8,0xa,0x21,0x4a,0x18,0x1a,0xe,0x8f,0x8c,0x7a,0x7e,0xf2,0x8d,0x45,0xa2,0xb1,0x78,0x42,0x14,0xc5,0xf1,0x89,0xc9,0xa9,0xb0,0xf7,0x57,0xe0,0x8f,0x4c,0xcf,0xac,0x6f,0xb8,0x36,0x93,0x29,0x69,0xb,0x6c,0x4b,0xe9,0xd4,0xec,0x1c,0xd,0x2,0xd1,0xf9,0x9d,0xdd,0x8c,0x2b,0x8b,0xb0,0xac,0x80,0x3d,0x39,0xa7,0xaa,0xb,0x34,0x8,0xc6,0xb2,0x99,0x7d,0x70,0x90,0x27,0x5a,0x1a,0xe8,0x9a,0x4c,0xc,0x99,0x6,0x42,0xbc,0x50,0xe4,0xa,0x79,0x94,0x94,0x40,0x49,0x57,0x90,0xd9,0xb,0x42,0x89,0xf2,0x21,0x57,0xb6,0x90,0x7e,0x4,0x4a,0xc7,0x36,0x32,0xac,0x5e,0x20,0x56,0x4e,0xb8,0xca,0x60,0xa0,0xd3,0x0,0xb1,0xa0,0x7a,0xca,0x55,0x73,0x35,0x65,0x60,0x86,0xfa,0x19,0x61,0x4f,0x34,0x9a,0x5c,0x3,0xe3,0xf3,0xb,0xa0,0x5d,0x22,0xf5,0xa,0xb3,0x21,0x5b,0xd7,0x5c,0xeb,0xc6,0x74,0xfa,0x6b,0x3a,0x35,0xf3,0xd6,0x64,0x6b,0xde,0xdd,0x73,0xf,0xed,0xe,0x71,0x0,0x22,0xdd,0xc7,0x27,0x83,0x1d,0x6a,0xb1,0xf9,0xc,0x5e,0xda,0xaf,0x2a,0x1,0xf5,0x6e,0xe7,0xed,0x7d,0x89,0x9d,0x7a,0x79,0xe5,0xe3,0xd3,0xf5,0x85,0x90,0xdd,0x9f,0xc1,0xb6,0xf0,0xea,0xda,0x7f,0x3e,0xeb,0xaf,0xef,0xfe,0x6,0x1a,0x96,0x59,0x89,0x91,0xf7,0xf1,0x7b,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char option_button_hover_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x40, 0xde, 0x8d, 0x6b, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x1, 0x44, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x42, 0x40, 0x4b, 0x5f, 0x5a, 0x6c, 0x2b, 0x2b, 0x31, 0x2e, 0x2e, 0x34, 0x5f, 0x5a, 0x6b, 0x2a, 0x2a, 0x30, 0x56, 0x53, 0x64, 0x22, 0x22, 0x27, 0x3e, 0x3b, 0x46, 0x57, 0x53, 0x63, 0x24, 0x24, 0x28, 0x24, 0x24, 0x29, 0x5b, 0x57, 0x68, 0x5a, 0x56, 0x67, 0x67, 0x63, 0x76, 0x2a, 0x2a, 0x31, 0x2a, 0x2a, 0x30, 0x2d, 0x2d, 0x34, 0x2f, 0x2f, 0x36, 0x2e, 0x2e, 0x35, 0x2c, 0x2c, 0x32, 0x4d, 0x4a, 0x57, 0x49, 0x46, 0x52, 0x48, 0x45, 0x51, 0x5a, 0x56, 0x65, 0x26, 0x26, 0x2b, 0x24, 0x24, 0x28, 0x27, 0x27, 0x2d, 0x29, 0x29, 0x2f, 0x28, 0x28, 0x2e, 0x25, 0x25, 0x2b, 0x23, 0x23, 0x28, 0x5b, 0x57, 0x66, 0x26, 0x26, 0x2c, 0x25, 0x25, 0x2a, 0x2a, 0x2a, 0x2f, 0x2b, 0x2b, 0x31, 0x22, 0x22, 0x26, 0x59, 0x55, 0x64, 0x47, 0x44, 0x50, 0x2d, 0x2d, 0x33, 0x22, 0x22, 0x27, 0x58, 0x54, 0x64, 0x46, 0x43, 0x50, 0x27, 0x27, 0x2b, 0x2e, 0x2e, 0x34, 0x2c, 0x2c, 0x31, 0x29, 0x29, 0x2e, 0x56, 0x53, 0x63, 0x45, 0x42, 0x4f, 0x56, 0x53, 0x62, 0x45, 0x42, 0x4e, 0x24, 0x24, 0x2a, 0x24, 0x24, 0x29, 0x20, 0x20, 0x25, 0x55, 0x51, 0x62, 0x44, 0x41, 0x4e, 0x28, 0x28, 0x2d, 0x2b, 0x2b, 0x30, 0x29, 0x29, 0x2d, 0x20, 0x20, 0x23, 0x55, 0x51, 0x60, 0x44, 0x41, 0x4d, 0x22, 0x22, 0x28, 0x27, 0x27, 0x2c, 0x1e, 0x1e, 0x22, 0x43, 0x40, 0x4c, 0x54, 0x50, 0x5f, 0x21, 0x21, 0x26, 0x21, 0x21, 0x25, 0x23, 0x23, 0x27, 0x20, 0x20, 0x24, 0x1d, 0x1d, 0x21, 0x47, 0x43, 0x51, 0x43, 0x3f, 0x4d, 0x42, 0x3f, 0x4c, 0x53, 0x4f, 0x5f, 0x1f, 0x1f, 0x24, 0x1f, 0x1f, 0x23, 0x1e, 0x1e, 0x21, 0x53, 0x50, 0x5f, 0x53, 0x4f, 0x5e, 0x5f, 0x5a, 0x6c, 0xff, 0xff, 0xff, 0xd1, 0x85, 0xc5, 0x5, 0x0, 0x0, 0x0, 0x24, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x4, 0xa, 0x11, 0x19, 0x1f, 0x22, 0x24, 0x1d, 0x16, 0xd, 0x7, 0x2, 0x15, 0x25, 0x34, 0x3f, 0x46, 0x47, 0x48, 0x43, 0x3a, 0x2d, 0x1b, 0x77, 0xef, 0xe6, 0x49, 0xef, 0xe6, 0xef, 0xe7, 0x77, 0xef, 0xe4, 0x4a, 0xba, 0xea, 0xc1, 0xeb, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x6b, 0x52, 0x65, 0xa5, 0x98, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x1, 0x10, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x8d, 0xd1, 0xd9, 0x52, 0xc2, 0x30, 0x14, 0x80, 0x61, 0xd6, 0xa2, 0xa8, 0x6c, 0x75, 0xdf, 0x77, 0xa8, 0xa2, 0x70, 0xd2, 0x4a, 0x25, 0x6d, 0x81, 0x62, 0xa1, 0x88, 0x20, 0x6e, 0xc5, 0xaa, 0x80, 0xfb, 0xfa, 0xfe, 0xf, 0x60, 0x49, 0x13, 0x86, 0xd1, 0xb, 0xfd, 0x6e, 0xf3, 0xcf, 0xe4, 0x24, 0xc7, 0xe3, 0xf5, 0xf9, 0x3, 0x41, 0x2e, 0xe4, 0xe0, 0x46, 0x46, 0xc3, 0x63, 0xe3, 0x9e, 0x9f, 0x7c, 0x13, 0x91, 0x68, 0x2c, 0x9e, 0xe0, 0x79, 0x7e, 0x72, 0x6a, 0x7a, 0x26, 0xec, 0xfd, 0x15, 0xf8, 0x23, 0xb3, 0x73, 0x9b, 0x5b, 0xae, 0xed, 0x64, 0x4a, 0xd8, 0xa1, 0x76, 0x85, 0x74, 0x6a, 0x7e, 0xc1, 0x9, 0x2, 0xd1, 0xc5, 0xbd, 0xfd, 0x8c, 0x2b, 0xb, 0x48, 0x94, 0xa8, 0x3, 0x31, 0x27, 0xcb, 0x4b, 0x4e, 0x10, 0x8c, 0x1d, 0xb2, 0xf3, 0x4c, 0x36, 0x8f, 0x95, 0x34, 0xa5, 0x2a, 0x22, 0xd6, 0x44, 0x27, 0xe0, 0xe2, 0x85, 0x22, 0x53, 0xc8, 0x43, 0x52, 0xa0, 0x4a, 0xaa, 0x4, 0x7a, 0x3f, 0x8, 0x25, 0xca, 0x47, 0x4c, 0xd9, 0x0, 0xb5, 0x42, 0x95, 0xaa, 0x26, 0x68, 0x46, 0x3f, 0xe0, 0x6b, 0xc7, 0x4c, 0x6d, 0x38, 0x50, 0x9d, 0x0, 0x48, 0x50, 0x3f, 0x61, 0xea, 0xb9, 0x86, 0x34, 0x34, 0x43, 0xf3, 0x14, 0x93, 0x2b, 0x5a, 0x67, 0x4c, 0xb, 0xa1, 0xf3, 0xb, 0x4a, 0xb9, 0x4, 0xf9, 0xa, 0x91, 0x21, 0xad, 0x36, 0x63, 0x5d, 0xeb, 0xf6, 0xe0, 0x99, 0x76, 0x43, 0xbf, 0xd1, 0xc9, 0x33, 0xad, 0xf6, 0x2d, 0x75, 0xd7, 0xe9, 0x62, 0x9b, 0x2, 0xdc, 0xbb, 0x7f, 0xd0, 0xc8, 0x47, 0x2d, 0x3f, 0x3e, 0x3d, 0xbb, 0x5e, 0x3a, 0xaf, 0x32, 0xa6, 0x9a, 0xbd, 0xee, 0xdb, 0xfb, 0xa, 0xf9, 0xea, 0xd5, 0xb5, 0x8f, 0x4f, 0xd7, 0x17, 0x80, 0x39, 0x98, 0xc1, 0x34, 0xd0, 0xfa, 0xc6, 0x7f, 0x96, 0xf5, 0xd7, 0xba, 0xbf, 0x1, 0xfe, 0x22, 0x58, 0x7c, 0xf4, 0xd2, 0xd1, 0x68, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char option_button_pressed_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x40,0xde,0x8d,0x6b,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x1,0x4d,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x31,0x2f,0x37,0x46,0x43,0x4f,0x2b,0x2b,0x31,0x2e,0x2e,0x34,0x47,0x44,0x50,0x2a,0x2a,0x30,0x55,0x52,0x5f,0x22,0x22,0x27,0x3d,0x3a,0x45,0x56,0x52,0x60,0x24,0x24,0x28,0x24,0x24,0x29,0x43,0x40,0x4c,0x42,0x40,0x4b,0x4c,0x49,0x56,0x2a,0x2a,0x31,0x2a,0x2a,0x30,0x2d,0x2d,0x34,0x2f,0x2f,0x36,0x2e,0x2e,0x35,0x2c,0x2c,0x32,0x3a,0x38,0x41,0x36,0x34,0x3d,0x44,0x41,0x4c,0x26,0x26,0x2b,0x24,0x24,0x28,0x27,0x27,0x2d,0x29,0x29,0x2f,0x28,0x28,0x2e,0x25,0x25,0x2b,0x23,0x23,0x28,0x44,0x42,0x4e,0x36,0x34,0x3e,0x44,0x41,0x4e,0x26,0x26,0x2c,0x25,0x25,0x2a,0x2a,0x2a,0x2f,0x2b,0x2b,0x31,0x22,0x22,0x26,0x46,0x42,0x4f,0x38,0x35,0x3f,0x2d,0x2d,0x33,0x22,0x22,0x27,0x47,0x45,0x50,0x39,0x37,0x40,0x27,0x27,0x2b,0x2e,0x2e,0x34,0x2c,0x2c,0x31,0x29,0x29,0x2e,0x49,0x46,0x53,0x3a,0x38,0x42,0x4a,0x47,0x54,0x3b,0x39,0x43,0x24,0x24,0x2a,0x24,0x24,0x29,0x20,0x20,0x25,0x4b,0x49,0x55,0x3c,0x3a,0x44,0x28,0x28,0x2d,0x2b,0x2b,0x30,0x29,0x29,0x2d,0x20,0x20,0x23,0x4e,0x4a,0x58,0x3e,0x3b,0x46,0x22,0x22,0x28,0x27,0x27,0x2c,0x1e,0x1e,0x22,0x50,0x4d,0x5a,0x3f,0x3d,0x48,0x3f,0x3d,0x47,0x4f,0x4c,0x59,0x21,0x21,0x26,0x21,0x21,0x25,0x23,0x23,0x27,0x20,0x20,0x24,0x1d,0x1d,0x21,0x45,0x42,0x4d,0x41,0x3e,0x49,0x40,0x3e,0x48,0x50,0x4e,0x5a,0x1f,0x1f,0x24,0x1f,0x1f,0x23,0x1e,0x1e,0x21,0x52,0x4e,0x5c,0x51,0x4e,0x5b,0x5d,0x59,0x69,0xff,0xff,0xff,0x2,0x4e,0xff,0xf1,0x0,0x0,0x0,0x24,0x74,0x52,0x4e,0x53,0x0,0x4,0xa,0x11,0x19,0x1f,0x22,0x24,0x1d,0x16,0xd,0x7,0x2,0x15,0x25,0x34,0x3f,0x46,0x47,0x48,0x43,0x3a,0x2d,0x1b,0x77,0xef,0xe6,0x49,0xef,0xe6,0xef,0xe7,0x77,0xef,0xe4,0x4a,0xba,0xea,0xc1,0xeb,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x6e,0x22,0xf,0x51,0x17,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x1,0xe,0x49,0x44,0x41,0x54,0x28,0xcf,0x8d,0xd1,0x57,0x53,0xc2,0x40,0x10,0xc0,0x71,0x6a,0x50,0x54,0x5a,0xec,0xbd,0x43,0x14,0xf5,0x2e,0x91,0xa8,0x5c,0x12,0x20,0x18,0xd,0x22,0x88,0xd,0x8d,0xd,0xb0,0xd7,0xef,0xff,0xea,0x71,0xd9,0x63,0x18,0x7d,0xd0,0xdf,0xf3,0x7f,0xe6,0x76,0xf7,0x3c,0x5e,0x9f,0x3f,0x10,0x14,0x42,0x94,0xd0,0xd3,0x1b,0xee,0xeb,0xf7,0xfc,0xe4,0x1b,0x88,0x44,0x63,0xf1,0x84,0x28,0x8a,0x83,0x43,0xc3,0x23,0x61,0xef,0xaf,0xc0,0x1f,0x19,0x1d,0x5b,0x5c,0x72,0x2d,0x27,0x53,0xd2,0xa,0x58,0x95,0xd2,0xa9,0xf1,0x9,0x1a,0x4,0xa2,0x93,0x6b,0xeb,0x60,0x3,0x61,0x59,0x1,0x9b,0x72,0x46,0x55,0xa7,0x68,0x10,0x8c,0x6d,0x6d,0x73,0x3b,0x59,0xa2,0xa5,0x81,0xae,0xc9,0xc4,0x90,0x69,0x20,0xc4,0x73,0x79,0x2e,0x97,0x45,0x49,0x9,0x14,0x74,0x5,0x99,0xed,0x20,0x94,0x28,0xee,0x72,0x45,0xb,0xe9,0x7b,0xa0,0xb0,0x6f,0x23,0xc3,0x6a,0x7,0x62,0xe9,0x80,0x2b,0x75,0x7,0x3a,0xd,0x10,0xb,0xca,0x87,0x5c,0x39,0x53,0x51,0xba,0x66,0xa8,0x1e,0x11,0xf6,0x44,0xed,0x98,0xab,0x61,0x7c,0x72,0xa,0xb4,0x33,0xa4,0x9e,0x63,0x36,0x64,0xfd,0x82,0xab,0x5f,0x9a,0x4e,0x67,0x4d,0xa7,0x62,0x5e,0x99,0x6c,0xcd,0xeb,0x9b,0x5b,0x70,0xd7,0x68,0x12,0x7,0x20,0xd2,0xba,0x7f,0x30,0xd8,0xa1,0xa6,0x1f,0x9f,0x9e,0x5d,0x2f,0x8d,0x57,0x95,0x80,0x6a,0xab,0xf9,0xf6,0x3e,0xc3,0x4e,0x3d,0x3b,0xf7,0xf1,0xe9,0xfa,0x42,0xc8,0xee,0xcc,0x60,0x5b,0x78,0x7e,0xe1,0x3f,0x9f,0xf5,0xd7,0x77,0x7f,0x3,0x1c,0x7f,0x59,0xc2,0x5e,0xdd,0xbf,0x43,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char option_button_normal_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x40, 0xde, 0x8d, 0x6b, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x1, 0x44, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x3a, 0x44, 0x56, 0x53, 0x61, 0x2b, 0x2b, 0x31, 0x2e, 0x2e, 0x34, 0x56, 0x52, 0x60, 0x2a, 0x2a, 0x30, 0x47, 0x44, 0x52, 0x22, 0x22, 0x27, 0x33, 0x31, 0x39, 0x47, 0x44, 0x50, 0x24, 0x24, 0x28, 0x24, 0x24, 0x29, 0x52, 0x50, 0x5d, 0x51, 0x4f, 0x5d, 0x5d, 0x5a, 0x6a, 0x2a, 0x2a, 0x31, 0x2a, 0x2a, 0x30, 0x2d, 0x2d, 0x34, 0x2f, 0x2f, 0x36, 0x2e, 0x2e, 0x35, 0x2c, 0x2c, 0x32, 0x46, 0x42, 0x4e, 0x42, 0x3e, 0x4a, 0x41, 0x3e, 0x49, 0x51, 0x4e, 0x5b, 0x26, 0x26, 0x2b, 0x24, 0x24, 0x28, 0x27, 0x27, 0x2d, 0x29, 0x29, 0x2f, 0x28, 0x28, 0x2e, 0x25, 0x25, 0x2b, 0x23, 0x23, 0x28, 0x40, 0x3e, 0x48, 0x50, 0x4e, 0x5a, 0x26, 0x26, 0x2c, 0x25, 0x25, 0x2a, 0x2a, 0x2a, 0x2f, 0x2b, 0x2b, 0x31, 0x22, 0x22, 0x26, 0x4f, 0x4c, 0x59, 0x3f, 0x3d, 0x47, 0x2d, 0x2d, 0x33, 0x22, 0x22, 0x27, 0x4e, 0x4a, 0x58, 0x3e, 0x3b, 0x46, 0x27, 0x27, 0x2b, 0x2e, 0x2e, 0x34, 0x2c, 0x2c, 0x31, 0x29, 0x29, 0x2e, 0x4b, 0x49, 0x55, 0x3c, 0x3a, 0x44, 0x4a, 0x47, 0x54, 0x3b, 0x39, 0x43, 0x24, 0x24, 0x2a, 0x24, 0x24, 0x29, 0x20, 0x20, 0x25, 0x49, 0x46, 0x53, 0x3a, 0x38, 0x42, 0x28, 0x28, 0x2d, 0x2b, 0x2b, 0x30, 0x29, 0x29, 0x2d, 0x20, 0x20, 0x23, 0x47, 0x45, 0x50, 0x39, 0x37, 0x40, 0x22, 0x22, 0x28, 0x27, 0x27, 0x2c, 0x1e, 0x1e, 0x22, 0x47, 0x43, 0x50, 0x38, 0x35, 0x3f, 0x46, 0x42, 0x4f, 0x21, 0x21, 0x26, 0x21, 0x21, 0x25, 0x23, 0x23, 0x27, 0x20, 0x20, 0x24, 0x1d, 0x1d, 0x21, 0x36, 0x34, 0x3e, 0x44, 0x41, 0x4e, 0x1f, 0x1f, 0x24, 0x1f, 0x1f, 0x23, 0x1e, 0x1e, 0x21, 0x44, 0x42, 0x4d, 0x44, 0x41, 0x4c, 0x4e, 0x4b, 0x58, 0xff, 0xff, 0xff, 0xd7, 0xc8, 0xfe, 0x88, 0x0, 0x0, 0x0, 0x24, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x4, 0xa, 0x11, 0x19, 0x1f, 0x22, 0x24, 0x1d, 0x16, 0xd, 0x7, 0x2, 0x15, 0x25, 0x34, 0x3f, 0x46, 0x47, 0x48, 0x43, 0x3a, 0x2d, 0x1b, 0x77, 0xef, 0xe6, 0x49, 0xef, 0xe6, 0xef, 0xe7, 0x77, 0xef, 0xe4, 0x4a, 0xba, 0xea, 0xc1, 0xeb, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x6b, 0x52, 0x65, 0xa5, 0x98, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x4, 0x4e, 0x1d, 0x2, 0xaf, 0x0, 0x0, 0x1, 0xe, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x8d, 0xd1, 0xd7, 0x56, 0xc2, 0x40, 0x10, 0x80, 0x61, 0x6a, 0x50, 0x54, 0x5a, 0xec, 0xbd, 0x43, 0x14, 0x85, 0xdd, 0x44, 0xa2, 0x6c, 0x12, 0x20, 0x18, 0xd, 0x22, 0x8, 0x16, 0x34, 0x16, 0xc0, 0x5e, 0xde, 0xff, 0x1, 0x5c, 0x36, 0xb3, 0x1c, 0x8e, 0x5e, 0xe8, 0x77, 0xfd, 0x9f, 0xb3, 0x33, 0xb3, 0x1e, 0xaf, 0xcf, 0x1f, 0x8, 0xa, 0x21, 0x4a, 0x18, 0x1a, 0xe, 0x8f, 0x8c, 0x7a, 0x7e, 0xf2, 0x8d, 0x45, 0xa2, 0xb1, 0x78, 0x42, 0x14, 0xc5, 0xf1, 0x89, 0xc9, 0xa9, 0xb0, 0xf7, 0x57, 0xe0, 0x8f, 0x4c, 0xcf, 0xac, 0x6f, 0xb8, 0x36, 0x93, 0x29, 0x69, 0xb, 0x6c, 0x4b, 0xe9, 0xd4, 0xec, 0x1c, 0xd, 0x2, 0xd1, 0xf9, 0x9d, 0xdd, 0x8c, 0x2b, 0x8b, 0xb0, 0xac, 0x80, 0x3d, 0x39, 0xa7, 0xaa, 0xb, 0x34, 0x8, 0xc6, 0xb2, 0x99, 0x7d, 0x70, 0x90, 0x27, 0x5a, 0x1a, 0xe8, 0x9a, 0x4c, 0xc, 0x99, 0x6, 0x42, 0xbc, 0x50, 0xe4, 0xa, 0x79, 0x94, 0x94, 0x40, 0x49, 0x57, 0x90, 0xd9, 0xb, 0x42, 0x89, 0xf2, 0x21, 0x57, 0xb6, 0x90, 0x7e, 0x4, 0x4a, 0xc7, 0x36, 0x32, 0xac, 0x5e, 0x20, 0x56, 0x4e, 0xb8, 0xca, 0x60, 0xa0, 0xd3, 0x0, 0xb1, 0xa0, 0x7a, 0xca, 0x55, 0x73, 0x35, 0x65, 0x60, 0x86, 0xfa, 0x19, 0x61, 0x4f, 0x34, 0x9a, 0x5c, 0x3, 0xe3, 0xf3, 0xb, 0xa0, 0x5d, 0x22, 0xf5, 0xa, 0xb3, 0x21, 0x5b, 0xd7, 0x5c, 0xeb, 0xc6, 0x74, 0xfa, 0x6b, 0x3a, 0x35, 0xf3, 0xd6, 0x64, 0x6b, 0xde, 0xdd, 0x73, 0xf, 0xed, 0xe, 0x71, 0x0, 0x22, 0xdd, 0xc7, 0x27, 0x83, 0x1d, 0x6a, 0xb1, 0xf9, 0xc, 0x5e, 0xda, 0xaf, 0x2a, 0x1, 0xf5, 0x6e, 0xe7, 0xed, 0x7d, 0x89, 0x9d, 0x7a, 0x79, 0xe5, 0xe3, 0xd3, 0xf5, 0x85, 0x90, 0xdd, 0x9f, 0xc1, 0xb6, 0xf0, 0xea, 0xda, 0x7f, 0x3e, 0xeb, 0xaf, 0xef, 0xfe, 0x6, 0x1a, 0x96, 0x59, 0x89, 0x91, 0xf7, 0xf1, 0x7b, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char panel_bg_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x1,0x3,0x0,0x0,0x0,0xfe,0xc1,0x2c,0xc8,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x6,0x50,0x4c,0x54,0x45,0x25,0x25,0x2a,0x35,0x32,0x3b,0x4a,0x73,0x58,0x4a,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x1,0xff,0x2,0x2d,0xde,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0xb,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0x40,0x5,0x0,0x0,0x10,0x0,0x1,0xa1,0xc5,0x21,0xc1,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char option_button_pressed_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x40, 0xde, 0x8d, 0x6b, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x1, 0x4d, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x31, 0x2f, 0x37, 0x46, 0x43, 0x4f, 0x2b, 0x2b, 0x31, 0x2e, 0x2e, 0x34, 0x47, 0x44, 0x50, 0x2a, 0x2a, 0x30, 0x55, 0x52, 0x5f, 0x22, 0x22, 0x27, 0x3d, 0x3a, 0x45, 0x56, 0x52, 0x60, 0x24, 0x24, 0x28, 0x24, 0x24, 0x29, 0x43, 0x40, 0x4c, 0x42, 0x40, 0x4b, 0x4c, 0x49, 0x56, 0x2a, 0x2a, 0x31, 0x2a, 0x2a, 0x30, 0x2d, 0x2d, 0x34, 0x2f, 0x2f, 0x36, 0x2e, 0x2e, 0x35, 0x2c, 0x2c, 0x32, 0x3a, 0x38, 0x41, 0x36, 0x34, 0x3d, 0x44, 0x41, 0x4c, 0x26, 0x26, 0x2b, 0x24, 0x24, 0x28, 0x27, 0x27, 0x2d, 0x29, 0x29, 0x2f, 0x28, 0x28, 0x2e, 0x25, 0x25, 0x2b, 0x23, 0x23, 0x28, 0x44, 0x42, 0x4e, 0x36, 0x34, 0x3e, 0x44, 0x41, 0x4e, 0x26, 0x26, 0x2c, 0x25, 0x25, 0x2a, 0x2a, 0x2a, 0x2f, 0x2b, 0x2b, 0x31, 0x22, 0x22, 0x26, 0x46, 0x42, 0x4f, 0x38, 0x35, 0x3f, 0x2d, 0x2d, 0x33, 0x22, 0x22, 0x27, 0x47, 0x45, 0x50, 0x39, 0x37, 0x40, 0x27, 0x27, 0x2b, 0x2e, 0x2e, 0x34, 0x2c, 0x2c, 0x31, 0x29, 0x29, 0x2e, 0x49, 0x46, 0x53, 0x3a, 0x38, 0x42, 0x4a, 0x47, 0x54, 0x3b, 0x39, 0x43, 0x24, 0x24, 0x2a, 0x24, 0x24, 0x29, 0x20, 0x20, 0x25, 0x4b, 0x49, 0x55, 0x3c, 0x3a, 0x44, 0x28, 0x28, 0x2d, 0x2b, 0x2b, 0x30, 0x29, 0x29, 0x2d, 0x20, 0x20, 0x23, 0x4e, 0x4a, 0x58, 0x3e, 0x3b, 0x46, 0x22, 0x22, 0x28, 0x27, 0x27, 0x2c, 0x1e, 0x1e, 0x22, 0x50, 0x4d, 0x5a, 0x3f, 0x3d, 0x48, 0x3f, 0x3d, 0x47, 0x4f, 0x4c, 0x59, 0x21, 0x21, 0x26, 0x21, 0x21, 0x25, 0x23, 0x23, 0x27, 0x20, 0x20, 0x24, 0x1d, 0x1d, 0x21, 0x45, 0x42, 0x4d, 0x41, 0x3e, 0x49, 0x40, 0x3e, 0x48, 0x50, 0x4e, 0x5a, 0x1f, 0x1f, 0x24, 0x1f, 0x1f, 0x23, 0x1e, 0x1e, 0x21, 0x52, 0x4e, 0x5c, 0x51, 0x4e, 0x5b, 0x5d, 0x59, 0x69, 0xff, 0xff, 0xff, 0x2, 0x4e, 0xff, 0xf1, 0x0, 0x0, 0x0, 0x24, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x4, 0xa, 0x11, 0x19, 0x1f, 0x22, 0x24, 0x1d, 0x16, 0xd, 0x7, 0x2, 0x15, 0x25, 0x34, 0x3f, 0x46, 0x47, 0x48, 0x43, 0x3a, 0x2d, 0x1b, 0x77, 0xef, 0xe6, 0x49, 0xef, 0xe6, 0xef, 0xe7, 0x77, 0xef, 0xe4, 0x4a, 0xba, 0xea, 0xc1, 0xeb, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x6e, 0x22, 0xf, 0x51, 0x17, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x1, 0xe, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x8d, 0xd1, 0x57, 0x53, 0xc2, 0x40, 0x10, 0xc0, 0x71, 0x6a, 0x50, 0x54, 0x5a, 0xec, 0xbd, 0x43, 0x14, 0xf5, 0x2e, 0x91, 0xa8, 0x5c, 0x12, 0x20, 0x18, 0xd, 0x22, 0x88, 0xd, 0x8d, 0xd, 0xb0, 0xd7, 0xef, 0xff, 0xea, 0x71, 0xd9, 0x63, 0x18, 0x7d, 0xd0, 0xdf, 0xf3, 0x7f, 0xe6, 0x76, 0xf7, 0x3c, 0x5e, 0x9f, 0x3f, 0x10, 0x14, 0x42, 0x94, 0xd0, 0xd3, 0x1b, 0xee, 0xeb, 0xf7, 0xfc, 0xe4, 0x1b, 0x88, 0x44, 0x63, 0xf1, 0x84, 0x28, 0x8a, 0x83, 0x43, 0xc3, 0x23, 0x61, 0xef, 0xaf, 0xc0, 0x1f, 0x19, 0x1d, 0x5b, 0x5c, 0x72, 0x2d, 0x27, 0x53, 0xd2, 0xa, 0x58, 0x95, 0xd2, 0xa9, 0xf1, 0x9, 0x1a, 0x4, 0xa2, 0x93, 0x6b, 0xeb, 0x60, 0x3, 0x61, 0x59, 0x1, 0x9b, 0x72, 0x46, 0x55, 0xa7, 0x68, 0x10, 0x8c, 0x6d, 0x6d, 0x73, 0x3b, 0x59, 0xa2, 0xa5, 0x81, 0xae, 0xc9, 0xc4, 0x90, 0x69, 0x20, 0xc4, 0x73, 0x79, 0x2e, 0x97, 0x45, 0x49, 0x9, 0x14, 0x74, 0x5, 0x99, 0xed, 0x20, 0x94, 0x28, 0xee, 0x72, 0x45, 0xb, 0xe9, 0x7b, 0xa0, 0xb0, 0x6f, 0x23, 0xc3, 0x6a, 0x7, 0x62, 0xe9, 0x80, 0x2b, 0x75, 0x7, 0x3a, 0xd, 0x10, 0xb, 0xca, 0x87, 0x5c, 0x39, 0x53, 0x51, 0xba, 0x66, 0xa8, 0x1e, 0x11, 0xf6, 0x44, 0xed, 0x98, 0xab, 0x61, 0x7c, 0x72, 0xa, 0xb4, 0x33, 0xa4, 0x9e, 0x63, 0x36, 0x64, 0xfd, 0x82, 0xab, 0x5f, 0x9a, 0x4e, 0x67, 0x4d, 0xa7, 0x62, 0x5e, 0x99, 0x6c, 0xcd, 0xeb, 0x9b, 0x5b, 0x70, 0xd7, 0x68, 0x12, 0x7, 0x20, 0xd2, 0xba, 0x7f, 0x30, 0xd8, 0xa1, 0xa6, 0x1f, 0x9f, 0x9e, 0x5d, 0x2f, 0x8d, 0x57, 0x95, 0x80, 0x6a, 0xab, 0xf9, 0xf6, 0x3e, 0xc3, 0x4e, 0x3d, 0x3b, 0xf7, 0xf1, 0xe9, 0xfa, 0x42, 0xc8, 0xee, 0xcc, 0x60, 0x5b, 0x78, 0x7e, 0xe1, 0x3f, 0x9f, 0xf5, 0xd7, 0x77, 0x7f, 0x3, 0x1c, 0x7f, 0x59, 0xc2, 0x5e, 0xdd, 0xbf, 0x43, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char popup_bg_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0xa5,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3b,0x3b,0x43,0x42,0x42,0x4b,0x3e,0x3e,0x47,0x3e,0x3e,0x46,0x41,0x41,0x4a,0x0,0x0,0x0,0x3d,0x3d,0x45,0x3b,0x3b,0x43,0x3a,0x3a,0x42,0x38,0x38,0x41,0x37,0x37,0x3e,0x36,0x36,0x3d,0x35,0x35,0x3c,0x0,0x0,0x0,0x38,0x38,0x40,0x38,0x38,0x40,0x31,0x31,0x38,0x34,0x34,0x3b,0x34,0x34,0x3b,0x39,0x39,0x3f,0x31,0x31,0x38,0x2f,0x2f,0x36,0x2d,0x2d,0x33,0x2c,0x2c,0x32,0x2b,0x2b,0x31,0x2a,0x2a,0x31,0x2a,0x2a,0x30,0x29,0x29,0x30,0x29,0x29,0x2f,0x28,0x28,0x2e,0x28,0x28,0x2d,0x27,0x27,0x2d,0x27,0x27,0x2c,0x29,0x29,0x2e,0x26,0x26,0x2c,0x35,0x32,0x3b,0xf,0xeb,0x7f,0x60,0x0,0x0,0x0,0x28,0x74,0x52,0x4e,0x53,0x0,0x1,0x3,0x5,0x8,0xa,0xb,0x4,0x13,0x19,0x1f,0x22,0x23,0x16,0x27,0x35,0x3f,0x45,0x46,0x94,0xf5,0xfa,0xfb,0xf5,0x40,0xfc,0xfb,0xfb,0xfb,0xfb,0xfc,0xfc,0x1a,0xf5,0xf6,0x95,0xfa,0xfb,0xf4,0x94,0x71,0xda,0xac,0x92,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x36,0x47,0xbf,0x88,0xd1,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0xaf,0x49,0x44,0x41,0x54,0x18,0xd3,0x65,0xcf,0xc9,0x12,0x82,0x30,0x10,0x4,0xd0,0x1,0x12,0xb6,0x0,0x21,0x2c,0xb2,0xaa,0xa0,0xa8,0x80,0x88,0x8,0xf8,0xff,0xbf,0x66,0x98,0x93,0xa5,0xef,0xd8,0x55,0xd3,0xd5,0x3,0xa0,0xa8,0x1a,0xa1,0xba,0x44,0x89,0xa6,0x2a,0x0,0x8a,0x41,0x4d,0xcb,0x66,0x8e,0xc3,0x6c,0xcb,0xa4,0x86,0x2,0x2a,0x75,0x3d,0xee,0x8b,0x20,0x10,0x3e,0xf7,0x5c,0xaa,0x82,0x66,0x7a,0x61,0x14,0xef,0xa4,0x38,0xa,0x3d,0x53,0x3,0x62,0xf1,0xa4,0xed,0x50,0x9b,0x70,0x8b,0x0,0xb5,0xd3,0xac,0xeb,0x51,0x97,0xa5,0x36,0x5,0x9d,0x89,0xbc,0xbf,0xa3,0x3e,0x17,0x4c,0x7,0xdd,0x9,0x8a,0xe1,0x81,0x86,0x22,0x70,0x30,0x28,0xc7,0x27,0x1a,0x4b,0xc,0x98,0xd8,0x4f,0x2f,0x34,0xed,0xb7,0x13,0x59,0x7a,0x98,0x17,0x34,0x1f,0xb7,0x52,0x52,0xf1,0x7a,0x5d,0xde,0xd2,0xb2,0x9e,0x78,0x45,0xb6,0x61,0xe7,0xba,0xb9,0x48,0xcd,0xf5,0xb6,0xd,0xc3,0xe9,0xe9,0xd7,0xf4,0xbf,0xe7,0x7e,0xdf,0xff,0x0,0xda,0x19,0x15,0x34,0xd5,0xa4,0x90,0x50,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char panel_bg_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x1, 0x3, 0x0, 0x0, 0x0, 0xfe, 0xc1, 0x2c, 0xc8, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x6, 0x50, 0x4c, 0x54, 0x45, 0x25, 0x25, 0x2a, 0x35, 0x32, 0x3b, 0x4a, 0x73, 0x58, 0x4a, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x1, 0xff, 0x2, 0x2d, 0xde, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0xb, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x40, 0x5, 0x0, 0x0, 0x10, 0x0, 0x1, 0xa1, 0xc5, 0x21, 0xc1, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char popup_bg_disabled_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x7b,0x50,0x4c,0x54,0x45,0xff,0x0,0xff,0x67,0x7a,0x85,0x66,0x7a,0x86,0x68,0x7b,0x86,0x57,0x51,0x51,0x4c,0x42,0x40,0x4d,0x43,0x41,0x56,0x4c,0x4b,0x4d,0x44,0x41,0x4e,0x44,0x42,0x4f,0x45,0x43,0x67,0x7b,0x87,0x4f,0x44,0x43,0x50,0x45,0x44,0x52,0x46,0x44,0x51,0x46,0x45,0x4b,0x40,0x3f,0x51,0x47,0x45,0x52,0x48,0x46,0x53,0x48,0x47,0x4b,0x41,0x3f,0x54,0x49,0x46,0x55,0x4a,0x47,0x55,0x49,0x47,0x68,0x7c,0x88,0x4a,0x40,0x3e,0x55,0x4b,0x49,0x56,0x4d,0x4b,0x53,0x49,0x47,0x50,0x46,0x44,0x4a,0x41,0x3e,0x48,0x3e,0x3c,0x4b,0x42,0x3f,0x49,0x3f,0x3d,0x46,0x3d,0x3c,0x47,0x3d,0x3b,0x47,0x3e,0x3b,0x49,0x40,0x3d,0x45,0x3c,0x3b,0x46,0x3c,0x3a,0xff,0xff,0xff,0x2e,0x48,0xbd,0x3e,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x28,0xbd,0xb0,0xb5,0xb2,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0xb3,0x49,0x44,0x41,0x54,0x18,0xd3,0x2d,0x8f,0xdb,0x16,0x82,0x20,0x10,0x45,0x11,0x19,0x12,0x91,0x54,0x44,0x93,0xb2,0x48,0xa1,0xfc,0xff,0x3f,0xec,0xa0,0xed,0xb7,0xd9,0x73,0xd6,0x5c,0x18,0x3,0x5,0x2f,0x1,0x2f,0xd8,0x49,0xc1,0x5,0x49,0x40,0xe2,0x54,0xc5,0x85,0x2a,0xa9,0x80,0xac,0x48,0x64,0xc3,0x89,0x64,0x7d,0x20,0x89,0x34,0x2,0x82,0x48,0x35,0xe6,0x7a,0x6d,0x1b,0x45,0x39,0xc2,0x3b,0x92,0x4d,0x6f,0x87,0xc1,0xf6,0x30,0x4e,0x33,0xed,0xb2,0x18,0xa7,0xdb,0x64,0x8d,0x24,0x37,0x33,0xed,0x9d,0xac,0xfb,0xf1,0xfe,0x18,0x97,0xa7,0x3a,0xc4,0xcb,0x51,0x16,0xf7,0xc9,0x42,0x78,0x88,0xf0,0x76,0xca,0xb4,0xcb,0x62,0xd,0x2,0x2b,0xc4,0x16,0x7c,0x5e,0x63,0x9e,0x35,0x75,0x6b,0xd4,0x58,0x9b,0x3e,0x98,0x8b,0xbb,0xd0,0x8f,0xa2,0x64,0x88,0xc4,0xb0,0x7a,0xe7,0x3a,0x1f,0x12,0x2,0xf9,0xb2,0x6f,0x8c,0x31,0x84,0x18,0xd3,0x26,0xf8,0xf1,0x8c,0x16,0xfb,0x9e,0xd2,0xbe,0xb,0x5d,0xfe,0xff,0xe5,0x7a,0x6,0x67,0xf9,0x3,0x92,0x36,0xd,0x2d,0xc1,0xf2,0x6d,0x3c,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char popup_bg_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0xa5, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3b, 0x3b, 0x43, 0x42, 0x42, 0x4b, 0x3e, 0x3e, 0x47, 0x3e, 0x3e, 0x46, 0x41, 0x41, 0x4a, 0x0, 0x0, 0x0, 0x3d, 0x3d, 0x45, 0x3b, 0x3b, 0x43, 0x3a, 0x3a, 0x42, 0x38, 0x38, 0x41, 0x37, 0x37, 0x3e, 0x36, 0x36, 0x3d, 0x35, 0x35, 0x3c, 0x0, 0x0, 0x0, 0x38, 0x38, 0x40, 0x38, 0x38, 0x40, 0x31, 0x31, 0x38, 0x34, 0x34, 0x3b, 0x34, 0x34, 0x3b, 0x39, 0x39, 0x3f, 0x31, 0x31, 0x38, 0x2f, 0x2f, 0x36, 0x2d, 0x2d, 0x33, 0x2c, 0x2c, 0x32, 0x2b, 0x2b, 0x31, 0x2a, 0x2a, 0x31, 0x2a, 0x2a, 0x30, 0x29, 0x29, 0x30, 0x29, 0x29, 0x2f, 0x28, 0x28, 0x2e, 0x28, 0x28, 0x2d, 0x27, 0x27, 0x2d, 0x27, 0x27, 0x2c, 0x29, 0x29, 0x2e, 0x26, 0x26, 0x2c, 0x35, 0x32, 0x3b, 0xf, 0xeb, 0x7f, 0x60, 0x0, 0x0, 0x0, 0x28, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x1, 0x3, 0x5, 0x8, 0xa, 0xb, 0x4, 0x13, 0x19, 0x1f, 0x22, 0x23, 0x16, 0x27, 0x35, 0x3f, 0x45, 0x46, 0x94, 0xf5, 0xfa, 0xfb, 0xf5, 0x40, 0xfc, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0x1a, 0xf5, 0xf6, 0x95, 0xfa, 0xfb, 0xf4, 0x94, 0x71, 0xda, 0xac, 0x92, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x36, 0x47, 0xbf, 0x88, 0xd1, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0xaf, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x65, 0xcf, 0xc9, 0x12, 0x82, 0x30, 0x10, 0x4, 0xd0, 0x1, 0x12, 0xb6, 0x0, 0x21, 0x2c, 0xb2, 0xaa, 0xa0, 0xa8, 0x80, 0x88, 0x8, 0xf8, 0xff, 0xbf, 0x66, 0x98, 0x93, 0xa5, 0xef, 0xd8, 0x55, 0xd3, 0xd5, 0x3, 0xa0, 0xa8, 0x1a, 0xa1, 0xba, 0x44, 0x89, 0xa6, 0x2a, 0x0, 0x8a, 0x41, 0x4d, 0xcb, 0x66, 0x8e, 0xc3, 0x6c, 0xcb, 0xa4, 0x86, 0x2, 0x2a, 0x75, 0x3d, 0xee, 0x8b, 0x20, 0x10, 0x3e, 0xf7, 0x5c, 0xaa, 0x82, 0x66, 0x7a, 0x61, 0x14, 0xef, 0xa4, 0x38, 0xa, 0x3d, 0x53, 0x3, 0x62, 0xf1, 0xa4, 0xed, 0x50, 0x9b, 0x70, 0x8b, 0x0, 0xb5, 0xd3, 0xac, 0xeb, 0x51, 0x97, 0xa5, 0x36, 0x5, 0x9d, 0x89, 0xbc, 0xbf, 0xa3, 0x3e, 0x17, 0x4c, 0x7, 0xdd, 0x9, 0x8a, 0xe1, 0x81, 0x86, 0x22, 0x70, 0x30, 0x28, 0xc7, 0x27, 0x1a, 0x4b, 0xc, 0x98, 0xd8, 0x4f, 0x2f, 0x34, 0xed, 0xb7, 0x13, 0x59, 0x7a, 0x98, 0x17, 0x34, 0x1f, 0xb7, 0x52, 0x52, 0xf1, 0x7a, 0x5d, 0xde, 0xd2, 0xb2, 0x9e, 0x78, 0x45, 0xb6, 0x61, 0xe7, 0xba, 0xb9, 0x48, 0xcd, 0xf5, 0xb6, 0xd, 0xc3, 0xe9, 0xe9, 0xd7, 0xf4, 0xbf, 0xe7, 0x7e, 0xdf, 0xff, 0x0, 0xda, 0x19, 0x15, 0x34, 0xd5, 0xa4, 0x90, 0x50, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char popup_checked_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0xa3,0x49,0x44,0x41,0x54,0x18,0x95,0x85,0xcd,0xa1,0xa,0xc2,0x50,0x0,0x85,0xe1,0xff,0xdc,0x5d,0xd8,0x14,0x4,0xab,0x69,0x37,0xac,0x98,0xd5,0x27,0xb0,0x89,0x16,0x8b,0xd5,0xf7,0xd0,0xec,0x73,0xf8,0x4,0x16,0x61,0x4d,0x10,0xc,0x16,0xa3,0x61,0x71,0xab,0x16,0xeb,0x84,0x3b,0xae,0x45,0x8b,0xa,0x9e,0x78,0xce,0x7,0x7,0xfe,0x44,0xbf,0xca,0xa2,0x28,0x3a,0x71,0x1c,0x1f,0x24,0x3d,0xcc,0xe7,0x18,0x42,0x50,0x92,0x24,0x5b,0x49,0x23,0xa0,0xfd,0x5,0xaa,0xaa,0x5a,0x1,0x73,0xe0,0x1e,0x45,0xd1,0x42,0x65,0x59,0x9e,0x80,0x96,0xf7,0x7e,0x62,0xad,0x1d,0x2,0xfb,0x97,0x9d,0x39,0xe7,0x72,0x1b,0x42,0x88,0x25,0xd,0xac,0xb5,0x47,0xa0,0x7,0x18,0x60,0xed,0x9c,0xcb,0x1,0x4c,0xd3,0x34,0x53,0xe0,0xa,0xf4,0x81,0x2e,0xb0,0x4b,0xd3,0x74,0xf3,0xbe,0x34,0x59,0x96,0xdd,0xbc,0xf7,0x63,0xe0,0x2,0x9c,0xeb,0xba,0x5e,0x4a,0xa,0x6f,0xf0,0x4,0x57,0x3d,0x2c,0x27,0x2b,0xe9,0x62,0x6b,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char popup_bg_disabled_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x7b, 0x50, 0x4c, 0x54, 0x45, 0xff, 0x0, 0xff, 0x67, 0x7a, 0x85, 0x66, 0x7a, 0x86, 0x68, 0x7b, 0x86, 0x57, 0x51, 0x51, 0x4c, 0x42, 0x40, 0x4d, 0x43, 0x41, 0x56, 0x4c, 0x4b, 0x4d, 0x44, 0x41, 0x4e, 0x44, 0x42, 0x4f, 0x45, 0x43, 0x67, 0x7b, 0x87, 0x4f, 0x44, 0x43, 0x50, 0x45, 0x44, 0x52, 0x46, 0x44, 0x51, 0x46, 0x45, 0x4b, 0x40, 0x3f, 0x51, 0x47, 0x45, 0x52, 0x48, 0x46, 0x53, 0x48, 0x47, 0x4b, 0x41, 0x3f, 0x54, 0x49, 0x46, 0x55, 0x4a, 0x47, 0x55, 0x49, 0x47, 0x68, 0x7c, 0x88, 0x4a, 0x40, 0x3e, 0x55, 0x4b, 0x49, 0x56, 0x4d, 0x4b, 0x53, 0x49, 0x47, 0x50, 0x46, 0x44, 0x4a, 0x41, 0x3e, 0x48, 0x3e, 0x3c, 0x4b, 0x42, 0x3f, 0x49, 0x3f, 0x3d, 0x46, 0x3d, 0x3c, 0x47, 0x3d, 0x3b, 0x47, 0x3e, 0x3b, 0x49, 0x40, 0x3d, 0x45, 0x3c, 0x3b, 0x46, 0x3c, 0x3a, 0xff, 0xff, 0xff, 0x2e, 0x48, 0xbd, 0x3e, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x28, 0xbd, 0xb0, 0xb5, 0xb2, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0xb3, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x2d, 0x8f, 0xdb, 0x16, 0x82, 0x20, 0x10, 0x45, 0x11, 0x19, 0x12, 0x91, 0x54, 0x44, 0x93, 0xb2, 0x48, 0xa1, 0xfc, 0xff, 0x3f, 0xec, 0xa0, 0xed, 0xb7, 0xd9, 0x73, 0xd6, 0x5c, 0x18, 0x3, 0x5, 0x2f, 0x1, 0x2f, 0xd8, 0x49, 0xc1, 0x5, 0x49, 0x40, 0xe2, 0x54, 0xc5, 0x85, 0x2a, 0xa9, 0x80, 0xac, 0x48, 0x64, 0xc3, 0x89, 0x64, 0x7d, 0x20, 0x89, 0x34, 0x2, 0x82, 0x48, 0x35, 0xe6, 0x7a, 0x6d, 0x1b, 0x45, 0x39, 0xc2, 0x3b, 0x92, 0x4d, 0x6f, 0x87, 0xc1, 0xf6, 0x30, 0x4e, 0x33, 0xed, 0xb2, 0x18, 0xa7, 0xdb, 0x64, 0x8d, 0x24, 0x37, 0x33, 0xed, 0x9d, 0xac, 0xfb, 0xf1, 0xfe, 0x18, 0x97, 0xa7, 0x3a, 0xc4, 0xcb, 0x51, 0x16, 0xf7, 0xc9, 0x42, 0x78, 0x88, 0xf0, 0x76, 0xca, 0xb4, 0xcb, 0x62, 0xd, 0x2, 0x2b, 0xc4, 0x16, 0x7c, 0x5e, 0x63, 0x9e, 0x35, 0x75, 0x6b, 0xd4, 0x58, 0x9b, 0x3e, 0x98, 0x8b, 0xbb, 0xd0, 0x8f, 0xa2, 0x64, 0x88, 0xc4, 0xb0, 0x7a, 0xe7, 0x3a, 0x1f, 0x12, 0x2, 0xf9, 0xb2, 0x6f, 0x8c, 0x31, 0x84, 0x18, 0xd3, 0x26, 0xf8, 0xf1, 0x8c, 0x16, 0xfb, 0x9e, 0xd2, 0xbe, 0xb, 0x5d, 0xfe, 0xff, 0xe5, 0x7a, 0x6, 0x67, 0xf9, 0x3, 0x92, 0x36, 0xd, 0x2d, 0xc1, 0xf2, 0x6d, 0x3c, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char popup_hover_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x4,0x3,0x0,0x0,0x0,0xed,0xdd,0xe2,0x52,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x30,0x50,0x4c,0x54,0x45,0xff,0x0,0xff,0x20,0x2e,0x31,0x83,0xae,0xb7,0xb3,0xd8,0xe1,0xaf,0xd5,0xde,0xac,0xd2,0xdb,0xa9,0xcf,0xd8,0xa5,0xcc,0xd5,0xa2,0xc9,0xd2,0x9e,0xc6,0xcf,0x9b,0xc3,0xcc,0x97,0xc0,0xc9,0x94,0xbd,0xc6,0x91,0xba,0xc3,0x8d,0xb7,0xc0,0xff,0xff,0xff,0x73,0xd4,0x4e,0xcb,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0xf,0x18,0xba,0x0,0xd9,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x4c,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0x14,0x4,0x3,0x1,0x6,0x21,0x25,0x30,0x50,0x64,0x10,0x32,0x6,0x3,0x20,0xc3,0x5,0xc,0x80,0x8c,0x50,0x30,0x0,0x32,0xd2,0xc0,0x0,0xc8,0x28,0x7,0x3,0x20,0xa3,0x3,0xc,0x80,0x8c,0x99,0x60,0x0,0x64,0xac,0x2,0x3,0x20,0x63,0x37,0x18,0x0,0x19,0x67,0xc0,0x0,0xc8,0xb8,0xb,0x6,0x40,0xc6,0x3b,0x30,0x50,0x44,0x58,0xa,0x73,0x6,0x0,0xe9,0xb4,0x2d,0xf5,0x51,0xd4,0xb8,0xa1,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char popup_checked_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x8, 0x6, 0x0, 0x0, 0x0, 0xc4, 0xf, 0xbe, 0x8b, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0xa3, 0x49, 0x44, 0x41, 0x54, 0x18, 0x95, 0x85, 0xcd, 0xa1, 0xa, 0xc2, 0x50, 0x0, 0x85, 0xe1, 0xff, 0xdc, 0x5d, 0xd8, 0x14, 0x4, 0xab, 0x69, 0x37, 0xac, 0x98, 0xd5, 0x27, 0xb0, 0x89, 0x16, 0x8b, 0xd5, 0xf7, 0xd0, 0xec, 0x73, 0xf8, 0x4, 0x16, 0x61, 0x4d, 0x10, 0xc, 0x16, 0xa3, 0x61, 0x71, 0xab, 0x16, 0xeb, 0x84, 0x3b, 0xae, 0x45, 0x8b, 0xa, 0x9e, 0x78, 0xce, 0x7, 0x7, 0xfe, 0x44, 0xbf, 0xca, 0xa2, 0x28, 0x3a, 0x71, 0x1c, 0x1f, 0x24, 0x3d, 0xcc, 0xe7, 0x18, 0x42, 0x50, 0x92, 0x24, 0x5b, 0x49, 0x23, 0xa0, 0xfd, 0x5, 0xaa, 0xaa, 0x5a, 0x1, 0x73, 0xe0, 0x1e, 0x45, 0xd1, 0x42, 0x65, 0x59, 0x9e, 0x80, 0x96, 0xf7, 0x7e, 0x62, 0xad, 0x1d, 0x2, 0xfb, 0x97, 0x9d, 0x39, 0xe7, 0x72, 0x1b, 0x42, 0x88, 0x25, 0xd, 0xac, 0xb5, 0x47, 0xa0, 0x7, 0x18, 0x60, 0xed, 0x9c, 0xcb, 0x1, 0x4c, 0xd3, 0x34, 0x53, 0xe0, 0xa, 0xf4, 0x81, 0x2e, 0xb0, 0x4b, 0xd3, 0x74, 0xf3, 0xbe, 0x34, 0x59, 0x96, 0xdd, 0xbc, 0xf7, 0x63, 0xe0, 0x2, 0x9c, 0xeb, 0xba, 0x5e, 0x4a, 0xa, 0x6f, 0xf0, 0x4, 0x57, 0x3d, 0x2c, 0x27, 0x2b, 0xe9, 0x62, 0x6b, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char popup_unchecked_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x1,0x3,0x0,0x0,0x0,0xfe,0xc1,0x2c,0xc8,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x6,0x50,0x4c,0x54,0x45,0xff,0x0,0xff,0xff,0xff,0xff,0x9f,0x18,0x32,0xe0,0x0,0x0,0x0,0x1,0x74,0x52,0x4e,0x53,0x0,0x40,0xe6,0xd8,0x66,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x1,0xff,0x2,0x2d,0xde,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x4,0x4e,0x1d,0x2,0xaf,0x0,0x0,0x0,0xb,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0x40,0x5,0x0,0x0,0x10,0x0,0x1,0xa1,0xc5,0x21,0xc1,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char popup_hover_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x30, 0x50, 0x4c, 0x54, 0x45, 0xff, 0x0, 0xff, 0x20, 0x2e, 0x31, 0x83, 0xae, 0xb7, 0xb3, 0xd8, 0xe1, 0xaf, 0xd5, 0xde, 0xac, 0xd2, 0xdb, 0xa9, 0xcf, 0xd8, 0xa5, 0xcc, 0xd5, 0xa2, 0xc9, 0xd2, 0x9e, 0xc6, 0xcf, 0x9b, 0xc3, 0xcc, 0x97, 0xc0, 0xc9, 0x94, 0xbd, 0xc6, 0x91, 0xba, 0xc3, 0x8d, 0xb7, 0xc0, 0xff, 0xff, 0xff, 0x73, 0xd4, 0x4e, 0xcb, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0xf, 0x18, 0xba, 0x0, 0xd9, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x14, 0x4, 0x3, 0x1, 0x6, 0x21, 0x25, 0x30, 0x50, 0x64, 0x10, 0x32, 0x6, 0x3, 0x20, 0xc3, 0x5, 0xc, 0x80, 0x8c, 0x50, 0x30, 0x0, 0x32, 0xd2, 0xc0, 0x0, 0xc8, 0x28, 0x7, 0x3, 0x20, 0xa3, 0x3, 0xc, 0x80, 0x8c, 0x99, 0x60, 0x0, 0x64, 0xac, 0x2, 0x3, 0x20, 0x63, 0x37, 0x18, 0x0, 0x19, 0x67, 0xc0, 0x0, 0xc8, 0xb8, 0xb, 0x6, 0x40, 0xc6, 0x3b, 0x30, 0x50, 0x44, 0x58, 0xa, 0x73, 0x6, 0x0, 0xe9, 0xb4, 0x2d, 0xf5, 0x51, 0xd4, 0xb8, 0xa1, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char popup_window_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x2a,0x0,0x0,0x0,0x46,0x8,0x3,0x0,0x0,0x0,0x8d,0x2b,0xf6,0x48,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x1,0x6e,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0xe8,0xe5,0xf1,0x0,0x0,0x0,0x0,0x0,0x0,0x1f,0x1d,0x22,0x0,0x0,0x0,0x1a,0x19,0x1c,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x1e,0x23,0x0,0x0,0x0,0x0,0x0,0x0,0x1f,0x1d,0x21,0x17,0x16,0x19,0x0,0x0,0x0,0x0,0x0,0x0,0x21,0x1f,0x24,0x1b,0x1a,0x1d,0x0,0x0,0x0,0x0,0x0,0x0,0x21,0x1f,0x24,0x1e,0x1c,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x22,0x20,0x25,0x20,0x1e,0x23,0x0,0x0,0x0,0x0,0x0,0x0,0x21,0x1f,0x24,0x0,0x0,0x0,0x21,0x1f,0x24,0x0,0x0,0x0,0x0,0x0,0x0,0x22,0x20,0x25,0x0,0x0,0x0,0x20,0x20,0x25,0x20,0x1d,0x25,0x20,0x1d,0x22,0x1d,0x1d,0x22,0x1d,0x1d,0x20,0x1d,0x1a,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x32,0x30,0x38,0xe8,0xe5,0xf1,0xe5,0xe2,0xeb,0xe3,0xe1,0xe8,0xe1,0xdf,0xe7,0xe0,0xde,0xe6,0xdf,0xdd,0xe5,0xde,0xdc,0xe4,0xdd,0xdb,0xe3,0xdc,0xda,0xe2,0xda,0xd8,0xe0,0xd9,0xd7,0xdf,0xd7,0xd6,0xdf,0xd6,0xd4,0xdd,0xd5,0xd3,0xdc,0xd4,0xd1,0xdb,0xd3,0xd0,0xda,0xd1,0xce,0xd8,0xd0,0xcd,0xd7,0xcf,0xcd,0xd7,0xe2,0xdf,0xeb,0x48,0x46,0x51,0x42,0x40,0x4b,0x40,0x3e,0x48,0x40,0x3d,0x48,0x48,0x45,0x50,0x42,0x3f,0x4a,0x3f,0x3d,0x48,0x47,0x44,0x50,0x41,0x3f,0x4a,0x3f,0x3d,0x47,0x41,0x3e,0x49,0x3f,0x3c,0x47,0x46,0x43,0x4f,0x3e,0x3c,0x46,0x40,0x3e,0x49,0x3d,0x3b,0x46,0x45,0x43,0x4e,0x3d,0x3b,0x45,0x44,0x42,0x4d,0x3d,0x3a,0x45,0x3e,0x3c,0x47,0x3c,0x3a,0x44,0x43,0x42,0x4c,0x43,0x40,0x4c,0x3e,0x3b,0x46,0x3b,0x39,0x43,0x43,0x3f,0x4c,0x43,0x3f,0x4b,0x3a,0x38,0x42,0x42,0x3e,0x4b,0x42,0x3e,0x49,0x3a,0x37,0x41,0x39,0x37,0x41,0x3f,0x3e,0x48,0x39,0x37,0x40,0x38,0x36,0x40,0x3e,0x3d,0x48,0x38,0x36,0x3f,0x3e,0x3d,0x47,0x3a,0x38,0x41,0x38,0x35,0x3f,0x37,0x35,0x3e,0x39,0x36,0x40,0x37,0x34,0x3e,0x3d,0x3a,0x46,0x36,0x34,0x3d,0x3d,0x3a,0x44,0x37,0x35,0x3f,0x35,0x33,0x3c,0x46,0x44,0x4f,0xff,0xff,0xff,0x7e,0xde,0x1d,0x81,0x0,0x0,0x0,0x33,0x74,0x52,0x4e,0x53,0x0,0xa2,0x3,0x9,0x17,0xc,0x20,0xf,0x2a,0x5e,0x12,0x30,0x68,0x46,0x20,0x4e,0xa2,0x7d,0x3a,0x4f,0xa4,0x7d,0x3f,0x25,0x60,0xc0,0xb8,0x57,0x1d,0xba,0x59,0xbd,0x5b,0x22,0xbf,0x5e,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xa1,0x9f,0x9e,0x52,0x92,0x15,0x44,0x7e,0xd8,0x5,0xc7,0xf4,0xac,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x79,0xa1,0xdc,0xd4,0xd0,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x1,0xe8,0x49,0x44,0x41,0x54,0x48,0xc7,0xd5,0xd6,0xd9,0x53,0xd3,0x60,0x14,0xc6,0xe1,0x92,0x5a,0xa3,0x44,0xa3,0xd6,0x85,0xa0,0xb1,0x5a,0xcb,0xda,0xbd,0x7c,0xb8,0xef,0x2b,0x69,0x21,0xd0,0xda,0x22,0x25,0xd,0x69,0x20,0x60,0x69,0x11,0x2a,0x22,0xcb,0x9f,0xef,0x78,0x97,0x7e,0xe7,0x3d,0x33,0x1d,0xbd,0x70,0xfc,0x5d,0x3f,0x77,0xe7,0xe2,0x3d,0x91,0xc8,0x7f,0xd8,0x88,0x60,0x1a,0x21,0x54,0xcc,0x3f,0x84,0xcd,0xb,0x4a,0x1f,0x31,0xfd,0x1d,0x7d,0xcc,0x4,0xe8,0x13,0x26,0x40,0x9f,0x32,0x1,0xfa,0x8c,0x9,0xd0,0xe7,0x4c,0x80,0xbe,0x60,0x2,0xf4,0x25,0x13,0xa0,0xaf,0x98,0x0,0x7d,0xcd,0x44,0xa8,0x22,0xde,0x30,0x49,0x54,0x89,0x9e,0x13,0x6f,0x99,0x64,0x1a,0x3b,0x2f,0xde,0x31,0x49,0x54,0xbd,0x70,0x51,0xbc,0x67,0x92,0xe8,0xa8,0x76,0x49,0x7c,0x60,0x12,0x97,0xf5,0x68,0x88,0xea,0x57,0xae,0x8a,0x8f,0x4c,0xe2,0x5a,0x7c,0x34,0x4c,0xaf,0xdf,0x10,0x9f,0x98,0xc4,0xcd,0x5b,0x21,0xaa,0x8c,0x19,0xe3,0xb,0x56,0x19,0x66,0x2d,0xdc,0xbe,0x63,0x2a,0x43,0xd2,0xbb,0x9,0x7d,0x58,0x7a,0xef,0x7e,0x72,0x58,0xfa,0x20,0x35,0x36,0x2c,0x1d,0x37,0x8,0xad,0xc0,0x0,0x5d,0x5c,0xb2,0x61,0x4b,0x8b,0x32,0x9d,0x58,0x5e,0xa9,0xc2,0x56,0x96,0x27,0x8,0xad,0x7d,0x86,0xd5,0x28,0xad,0xd7,0x1a,0xb0,0x5a,0x9d,0xd2,0x55,0x4c,0x57,0x1,0xad,0x7c,0x81,0x55,0x8,0x9d,0x5c,0xb3,0x9b,0x30,0x7b,0x6d,0x52,0xa2,0x53,0xeb,0x55,0x7,0x56,0x5d,0x9f,0x22,0xb4,0xe5,0xc2,0x5a,0x94,0x6e,0x34,0x30,0x6d,0x6c,0x10,0xea,0xb5,0x7d,0x58,0xdb,0x93,0xe9,0xf4,0x66,0x13,0xd3,0xe6,0xe6,0xb4,0x4c,0xb7,0x9c,0x0,0xe6,0x6c,0x11,0xba,0xed,0x62,0xea,0x6e,0x13,0xba,0xe3,0x7e,0x85,0xb9,0x3b,0x84,0x96,0xfd,0xe,0xcc,0x2f,0x13,0xba,0xeb,0x77,0x61,0xfe,0x2e,0xa1,0x76,0xd0,0x83,0x5,0x36,0xa1,0x7b,0xc1,0x37,0x58,0xb0,0x27,0xd3,0x99,0xfd,0x83,0x3e,0xec,0x60,0x7f,0x46,0xa2,0xb3,0xad,0xce,0x77,0x58,0xa7,0x35,0x2b,0xd3,0xf6,0x21,0xa6,0x87,0x6d,0x40,0x7f,0xc0,0x0,0x3d,0xea,0xfd,0x84,0xf5,0x8e,0x8,0x75,0xfa,0x98,0xf6,0x1d,0x42,0x8f,0x39,0x7a,0x4c,0xe9,0xc9,0x29,0xec,0x64,0x90,0x46,0x92,0xa9,0xb4,0x75,0xca,0x64,0xa5,0x53,0xc9,0xc8,0x1f,0xd2,0xc,0x4f,0x33,0x3,0x54,0x4f,0x64,0x79,0x9a,0x4d,0xe8,0x21,0x6a,0xe6,0xf2,0x1e,0x47,0xbd,0x7c,0xce,0xc,0xd1,0x42,0xb1,0x54,0xef,0x62,0xd9,0x3d,0x2b,0x15,0xb,0x21,0xaa,0x6a,0xc6,0xdc,0x99,0x67,0x81,0xbc,0xfa,0x9c,0xa1,0xa9,0x21,0x1a,0x35,0xe3,0x46,0x29,0x9f,0xcd,0xa4,0xa5,0x32,0xd9,0x7c,0xc9,0x88,0x9b,0xe1,0xe1,0x54,0x62,0xa6,0x56,0xcc,0x25,0x52,0xa4,0x44,0xae,0xa8,0x99,0xb1,0xd0,0x5,0x7e,0x3f,0x4,0x6a,0xc1,0xd4,0x93,0x24,0xdd,0x2c,0xa8,0xd1,0x1,0xf9,0xf,0xfb,0x5,0x66,0x6f,0x2a,0x9a,0xa8,0x51,0x81,0xce,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char popup_unchecked_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x1, 0x3, 0x0, 0x0, 0x0, 0xfe, 0xc1, 0x2c, 0xc8, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x6, 0x50, 0x4c, 0x54, 0x45, 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0x9f, 0x18, 0x32, 0xe0, 0x0, 0x0, 0x0, 0x1, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x40, 0xe6, 0xd8, 0x66, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x1, 0xff, 0x2, 0x2d, 0xde, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x4, 0x4e, 0x1d, 0x2, 0xaf, 0x0, 0x0, 0x0, 0xb, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x40, 0x5, 0x0, 0x0, 0x10, 0x0, 0x1, 0xa1, 0xc5, 0x21, 0xc1, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char progress_bar_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x33,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2d,0x2c,0x2f,0x48,0x46,0x4a,0x4c,0x4a,0x4e,0x48,0x46,0x4a,0x40,0x3e,0x42,0x38,0x36,0x3a,0x27,0x27,0x27,0xe1,0x1d,0x66,0x4d,0x0,0x0,0x0,0xc,0x74,0x52,0x4e,0x53,0xa,0x1a,0x26,0x29,0x2a,0x48,0x65,0x6d,0x6e,0x66,0xf5,0xfe,0xb7,0x4a,0xbe,0x33,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x10,0x95,0xb2,0xd,0x2c,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x44,0x49,0x44,0x41,0x54,0x18,0xd3,0xc5,0xcf,0x31,0x16,0x0,0x10,0xc,0x44,0xc1,0x4d,0x84,0x4,0xc1,0xfd,0x6f,0xab,0xc9,0x53,0x70,0x0,0x53,0x6e,0xb5,0x1f,0x20,0x4e,0x12,0x12,0x13,0x40,0xb9,0xa8,0x5,0x2d,0x99,0xc0,0xb5,0x75,0xf,0xbd,0x55,0x86,0xe8,0x98,0x2b,0xcc,0xa1,0x2,0x31,0x5f,0x87,0xdb,0xbf,0xe1,0x3e,0xf6,0x5c,0x7f,0xe2,0xee,0xfc,0xd,0x60,0x3b,0xa,0x1d,0x9e,0x6a,0x29,0x33,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char popup_window_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x2a, 0x0, 0x0, 0x0, 0x46, 0x8, 0x3, 0x0, 0x0, 0x0, 0x8d, 0x2b, 0xf6, 0x48, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x1, 0x6e, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0xe8, 0xe5, 0xf1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x1d, 0x22, 0x0, 0x0, 0x0, 0x1a, 0x19, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x1e, 0x23, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x1d, 0x21, 0x17, 0x16, 0x19, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x21, 0x1f, 0x24, 0x1b, 0x1a, 0x1d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x21, 0x1f, 0x24, 0x1e, 0x1c, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22, 0x20, 0x25, 0x20, 0x1e, 0x23, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x21, 0x1f, 0x24, 0x0, 0x0, 0x0, 0x21, 0x1f, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22, 0x20, 0x25, 0x0, 0x0, 0x0, 0x20, 0x20, 0x25, 0x20, 0x1d, 0x25, 0x20, 0x1d, 0x22, 0x1d, 0x1d, 0x22, 0x1d, 0x1d, 0x20, 0x1d, 0x1a, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32, 0x30, 0x38, 0xe8, 0xe5, 0xf1, 0xe5, 0xe2, 0xeb, 0xe3, 0xe1, 0xe8, 0xe1, 0xdf, 0xe7, 0xe0, 0xde, 0xe6, 0xdf, 0xdd, 0xe5, 0xde, 0xdc, 0xe4, 0xdd, 0xdb, 0xe3, 0xdc, 0xda, 0xe2, 0xda, 0xd8, 0xe0, 0xd9, 0xd7, 0xdf, 0xd7, 0xd6, 0xdf, 0xd6, 0xd4, 0xdd, 0xd5, 0xd3, 0xdc, 0xd4, 0xd1, 0xdb, 0xd3, 0xd0, 0xda, 0xd1, 0xce, 0xd8, 0xd0, 0xcd, 0xd7, 0xcf, 0xcd, 0xd7, 0xe2, 0xdf, 0xeb, 0x48, 0x46, 0x51, 0x42, 0x40, 0x4b, 0x40, 0x3e, 0x48, 0x40, 0x3d, 0x48, 0x48, 0x45, 0x50, 0x42, 0x3f, 0x4a, 0x3f, 0x3d, 0x48, 0x47, 0x44, 0x50, 0x41, 0x3f, 0x4a, 0x3f, 0x3d, 0x47, 0x41, 0x3e, 0x49, 0x3f, 0x3c, 0x47, 0x46, 0x43, 0x4f, 0x3e, 0x3c, 0x46, 0x40, 0x3e, 0x49, 0x3d, 0x3b, 0x46, 0x45, 0x43, 0x4e, 0x3d, 0x3b, 0x45, 0x44, 0x42, 0x4d, 0x3d, 0x3a, 0x45, 0x3e, 0x3c, 0x47, 0x3c, 0x3a, 0x44, 0x43, 0x42, 0x4c, 0x43, 0x40, 0x4c, 0x3e, 0x3b, 0x46, 0x3b, 0x39, 0x43, 0x43, 0x3f, 0x4c, 0x43, 0x3f, 0x4b, 0x3a, 0x38, 0x42, 0x42, 0x3e, 0x4b, 0x42, 0x3e, 0x49, 0x3a, 0x37, 0x41, 0x39, 0x37, 0x41, 0x3f, 0x3e, 0x48, 0x39, 0x37, 0x40, 0x38, 0x36, 0x40, 0x3e, 0x3d, 0x48, 0x38, 0x36, 0x3f, 0x3e, 0x3d, 0x47, 0x3a, 0x38, 0x41, 0x38, 0x35, 0x3f, 0x37, 0x35, 0x3e, 0x39, 0x36, 0x40, 0x37, 0x34, 0x3e, 0x3d, 0x3a, 0x46, 0x36, 0x34, 0x3d, 0x3d, 0x3a, 0x44, 0x37, 0x35, 0x3f, 0x35, 0x33, 0x3c, 0x46, 0x44, 0x4f, 0xff, 0xff, 0xff, 0x7e, 0xde, 0x1d, 0x81, 0x0, 0x0, 0x0, 0x33, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xa2, 0x3, 0x9, 0x17, 0xc, 0x20, 0xf, 0x2a, 0x5e, 0x12, 0x30, 0x68, 0x46, 0x20, 0x4e, 0xa2, 0x7d, 0x3a, 0x4f, 0xa4, 0x7d, 0x3f, 0x25, 0x60, 0xc0, 0xb8, 0x57, 0x1d, 0xba, 0x59, 0xbd, 0x5b, 0x22, 0xbf, 0x5e, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xa1, 0x9f, 0x9e, 0x52, 0x92, 0x15, 0x44, 0x7e, 0xd8, 0x5, 0xc7, 0xf4, 0xac, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x79, 0xa1, 0xdc, 0xd4, 0xd0, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x1, 0xe8, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xd5, 0xd6, 0xd9, 0x53, 0xd3, 0x60, 0x14, 0xc6, 0xe1, 0x92, 0x5a, 0xa3, 0x44, 0xa3, 0xd6, 0x85, 0xa0, 0xb1, 0x5a, 0xcb, 0xda, 0xbd, 0x7c, 0xb8, 0xef, 0x2b, 0x69, 0x21, 0xd0, 0xda, 0x22, 0x25, 0xd, 0x69, 0x20, 0x60, 0x69, 0x11, 0x2a, 0x22, 0xcb, 0x9f, 0xef, 0x78, 0x97, 0x7e, 0xe7, 0x3d, 0x33, 0x1d, 0xbd, 0x70, 0xfc, 0x5d, 0x3f, 0x77, 0xe7, 0xe2, 0x3d, 0x91, 0xc8, 0x7f, 0xd8, 0x88, 0x60, 0x1a, 0x21, 0x54, 0xcc, 0x3f, 0x84, 0xcd, 0xb, 0x4a, 0x1f, 0x31, 0xfd, 0x1d, 0x7d, 0xcc, 0x4, 0xe8, 0x13, 0x26, 0x40, 0x9f, 0x32, 0x1, 0xfa, 0x8c, 0x9, 0xd0, 0xe7, 0x4c, 0x80, 0xbe, 0x60, 0x2, 0xf4, 0x25, 0x13, 0xa0, 0xaf, 0x98, 0x0, 0x7d, 0xcd, 0x44, 0xa8, 0x22, 0xde, 0x30, 0x49, 0x54, 0x89, 0x9e, 0x13, 0x6f, 0x99, 0x64, 0x1a, 0x3b, 0x2f, 0xde, 0x31, 0x49, 0x54, 0xbd, 0x70, 0x51, 0xbc, 0x67, 0x92, 0xe8, 0xa8, 0x76, 0x49, 0x7c, 0x60, 0x12, 0x97, 0xf5, 0x68, 0x88, 0xea, 0x57, 0xae, 0x8a, 0x8f, 0x4c, 0xe2, 0x5a, 0x7c, 0x34, 0x4c, 0xaf, 0xdf, 0x10, 0x9f, 0x98, 0xc4, 0xcd, 0x5b, 0x21, 0xaa, 0x8c, 0x19, 0xe3, 0xb, 0x56, 0x19, 0x66, 0x2d, 0xdc, 0xbe, 0x63, 0x2a, 0x43, 0xd2, 0xbb, 0x9, 0x7d, 0x58, 0x7a, 0xef, 0x7e, 0x72, 0x58, 0xfa, 0x20, 0x35, 0x36, 0x2c, 0x1d, 0x37, 0x8, 0xad, 0xc0, 0x0, 0x5d, 0x5c, 0xb2, 0x61, 0x4b, 0x8b, 0x32, 0x9d, 0x58, 0x5e, 0xa9, 0xc2, 0x56, 0x96, 0x27, 0x8, 0xad, 0x7d, 0x86, 0xd5, 0x28, 0xad, 0xd7, 0x1a, 0xb0, 0x5a, 0x9d, 0xd2, 0x55, 0x4c, 0x57, 0x1, 0xad, 0x7c, 0x81, 0x55, 0x8, 0x9d, 0x5c, 0xb3, 0x9b, 0x30, 0x7b, 0x6d, 0x52, 0xa2, 0x53, 0xeb, 0x55, 0x7, 0x56, 0x5d, 0x9f, 0x22, 0xb4, 0xe5, 0xc2, 0x5a, 0x94, 0x6e, 0x34, 0x30, 0x6d, 0x6c, 0x10, 0xea, 0xb5, 0x7d, 0x58, 0xdb, 0x93, 0xe9, 0xf4, 0x66, 0x13, 0xd3, 0xe6, 0xe6, 0xb4, 0x4c, 0xb7, 0x9c, 0x0, 0xe6, 0x6c, 0x11, 0xba, 0xed, 0x62, 0xea, 0x6e, 0x13, 0xba, 0xe3, 0x7e, 0x85, 0xb9, 0x3b, 0x84, 0x96, 0xfd, 0xe, 0xcc, 0x2f, 0x13, 0xba, 0xeb, 0x77, 0x61, 0xfe, 0x2e, 0xa1, 0x76, 0xd0, 0x83, 0x5, 0x36, 0xa1, 0x7b, 0xc1, 0x37, 0x58, 0xb0, 0x27, 0xd3, 0x99, 0xfd, 0x83, 0x3e, 0xec, 0x60, 0x7f, 0x46, 0xa2, 0xb3, 0xad, 0xce, 0x77, 0x58, 0xa7, 0x35, 0x2b, 0xd3, 0xf6, 0x21, 0xa6, 0x87, 0x6d, 0x40, 0x7f, 0xc0, 0x0, 0x3d, 0xea, 0xfd, 0x84, 0xf5, 0x8e, 0x8, 0x75, 0xfa, 0x98, 0xf6, 0x1d, 0x42, 0x8f, 0x39, 0x7a, 0x4c, 0xe9, 0xc9, 0x29, 0xec, 0x64, 0x90, 0x46, 0x92, 0xa9, 0xb4, 0x75, 0xca, 0x64, 0xa5, 0x53, 0xc9, 0xc8, 0x1f, 0xd2, 0xc, 0x4f, 0x33, 0x3, 0x54, 0x4f, 0x64, 0x79, 0x9a, 0x4d, 0xe8, 0x21, 0x6a, 0xe6, 0xf2, 0x1e, 0x47, 0xbd, 0x7c, 0xce, 0xc, 0xd1, 0x42, 0xb1, 0x54, 0xef, 0x62, 0xd9, 0x3d, 0x2b, 0x15, 0xb, 0x21, 0xaa, 0x6a, 0xc6, 0xdc, 0x99, 0x67, 0x81, 0xbc, 0xfa, 0x9c, 0xa1, 0xa9, 0x21, 0x1a, 0x35, 0xe3, 0x46, 0x29, 0x9f, 0xcd, 0xa4, 0xa5, 0x32, 0xd9, 0x7c, 0xc9, 0x88, 0x9b, 0xe1, 0xe1, 0x54, 0x62, 0xa6, 0x56, 0xcc, 0x25, 0x52, 0xa4, 0x44, 0xae, 0xa8, 0x99, 0xb1, 0xd0, 0x5, 0x7e, 0x3f, 0x4, 0x6a, 0xc1, 0xd4, 0x93, 0x24, 0xdd, 0x2c, 0xa8, 0xd1, 0x1, 0xf9, 0xf, 0xfb, 0x5, 0x66, 0x6f, 0x2a, 0x9a, 0xa8, 0x51, 0x81, 0xce, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char progress_fill_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x4,0x0,0x0,0x0,0xb5,0xfa,0x37,0xea,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0x26,0x78,0x80,0xa6,0xcf,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x4,0x4e,0x1d,0x2,0xaf,0x0,0x0,0x0,0x60,0x49,0x44,0x41,0x54,0x28,0xcf,0x63,0x60,0x18,0x78,0xc0,0x8,0x63,0x38,0x58,0x7c,0xde,0xf8,0x45,0xc,0xc2,0xe6,0x79,0xc5,0xeb,0x7f,0xe0,0x4,0x9a,0x2,0xe3,0x97,0x1f,0xb9,0xff,0x70,0x43,0xd8,0x2c,0x5f,0xf9,0xbf,0x9e,0x15,0x87,0xb2,0x61,0xa,0xbe,0x88,0xfd,0x81,0x1b,0xfb,0x87,0xfb,0xb,0x37,0x8c,0xcd,0x44,0xc8,0xd,0x54,0x54,0xc0,0xf3,0x8a,0xe5,0x2b,0x8c,0xcd,0xf2,0x95,0xe7,0x15,0x86,0x2,0x5e,0x7f,0xfe,0xaf,0xec,0xc,0x10,0xc8,0xff,0x95,0xd7,0x9f,0xe6,0x1,0x4c,0x2,0x0,0x0,0x68,0x3f,0x16,0xd7,0xea,0x7c,0xdd,0x1a,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char progress_bar_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x33, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2d, 0x2c, 0x2f, 0x48, 0x46, 0x4a, 0x4c, 0x4a, 0x4e, 0x48, 0x46, 0x4a, 0x40, 0x3e, 0x42, 0x38, 0x36, 0x3a, 0x27, 0x27, 0x27, 0xe1, 0x1d, 0x66, 0x4d, 0x0, 0x0, 0x0, 0xc, 0x74, 0x52, 0x4e, 0x53, 0xa, 0x1a, 0x26, 0x29, 0x2a, 0x48, 0x65, 0x6d, 0x6e, 0x66, 0xf5, 0xfe, 0xb7, 0x4a, 0xbe, 0x33, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x10, 0x95, 0xb2, 0xd, 0x2c, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x44, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0xc5, 0xcf, 0x31, 0x16, 0x0, 0x10, 0xc, 0x44, 0xc1, 0x4d, 0x84, 0x4, 0xc1, 0xfd, 0x6f, 0xab, 0xc9, 0x53, 0x70, 0x0, 0x53, 0x6e, 0xb5, 0x1f, 0x20, 0x4e, 0x12, 0x12, 0x13, 0x40, 0xb9, 0xa8, 0x5, 0x2d, 0x99, 0xc0, 0xb5, 0x75, 0xf, 0xbd, 0x55, 0x86, 0xe8, 0x98, 0x2b, 0xcc, 0xa1, 0x2, 0x31, 0x5f, 0x87, 0xdb, 0xbf, 0xe1, 0x3e, 0xf6, 0x5c, 0x7f, 0xe2, 0xee, 0xfc, 0xd, 0x60, 0x3b, 0xa, 0x1d, 0x9e, 0x6a, 0x29, 0x33, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char radio_checked_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x45,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x4,0x3,0x4,0x9,0x9,0x9,0x6,0x6,0x6,0xa,0xa,0xb,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x7f,0x7f,0x82,0xd8,0xd8,0xd8,0xd9,0xd9,0xd9,0x47,0x47,0x48,0xd3,0xd3,0xd3,0xa2,0xa2,0xa2,0x79,0x79,0x79,0x73,0x73,0x73,0x1c,0x1c,0x1c,0x3,0x3,0x3,0x0,0x0,0x0,0xff,0xff,0xff,0xa,0x69,0x4,0xd4,0x0,0x0,0x0,0xb,0x74,0x52,0x4e,0x53,0x0,0x0,0x0,0x0,0x0,0x1b,0x88,0xd1,0xf7,0x64,0xf6,0x2,0xb3,0xed,0xd7,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x16,0x7c,0xd1,0xa8,0x19,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x69,0x49,0x44,0x41,0x54,0x18,0xd3,0x6d,0x8f,0xdb,0xe,0xc0,0x20,0x8,0x43,0xdd,0xc5,0x3b,0x9d,0xa8,0xec,0xff,0x7f,0x75,0x6a,0x96,0x2c,0x8b,0xf6,0xad,0x27,0x14,0x8a,0x52,0x2b,0x69,0x63,0x9d,0xb3,0x46,0xbf,0x76,0xf3,0x21,0x12,0x40,0x31,0xf8,0x7d,0x0,0x7f,0x35,0xdb,0x45,0x97,0x1f,0xf3,0x81,0x90,0x38,0x67,0x4e,0xa0,0xd0,0x53,0x26,0x22,0x95,0x2a,0x52,0x4b,0x42,0x34,0xd,0x58,0x2,0xd7,0xbb,0xa9,0x32,0xc8,0x36,0xe0,0x80,0x2c,0x1d,0x48,0x6,0xdc,0xa,0x4c,0x91,0x69,0xe9,0x74,0x76,0x2a,0xa6,0x8e,0xaf,0xfa,0xb9,0x7e,0xee,0xaf,0x7,0xb9,0xfb,0x8,0xe7,0x90,0x1c,0x65,0x49,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char progress_fill_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0x26, 0x78, 0x80, 0xa6, 0xcf, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x4, 0x4e, 0x1d, 0x2, 0xaf, 0x0, 0x0, 0x0, 0x60, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x63, 0x60, 0x18, 0x78, 0xc0, 0x8, 0x63, 0x38, 0x58, 0x7c, 0xde, 0xf8, 0x45, 0xc, 0xc2, 0xe6, 0x79, 0xc5, 0xeb, 0x7f, 0xe0, 0x4, 0x9a, 0x2, 0xe3, 0x97, 0x1f, 0xb9, 0xff, 0x70, 0x43, 0xd8, 0x2c, 0x5f, 0xf9, 0xbf, 0x9e, 0x15, 0x87, 0xb2, 0x61, 0xa, 0xbe, 0x88, 0xfd, 0x81, 0x1b, 0xfb, 0x87, 0xfb, 0xb, 0x37, 0x8c, 0xcd, 0x44, 0xc8, 0xd, 0x54, 0x54, 0xc0, 0xf3, 0x8a, 0xe5, 0x2b, 0x8c, 0xcd, 0xf2, 0x95, 0xe7, 0x15, 0x86, 0x2, 0x5e, 0x7f, 0xfe, 0xaf, 0xec, 0xc, 0x10, 0xc8, 0xff, 0x95, 0xd7, 0x9f, 0xe6, 0x1, 0x4c, 0x2, 0x0, 0x0, 0x68, 0x3f, 0x16, 0xd7, 0xea, 0x7c, 0xdd, 0x1a, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char radio_unchecked_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x4,0x3,0x0,0x0,0x0,0xed,0xdd,0xe2,0x52,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2d,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x4,0x3,0x4,0x9,0x9,0x9,0x6,0x6,0x6,0xa,0xa,0xb,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x7f,0x7f,0x82,0xd9,0xd9,0xd9,0x47,0x47,0x48,0xff,0xff,0xff,0xbd,0x7d,0x89,0x66,0x0,0x0,0x0,0xb,0x74,0x52,0x4e,0x53,0x0,0x0,0x0,0x0,0x0,0x1b,0x88,0xd1,0xf7,0x64,0xf6,0x2,0xb3,0xed,0xd7,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0xe,0x6f,0xbd,0x30,0x4f,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x4a,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0x40,0x80,0xb0,0x8a,0xf6,0x54,0x10,0x2d,0xb9,0xfa,0xcc,0x99,0x5d,0x93,0x80,0x8c,0xb9,0x67,0x80,0xe0,0x26,0x3,0x3,0xeb,0x1a,0x10,0xe3,0x54,0x0,0x3,0xdb,0x1e,0x10,0xe3,0x74,0x2,0x3,0xfb,0x19,0x30,0x28,0x60,0xe0,0x80,0x30,0x1a,0x10,0xc,0xb8,0x14,0x5c,0x31,0x5c,0x3b,0xdc,0x40,0x6,0x4b,0x90,0x15,0x53,0x90,0x2d,0x85,0x2,0x0,0x37,0xca,0x3d,0x81,0xc4,0xfc,0x38,0x7b,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char radio_checked_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x45, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4, 0x3, 0x4, 0x9, 0x9, 0x9, 0x6, 0x6, 0x6, 0xa, 0xa, 0xb, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x7f, 0x7f, 0x82, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0x47, 0x47, 0x48, 0xd3, 0xd3, 0xd3, 0xa2, 0xa2, 0xa2, 0x79, 0x79, 0x79, 0x73, 0x73, 0x73, 0x1c, 0x1c, 0x1c, 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xa, 0x69, 0x4, 0xd4, 0x0, 0x0, 0x0, 0xb, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x88, 0xd1, 0xf7, 0x64, 0xf6, 0x2, 0xb3, 0xed, 0xd7, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x16, 0x7c, 0xd1, 0xa8, 0x19, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x69, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x6d, 0x8f, 0xdb, 0xe, 0xc0, 0x20, 0x8, 0x43, 0xdd, 0xc5, 0x3b, 0x9d, 0xa8, 0xec, 0xff, 0x7f, 0x75, 0x6a, 0x96, 0x2c, 0x8b, 0xf6, 0xad, 0x27, 0x14, 0x8a, 0x52, 0x2b, 0x69, 0x63, 0x9d, 0xb3, 0x46, 0xbf, 0x76, 0xf3, 0x21, 0x12, 0x40, 0x31, 0xf8, 0x7d, 0x0, 0x7f, 0x35, 0xdb, 0x45, 0x97, 0x1f, 0xf3, 0x81, 0x90, 0x38, 0x67, 0x4e, 0xa0, 0xd0, 0x53, 0x26, 0x22, 0x95, 0x2a, 0x52, 0x4b, 0x42, 0x34, 0xd, 0x58, 0x2, 0xd7, 0xbb, 0xa9, 0x32, 0xc8, 0x36, 0xe0, 0x80, 0x2c, 0x1d, 0x48, 0x6, 0xdc, 0xa, 0x4c, 0x91, 0x69, 0xe9, 0x74, 0x76, 0x2a, 0xa6, 0x8e, 0xaf, 0xfa, 0xb9, 0x7e, 0xee, 0xaf, 0x7, 0xb9, 0xfb, 0x8, 0xe7, 0x90, 0x1c, 0x65, 0x49, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char reference_border_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x4,0x3,0x0,0x0,0x0,0xed,0xdd,0xe2,0x52,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0xf,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0xff,0xd1,0xd1,0xff,0xb7,0xb7,0xff,0x41,0x41,0xff,0xff,0xff,0xd5,0xfa,0x24,0x40,0x0,0x0,0x0,0x2,0x74,0x52,0x4e,0x53,0x0,0x0,0x76,0x93,0xcd,0x38,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x4,0x8f,0x68,0xd9,0x51,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x27,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x50,0x32,0x6,0x3,0x25,0x6,0x5,0x6,0x30,0x60,0x62,0x30,0x10,0x4,0x3,0x66,0x6,0x3,0x1,0x90,0x0,0x23,0x2d,0x18,0x30,0x2b,0xe0,0x96,0xc2,0x9c,0x1,0x0,0x5,0x29,0x7,0xb,0xf6,0x43,0xc2,0xd4,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char radio_unchecked_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x2d, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4, 0x3, 0x4, 0x9, 0x9, 0x9, 0x6, 0x6, 0x6, 0xa, 0xa, 0xb, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x7f, 0x7f, 0x82, 0xd9, 0xd9, 0xd9, 0x47, 0x47, 0x48, 0xff, 0xff, 0xff, 0xbd, 0x7d, 0x89, 0x66, 0x0, 0x0, 0x0, 0xb, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x88, 0xd1, 0xf7, 0x64, 0xf6, 0x2, 0xb3, 0xed, 0xd7, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0xe, 0x6f, 0xbd, 0x30, 0x4f, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x4a, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x40, 0x80, 0xb0, 0x8a, 0xf6, 0x54, 0x10, 0x2d, 0xb9, 0xfa, 0xcc, 0x99, 0x5d, 0x93, 0x80, 0x8c, 0xb9, 0x67, 0x80, 0xe0, 0x26, 0x3, 0x3, 0xeb, 0x1a, 0x10, 0xe3, 0x54, 0x0, 0x3, 0xdb, 0x1e, 0x10, 0xe3, 0x74, 0x2, 0x3, 0xfb, 0x19, 0x30, 0x28, 0x60, 0xe0, 0x80, 0x30, 0x1a, 0x10, 0xc, 0xb8, 0x14, 0x5c, 0x31, 0x5c, 0x3b, 0xdc, 0x40, 0x6, 0x4b, 0x90, 0x15, 0x53, 0x90, 0x2d, 0x85, 0x2, 0x0, 0x37, 0xca, 0x3d, 0x81, 0xc4, 0xfc, 0x38, 0x7b, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char scroll_bg_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0xc,0x8,0x3,0x0,0x0,0x0,0x61,0xab,0xac,0xd5,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x48,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x40,0x3e,0x4a,0x2a,0x29,0x2f,0x20,0x20,0x24,0x3f,0x3e,0x49,0x1f,0x1f,0x24,0x20,0x20,0x24,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x3f,0x3e,0x49,0x3f,0x3e,0x49,0x1e,0x1e,0x23,0x20,0x20,0x25,0x22,0x22,0x27,0x23,0x23,0x27,0x23,0x23,0x28,0x25,0x25,0x2a,0xff,0xff,0xff,0x34,0x3f,0xa6,0x65,0x0,0x0,0x0,0x11,0x74,0x52,0x4e,0x53,0x0,0x4,0x19,0x40,0x5d,0x66,0x28,0x93,0xf0,0xfc,0x94,0xfc,0xfd,0x67,0x1a,0x96,0x95,0x1c,0xf0,0x43,0x52,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x17,0xb,0xd6,0x98,0x8f,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x5c,0x49,0x44,0x41,0x54,0x8,0xd7,0x55,0x8e,0x49,0xe,0xc0,0x20,0xc,0x3,0x3,0x61,0x9,0x3b,0x61,0xfb,0xff,0x53,0x4b,0x5b,0x55,0x15,0x73,0x1b,0xc9,0xb2,0xd,0x20,0x24,0x2a,0xad,0x15,0x4a,0x1,0x20,0x8c,0x25,0xc7,0xec,0xc8,0x1a,0x1,0xd2,0x87,0xd6,0xc7,0xe8,0x2d,0x78,0x9,0x48,0x6d,0xae,0xcd,0x6c,0x84,0xa0,0x62,0x5f,0xf,0x3d,0x2a,0x48,0x3c,0x5e,0x19,0x9c,0x4e,0x39,0x62,0x47,0x41,0x2e,0x5f,0x75,0xc9,0x7b,0xb4,0x52,0x64,0x8e,0x54,0xcd,0x7d,0xe1,0xbf,0x73,0x1,0x30,0x2f,0x7,0x53,0x16,0x34,0xbd,0xfa,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char reference_border_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0xf, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0xff, 0xd1, 0xd1, 0xff, 0xb7, 0xb7, 0xff, 0x41, 0x41, 0xff, 0xff, 0xff, 0xd5, 0xfa, 0x24, 0x40, 0x0, 0x0, 0x0, 0x2, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x76, 0x93, 0xcd, 0x38, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x4, 0x8f, 0x68, 0xd9, 0x51, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x27, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x50, 0x32, 0x6, 0x3, 0x25, 0x6, 0x5, 0x6, 0x30, 0x60, 0x62, 0x30, 0x10, 0x4, 0x3, 0x66, 0x6, 0x3, 0x1, 0x90, 0x0, 0x23, 0x2d, 0x18, 0x30, 0x2b, 0xe0, 0x96, 0xc2, 0x9c, 0x1, 0x0, 0x5, 0x29, 0x7, 0xb, 0xf6, 0x43, 0xc2, 0xd4, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char scroll_button_down_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x4,0x3,0x0,0x0,0x0,0xed,0xdd,0xe2,0x52,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x21,0x50,0x4c,0x54,0x45,0x2d,0x2c,0x2f,0x48,0x46,0x4a,0x2d,0x2c,0x2f,0x2d,0x2c,0x2f,0x2d,0x2c,0x2f,0x4c,0x4a,0x4e,0x48,0x46,0x4a,0x40,0x3e,0x42,0x38,0x36,0x3a,0xc3,0xc3,0xc3,0x59,0x59,0x59,0xb3,0x52,0xf2,0x5,0x0,0x0,0x0,0x5,0x74,0x52,0x4e,0x53,0x8,0xfe,0x9,0xd,0x19,0x4a,0xb6,0xc1,0xe6,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0xa,0x68,0xd0,0xf4,0x56,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x4,0x4e,0x1d,0x2,0xaf,0x0,0x0,0x0,0x33,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0xc,0x5,0x3,0x21,0x86,0xf4,0xe,0x30,0x28,0x63,0x88,0x80,0x30,0x5a,0xf1,0x33,0x66,0x2,0x1,0x2a,0xa3,0x73,0xe6,0xcc,0x19,0x10,0x35,0x40,0x1,0x8,0xa3,0x73,0x6,0x1,0x73,0xe0,0x96,0x1a,0x42,0x9c,0x21,0x2,0x0,0x5a,0xfa,0x3d,0xf9,0xfa,0xe2,0x64,0xe2,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char scroll_bg_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x3, 0x0, 0x0, 0x0, 0x61, 0xab, 0xac, 0xd5, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x48, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x40, 0x3e, 0x4a, 0x2a, 0x29, 0x2f, 0x20, 0x20, 0x24, 0x3f, 0x3e, 0x49, 0x1f, 0x1f, 0x24, 0x20, 0x20, 0x24, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x3f, 0x3e, 0x49, 0x3f, 0x3e, 0x49, 0x1e, 0x1e, 0x23, 0x20, 0x20, 0x25, 0x22, 0x22, 0x27, 0x23, 0x23, 0x27, 0x23, 0x23, 0x28, 0x25, 0x25, 0x2a, 0xff, 0xff, 0xff, 0x34, 0x3f, 0xa6, 0x65, 0x0, 0x0, 0x0, 0x11, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x4, 0x19, 0x40, 0x5d, 0x66, 0x28, 0x93, 0xf0, 0xfc, 0x94, 0xfc, 0xfd, 0x67, 0x1a, 0x96, 0x95, 0x1c, 0xf0, 0x43, 0x52, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x17, 0xb, 0xd6, 0x98, 0x8f, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x5c, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x55, 0x8e, 0x49, 0xe, 0xc0, 0x20, 0xc, 0x3, 0x3, 0x61, 0x9, 0x3b, 0x61, 0xfb, 0xff, 0x53, 0x4b, 0x5b, 0x55, 0x15, 0x73, 0x1b, 0xc9, 0xb2, 0xd, 0x20, 0x24, 0x2a, 0xad, 0x15, 0x4a, 0x1, 0x20, 0x8c, 0x25, 0xc7, 0xec, 0xc8, 0x1a, 0x1, 0xd2, 0x87, 0xd6, 0xc7, 0xe8, 0x2d, 0x78, 0x9, 0x48, 0x6d, 0xae, 0xcd, 0x6c, 0x84, 0xa0, 0x62, 0x5f, 0xf, 0x3d, 0x2a, 0x48, 0x3c, 0x5e, 0x19, 0x9c, 0x4e, 0x39, 0x62, 0x47, 0x41, 0x2e, 0x5f, 0x75, 0xc9, 0x7b, 0xb4, 0x52, 0x64, 0x8e, 0x54, 0xcd, 0x7d, 0xe1, 0xbf, 0x73, 0x1, 0x30, 0x2f, 0x7, 0x53, 0x16, 0x34, 0xbd, 0xfa, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char scroll_button_down_hl_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x4,0x3,0x0,0x0,0x0,0xed,0xdd,0xe2,0x52,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x21,0x50,0x4c,0x54,0x45,0x3d,0x3b,0x3f,0x60,0x5d,0x62,0x3d,0x3b,0x3f,0x3d,0x3b,0x3f,0x3d,0x3b,0x3f,0x65,0x62,0x67,0x60,0x5d,0x62,0x56,0x53,0x58,0x4b,0x49,0x4e,0xce,0xce,0xce,0x59,0x59,0x59,0xb8,0xf5,0x6d,0x48,0x0,0x0,0x0,0x5,0x74,0x52,0x4e,0x53,0x7,0xfe,0xc,0x9,0x1c,0xda,0x2b,0xa5,0x57,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0xa,0x68,0xd0,0xf4,0x56,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x33,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0xc,0x5,0x3,0x21,0x86,0xf4,0xe,0x30,0x28,0x63,0x88,0x80,0x30,0x5a,0xf1,0x33,0x66,0x2,0x1,0x2a,0xa3,0x73,0xe6,0xcc,0x19,0x10,0x35,0x40,0x1,0x8,0xa3,0x73,0x6,0x1,0x73,0xe0,0x96,0x1a,0x42,0x9c,0x21,0x2,0x0,0x5a,0xfa,0x3d,0xf9,0xfa,0xe2,0x64,0xe2,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char scroll_button_down_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x21, 0x50, 0x4c, 0x54, 0x45, 0x2d, 0x2c, 0x2f, 0x48, 0x46, 0x4a, 0x2d, 0x2c, 0x2f, 0x2d, 0x2c, 0x2f, 0x2d, 0x2c, 0x2f, 0x4c, 0x4a, 0x4e, 0x48, 0x46, 0x4a, 0x40, 0x3e, 0x42, 0x38, 0x36, 0x3a, 0xc3, 0xc3, 0xc3, 0x59, 0x59, 0x59, 0xb3, 0x52, 0xf2, 0x5, 0x0, 0x0, 0x0, 0x5, 0x74, 0x52, 0x4e, 0x53, 0x8, 0xfe, 0x9, 0xd, 0x19, 0x4a, 0xb6, 0xc1, 0xe6, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0xa, 0x68, 0xd0, 0xf4, 0x56, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x4, 0x4e, 0x1d, 0x2, 0xaf, 0x0, 0x0, 0x0, 0x33, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0xc, 0x5, 0x3, 0x21, 0x86, 0xf4, 0xe, 0x30, 0x28, 0x63, 0x88, 0x80, 0x30, 0x5a, 0xf1, 0x33, 0x66, 0x2, 0x1, 0x2a, 0xa3, 0x73, 0xe6, 0xcc, 0x19, 0x10, 0x35, 0x40, 0x1, 0x8, 0xa3, 0x73, 0x6, 0x1, 0x73, 0xe0, 0x96, 0x1a, 0x42, 0x9c, 0x21, 0x2, 0x0, 0x5a, 0xfa, 0x3d, 0xf9, 0xfa, 0xe2, 0x64, 0xe2, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char scroll_button_left_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x4,0x3,0x0,0x0,0x0,0xed,0xdd,0xe2,0x52,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x30,0x50,0x4c,0x54,0x45,0x2d,0x2c,0x2f,0x48,0x46,0x4a,0x2d,0x2c,0x2f,0x2d,0x2c,0x2f,0x2d,0x2c,0x2f,0x4c,0x4a,0x4e,0x48,0x46,0x4a,0x40,0x3e,0x42,0x38,0x36,0x3a,0xc3,0xc3,0xc3,0xc2,0xc2,0xc2,0xc1,0xc1,0xc1,0xc0,0xc0,0xc0,0xbf,0xbf,0xbf,0xbe,0xbe,0xbe,0x59,0x59,0x59,0x8e,0x47,0x76,0xf1,0x0,0x0,0x0,0x5,0x74,0x52,0x4e,0x53,0x8,0xfe,0x9,0xd,0x19,0x4a,0xb6,0xc1,0xe6,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0xf,0x18,0xba,0x0,0xd9,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x3e,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0xc,0x5,0x3,0x21,0x86,0xf4,0xe,0x30,0x28,0x63,0x88,0x80,0x30,0x5a,0x51,0x19,0x33,0xa1,0x8c,0xae,0x55,0x50,0xc6,0x2e,0x28,0xa3,0x7b,0xf7,0x6e,0x8,0xa3,0xe7,0xcc,0x19,0xa8,0x14,0x9c,0xd1,0x7b,0x17,0xa6,0xfd,0x1d,0x86,0x81,0x60,0x6,0xdc,0x52,0x43,0x88,0x33,0x44,0x0,0xcc,0x4e,0x3f,0xd1,0x4,0x90,0xbf,0x60,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char scroll_button_down_hl_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x21, 0x50, 0x4c, 0x54, 0x45, 0x3d, 0x3b, 0x3f, 0x60, 0x5d, 0x62, 0x3d, 0x3b, 0x3f, 0x3d, 0x3b, 0x3f, 0x3d, 0x3b, 0x3f, 0x65, 0x62, 0x67, 0x60, 0x5d, 0x62, 0x56, 0x53, 0x58, 0x4b, 0x49, 0x4e, 0xce, 0xce, 0xce, 0x59, 0x59, 0x59, 0xb8, 0xf5, 0x6d, 0x48, 0x0, 0x0, 0x0, 0x5, 0x74, 0x52, 0x4e, 0x53, 0x7, 0xfe, 0xc, 0x9, 0x1c, 0xda, 0x2b, 0xa5, 0x57, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0xa, 0x68, 0xd0, 0xf4, 0x56, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x33, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0xc, 0x5, 0x3, 0x21, 0x86, 0xf4, 0xe, 0x30, 0x28, 0x63, 0x88, 0x80, 0x30, 0x5a, 0xf1, 0x33, 0x66, 0x2, 0x1, 0x2a, 0xa3, 0x73, 0xe6, 0xcc, 0x19, 0x10, 0x35, 0x40, 0x1, 0x8, 0xa3, 0x73, 0x6, 0x1, 0x73, 0xe0, 0x96, 0x1a, 0x42, 0x9c, 0x21, 0x2, 0x0, 0x5a, 0xfa, 0x3d, 0xf9, 0xfa, 0xe2, 0x64, 0xe2, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char scroll_button_left_hl_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x33,0x50,0x4c,0x54,0x45,0x3d,0x3b,0x3f,0x60,0x5d,0x62,0x3d,0x3b,0x3f,0x3d,0x3b,0x3f,0x3d,0x3b,0x3f,0x65,0x62,0x67,0x60,0x5d,0x62,0x56,0x53,0x58,0x4b,0x49,0x4e,0xc9,0xc9,0xc9,0xc8,0xc8,0xc8,0xc6,0xc6,0xc6,0xc7,0xc7,0xc7,0xc5,0xc5,0xc5,0xc4,0xc4,0xc4,0xc3,0xc3,0xc3,0x59,0x59,0x59,0x2a,0x13,0xff,0x12,0x0,0x0,0x0,0x5,0x74,0x52,0x4e,0x53,0x7,0xfe,0xc,0x9,0x1c,0xda,0x2b,0xa5,0x57,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x10,0x95,0xb2,0xd,0x2c,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x4c,0x49,0x44,0x41,0x54,0x18,0xd3,0x85,0xcf,0xcb,0xe,0x80,0x20,0xc,0x44,0xd1,0xa2,0x96,0x47,0x7,0xe4,0xff,0xff,0x16,0xdc,0x90,0xe,0xc6,0x78,0x97,0x27,0x69,0xd3,0x8a,0x4,0x75,0x85,0x43,0x62,0xca,0xae,0x14,0x45,0x33,0xa5,0xdf,0x50,0xa,0x83,0x99,0x11,0xa0,0xa2,0x7a,0x0,0xd0,0xe0,0xa1,0x3d,0xd1,0xc8,0x3d,0xe3,0xa5,0xbd,0x6f,0x30,0xe5,0xef,0xb0,0x5,0xaf,0xe7,0x4e,0x7e,0xff,0x1a,0xb,0x26,0x7,0xac,0xd9,0xa3,0x51,0xe3,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char scroll_button_left_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x30, 0x50, 0x4c, 0x54, 0x45, 0x2d, 0x2c, 0x2f, 0x48, 0x46, 0x4a, 0x2d, 0x2c, 0x2f, 0x2d, 0x2c, 0x2f, 0x2d, 0x2c, 0x2f, 0x4c, 0x4a, 0x4e, 0x48, 0x46, 0x4a, 0x40, 0x3e, 0x42, 0x38, 0x36, 0x3a, 0xc3, 0xc3, 0xc3, 0xc2, 0xc2, 0xc2, 0xc1, 0xc1, 0xc1, 0xc0, 0xc0, 0xc0, 0xbf, 0xbf, 0xbf, 0xbe, 0xbe, 0xbe, 0x59, 0x59, 0x59, 0x8e, 0x47, 0x76, 0xf1, 0x0, 0x0, 0x0, 0x5, 0x74, 0x52, 0x4e, 0x53, 0x8, 0xfe, 0x9, 0xd, 0x19, 0x4a, 0xb6, 0xc1, 0xe6, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0xf, 0x18, 0xba, 0x0, 0xd9, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x3e, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0xc, 0x5, 0x3, 0x21, 0x86, 0xf4, 0xe, 0x30, 0x28, 0x63, 0x88, 0x80, 0x30, 0x5a, 0x51, 0x19, 0x33, 0xa1, 0x8c, 0xae, 0x55, 0x50, 0xc6, 0x2e, 0x28, 0xa3, 0x7b, 0xf7, 0x6e, 0x8, 0xa3, 0xe7, 0xcc, 0x19, 0xa8, 0x14, 0x9c, 0xd1, 0x7b, 0x17, 0xa6, 0xfd, 0x1d, 0x86, 0x81, 0x60, 0x6, 0xdc, 0x52, 0x43, 0x88, 0x33, 0x44, 0x0, 0xcc, 0x4e, 0x3f, 0xd1, 0x4, 0x90, 0xbf, 0x60, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char scroll_button_right_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x4,0x3,0x0,0x0,0x0,0xed,0xdd,0xe2,0x52,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x30,0x50,0x4c,0x54,0x45,0x2d,0x2c,0x2f,0x48,0x46,0x4a,0x2d,0x2c,0x2f,0x2d,0x2c,0x2f,0x2d,0x2c,0x2f,0x4c,0x4a,0x4e,0x48,0x46,0x4a,0x40,0x3e,0x42,0x38,0x36,0x3a,0xc3,0xc3,0xc3,0xc2,0xc2,0xc2,0xc1,0xc1,0xc1,0xc0,0xc0,0xc0,0xbf,0xbf,0xbf,0xbe,0xbe,0xbe,0x59,0x59,0x59,0x8e,0x47,0x76,0xf1,0x0,0x0,0x0,0x5,0x74,0x52,0x4e,0x53,0x8,0xfe,0x9,0xd,0x19,0x4a,0xb6,0xc1,0xe6,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0xf,0x18,0xba,0x0,0xd9,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x40,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0xc,0x5,0x3,0x21,0x86,0xf4,0xe,0x30,0x28,0x63,0x88,0x80,0x30,0x5a,0x51,0x18,0x33,0x61,0x8c,0x59,0x2b,0xa0,0x8c,0x5d,0xab,0xa0,0x8c,0xdd,0xbb,0x77,0x40,0x18,0x67,0xce,0x9c,0x80,0x31,0xa0,0x52,0x77,0x6f,0x40,0x19,0xef,0x30,0xc,0x84,0x30,0xe0,0x96,0x1a,0x42,0x9c,0x21,0x2,0x0,0xfd,0x36,0x40,0x93,0xf1,0x83,0x5f,0xf2,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char scroll_button_left_hl_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x33, 0x50, 0x4c, 0x54, 0x45, 0x3d, 0x3b, 0x3f, 0x60, 0x5d, 0x62, 0x3d, 0x3b, 0x3f, 0x3d, 0x3b, 0x3f, 0x3d, 0x3b, 0x3f, 0x65, 0x62, 0x67, 0x60, 0x5d, 0x62, 0x56, 0x53, 0x58, 0x4b, 0x49, 0x4e, 0xc9, 0xc9, 0xc9, 0xc8, 0xc8, 0xc8, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc5, 0xc5, 0xc5, 0xc4, 0xc4, 0xc4, 0xc3, 0xc3, 0xc3, 0x59, 0x59, 0x59, 0x2a, 0x13, 0xff, 0x12, 0x0, 0x0, 0x0, 0x5, 0x74, 0x52, 0x4e, 0x53, 0x7, 0xfe, 0xc, 0x9, 0x1c, 0xda, 0x2b, 0xa5, 0x57, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x10, 0x95, 0xb2, 0xd, 0x2c, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x85, 0xcf, 0xcb, 0xe, 0x80, 0x20, 0xc, 0x44, 0xd1, 0xa2, 0x96, 0x47, 0x7, 0xe4, 0xff, 0xff, 0x16, 0xdc, 0x90, 0xe, 0xc6, 0x78, 0x97, 0x27, 0x69, 0xd3, 0x8a, 0x4, 0x75, 0x85, 0x43, 0x62, 0xca, 0xae, 0x14, 0x45, 0x33, 0xa5, 0xdf, 0x50, 0xa, 0x83, 0x99, 0x11, 0xa0, 0xa2, 0x7a, 0x0, 0xd0, 0xe0, 0xa1, 0x3d, 0xd1, 0xc8, 0x3d, 0xe3, 0xa5, 0xbd, 0x6f, 0x30, 0xe5, 0xef, 0xb0, 0x5, 0xaf, 0xe7, 0x4e, 0x7e, 0xff, 0x1a, 0xb, 0x26, 0x7, 0xac, 0xd9, 0xa3, 0x51, 0xe3, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char scroll_button_right_hl_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x36,0x50,0x4c,0x54,0x45,0x3d,0x3b,0x3f,0x60,0x5d,0x62,0x3d,0x3b,0x3f,0x3d,0x3b,0x3f,0x3d,0x3b,0x3f,0x65,0x62,0x67,0x60,0x5d,0x62,0x56,0x53,0x58,0x4b,0x49,0x4e,0xc9,0xc9,0xc9,0xc8,0xc8,0xc8,0xc6,0xc6,0xc6,0xc7,0xc7,0xc7,0xc5,0xc5,0xc5,0xc4,0xc4,0xc4,0xc3,0xc3,0xc3,0xc2,0xc2,0xc2,0x59,0x59,0x59,0x56,0xec,0x9e,0xdc,0x0,0x0,0x0,0x5,0x74,0x52,0x4e,0x53,0x7,0xfe,0xc,0x9,0x1c,0xda,0x2b,0xa5,0x57,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x11,0xe2,0xb5,0x3d,0xba,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x4,0x4e,0x1d,0x2,0xaf,0x0,0x0,0x0,0x4c,0x49,0x44,0x41,0x54,0x18,0xd3,0x85,0xcf,0xcb,0xe,0x80,0x30,0x8,0x44,0x51,0xaa,0xd2,0x7,0xb4,0xd2,0xff,0xff,0xda,0xea,0x6e,0x46,0x63,0xbc,0xcb,0x93,0x40,0x40,0x24,0x29,0x94,0x36,0xc9,0xa5,0x42,0x25,0x8b,0x56,0x4a,0xbf,0xa0,0xb5,0x7,0x98,0x19,0x83,0x77,0xef,0xc,0x3e,0xdc,0x11,0xc6,0x1d,0xc2,0x79,0x45,0x23,0x11,0xc1,0x4b,0xe7,0xfc,0x3b,0xc,0xe0,0xf5,0xdc,0xce,0xef,0x1f,0xb,0xc,0x30,0x7,0xaf,0x1f,0x5b,0x76,0x12,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char scroll_button_right_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x30, 0x50, 0x4c, 0x54, 0x45, 0x2d, 0x2c, 0x2f, 0x48, 0x46, 0x4a, 0x2d, 0x2c, 0x2f, 0x2d, 0x2c, 0x2f, 0x2d, 0x2c, 0x2f, 0x4c, 0x4a, 0x4e, 0x48, 0x46, 0x4a, 0x40, 0x3e, 0x42, 0x38, 0x36, 0x3a, 0xc3, 0xc3, 0xc3, 0xc2, 0xc2, 0xc2, 0xc1, 0xc1, 0xc1, 0xc0, 0xc0, 0xc0, 0xbf, 0xbf, 0xbf, 0xbe, 0xbe, 0xbe, 0x59, 0x59, 0x59, 0x8e, 0x47, 0x76, 0xf1, 0x0, 0x0, 0x0, 0x5, 0x74, 0x52, 0x4e, 0x53, 0x8, 0xfe, 0x9, 0xd, 0x19, 0x4a, 0xb6, 0xc1, 0xe6, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0xf, 0x18, 0xba, 0x0, 0xd9, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x40, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0xc, 0x5, 0x3, 0x21, 0x86, 0xf4, 0xe, 0x30, 0x28, 0x63, 0x88, 0x80, 0x30, 0x5a, 0x51, 0x18, 0x33, 0x61, 0x8c, 0x59, 0x2b, 0xa0, 0x8c, 0x5d, 0xab, 0xa0, 0x8c, 0xdd, 0xbb, 0x77, 0x40, 0x18, 0x67, 0xce, 0x9c, 0x80, 0x31, 0xa0, 0x52, 0x77, 0x6f, 0x40, 0x19, 0xef, 0x30, 0xc, 0x84, 0x30, 0xe0, 0x96, 0x1a, 0x42, 0x9c, 0x21, 0x2, 0x0, 0xfd, 0x36, 0x40, 0x93, 0xf1, 0x83, 0x5f, 0xf2, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char scroll_button_up_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x4,0x3,0x0,0x0,0x0,0xed,0xdd,0xe2,0x52,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x21,0x50,0x4c,0x54,0x45,0x2d,0x2c,0x2f,0x48,0x46,0x4a,0x2d,0x2c,0x2f,0x2d,0x2c,0x2f,0x2d,0x2c,0x2f,0x4c,0x4a,0x4e,0x48,0x46,0x4a,0x40,0x3e,0x42,0x38,0x36,0x3a,0xc3,0xc3,0xc3,0x59,0x59,0x59,0xb3,0x52,0xf2,0x5,0x0,0x0,0x0,0x5,0x74,0x52,0x4e,0x53,0x8,0xfe,0x9,0xd,0x19,0x4a,0xb6,0xc1,0xe6,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0xa,0x68,0xd0,0xf4,0x56,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x36,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0xc,0x5,0x3,0x21,0x86,0xf4,0xe,0x30,0x28,0x63,0x88,0x80,0x30,0x5a,0xb1,0x33,0x3a,0x67,0x40,0x19,0x33,0x67,0x42,0x18,0x9d,0x33,0x67,0xce,0x0,0x33,0x66,0x2,0x1,0x2a,0x3,0x9f,0x39,0x10,0x6,0xdc,0x52,0x43,0x88,0x33,0x44,0x0,0x59,0xc8,0x3d,0xf9,0xf,0x68,0xc5,0xa9,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char scroll_button_right_hl_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x36, 0x50, 0x4c, 0x54, 0x45, 0x3d, 0x3b, 0x3f, 0x60, 0x5d, 0x62, 0x3d, 0x3b, 0x3f, 0x3d, 0x3b, 0x3f, 0x3d, 0x3b, 0x3f, 0x65, 0x62, 0x67, 0x60, 0x5d, 0x62, 0x56, 0x53, 0x58, 0x4b, 0x49, 0x4e, 0xc9, 0xc9, 0xc9, 0xc8, 0xc8, 0xc8, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc5, 0xc5, 0xc5, 0xc4, 0xc4, 0xc4, 0xc3, 0xc3, 0xc3, 0xc2, 0xc2, 0xc2, 0x59, 0x59, 0x59, 0x56, 0xec, 0x9e, 0xdc, 0x0, 0x0, 0x0, 0x5, 0x74, 0x52, 0x4e, 0x53, 0x7, 0xfe, 0xc, 0x9, 0x1c, 0xda, 0x2b, 0xa5, 0x57, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x11, 0xe2, 0xb5, 0x3d, 0xba, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x4, 0x4e, 0x1d, 0x2, 0xaf, 0x0, 0x0, 0x0, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x85, 0xcf, 0xcb, 0xe, 0x80, 0x30, 0x8, 0x44, 0x51, 0xaa, 0xd2, 0x7, 0xb4, 0xd2, 0xff, 0xff, 0xda, 0xea, 0x6e, 0x46, 0x63, 0xbc, 0xcb, 0x93, 0x40, 0x40, 0x24, 0x29, 0x94, 0x36, 0xc9, 0xa5, 0x42, 0x25, 0x8b, 0x56, 0x4a, 0xbf, 0xa0, 0xb5, 0x7, 0x98, 0x19, 0x83, 0x77, 0xef, 0xc, 0x3e, 0xdc, 0x11, 0xc6, 0x1d, 0xc2, 0x79, 0x45, 0x23, 0x11, 0xc1, 0x4b, 0xe7, 0xfc, 0x3b, 0xc, 0xe0, 0xf5, 0xdc, 0xce, 0xef, 0x1f, 0xb, 0xc, 0x30, 0x7, 0xaf, 0x1f, 0x5b, 0x76, 0x12, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char scroll_button_up_hl_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x4,0x3,0x0,0x0,0x0,0xed,0xdd,0xe2,0x52,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x21,0x50,0x4c,0x54,0x45,0x3d,0x3b,0x3f,0x60,0x5d,0x62,0x3d,0x3b,0x3f,0x3d,0x3b,0x3f,0x3d,0x3b,0x3f,0x65,0x62,0x67,0x60,0x5d,0x62,0x56,0x53,0x58,0x4b,0x49,0x4e,0xce,0xce,0xce,0x59,0x59,0x59,0xb8,0xf5,0x6d,0x48,0x0,0x0,0x0,0x5,0x74,0x52,0x4e,0x53,0x7,0xfe,0xc,0x9,0x1c,0xda,0x2b,0xa5,0x57,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0xa,0x68,0xd0,0xf4,0x56,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x36,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0xc,0x5,0x3,0x21,0x86,0xf4,0xe,0x30,0x28,0x63,0x88,0x80,0x30,0x5a,0xb1,0x33,0x3a,0x67,0x40,0x19,0x33,0x67,0x42,0x18,0x9d,0x33,0x67,0xce,0x0,0x33,0x66,0x2,0x1,0x2a,0x3,0x9f,0x39,0x10,0x6,0xdc,0x52,0x43,0x88,0x33,0x44,0x0,0x59,0xc8,0x3d,0xf9,0xf,0x68,0xc5,0xa9,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char scroll_button_up_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x21, 0x50, 0x4c, 0x54, 0x45, 0x2d, 0x2c, 0x2f, 0x48, 0x46, 0x4a, 0x2d, 0x2c, 0x2f, 0x2d, 0x2c, 0x2f, 0x2d, 0x2c, 0x2f, 0x4c, 0x4a, 0x4e, 0x48, 0x46, 0x4a, 0x40, 0x3e, 0x42, 0x38, 0x36, 0x3a, 0xc3, 0xc3, 0xc3, 0x59, 0x59, 0x59, 0xb3, 0x52, 0xf2, 0x5, 0x0, 0x0, 0x0, 0x5, 0x74, 0x52, 0x4e, 0x53, 0x8, 0xfe, 0x9, 0xd, 0x19, 0x4a, 0xb6, 0xc1, 0xe6, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0xa, 0x68, 0xd0, 0xf4, 0x56, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x36, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0xc, 0x5, 0x3, 0x21, 0x86, 0xf4, 0xe, 0x30, 0x28, 0x63, 0x88, 0x80, 0x30, 0x5a, 0xb1, 0x33, 0x3a, 0x67, 0x40, 0x19, 0x33, 0x67, 0x42, 0x18, 0x9d, 0x33, 0x67, 0xce, 0x0, 0x33, 0x66, 0x2, 0x1, 0x2a, 0x3, 0x9f, 0x39, 0x10, 0x6, 0xdc, 0x52, 0x43, 0x88, 0x33, 0x44, 0x0, 0x59, 0xc8, 0x3d, 0xf9, 0xf, 0x68, 0xc5, 0xa9, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char scroll_grabber_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0xc,0x8,0x3,0x0,0x0,0x0,0x61,0xab,0xac,0xd5,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x60,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x5b,0x59,0x61,0x5b,0x59,0x61,0x5a,0x58,0x60,0x59,0x57,0x5f,0x5a,0x58,0x60,0x5a,0x58,0x60,0x57,0x56,0x5e,0x58,0x56,0x5e,0x56,0x55,0x5d,0x57,0x55,0x5d,0x57,0x55,0x5d,0x55,0x53,0x5b,0x55,0x53,0x5b,0x54,0x53,0x5b,0x55,0x54,0x5c,0x54,0x52,0x5a,0x55,0x53,0x5b,0x5a,0x58,0x60,0x56,0x54,0x5c,0x54,0x53,0x5a,0x55,0x53,0x5b,0x53,0x51,0x59,0x52,0x51,0x59,0x52,0x50,0x58,0x51,0x50,0x58,0x51,0x4f,0x57,0x50,0x4e,0x56,0x4f,0x4d,0x55,0x50,0x4f,0x57,0x54,0x52,0x5a,0xff,0xff,0xff,0xc7,0x51,0xc2,0xf2,0x0,0x0,0x0,0x12,0x74,0x52,0x4e,0x53,0x0,0x2c,0xb8,0xf4,0x2e,0xf2,0xb8,0xf4,0xf5,0xf4,0xf5,0xb8,0x2f,0xf2,0x2e,0xb8,0xf4,0xb8,0x66,0xf6,0xf7,0x12,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x1f,0x5,0xd,0x10,0xbd,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x50,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0xc0,0x7,0x18,0x99,0x98,0x85,0x98,0x18,0x21,0x6c,0x16,0x56,0x61,0x11,0x11,0x61,0x56,0x16,0x30,0x87,0x4d,0x54,0xc,0x8,0x44,0xd9,0xc0,0x1c,0x76,0x71,0x9,0x20,0x10,0xe7,0x0,0x73,0x38,0x25,0xa5,0x80,0x40,0x92,0xb,0xcc,0xe1,0x96,0x90,0x6,0x2,0x9,0x6e,0x30,0x87,0x87,0x57,0x4a,0x46,0x46,0x96,0x97,0x7,0x62,0x1c,0x1f,0xbf,0x80,0x9c,0x20,0x1f,0x5e,0xdb,0x1,0x23,0xfd,0x4,0x11,0x2d,0x48,0xcb,0xd2,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char scroll_button_up_hl_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x21, 0x50, 0x4c, 0x54, 0x45, 0x3d, 0x3b, 0x3f, 0x60, 0x5d, 0x62, 0x3d, 0x3b, 0x3f, 0x3d, 0x3b, 0x3f, 0x3d, 0x3b, 0x3f, 0x65, 0x62, 0x67, 0x60, 0x5d, 0x62, 0x56, 0x53, 0x58, 0x4b, 0x49, 0x4e, 0xce, 0xce, 0xce, 0x59, 0x59, 0x59, 0xb8, 0xf5, 0x6d, 0x48, 0x0, 0x0, 0x0, 0x5, 0x74, 0x52, 0x4e, 0x53, 0x7, 0xfe, 0xc, 0x9, 0x1c, 0xda, 0x2b, 0xa5, 0x57, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0xa, 0x68, 0xd0, 0xf4, 0x56, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x36, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0xc, 0x5, 0x3, 0x21, 0x86, 0xf4, 0xe, 0x30, 0x28, 0x63, 0x88, 0x80, 0x30, 0x5a, 0xb1, 0x33, 0x3a, 0x67, 0x40, 0x19, 0x33, 0x67, 0x42, 0x18, 0x9d, 0x33, 0x67, 0xce, 0x0, 0x33, 0x66, 0x2, 0x1, 0x2a, 0x3, 0x9f, 0x39, 0x10, 0x6, 0xdc, 0x52, 0x43, 0x88, 0x33, 0x44, 0x0, 0x59, 0xc8, 0x3d, 0xf9, 0xf, 0x68, 0xc5, 0xa9, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char scroll_grabber_hl_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0xc,0x8,0x3,0x0,0x0,0x0,0x61,0xab,0xac,0xd5,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x6c,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x97,0xd0,0xdf,0x92,0xcb,0xdc,0x84,0xbb,0xd4,0x92,0xca,0xdc,0x95,0xd0,0xdd,0x83,0xbb,0xd3,0x8b,0xc8,0xd7,0x79,0xb5,0xcb,0x78,0xb4,0xca,0x73,0xb0,0xc7,0x73,0xb0,0xc7,0x7b,0xc0,0xcf,0x79,0xc5,0xd1,0x6b,0xae,0xc1,0x75,0xc6,0xcf,0x70,0xbc,0xca,0x64,0xa6,0xbc,0x71,0xbc,0xc9,0x82,0xba,0xd4,0x6a,0xa2,0xc6,0x62,0x9a,0xc2,0x61,0x9a,0xc1,0x68,0x9f,0xc2,0x5d,0x92,0xbb,0x5c,0x92,0xb8,0x58,0x8d,0xb6,0x59,0x8e,0xb3,0x56,0x89,0xb0,0x5c,0x91,0xb2,0x53,0x84,0xa9,0x58,0x8f,0xae,0x54,0x83,0xa4,0x57,0x8e,0xad,0x64,0xa5,0xba,0xff,0xff,0xff,0xbb,0x65,0x65,0x27,0x0,0x0,0x0,0x13,0x74,0x52,0x4e,0x53,0x0,0x25,0xad,0xf1,0xad,0x27,0xef,0xad,0xf1,0xf3,0xf1,0xf3,0xad,0x28,0xef,0x27,0xad,0xf2,0xad,0xcd,0x8a,0x27,0xfe,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x23,0x2a,0x62,0x6c,0x3a,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x50,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0xc0,0x7,0x18,0x99,0x98,0x85,0x59,0x18,0x21,0x6c,0x56,0x36,0x11,0x51,0x31,0x11,0x36,0x56,0x30,0x87,0x5d,0x5c,0x2,0x8,0xc4,0xd9,0xc1,0x1c,0xe,0x49,0x29,0x20,0x90,0xe4,0x4,0x73,0xb8,0xa4,0x65,0x80,0x40,0x9a,0x1b,0xcc,0xe1,0x91,0x95,0x3,0x2,0x59,0x1e,0x30,0x87,0x97,0x4f,0x5e,0x41,0x41,0x91,0x8f,0x17,0x62,0x1c,0xbf,0x80,0xa0,0x92,0x10,0x3f,0x5e,0xdb,0x1,0x41,0x87,0x4,0x7d,0x15,0xc4,0xfd,0x6a,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char scroll_grabber_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x3, 0x0, 0x0, 0x0, 0x61, 0xab, 0xac, 0xd5, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x60, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x5b, 0x59, 0x61, 0x5b, 0x59, 0x61, 0x5a, 0x58, 0x60, 0x59, 0x57, 0x5f, 0x5a, 0x58, 0x60, 0x5a, 0x58, 0x60, 0x57, 0x56, 0x5e, 0x58, 0x56, 0x5e, 0x56, 0x55, 0x5d, 0x57, 0x55, 0x5d, 0x57, 0x55, 0x5d, 0x55, 0x53, 0x5b, 0x55, 0x53, 0x5b, 0x54, 0x53, 0x5b, 0x55, 0x54, 0x5c, 0x54, 0x52, 0x5a, 0x55, 0x53, 0x5b, 0x5a, 0x58, 0x60, 0x56, 0x54, 0x5c, 0x54, 0x53, 0x5a, 0x55, 0x53, 0x5b, 0x53, 0x51, 0x59, 0x52, 0x51, 0x59, 0x52, 0x50, 0x58, 0x51, 0x50, 0x58, 0x51, 0x4f, 0x57, 0x50, 0x4e, 0x56, 0x4f, 0x4d, 0x55, 0x50, 0x4f, 0x57, 0x54, 0x52, 0x5a, 0xff, 0xff, 0xff, 0xc7, 0x51, 0xc2, 0xf2, 0x0, 0x0, 0x0, 0x12, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x2c, 0xb8, 0xf4, 0x2e, 0xf2, 0xb8, 0xf4, 0xf5, 0xf4, 0xf5, 0xb8, 0x2f, 0xf2, 0x2e, 0xb8, 0xf4, 0xb8, 0x66, 0xf6, 0xf7, 0x12, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x1f, 0x5, 0xd, 0x10, 0xbd, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x50, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0xc0, 0x7, 0x18, 0x99, 0x98, 0x85, 0x98, 0x18, 0x21, 0x6c, 0x16, 0x56, 0x61, 0x11, 0x11, 0x61, 0x56, 0x16, 0x30, 0x87, 0x4d, 0x54, 0xc, 0x8, 0x44, 0xd9, 0xc0, 0x1c, 0x76, 0x71, 0x9, 0x20, 0x10, 0xe7, 0x0, 0x73, 0x38, 0x25, 0xa5, 0x80, 0x40, 0x92, 0xb, 0xcc, 0xe1, 0x96, 0x90, 0x6, 0x2, 0x9, 0x6e, 0x30, 0x87, 0x87, 0x57, 0x4a, 0x46, 0x46, 0x96, 0x97, 0x7, 0x62, 0x1c, 0x1f, 0xbf, 0x80, 0x9c, 0x20, 0x1f, 0x5e, 0xdb, 0x1, 0x23, 0xfd, 0x4, 0x11, 0x2d, 0x48, 0xcb, 0xd2, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char selection_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x4,0x3,0x0,0x0,0x0,0xed,0xdd,0xe2,0x52,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2d,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfd,0xfb,0xff,0xfd,0xf7,0xff,0xfd,0xf7,0xff,0xfd,0xf7,0xff,0xfd,0xf6,0xff,0xf6,0xf4,0xff,0x15,0x15,0x17,0xff,0x70,0xc0,0x21,0x0,0x0,0x0,0xe,0x74,0x52,0x4e,0x53,0x6,0xf,0x16,0x18,0x2a,0x3b,0x40,0x3c,0x6,0x3d,0x44,0x3e,0x31,0x25,0x8,0x3d,0x16,0xb4,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0xe,0x6f,0xbd,0x30,0x4f,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x37,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0x54,0x36,0x6,0x2,0x23,0x1,0x6,0x91,0xb0,0x34,0x20,0x48,0x75,0x64,0x50,0xef,0x5c,0x5,0x4,0x33,0x8a,0x18,0xcc,0xf6,0xdc,0x5,0x82,0xd3,0xc9,0xc,0x66,0x6b,0x41,0x8c,0x5b,0x94,0x33,0x60,0x6,0xc2,0xad,0x80,0x5b,0xa,0x73,0x6,0x0,0x45,0x34,0x48,0x41,0xa3,0xc5,0x91,0x23,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char scroll_grabber_hl_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x3, 0x0, 0x0, 0x0, 0x61, 0xab, 0xac, 0xd5, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x6c, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x97, 0xd0, 0xdf, 0x92, 0xcb, 0xdc, 0x84, 0xbb, 0xd4, 0x92, 0xca, 0xdc, 0x95, 0xd0, 0xdd, 0x83, 0xbb, 0xd3, 0x8b, 0xc8, 0xd7, 0x79, 0xb5, 0xcb, 0x78, 0xb4, 0xca, 0x73, 0xb0, 0xc7, 0x73, 0xb0, 0xc7, 0x7b, 0xc0, 0xcf, 0x79, 0xc5, 0xd1, 0x6b, 0xae, 0xc1, 0x75, 0xc6, 0xcf, 0x70, 0xbc, 0xca, 0x64, 0xa6, 0xbc, 0x71, 0xbc, 0xc9, 0x82, 0xba, 0xd4, 0x6a, 0xa2, 0xc6, 0x62, 0x9a, 0xc2, 0x61, 0x9a, 0xc1, 0x68, 0x9f, 0xc2, 0x5d, 0x92, 0xbb, 0x5c, 0x92, 0xb8, 0x58, 0x8d, 0xb6, 0x59, 0x8e, 0xb3, 0x56, 0x89, 0xb0, 0x5c, 0x91, 0xb2, 0x53, 0x84, 0xa9, 0x58, 0x8f, 0xae, 0x54, 0x83, 0xa4, 0x57, 0x8e, 0xad, 0x64, 0xa5, 0xba, 0xff, 0xff, 0xff, 0xbb, 0x65, 0x65, 0x27, 0x0, 0x0, 0x0, 0x13, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x25, 0xad, 0xf1, 0xad, 0x27, 0xef, 0xad, 0xf1, 0xf3, 0xf1, 0xf3, 0xad, 0x28, 0xef, 0x27, 0xad, 0xf2, 0xad, 0xcd, 0x8a, 0x27, 0xfe, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x23, 0x2a, 0x62, 0x6c, 0x3a, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x50, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0xc0, 0x7, 0x18, 0x99, 0x98, 0x85, 0x59, 0x18, 0x21, 0x6c, 0x56, 0x36, 0x11, 0x51, 0x31, 0x11, 0x36, 0x56, 0x30, 0x87, 0x5d, 0x5c, 0x2, 0x8, 0xc4, 0xd9, 0xc1, 0x1c, 0xe, 0x49, 0x29, 0x20, 0x90, 0xe4, 0x4, 0x73, 0xb8, 0xa4, 0x65, 0x80, 0x40, 0x9a, 0x1b, 0xcc, 0xe1, 0x91, 0x95, 0x3, 0x2, 0x59, 0x1e, 0x30, 0x87, 0x97, 0x4f, 0x5e, 0x41, 0x41, 0x91, 0x8f, 0x17, 0x62, 0x1c, 0xbf, 0x80, 0xa0, 0x92, 0x10, 0x3f, 0x5e, 0xdb, 0x1, 0x41, 0x87, 0x4, 0x7d, 0x15, 0xc4, 0xfd, 0x6a, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char selection_oof_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x4,0x3,0x0,0x0,0x0,0xed,0xdd,0xe2,0x52,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x30,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2c,0x2,0xfd,0xfb,0xff,0xfd,0xfb,0xff,0xfd,0xfb,0xff,0xfd,0xfb,0xff,0x15,0x15,0x17,0xe9,0x54,0x1,0x21,0x0,0x0,0x0,0xf,0x74,0x52,0x4e,0x53,0xa,0x1a,0x26,0x29,0x2a,0x48,0x65,0x6d,0x6e,0x66,0x3,0x20,0x25,0x16,0xc,0x1f,0x74,0xbf,0x74,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0xf,0x18,0xba,0x0,0xd9,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x38,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0x54,0x76,0x1,0x2,0x23,0x1,0x6,0xd1,0xf4,0xe,0x20,0x28,0xb,0x64,0xd0,0x5c,0x7d,0x6,0x8,0x76,0x4d,0x62,0x70,0xdf,0xfb,0xe,0x8,0x6e,0x97,0x30,0x78,0x9c,0x3,0x31,0xde,0xb4,0x50,0xca,0x80,0x1b,0x8,0xb7,0x2,0x6e,0x29,0xcc,0x19,0x0,0x1a,0x23,0x52,0x59,0xa4,0x2f,0x3d,0xa7,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char scroll_grabber_pressed_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x6, 0x0, 0x0, 0x0, 0x56, 0x75, 0x5c, 0xe7, 0x0, 0x0, 0x0, 0x4, 0x73, 0x42, 0x49, 0x54, 0x8, 0x8, 0x8, 0x8, 0x7c, 0x8, 0x64, 0x88, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xd, 0xd7, 0x0, 0x0, 0xd, 0xd7, 0x1, 0x42, 0x28, 0x9b, 0x78, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x0, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x6e, 0x6b, 0x73, 0x63, 0x61, 0x70, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x9b, 0xee, 0x3c, 0x1a, 0x0, 0x0, 0x0, 0x66, 0x49, 0x44, 0x41, 0x54, 0x28, 0x91, 0xcd, 0x91, 0xb1, 0xa, 0xc0, 0x20, 0x10, 0x43, 0x63, 0x71, 0xbf, 0x5f, 0x12, 0x9c, 0xfd, 0x1a, 0x3f, 0xcd, 0xa9, 0x83, 0xe0, 0x2f, 0x65, 0x2f, 0x9c, 0x8b, 0x83, 0x47, 0xed, 0x60, 0xbb, 0x34, 0xdb, 0x3d, 0x12, 0x48, 0x38, 0xa7, 0xaa, 0xd8, 0xd1, 0xb1, 0xe5, 0x7e, 0x13, 0xf0, 0xf3, 0xd1, 0x5a, 0xf3, 0x24, 0x23, 0x80, 0x34, 0x50, 0x11, 0x91, 0x1a, 0x42, 0xb8, 0x96, 0x1, 0x92, 0x51, 0x55, 0xf3, 0x84, 0x32, 0x49, 0x0, 0x38, 0x9f, 0x2a, 0x25, 0xdc, 0x65, 0xd8, 0xe7, 0xd1, 0x65, 0xe1, 0x31, 0xcc, 0x6c, 0x10, 0x91, 0x3a, 0x3a, 0x9b, 0xd1, 0xb3, 0xc7, 0xfd, 0xef, 0x71, 0x1d, 0x42, 0xe6, 0x21, 0x43, 0xf5, 0x2b, 0xd8, 0x6c, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char spinbox_updown_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0xcd,0x49,0x44,0x41,0x54,0x38,0x8d,0xe5,0x53,0x31,0xe,0x82,0x40,0x10,0x9c,0x5d,0x22,0x3e,0x80,0x86,0xc4,0x0,0xe1,0xf,0x16,0x5a,0x58,0xf9,0x5,0xe3,0x13,0xd0,0xc2,0xc4,0xcf,0xd8,0xf0,0x5,0xe3,0x1f,0x2c,0x2c,0x6c,0xf8,0x1,0xc5,0x72,0x85,0x9,0xd,0xf,0x10,0x43,0xce,0x86,0x82,0xe0,0xe9,0x19,0x8d,0x95,0x53,0xce,0xce,0x6e,0x26,0x99,0x59,0xe0,0x97,0x10,0x91,0x95,0x52,0x2a,0x79,0xa5,0xa1,0x67,0x83,0xa2,0x28,0xa6,0x0,0x8e,0x0,0x98,0x99,0xe7,0x61,0x18,0x9e,0xde,0x3e,0x20,0x22,0x3e,0x11,0x65,0x0,0x46,0x2d,0x55,0x3a,0x8e,0x33,0xe,0x82,0xe0,0xd2,0xd7,0x72,0x9f,0xc8,0xb2,0x6c,0x0,0x60,0xdf,0x59,0x6,0x0,0xbf,0x69,0x9a,0x43,0x9e,0xe7,0x43,0xeb,0x1,0xcf,0xf3,0x76,0x44,0x34,0x33,0x18,0x9b,0xb8,0xae,0x9b,0x9a,0x1c,0xff,0x3b,0x1e,0x62,0x14,0x91,0x94,0x88,0x8c,0xe5,0x21,0xa2,0x34,0x8a,0xa2,0x75,0x97,0x7b,0x48,0xa1,0xaa,0xaa,0x8d,0xd6,0xda,0x54,0x9a,0x73,0x5d,0xd7,0x5b,0xab,0x83,0xd6,0xc5,0xe7,0x45,0x2,0x80,0x38,0x8e,0x4b,0xad,0xf5,0x2,0xc0,0x15,0xc0,0x8d,0x99,0x97,0xa6,0x65,0x2b,0x94,0x52,0x89,0xed,0x99,0xbe,0xc6,0x1d,0x31,0x1f,0x40,0xdc,0x74,0x8a,0x5b,0xc1,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char selection_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x2d, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfd, 0xfb, 0xff, 0xfd, 0xf7, 0xff, 0xfd, 0xf7, 0xff, 0xfd, 0xf7, 0xff, 0xfd, 0xf6, 0xff, 0xf6, 0xf4, 0xff, 0x15, 0x15, 0x17, 0xff, 0x70, 0xc0, 0x21, 0x0, 0x0, 0x0, 0xe, 0x74, 0x52, 0x4e, 0x53, 0x6, 0xf, 0x16, 0x18, 0x2a, 0x3b, 0x40, 0x3c, 0x6, 0x3d, 0x44, 0x3e, 0x31, 0x25, 0x8, 0x3d, 0x16, 0xb4, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0xe, 0x6f, 0xbd, 0x30, 0x4f, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x37, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x54, 0x36, 0x6, 0x2, 0x23, 0x1, 0x6, 0x91, 0xb0, 0x34, 0x20, 0x48, 0x75, 0x64, 0x50, 0xef, 0x5c, 0x5, 0x4, 0x33, 0x8a, 0x18, 0xcc, 0xf6, 0xdc, 0x5, 0x82, 0xd3, 0xc9, 0xc, 0x66, 0x6b, 0x41, 0x8c, 0x5b, 0x94, 0x33, 0x60, 0x6, 0xc2, 0xad, 0x80, 0x5b, 0xa, 0x73, 0x6, 0x0, 0x45, 0x34, 0x48, 0x41, 0xa3, 0xc5, 0x91, 0x23, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char submenu_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x64,0x49,0x44,0x41,0x54,0x18,0x95,0x7d,0xca,0x21,0x12,0x80,0x20,0x14,0x45,0xd1,0xf7,0x2d,0x4,0x36,0x40,0x63,0xa8,0xba,0x1f,0xbb,0x9d,0xe5,0xb8,0x0,0xb3,0xfb,0xd1,0xc,0x8d,0xd,0x10,0x48,0xcf,0x22,0x6,0xc7,0xef,0x6d,0x77,0xe6,0x8,0x0,0xa4,0x94,0x88,0x3b,0x92,0x4b,0x8,0x61,0xeb,0x3f,0xe0,0x95,0x88,0xac,0x39,0xe7,0x49,0x5,0x0,0x2c,0xc9,0xbd,0x94,0x62,0x35,0x0,0x0,0x63,0x6b,0x6d,0xfd,0x3,0x4f,0x1a,0x38,0x8d,0x31,0x51,0x3,0x55,0x44,0x66,0xe7,0x5c,0xfd,0x4,0x24,0xa3,0xf7,0xfe,0xe8,0x7f,0x1,0xe,0xc2,0x1e,0x10,0xa,0xf0,0x33,0x4c,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char selection_oof_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x30, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2c, 0x2, 0xfd, 0xfb, 0xff, 0xfd, 0xfb, 0xff, 0xfd, 0xfb, 0xff, 0xfd, 0xfb, 0xff, 0x15, 0x15, 0x17, 0xe9, 0x54, 0x1, 0x21, 0x0, 0x0, 0x0, 0xf, 0x74, 0x52, 0x4e, 0x53, 0xa, 0x1a, 0x26, 0x29, 0x2a, 0x48, 0x65, 0x6d, 0x6e, 0x66, 0x3, 0x20, 0x25, 0x16, 0xc, 0x1f, 0x74, 0xbf, 0x74, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0xf, 0x18, 0xba, 0x0, 0xd9, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x38, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x54, 0x76, 0x1, 0x2, 0x23, 0x1, 0x6, 0xd1, 0xf4, 0xe, 0x20, 0x28, 0xb, 0x64, 0xd0, 0x5c, 0x7d, 0x6, 0x8, 0x76, 0x4d, 0x62, 0x70, 0xdf, 0xfb, 0xe, 0x8, 0x6e, 0x97, 0x30, 0x78, 0x9c, 0x3, 0x31, 0xde, 0xb4, 0x50, 0xca, 0x80, 0x1b, 0x8, 0xb7, 0x2, 0x6e, 0x29, 0xcc, 0x19, 0x0, 0x1a, 0x23, 0x52, 0x59, 0xa4, 0x2f, 0x3d, 0xa7, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char tab_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x4,0x0,0x0,0x0,0x6e,0x6,0x76,0x0,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0x0,0xaa,0x8d,0x23,0x32,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x1f,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0xc0,0x4,0xff,0x23,0xff,0x8b,0xfc,0x17,0xf9,0x1f,0x49,0xac,0x10,0x13,0x3,0x3,0x61,0x53,0xb0,0x98,0x80,0xc,0x0,0xa8,0x3e,0x18,0x31,0xbe,0x78,0xfc,0x7a,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char spinbox_updown_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0xcd, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xe5, 0x53, 0x31, 0xe, 0x82, 0x40, 0x10, 0x9c, 0x5d, 0x22, 0x3e, 0x80, 0x86, 0xc4, 0x0, 0xe1, 0xf, 0x16, 0x5a, 0x58, 0xf9, 0x5, 0xe3, 0x13, 0xd0, 0xc2, 0xc4, 0xcf, 0xd8, 0xf0, 0x5, 0xe3, 0x1f, 0x2c, 0x2c, 0x6c, 0xf8, 0x1, 0xc5, 0x72, 0x85, 0x9, 0xd, 0xf, 0x10, 0x43, 0xce, 0x86, 0x82, 0xe0, 0xe9, 0x19, 0x8d, 0x95, 0x53, 0xce, 0xce, 0x6e, 0x26, 0x99, 0x59, 0xe0, 0x97, 0x10, 0x91, 0x95, 0x52, 0x2a, 0x79, 0xa5, 0xa1, 0x67, 0x83, 0xa2, 0x28, 0xa6, 0x0, 0x8e, 0x0, 0x98, 0x99, 0xe7, 0x61, 0x18, 0x9e, 0xde, 0x3e, 0x20, 0x22, 0x3e, 0x11, 0x65, 0x0, 0x46, 0x2d, 0x55, 0x3a, 0x8e, 0x33, 0xe, 0x82, 0xe0, 0xd2, 0xd7, 0x72, 0x9f, 0xc8, 0xb2, 0x6c, 0x0, 0x60, 0xdf, 0x59, 0x6, 0x0, 0xbf, 0x69, 0x9a, 0x43, 0x9e, 0xe7, 0x43, 0xeb, 0x1, 0xcf, 0xf3, 0x76, 0x44, 0x34, 0x33, 0x18, 0x9b, 0xb8, 0xae, 0x9b, 0x9a, 0x1c, 0xff, 0x3b, 0x1e, 0x62, 0x14, 0x91, 0x94, 0x88, 0x8c, 0xe5, 0x21, 0xa2, 0x34, 0x8a, 0xa2, 0x75, 0x97, 0x7b, 0x48, 0xa1, 0xaa, 0xaa, 0x8d, 0xd6, 0xda, 0x54, 0x9a, 0x73, 0x5d, 0xd7, 0x5b, 0xab, 0x83, 0xd6, 0xc5, 0xe7, 0x45, 0x2, 0x80, 0x38, 0x8e, 0x4b, 0xad, 0xf5, 0x2, 0xc0, 0x15, 0xc0, 0x8d, 0x99, 0x97, 0xa6, 0x65, 0x2b, 0x94, 0x52, 0x89, 0xed, 0x99, 0xbe, 0xc6, 0x1d, 0x31, 0x1f, 0x40, 0xdc, 0x74, 0x8a, 0x5b, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char tab_behind_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x5a,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30,0x2e,0x36,0x43,0x40,0x4d,0x0,0x0,0x0,0x43,0x40,0x4c,0x3e,0x3c,0x47,0x3e,0x3b,0x46,0x31,0x2f,0x38,0x2d,0x2b,0x33,0x3f,0x3c,0x47,0x35,0x32,0x3b,0x5b,0xb0,0x1,0xb7,0x0,0x0,0x0,0x18,0x74,0x52,0x4e,0x53,0x0,0x1,0x3,0x5,0x8,0xa,0xb,0xc,0x4,0x11,0x19,0x1f,0x22,0x24,0x15,0x25,0x34,0x3f,0x46,0x47,0x77,0xf3,0x7,0xef,0xd3,0x51,0x5e,0xca,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x1d,0xeb,0x3,0x71,0x91,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x6e,0x49,0x44,0x41,0x54,0x18,0xd3,0xb5,0xcc,0x49,0xe,0x80,0x20,0x10,0x44,0xd1,0x2,0x6c,0x90,0x49,0x26,0x27,0xd4,0xfb,0x9f,0x53,0x63,0x34,0x2e,0x58,0xfb,0x97,0x2f,0xa9,0x2,0x18,0x17,0x1d,0x49,0xa5,0x24,0x75,0x82,0x33,0x80,0xf5,0xa4,0x8d,0x75,0xde,0x3b,0x6b,0x34,0xf5,0xc,0x9c,0x86,0x10,0x53,0x2e,0x25,0xa7,0x18,0x6,0xe2,0x10,0x3a,0x8c,0xd3,0x5a,0xaf,0xd6,0x69,0xc,0x5a,0x60,0x36,0x71,0xd9,0xf6,0xbb,0x6d,0x89,0x66,0x6,0xd9,0x74,0xec,0x4f,0x47,0xb2,0x4,0xe9,0x72,0x7d,0xa1,0x66,0x27,0xa1,0x7c,0xf9,0xa0,0x78,0xd5,0x42,0x33,0x69,0x4e,0xff,0x80,0x13,0xce,0x8,0x12,0xa9,0x90,0xd8,0x47,0x93,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char submenu_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x8, 0x6, 0x0, 0x0, 0x0, 0xc4, 0xf, 0xbe, 0x8b, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0x64, 0x49, 0x44, 0x41, 0x54, 0x18, 0x95, 0x7d, 0xca, 0x21, 0x12, 0x80, 0x20, 0x14, 0x45, 0xd1, 0xf7, 0x2d, 0x4, 0x36, 0x40, 0x63, 0xa8, 0xba, 0x1f, 0xbb, 0x9d, 0xe5, 0xb8, 0x0, 0xb3, 0xfb, 0xd1, 0xc, 0x8d, 0xd, 0x10, 0x48, 0xcf, 0x22, 0x6, 0xc7, 0xef, 0x6d, 0x77, 0xe6, 0x8, 0x0, 0xa4, 0x94, 0x88, 0x3b, 0x92, 0x4b, 0x8, 0x61, 0xeb, 0x3f, 0xe0, 0x95, 0x88, 0xac, 0x39, 0xe7, 0x49, 0x5, 0x0, 0x2c, 0xc9, 0xbd, 0x94, 0x62, 0x35, 0x0, 0x0, 0x63, 0x6b, 0x6d, 0xfd, 0x3, 0x4f, 0x1a, 0x38, 0x8d, 0x31, 0x51, 0x3, 0x55, 0x44, 0x66, 0xe7, 0x5c, 0xfd, 0x4, 0x24, 0xa3, 0xf7, 0xfe, 0xe8, 0x7f, 0x1, 0xe, 0xc2, 0x1e, 0x10, 0xa, 0xf0, 0x33, 0x4c, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char tab_close_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0xfa,0x49,0x44,0x41,0x54,0x38,0x8d,0xcd,0x92,0x5f,0x4a,0xc4,0x30,0x10,0x87,0xbf,0xb1,0xb9,0xc2,0x16,0x7c,0x6b,0xc1,0xa2,0x85,0x7a,0x4,0x2d,0xfe,0x39,0xc4,0x9e,0x70,0x4f,0x61,0xc5,0x3d,0x83,0x5,0x95,0x4,0xd2,0x37,0x5,0x8f,0x90,0x94,0xf1,0xc5,0x4a,0x76,0xcd,0x22,0xf8,0xa2,0xf3,0x38,0xc3,0xef,0x9b,0xe4,0x4b,0xe0,0x5f,0x95,0xf7,0x7e,0xed,0x9c,0x2b,0xf,0xcd,0x9d,0x73,0xa5,0xf7,0x7e,0x9d,0xf6,0x8e,0xd2,0xb0,0x88,0x6c,0x8c,0x31,0x43,0xe,0xe2,0x9c,0x2b,0x8d,0x31,0x83,0x88,0x6c,0x52,0xc8,0x17,0x20,0xc6,0x38,0xa8,0xea,0x8,0x74,0xc6,0x98,0xed,0x34,0x4d,0xc7,0xcb,0xcc,0x5a,0xbb,0x2a,0x8a,0xe2,0xe,0xe8,0x80,0x17,0xe0,0x61,0x99,0x49,0xba,0xc5,0x5a,0xbb,0xfa,0xdc,0x72,0xe,0x3c,0x3,0xd7,0x21,0x84,0x98,0xf6,0x54,0xf5,0xaa,0xae,0xeb,0xb7,0x2c,0x60,0x1f,0x22,0x22,0x56,0x55,0x23,0xd0,0xe6,0xc2,0x59,0x40,0x2,0xd9,0x8a,0x48,0xbb,0x28,0x50,0xd5,0x8b,0xfd,0xf0,0x8e,0x83,0x9f,0x4a,0x44,0xb2,0xcb,0xbe,0x1,0x92,0x2b,0xb4,0xaa,0x6a,0x81,0x27,0xe0,0x4,0xb8,0x4f,0xc5,0x66,0x1,0x19,0x89,0x97,0x21,0x84,0x5e,0x55,0x1f,0x81,0xb3,0x1c,0x44,0xe,0x85,0x53,0x61,0xb9,0xd7,0xa9,0xaa,0xea,0x75,0xe7,0x4,0xc6,0x98,0x1b,0x11,0xe9,0x80,0x31,0xc6,0xd8,0xa7,0xc2,0x9a,0xa6,0x79,0x9f,0xe7,0xf9,0x16,0x18,0x81,0x53,0x55,0xed,0xb3,0xa2,0x7e,0xf3,0x95,0xff,0xbe,0x3e,0x0,0xbd,0x2c,0x93,0xec,0xb,0xe5,0x4f,0xb1,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char tab_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x8, 0x4, 0x0, 0x0, 0x0, 0x6e, 0x6, 0x76, 0x0, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0x0, 0xaa, 0x8d, 0x23, 0x32, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x1f, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0xc0, 0x4, 0xff, 0x23, 0xff, 0x8b, 0xfc, 0x17, 0xf9, 0x1f, 0x49, 0xac, 0x10, 0x13, 0x3, 0x3, 0x61, 0x53, 0xb0, 0x98, 0x80, 0xc, 0x0, 0xa8, 0x3e, 0x18, 0x31, 0xbe, 0x78, 0xfc, 0x7a, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char tab_container_bg_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x8a,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c,0x3a,0x44,0x56,0x53,0x61,0x56,0x52,0x60,0x47,0x44,0x52,0x33,0x31,0x39,0x47,0x44,0x50,0x47,0x44,0x51,0x52,0x50,0x5d,0x51,0x4f,0x5d,0x46,0x42,0x4e,0x42,0x3e,0x4a,0x41,0x3e,0x49,0x51,0x4e,0x5b,0x40,0x3e,0x48,0x4f,0x4c,0x59,0x3f,0x3d,0x47,0x4e,0x4a,0x58,0x3e,0x3b,0x46,0x4b,0x49,0x55,0x3c,0x3a,0x44,0x4a,0x47,0x54,0x3b,0x39,0x43,0x49,0x46,0x53,0x3a,0x38,0x42,0x47,0x45,0x50,0x39,0x37,0x40,0x47,0x43,0x50,0x38,0x35,0x3f,0x36,0x34,0x3e,0x44,0x42,0x4d,0x44,0x41,0x4c,0xff,0xff,0xff,0xe5,0x37,0x10,0x78,0x0,0x0,0x0,0x15,0x74,0x52,0x4e,0x53,0x4,0xa,0x11,0x19,0x1f,0x22,0x24,0x15,0x25,0x34,0x3f,0x46,0x47,0x48,0x77,0xef,0xef,0xef,0x77,0xef,0xed,0xe8,0xff,0x76,0xed,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x2d,0xcd,0xda,0x41,0x3d,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x93,0x49,0x44,0x41,0x54,0x18,0xd3,0x65,0xcf,0x47,0x12,0x82,0x40,0x10,0x5,0xd0,0x9e,0xc8,0x44,0x92,0x22,0x41,0x54,0x44,0x40,0x14,0xef,0x7f,0x3e,0x7,0x8a,0xea,0x85,0xbe,0xe5,0xaf,0xea,0xf0,0x1,0x8,0x65,0x5c,0xc8,0x40,0x70,0x46,0x9,0x0,0x89,0x94,0x36,0xd6,0x79,0xef,0xac,0xd1,0x2a,0x22,0x40,0x55,0x9c,0x14,0xa7,0x4d,0x91,0xc4,0x8a,0x2,0xd3,0x69,0x59,0xd5,0x9b,0xaa,0x4c,0x35,0x3,0x6e,0x9a,0xfa,0xbc,0xab,0x1b,0xc3,0x41,0xd8,0xf6,0x82,0x5a,0x2b,0x40,0xba,0xeb,0xd,0x5d,0x9d,0x4,0xe9,0xbb,0x3b,0xea,0xfc,0x1a,0xf4,0xf,0xd4,0xaf,0x81,0x1b,0x46,0x34,0x84,0x11,0x61,0xa7,0x27,0x9a,0xc2,0x52,0x6e,0xe6,0x17,0x9a,0xc3,0x59,0xa6,0xb3,0xf1,0xbd,0x1b,0xb3,0xf0,0x18,0x55,0xf9,0x61,0xf9,0x6c,0x96,0x63,0x1e,0x5e,0xff,0x2b,0xf7,0x5b,0xff,0xb,0x69,0x5a,0x14,0xfa,0x84,0xf6,0xc2,0x8,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char tab_behind_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x5a, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x2e, 0x36, 0x43, 0x40, 0x4d, 0x0, 0x0, 0x0, 0x43, 0x40, 0x4c, 0x3e, 0x3c, 0x47, 0x3e, 0x3b, 0x46, 0x31, 0x2f, 0x38, 0x2d, 0x2b, 0x33, 0x3f, 0x3c, 0x47, 0x35, 0x32, 0x3b, 0x5b, 0xb0, 0x1, 0xb7, 0x0, 0x0, 0x0, 0x18, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x1, 0x3, 0x5, 0x8, 0xa, 0xb, 0xc, 0x4, 0x11, 0x19, 0x1f, 0x22, 0x24, 0x15, 0x25, 0x34, 0x3f, 0x46, 0x47, 0x77, 0xf3, 0x7, 0xef, 0xd3, 0x51, 0x5e, 0xca, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x1d, 0xeb, 0x3, 0x71, 0x91, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x6e, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0xb5, 0xcc, 0x49, 0xe, 0x80, 0x20, 0x10, 0x44, 0xd1, 0x2, 0x6c, 0x90, 0x49, 0x26, 0x27, 0xd4, 0xfb, 0x9f, 0x53, 0x63, 0x34, 0x2e, 0x58, 0xfb, 0x97, 0x2f, 0xa9, 0x2, 0x18, 0x17, 0x1d, 0x49, 0xa5, 0x24, 0x75, 0x82, 0x33, 0x80, 0xf5, 0xa4, 0x8d, 0x75, 0xde, 0x3b, 0x6b, 0x34, 0xf5, 0xc, 0x9c, 0x86, 0x10, 0x53, 0x2e, 0x25, 0xa7, 0x18, 0x6, 0xe2, 0x10, 0x3a, 0x8c, 0xd3, 0x5a, 0xaf, 0xd6, 0x69, 0xc, 0x5a, 0x60, 0x36, 0x71, 0xd9, 0xf6, 0xbb, 0x6d, 0x89, 0x66, 0x6, 0xd9, 0x74, 0xec, 0x4f, 0x47, 0xb2, 0x4, 0xe9, 0x72, 0x7d, 0xa1, 0x66, 0x27, 0xa1, 0x7c, 0xf9, 0xa0, 0x78, 0xd5, 0x42, 0x33, 0x69, 0x4e, 0xff, 0x80, 0x13, 0xce, 0x8, 0x12, 0xa9, 0x90, 0xd8, 0x47, 0x93, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char tab_current_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x9c,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3f,0x3d,0x48,0x5b,0x58,0x66,0x5b,0x57,0x65,0x57,0x54,0x62,0x55,0x53,0x62,0x4a,0x46,0x52,0x46,0x41,0x4e,0x45,0x41,0x4d,0x55,0x52,0x60,0x44,0x41,0x4c,0x53,0x50,0x5e,0x43,0x40,0x4b,0x52,0x4e,0x5d,0x41,0x3e,0x4a,0x4f,0x4d,0x5a,0x3f,0x3d,0x48,0x4e,0x4b,0x59,0x3e,0x3c,0x47,0x4d,0x4a,0x58,0x3d,0x3b,0x46,0x4b,0x49,0x54,0x3c,0x3a,0x44,0x4b,0x47,0x54,0x3b,0x39,0x43,0x3b,0x39,0x42,0x3b,0x38,0x43,0x3b,0x38,0x42,0x3a,0x37,0x41,0x39,0x37,0x41,0x3a,0x38,0x41,0x39,0x36,0x3f,0x38,0x36,0x3f,0x39,0x36,0x40,0x38,0x36,0x40,0x37,0x35,0x3e,0x37,0x34,0x3e,0x36,0x35,0x3d,0x35,0x32,0x3b,0x59,0xdd,0xd3,0xff,0x0,0x0,0x0,0x11,0x74,0x52,0x4e,0x53,0x4,0xa,0x11,0x19,0x1f,0x22,0x24,0x15,0x25,0x34,0x3f,0x46,0x47,0x48,0x77,0xef,0xef,0xa3,0x31,0x6b,0xc2,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x33,0x37,0xd5,0x7c,0x5e,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0xa2,0x49,0x44,0x41,0x54,0x18,0xd3,0x45,0xcd,0xd9,0x12,0x82,0x30,0xc,0x40,0xd1,0x0,0x2d,0x4b,0x5b,0x36,0x59,0x44,0x44,0x44,0xa4,0x68,0x59,0x54,0xfc,0xff,0x8f,0x33,0x30,0x4c,0x3d,0x93,0xa7,0x3b,0x93,0x4,0xc0,0x30,0x2d,0x42,0x6d,0x44,0x89,0x65,0x1a,0x0,0x86,0xe3,0x7a,0x8c,0xb,0xdf,0x17,0x9c,0x79,0xae,0x63,0x80,0xe9,0x6,0x61,0x7c,0xd8,0xc4,0x61,0xe0,0x9a,0x60,0x79,0x51,0x92,0x66,0x9b,0x34,0x89,0x3c,0xb,0x8,0xcb,0xb3,0xe3,0x2e,0xcb,0x19,0x1,0xca,0x8b,0x93,0x56,0x70,0xa,0xb6,0x28,0xcf,0x5a,0x29,0x6c,0xb0,0xfd,0xea,0xa2,0x55,0xfe,0x1a,0xea,0xab,0x56,0xaf,0x41,0x34,0x37,0xad,0xc1,0x15,0xca,0xdb,0xbb,0xd6,0xe2,0x51,0xc2,0xba,0x7f,0xe8,0xf0,0x2d,0x6,0x29,0xfb,0x5e,0xca,0xc7,0x53,0xca,0x3d,0xa8,0x61,0x50,0xc3,0xa8,0xc6,0x41,0xed,0x61,0x9a,0xa6,0x19,0xbd,0xe6,0xf7,0x1e,0x3e,0xcb,0x82,0x83,0xbe,0x18,0x7e,0xa1,0xe5,0x17,0x1f,0xcf,0x5d,0x82,0x6b,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char tab_close_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0xfa, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xcd, 0x92, 0x5f, 0x4a, 0xc4, 0x30, 0x10, 0x87, 0xbf, 0xb1, 0xb9, 0xc2, 0x16, 0x7c, 0x6b, 0xc1, 0xa2, 0x85, 0x7a, 0x4, 0x2d, 0xfe, 0x39, 0xc4, 0x9e, 0x70, 0x4f, 0x61, 0xc5, 0x3d, 0x83, 0x5, 0x95, 0x4, 0xd2, 0x37, 0x5, 0x8f, 0x90, 0x94, 0xf1, 0xc5, 0x4a, 0x76, 0xcd, 0x22, 0xf8, 0xa2, 0xf3, 0x38, 0xc3, 0xef, 0x9b, 0xe4, 0x4b, 0xe0, 0x5f, 0x95, 0xf7, 0x7e, 0xed, 0x9c, 0x2b, 0xf, 0xcd, 0x9d, 0x73, 0xa5, 0xf7, 0x7e, 0x9d, 0xf6, 0x8e, 0xd2, 0xb0, 0x88, 0x6c, 0x8c, 0x31, 0x43, 0xe, 0xe2, 0x9c, 0x2b, 0x8d, 0x31, 0x83, 0x88, 0x6c, 0x52, 0xc8, 0x17, 0x20, 0xc6, 0x38, 0xa8, 0xea, 0x8, 0x74, 0xc6, 0x98, 0xed, 0x34, 0x4d, 0xc7, 0xcb, 0xcc, 0x5a, 0xbb, 0x2a, 0x8a, 0xe2, 0xe, 0xe8, 0x80, 0x17, 0xe0, 0x61, 0x99, 0x49, 0xba, 0xc5, 0x5a, 0xbb, 0xfa, 0xdc, 0x72, 0xe, 0x3c, 0x3, 0xd7, 0x21, 0x84, 0x98, 0xf6, 0x54, 0xf5, 0xaa, 0xae, 0xeb, 0xb7, 0x2c, 0x60, 0x1f, 0x22, 0x22, 0x56, 0x55, 0x23, 0xd0, 0xe6, 0xc2, 0x59, 0x40, 0x2, 0xd9, 0x8a, 0x48, 0xbb, 0x28, 0x50, 0xd5, 0x8b, 0xfd, 0xf0, 0x8e, 0x83, 0x9f, 0x4a, 0x44, 0xb2, 0xcb, 0xbe, 0x1, 0x92, 0x2b, 0xb4, 0xaa, 0x6a, 0x81, 0x27, 0xe0, 0x4, 0xb8, 0x4f, 0xc5, 0x66, 0x1, 0x19, 0x89, 0x97, 0x21, 0x84, 0x5e, 0x55, 0x1f, 0x81, 0xb3, 0x1c, 0x44, 0xe, 0x85, 0x53, 0x61, 0xb9, 0xd7, 0xa9, 0xaa, 0xea, 0x75, 0xe7, 0x4, 0xc6, 0x98, 0x1b, 0x11, 0xe9, 0x80, 0x31, 0xc6, 0xd8, 0xa7, 0xc2, 0x9a, 0xa6, 0x79, 0x9f, 0xe7, 0xf9, 0x16, 0x18, 0x81, 0x53, 0x55, 0xed, 0xb3, 0xa2, 0x7e, 0xf3, 0x95, 0xff, 0xbe, 0x3e, 0x0, 0xbd, 0x2c, 0x93, 0xec, 0xb, 0xe5, 0x4f, 0xb1, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; -static const unsigned char tab_disabled_png[] = { -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x12,0x0,0x0,0xb,0x12,0x1,0xd2,0xdd,0x7e,0xfc,0x0,0x0,0x0,0xd2,0x49,0x44,0x41,0x54,0x38,0xcb,0xd5,0x90,0x51,0xa,0xc2,0x30,0xc,0x86,0xd3,0x2e,0xdb,0x4,0x1f,0xb6,0x57,0x75,0x77,0xd9,0x1d,0x3c,0x8d,0x47,0xd8,0x69,0xbc,0x81,0xf,0xbb,0xcb,0xf0,0x6d,0xa8,0xa0,0xa0,0x6b,0xd7,0x9a,0x40,0x26,0xa,0xdb,0x98,0x22,0x88,0x81,0xf,0x92,0xf2,0xe7,0x4f,0x13,0x5,0x0,0x48,0x44,0x44,0x4c,0xcc,0x24,0xf,0x8,0xd,0xaf,0xe1,0x88,0x96,0x68,0x88,0x2b,0x71,0xe3,0xbc,0x6b,0x9e,0x13,0x29,0x91,0x48,0xce,0x66,0x4a,0xe0,0xf0,0x2,0x37,0x5d,0x88,0x13,0x71,0x4,0x99,0xce,0xe2,0x34,0xcf,0xf3,0x75,0xb6,0xcc,0xa,0xd3,0x1a,0x18,0x8b,0x30,0x8,0xa1,0xda,0x57,0x9b,0xb2,0x2c,0xb7,0x54,0x5a,0x94,0x6f,0x27,0xab,0xc5,0xaa,0xa8,0xf,0x35,0x58,0x6b,0xc1,0x7b,0xdf,0xdb,0xac,0x94,0x2,0x44,0x4,0xd6,0x52,0xb9,0x23,0xce,0x8f,0x15,0x1a,0xdb,0x80,0x31,0xe3,0xd3,0xd9,0x98,0x35,0xac,0x95,0x55,0x23,0x2d,0x7,0x8b,0x87,0xa6,0xe,0x19,0xc9,0xea,0x1,0xca,0xb5,0x15,0x3f,0x4e,0x35,0x11,0x1d,0x1f,0x58,0x63,0xb7,0xde,0x87,0x6,0x80,0xcf,0x8f,0x6f,0x1a,0xc0,0x77,0xd,0x9c,0x73,0x93,0xd,0x58,0xdb,0x85,0xee,0x73,0xfd,0xcd,0xa,0xff,0x6b,0x70,0x7,0xd6,0xd5,0x90,0x3b,0x10,0xe9,0x51,0x80,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char tab_container_bg_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x8a, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x3a, 0x44, 0x56, 0x53, 0x61, 0x56, 0x52, 0x60, 0x47, 0x44, 0x52, 0x33, 0x31, 0x39, 0x47, 0x44, 0x50, 0x47, 0x44, 0x51, 0x52, 0x50, 0x5d, 0x51, 0x4f, 0x5d, 0x46, 0x42, 0x4e, 0x42, 0x3e, 0x4a, 0x41, 0x3e, 0x49, 0x51, 0x4e, 0x5b, 0x40, 0x3e, 0x48, 0x4f, 0x4c, 0x59, 0x3f, 0x3d, 0x47, 0x4e, 0x4a, 0x58, 0x3e, 0x3b, 0x46, 0x4b, 0x49, 0x55, 0x3c, 0x3a, 0x44, 0x4a, 0x47, 0x54, 0x3b, 0x39, 0x43, 0x49, 0x46, 0x53, 0x3a, 0x38, 0x42, 0x47, 0x45, 0x50, 0x39, 0x37, 0x40, 0x47, 0x43, 0x50, 0x38, 0x35, 0x3f, 0x36, 0x34, 0x3e, 0x44, 0x42, 0x4d, 0x44, 0x41, 0x4c, 0xff, 0xff, 0xff, 0xe5, 0x37, 0x10, 0x78, 0x0, 0x0, 0x0, 0x15, 0x74, 0x52, 0x4e, 0x53, 0x4, 0xa, 0x11, 0x19, 0x1f, 0x22, 0x24, 0x15, 0x25, 0x34, 0x3f, 0x46, 0x47, 0x48, 0x77, 0xef, 0xef, 0xef, 0x77, 0xef, 0xed, 0xe8, 0xff, 0x76, 0xed, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x2d, 0xcd, 0xda, 0x41, 0x3d, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x93, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x65, 0xcf, 0x47, 0x12, 0x82, 0x40, 0x10, 0x5, 0xd0, 0x9e, 0xc8, 0x44, 0x92, 0x22, 0x41, 0x54, 0x44, 0x40, 0x14, 0xef, 0x7f, 0x3e, 0x7, 0x8a, 0xea, 0x85, 0xbe, 0xe5, 0xaf, 0xea, 0xf0, 0x1, 0x8, 0x65, 0x5c, 0xc8, 0x40, 0x70, 0x46, 0x9, 0x0, 0x89, 0x94, 0x36, 0xd6, 0x79, 0xef, 0xac, 0xd1, 0x2a, 0x22, 0x40, 0x55, 0x9c, 0x14, 0xa7, 0x4d, 0x91, 0xc4, 0x8a, 0x2, 0xd3, 0x69, 0x59, 0xd5, 0x9b, 0xaa, 0x4c, 0x35, 0x3, 0x6e, 0x9a, 0xfa, 0xbc, 0xab, 0x1b, 0xc3, 0x41, 0xd8, 0xf6, 0x82, 0x5a, 0x2b, 0x40, 0xba, 0xeb, 0xd, 0x5d, 0x9d, 0x4, 0xe9, 0xbb, 0x3b, 0xea, 0xfc, 0x1a, 0xf4, 0xf, 0xd4, 0xaf, 0x81, 0x1b, 0x46, 0x34, 0x84, 0x11, 0x61, 0xa7, 0x27, 0x9a, 0xc2, 0x52, 0x6e, 0xe6, 0x17, 0x9a, 0xc3, 0x59, 0xa6, 0xb3, 0xf1, 0xbd, 0x1b, 0xb3, 0xf0, 0x18, 0x55, 0xf9, 0x61, 0xf9, 0x6c, 0x96, 0x63, 0x1e, 0x5e, 0xff, 0x2b, 0xf7, 0x5b, 0xff, 0xb, 0x69, 0x5a, 0x14, 0xfa, 0x84, 0xf6, 0xc2, 0x8, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char tab_menu_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x6f,0x49,0x44,0x41,0x54,0x38,0x8d,0x63,0x60,0x18,0x5,0xa3,0x80,0x81,0x81,0x11,0x5d,0xe0,0xc1,0x83,0x7,0xff,0xf1,0x69,0x50,0x50,0x50,0x40,0xd1,0xc3,0x44,0xa9,0xb,0xa8,0x6f,0x0,0x23,0x23,0x63,0x3c,0x3,0x3,0xc3,0x57,0x2c,0x6a,0xbf,0x33,0x32,0x32,0xa6,0x63,0xa8,0xc7,0x66,0xea,0xfd,0xfb,0xf7,0x35,0x18,0x18,0x18,0x56,0x31,0x32,0x32,0xea,0x42,0x85,0x6e,0x30,0x33,0x33,0x87,0xc9,0xca,0xca,0x5e,0x26,0xca,0x0,0x6,0x6,0x6,0x86,0x17,0x2f,0x5e,0x70,0xff,0xfc,0xf9,0x73,0xa,0x3,0x3,0x3,0x3,0x3b,0x3b,0x7b,0x8e,0x84,0x84,0x4,0x36,0x57,0xd,0x2,0x0,0x0,0x67,0xf2,0x14,0xc2,0xc2,0xbe,0xf5,0xb5,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char tab_current_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x9c, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x3d, 0x48, 0x5b, 0x58, 0x66, 0x5b, 0x57, 0x65, 0x57, 0x54, 0x62, 0x55, 0x53, 0x62, 0x4a, 0x46, 0x52, 0x46, 0x41, 0x4e, 0x45, 0x41, 0x4d, 0x55, 0x52, 0x60, 0x44, 0x41, 0x4c, 0x53, 0x50, 0x5e, 0x43, 0x40, 0x4b, 0x52, 0x4e, 0x5d, 0x41, 0x3e, 0x4a, 0x4f, 0x4d, 0x5a, 0x3f, 0x3d, 0x48, 0x4e, 0x4b, 0x59, 0x3e, 0x3c, 0x47, 0x4d, 0x4a, 0x58, 0x3d, 0x3b, 0x46, 0x4b, 0x49, 0x54, 0x3c, 0x3a, 0x44, 0x4b, 0x47, 0x54, 0x3b, 0x39, 0x43, 0x3b, 0x39, 0x42, 0x3b, 0x38, 0x43, 0x3b, 0x38, 0x42, 0x3a, 0x37, 0x41, 0x39, 0x37, 0x41, 0x3a, 0x38, 0x41, 0x39, 0x36, 0x3f, 0x38, 0x36, 0x3f, 0x39, 0x36, 0x40, 0x38, 0x36, 0x40, 0x37, 0x35, 0x3e, 0x37, 0x34, 0x3e, 0x36, 0x35, 0x3d, 0x35, 0x32, 0x3b, 0x59, 0xdd, 0xd3, 0xff, 0x0, 0x0, 0x0, 0x11, 0x74, 0x52, 0x4e, 0x53, 0x4, 0xa, 0x11, 0x19, 0x1f, 0x22, 0x24, 0x15, 0x25, 0x34, 0x3f, 0x46, 0x47, 0x48, 0x77, 0xef, 0xef, 0xa3, 0x31, 0x6b, 0xc2, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x33, 0x37, 0xd5, 0x7c, 0x5e, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0xa2, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x45, 0xcd, 0xd9, 0x12, 0x82, 0x30, 0xc, 0x40, 0xd1, 0x0, 0x2d, 0x4b, 0x5b, 0x36, 0x59, 0x44, 0x44, 0x44, 0xa4, 0x68, 0x59, 0x54, 0xfc, 0xff, 0x8f, 0x33, 0x30, 0x4c, 0x3d, 0x93, 0xa7, 0x3b, 0x93, 0x4, 0xc0, 0x30, 0x2d, 0x42, 0x6d, 0x44, 0x89, 0x65, 0x1a, 0x0, 0x86, 0xe3, 0x7a, 0x8c, 0xb, 0xdf, 0x17, 0x9c, 0x79, 0xae, 0x63, 0x80, 0xe9, 0x6, 0x61, 0x7c, 0xd8, 0xc4, 0x61, 0xe0, 0x9a, 0x60, 0x79, 0x51, 0x92, 0x66, 0x9b, 0x34, 0x89, 0x3c, 0xb, 0x8, 0xcb, 0xb3, 0xe3, 0x2e, 0xcb, 0x19, 0x1, 0xca, 0x8b, 0x93, 0x56, 0x70, 0xa, 0xb6, 0x28, 0xcf, 0x5a, 0x29, 0x6c, 0xb0, 0xfd, 0xea, 0xa2, 0x55, 0xfe, 0x1a, 0xea, 0xab, 0x56, 0xaf, 0x41, 0x34, 0x37, 0xad, 0xc1, 0x15, 0xca, 0xdb, 0xbb, 0xd6, 0xe2, 0x51, 0xc2, 0xba, 0x7f, 0xe8, 0xf0, 0x2d, 0x6, 0x29, 0xfb, 0x5e, 0xca, 0xc7, 0x53, 0xca, 0x3d, 0xa8, 0x61, 0x50, 0xc3, 0xa8, 0xc6, 0x41, 0xed, 0x61, 0x9a, 0xa6, 0x19, 0xbd, 0xe6, 0xf7, 0x1e, 0x3e, 0xcb, 0x82, 0x83, 0xbe, 0x18, 0x7e, 0xa1, 0xe5, 0x17, 0x1f, 0xcf, 0x5d, 0x82, 0x6b, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char tab_menu_hl_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x6f,0x49,0x44,0x41,0x54,0x38,0x8d,0x63,0x60,0x18,0x5,0xa3,0x80,0x81,0x81,0x11,0x5d,0xe0,0xc1,0x83,0x7,0xff,0xf1,0x69,0x50,0x50,0x50,0x40,0xd1,0xc3,0x44,0xa9,0xb,0xa8,0x6f,0x0,0x23,0x23,0x63,0x3c,0x3,0x3,0xc3,0x57,0x2c,0x6a,0xbf,0x33,0x32,0x32,0xa6,0x63,0xa8,0xc7,0x66,0xea,0xfd,0xfb,0xf7,0x35,0x18,0x18,0x18,0x56,0x31,0x32,0x32,0xea,0x42,0x85,0x6e,0x30,0x33,0x33,0x87,0xc9,0xca,0xca,0x5e,0x26,0xca,0x0,0x6,0x6,0x6,0x86,0x17,0x2f,0x5e,0x70,0xff,0xfc,0xf9,0x73,0xa,0x3,0x3,0x3,0x3,0x3b,0x3b,0x7b,0x8e,0x84,0x84,0x4,0x36,0x57,0xd,0x2,0x0,0x0,0x67,0xf2,0x14,0xc2,0xc2,0xbe,0xf5,0xb5,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char tab_menu_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0x6f, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0x63, 0x60, 0x18, 0x5, 0xa3, 0x80, 0x81, 0x81, 0x11, 0x5d, 0xe0, 0xc1, 0x83, 0x7, 0xff, 0xf1, 0x69, 0x50, 0x50, 0x50, 0x40, 0xd1, 0xc3, 0x44, 0xa9, 0xb, 0xa8, 0x6f, 0x0, 0x23, 0x23, 0x63, 0x3c, 0x3, 0x3, 0xc3, 0x57, 0x2c, 0x6a, 0xbf, 0x33, 0x32, 0x32, 0xa6, 0x63, 0xa8, 0xc7, 0x66, 0xea, 0xfd, 0xfb, 0xf7, 0x35, 0x18, 0x18, 0x18, 0x56, 0x31, 0x32, 0x32, 0xea, 0x42, 0x85, 0x6e, 0x30, 0x33, 0x33, 0x87, 0xc9, 0xca, 0xca, 0x5e, 0x26, 0xca, 0x0, 0x6, 0x6, 0x6, 0x86, 0x17, 0x2f, 0x5e, 0x70, 0xff, 0xfc, 0xf9, 0x73, 0xa, 0x3, 0x3, 0x3, 0x3, 0x3b, 0x3b, 0x7b, 0x8e, 0x84, 0x84, 0x4, 0x36, 0x57, 0xd, 0x2, 0x0, 0x0, 0x67, 0xf2, 0x14, 0xc2, 0xc2, 0xbe, 0xf5, 0xb5, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char toggle_off_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x40,0x0,0x0,0x0,0x20,0x8,0x3,0x0,0x0,0x0,0x95,0x43,0x8e,0xb6,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x1,0x7a,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x14,0x14,0x17,0x20,0x20,0x25,0x24,0x24,0x28,0x24,0x24,0x29,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10,0x10,0x13,0x22,0x22,0x27,0x0,0x0,0x0,0x0,0x0,0x0,0x19,0x19,0x1c,0x1a,0x1a,0x1d,0x0,0x0,0x0,0x0,0x0,0x0,0x11,0x11,0x14,0x12,0x12,0x14,0x23,0x23,0x27,0x0,0x0,0x0,0x0,0x0,0x0,0x15,0x15,0x18,0x20,0x20,0x25,0x20,0x20,0x24,0x0,0x0,0x0,0x0,0x0,0x0,0x24,0x24,0x28,0x0,0x0,0x0,0x24,0x24,0x28,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x24,0x24,0x27,0x15,0x15,0x18,0x23,0x23,0x28,0x12,0x12,0x14,0x0,0x0,0x0,0x1a,0x1a,0x1e,0x0,0x0,0x0,0x11,0x11,0x13,0x22,0x22,0x26,0x0,0x0,0x0,0x0,0x0,0x0,0x24,0x24,0x29,0x25,0x25,0x2a,0x24,0x24,0x28,0x25,0x25,0x28,0x25,0x25,0x29,0x25,0x25,0x27,0x2d,0x26,0x2c,0x4d,0x2b,0x37,0x63,0x2f,0x3f,0x6e,0x31,0x43,0x71,0x32,0x44,0x6c,0x31,0x42,0x51,0x2c,0x39,0x47,0x2a,0x35,0x66,0x30,0x40,0x4d,0x2b,0x38,0x32,0x26,0x2e,0x26,0x25,0x2a,0x2e,0x25,0x2c,0x3c,0x28,0x31,0x52,0x2c,0x39,0x68,0x30,0x40,0x27,0x25,0x2a,0x50,0x2c,0x38,0x5f,0x2e,0x3d,0x35,0x27,0x2f,0x38,0x27,0x30,0x5e,0x2e,0x3d,0x43,0x2a,0x34,0x5f,0x2f,0x3e,0x2f,0x25,0x2c,0x44,0x2a,0x34,0x2b,0x26,0x2c,0x64,0x2f,0x3f,0x36,0x27,0x30,0x37,0x27,0x30,0x66,0x2f,0x40,0x2c,0x26,0x2c,0x46,0x2a,0x35,0x53,0x2c,0x39,0x40,0x40,0x44,0xad,0xad,0xaf,0xff,0xff,0xff,0xf2,0xf2,0xf2,0x77,0x77,0x7a,0x5b,0x5b,0x5f,0x32,0x32,0x37,0x5d,0x2e,0x3d,0x3e,0x29,0x32,0xc9,0xc9,0xca,0xbb,0xbb,0xbd,0x69,0x69,0x6c,0x69,0x30,0x41,0x2f,0x26,0x2d,0x84,0x84,0x87,0xd6,0xd6,0xd7,0x92,0x92,0x94,0xa0,0xa0,0xa2,0x4e,0x4e,0x52,0x48,0x2b,0x36,0x2c,0x26,0x2b,0x97,0xb0,0x86,0xb4,0x0,0x0,0x0,0x41,0x74,0x52,0x4e,0x53,0x0,0x1,0x2,0x3,0x4,0x9,0xe,0x13,0x16,0x18,0x19,0xa,0x26,0x36,0x44,0x4d,0x52,0x54,0x55,0x6,0x12,0x27,0x43,0x98,0xe5,0xfa,0xfe,0x8,0x17,0x35,0x86,0xf3,0x7,0x3a,0xb4,0xb9,0xb,0x28,0x8a,0x8b,0xf6,0x45,0x5,0x9b,0xe6,0xe6,0x37,0xf,0xfb,0x4c,0xfe,0x4e,0x4f,0x50,0xfb,0x9c,0xf6,0x8c,0x3b,0xbb,0x3c,0x87,0xf3,0x53,0x14,0xe5,0x7c,0xf3,0x66,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x6b,0x52,0x65,0xa5,0x98,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x2,0x47,0x49,0x44,0x41,0x54,0x48,0xc7,0xd5,0x55,0xfb,0x5b,0x93,0x50,0x18,0x96,0x3,0xc,0x48,0x60,0xde,0x70,0x9b,0x43,0x37,0x75,0xa6,0x9b,0xb5,0xad,0x56,0x59,0x99,0xe9,0xc6,0x39,0xb3,0x56,0x59,0xcd,0x4c,0xbb,0xd9,0x3d,0xdb,0xd,0x74,0xa6,0xa3,0xdb,0xff,0x1e,0x70,0x68,0x6e,0xc0,0xe0,0xe9,0xe9,0x97,0x7a,0x79,0x9e,0x3,0xf,0x7c,0xdf,0xcb,0x7b,0xbe,0xf3,0x5d,0x86,0x86,0xfe,0x21,0x10,0x80,0x24,0xa9,0x40,0x90,0x24,0x20,0x3c,0xdd,0x1,0x45,0x87,0x18,0x96,0x3b,0x17,0x0,0x8e,0x65,0x42,0x34,0x5,0xdc,0x7f,0xa7,0x86,0x59,0x5e,0x10,0xc3,0x23,0xa3,0x63,0xbe,0x18,0x1d,0x9,0x8b,0x2,0xcf,0xe,0x53,0xe,0x15,0x60,0x7c,0x42,0x9a,0x8c,0x44,0x63,0x53,0xc5,0x52,0x0,0x8a,0x53,0xb1,0x68,0x64,0x52,0x9a,0x18,0xef,0x13,0x1,0xe2,0xf2,0xf4,0x4c,0x42,0x81,0x10,0x21,0x84,0xed,0x90,0x9,0x88,0xca,0xc8,0x93,0x24,0x31,0x33,0x2d,0xc7,0x7b,0x18,0x88,0x24,0x37,0x3b,0xa7,0xc0,0xcd,0x3b,0x77,0x2b,0xf7,0x30,0xee,0x3f,0xd8,0xb4,0x58,0xca,0x70,0x80,0x8e,0xb9,0x59,0x2e,0x49,0x9c,0xed,0x9f,0x11,0xe6,0x15,0xb4,0xf5,0xf0,0xd1,0xe3,0xaa,0xf5,0xb9,0xba,0xfd,0x64,0xe7,0xe9,0xd6,0xae,0xa5,0x64,0xd0,0x4e,0xe6,0x5,0xa6,0x1b,0x7,0x90,0x5a,0x38,0xaf,0xa0,0xbd,0x67,0xcf,0x7b,0x2d,0x5e,0xbc,0xdc,0xdb,0xf5,0x8d,0xc5,0xe2,0x42,0xea,0xf7,0x26,0x28,0x59,0x5c,0x82,0xaf,0xf6,0xb7,0xfb,0x2d,0x5e,0xef,0xbf,0xa9,0xfa,0x31,0x2c,0xa5,0xe5,0xc,0x96,0x40,0xd0,0xfc,0x32,0x7c,0xfb,0xee,0xbd,0xd3,0xe2,0xc3,0xc7,0x4f,0xbe,0xe7,0xb1,0xcc,0xd3,0x98,0x0,0x84,0x84,0xb,0xf0,0x60,0xc7,0x6d,0xf1,0xf9,0xc0,0x7e,0xa8,0xd5,0x1b,0xcd,0x56,0x49,0x6d,0x18,0xb0,0x16,0xcd,0x7a,0x7b,0x31,0x9b,0xc3,0x7b,0x20,0x19,0x31,0x86,0xe,0x8f,0xdc,0x4,0x47,0x87,0xf6,0x43,0xfb,0xb8,0xf6,0xa5,0x51,0x53,0x4d,0x47,0xd5,0xf6,0x36,0x90,0x4f,0x33,0x24,0x26,0x60,0x2f,0x5d,0x46,0x27,0xa7,0x6e,0x82,0xd3,0x13,0x5b,0x80,0xe9,0x74,0xdc,0x51,0x75,0x93,0x40,0xef,0x12,0x14,0xb,0x2c,0x85,0x9,0xe4,0x2b,0xa,0xaa,0x78,0x4,0xac,0x5a,0xc1,0x77,0x55,0x37,0x96,0xaf,0x75,0xb5,0xdd,0x6e,0x6b,0xd6,0x62,0x7f,0xbf,0x2a,0xdb,0x4,0x6c,0x58,0xf1,0x55,0xa0,0x99,0xa,0xea,0xdf,0x54,0xd3,0x53,0x6d,0x7b,0x28,0x60,0xc4,0x6b,0xd0,0x37,0x6,0x7a,0xa7,0xa4,0x35,0x5b,0x4e,0x82,0x6e,0xc,0x40,0x28,0x1b,0x70,0xa,0x6a,0x53,0x6f,0xd6,0x4b,0x4e,0x82,0xee,0x29,0x18,0x79,0xb0,0x12,0x90,0x7,0x5a,0xe7,0xbb,0x11,0xcb,0x96,0x66,0x2f,0x18,0x2b,0x92,0x9d,0x7,0x66,0x26,0x5e,0x47,0x7f,0x91,0x89,0x66,0x2d,0x2c,0xfe,0x79,0x2d,0xdc,0x38,0xab,0x5,0xef,0x6a,0xfc,0xe1,0xef,0xdf,0x5b,0x8d,0x66,0x3f,0xb8,0xb9,0xaa,0xc0,0x9f,0xce,0x7e,0xe0,0xe3,0xbf,0x7a,0xab,0xa7,0x1f,0x98,0x1d,0x89,0x13,0xd6,0x6e,0xc3,0x32,0xc4,0xd,0x9,0xd9,0x80,0xc6,0xe5,0xe9,0x9f,0x58,0x13,0xb8,0x78,0x7f,0x4f,0x4b,0x32,0x92,0x18,0x89,0xe6,0x3,0x5b,0xa2,0xf1,0xf3,0x7c,0x34,0x22,0x4a,0x4c,0xd2,0xd1,0x98,0x9,0x2a,0xc5,0xf2,0xd9,0x74,0x61,0x7d,0x2c,0x0,0xeb,0x85,0x74,0x96,0x67,0x53,0x94,0x6b,0x36,0x10,0x20,0x43,0xe7,0x36,0xe4,0xe0,0xb9,0x20,0x6f,0xe4,0xe8,0x8c,0xf7,0x6c,0x31,0x26,0x53,0xf0,0x60,0x32,0x46,0xd3,0x80,0xc9,0xf4,0xff,0xe2,0x17,0x82,0xde,0x40,0xde,0x2d,0xc3,0x2a,0xca,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char tab_menu_hl_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0x6f, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0x63, 0x60, 0x18, 0x5, 0xa3, 0x80, 0x81, 0x81, 0x11, 0x5d, 0xe0, 0xc1, 0x83, 0x7, 0xff, 0xf1, 0x69, 0x50, 0x50, 0x50, 0x40, 0xd1, 0xc3, 0x44, 0xa9, 0xb, 0xa8, 0x6f, 0x0, 0x23, 0x23, 0x63, 0x3c, 0x3, 0x3, 0xc3, 0x57, 0x2c, 0x6a, 0xbf, 0x33, 0x32, 0x32, 0xa6, 0x63, 0xa8, 0xc7, 0x66, 0xea, 0xfd, 0xfb, 0xf7, 0x35, 0x18, 0x18, 0x18, 0x56, 0x31, 0x32, 0x32, 0xea, 0x42, 0x85, 0x6e, 0x30, 0x33, 0x33, 0x87, 0xc9, 0xca, 0xca, 0x5e, 0x26, 0xca, 0x0, 0x6, 0x6, 0x6, 0x86, 0x17, 0x2f, 0x5e, 0x70, 0xff, 0xfc, 0xf9, 0x73, 0xa, 0x3, 0x3, 0x3, 0x3, 0x3b, 0x3b, 0x7b, 0x8e, 0x84, 0x84, 0x4, 0x36, 0x57, 0xd, 0x2, 0x0, 0x0, 0x67, 0xf2, 0x14, 0xc2, 0xc2, 0xbe, 0xf5, 0xb5, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char toggle_on_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x40,0x0,0x0,0x0,0x20,0x8,0x3,0x0,0x0,0x0,0x95,0x43,0x8e,0xb6,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x1,0x74,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xd,0xd,0xf,0x1a,0x1a,0x1e,0x20,0x20,0x24,0x22,0x22,0x27,0x24,0x24,0x29,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xa,0xa,0xc,0x1d,0x1d,0x21,0x0,0x0,0x0,0x0,0x0,0x0,0x11,0x11,0x14,0x23,0x23,0x28,0x12,0x12,0x15,0x0,0x0,0x0,0x0,0x0,0x0,0xb,0xb,0xd,0x23,0x23,0x28,0xb,0xb,0xd,0x1e,0x1e,0x22,0x0,0x0,0x0,0x0,0x0,0x0,0xe,0xe,0x10,0x1a,0x1a,0x1e,0x1a,0x1a,0x1d,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x20,0x24,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xe,0xe,0x10,0xb,0xb,0xd,0x0,0x0,0x0,0x13,0x13,0x15,0x0,0x0,0x0,0xb,0xb,0xc,0x1d,0x1d,0x21,0x0,0x0,0x0,0x0,0x0,0x0,0x25,0x25,0x2a,0x24,0x24,0x29,0x25,0x2c,0x36,0x27,0x49,0x65,0x29,0x5d,0x85,0x2a,0x66,0x95,0x2a,0x68,0x99,0x29,0x64,0x92,0x28,0x4c,0x6b,0x25,0x27,0x2d,0x27,0x43,0x5c,0x29,0x5f,0x89,0x27,0x49,0x66,0x25,0x30,0x3e,0x25,0x26,0x2d,0x25,0x25,0x2b,0x25,0x26,0x2c,0x25,0x2d,0x38,0x25,0x3a,0x4c,0x27,0x4d,0x6b,0x29,0x60,0x8c,0x27,0x44,0x5c,0x27,0x4b,0x69,0x28,0x59,0x7f,0x25,0x34,0x43,0x25,0x35,0x45,0x28,0x58,0x7f,0x25,0x26,0x2b,0x27,0x40,0x57,0x27,0x41,0x57,0x25,0x2a,0x33,0x29,0x5d,0x87,0x25,0x34,0x44,0x25,0x2b,0x34,0x40,0x40,0x44,0xad,0xad,0xaf,0xff,0xff,0xff,0xf2,0xf2,0xf2,0x77,0x77,0x7a,0x5b,0x5b,0x5f,0x4e,0x4e,0x52,0xc9,0xc9,0xca,0x27,0x43,0x5b,0x27,0x4d,0x6c,0x27,0x4e,0x6d,0xbb,0xbb,0xbd,0x69,0x69,0x6c,0x28,0x56,0x7b,0x26,0x3b,0x4e,0x26,0x3a,0x4e,0x32,0x32,0x37,0x84,0x84,0x87,0xd6,0xd6,0xd7,0x29,0x61,0x8d,0x25,0x2e,0x39,0x92,0x92,0x94,0xa0,0xa0,0xa2,0xe4,0xe4,0xe5,0x27,0x44,0x5d,0xdd,0xc9,0xf2,0x7e,0x0,0x0,0x0,0x41,0x74,0x52,0x4e,0x53,0x0,0x1,0x2,0x3,0x4,0x9,0xe,0x13,0x16,0x18,0x19,0xa,0x26,0x36,0x44,0x4d,0x52,0x54,0x55,0x6,0x12,0x27,0x43,0x80,0xc5,0xe7,0xf5,0xfe,0x8,0x17,0x35,0x73,0xd9,0x7,0x3a,0x96,0xf9,0x9a,0xb,0x28,0x76,0xfb,0x77,0xde,0x45,0x5,0x82,0xc6,0xc6,0x37,0xf,0xe9,0x4c,0x4e,0x4f,0x50,0x83,0x78,0x3b,0x9c,0x3c,0x74,0xda,0x53,0x14,0x37,0x21,0x5a,0x6c,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x65,0xb5,0xdd,0x88,0x9f,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x4,0x4e,0x1d,0x2,0xaf,0x0,0x0,0x2,0x28,0x49,0x44,0x41,0x54,0x48,0xc7,0xd5,0x55,0x69,0x57,0xd3,0x40,0x14,0x25,0x93,0xa4,0x49,0x24,0x49,0xd9,0x42,0xd7,0x0,0x85,0x50,0x2c,0xb4,0x68,0x5b,0xab,0x28,0xb2,0xc,0x4b,0x95,0x82,0x56,0xab,0x42,0x45,0x5c,0x9b,0xad,0x45,0x11,0x6d,0x3,0xa8,0x7f,0xde,0xc4,0x94,0x26,0x69,0x30,0x89,0xc7,0x2f,0x7a,0x3f,0xe4,0x9c,0xcc,0x3b,0xef,0xce,0x7d,0x6f,0xde,0x32,0x30,0xf0,0xf,0x1,0x1,0x28,0x8a,0xf9,0x2,0x45,0x1,0x72,0xa5,0x3b,0xc0,0xf0,0x10,0x41,0x52,0xd7,0x7c,0x40,0x91,0x44,0x8,0xc7,0x80,0xfb,0x76,0x6c,0x90,0xa4,0x19,0x36,0x3c,0x34,0x3c,0xe2,0x89,0xe1,0xa1,0x30,0xcb,0xd0,0xe4,0x20,0xd6,0xa7,0x2,0x8c,0x8e,0x71,0xe3,0x91,0x68,0x2c,0x9e,0x80,0x3e,0x48,0xc4,0x63,0xd1,0xc8,0x38,0x37,0x36,0xea,0x10,0x1,0x92,0xfc,0xc4,0xe4,0xd4,0x86,0x9f,0xf3,0x25,0x36,0xa6,0x26,0x27,0xf8,0xa4,0x8d,0x1,0x49,0x51,0xd3,0x33,0x82,0xa7,0xcf,0xe6,0xd6,0x76,0xf9,0x81,0x89,0x87,0x3b,0x9b,0x50,0x98,0x99,0xa6,0x52,0x88,0x15,0x3f,0xc1,0xcc,0x7a,0x6a,0xaf,0xec,0xee,0x3d,0x7a,0x5c,0x7d,0x62,0xe0,0x69,0xed,0xd9,0xf3,0x17,0xfb,0x95,0xc4,0x2c,0x43,0xf4,0xf2,0x0,0xd2,0x73,0xd7,0x33,0x9e,0xfe,0x7,0xf5,0x97,0xf6,0xff,0xc3,0x57,0x7,0x95,0xcc,0xfc,0x5c,0xfa,0x32,0x8,0x8c,0x67,0x17,0xbc,0xfc,0x8f,0x5e,0xd7,0x6b,0xce,0x93,0x5a,0xfd,0xcd,0xd1,0x42,0x96,0xcf,0x99,0x12,0x10,0x9c,0x5e,0xf4,0x8c,0xff,0xed,0xbb,0xf7,0xfd,0x47,0x87,0x7b,0x1f,0xe0,0x22,0x8d,0x9b,0x4,0x20,0xc4,0xdc,0xb0,0x4c,0xd,0x51,0x92,0x15,0xa8,0x4a,0x4d,0xa8,0xb6,0xba,0x47,0xc7,0x1f,0xdd,0xa4,0x9f,0x8e,0xe1,0xcd,0x7c,0xc1,0x8c,0x1,0x25,0xd8,0x98,0x65,0x69,0x9d,0x34,0x3e,0x4b,0xd,0x55,0x6a,0x59,0x4,0xa7,0x5f,0xdc,0x4,0x5f,0x4f,0x61,0x31,0x4b,0xa0,0x26,0x1,0x79,0x2b,0x6e,0x9,0x90,0xda,0x10,0x9e,0x74,0x54,0x4d,0x56,0x7b,0x4,0x67,0xe7,0x6e,0x82,0xf3,0x33,0x28,0x94,0x48,0xcc,0x24,0xe0,0x6f,0x5b,0x6f,0xa8,0x6a,0xfa,0xe7,0x42,0x54,0x5b,0x17,0x5a,0x8f,0xa0,0x5c,0x75,0x13,0x54,0xcb,0x10,0xde,0xe1,0xbb,0x4,0x64,0xd8,0x2a,0xa2,0xb6,0xa1,0x40,0xfc,0xa6,0x3b,0x7f,0x17,0x3,0x2b,0x20,0xd8,0xa2,0x65,0xd1,0x3a,0xb0,0x2d,0x2b,0x3a,0x81,0x22,0x5,0xcd,0x1,0x8,0xe5,0x6d,0xaf,0xa0,0xca,0x9a,0x2c,0xfe,0x4a,0xa0,0x16,0xf4,0x15,0xf4,0x3a,0x58,0xb2,0x99,0xda,0x9d,0xa6,0x9e,0x4b,0x5,0xc2,0xa6,0xe2,0x5d,0x7,0x4b,0x5c,0xb7,0xe,0xfe,0xba,0x12,0x8d,0x5e,0x98,0xff,0xf3,0x5e,0xb8,0x6b,0xf5,0x42,0x80,0x6e,0xdc,0x77,0x76,0xe3,0xf,0x67,0x37,0x1a,0xf3,0xe0,0xde,0xb2,0xa7,0x86,0xfe,0x79,0x90,0x59,0xbe,0x6f,0x9b,0x7,0xc6,0x44,0xa2,0x98,0x95,0x55,0x18,0x18,0xab,0x2b,0xc,0x95,0x74,0xce,0xb4,0x14,0xc1,0xb1,0x91,0x68,0x51,0xf0,0x77,0x16,0x8a,0xd1,0x8,0xcb,0x11,0xa9,0xbe,0xc1,0x8c,0x60,0x69,0x92,0xce,0x67,0x4b,0x6b,0x23,0x3e,0x58,0x2b,0x65,0xf3,0x34,0x99,0xc6,0x5c,0xbb,0x1,0x1,0x39,0xbc,0xb0,0xce,0xfb,0xef,0x5,0x7e,0xbd,0x80,0xe7,0xae,0xde,0x2d,0xfa,0x66,0xf2,0x5f,0x4c,0xfa,0x6a,0xfa,0xcd,0x66,0xfa,0x7f,0xf1,0x13,0xb7,0x71,0x36,0xc6,0x87,0x41,0xd4,0x5,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char toggle_off_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x20, 0x8, 0x3, 0x0, 0x0, 0x0, 0x95, 0x43, 0x8e, 0xb6, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x1, 0x7a, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x14, 0x17, 0x20, 0x20, 0x25, 0x24, 0x24, 0x28, 0x24, 0x24, 0x29, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x10, 0x13, 0x22, 0x22, 0x27, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x19, 0x19, 0x1c, 0x1a, 0x1a, 0x1d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x11, 0x11, 0x14, 0x12, 0x12, 0x14, 0x23, 0x23, 0x27, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x15, 0x15, 0x18, 0x20, 0x20, 0x25, 0x20, 0x20, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x24, 0x28, 0x0, 0x0, 0x0, 0x24, 0x24, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x24, 0x27, 0x15, 0x15, 0x18, 0x23, 0x23, 0x28, 0x12, 0x12, 0x14, 0x0, 0x0, 0x0, 0x1a, 0x1a, 0x1e, 0x0, 0x0, 0x0, 0x11, 0x11, 0x13, 0x22, 0x22, 0x26, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x24, 0x29, 0x25, 0x25, 0x2a, 0x24, 0x24, 0x28, 0x25, 0x25, 0x28, 0x25, 0x25, 0x29, 0x25, 0x25, 0x27, 0x2d, 0x26, 0x2c, 0x4d, 0x2b, 0x37, 0x63, 0x2f, 0x3f, 0x6e, 0x31, 0x43, 0x71, 0x32, 0x44, 0x6c, 0x31, 0x42, 0x51, 0x2c, 0x39, 0x47, 0x2a, 0x35, 0x66, 0x30, 0x40, 0x4d, 0x2b, 0x38, 0x32, 0x26, 0x2e, 0x26, 0x25, 0x2a, 0x2e, 0x25, 0x2c, 0x3c, 0x28, 0x31, 0x52, 0x2c, 0x39, 0x68, 0x30, 0x40, 0x27, 0x25, 0x2a, 0x50, 0x2c, 0x38, 0x5f, 0x2e, 0x3d, 0x35, 0x27, 0x2f, 0x38, 0x27, 0x30, 0x5e, 0x2e, 0x3d, 0x43, 0x2a, 0x34, 0x5f, 0x2f, 0x3e, 0x2f, 0x25, 0x2c, 0x44, 0x2a, 0x34, 0x2b, 0x26, 0x2c, 0x64, 0x2f, 0x3f, 0x36, 0x27, 0x30, 0x37, 0x27, 0x30, 0x66, 0x2f, 0x40, 0x2c, 0x26, 0x2c, 0x46, 0x2a, 0x35, 0x53, 0x2c, 0x39, 0x40, 0x40, 0x44, 0xad, 0xad, 0xaf, 0xff, 0xff, 0xff, 0xf2, 0xf2, 0xf2, 0x77, 0x77, 0x7a, 0x5b, 0x5b, 0x5f, 0x32, 0x32, 0x37, 0x5d, 0x2e, 0x3d, 0x3e, 0x29, 0x32, 0xc9, 0xc9, 0xca, 0xbb, 0xbb, 0xbd, 0x69, 0x69, 0x6c, 0x69, 0x30, 0x41, 0x2f, 0x26, 0x2d, 0x84, 0x84, 0x87, 0xd6, 0xd6, 0xd7, 0x92, 0x92, 0x94, 0xa0, 0xa0, 0xa2, 0x4e, 0x4e, 0x52, 0x48, 0x2b, 0x36, 0x2c, 0x26, 0x2b, 0x97, 0xb0, 0x86, 0xb4, 0x0, 0x0, 0x0, 0x41, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x1, 0x2, 0x3, 0x4, 0x9, 0xe, 0x13, 0x16, 0x18, 0x19, 0xa, 0x26, 0x36, 0x44, 0x4d, 0x52, 0x54, 0x55, 0x6, 0x12, 0x27, 0x43, 0x98, 0xe5, 0xfa, 0xfe, 0x8, 0x17, 0x35, 0x86, 0xf3, 0x7, 0x3a, 0xb4, 0xb9, 0xb, 0x28, 0x8a, 0x8b, 0xf6, 0x45, 0x5, 0x9b, 0xe6, 0xe6, 0x37, 0xf, 0xfb, 0x4c, 0xfe, 0x4e, 0x4f, 0x50, 0xfb, 0x9c, 0xf6, 0x8c, 0x3b, 0xbb, 0x3c, 0x87, 0xf3, 0x53, 0x14, 0xe5, 0x7c, 0xf3, 0x66, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x6b, 0x52, 0x65, 0xa5, 0x98, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x2, 0x47, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xd5, 0x55, 0xfb, 0x5b, 0x93, 0x50, 0x18, 0x96, 0x3, 0xc, 0x48, 0x60, 0xde, 0x70, 0x9b, 0x43, 0x37, 0x75, 0xa6, 0x9b, 0xb5, 0xad, 0x56, 0x59, 0x99, 0xe9, 0xc6, 0x39, 0xb3, 0x56, 0x59, 0xcd, 0x4c, 0xbb, 0xd9, 0x3d, 0xdb, 0xd, 0x74, 0xa6, 0xa3, 0xdb, 0xff, 0x1e, 0x70, 0x68, 0x6e, 0xc0, 0xe0, 0xe9, 0xe9, 0x97, 0x7a, 0x79, 0x9e, 0x3, 0xf, 0x7c, 0xdf, 0xcb, 0x7b, 0xbe, 0xf3, 0x5d, 0x86, 0x86, 0xfe, 0x21, 0x10, 0x80, 0x24, 0xa9, 0x40, 0x90, 0x24, 0x20, 0x3c, 0xdd, 0x1, 0x45, 0x87, 0x18, 0x96, 0x3b, 0x17, 0x0, 0x8e, 0x65, 0x42, 0x34, 0x5, 0xdc, 0x7f, 0xa7, 0x86, 0x59, 0x5e, 0x10, 0xc3, 0x23, 0xa3, 0x63, 0xbe, 0x18, 0x1d, 0x9, 0x8b, 0x2, 0xcf, 0xe, 0x53, 0xe, 0x15, 0x60, 0x7c, 0x42, 0x9a, 0x8c, 0x44, 0x63, 0x53, 0xc5, 0x52, 0x0, 0x8a, 0x53, 0xb1, 0x68, 0x64, 0x52, 0x9a, 0x18, 0xef, 0x13, 0x1, 0xe2, 0xf2, 0xf4, 0x4c, 0x42, 0x81, 0x10, 0x21, 0x84, 0xed, 0x90, 0x9, 0x88, 0xca, 0xc8, 0x93, 0x24, 0x31, 0x33, 0x2d, 0xc7, 0x7b, 0x18, 0x88, 0x24, 0x37, 0x3b, 0xa7, 0xc0, 0xcd, 0x3b, 0x77, 0x2b, 0xf7, 0x30, 0xee, 0x3f, 0xd8, 0xb4, 0x58, 0xca, 0x70, 0x80, 0x8e, 0xb9, 0x59, 0x2e, 0x49, 0x9c, 0xed, 0x9f, 0x11, 0xe6, 0x15, 0xb4, 0xf5, 0xf0, 0xd1, 0xe3, 0xaa, 0xf5, 0xb9, 0xba, 0xfd, 0x64, 0xe7, 0xe9, 0xd6, 0xae, 0xa5, 0x64, 0xd0, 0x4e, 0xe6, 0x5, 0xa6, 0x1b, 0x7, 0x90, 0x5a, 0x38, 0xaf, 0xa0, 0xbd, 0x67, 0xcf, 0x7b, 0x2d, 0x5e, 0xbc, 0xdc, 0xdb, 0xf5, 0x8d, 0xc5, 0xe2, 0x42, 0xea, 0xf7, 0x26, 0x28, 0x59, 0x5c, 0x82, 0xaf, 0xf6, 0xb7, 0xfb, 0x2d, 0x5e, 0xef, 0xbf, 0xa9, 0xfa, 0x31, 0x2c, 0xa5, 0xe5, 0xc, 0x96, 0x40, 0xd0, 0xfc, 0x32, 0x7c, 0xfb, 0xee, 0xbd, 0xd3, 0xe2, 0xc3, 0xc7, 0x4f, 0xbe, 0xe7, 0xb1, 0xcc, 0xd3, 0x98, 0x0, 0x84, 0x84, 0xb, 0xf0, 0x60, 0xc7, 0x6d, 0xf1, 0xf9, 0xc0, 0x7e, 0xa8, 0xd5, 0x1b, 0xcd, 0x56, 0x49, 0x6d, 0x18, 0xb0, 0x16, 0xcd, 0x7a, 0x7b, 0x31, 0x9b, 0xc3, 0x7b, 0x20, 0x19, 0x31, 0x86, 0xe, 0x8f, 0xdc, 0x4, 0x47, 0x87, 0xf6, 0x43, 0xfb, 0xb8, 0xf6, 0xa5, 0x51, 0x53, 0x4d, 0x47, 0xd5, 0xf6, 0x36, 0x90, 0x4f, 0x33, 0x24, 0x26, 0x60, 0x2f, 0x5d, 0x46, 0x27, 0xa7, 0x6e, 0x82, 0xd3, 0x13, 0x5b, 0x80, 0xe9, 0x74, 0xdc, 0x51, 0x75, 0x93, 0x40, 0xef, 0x12, 0x14, 0xb, 0x2c, 0x85, 0x9, 0xe4, 0x2b, 0xa, 0xaa, 0x78, 0x4, 0xac, 0x5a, 0xc1, 0x77, 0x55, 0x37, 0x96, 0xaf, 0x75, 0xb5, 0xdd, 0x6e, 0x6b, 0xd6, 0x62, 0x7f, 0xbf, 0x2a, 0xdb, 0x4, 0x6c, 0x58, 0xf1, 0x55, 0xa0, 0x99, 0xa, 0xea, 0xdf, 0x54, 0xd3, 0x53, 0x6d, 0x7b, 0x28, 0x60, 0xc4, 0x6b, 0xd0, 0x37, 0x6, 0x7a, 0xa7, 0xa4, 0x35, 0x5b, 0x4e, 0x82, 0x6e, 0xc, 0x40, 0x28, 0x1b, 0x70, 0xa, 0x6a, 0x53, 0x6f, 0xd6, 0x4b, 0x4e, 0x82, 0xee, 0x29, 0x18, 0x79, 0xb0, 0x12, 0x90, 0x7, 0x5a, 0xe7, 0xbb, 0x11, 0xcb, 0x96, 0x66, 0x2f, 0x18, 0x2b, 0x92, 0x9d, 0x7, 0x66, 0x26, 0x5e, 0x47, 0x7f, 0x91, 0x89, 0x66, 0x2d, 0x2c, 0xfe, 0x79, 0x2d, 0xdc, 0x38, 0xab, 0x5, 0xef, 0x6a, 0xfc, 0xe1, 0xef, 0xdf, 0x5b, 0x8d, 0x66, 0x3f, 0xb8, 0xb9, 0xaa, 0xc0, 0x9f, 0xce, 0x7e, 0xe0, 0xe3, 0xbf, 0x7a, 0xab, 0xa7, 0x1f, 0x98, 0x1d, 0x89, 0x13, 0xd6, 0x6e, 0xc3, 0x32, 0xc4, 0xd, 0x9, 0xd9, 0x80, 0xc6, 0xe5, 0xe9, 0x9f, 0x58, 0x13, 0xb8, 0x78, 0x7f, 0x4f, 0x4b, 0x32, 0x92, 0x18, 0x89, 0xe6, 0x3, 0x5b, 0xa2, 0xf1, 0xf3, 0x7c, 0x34, 0x22, 0x4a, 0x4c, 0xd2, 0xd1, 0x98, 0x9, 0x2a, 0xc5, 0xf2, 0xd9, 0x74, 0x61, 0x7d, 0x2c, 0x0, 0xeb, 0x85, 0x74, 0x96, 0x67, 0x53, 0x94, 0x6b, 0x36, 0x10, 0x20, 0x43, 0xe7, 0x36, 0xe4, 0xe0, 0xb9, 0x20, 0x6f, 0xe4, 0xe8, 0x8c, 0xf7, 0x6c, 0x31, 0x26, 0x53, 0xf0, 0x60, 0x32, 0x46, 0xd3, 0x80, 0xc9, 0xf4, 0xff, 0xe2, 0x17, 0x82, 0xde, 0x40, 0xde, 0x2d, 0xc3, 0x2a, 0xca, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char tool_button_pressed_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x2,0x1,0x50,0x4c,0x54,0x45,0x29,0x3a,0x40,0x2d,0x3e,0x44,0x26,0x34,0x3b,0x24,0x34,0x39,0x23,0x31,0x38,0x22,0x31,0x37,0x22,0x31,0x37,0x22,0x30,0x36,0x22,0x31,0x36,0x26,0x34,0x3c,0x32,0x44,0x4c,0x26,0x34,0x39,0x23,0x31,0x36,0x21,0x2e,0x34,0x1f,0x2c,0x30,0x1f,0x2b,0x2f,0x1f,0x2a,0x2e,0x1e,0x2b,0x2f,0x1f,0x2b,0x2e,0x36,0x4b,0x52,0x25,0x33,0x38,0x20,0x2f,0x32,0x1c,0x29,0x2e,0x1b,0x26,0x2a,0x1a,0x23,0x26,0x18,0x22,0x26,0x19,0x22,0x26,0x19,0x23,0x26,0x19,0x26,0x29,0x20,0x2d,0x32,0x25,0x31,0x38,0x3c,0x51,0x59,0x23,0x31,0x37,0x1f,0x2b,0x31,0x1a,0x25,0x2b,0x17,0x20,0x24,0x15,0x1c,0x21,0x14,0x1b,0x21,0x14,0x1c,0x21,0x13,0x1b,0x21,0x15,0x1d,0x21,0x1a,0x25,0x2a,0x40,0x57,0x60,0x23,0x31,0x36,0x1f,0x2b,0x31,0x1b,0x25,0x29,0x16,0x1e,0x23,0x14,0x1b,0x1d,0x12,0x19,0x1d,0x12,0x1b,0x1d,0x14,0x1a,0x1d,0x45,0x5e,0x67,0x22,0x32,0x37,0x20,0x2d,0x31,0x1a,0x26,0x2a,0x15,0x1f,0x25,0x14,0x1c,0x1f,0x12,0x1b,0x1f,0x12,0x1b,0x20,0x14,0x1b,0x1f,0x15,0x1e,0x24,0x1a,0x25,0x29,0x4b,0x64,0x6d,0x23,0x32,0x38,0x20,0x2e,0x32,0x1b,0x27,0x2b,0x17,0x22,0x27,0x16,0x1e,0x23,0x14,0x1e,0x23,0x16,0x20,0x24,0x14,0x1e,0x22,0x15,0x1e,0x22,0x17,0x21,0x27,0x1c,0x27,0x2c,0x4f,0x6a,0x75,0x21,0x2f,0x33,0x1d,0x29,0x2d,0x19,0x23,0x2a,0x18,0x22,0x27,0x16,0x21,0x27,0x18,0x23,0x29,0x17,0x21,0x26,0x19,0x23,0x29,0x1c,0x28,0x2d,0x21,0x2e,0x33,0x54,0x70,0x7c,0x23,0x33,0x38,0x22,0x30,0x34,0x1e,0x2a,0x2f,0x1a,0x26,0x2d,0x1a,0x25,0x2b,0x19,0x25,0x2b,0x1a,0x26,0x2d,0x1a,0x26,0x2c,0x18,0x25,0x2a,0x1a,0x24,0x2a,0x1a,0x25,0x2c,0x1d,0x2a,0x2f,0x22,0x2f,0x34,0x59,0x77,0x82,0x23,0x33,0x39,0x22,0x30,0x35,0x1f,0x2c,0x31,0x1c,0x28,0x30,0x1c,0x28,0x2e,0x1b,0x29,0x2f,0x1c,0x2a,0x31,0x1b,0x28,0x2f,0x1c,0x28,0x2d,0x1b,0x27,0x2f,0x1f,0x2b,0x31,0x5e,0x7d,0x8a,0x24,0x34,0x39,0x21,0x2f,0x37,0x20,0x2d,0x34,0x1d,0x2b,0x33,0x1d,0x2b,0x32,0x1d,0x2d,0x35,0x1e,0x2e,0x36,0x1f,0x2e,0x36,0x1d,0x2b,0x34,0x1d,0x2b,0x31,0x1d,0x2b,0x32,0x20,0x2d,0x32,0x21,0x2f,0x36,0x63,0x83,0x90,0x25,0x34,0x39,0x21,0x31,0x36,0x1f,0x2e,0x34,0x1f,0x2e,0x34,0x1f,0x2e,0x36,0x20,0x31,0x39,0x21,0x33,0x3b,0x21,0x32,0x3b,0x1f,0x30,0x37,0x1f,0x2e,0x35,0x1e,0x2d,0x33,0x1f,0x2d,0x33,0x21,0x30,0x36,0x67,0x8a,0x97,0x24,0x33,0x39,0x20,0x30,0x36,0x1f,0x2f,0x35,0x21,0x30,0x37,0x22,0x32,0x39,0x21,0x35,0x3e,0x24,0x37,0x41,0x24,0x36,0x41,0x21,0x33,0x3c,0x21,0x31,0x38,0x1e,0x2f,0x35,0x1e,0x2e,0x35,0x20,0x2e,0x35,0x24,0x31,0x39,0x6c,0x90,0x9e,0x22,0x30,0x36,0x1f,0x2e,0x36,0x20,0x30,0x36,0x20,0x31,0x39,0x23,0x34,0x3d,0x23,0x37,0x41,0x26,0x3c,0x47,0x26,0x3b,0x46,0x22,0x35,0x3f,0x22,0x32,0x3b,0x1f,0x30,0x37,0x1f,0x2e,0x35,0x1f,0x2d,0x35,0x21,0x30,0x36,0x72,0x96,0xa5,0x72,0x96,0xa5,0xe8,0x14,0xaa,0x3f,0x0,0x0,0x0,0xaa,0x74,0x52,0x4e,0x53,0xc3,0xc3,0xe6,0xd7,0xcb,0xc3,0xbf,0xbe,0xbd,0xe5,0xc3,0xd7,0xc0,0xac,0xa0,0x9a,0x98,0x98,0x98,0xc3,0xcb,0xac,0x92,0x82,0x7b,0x78,0x78,0x7b,0x82,0xac,0xcb,0xc3,0xc3,0xa0,0x82,0x6f,0x67,0x64,0x63,0x64,0x67,0x82,0xc3,0xbf,0x9a,0x7a,0x67,0x5e,0x5b,0x5a,0x5e,0xc3,0xbd,0x98,0x78,0x64,0x5b,0x57,0x57,0x5b,0x64,0x78,0xc3,0xbd,0x98,0x78,0x63,0x5a,0x57,0x56,0x57,0x5a,0x63,0x77,0xc3,0x98,0x78,0x63,0x5a,0x57,0x56,0x5a,0x63,0x77,0x98,0xc3,0xbd,0x98,0x78,0x63,0x5a,0x57,0x56,0x56,0x57,0x5a,0x63,0x77,0x98,0xc3,0xbd,0x98,0x77,0x63,0x5a,0x57,0x56,0x57,0x5a,0x63,0x77,0xc3,0xbb,0x96,0x76,0x63,0x5a,0x57,0x56,0x56,0x57,0x5a,0x63,0x76,0x96,0xc3,0xb5,0x92,0x75,0x62,0x5a,0x57,0x56,0x56,0x57,0x59,0x62,0x74,0x92,0xc3,0xa9,0x8b,0x71,0x61,0x59,0x57,0x56,0x56,0x57,0x59,0x61,0x71,0x8b,0xa9,0xc3,0x95,0x7e,0x6b,0x5e,0x59,0x57,0x56,0x56,0x57,0x59,0x5e,0x6b,0x7e,0x95,0xc3,0x4f,0x78,0x99,0x30,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0xa9,0x27,0xf,0x6,0x4,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0xff,0x49,0x44,0x41,0x54,0x18,0xd3,0x63,0x60,0x40,0x7,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec,0x1c,0x1c,0x1c,0x6c,0xac,0x2c,0xcc,0x9c,0x8c,0xc,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc,0x2,0x82,0x82,0x42,0xfc,0x7c,0xbc,0x3c,0xdc,0x5c,0xc,0xc2,0x22,0xa2,0x62,0xe2,0x12,0x92,0x52,0x52,0x92,0xd2,0x32,0x62,0xb2,0x72,0xc2,0xc,0xf2,0xa,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0x6a,0xea,0x1a,0xca,0x9a,0x8a,0xa,0xf2,0xc,0x5a,0xda,0x3a,0xba,0x7a,0xfa,0x6,0x86,0x86,0x6,0x46,0x7a,0xba,0x3a,0xda,0x5a,0xc,0xc6,0x26,0xa6,0x66,0xe6,0x16,0x96,0x56,0x56,0x96,0xd6,0x36,0xb6,0xa6,0x26,0xc6,0xc,0x76,0xf6,0xe,0x8e,0x4e,0xce,0x2e,0xae,0xae,0x6e,0xee,0x1e,0x9e,0xe,0x26,0x76,0xc,0x5e,0xf6,0xde,0x3e,0xbe,0x7e,0xfe,0x1,0x1,0xfe,0x81,0x41,0xc1,0x21,0xf6,0x5e,0xc,0xa1,0x61,0xe1,0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1,0x9,0x89,0x49,0x61,0xa1,0xc,0xc9,0x29,0xa9,0x69,0xe9,0x19,0x99,0x59,0x59,0xd9,0x39,0xb9,0x79,0xa9,0x29,0xc9,0xc,0xf9,0x5,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5,0x15,0x95,0x55,0xd5,0x35,0x5,0xf9,0xc,0xb5,0x75,0xf5,0xd,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed,0x1d,0x9d,0x5d,0x75,0xb5,0xc,0xdd,0x3d,0xbd,0x7d,0xfd,0x13,0x26,0x4e,0x9a,0x3c,0x65,0xea,0xb4,0xe9,0x33,0x66,0x76,0x33,0xcc,0x9a,0x3d,0x67,0xee,0xbc,0xf9,0xb,0x16,0x2e,0x5a,0xbc,0x64,0xe9,0xb2,0xe5,0x2b,0x66,0x31,0xac,0x44,0x3,0x0,0xa4,0xd7,0x4d,0x73,0x12,0x21,0x19,0xde,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char toggle_on_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x20, 0x8, 0x3, 0x0, 0x0, 0x0, 0x95, 0x43, 0x8e, 0xb6, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x1, 0x74, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0xd, 0xf, 0x1a, 0x1a, 0x1e, 0x20, 0x20, 0x24, 0x22, 0x22, 0x27, 0x24, 0x24, 0x29, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0xa, 0xc, 0x1d, 0x1d, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x11, 0x11, 0x14, 0x23, 0x23, 0x28, 0x12, 0x12, 0x15, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xb, 0xd, 0x23, 0x23, 0x28, 0xb, 0xb, 0xd, 0x1e, 0x1e, 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, 0xe, 0x10, 0x1a, 0x1a, 0x1e, 0x1a, 0x1a, 0x1d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x20, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, 0xe, 0x10, 0xb, 0xb, 0xd, 0x0, 0x0, 0x0, 0x13, 0x13, 0x15, 0x0, 0x0, 0x0, 0xb, 0xb, 0xc, 0x1d, 0x1d, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x25, 0x25, 0x2a, 0x24, 0x24, 0x29, 0x25, 0x2c, 0x36, 0x27, 0x49, 0x65, 0x29, 0x5d, 0x85, 0x2a, 0x66, 0x95, 0x2a, 0x68, 0x99, 0x29, 0x64, 0x92, 0x28, 0x4c, 0x6b, 0x25, 0x27, 0x2d, 0x27, 0x43, 0x5c, 0x29, 0x5f, 0x89, 0x27, 0x49, 0x66, 0x25, 0x30, 0x3e, 0x25, 0x26, 0x2d, 0x25, 0x25, 0x2b, 0x25, 0x26, 0x2c, 0x25, 0x2d, 0x38, 0x25, 0x3a, 0x4c, 0x27, 0x4d, 0x6b, 0x29, 0x60, 0x8c, 0x27, 0x44, 0x5c, 0x27, 0x4b, 0x69, 0x28, 0x59, 0x7f, 0x25, 0x34, 0x43, 0x25, 0x35, 0x45, 0x28, 0x58, 0x7f, 0x25, 0x26, 0x2b, 0x27, 0x40, 0x57, 0x27, 0x41, 0x57, 0x25, 0x2a, 0x33, 0x29, 0x5d, 0x87, 0x25, 0x34, 0x44, 0x25, 0x2b, 0x34, 0x40, 0x40, 0x44, 0xad, 0xad, 0xaf, 0xff, 0xff, 0xff, 0xf2, 0xf2, 0xf2, 0x77, 0x77, 0x7a, 0x5b, 0x5b, 0x5f, 0x4e, 0x4e, 0x52, 0xc9, 0xc9, 0xca, 0x27, 0x43, 0x5b, 0x27, 0x4d, 0x6c, 0x27, 0x4e, 0x6d, 0xbb, 0xbb, 0xbd, 0x69, 0x69, 0x6c, 0x28, 0x56, 0x7b, 0x26, 0x3b, 0x4e, 0x26, 0x3a, 0x4e, 0x32, 0x32, 0x37, 0x84, 0x84, 0x87, 0xd6, 0xd6, 0xd7, 0x29, 0x61, 0x8d, 0x25, 0x2e, 0x39, 0x92, 0x92, 0x94, 0xa0, 0xa0, 0xa2, 0xe4, 0xe4, 0xe5, 0x27, 0x44, 0x5d, 0xdd, 0xc9, 0xf2, 0x7e, 0x0, 0x0, 0x0, 0x41, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x1, 0x2, 0x3, 0x4, 0x9, 0xe, 0x13, 0x16, 0x18, 0x19, 0xa, 0x26, 0x36, 0x44, 0x4d, 0x52, 0x54, 0x55, 0x6, 0x12, 0x27, 0x43, 0x80, 0xc5, 0xe7, 0xf5, 0xfe, 0x8, 0x17, 0x35, 0x73, 0xd9, 0x7, 0x3a, 0x96, 0xf9, 0x9a, 0xb, 0x28, 0x76, 0xfb, 0x77, 0xde, 0x45, 0x5, 0x82, 0xc6, 0xc6, 0x37, 0xf, 0xe9, 0x4c, 0x4e, 0x4f, 0x50, 0x83, 0x78, 0x3b, 0x9c, 0x3c, 0x74, 0xda, 0x53, 0x14, 0x37, 0x21, 0x5a, 0x6c, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x65, 0xb5, 0xdd, 0x88, 0x9f, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x4, 0x4e, 0x1d, 0x2, 0xaf, 0x0, 0x0, 0x2, 0x28, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xd5, 0x55, 0x69, 0x57, 0xd3, 0x40, 0x14, 0x25, 0x93, 0xa4, 0x49, 0x24, 0x49, 0xd9, 0x42, 0xd7, 0x0, 0x85, 0x50, 0x2c, 0xb4, 0x68, 0x5b, 0xab, 0x28, 0xb2, 0xc, 0x4b, 0x95, 0x82, 0x56, 0xab, 0x42, 0x45, 0x5c, 0x9b, 0xad, 0x45, 0x11, 0x6d, 0x3, 0xa8, 0x7f, 0xde, 0xc4, 0x94, 0x26, 0x69, 0x30, 0x89, 0xc7, 0x2f, 0x7a, 0x3f, 0xe4, 0x9c, 0xcc, 0x3b, 0xef, 0xce, 0x7d, 0x6f, 0xde, 0x32, 0x30, 0xf0, 0xf, 0x1, 0x1, 0x28, 0x8a, 0xf9, 0x2, 0x45, 0x1, 0x72, 0xa5, 0x3b, 0xc0, 0xf0, 0x10, 0x41, 0x52, 0xd7, 0x7c, 0x40, 0x91, 0x44, 0x8, 0xc7, 0x80, 0xfb, 0x76, 0x6c, 0x90, 0xa4, 0x19, 0x36, 0x3c, 0x34, 0x3c, 0xe2, 0x89, 0xe1, 0xa1, 0x30, 0xcb, 0xd0, 0xe4, 0x20, 0xd6, 0xa7, 0x2, 0x8c, 0x8e, 0x71, 0xe3, 0x91, 0x68, 0x2c, 0x9e, 0x80, 0x3e, 0x48, 0xc4, 0x63, 0xd1, 0xc8, 0x38, 0x37, 0x36, 0xea, 0x10, 0x1, 0x92, 0xfc, 0xc4, 0xe4, 0xd4, 0x86, 0x9f, 0xf3, 0x25, 0x36, 0xa6, 0x26, 0x27, 0xf8, 0xa4, 0x8d, 0x1, 0x49, 0x51, 0xd3, 0x33, 0x82, 0xa7, 0xcf, 0xe6, 0xd6, 0x76, 0xf9, 0x81, 0x89, 0x87, 0x3b, 0x9b, 0x50, 0x98, 0x99, 0xa6, 0x52, 0x88, 0x15, 0x3f, 0xc1, 0xcc, 0x7a, 0x6a, 0xaf, 0xec, 0xee, 0x3d, 0x7a, 0x5c, 0x7d, 0x62, 0xe0, 0x69, 0xed, 0xd9, 0xf3, 0x17, 0xfb, 0x95, 0xc4, 0x2c, 0x43, 0xf4, 0xf2, 0x0, 0xd2, 0x73, 0xd7, 0x33, 0x9e, 0xfe, 0x7, 0xf5, 0x97, 0xf6, 0xff, 0xc3, 0x57, 0x7, 0x95, 0xcc, 0xfc, 0x5c, 0xfa, 0x32, 0x8, 0x8c, 0x67, 0x17, 0xbc, 0xfc, 0x8f, 0x5e, 0xd7, 0x6b, 0xce, 0x93, 0x5a, 0xfd, 0xcd, 0xd1, 0x42, 0x96, 0xcf, 0x99, 0x12, 0x10, 0x9c, 0x5e, 0xf4, 0x8c, 0xff, 0xed, 0xbb, 0xf7, 0xfd, 0x47, 0x87, 0x7b, 0x1f, 0xe0, 0x22, 0x8d, 0x9b, 0x4, 0x20, 0xc4, 0xdc, 0xb0, 0x4c, 0xd, 0x51, 0x92, 0x15, 0xa8, 0x4a, 0x4d, 0xa8, 0xb6, 0xba, 0x47, 0xc7, 0x1f, 0xdd, 0xa4, 0x9f, 0x8e, 0xe1, 0xcd, 0x7c, 0xc1, 0x8c, 0x1, 0x25, 0xd8, 0x98, 0x65, 0x69, 0x9d, 0x34, 0x3e, 0x4b, 0xd, 0x55, 0x6a, 0x59, 0x4, 0xa7, 0x5f, 0xdc, 0x4, 0x5f, 0x4f, 0x61, 0x31, 0x4b, 0xa0, 0x26, 0x1, 0x79, 0x2b, 0x6e, 0x9, 0x90, 0xda, 0x10, 0x9e, 0x74, 0x54, 0x4d, 0x56, 0x7b, 0x4, 0x67, 0xe7, 0x6e, 0x82, 0xf3, 0x33, 0x28, 0x94, 0x48, 0xcc, 0x24, 0xe0, 0x6f, 0x5b, 0x6f, 0xa8, 0x6a, 0xfa, 0xe7, 0x42, 0x54, 0x5b, 0x17, 0x5a, 0x8f, 0xa0, 0x5c, 0x75, 0x13, 0x54, 0xcb, 0x10, 0xde, 0xe1, 0xbb, 0x4, 0x64, 0xd8, 0x2a, 0xa2, 0xb6, 0xa1, 0x40, 0xfc, 0xa6, 0x3b, 0x7f, 0x17, 0x3, 0x2b, 0x20, 0xd8, 0xa2, 0x65, 0xd1, 0x3a, 0xb0, 0x2d, 0x2b, 0x3a, 0x81, 0x22, 0x5, 0xcd, 0x1, 0x8, 0xe5, 0x6d, 0xaf, 0xa0, 0xca, 0x9a, 0x2c, 0xfe, 0x4a, 0xa0, 0x16, 0xf4, 0x15, 0xf4, 0x3a, 0x58, 0xb2, 0x99, 0xda, 0x9d, 0xa6, 0x9e, 0x4b, 0x5, 0xc2, 0xa6, 0xe2, 0x5d, 0x7, 0x4b, 0x5c, 0xb7, 0xe, 0xfe, 0xba, 0x12, 0x8d, 0x5e, 0x98, 0xff, 0xf3, 0x5e, 0xb8, 0x6b, 0xf5, 0x42, 0x80, 0x6e, 0xdc, 0x77, 0x76, 0xe3, 0xf, 0x67, 0x37, 0x1a, 0xf3, 0xe0, 0xde, 0xb2, 0xa7, 0x86, 0xfe, 0x79, 0x90, 0x59, 0xbe, 0x6f, 0x9b, 0x7, 0xc6, 0x44, 0xa2, 0x98, 0x95, 0x55, 0x18, 0x18, 0xab, 0x2b, 0xc, 0x95, 0x74, 0xce, 0xb4, 0x14, 0xc1, 0xb1, 0x91, 0x68, 0x51, 0xf0, 0x77, 0x16, 0x8a, 0xd1, 0x8, 0xcb, 0x11, 0xa9, 0xbe, 0xc1, 0x8c, 0x60, 0x69, 0x92, 0xce, 0x67, 0x4b, 0x6b, 0x23, 0x3e, 0x58, 0x2b, 0x65, 0xf3, 0x34, 0x99, 0xc6, 0x5c, 0xbb, 0x1, 0x1, 0x39, 0xbc, 0xb0, 0xce, 0xfb, 0xef, 0x5, 0x7e, 0xbd, 0x80, 0xe7, 0xae, 0xde, 0x2d, 0xfa, 0x66, 0xf2, 0x5f, 0x4c, 0xfa, 0x6a, 0xfa, 0xcd, 0x66, 0xfa, 0x7f, 0xf1, 0x13, 0xb7, 0x71, 0x36, 0xc6, 0x87, 0x41, 0xd4, 0x5, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char tooltip_bg_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x33,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2d,0x2c,0x2f,0x48,0x46,0x4a,0xdd,0xdd,0xdd,0x4c,0x4a,0x4e,0x48,0x46,0x4a,0x40,0x3e,0x42,0xdd,0xdd,0xdd,0xfe,0x3f,0x83,0xa9,0x0,0x0,0x0,0xd,0x74,0x52,0x4e,0x53,0xa,0x1a,0x26,0x29,0x2a,0x48,0x65,0x6d,0x6e,0x66,0xf5,0xfe,0xcc,0xff,0xb7,0x4a,0xbe,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0xc,0x81,0xb3,0x51,0x63,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x44,0x49,0x44,0x41,0x54,0x18,0xd3,0xc5,0xcf,0xbb,0x15,0x0,0x20,0x8,0x43,0xd1,0x80,0x28,0xf8,0x41,0xf7,0xdf,0xd6,0x86,0x63,0xa1,0x3,0x78,0xcb,0x54,0x79,0x0,0x71,0x92,0x90,0x98,0x0,0xca,0x45,0x2d,0x68,0xc9,0x4,0xae,0xad,0x7b,0xe8,0xad,0x32,0x44,0xe7,0x1a,0x61,0x4d,0x15,0x88,0xf9,0x38,0xdc,0xfe,0xd,0xf7,0xb1,0xe7,0xfa,0x13,0x77,0xe7,0x6f,0xdc,0x6c,0x9,0x25,0x82,0x67,0x68,0x78,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char tool_button_pressed_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x2, 0x1, 0x50, 0x4c, 0x54, 0x45, 0x29, 0x3a, 0x40, 0x2d, 0x3e, 0x44, 0x26, 0x34, 0x3b, 0x24, 0x34, 0x39, 0x23, 0x31, 0x38, 0x22, 0x31, 0x37, 0x22, 0x31, 0x37, 0x22, 0x30, 0x36, 0x22, 0x31, 0x36, 0x26, 0x34, 0x3c, 0x32, 0x44, 0x4c, 0x26, 0x34, 0x39, 0x23, 0x31, 0x36, 0x21, 0x2e, 0x34, 0x1f, 0x2c, 0x30, 0x1f, 0x2b, 0x2f, 0x1f, 0x2a, 0x2e, 0x1e, 0x2b, 0x2f, 0x1f, 0x2b, 0x2e, 0x36, 0x4b, 0x52, 0x25, 0x33, 0x38, 0x20, 0x2f, 0x32, 0x1c, 0x29, 0x2e, 0x1b, 0x26, 0x2a, 0x1a, 0x23, 0x26, 0x18, 0x22, 0x26, 0x19, 0x22, 0x26, 0x19, 0x23, 0x26, 0x19, 0x26, 0x29, 0x20, 0x2d, 0x32, 0x25, 0x31, 0x38, 0x3c, 0x51, 0x59, 0x23, 0x31, 0x37, 0x1f, 0x2b, 0x31, 0x1a, 0x25, 0x2b, 0x17, 0x20, 0x24, 0x15, 0x1c, 0x21, 0x14, 0x1b, 0x21, 0x14, 0x1c, 0x21, 0x13, 0x1b, 0x21, 0x15, 0x1d, 0x21, 0x1a, 0x25, 0x2a, 0x40, 0x57, 0x60, 0x23, 0x31, 0x36, 0x1f, 0x2b, 0x31, 0x1b, 0x25, 0x29, 0x16, 0x1e, 0x23, 0x14, 0x1b, 0x1d, 0x12, 0x19, 0x1d, 0x12, 0x1b, 0x1d, 0x14, 0x1a, 0x1d, 0x45, 0x5e, 0x67, 0x22, 0x32, 0x37, 0x20, 0x2d, 0x31, 0x1a, 0x26, 0x2a, 0x15, 0x1f, 0x25, 0x14, 0x1c, 0x1f, 0x12, 0x1b, 0x1f, 0x12, 0x1b, 0x20, 0x14, 0x1b, 0x1f, 0x15, 0x1e, 0x24, 0x1a, 0x25, 0x29, 0x4b, 0x64, 0x6d, 0x23, 0x32, 0x38, 0x20, 0x2e, 0x32, 0x1b, 0x27, 0x2b, 0x17, 0x22, 0x27, 0x16, 0x1e, 0x23, 0x14, 0x1e, 0x23, 0x16, 0x20, 0x24, 0x14, 0x1e, 0x22, 0x15, 0x1e, 0x22, 0x17, 0x21, 0x27, 0x1c, 0x27, 0x2c, 0x4f, 0x6a, 0x75, 0x21, 0x2f, 0x33, 0x1d, 0x29, 0x2d, 0x19, 0x23, 0x2a, 0x18, 0x22, 0x27, 0x16, 0x21, 0x27, 0x18, 0x23, 0x29, 0x17, 0x21, 0x26, 0x19, 0x23, 0x29, 0x1c, 0x28, 0x2d, 0x21, 0x2e, 0x33, 0x54, 0x70, 0x7c, 0x23, 0x33, 0x38, 0x22, 0x30, 0x34, 0x1e, 0x2a, 0x2f, 0x1a, 0x26, 0x2d, 0x1a, 0x25, 0x2b, 0x19, 0x25, 0x2b, 0x1a, 0x26, 0x2d, 0x1a, 0x26, 0x2c, 0x18, 0x25, 0x2a, 0x1a, 0x24, 0x2a, 0x1a, 0x25, 0x2c, 0x1d, 0x2a, 0x2f, 0x22, 0x2f, 0x34, 0x59, 0x77, 0x82, 0x23, 0x33, 0x39, 0x22, 0x30, 0x35, 0x1f, 0x2c, 0x31, 0x1c, 0x28, 0x30, 0x1c, 0x28, 0x2e, 0x1b, 0x29, 0x2f, 0x1c, 0x2a, 0x31, 0x1b, 0x28, 0x2f, 0x1c, 0x28, 0x2d, 0x1b, 0x27, 0x2f, 0x1f, 0x2b, 0x31, 0x5e, 0x7d, 0x8a, 0x24, 0x34, 0x39, 0x21, 0x2f, 0x37, 0x20, 0x2d, 0x34, 0x1d, 0x2b, 0x33, 0x1d, 0x2b, 0x32, 0x1d, 0x2d, 0x35, 0x1e, 0x2e, 0x36, 0x1f, 0x2e, 0x36, 0x1d, 0x2b, 0x34, 0x1d, 0x2b, 0x31, 0x1d, 0x2b, 0x32, 0x20, 0x2d, 0x32, 0x21, 0x2f, 0x36, 0x63, 0x83, 0x90, 0x25, 0x34, 0x39, 0x21, 0x31, 0x36, 0x1f, 0x2e, 0x34, 0x1f, 0x2e, 0x34, 0x1f, 0x2e, 0x36, 0x20, 0x31, 0x39, 0x21, 0x33, 0x3b, 0x21, 0x32, 0x3b, 0x1f, 0x30, 0x37, 0x1f, 0x2e, 0x35, 0x1e, 0x2d, 0x33, 0x1f, 0x2d, 0x33, 0x21, 0x30, 0x36, 0x67, 0x8a, 0x97, 0x24, 0x33, 0x39, 0x20, 0x30, 0x36, 0x1f, 0x2f, 0x35, 0x21, 0x30, 0x37, 0x22, 0x32, 0x39, 0x21, 0x35, 0x3e, 0x24, 0x37, 0x41, 0x24, 0x36, 0x41, 0x21, 0x33, 0x3c, 0x21, 0x31, 0x38, 0x1e, 0x2f, 0x35, 0x1e, 0x2e, 0x35, 0x20, 0x2e, 0x35, 0x24, 0x31, 0x39, 0x6c, 0x90, 0x9e, 0x22, 0x30, 0x36, 0x1f, 0x2e, 0x36, 0x20, 0x30, 0x36, 0x20, 0x31, 0x39, 0x23, 0x34, 0x3d, 0x23, 0x37, 0x41, 0x26, 0x3c, 0x47, 0x26, 0x3b, 0x46, 0x22, 0x35, 0x3f, 0x22, 0x32, 0x3b, 0x1f, 0x30, 0x37, 0x1f, 0x2e, 0x35, 0x1f, 0x2d, 0x35, 0x21, 0x30, 0x36, 0x72, 0x96, 0xa5, 0x72, 0x96, 0xa5, 0xe8, 0x14, 0xaa, 0x3f, 0x0, 0x0, 0x0, 0xaa, 0x74, 0x52, 0x4e, 0x53, 0xc3, 0xc3, 0xe6, 0xd7, 0xcb, 0xc3, 0xbf, 0xbe, 0xbd, 0xe5, 0xc3, 0xd7, 0xc0, 0xac, 0xa0, 0x9a, 0x98, 0x98, 0x98, 0xc3, 0xcb, 0xac, 0x92, 0x82, 0x7b, 0x78, 0x78, 0x7b, 0x82, 0xac, 0xcb, 0xc3, 0xc3, 0xa0, 0x82, 0x6f, 0x67, 0x64, 0x63, 0x64, 0x67, 0x82, 0xc3, 0xbf, 0x9a, 0x7a, 0x67, 0x5e, 0x5b, 0x5a, 0x5e, 0xc3, 0xbd, 0x98, 0x78, 0x64, 0x5b, 0x57, 0x57, 0x5b, 0x64, 0x78, 0xc3, 0xbd, 0x98, 0x78, 0x63, 0x5a, 0x57, 0x56, 0x57, 0x5a, 0x63, 0x77, 0xc3, 0x98, 0x78, 0x63, 0x5a, 0x57, 0x56, 0x5a, 0x63, 0x77, 0x98, 0xc3, 0xbd, 0x98, 0x78, 0x63, 0x5a, 0x57, 0x56, 0x56, 0x57, 0x5a, 0x63, 0x77, 0x98, 0xc3, 0xbd, 0x98, 0x77, 0x63, 0x5a, 0x57, 0x56, 0x57, 0x5a, 0x63, 0x77, 0xc3, 0xbb, 0x96, 0x76, 0x63, 0x5a, 0x57, 0x56, 0x56, 0x57, 0x5a, 0x63, 0x76, 0x96, 0xc3, 0xb5, 0x92, 0x75, 0x62, 0x5a, 0x57, 0x56, 0x56, 0x57, 0x59, 0x62, 0x74, 0x92, 0xc3, 0xa9, 0x8b, 0x71, 0x61, 0x59, 0x57, 0x56, 0x56, 0x57, 0x59, 0x61, 0x71, 0x8b, 0xa9, 0xc3, 0x95, 0x7e, 0x6b, 0x5e, 0x59, 0x57, 0x56, 0x56, 0x57, 0x59, 0x5e, 0x6b, 0x7e, 0x95, 0xc3, 0x4f, 0x78, 0x99, 0x30, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0xa9, 0x27, 0xf, 0x6, 0x4, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0xff, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x63, 0x60, 0x40, 0x7, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x1c, 0x1c, 0x6c, 0xac, 0x2c, 0xcc, 0x9c, 0x8c, 0xc, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x2, 0x82, 0x82, 0x42, 0xfc, 0x7c, 0xbc, 0x3c, 0xdc, 0x5c, 0xc, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0x52, 0x92, 0xd2, 0x32, 0x62, 0xb2, 0x72, 0xc2, 0xc, 0xf2, 0xa, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0x6a, 0xea, 0x1a, 0xca, 0x9a, 0x8a, 0xa, 0xf2, 0xc, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x6, 0x86, 0x86, 0x6, 0x46, 0x7a, 0xba, 0x3a, 0xda, 0x5a, 0xc, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0x56, 0x96, 0xd6, 0x36, 0xb6, 0xa6, 0x26, 0xc6, 0xc, 0x76, 0xf6, 0xe, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0xe, 0x26, 0x76, 0xc, 0x5e, 0xf6, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x1, 0x1, 0xfe, 0x81, 0x41, 0xc1, 0x21, 0xf6, 0x5e, 0xc, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 0x9, 0x89, 0x49, 0x61, 0xa1, 0xc, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xa9, 0x29, 0xc9, 0xc, 0xf9, 0x5, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0x5, 0xf9, 0xc, 0xb5, 0x75, 0xf5, 0xd, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0x75, 0xb5, 0xc, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x13, 0x26, 0x4e, 0x9a, 0x3c, 0x65, 0xea, 0xb4, 0xe9, 0x33, 0x66, 0x76, 0x33, 0xcc, 0x9a, 0x3d, 0x67, 0xee, 0xbc, 0xf9, 0xb, 0x16, 0x2e, 0x5a, 0xbc, 0x64, 0xe9, 0xb2, 0xe5, 0x2b, 0x66, 0x31, 0xac, 0x44, 0x3, 0x0, 0xa4, 0xd7, 0x4d, 0x73, 0x12, 0x21, 0x19, 0xde, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char tree_bg_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xa,0x0,0x0,0x0,0xa,0x4,0x3,0x0,0x0,0x0,0x7f,0x1c,0xd2,0x8e,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2a,0x50,0x4c,0x54,0x45,0x17,0x16,0x1a,0x1d,0x1c,0x21,0x20,0x1e,0x24,0x21,0x1f,0x25,0x1d,0x1c,0x21,0x20,0x1e,0x24,0x1d,0x1c,0x21,0x1d,0x1c,0x21,0x24,0x22,0x29,0x28,0x26,0x2d,0x28,0x26,0x2e,0x2b,0x2a,0x31,0x2c,0x2a,0x32,0xff,0xff,0xff,0xb9,0x11,0x56,0x3e,0x0,0x0,0x0,0x8,0x74,0x52,0x4e,0x53,0x6f,0xef,0xf7,0xf7,0xf0,0xf9,0xf1,0xee,0xcf,0x21,0xd2,0xdf,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0xd,0xf6,0xb4,0x61,0xf5,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x2d,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0x54,0x36,0x36,0x12,0x60,0xf0,0x98,0xb5,0x6a,0x65,0xb,0x43,0xe4,0x9e,0x33,0xa7,0xa7,0x32,0x58,0x9d,0x39,0x73,0x66,0x31,0x16,0x12,0x22,0xb,0x52,0xd9,0xc6,0xc0,0x2,0xd4,0x55,0x0,0x0,0xc,0x14,0x1a,0x90,0x55,0x1a,0xec,0xdb,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char tooltip_bg_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x33, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2d, 0x2c, 0x2f, 0x48, 0x46, 0x4a, 0xdd, 0xdd, 0xdd, 0x4c, 0x4a, 0x4e, 0x48, 0x46, 0x4a, 0x40, 0x3e, 0x42, 0xdd, 0xdd, 0xdd, 0xfe, 0x3f, 0x83, 0xa9, 0x0, 0x0, 0x0, 0xd, 0x74, 0x52, 0x4e, 0x53, 0xa, 0x1a, 0x26, 0x29, 0x2a, 0x48, 0x65, 0x6d, 0x6e, 0x66, 0xf5, 0xfe, 0xcc, 0xff, 0xb7, 0x4a, 0xbe, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0xc, 0x81, 0xb3, 0x51, 0x63, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x44, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0xc5, 0xcf, 0xbb, 0x15, 0x0, 0x20, 0x8, 0x43, 0xd1, 0x80, 0x28, 0xf8, 0x41, 0xf7, 0xdf, 0xd6, 0x86, 0x63, 0xa1, 0x3, 0x78, 0xcb, 0x54, 0x79, 0x0, 0x71, 0x92, 0x90, 0x98, 0x0, 0xca, 0x45, 0x2d, 0x68, 0xc9, 0x4, 0xae, 0xad, 0x7b, 0xe8, 0xad, 0x32, 0x44, 0xe7, 0x1a, 0x61, 0x4d, 0x15, 0x88, 0xf9, 0x38, 0xdc, 0xfe, 0xd, 0xf7, 0xb1, 0xe7, 0xfa, 0x13, 0x77, 0xe7, 0x6f, 0xdc, 0x6c, 0x9, 0x25, 0x82, 0x67, 0x68, 0x78, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char tree_bg_focus_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x20,0x8,0x6,0x0,0x0,0x0,0x73,0x7a,0x7a,0xf4,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdb,0xb,0x4,0x12,0x2d,0x3a,0xb5,0x1b,0x14,0x49,0x0,0x0,0x2,0xd9,0x49,0x44,0x41,0x54,0x58,0xc3,0xc5,0x57,0x31,0x8e,0x14,0x31,0x10,0xac,0xea,0x3d,0x11,0x91,0xdf,0x49,0xf7,0xf,0x78,0x1,0xf,0x40,0x84,0x44,0x10,0xf2,0x20,0x42,0x62,0x12,0xc4,0x3,0x78,0x1,0xff,0x21,0x42,0xb8,0x8a,0xc0,0x1e,0x4f,0xdb,0xe3,0xb9,0xbb,0x45,0x20,0x7c,0x1a,0xdd,0x8c,0xec,0xed,0xae,0xae,0xea,0xee,0xe9,0xe1,0xfd,0xed,0xdd,0xb,0x0,0xdf,0xf1,0x7f,0xd6,0x4b,0xde,0xdf,0xde,0xf9,0xcb,0xeb,0x9f,0xff,0xc5,0xfb,0x9b,0xaf,0xcf,0x70,0xb3,0x3d,0x3c,0xff,0xf0,0xd,0x24,0x11,0x71,0x1,0x49,0x90,0x4,0x0,0x4,0xd3,0x2f,0xb6,0x7b,0xf,0xff,0x86,0x2d,0x8c,0x47,0x60,0x1b,0x0,0x61,0x1b,0xb6,0x21,0x15,0xd8,0xc6,0x8f,0x8f,0xaf,0x0,0x60,0x7,0x0,0xa2,0x2,0x20,0x11,0x41,0x30,0xa2,0x2,0xc1,0xb5,0x0,0x8c,0x79,0xd9,0x80,0x24,0x48,0x0,0x48,0x28,0x9d,0xb9,0xd9,0xd,0xb0,0x31,0x40,0x5c,0x2e,0x1,0x46,0x0,0xd,0xd0,0xb6,0xef,0x35,0x8e,0x13,0x6,0xbc,0x33,0x60,0xa3,0x9a,0x11,0x6c,0x82,0xe6,0xa,0x0,0x86,0xe8,0x2f,0x71,0xa9,0xf7,0x9c,0x4d,0x1f,0x69,0x5e,0x1,0xd8,0xa3,0x37,0xa4,0xa,0x27,0x1a,0x13,0x79,0x25,0x9,0xaa,0xe3,0xd8,0x9c,0x5f,0xea,0x7d,0x67,0x80,0xd7,0x31,0x20,0xab,0x3,0x20,0x5,0x20,0x2a,0x13,0x41,0x40,0x2b,0x0,0x76,0x22,0xb9,0xb1,0xd1,0x92,0x91,0x5d,0x86,0xf3,0x35,0xef,0x5,0xa3,0x25,0x60,0xd,0x6e,0x66,0xe5,0x0,0xc0,0xa8,0x54,0x1,0x6,0xe9,0x16,0x9f,0x4f,0xdc,0x1c,0x13,0xed,0xb1,0x55,0x31,0x78,0x70,0x8e,0xca,0xcb,0x8e,0x6a,0xbe,0x56,0x88,0x67,0x38,0xdb,0x75,0x58,0x76,0xdf,0x1b,0x6c,0x7a,0xc,0x6c,0x90,0x0,0xfd,0xe0,0xe8,0x98,0xe4,0x4,0xe2,0x69,0xc,0xe4,0x40,0xaa,0xf9,0x63,0x70,0xbb,0x4,0x16,0x9c,0x12,0xa7,0x3e,0xe7,0x38,0xb3,0x4,0x2b,0x6f,0xc7,0x23,0xbb,0xc3,0x66,0xdb,0x38,0x7,0x0,0xcf,0x32,0x34,0xb6,0x52,0xb4,0x3c,0xf7,0x35,0x10,0xd9,0xf7,0x6,0x56,0x93,0x4,0x4b,0x0,0x43,0x28,0xf9,0x4a,0x3d,0x6e,0xb0,0x3e,0x9,0x31,0xa9,0x62,0xd6,0xc4,0x36,0x9c,0xf2,0xd9,0xbd,0x41,0x2d,0x24,0x68,0xc7,0x1f,0x62,0x60,0x6a,0xc1,0x7f,0x95,0x81,0xaa,0x13,0x61,0x9,0xa6,0xf6,0x1c,0x30,0x17,0x11,0x6f,0x48,0x12,0x3b,0xf3,0x7b,0xc2,0xeb,0xca,0x92,0xb7,0x72,0x5f,0x31,0x90,0x11,0x4e,0x48,0xb3,0x13,0xa6,0xcc,0x3e,0x51,0x60,0x91,0x53,0x55,0x87,0xf3,0x2a,0x98,0xff,0x7c,0x6c,0x1a,0xf9,0xec,0xda,0xeb,0x94,0x13,0x43,0xdd,0x3f,0x2a,0x41,0xd2,0xb,0x27,0x65,0xe8,0x13,0x20,0x29,0x3f,0xc6,0x7c,0x48,0x65,0x8,0x41,0xda,0xa4,0xd5,0x11,0xc0,0x2a,0x61,0xce,0x18,0x58,0xd2,0xbe,0x98,0x48,0x96,0xdd,0xf5,0xbc,0x11,0x65,0xb6,0x12,0x55,0xcb,0xde,0xb3,0x78,0x27,0x78,0xdc,0xcb,0x72,0xe6,0xd7,0x8a,0x27,0xe6,0x52,0x1f,0x10,0xe0,0xb8,0x92,0x81,0xb4,0x3f,0x1,0x1d,0xed,0x6c,0xd4,0xef,0x12,0x2f,0x73,0xa0,0xe,0xf,0x42,0x24,0x20,0xf,0x91,0xbf,0x6e,0x44,0xfb,0xde,0xa1,0x4,0xa5,0x7,0xaa,0xa0,0x23,0xad,0xd4,0x4b,0xaa,0x73,0x0,0xb7,0xa1,0x82,0x87,0x46,0x74,0x9a,0xf,0x48,0x5d,0xb3,0xd,0xa2,0xb0,0x96,0xe5,0x7d,0xc8,0x81,0x19,0xf1,0x36,0x2b,0xba,0xbd,0x5e,0xb3,0xb7,0x55,0x12,0x76,0x90,0xc4,0x3a,0x1,0xa7,0x66,0xbc,0x3,0x90,0xe0,0x8,0xc8,0x42,0x29,0xa5,0x7b,0xa2,0x63,0x9f,0x88,0x26,0xa,0x9c,0x85,0x6f,0x7b,0x2b,0x0,0x92,0x51,0x4a,0x81,0x5c,0x2a,0xcb,0x2a,0x47,0x0,0xb0,0x2b,0x8,0x11,0x62,0x20,0x58,0x20,0x47,0x77,0x5a,0xe5,0x98,0x43,0x3f,0x2,0xd8,0xc1,0xa5,0x39,0x40,0x82,0xb5,0xd9,0xd7,0x5a,0x2,0x59,0x80,0x9,0x8a,0x0,0x7f,0x1,0x8,0x44,0x8,0x64,0xe0,0xe8,0x6e,0x4b,0xb4,0x87,0xa6,0xc4,0x3d,0x17,0x24,0xa3,0xa8,0xc0,0x32,0x8a,0xea,0x33,0x67,0x0,0x6e,0xc,0x94,0x5e,0xe2,0x46,0x11,0x3a,0x0,0x82,0x57,0x1,0x98,0xbf,0xb,0xa4,0xf6,0x55,0xd4,0x2a,0xe1,0x0,0x40,0xf5,0xf3,0xa5,0xd3,0x16,0x6a,0xb4,0xa7,0x19,0xfa,0x4f,0x18,0xe8,0x2c,0x34,0xfb,0x92,0x20,0xbb,0xf,0xa3,0x1d,0xc0,0xcd,0xe7,0xb7,0x83,0xf9,0xf2,0x24,0xd3,0xd7,0xaf,0x40,0x9a,0x84,0x1,0xf0,0xfe,0xf6,0xee,0x1d,0x80,0x4f,0xff,0xc8,0xdf,0x63,0xeb,0xfd,0x6f,0x3,0x74,0x35,0xa7,0x2a,0xf0,0x17,0xed,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char tree_bg_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0xa, 0x4, 0x3, 0x0, 0x0, 0x0, 0x7f, 0x1c, 0xd2, 0x8e, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x2a, 0x50, 0x4c, 0x54, 0x45, 0x17, 0x16, 0x1a, 0x1d, 0x1c, 0x21, 0x20, 0x1e, 0x24, 0x21, 0x1f, 0x25, 0x1d, 0x1c, 0x21, 0x20, 0x1e, 0x24, 0x1d, 0x1c, 0x21, 0x1d, 0x1c, 0x21, 0x24, 0x22, 0x29, 0x28, 0x26, 0x2d, 0x28, 0x26, 0x2e, 0x2b, 0x2a, 0x31, 0x2c, 0x2a, 0x32, 0xff, 0xff, 0xff, 0xb9, 0x11, 0x56, 0x3e, 0x0, 0x0, 0x0, 0x8, 0x74, 0x52, 0x4e, 0x53, 0x6f, 0xef, 0xf7, 0xf7, 0xf0, 0xf9, 0xf1, 0xee, 0xcf, 0x21, 0xd2, 0xdf, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0xd, 0xf6, 0xb4, 0x61, 0xf5, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x2d, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x54, 0x36, 0x36, 0x12, 0x60, 0xf0, 0x98, 0xb5, 0x6a, 0x65, 0xb, 0x43, 0xe4, 0x9e, 0x33, 0xa7, 0xa7, 0x32, 0x58, 0x9d, 0x39, 0x73, 0x66, 0x31, 0x16, 0x12, 0x22, 0xb, 0x52, 0xd9, 0xc6, 0xc0, 0x2, 0xd4, 0x55, 0x0, 0x0, 0xc, 0x14, 0x1a, 0x90, 0x55, 0x1a, 0xec, 0xdb, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char tree_cursor_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xe,0x0,0x0,0x0,0xe,0x8,0x3,0x0,0x0,0x0,0x28,0x96,0xdd,0xe3,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0xc6,0x50,0x4c,0x54,0x45,0xd4,0xab,0x9e,0xd3,0xaa,0x9d,0xd4,0xab,0x9e,0xd3,0xaa,0x9d,0xd4,0xab,0x9c,0xd4,0xac,0x9e,0xd5,0xaf,0xa3,0xd5,0xb0,0xa3,0xd5,0xaf,0xa3,0xd5,0xad,0xa1,0xd5,0xaf,0xa3,0xd5,0xad,0xa1,0xd5,0xb0,0xa3,0xd6,0xad,0xa0,0xd6,0xad,0xa0,0xd5,0xb0,0xa3,0xd7,0xb1,0xa5,0xd7,0xb1,0xa7,0xd7,0xb1,0xa7,0xd7,0xb1,0xa7,0xd7,0xb1,0xa7,0xd7,0xb1,0xa5,0xd7,0xb1,0xa5,0xd8,0xb3,0xa8,0xd8,0xb5,0xaa,0xda,0xb3,0xa8,0xda,0xb3,0xa8,0xd8,0xb3,0xa8,0xd8,0xb5,0xaa,0xda,0xb3,0xa8,0xd8,0xb3,0xa8,0xdb,0xb7,0xad,0xda,0xb8,0xae,0xdb,0xb9,0xad,0xdb,0xb9,0xad,0xdb,0xb7,0xad,0xdd,0xba,0xb1,0xdd,0xbb,0xb1,0xdd,0xbd,0xb1,0xdd,0xbf,0xb3,0xdd,0xbd,0xb3,0xdf,0xc1,0xb7,0xdf,0xc0,0xb5,0xdf,0xbf,0xb5,0xe1,0xc3,0xb9,0xe1,0xc3,0xbb,0xe1,0xc5,0xbb,0xe2,0xc7,0xbe,0xe1,0xc5,0xbd,0xe4,0xcb,0xc2,0xe3,0xca,0xc1,0xe3,0xcb,0xc3,0xe6,0xce,0xc6,0xe6,0xd0,0xc6,0xe8,0xd1,0xca,0xe8,0xd1,0xca,0xe8,0xd0,0xca,0xe8,0xcf,0xca,0xb7,0x7d,0x69,0xb1,0x77,0x63,0xac,0x73,0x5c,0xa6,0x69,0x56,0x9c,0x67,0x54,0x93,0x62,0x51,0x88,0x60,0x50,0x0,0x0,0x0,0x39,0x76,0x1d,0xc2,0x0,0x0,0x0,0x3a,0x74,0x52,0x4e,0x53,0x32,0x2f,0x30,0x33,0x38,0x40,0x32,0x2f,0x2f,0x2f,0x31,0x33,0x33,0x33,0x36,0x38,0x31,0x2f,0x30,0x31,0x33,0x33,0x35,0x2f,0x2f,0x2f,0x30,0x32,0x33,0x33,0x33,0x2f,0x2f,0x2f,0x30,0x30,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x32,0x2f,0x2f,0x2f,0xb8,0xf,0x95,0x41,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x41,0x89,0xde,0x6c,0x4e,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x4,0x4e,0x1d,0x2,0xaf,0x0,0x0,0x0,0x9e,0x49,0x44,0x41,0x54,0x8,0xd7,0x55,0xcf,0x5b,0x17,0x81,0x40,0x14,0x5,0xe0,0xe3,0x9a,0x4b,0x2e,0x31,0x14,0x62,0x22,0x53,0x4d,0x83,0x44,0xc,0xa6,0xa9,0xf9,0xff,0xbf,0xca,0xd4,0x5a,0x1e,0x7c,0xfb,0xec,0xb5,0x9f,0xf,0x7c,0xfe,0x80,0x80,0x86,0xd6,0x6c,0x69,0xed,0x8e,0x80,0xbc,0x6b,0x18,0xbd,0xfe,0x60,0x68,0x9a,0xa3,0xf1,0x24,0x7,0x39,0xb5,0x2c,0x6b,0x36,0x47,0x68,0x81,0xd0,0x52,0x42,0x61,0x3b,0xb6,0xb3,0x72,0xd6,0x1b,0x77,0xeb,0xee,0xa,0x28,0x31,0xc6,0x9e,0x87,0x3d,0xbc,0x3f,0xf8,0x7e,0x9,0xea,0x48,0x8,0x9,0xc2,0x28,0x22,0x21,0x9,0x14,0x28,0x1a,0x33,0x16,0xd3,0x98,0xb2,0x98,0x51,0x5,0xe5,0x49,0x3b,0xeb,0x5e,0x74,0x4a,0x28,0x92,0xca,0xb5,0xbe,0xa4,0x0,0x99,0xde,0xd2,0xca,0xbd,0x5a,0x9,0x79,0x96,0x3d,0xb2,0x9f,0x1c,0xc4,0x93,0xf3,0x17,0xaf,0xfb,0xe6,0x2,0xfe,0x5f,0xf8,0x2,0x30,0xbc,0x1f,0xb4,0x2b,0xfc,0x80,0xca,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char tree_bg_focus_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x20, 0x8, 0x6, 0x0, 0x0, 0x0, 0x73, 0x7a, 0x7a, 0xf4, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xdb, 0xb, 0x4, 0x12, 0x2d, 0x3a, 0xb5, 0x1b, 0x14, 0x49, 0x0, 0x0, 0x2, 0xd9, 0x49, 0x44, 0x41, 0x54, 0x58, 0xc3, 0xc5, 0x57, 0x31, 0x8e, 0x14, 0x31, 0x10, 0xac, 0xea, 0x3d, 0x11, 0x91, 0xdf, 0x49, 0xf7, 0xf, 0x78, 0x1, 0xf, 0x40, 0x84, 0x44, 0x10, 0xf2, 0x20, 0x42, 0x62, 0x12, 0xc4, 0x3, 0x78, 0x1, 0xff, 0x21, 0x42, 0xb8, 0x8a, 0xc0, 0x1e, 0x4f, 0xdb, 0xe3, 0xb9, 0xbb, 0x45, 0x20, 0x7c, 0x1a, 0xdd, 0x8c, 0xec, 0xed, 0xae, 0xae, 0xea, 0xee, 0xe9, 0xe1, 0xfd, 0xed, 0xdd, 0xb, 0x0, 0xdf, 0xf1, 0x7f, 0xd6, 0x4b, 0xde, 0xdf, 0xde, 0xf9, 0xcb, 0xeb, 0x9f, 0xff, 0xc5, 0xfb, 0x9b, 0xaf, 0xcf, 0x70, 0xb3, 0x3d, 0x3c, 0xff, 0xf0, 0xd, 0x24, 0x11, 0x71, 0x1, 0x49, 0x90, 0x4, 0x0, 0x4, 0xd3, 0x2f, 0xb6, 0x7b, 0xf, 0xff, 0x86, 0x2d, 0x8c, 0x47, 0x60, 0x1b, 0x0, 0x61, 0x1b, 0xb6, 0x21, 0x15, 0xd8, 0xc6, 0x8f, 0x8f, 0xaf, 0x0, 0x60, 0x7, 0x0, 0xa2, 0x2, 0x20, 0x11, 0x41, 0x30, 0xa2, 0x2, 0xc1, 0xb5, 0x0, 0x8c, 0x79, 0xd9, 0x80, 0x24, 0x48, 0x0, 0x48, 0x28, 0x9d, 0xb9, 0xd9, 0xd, 0xb0, 0x31, 0x40, 0x5c, 0x2e, 0x1, 0x46, 0x0, 0xd, 0xd0, 0xb6, 0xef, 0x35, 0x8e, 0x13, 0x6, 0xbc, 0x33, 0x60, 0xa3, 0x9a, 0x11, 0x6c, 0x82, 0xe6, 0xa, 0x0, 0x86, 0xe8, 0x2f, 0x71, 0xa9, 0xf7, 0x9c, 0x4d, 0x1f, 0x69, 0x5e, 0x1, 0xd8, 0xa3, 0x37, 0xa4, 0xa, 0x27, 0x1a, 0x13, 0x79, 0x25, 0x9, 0xaa, 0xe3, 0xd8, 0x9c, 0x5f, 0xea, 0x7d, 0x67, 0x80, 0xd7, 0x31, 0x20, 0xab, 0x3, 0x20, 0x5, 0x20, 0x2a, 0x13, 0x41, 0x40, 0x2b, 0x0, 0x76, 0x22, 0xb9, 0xb1, 0xd1, 0x92, 0x91, 0x5d, 0x86, 0xf3, 0x35, 0xef, 0x5, 0xa3, 0x25, 0x60, 0xd, 0x6e, 0x66, 0xe5, 0x0, 0xc0, 0xa8, 0x54, 0x1, 0x6, 0xe9, 0x16, 0x9f, 0x4f, 0xdc, 0x1c, 0x13, 0xed, 0xb1, 0x55, 0x31, 0x78, 0x70, 0x8e, 0xca, 0xcb, 0x8e, 0x6a, 0xbe, 0x56, 0x88, 0x67, 0x38, 0xdb, 0x75, 0x58, 0x76, 0xdf, 0x1b, 0x6c, 0x7a, 0xc, 0x6c, 0x90, 0x0, 0xfd, 0xe0, 0xe8, 0x98, 0xe4, 0x4, 0xe2, 0x69, 0xc, 0xe4, 0x40, 0xaa, 0xf9, 0x63, 0x70, 0xbb, 0x4, 0x16, 0x9c, 0x12, 0xa7, 0x3e, 0xe7, 0x38, 0xb3, 0x4, 0x2b, 0x6f, 0xc7, 0x23, 0xbb, 0xc3, 0x66, 0xdb, 0x38, 0x7, 0x0, 0xcf, 0x32, 0x34, 0xb6, 0x52, 0xb4, 0x3c, 0xf7, 0x35, 0x10, 0xd9, 0xf7, 0x6, 0x56, 0x93, 0x4, 0x4b, 0x0, 0x43, 0x28, 0xf9, 0x4a, 0x3d, 0x6e, 0xb0, 0x3e, 0x9, 0x31, 0xa9, 0x62, 0xd6, 0xc4, 0x36, 0x9c, 0xf2, 0xd9, 0xbd, 0x41, 0x2d, 0x24, 0x68, 0xc7, 0x1f, 0x62, 0x60, 0x6a, 0xc1, 0x7f, 0x95, 0x81, 0xaa, 0x13, 0x61, 0x9, 0xa6, 0xf6, 0x1c, 0x30, 0x17, 0x11, 0x6f, 0x48, 0x12, 0x3b, 0xf3, 0x7b, 0xc2, 0xeb, 0xca, 0x92, 0xb7, 0x72, 0x5f, 0x31, 0x90, 0x11, 0x4e, 0x48, 0xb3, 0x13, 0xa6, 0xcc, 0x3e, 0x51, 0x60, 0x91, 0x53, 0x55, 0x87, 0xf3, 0x2a, 0x98, 0xff, 0x7c, 0x6c, 0x1a, 0xf9, 0xec, 0xda, 0xeb, 0x94, 0x13, 0x43, 0xdd, 0x3f, 0x2a, 0x41, 0xd2, 0xb, 0x27, 0x65, 0xe8, 0x13, 0x20, 0x29, 0x3f, 0xc6, 0x7c, 0x48, 0x65, 0x8, 0x41, 0xda, 0xa4, 0xd5, 0x11, 0xc0, 0x2a, 0x61, 0xce, 0x18, 0x58, 0xd2, 0xbe, 0x98, 0x48, 0x96, 0xdd, 0xf5, 0xbc, 0x11, 0x65, 0xb6, 0x12, 0x55, 0xcb, 0xde, 0xb3, 0x78, 0x27, 0x78, 0xdc, 0xcb, 0x72, 0xe6, 0xd7, 0x8a, 0x27, 0xe6, 0x52, 0x1f, 0x10, 0xe0, 0xb8, 0x92, 0x81, 0xb4, 0x3f, 0x1, 0x1d, 0xed, 0x6c, 0xd4, 0xef, 0x12, 0x2f, 0x73, 0xa0, 0xe, 0xf, 0x42, 0x24, 0x20, 0xf, 0x91, 0xbf, 0x6e, 0x44, 0xfb, 0xde, 0xa1, 0x4, 0xa5, 0x7, 0xaa, 0xa0, 0x23, 0xad, 0xd4, 0x4b, 0xaa, 0x73, 0x0, 0xb7, 0xa1, 0x82, 0x87, 0x46, 0x74, 0x9a, 0xf, 0x48, 0x5d, 0xb3, 0xd, 0xa2, 0xb0, 0x96, 0xe5, 0x7d, 0xc8, 0x81, 0x19, 0xf1, 0x36, 0x2b, 0xba, 0xbd, 0x5e, 0xb3, 0xb7, 0x55, 0x12, 0x76, 0x90, 0xc4, 0x3a, 0x1, 0xa7, 0x66, 0xbc, 0x3, 0x90, 0xe0, 0x8, 0xc8, 0x42, 0x29, 0xa5, 0x7b, 0xa2, 0x63, 0x9f, 0x88, 0x26, 0xa, 0x9c, 0x85, 0x6f, 0x7b, 0x2b, 0x0, 0x92, 0x51, 0x4a, 0x81, 0x5c, 0x2a, 0xcb, 0x2a, 0x47, 0x0, 0xb0, 0x2b, 0x8, 0x11, 0x62, 0x20, 0x58, 0x20, 0x47, 0x77, 0x5a, 0xe5, 0x98, 0x43, 0x3f, 0x2, 0xd8, 0xc1, 0xa5, 0x39, 0x40, 0x82, 0xb5, 0xd9, 0xd7, 0x5a, 0x2, 0x59, 0x80, 0x9, 0x8a, 0x0, 0x7f, 0x1, 0x8, 0x44, 0x8, 0x64, 0xe0, 0xe8, 0x6e, 0x4b, 0xb4, 0x87, 0xa6, 0xc4, 0x3d, 0x17, 0x24, 0xa3, 0xa8, 0xc0, 0x32, 0x8a, 0xea, 0x33, 0x67, 0x0, 0x6e, 0xc, 0x94, 0x5e, 0xe2, 0x46, 0x11, 0x3a, 0x0, 0x82, 0x57, 0x1, 0x98, 0xbf, 0xb, 0xa4, 0xf6, 0x55, 0xd4, 0x2a, 0xe1, 0x0, 0x40, 0xf5, 0xf3, 0xa5, 0xd3, 0x16, 0x6a, 0xb4, 0xa7, 0x19, 0xfa, 0x4f, 0x18, 0xe8, 0x2c, 0x34, 0xfb, 0x92, 0x20, 0xbb, 0xf, 0xa3, 0x1d, 0xc0, 0xcd, 0xe7, 0xb7, 0x83, 0xf9, 0xf2, 0x24, 0xd3, 0xd7, 0xaf, 0x40, 0x9a, 0x84, 0x1, 0xf0, 0xfe, 0xf6, 0xee, 0x1d, 0x80, 0x4f, 0xff, 0xc8, 0xdf, 0x63, 0xeb, 0xfd, 0x6f, 0x3, 0x74, 0x35, 0xa7, 0x2a, 0xf0, 0x17, 0xed, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char tree_cursor_unfocus_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xe,0x0,0x0,0x0,0xe,0x8,0x3,0x0,0x0,0x0,0x28,0x96,0xdd,0xe3,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x99,0x50,0x4c,0x54,0x45,0xc0,0xb5,0xb2,0xbf,0xb4,0xb1,0xc0,0xb5,0xb2,0xbf,0xb4,0xb1,0xbf,0xb5,0xb1,0xc0,0xb5,0xb2,0xc3,0xb8,0xb5,0xc3,0xb8,0xb5,0xc2,0xb7,0xb4,0xc3,0xb8,0xb5,0xc2,0xb7,0xb4,0xc3,0xb8,0xb5,0xc2,0xb7,0xb4,0xc3,0xb8,0xb5,0xc5,0xba,0xb7,0xc5,0xbc,0xb9,0xc5,0xbc,0xb9,0xc5,0xbc,0xb9,0xc5,0xbc,0xb9,0xc5,0xba,0xb7,0xc5,0xba,0xb7,0xc6,0xbd,0xba,0xc7,0xbe,0xbb,0xc7,0xbe,0xbb,0xc6,0xbd,0xba,0xc7,0xbe,0xbb,0xc6,0xbd,0xba,0xca,0xc1,0xbe,0xca,0xc1,0xbe,0xcd,0xc4,0xc1,0xcd,0xc6,0xc3,0xd0,0xc9,0xc6,0xcf,0xc8,0xc5,0xd2,0xcb,0xc8,0xd3,0xcb,0xc9,0xd3,0xcc,0xc9,0xd5,0xcd,0xcb,0xd4,0xcc,0xca,0xd7,0xd1,0xcf,0xd6,0xd0,0xce,0xda,0xd4,0xd2,0xdd,0xd7,0xd5,0xdd,0xd7,0xd5,0x9a,0x8b,0x86,0x94,0x85,0x80,0x8e,0x80,0x7a,0x88,0x79,0x74,0x81,0x75,0x6f,0x7a,0x6f,0x6a,0x73,0x69,0x65,0x0,0x0,0x0,0xfb,0x87,0x71,0x8e,0x0,0x0,0x0,0x2b,0x74,0x52,0x4e,0x53,0x32,0x2f,0x30,0x33,0x38,0x40,0x32,0x2f,0x2f,0x31,0x33,0x33,0x36,0x38,0x31,0x2f,0x30,0x31,0x33,0x33,0x35,0x2f,0x2f,0x30,0x32,0x33,0x33,0x2f,0x30,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x32,0x2f,0x82,0xd8,0x8a,0x2f,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x32,0x40,0xd2,0x4c,0xc8,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x4,0x4e,0x1d,0x2,0xaf,0x0,0x0,0x0,0x82,0x49,0x44,0x41,0x54,0x8,0xd7,0x55,0xcf,0xe9,0x16,0xc1,0x30,0x14,0x4,0xe0,0xb1,0x96,0x16,0x25,0x34,0x84,0x26,0x2d,0xaa,0xb6,0xac,0xef,0xff,0x72,0x6e,0x38,0xe,0xfd,0xe6,0xce,0x99,0xdf,0x17,0xcf,0xe,0x68,0xf4,0x48,0x7f,0x40,0x86,0x23,0xd,0x33,0x4e,0x92,0x64,0x32,0x4d,0xb3,0x2c,0x9d,0xcd,0xd,0xec,0x22,0xcf,0xf3,0xe5,0x8a,0xb1,0x35,0x63,0x1b,0xb,0x57,0xf0,0x82,0x73,0xbe,0xdd,0x9,0x21,0xf6,0xe,0xfe,0xf0,0x55,0x96,0xa5,0x47,0x90,0x91,0x52,0x4a,0x2a,0x29,0x3,0x42,0x55,0x93,0xaa,0x8e,0x53,0x5,0xf8,0x23,0x39,0x51,0xcf,0x14,0xf,0xd7,0x44,0x97,0xf7,0x35,0xe,0xb6,0xbd,0xb6,0x1f,0xb4,0x16,0xe6,0xf6,0xc7,0x40,0xdf,0x1f,0x3f,0x1a,0xdd,0x17,0x5e,0xc0,0x36,0x18,0x83,0x7f,0x54,0x76,0x87,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char tree_cursor_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0xe, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x96, 0xdd, 0xe3, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0xc6, 0x50, 0x4c, 0x54, 0x45, 0xd4, 0xab, 0x9e, 0xd3, 0xaa, 0x9d, 0xd4, 0xab, 0x9e, 0xd3, 0xaa, 0x9d, 0xd4, 0xab, 0x9c, 0xd4, 0xac, 0x9e, 0xd5, 0xaf, 0xa3, 0xd5, 0xb0, 0xa3, 0xd5, 0xaf, 0xa3, 0xd5, 0xad, 0xa1, 0xd5, 0xaf, 0xa3, 0xd5, 0xad, 0xa1, 0xd5, 0xb0, 0xa3, 0xd6, 0xad, 0xa0, 0xd6, 0xad, 0xa0, 0xd5, 0xb0, 0xa3, 0xd7, 0xb1, 0xa5, 0xd7, 0xb1, 0xa7, 0xd7, 0xb1, 0xa7, 0xd7, 0xb1, 0xa7, 0xd7, 0xb1, 0xa7, 0xd7, 0xb1, 0xa5, 0xd7, 0xb1, 0xa5, 0xd8, 0xb3, 0xa8, 0xd8, 0xb5, 0xaa, 0xda, 0xb3, 0xa8, 0xda, 0xb3, 0xa8, 0xd8, 0xb3, 0xa8, 0xd8, 0xb5, 0xaa, 0xda, 0xb3, 0xa8, 0xd8, 0xb3, 0xa8, 0xdb, 0xb7, 0xad, 0xda, 0xb8, 0xae, 0xdb, 0xb9, 0xad, 0xdb, 0xb9, 0xad, 0xdb, 0xb7, 0xad, 0xdd, 0xba, 0xb1, 0xdd, 0xbb, 0xb1, 0xdd, 0xbd, 0xb1, 0xdd, 0xbf, 0xb3, 0xdd, 0xbd, 0xb3, 0xdf, 0xc1, 0xb7, 0xdf, 0xc0, 0xb5, 0xdf, 0xbf, 0xb5, 0xe1, 0xc3, 0xb9, 0xe1, 0xc3, 0xbb, 0xe1, 0xc5, 0xbb, 0xe2, 0xc7, 0xbe, 0xe1, 0xc5, 0xbd, 0xe4, 0xcb, 0xc2, 0xe3, 0xca, 0xc1, 0xe3, 0xcb, 0xc3, 0xe6, 0xce, 0xc6, 0xe6, 0xd0, 0xc6, 0xe8, 0xd1, 0xca, 0xe8, 0xd1, 0xca, 0xe8, 0xd0, 0xca, 0xe8, 0xcf, 0xca, 0xb7, 0x7d, 0x69, 0xb1, 0x77, 0x63, 0xac, 0x73, 0x5c, 0xa6, 0x69, 0x56, 0x9c, 0x67, 0x54, 0x93, 0x62, 0x51, 0x88, 0x60, 0x50, 0x0, 0x0, 0x0, 0x39, 0x76, 0x1d, 0xc2, 0x0, 0x0, 0x0, 0x3a, 0x74, 0x52, 0x4e, 0x53, 0x32, 0x2f, 0x30, 0x33, 0x38, 0x40, 0x32, 0x2f, 0x2f, 0x2f, 0x31, 0x33, 0x33, 0x33, 0x36, 0x38, 0x31, 0x2f, 0x30, 0x31, 0x33, 0x33, 0x35, 0x2f, 0x2f, 0x2f, 0x30, 0x32, 0x33, 0x33, 0x33, 0x2f, 0x2f, 0x2f, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x32, 0x2f, 0x2f, 0x2f, 0xb8, 0xf, 0x95, 0x41, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x41, 0x89, 0xde, 0x6c, 0x4e, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x4, 0x4e, 0x1d, 0x2, 0xaf, 0x0, 0x0, 0x0, 0x9e, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x55, 0xcf, 0x5b, 0x17, 0x81, 0x40, 0x14, 0x5, 0xe0, 0xe3, 0x9a, 0x4b, 0x2e, 0x31, 0x14, 0x62, 0x22, 0x53, 0x4d, 0x83, 0x44, 0xc, 0xa6, 0xa9, 0xf9, 0xff, 0xbf, 0xca, 0xd4, 0x5a, 0x1e, 0x7c, 0xfb, 0xec, 0xb5, 0x9f, 0xf, 0x7c, 0xfe, 0x80, 0x80, 0x86, 0xd6, 0x6c, 0x69, 0xed, 0x8e, 0x80, 0xbc, 0x6b, 0x18, 0xbd, 0xfe, 0x60, 0x68, 0x9a, 0xa3, 0xf1, 0x24, 0x7, 0x39, 0xb5, 0x2c, 0x6b, 0x36, 0x47, 0x68, 0x81, 0xd0, 0x52, 0x42, 0x61, 0x3b, 0xb6, 0xb3, 0x72, 0xd6, 0x1b, 0x77, 0xeb, 0xee, 0xa, 0x28, 0x31, 0xc6, 0x9e, 0x87, 0x3d, 0xbc, 0x3f, 0xf8, 0x7e, 0x9, 0xea, 0x48, 0x8, 0x9, 0xc2, 0x28, 0x22, 0x21, 0x9, 0x14, 0x28, 0x1a, 0x33, 0x16, 0xd3, 0x98, 0xb2, 0x98, 0x51, 0x5, 0xe5, 0x49, 0x3b, 0xeb, 0x5e, 0x74, 0x4a, 0x28, 0x92, 0xca, 0xb5, 0xbe, 0xa4, 0x0, 0x99, 0xde, 0xd2, 0xca, 0xbd, 0x5a, 0x9, 0x79, 0x96, 0x3d, 0xb2, 0x9f, 0x1c, 0xc4, 0x93, 0xf3, 0x17, 0xaf, 0xfb, 0xe6, 0x2, 0xfe, 0x5f, 0xf8, 0x2, 0x30, 0xbc, 0x1f, 0xb4, 0x2b, 0xfc, 0x80, 0xca, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char tree_title_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x1,0x3,0x0,0x0,0x0,0x25,0x3d,0x6d,0x22,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x6,0x50,0x4c,0x54,0x45,0x25,0x23,0x25,0x4c,0x4a,0x4e,0x1,0xf9,0x98,0x2e,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x1,0xff,0x2,0x2d,0xde,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0xc,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0x20,0xd,0x0,0x0,0x0,0x30,0x0,0x1,0xc7,0xaa,0x85,0x8e,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char tree_cursor_unfocus_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0xe, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x96, 0xdd, 0xe3, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x99, 0x50, 0x4c, 0x54, 0x45, 0xc0, 0xb5, 0xb2, 0xbf, 0xb4, 0xb1, 0xc0, 0xb5, 0xb2, 0xbf, 0xb4, 0xb1, 0xbf, 0xb5, 0xb1, 0xc0, 0xb5, 0xb2, 0xc3, 0xb8, 0xb5, 0xc3, 0xb8, 0xb5, 0xc2, 0xb7, 0xb4, 0xc3, 0xb8, 0xb5, 0xc2, 0xb7, 0xb4, 0xc3, 0xb8, 0xb5, 0xc2, 0xb7, 0xb4, 0xc3, 0xb8, 0xb5, 0xc5, 0xba, 0xb7, 0xc5, 0xbc, 0xb9, 0xc5, 0xbc, 0xb9, 0xc5, 0xbc, 0xb9, 0xc5, 0xbc, 0xb9, 0xc5, 0xba, 0xb7, 0xc5, 0xba, 0xb7, 0xc6, 0xbd, 0xba, 0xc7, 0xbe, 0xbb, 0xc7, 0xbe, 0xbb, 0xc6, 0xbd, 0xba, 0xc7, 0xbe, 0xbb, 0xc6, 0xbd, 0xba, 0xca, 0xc1, 0xbe, 0xca, 0xc1, 0xbe, 0xcd, 0xc4, 0xc1, 0xcd, 0xc6, 0xc3, 0xd0, 0xc9, 0xc6, 0xcf, 0xc8, 0xc5, 0xd2, 0xcb, 0xc8, 0xd3, 0xcb, 0xc9, 0xd3, 0xcc, 0xc9, 0xd5, 0xcd, 0xcb, 0xd4, 0xcc, 0xca, 0xd7, 0xd1, 0xcf, 0xd6, 0xd0, 0xce, 0xda, 0xd4, 0xd2, 0xdd, 0xd7, 0xd5, 0xdd, 0xd7, 0xd5, 0x9a, 0x8b, 0x86, 0x94, 0x85, 0x80, 0x8e, 0x80, 0x7a, 0x88, 0x79, 0x74, 0x81, 0x75, 0x6f, 0x7a, 0x6f, 0x6a, 0x73, 0x69, 0x65, 0x0, 0x0, 0x0, 0xfb, 0x87, 0x71, 0x8e, 0x0, 0x0, 0x0, 0x2b, 0x74, 0x52, 0x4e, 0x53, 0x32, 0x2f, 0x30, 0x33, 0x38, 0x40, 0x32, 0x2f, 0x2f, 0x31, 0x33, 0x33, 0x36, 0x38, 0x31, 0x2f, 0x30, 0x31, 0x33, 0x33, 0x35, 0x2f, 0x2f, 0x30, 0x32, 0x33, 0x33, 0x2f, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x32, 0x2f, 0x82, 0xd8, 0x8a, 0x2f, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x32, 0x40, 0xd2, 0x4c, 0xc8, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x4, 0x4e, 0x1d, 0x2, 0xaf, 0x0, 0x0, 0x0, 0x82, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x55, 0xcf, 0xe9, 0x16, 0xc1, 0x30, 0x14, 0x4, 0xe0, 0xb1, 0x96, 0x16, 0x25, 0x34, 0x84, 0x26, 0x2d, 0xaa, 0xb6, 0xac, 0xef, 0xff, 0x72, 0x6e, 0x38, 0xe, 0xfd, 0xe6, 0xce, 0x99, 0xdf, 0x17, 0xcf, 0xe, 0x68, 0xf4, 0x48, 0x7f, 0x40, 0x86, 0x23, 0xd, 0x33, 0x4e, 0x92, 0x64, 0x32, 0x4d, 0xb3, 0x2c, 0x9d, 0xcd, 0xd, 0xec, 0x22, 0xcf, 0xf3, 0xe5, 0x8a, 0xb1, 0x35, 0x63, 0x1b, 0xb, 0x57, 0xf0, 0x82, 0x73, 0xbe, 0xdd, 0x9, 0x21, 0xf6, 0xe, 0xfe, 0xf0, 0x55, 0x96, 0xa5, 0x47, 0x90, 0x91, 0x52, 0x4a, 0x2a, 0x29, 0x3, 0x42, 0x55, 0x93, 0xaa, 0x8e, 0x53, 0x5, 0xf8, 0x23, 0x39, 0x51, 0xcf, 0x14, 0xf, 0xd7, 0x44, 0x97, 0xf7, 0x35, 0xe, 0xb6, 0xbd, 0xb6, 0x1f, 0xb4, 0x16, 0xe6, 0xf6, 0xc7, 0x40, 0xdf, 0x1f, 0x3f, 0x1a, 0xdd, 0x17, 0x5e, 0xc0, 0x36, 0x18, 0x83, 0x7f, 0x54, 0x76, 0x87, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char tree_title_pressed_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x1,0x3,0x0,0x0,0x0,0x25,0x3d,0x6d,0x22,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x6,0x50,0x4c,0x54,0x45,0x36,0x34,0x36,0x4c,0x4a,0x4e,0x14,0xd7,0x5b,0xf8,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x1,0xff,0x2,0x2d,0xde,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0xc,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0x20,0xd,0x0,0x0,0x0,0x30,0x0,0x1,0xc7,0xaa,0x85,0x8e,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char tree_title_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x1, 0x3, 0x0, 0x0, 0x0, 0x25, 0x3d, 0x6d, 0x22, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x6, 0x50, 0x4c, 0x54, 0x45, 0x25, 0x23, 0x25, 0x4c, 0x4a, 0x4e, 0x1, 0xf9, 0x98, 0x2e, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x1, 0xff, 0x2, 0x2d, 0xde, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0xc, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x20, 0xd, 0x0, 0x0, 0x0, 0x30, 0x0, 0x1, 0xc7, 0xaa, 0x85, 0x8e, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char unchecked_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x36,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x38,0x37,0x40,0x20,0x20,0x24,0x20,0x20,0x24,0x38,0x36,0x40,0x20,0x20,0x25,0x1e,0x1e,0x22,0x1f,0x1f,0x23,0x20,0x20,0x24,0x22,0x22,0x27,0x23,0x23,0x28,0x25,0x25,0x2a,0xff,0xff,0xff,0xf7,0x93,0x46,0x7a,0x0,0x0,0x0,0xb,0x74,0x52,0x4e,0x53,0x0,0x7,0x27,0x50,0x66,0x68,0xb4,0xfa,0xfb,0xb4,0xfa,0xa4,0x7f,0xe1,0x5a,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x11,0xe2,0xb5,0x3d,0xba,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x53,0x49,0x44,0x41,0x54,0x18,0xd3,0xb5,0xcf,0xc1,0x12,0x80,0x20,0x8,0x45,0x51,0x5,0x14,0xd,0x5,0xff,0xff,0x6b,0x23,0x27,0x67,0x9a,0x6c,0xdb,0x5d,0x9e,0xd,0x8f,0x10,0xb6,0x22,0x20,0xa5,0x19,0x21,0x44,0x7,0xc8,0x2c,0x6d,0x26,0x9c,0xc1,0x1,0xb9,0xab,0xcd,0xb4,0x33,0x3a,0x90,0xe8,0xb8,0x53,0x21,0x87,0xd4,0x6c,0x81,0xb5,0xf4,0x17,0x6c,0x67,0x9f,0xc3,0xca,0x35,0xc,0x6a,0x59,0xd3,0x8f,0xa,0x5f,0xcf,0xbd,0x3a,0x1,0x93,0xe2,0x8,0xa4,0xb1,0xeb,0xd3,0x56,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char tree_title_pressed_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x1, 0x3, 0x0, 0x0, 0x0, 0x25, 0x3d, 0x6d, 0x22, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x6, 0x50, 0x4c, 0x54, 0x45, 0x36, 0x34, 0x36, 0x4c, 0x4a, 0x4e, 0x14, 0xd7, 0x5b, 0xf8, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x1, 0xff, 0x2, 0x2d, 0xde, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0xc, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x20, 0xd, 0x0, 0x0, 0x0, 0x30, 0x0, 0x1, 0xc7, 0xaa, 0x85, 0x8e, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char updown_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x2b,0x8a,0x3e,0x7d,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0xa6,0x49,0x44,0x41,0x54,0x28,0x91,0xa5,0x90,0x21,0xe,0xc2,0x50,0x10,0x44,0xdf,0x27,0x9b,0x10,0x2e,0xc0,0x9,0xd6,0x81,0xe3,0x6,0xe0,0xa0,0xd7,0x2d,0xae,0x18,0x24,0x95,0xc5,0x7d,0x51,0xdd,0xb,0x60,0xf6,0x67,0x31,0xfb,0x49,0xc1,0x20,0x3a,0x6a,0x93,0x99,0x9d,0xcc,0xc,0x2c,0x45,0xaa,0x47,0xce,0x79,0x2b,0x22,0x2d,0x80,0x99,0x5d,0x54,0x75,0xfa,0x8,0x82,0xec,0x80,0x7d,0xe8,0x7,0x33,0x3b,0xa9,0xea,0x94,0x82,0xbc,0x1,0x3b,0x60,0x8,0xc1,0x1e,0x78,0x9a,0xd9,0x51,0xc2,0x76,0x57,0xbf,0x0,0xaa,0x9b,0x88,0xb4,0x2b,0x77,0x7f,0x1,0x7d,0xb5,0x54,0xd5,0x29,0x84,0x7d,0x70,0x4b,0x6b,0x8e,0xe3,0x78,0x7,0x36,0x66,0x76,0xae,0xd5,0x22,0xf8,0x15,0x78,0x89,0xbb,0xaf,0x53,0x4a,0x7,0x11,0xe9,0x72,0xce,0x5f,0x21,0xdd,0xfd,0x21,0xa5,0x94,0x66,0x96,0xba,0x9b,0xd5,0x1c,0x4a,0x29,0xcd,0xff,0xa1,0x7e,0xa6,0xbe,0xc6,0xd4,0x9f,0x3c,0xcb,0xf1,0x6,0x8e,0x4e,0x65,0x44,0x6f,0x74,0x5c,0xa1,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char unchecked_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x36, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x38, 0x37, 0x40, 0x20, 0x20, 0x24, 0x20, 0x20, 0x24, 0x38, 0x36, 0x40, 0x20, 0x20, 0x25, 0x1e, 0x1e, 0x22, 0x1f, 0x1f, 0x23, 0x20, 0x20, 0x24, 0x22, 0x22, 0x27, 0x23, 0x23, 0x28, 0x25, 0x25, 0x2a, 0xff, 0xff, 0xff, 0xf7, 0x93, 0x46, 0x7a, 0x0, 0x0, 0x0, 0xb, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x7, 0x27, 0x50, 0x66, 0x68, 0xb4, 0xfa, 0xfb, 0xb4, 0xfa, 0xa4, 0x7f, 0xe1, 0x5a, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x11, 0xe2, 0xb5, 0x3d, 0xba, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x53, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0xb5, 0xcf, 0xc1, 0x12, 0x80, 0x20, 0x8, 0x45, 0x51, 0x5, 0x14, 0xd, 0x5, 0xff, 0xff, 0x6b, 0x23, 0x27, 0x67, 0x9a, 0x6c, 0xdb, 0x5d, 0x9e, 0xd, 0x8f, 0x10, 0xb6, 0x22, 0x20, 0xa5, 0x19, 0x21, 0x44, 0x7, 0xc8, 0x2c, 0x6d, 0x26, 0x9c, 0xc1, 0x1, 0xb9, 0xab, 0xcd, 0xb4, 0x33, 0x3a, 0x90, 0xe8, 0xb8, 0x53, 0x21, 0x87, 0xd4, 0x6c, 0x81, 0xb5, 0xf4, 0x17, 0x6c, 0x67, 0x9f, 0xc3, 0xca, 0x35, 0xc, 0x6a, 0x59, 0xd3, 0x8f, 0xa, 0x5f, 0xcf, 0xbd, 0x3a, 0x1, 0x93, 0xe2, 0x8, 0xa4, 0xb1, 0xeb, 0xd3, 0x56, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char vseparator_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x2,0x3,0x0,0x0,0x0,0xb9,0x61,0x56,0x18,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0xc,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x73,0x9b,0xaa,0xce,0xdc,0xe1,0xff,0xff,0xff,0x64,0x6c,0x1,0xd2,0x0,0x0,0x0,0x3,0x74,0x52,0x4e,0x53,0x0,0xb3,0xb3,0x67,0xf6,0xdb,0x93,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x3,0x11,0xc,0x4c,0xf2,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x10,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0x80,0x81,0xac,0x95,0xc,0x48,0x0,0x0,0xe,0x79,0x1,0x14,0xa1,0xc9,0x59,0x2,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char updown_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x2b, 0x8a, 0x3e, 0x7d, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0xa6, 0x49, 0x44, 0x41, 0x54, 0x28, 0x91, 0xa5, 0x90, 0x21, 0xe, 0xc2, 0x50, 0x10, 0x44, 0xdf, 0x27, 0x9b, 0x10, 0x2e, 0xc0, 0x9, 0xd6, 0x81, 0xe3, 0x6, 0xe0, 0xa0, 0xd7, 0x2d, 0xae, 0x18, 0x24, 0x95, 0xc5, 0x7d, 0x51, 0xdd, 0xb, 0x60, 0xf6, 0x67, 0x31, 0xfb, 0x49, 0xc1, 0x20, 0x3a, 0x6a, 0x93, 0x99, 0x9d, 0xcc, 0xc, 0x2c, 0x45, 0xaa, 0x47, 0xce, 0x79, 0x2b, 0x22, 0x2d, 0x80, 0x99, 0x5d, 0x54, 0x75, 0xfa, 0x8, 0x82, 0xec, 0x80, 0x7d, 0xe8, 0x7, 0x33, 0x3b, 0xa9, 0xea, 0x94, 0x82, 0xbc, 0x1, 0x3b, 0x60, 0x8, 0xc1, 0x1e, 0x78, 0x9a, 0xd9, 0x51, 0xc2, 0x76, 0x57, 0xbf, 0x0, 0xaa, 0x9b, 0x88, 0xb4, 0x2b, 0x77, 0x7f, 0x1, 0x7d, 0xb5, 0x54, 0xd5, 0x29, 0x84, 0x7d, 0x70, 0x4b, 0x6b, 0x8e, 0xe3, 0x78, 0x7, 0x36, 0x66, 0x76, 0xae, 0xd5, 0x22, 0xf8, 0x15, 0x78, 0x89, 0xbb, 0xaf, 0x53, 0x4a, 0x7, 0x11, 0xe9, 0x72, 0xce, 0x5f, 0x21, 0xdd, 0xfd, 0x21, 0xa5, 0x94, 0x66, 0x96, 0xba, 0x9b, 0xd5, 0x1c, 0x4a, 0x29, 0xcd, 0xff, 0xa1, 0x7e, 0xa6, 0xbe, 0xc6, 0xd4, 0x9f, 0x3c, 0xcb, 0xf1, 0x6, 0x8e, 0x4e, 0x65, 0x44, 0x6f, 0x74, 0x5c, 0xa1, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char vslider_bg_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x54,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x4d,0x4b,0x59,0x34,0x33,0x3a,0x2d,0x2c,0x32,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x4d,0x4b,0x59,0x3f,0x3e,0x49,0x2a,0x29,0x2f,0x20,0x20,0x24,0x3f,0x3e,0x49,0x3f,0x3e,0x49,0x1f,0x1f,0x24,0x40,0x3e,0x4a,0x20,0x20,0x24,0x34,0x33,0x3a,0x20,0x20,0x25,0x22,0x22,0x27,0x23,0x23,0x28,0x25,0x25,0x2a,0x1e,0x1e,0x23,0x23,0x23,0x27,0x2d,0x2c,0x32,0x1f,0x1f,0x23,0xff,0xff,0xff,0x3,0x35,0xf1,0x5f,0x0,0x0,0x0,0x13,0x74,0x52,0x4e,0x53,0x0,0x0,0x0,0x0,0x4,0x1a,0x40,0x5d,0x19,0x28,0x96,0xf0,0xfd,0x94,0x95,0xfc,0x93,0xfc,0xc0,0x0,0xb4,0xa,0x5f,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x1b,0x2,0x60,0xd4,0xa4,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x64,0x49,0x44,0x41,0x54,0x18,0xd3,0x9d,0xcf,0x39,0x2,0x80,0x20,0x10,0x3,0xc0,0xe5,0x90,0x43,0x50,0x94,0x1b,0xfe,0xff,0x50,0x5,0x69,0x94,0xce,0x94,0x53,0xec,0x26,0x0,0x0,0x88,0x2e,0x8c,0x73,0x26,0x28,0x82,0x1e,0x44,0xe5,0xaa,0xb4,0x56,0x9b,0x1c,0x82,0xc4,0x6e,0x9c,0xf7,0xce,0x1c,0x62,0x0,0x53,0x2e,0xc4,0x18,0x9c,0x62,0x3,0xb8,0xf6,0xf1,0x8e,0x3f,0xf9,0x3,0xd8,0xa6,0xdc,0x20,0x27,0x8b,0x3b,0x90,0x52,0x43,0x83,0x50,0xb,0xf9,0xb,0xd3,0xd1,0xe9,0xed,0x5c,0x6c,0xaa,0xfe,0x1d,0xf7,0x9e,0x7f,0x1,0x89,0x5c,0xa,0x6b,0x1f,0xe5,0xca,0x60,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char vseparator_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x2, 0x3, 0x0, 0x0, 0x0, 0xb9, 0x61, 0x56, 0x18, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0xc, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x73, 0x9b, 0xaa, 0xce, 0xdc, 0xe1, 0xff, 0xff, 0xff, 0x64, 0x6c, 0x1, 0xd2, 0x0, 0x0, 0x0, 0x3, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xb3, 0xb3, 0x67, 0xf6, 0xdb, 0x93, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x3, 0x11, 0xc, 0x4c, 0xf2, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x10, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x80, 0x81, 0xac, 0x95, 0xc, 0x48, 0x0, 0x0, 0xe, 0x79, 0x1, 0x14, 0xa1, 0xc9, 0x59, 0x2, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char vslider_grabber_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x4,0x0,0x0,0x0,0xb5,0xfa,0x37,0xea,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xb7,0xff,0x88,0x5,0x1d,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe1,0x1,0x12,0x1,0x36,0x8,0x50,0xb9,0xa7,0x53,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xf6,0x49,0x44,0x41,0x54,0x28,0xcf,0xbd,0x90,0xb1,0x4a,0x42,0x51,0x0,0x86,0xbf,0x73,0x8e,0x71,0xe5,0x9a,0x5c,0x41,0xd0,0x66,0x6b,0x33,0x1c,0x7c,0x80,0xa0,0xa5,0x17,0x8,0xa2,0x2d,0x84,0xf0,0x1,0xa2,0x25,0xf1,0x9,0x9a,0x1c,0xda,0x5b,0xb2,0x47,0xa8,0xa5,0xc1,0xa0,0x51,0x88,0xa2,0x29,0xa,0xc1,0x84,0x8,0x43,0xf4,0x96,0x17,0xcf,0xed,0xde,0x73,0x9c,0xcc,0x5c,0xda,0xea,0x9f,0x3f,0xfe,0x9f,0xef,0x87,0x3f,0x8f,0x0,0x40,0xe1,0xe2,0x91,0x42,0x10,0x32,0xe6,0x3,0x8d,0xc1,0xce,0x1,0x45,0xb6,0xba,0xbb,0xba,0xed,0x95,0x8c,0xd0,0x7d,0xff,0xe1,0xee,0xe2,0xb6,0xdd,0x79,0x61,0xc4,0xd7,0xc,0x48,0x57,0x2b,0xeb,0xb5,0x28,0xaf,0x1,0xc5,0x12,0x4e,0xac,0x7b,0x6f,0x57,0x27,0x8d,0xcf,0xe,0x1,0x56,0x1,0xb9,0x9d,0xba,0x28,0x6,0x18,0xc,0x31,0x21,0x5a,0xda,0x4c,0xb6,0xbc,0xb9,0x35,0x7c,0xea,0xbd,0x13,0x4a,0x20,0xe5,0x95,0xf4,0x6c,0x12,0x30,0x84,0xf8,0x44,0x6b,0xfb,0xcd,0x83,0x3d,0x1c,0xf9,0x8b,0x80,0x4a,0xba,0x88,0x4,0x30,0x1e,0xdd,0x3b,0x1b,0xf1,0x77,0x87,0x24,0x81,0x8b,0x79,0x3e,0x3b,0x6a,0x5d,0x33,0x51,0x80,0x2d,0x38,0x2b,0x65,0xb5,0x6c,0x91,0x28,0x92,0xa4,0xad,0xec,0x76,0xcf,0x8f,0xf,0x1f,0xdb,0xc,0x31,0xb,0x9a,0xb1,0xd0,0x3,0xfb,0xda,0x3a,0xbd,0xbc,0x89,0xfa,0xf8,0x73,0xcd,0x9f,0x47,0x45,0x4,0xf8,0x4,0x18,0xfe,0x2f,0x53,0x8,0x62,0x5c,0xcf,0x1f,0x5f,0xcb,0x2c,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char vslider_bg_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x54, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4d, 0x4b, 0x59, 0x34, 0x33, 0x3a, 0x2d, 0x2c, 0x32, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x3f, 0x3e, 0x49, 0x2a, 0x29, 0x2f, 0x20, 0x20, 0x24, 0x3f, 0x3e, 0x49, 0x3f, 0x3e, 0x49, 0x1f, 0x1f, 0x24, 0x40, 0x3e, 0x4a, 0x20, 0x20, 0x24, 0x34, 0x33, 0x3a, 0x20, 0x20, 0x25, 0x22, 0x22, 0x27, 0x23, 0x23, 0x28, 0x25, 0x25, 0x2a, 0x1e, 0x1e, 0x23, 0x23, 0x23, 0x27, 0x2d, 0x2c, 0x32, 0x1f, 0x1f, 0x23, 0xff, 0xff, 0xff, 0x3, 0x35, 0xf1, 0x5f, 0x0, 0x0, 0x0, 0x13, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x0, 0x0, 0x4, 0x1a, 0x40, 0x5d, 0x19, 0x28, 0x96, 0xf0, 0xfd, 0x94, 0x95, 0xfc, 0x93, 0xfc, 0xc0, 0x0, 0xb4, 0xa, 0x5f, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x1b, 0x2, 0x60, 0xd4, 0xa4, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x64, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x9d, 0xcf, 0x39, 0x2, 0x80, 0x20, 0x10, 0x3, 0xc0, 0xe5, 0x90, 0x43, 0x50, 0x94, 0x1b, 0xfe, 0xff, 0x50, 0x5, 0x69, 0x94, 0xce, 0x94, 0x53, 0xec, 0x26, 0x0, 0x0, 0x88, 0x2e, 0x8c, 0x73, 0x26, 0x28, 0x82, 0x1e, 0x44, 0xe5, 0xaa, 0xb4, 0x56, 0x9b, 0x1c, 0x82, 0xc4, 0x6e, 0x9c, 0xf7, 0xce, 0x1c, 0x62, 0x0, 0x53, 0x2e, 0xc4, 0x18, 0x9c, 0x62, 0x3, 0xb8, 0xf6, 0xf1, 0x8e, 0x3f, 0xf9, 0x3, 0xd8, 0xa6, 0xdc, 0x20, 0x27, 0x8b, 0x3b, 0x90, 0x52, 0x43, 0x83, 0x50, 0xb, 0xf9, 0xb, 0xd3, 0xd1, 0xe9, 0xed, 0x5c, 0x6c, 0xaa, 0xfe, 0x1d, 0xf7, 0x9e, 0x7f, 0x1, 0x89, 0x5c, 0xa, 0x6b, 0x1f, 0xe5, 0xca, 0x60, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char vslider_grabber_hl_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0xc3,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x17,0x2a,0x29,0x3a,0x69,0x69,0x5b,0xa6,0xa5,0x61,0xb3,0xbc,0x63,0xb7,0xc8,0x65,0xbb,0xca,0x60,0xaf,0xb1,0x48,0x83,0x83,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0xf,0xf,0x55,0x9b,0x9a,0x60,0xb2,0xbd,0x5e,0xb1,0xcd,0x61,0xb3,0xc2,0x0,0x0,0x0,0x27,0x48,0x47,0x62,0xb4,0xbd,0x51,0x93,0x92,0x68,0xc0,0xcf,0x0,0x0,0x0,0x56,0x9d,0x9c,0x68,0xc1,0xcf,0x2d,0x52,0x52,0x63,0xb7,0xbf,0x52,0x96,0x95,0x62,0xb3,0xbf,0x5e,0xb0,0xcd,0x0,0x0,0x0,0x3,0x5,0x5,0x36,0x63,0x63,0x63,0xb4,0xb6,0x60,0xb1,0xbc,0x63,0xb7,0xc7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x55,0xa3,0xc8,0x4f,0x98,0xc4,0x4b,0x93,0xc2,0x4c,0x94,0xc2,0x54,0xa2,0xc8,0x5a,0xab,0xcb,0x4e,0x97,0xc4,0x49,0x8f,0xc0,0x47,0x8c,0xbf,0x48,0x8e,0xc0,0x52,0x9e,0xc6,0x51,0x9d,0xc6,0x5a,0xac,0xcc,0x53,0x9f,0xc7,0x4d,0x96,0xc3,0x4b,0x92,0xc2,0xff,0xff,0xff,0x76,0xbd,0x27,0x7a,0x0,0x0,0x0,0x1,0x74,0x52,0x4e,0x53,0x0,0x40,0xe6,0xd8,0x66,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x0,0x88,0x5,0x1d,0x48,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe1,0x1,0x12,0x1,0x36,0x11,0x34,0xd2,0xf,0x93,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x48,0x49,0x44,0x41,0x54,0x18,0xd3,0x63,0x60,0xa0,0x12,0x10,0x14,0xe0,0xe7,0xe3,0x45,0xe2,0x4b,0x9a,0x18,0x1b,0x19,0x1a,0x48,0x88,0x8b,0xc1,0xe4,0x4d,0x2c,0x2d,0x80,0xc0,0xdc,0xcc,0x54,0x6,0x22,0x20,0x60,0x6c,0x1,0x1,0xe6,0x56,0x72,0x68,0x2,0xd6,0x8a,0xa8,0x5a,0x6c,0x94,0x11,0x86,0xda,0xdb,0xd9,0xaa,0xa9,0xaa,0x20,0x59,0xab,0xa3,0xad,0xc5,0x40,0x3d,0x0,0x0,0xbf,0x8e,0xc,0xed,0xed,0xc7,0x67,0x72,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char vslider_grabber_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xb7, 0xff, 0x88, 0x5, 0x1d, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe1, 0x1, 0x12, 0x1, 0x36, 0x8, 0x50, 0xb9, 0xa7, 0x53, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0xf6, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0xbd, 0x90, 0xb1, 0x4a, 0x42, 0x51, 0x0, 0x86, 0xbf, 0x73, 0x8e, 0x71, 0xe5, 0x9a, 0x5c, 0x41, 0xd0, 0x66, 0x6b, 0x33, 0x1c, 0x7c, 0x80, 0xa0, 0xa5, 0x17, 0x8, 0xa2, 0x2d, 0x84, 0xf0, 0x1, 0xa2, 0x25, 0xf1, 0x9, 0x9a, 0x1c, 0xda, 0x5b, 0xb2, 0x47, 0xa8, 0xa5, 0xc1, 0xa0, 0x51, 0x88, 0xa2, 0x29, 0xa, 0xc1, 0x84, 0x8, 0x43, 0xf4, 0x96, 0x17, 0xcf, 0xed, 0xde, 0x73, 0x9c, 0xcc, 0x5c, 0xda, 0xea, 0x9f, 0x3f, 0xfe, 0x9f, 0xef, 0x87, 0x3f, 0x8f, 0x0, 0x40, 0xe1, 0xe2, 0x91, 0x42, 0x10, 0x32, 0xe6, 0x3, 0x8d, 0xc1, 0xce, 0x1, 0x45, 0xb6, 0xba, 0xbb, 0xba, 0xed, 0x95, 0x8c, 0xd0, 0x7d, 0xff, 0xe1, 0xee, 0xe2, 0xb6, 0xdd, 0x79, 0x61, 0xc4, 0xd7, 0xc, 0x48, 0x57, 0x2b, 0xeb, 0xb5, 0x28, 0xaf, 0x1, 0xc5, 0x12, 0x4e, 0xac, 0x7b, 0x6f, 0x57, 0x27, 0x8d, 0xcf, 0xe, 0x1, 0x56, 0x1, 0xb9, 0x9d, 0xba, 0x28, 0x6, 0x18, 0xc, 0x31, 0x21, 0x5a, 0xda, 0x4c, 0xb6, 0xbc, 0xb9, 0x35, 0x7c, 0xea, 0xbd, 0x13, 0x4a, 0x20, 0xe5, 0x95, 0xf4, 0x6c, 0x12, 0x30, 0x84, 0xf8, 0x44, 0x6b, 0xfb, 0xcd, 0x83, 0x3d, 0x1c, 0xf9, 0x8b, 0x80, 0x4a, 0xba, 0x88, 0x4, 0x30, 0x1e, 0xdd, 0x3b, 0x1b, 0xf1, 0x77, 0x87, 0x24, 0x81, 0x8b, 0x79, 0x3e, 0x3b, 0x6a, 0x5d, 0x33, 0x51, 0x80, 0x2d, 0x38, 0x2b, 0x65, 0xb5, 0x6c, 0x91, 0x28, 0x92, 0xa4, 0xad, 0xec, 0x76, 0xcf, 0x8f, 0xf, 0x1f, 0xdb, 0xc, 0x31, 0xb, 0x9a, 0xb1, 0xd0, 0x3, 0xfb, 0xda, 0x3a, 0xbd, 0xbc, 0x89, 0xfa, 0xf8, 0x73, 0xcd, 0x9f, 0x47, 0x45, 0x4, 0xf8, 0x4, 0x18, 0xfe, 0x2f, 0x53, 0x8, 0x62, 0x5c, 0xcf, 0x1f, 0x5f, 0xcb, 0x2c, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char vslider_tick_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x4,0x4,0x3,0x0,0x0,0x0,0x75,0x9a,0xa2,0xdf,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x1e,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x81,0xa2,0xad,0x8c,0xac,0xb8,0x38,0x55,0x5f,0x82,0x82,0x82,0x8d,0x8d,0x8d,0x98,0x98,0x98,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0xff,0xff,0xff,0xe1,0x56,0x59,0xc8,0x0,0x0,0x0,0x9,0x74,0x52,0x4e,0x53,0x0,0x0,0x0,0x0,0x79,0x79,0x79,0x31,0x1c,0x18,0xed,0xfe,0x2b,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x9,0xf1,0xd9,0xa5,0xec,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x1d,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0x80,0x1,0xd7,0x44,0x5,0x6,0x6,0xe6,0x92,0x30,0x86,0xf2,0x62,0x3,0x20,0xa3,0xbd,0x1c,0x2e,0x3,0x0,0x3f,0xce,0x3,0xaf,0xf9,0x94,0x50,0x96,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char vslider_grabber_disabled_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe1, 0x7, 0xa, 0x13, 0x2e, 0x39, 0x86, 0x33, 0xc2, 0xfe, 0x0, 0x0, 0x0, 0x1d, 0x69, 0x54, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x0, 0x0, 0x0, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x64, 0x2e, 0x65, 0x7, 0x0, 0x0, 0x0, 0xb7, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x63, 0x60, 0xa0, 0x13, 0x60, 0x66, 0xe0, 0x65, 0x90, 0x61, 0x50, 0x67, 0xd0, 0x60, 0x50, 0x62, 0x10, 0x67, 0xe0, 0x2, 0xf2, 0x19, 0x51, 0xa5, 0xc5, 0x8c, 0xf3, 0x5c, 0xf, 0xfa, 0xbc, 0xf7, 0xfe, 0xe0, 0x71, 0xdb, 0x71, 0xbd, 0x66, 0xaa, 0xa0, 0x21, 0x83, 0x8, 0x3, 0x2b, 0x42, 0x1, 0xaf, 0x71, 0x9e, 0xe7, 0xb, 0xf7, 0xff, 0x2e, 0x40, 0xe8, 0xfa, 0xdf, 0xe3, 0xbf, 0xf7, 0x1f, 0x8f, 0x7, 0x36, 0x73, 0xd8, 0x74, 0x18, 0xb8, 0x61, 0xe6, 0xc8, 0xb8, 0x1e, 0x74, 0xff, 0xef, 0x4, 0x87, 0xce, 0x40, 0x65, 0x5e, 0xff, 0x3d, 0x6e, 0xcb, 0xf8, 0x3, 0xcd, 0x61, 0x1, 0x29, 0x50, 0xf7, 0x79, 0xef, 0x82, 0xa4, 0x0, 0xa2, 0xc8, 0xed, 0xbf, 0xdf, 0x17, 0xcb, 0x62, 0xa0, 0x29, 0x78, 0x14, 0x7c, 0xb7, 0xad, 0x65, 0xe0, 0xc1, 0x69, 0x85, 0xe7, 0x1d, 0x85, 0x50, 0x6, 0x31, 0x88, 0x15, 0x48, 0x8e, 0x74, 0xf9, 0xef, 0xfe, 0xdf, 0xfb, 0x9f, 0xe7, 0x3, 0xab, 0xa9, 0x40, 0x47, 0xf2, 0xc0, 0x1c, 0x89, 0xe4, 0x4d, 0xf7, 0x7b, 0xee, 0x47, 0xd5, 0x53, 0x98, 0x34, 0x18, 0x84, 0x91, 0xbd, 0x89, 0x1c, 0x50, 0x2a, 0xc, 0x52, 0x40, 0x9d, 0x4c, 0xc, 0xf4, 0x4, 0x0, 0xf1, 0x9, 0x63, 0x9b, 0x3e, 0x2a, 0x19, 0x52, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char vsplit_bg_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x1,0x3,0x0,0x0,0x0,0xfe,0xc1,0x2c,0xc8,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x6,0x50,0x4c,0x54,0x45,0x27,0x27,0x29,0xff,0xff,0xff,0x11,0xab,0xb9,0xf3,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x1,0xff,0x2,0x2d,0xde,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0xb,0x49,0x44,0x41,0x54,0x8,0xd7,0x63,0x60,0x40,0x5,0x0,0x0,0x10,0x0,0x1,0xa1,0xc5,0x21,0xc1,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char vslider_grabber_hl_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0xc3, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x17, 0x2a, 0x29, 0x3a, 0x69, 0x69, 0x5b, 0xa6, 0xa5, 0x61, 0xb3, 0xbc, 0x63, 0xb7, 0xc8, 0x65, 0xbb, 0xca, 0x60, 0xaf, 0xb1, 0x48, 0x83, 0x83, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0xf, 0xf, 0x55, 0x9b, 0x9a, 0x60, 0xb2, 0xbd, 0x5e, 0xb1, 0xcd, 0x61, 0xb3, 0xc2, 0x0, 0x0, 0x0, 0x27, 0x48, 0x47, 0x62, 0xb4, 0xbd, 0x51, 0x93, 0x92, 0x68, 0xc0, 0xcf, 0x0, 0x0, 0x0, 0x56, 0x9d, 0x9c, 0x68, 0xc1, 0xcf, 0x2d, 0x52, 0x52, 0x63, 0xb7, 0xbf, 0x52, 0x96, 0x95, 0x62, 0xb3, 0xbf, 0x5e, 0xb0, 0xcd, 0x0, 0x0, 0x0, 0x3, 0x5, 0x5, 0x36, 0x63, 0x63, 0x63, 0xb4, 0xb6, 0x60, 0xb1, 0xbc, 0x63, 0xb7, 0xc7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55, 0xa3, 0xc8, 0x4f, 0x98, 0xc4, 0x4b, 0x93, 0xc2, 0x4c, 0x94, 0xc2, 0x54, 0xa2, 0xc8, 0x5a, 0xab, 0xcb, 0x4e, 0x97, 0xc4, 0x49, 0x8f, 0xc0, 0x47, 0x8c, 0xbf, 0x48, 0x8e, 0xc0, 0x52, 0x9e, 0xc6, 0x51, 0x9d, 0xc6, 0x5a, 0xac, 0xcc, 0x53, 0x9f, 0xc7, 0x4d, 0x96, 0xc3, 0x4b, 0x92, 0xc2, 0xff, 0xff, 0xff, 0x76, 0xbd, 0x27, 0x7a, 0x0, 0x0, 0x0, 0x1, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x40, 0xe6, 0xd8, 0x66, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x0, 0x88, 0x5, 0x1d, 0x48, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe1, 0x1, 0x12, 0x1, 0x36, 0x11, 0x34, 0xd2, 0xf, 0x93, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x48, 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x63, 0x60, 0xa0, 0x12, 0x10, 0x14, 0xe0, 0xe7, 0xe3, 0x45, 0xe2, 0x4b, 0x9a, 0x18, 0x1b, 0x19, 0x1a, 0x48, 0x88, 0x8b, 0xc1, 0xe4, 0x4d, 0x2c, 0x2d, 0x80, 0xc0, 0xdc, 0xcc, 0x54, 0x6, 0x22, 0x20, 0x60, 0x6c, 0x1, 0x1, 0xe6, 0x56, 0x72, 0x68, 0x2, 0xd6, 0x8a, 0xa8, 0x5a, 0x6c, 0x94, 0x11, 0x86, 0xda, 0xdb, 0xd9, 0xaa, 0xa9, 0xaa, 0x20, 0x59, 0xab, 0xa3, 0xad, 0xc5, 0x40, 0x3d, 0x0, 0x0, 0xbf, 0x8e, 0xc, 0xed, 0xed, 0xc7, 0x67, 0x72, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char vsplitter_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x40,0x0,0x0,0x0,0x8,0x8,0x0,0x0,0x0,0x0,0x6c,0x9,0xa6,0x3,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x2,0x74,0x52,0x4e,0x53,0x0,0x0,0x76,0x93,0xcd,0x38,0x0,0x0,0x0,0x2,0x62,0x4b,0x47,0x44,0x0,0xff,0x87,0x8f,0xcc,0xbf,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0x1f,0x49,0x44,0x41,0x54,0x28,0xcf,0x63,0x60,0xa0,0x10,0x30,0x33,0x2c,0x10,0x3d,0x47,0x9,0x66,0x66,0x10,0xbd,0xf6,0x98,0x22,0x3c,0xe0,0x60,0x18,0x84,0x1,0x0,0x59,0x34,0x6a,0x2d,0x64,0xeb,0x72,0x24,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char vslider_tick_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x4, 0x4, 0x3, 0x0, 0x0, 0x0, 0x75, 0x9a, 0xa2, 0xdf, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x1e, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x81, 0xa2, 0xad, 0x8c, 0xac, 0xb8, 0x38, 0x55, 0x5f, 0x82, 0x82, 0x82, 0x8d, 0x8d, 0x8d, 0x98, 0x98, 0x98, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0xff, 0xff, 0xff, 0xe1, 0x56, 0x59, 0xc8, 0x0, 0x0, 0x0, 0x9, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x0, 0x0, 0x79, 0x79, 0x79, 0x31, 0x1c, 0x18, 0xed, 0xfe, 0x2b, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x9, 0xf1, 0xd9, 0xa5, 0xec, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x1d, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x80, 0x1, 0xd7, 0x44, 0x5, 0x6, 0x6, 0xe6, 0x92, 0x30, 0x86, 0xf2, 0x62, 0x3, 0x20, 0xa3, 0xbd, 0x1c, 0x2e, 0x3, 0x0, 0x3f, 0xce, 0x3, 0xaf, 0xf9, 0x94, 0x50, 0x96, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - -static const unsigned char window_resizer_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x8,0x19,0x11,0x33,0x13,0xaa,0xc0,0xf,0x5f,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x2f,0x49,0x44,0x41,0x54,0x38,0xcb,0x63,0x60,0x18,0x5,0x24,0x81,0x17,0x2f,0x5e,0xf4,0xa3,0x8b,0x31,0x91,0xa2,0xb9,0xb9,0xb9,0x99,0x7c,0x9b,0xb3,0xb3,0xb3,0xfb,0x87,0x81,0x66,0x6c,0x81,0x48,0x92,0x66,0xa2,0x5c,0x43,0x91,0xe6,0x11,0xa,0x0,0x73,0x5b,0x34,0x19,0x10,0xa0,0xb6,0x7d,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char vsplit_bg_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x1, 0x3, 0x0, 0x0, 0x0, 0xfe, 0xc1, 0x2c, 0xc8, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x6, 0x50, 0x4c, 0x54, 0x45, 0x27, 0x27, 0x29, 0xff, 0xff, 0xff, 0x11, 0xab, 0xb9, 0xf3, 0x0, 0x0, 0x0, 0x1, 0x62, 0x4b, 0x47, 0x44, 0x1, 0xff, 0x2, 0x2d, 0xde, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0xb, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x40, 0x5, 0x0, 0x0, 0x10, 0x0, 0x1, 0xa1, 0xc5, 0x21, 0xc1, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; +static const unsigned char vsplitter_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x8, 0x8, 0x0, 0x0, 0x0, 0x0, 0x6c, 0x9, 0xa6, 0x3, 0x0, 0x0, 0x0, 0x4, 0x67, 0x41, 0x4d, 0x41, 0x0, 0x0, 0xb1, 0x8f, 0xb, 0xfc, 0x61, 0x5, 0x0, 0x0, 0x0, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x0, 0x0, 0x7a, 0x26, 0x0, 0x0, 0x80, 0x84, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0x80, 0xe8, 0x0, 0x0, 0x75, 0x30, 0x0, 0x0, 0xea, 0x60, 0x0, 0x0, 0x3a, 0x98, 0x0, 0x0, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x0, 0x0, 0x0, 0x2, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x76, 0x93, 0xcd, 0x38, 0x0, 0x0, 0x0, 0x2, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x6, 0x16, 0x12, 0x2b, 0x5, 0x39, 0x1a, 0x32, 0x39, 0x0, 0x0, 0x0, 0x1f, 0x49, 0x44, 0x41, 0x54, 0x28, 0xcf, 0x63, 0x60, 0xa0, 0x10, 0x30, 0x33, 0x2c, 0x10, 0x3d, 0x47, 0x9, 0x66, 0x66, 0x10, 0xbd, 0xf6, 0x98, 0x22, 0x3c, 0xe0, 0x60, 0x18, 0x84, 0x1, 0x0, 0x59, 0x34, 0x6a, 0x2d, 0x64, 0xeb, 0x72, 0x24, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xc9, 0xad, 0xc8, 0x52, 0x0, 0x0, 0x0, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0, 0x32, 0x30, 0x31, 0x36, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x32, 0x54, 0x32, 0x30, 0x3a, 0x33, 0x39, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0xb8, 0xf0, 0x70, 0xee, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 +}; +static const unsigned char window_resizer_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x8, 0x19, 0x11, 0x33, 0x13, 0xaa, 0xc0, 0xf, 0x5f, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x0, 0x2f, 0x49, 0x44, 0x41, 0x54, 0x38, 0xcb, 0x63, 0x60, 0x18, 0x5, 0x24, 0x81, 0x17, 0x2f, 0x5e, 0xf4, 0xa3, 0x8b, 0x31, 0x91, 0xa2, 0xb9, 0xb9, 0xb9, 0x99, 0x7c, 0x9b, 0xb3, 0xb3, 0xb3, 0xfb, 0x87, 0x81, 0x66, 0x6c, 0x81, 0x48, 0x92, 0x66, 0xa2, 0x5c, 0x43, 0x91, 0xe6, 0x11, 0xa, 0x0, 0x73, 0x5b, 0x34, 0x19, 0x10, 0xa0, 0xb6, 0x7d, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 +}; - - +// shaders block diff --git a/scene/resources/default_theme/vslider_grabber_disabled.png b/scene/resources/default_theme/vslider_grabber_disabled.png Binary files differnew file mode 100644 index 000000000..c830359f4 --- /dev/null +++ b/scene/resources/default_theme/vslider_grabber_disabled.png diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp index 3fbfbc705..fc0d80a9b 100644 --- a/scene/resources/dynamic_font.cpp +++ b/scene/resources/dynamic_font.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -42,10 +43,10 @@ bool DynamicFontData::CacheID::operator<(CacheID right) const { return false; } -Ref<DynamicFontAtSize> DynamicFontData::_get_dynamic_font_at_size(CacheID p_id) { +Ref<DynamicFontAtSize> DynamicFontData::_get_dynamic_font_at_size(CacheID p_cache_id) { - if (size_cache.has(p_id)) { - return Ref<DynamicFontAtSize>(size_cache[p_id]); + if (size_cache.has(p_cache_id)) { + return Ref<DynamicFontAtSize>(size_cache[p_cache_id]); } Ref<DynamicFontAtSize> dfas; @@ -54,8 +55,8 @@ Ref<DynamicFontAtSize> DynamicFontData::_get_dynamic_font_at_size(CacheID p_id) dfas->font = Ref<DynamicFontData>(this); - size_cache[p_id] = dfas.ptr(); - dfas->id = p_id; + size_cache[p_cache_id] = dfas.ptr(); + dfas->id = p_cache_id; dfas->_load(); return dfas; @@ -337,7 +338,7 @@ float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharT cpos.y += ch->v_align; ERR_FAIL_COND_V(ch->texture_idx < -1 || ch->texture_idx >= fb->textures.size(), 0); if (ch->texture_idx != -1) - VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, ch->rect.size), fb->textures[ch->texture_idx].texture->get_rid(), ch->rect, p_modulate); + VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, ch->rect.size), fb->textures[ch->texture_idx].texture->get_rid(), ch->rect, p_modulate, false, RID(), false); advance = ch->advance; used_fallback = true; break; @@ -359,7 +360,7 @@ float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharT cpos.y += c->v_align; ERR_FAIL_COND_V(c->texture_idx < -1 || c->texture_idx >= textures.size(), 0); if (c->texture_idx != -1) - VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, c->rect.size), textures[c->texture_idx].texture->get_rid(), c->rect, p_modulate); + VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, c->rect.size), textures[c->texture_idx].texture->get_rid(), c->rect, p_modulate, false, RID(), false); advance = c->advance; //textures[c->texture_idx].texture->draw(p_canvas_item,Vector2()); } @@ -568,7 +569,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) { //blit to image and texture { - Image img(tex.texture_size, tex.texture_size, 0, Image::FORMAT_LA8, tex.imgdata); + Ref<Image> img = memnew(Image(tex.texture_size, tex.texture_size, 0, Image::FORMAT_LA8, tex.imgdata)); if (tex.texture.is_null()) { tex.texture.instance(); @@ -860,8 +861,8 @@ void DynamicFont::_get_property_list(List<PropertyInfo> *p_list) const { void DynamicFont::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_font_data", "data:DynamicFontData"), &DynamicFont::set_font_data); - ClassDB::bind_method(D_METHOD("get_font_data:DynamicFontData"), &DynamicFont::get_font_data); + ClassDB::bind_method(D_METHOD("set_font_data", "data"), &DynamicFont::set_font_data); + ClassDB::bind_method(D_METHOD("get_font_data"), &DynamicFont::get_font_data); ClassDB::bind_method(D_METHOD("set_size", "data"), &DynamicFont::set_size); ClassDB::bind_method(D_METHOD("get_size"), &DynamicFont::get_size); @@ -873,9 +874,9 @@ void DynamicFont::_bind_methods() { ClassDB::bind_method(D_METHOD("set_spacing", "type", "value"), &DynamicFont::set_spacing); ClassDB::bind_method(D_METHOD("get_spacing", "type"), &DynamicFont::get_spacing); - ClassDB::bind_method(D_METHOD("add_fallback", "data:DynamicFontData"), &DynamicFont::add_fallback); - ClassDB::bind_method(D_METHOD("set_fallback", "idx", "data:DynamicFontData"), &DynamicFont::set_fallback); - ClassDB::bind_method(D_METHOD("get_fallback:DynamicFontData", "idx"), &DynamicFont::get_fallback); + ClassDB::bind_method(D_METHOD("add_fallback", "data"), &DynamicFont::add_fallback); + ClassDB::bind_method(D_METHOD("set_fallback", "idx", "data"), &DynamicFont::set_fallback); + ClassDB::bind_method(D_METHOD("get_fallback", "idx"), &DynamicFont::get_fallback); ClassDB::bind_method(D_METHOD("remove_fallback", "idx"), &DynamicFont::remove_fallback); ClassDB::bind_method(D_METHOD("get_fallback_count"), &DynamicFont::get_fallback_count); diff --git a/scene/resources/dynamic_font.h b/scene/resources/dynamic_font.h index 4243ab2c0..9024761b9 100644 --- a/scene/resources/dynamic_font.h +++ b/scene/resources/dynamic_font.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -71,7 +72,7 @@ private: friend class DynamicFont; - Ref<DynamicFontAtSize> _get_dynamic_font_at_size(CacheID p_cache); + Ref<DynamicFontAtSize> _get_dynamic_font_at_size(CacheID p_cache_id); protected: static void _bind_methods(); diff --git a/scene/resources/dynamic_font_stb.cpp b/scene/resources/dynamic_font_stb.cpp index 7b62ccc36..8efad94b9 100644 --- a/scene/resources/dynamic_font_stb.cpp +++ b/scene/resources/dynamic_font_stb.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,7 +33,6 @@ #define STB_TRUETYPE_IMPLEMENTATION #include "os/file_access.h" -#include "stb_truetype.h" void DynamicFontData::lock() { @@ -386,8 +386,8 @@ DynamicFontAtSize::~DynamicFontAtSize() { void DynamicFont::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_font_data", "data:DynamicFontData"), &DynamicFont::set_font_data); - ClassDB::bind_method(D_METHOD("get_font_data:DynamicFontData"), &DynamicFont::get_font_data); + ClassDB::bind_method(D_METHOD("set_font_data", "data"), &DynamicFont::set_font_data); + ClassDB::bind_method(D_METHOD("get_font_data"), &DynamicFont::get_font_data); ClassDB::bind_method(D_METHOD("set_size", "data"), &DynamicFont::set_size); ClassDB::bind_method(D_METHOD("get_size"), &DynamicFont::get_size); diff --git a/scene/resources/dynamic_font_stb.h b/scene/resources/dynamic_font_stb.h index 0c17e3a8b..a2c081a92 100644 --- a/scene/resources/dynamic_font_stb.h +++ b/scene/resources/dynamic_font_stb.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,7 +34,8 @@ #include "font.h" #include "io/resource_loader.h" -#include "stb_truetype.h" + +#include "thirdparty/misc/stb_truetype.h" class DynamicFontAtSize; class DynamicFont; diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index b134d8052..0bf6a50d9 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -27,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "environment.h" -#include "global_config.h" +#include "project_settings.h" #include "servers/visual_server.h" #include "texture.h" @@ -43,21 +44,21 @@ void Environment::set_background(BGMode p_bg) { _change_notify(); } -void Environment::set_skybox(const Ref<SkyBox> &p_skybox) { +void Environment::set_sky(const Ref<Sky> &p_sky) { - bg_skybox = p_skybox; + bg_sky = p_sky; RID sb_rid; - if (bg_skybox.is_valid()) - sb_rid = bg_skybox->get_rid(); + if (bg_sky.is_valid()) + sb_rid = bg_sky->get_rid(); - VS::get_singleton()->environment_set_skybox(environment, sb_rid); + VS::get_singleton()->environment_set_sky(environment, sb_rid); } -void Environment::set_skybox_scale(float p_scale) { +void Environment::set_sky_scale(float p_scale) { - bg_skybox_scale = p_scale; - VS::get_singleton()->environment_set_skybox_scale(environment, p_scale); + bg_sky_scale = p_scale; + VS::get_singleton()->environment_set_sky_scale(environment, p_scale); } void Environment::set_bg_color(const Color &p_color) { @@ -78,31 +79,31 @@ void Environment::set_canvas_max_layer(int p_max_layer) { void Environment::set_ambient_light_color(const Color &p_color) { ambient_color = p_color; - VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, ambient_energy, ambient_skybox_contribution); + VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, ambient_energy, ambient_sky_contribution); } void Environment::set_ambient_light_energy(float p_energy) { ambient_energy = p_energy; - VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, ambient_energy, ambient_skybox_contribution); + VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, ambient_energy, ambient_sky_contribution); } -void Environment::set_ambient_light_skybox_contribution(float p_energy) { +void Environment::set_ambient_light_sky_contribution(float p_energy) { - ambient_skybox_contribution = p_energy; - VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, ambient_energy, ambient_skybox_contribution); + ambient_sky_contribution = p_energy; + VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, ambient_energy, ambient_sky_contribution); } Environment::BGMode Environment::get_background() const { return bg_mode; } -Ref<SkyBox> Environment::get_skybox() const { +Ref<Sky> Environment::get_sky() const { - return bg_skybox; + return bg_sky; } -float Environment::get_skybox_scale() const { +float Environment::get_sky_scale() const { - return bg_skybox_scale; + return bg_sky_scale; } Color Environment::get_bg_color() const { @@ -125,9 +126,9 @@ float Environment::get_ambient_light_energy() const { return ambient_energy; } -float Environment::get_ambient_light_skybox_contribution() const { +float Environment::get_ambient_light_sky_contribution() const { - return ambient_skybox_contribution; + return ambient_sky_contribution; } void Environment::set_tonemapper(ToneMapper p_tone_mapper) { @@ -166,6 +167,7 @@ void Environment::set_tonemap_auto_exposure(bool p_enabled) { tonemap_auto_exposure = p_enabled; VS::get_singleton()->environment_set_tonemap(environment, VS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); + _change_notify(); } bool Environment::get_tonemap_auto_exposure() const { @@ -216,6 +218,7 @@ void Environment::set_adjustment_enable(bool p_enable) { adjustment_enabled = p_enable; VS::get_singleton()->environment_set_adjustment(environment, adjustment_enabled, adjustment_brightness, adjustment_contrast, adjustment_saturation, adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID()); + _change_notify(); } bool Environment::is_adjustment_enabled() const { @@ -265,29 +268,56 @@ Ref<Texture> Environment::get_adjustment_color_correction() const { void Environment::_validate_property(PropertyInfo &property) const { - if (property.name == "background/skybox" || property.name == "background/skybox_scale" || property.name == "ambient_light/skybox_contribution") { - if (bg_mode != BG_SKYBOX) { + if (property.name == "background_sky" || property.name == "background_sky_scale" || property.name == "ambient_light/sky_contribution") { + if (bg_mode != BG_SKY) { property.usage = PROPERTY_USAGE_NOEDITOR; } } - if (property.name == "background/color") { + if (property.name == "background_color") { if (bg_mode != BG_COLOR) { property.usage = PROPERTY_USAGE_NOEDITOR; } } - if (property.name == "background/canvas_max_layer") { + if (property.name == "background_canvas_max_layer") { if (bg_mode != BG_CANVAS) { property.usage = PROPERTY_USAGE_NOEDITOR; } } + + static const char *hide_prefixes[] = { + "fog_", + "auto_exposure_", + "ss_reflections_", + "ssao_", + "dof_blur_far_", + "dof_blur_near_", + "glow_", + "adjustment_", + NULL + + }; + + const char **prefixes = hide_prefixes; + while (*prefixes) { + String prefix = String(*prefixes); + + String enabled = prefix + "enabled"; + if (property.name.begins_with(prefix) && property.name != enabled && !bool(get(enabled))) { + property.usage = PROPERTY_USAGE_NOEDITOR; + return; + } + + prefixes++; + } } void Environment::set_ssr_enabled(bool p_enable) { ssr_enabled = p_enable; - VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_accel, ssr_fade, ssr_depth_tolerance, ssr_smooth, ssr_roughness); + VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance, ssr_roughness); + _change_notify(); } bool Environment::is_ssr_enabled() const { @@ -298,57 +328,47 @@ bool Environment::is_ssr_enabled() const { void Environment::set_ssr_max_steps(int p_steps) { ssr_max_steps = p_steps; - VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_accel, ssr_fade, ssr_depth_tolerance, ssr_smooth, ssr_roughness); + VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance, ssr_roughness); } int Environment::get_ssr_max_steps() const { return ssr_max_steps; } -void Environment::set_ssr_accel(float p_accel) { +void Environment::set_ssr_fade_in(float p_fade_in) { - ssr_accel = p_accel; - VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_accel, ssr_fade, ssr_depth_tolerance, ssr_smooth, ssr_roughness); + ssr_fade_in = p_fade_in; + VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance, ssr_roughness); } -float Environment::get_ssr_accel() const { +float Environment::get_ssr_fade_in() const { - return ssr_accel; + return ssr_fade_in; } -void Environment::set_ssr_fade(float p_fade) { +void Environment::set_ssr_fade_out(float p_fade_out) { - ssr_fade = p_fade; - VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_accel, ssr_fade, ssr_depth_tolerance, ssr_smooth, ssr_roughness); + ssr_fade_out = p_fade_out; + VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance, ssr_roughness); } -float Environment::get_ssr_fade() const { +float Environment::get_ssr_fade_out() const { - return ssr_fade; + return ssr_fade_out; } void Environment::set_ssr_depth_tolerance(float p_depth_tolerance) { ssr_depth_tolerance = p_depth_tolerance; - VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_accel, ssr_fade, ssr_depth_tolerance, ssr_smooth, ssr_roughness); + VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance, ssr_roughness); } float Environment::get_ssr_depth_tolerance() const { return ssr_depth_tolerance; } -void Environment::set_ssr_smooth(bool p_enable) { - - ssr_smooth = p_enable; - VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_accel, ssr_fade, ssr_depth_tolerance, ssr_smooth, ssr_roughness); -} -bool Environment::is_ssr_smooth() const { - - return ssr_smooth; -} - void Environment::set_ssr_rough(bool p_enable) { ssr_roughness = p_enable; - VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_accel, ssr_fade, ssr_depth_tolerance, ssr_smooth, ssr_roughness); + VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance, ssr_roughness); } bool Environment::is_ssr_rough() const { @@ -359,6 +379,7 @@ void Environment::set_ssao_enabled(bool p_enable) { ssao_enabled = p_enable; VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, ssao_blur); + _change_notify(); } bool Environment::is_ssao_enabled() const { @@ -451,7 +472,8 @@ bool Environment::is_ssao_blur_enabled() const { void Environment::set_glow_enabled(bool p_enabled) { glow_enabled = p_enabled; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_treshold, glow_hdr_bleed_treshold, glow_bicubic_upscale); + VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_bicubic_upscale); + _change_notify(); } bool Environment::is_glow_enabled() const { @@ -468,7 +490,7 @@ void Environment::set_glow_level(int p_level, bool p_enabled) { else glow_levels &= ~(1 << p_level); - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_treshold, glow_hdr_bleed_treshold, glow_bicubic_upscale); + VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_bicubic_upscale); } bool Environment::is_glow_level_enabled(int p_level) const { @@ -481,7 +503,7 @@ void Environment::set_glow_intensity(float p_intensity) { glow_intensity = p_intensity; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_treshold, glow_hdr_bleed_treshold, glow_bicubic_upscale); + VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_bicubic_upscale); } float Environment::get_glow_intensity() const { @@ -491,18 +513,18 @@ float Environment::get_glow_intensity() const { void Environment::set_glow_strength(float p_strength) { glow_strength = p_strength; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_treshold, glow_hdr_bleed_treshold, glow_bicubic_upscale); + VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_bicubic_upscale); } float Environment::get_glow_strength() const { return glow_strength; } -void Environment::set_glow_bloom(float p_treshold) { +void Environment::set_glow_bloom(float p_threshold) { - glow_bloom = p_treshold; + glow_bloom = p_threshold; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_treshold, glow_hdr_bleed_treshold, glow_bicubic_upscale); + VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_bicubic_upscale); } float Environment::get_glow_bloom() const { @@ -513,29 +535,29 @@ void Environment::set_glow_blend_mode(GlowBlendMode p_mode) { glow_blend_mode = p_mode; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_treshold, glow_hdr_bleed_treshold, glow_bicubic_upscale); + VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_bicubic_upscale); } Environment::GlowBlendMode Environment::get_glow_blend_mode() const { return glow_blend_mode; } -void Environment::set_glow_hdr_bleed_treshold(float p_treshold) { +void Environment::set_glow_hdr_bleed_threshold(float p_threshold) { - glow_hdr_bleed_treshold = p_treshold; + glow_hdr_bleed_threshold = p_threshold; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_treshold, glow_hdr_bleed_treshold, glow_bicubic_upscale); + VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_bicubic_upscale); } -float Environment::get_glow_hdr_bleed_treshold() const { +float Environment::get_glow_hdr_bleed_threshold() const { - return glow_hdr_bleed_treshold; + return glow_hdr_bleed_threshold; } void Environment::set_glow_hdr_bleed_scale(float p_scale) { glow_hdr_bleed_scale = p_scale; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_treshold, glow_hdr_bleed_treshold, glow_bicubic_upscale); + VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_bicubic_upscale); } float Environment::get_glow_hdr_bleed_scale() const { @@ -545,7 +567,7 @@ float Environment::get_glow_hdr_bleed_scale() const { void Environment::set_glow_bicubic_upscale(bool p_enable) { glow_bicubic_upscale = p_enable; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_treshold, glow_hdr_bleed_treshold, glow_bicubic_upscale); + VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_bicubic_upscale); } bool Environment::is_glow_bicubic_upscale_enabled() const { @@ -557,6 +579,7 @@ void Environment::set_dof_blur_far_enabled(bool p_enable) { dof_blur_far_enabled = p_enable; VS::get_singleton()->environment_set_dof_blur_far(environment, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_far_amount, VS::EnvironmentDOFBlurQuality(dof_blur_far_quality)); + _change_notify(); } bool Environment::is_dof_blur_far_enabled() const { @@ -609,6 +632,7 @@ void Environment::set_dof_blur_near_enabled(bool p_enable) { dof_blur_near_enabled = p_enable; VS::get_singleton()->environment_set_dof_blur_near(environment, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_near_amount, VS::EnvironmentDOFBlurQuality(dof_blur_near_quality)); + _change_notify(); } bool Environment::is_dof_blur_near_enabled() const { @@ -660,39 +684,260 @@ Environment::DOFBlurQuality Environment::get_dof_blur_near_quality() const { return dof_blur_near_quality; } +void Environment::set_fog_enabled(bool p_enabled) { + + fog_enabled = p_enabled; + VS::get_singleton()->environment_set_fog(environment, fog_enabled, fog_color, fog_sun_color, fog_sun_amount); + _change_notify(); +} + +bool Environment::is_fog_enabled() const { + + return fog_enabled; +} + +void Environment::set_fog_color(const Color &p_color) { + + fog_color = p_color; + VS::get_singleton()->environment_set_fog(environment, fog_enabled, fog_color, fog_sun_color, fog_sun_amount); +} +Color Environment::get_fog_color() const { + + return fog_color; +} + +void Environment::set_fog_sun_color(const Color &p_color) { + + fog_sun_color = p_color; + VS::get_singleton()->environment_set_fog(environment, fog_enabled, fog_color, fog_sun_color, fog_sun_amount); +} +Color Environment::get_fog_sun_color() const { + + return fog_sun_color; +} + +void Environment::set_fog_sun_amount(float p_amount) { + + fog_sun_amount = p_amount; + VS::get_singleton()->environment_set_fog(environment, fog_enabled, fog_color, fog_sun_color, fog_sun_amount); +} +float Environment::get_fog_sun_amount() const { + + return fog_sun_amount; +} + +void Environment::set_fog_depth_enabled(bool p_enabled) { + + fog_depth_enabled = p_enabled; + VS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); +} +bool Environment::is_fog_depth_enabled() const { + + return fog_depth_enabled; +} + +void Environment::set_fog_depth_begin(float p_distance) { + + fog_depth_begin = p_distance; + VS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); +} +float Environment::get_fog_depth_begin() const { + + return fog_depth_begin; +} + +void Environment::set_fog_depth_curve(float p_curve) { + + fog_depth_curve = p_curve; + VS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); +} +float Environment::get_fog_depth_curve() const { + + return fog_depth_curve; +} + +void Environment::set_fog_transmit_enabled(bool p_enabled) { + + fog_transmit_enabled = p_enabled; + VS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); +} +bool Environment::is_fog_transmit_enabled() const { + + return fog_transmit_enabled; +} + +void Environment::set_fog_transmit_curve(float p_curve) { + + fog_transmit_curve = p_curve; + VS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); +} +float Environment::get_fog_transmit_curve() const { + + return fog_transmit_curve; +} + +void Environment::set_fog_height_enabled(bool p_enabled) { + + fog_height_enabled = p_enabled; + VS::get_singleton()->environment_set_fog_height(environment, fog_height_enabled, fog_height_min, fog_height_max, fog_height_curve); +} +bool Environment::is_fog_height_enabled() const { + + return fog_height_enabled; +} + +void Environment::set_fog_height_min(float p_distance) { + + fog_height_min = p_distance; + VS::get_singleton()->environment_set_fog_height(environment, fog_height_enabled, fog_height_min, fog_height_max, fog_height_curve); +} +float Environment::get_fog_height_min() const { + + return fog_height_min; +} + +void Environment::set_fog_height_max(float p_distance) { + + fog_height_max = p_distance; + VS::get_singleton()->environment_set_fog_height(environment, fog_height_enabled, fog_height_min, fog_height_max, fog_height_curve); +} +float Environment::get_fog_height_max() const { + + return fog_height_max; +} + +void Environment::set_fog_height_curve(float p_distance) { + + fog_height_curve = p_distance; + VS::get_singleton()->environment_set_fog_height(environment, fog_height_enabled, fog_height_min, fog_height_max, fog_height_curve); +} +float Environment::get_fog_height_curve() const { + + return fog_height_curve; +} + void Environment::_bind_methods() { ClassDB::bind_method(D_METHOD("set_background", "mode"), &Environment::set_background); - ClassDB::bind_method(D_METHOD("set_skybox", "skybox:CubeMap"), &Environment::set_skybox); - ClassDB::bind_method(D_METHOD("set_skybox_scale", "scale"), &Environment::set_skybox_scale); + ClassDB::bind_method(D_METHOD("set_sky", "sky"), &Environment::set_sky); + ClassDB::bind_method(D_METHOD("set_sky_scale", "scale"), &Environment::set_sky_scale); ClassDB::bind_method(D_METHOD("set_bg_color", "color"), &Environment::set_bg_color); ClassDB::bind_method(D_METHOD("set_bg_energy", "energy"), &Environment::set_bg_energy); ClassDB::bind_method(D_METHOD("set_canvas_max_layer", "layer"), &Environment::set_canvas_max_layer); ClassDB::bind_method(D_METHOD("set_ambient_light_color", "color"), &Environment::set_ambient_light_color); ClassDB::bind_method(D_METHOD("set_ambient_light_energy", "energy"), &Environment::set_ambient_light_energy); - ClassDB::bind_method(D_METHOD("set_ambient_light_skybox_contribution", "energy"), &Environment::set_ambient_light_skybox_contribution); + ClassDB::bind_method(D_METHOD("set_ambient_light_sky_contribution", "energy"), &Environment::set_ambient_light_sky_contribution); ClassDB::bind_method(D_METHOD("get_background"), &Environment::get_background); - ClassDB::bind_method(D_METHOD("get_skybox:CubeMap"), &Environment::get_skybox); - ClassDB::bind_method(D_METHOD("get_skybox_scale"), &Environment::get_skybox_scale); + ClassDB::bind_method(D_METHOD("get_sky"), &Environment::get_sky); + ClassDB::bind_method(D_METHOD("get_sky_scale"), &Environment::get_sky_scale); ClassDB::bind_method(D_METHOD("get_bg_color"), &Environment::get_bg_color); ClassDB::bind_method(D_METHOD("get_bg_energy"), &Environment::get_bg_energy); ClassDB::bind_method(D_METHOD("get_canvas_max_layer"), &Environment::get_canvas_max_layer); ClassDB::bind_method(D_METHOD("get_ambient_light_color"), &Environment::get_ambient_light_color); ClassDB::bind_method(D_METHOD("get_ambient_light_energy"), &Environment::get_ambient_light_energy); - ClassDB::bind_method(D_METHOD("get_ambient_light_skybox_contribution"), &Environment::get_ambient_light_skybox_contribution); + ClassDB::bind_method(D_METHOD("get_ambient_light_sky_contribution"), &Environment::get_ambient_light_sky_contribution); ADD_GROUP("Background", "background_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "background_mode", PROPERTY_HINT_ENUM, "Clear Color,Custom Color,Skybox,Canvas,Keep"), "set_background", "get_background"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "background_skybox", PROPERTY_HINT_RESOURCE_TYPE, "SkyBox"), "set_skybox", "get_skybox"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "background_skybox_scale", PROPERTY_HINT_RANGE, "0,32,0.01"), "set_skybox_scale", "get_skybox_scale"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "background_mode", PROPERTY_HINT_ENUM, "Clear Color,Custom Color,Sky,Canvas,Keep"), "set_background", "get_background"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "background_sky", PROPERTY_HINT_RESOURCE_TYPE, "Sky"), "set_sky", "get_sky"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "background_sky_scale", PROPERTY_HINT_RANGE, "0,32,0.01"), "set_sky_scale", "get_sky_scale"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "background_color"), "set_bg_color", "get_bg_color"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "background_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_bg_energy", "get_bg_energy"); ADD_PROPERTY(PropertyInfo(Variant::INT, "background_canvas_max_layer", PROPERTY_HINT_RANGE, "-1000,1000,1"), "set_canvas_max_layer", "get_canvas_max_layer"); ADD_GROUP("Ambient Light", "ambient_light_"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ambient_light_color"), "set_ambient_light_color", "get_ambient_light_color"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "ambient_light_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_ambient_light_energy", "get_ambient_light_energy"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ambient_light_skybox_contribution", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ambient_light_skybox_contribution", "get_ambient_light_skybox_contribution"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "ambient_light_sky_contribution", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ambient_light_sky_contribution", "get_ambient_light_sky_contribution"); + + ClassDB::bind_method(D_METHOD("set_fog_enabled", "enabled"), &Environment::set_fog_enabled); + ClassDB::bind_method(D_METHOD("is_fog_enabled"), &Environment::is_fog_enabled); + + ClassDB::bind_method(D_METHOD("set_fog_color", "color"), &Environment::set_fog_color); + ClassDB::bind_method(D_METHOD("get_fog_color"), &Environment::get_fog_color); + + ClassDB::bind_method(D_METHOD("set_fog_sun_color", "color"), &Environment::set_fog_sun_color); + ClassDB::bind_method(D_METHOD("get_fog_sun_color"), &Environment::get_fog_sun_color); + + ClassDB::bind_method(D_METHOD("set_fog_sun_amount", "amount"), &Environment::set_fog_sun_amount); + ClassDB::bind_method(D_METHOD("get_fog_sun_amount"), &Environment::get_fog_sun_amount); + + ClassDB::bind_method(D_METHOD("set_fog_depth_enabled", "enabled"), &Environment::set_fog_depth_enabled); + ClassDB::bind_method(D_METHOD("is_fog_depth_enabled"), &Environment::is_fog_depth_enabled); + + ClassDB::bind_method(D_METHOD("set_fog_depth_begin", "distance"), &Environment::set_fog_depth_begin); + ClassDB::bind_method(D_METHOD("get_fog_depth_begin"), &Environment::get_fog_depth_begin); + + ClassDB::bind_method(D_METHOD("set_fog_depth_curve", "curve"), &Environment::set_fog_depth_curve); + ClassDB::bind_method(D_METHOD("get_fog_depth_curve"), &Environment::get_fog_depth_curve); + + ClassDB::bind_method(D_METHOD("set_fog_transmit_enabled", "enabled"), &Environment::set_fog_transmit_enabled); + ClassDB::bind_method(D_METHOD("is_fog_transmit_enabled"), &Environment::is_fog_transmit_enabled); + + ClassDB::bind_method(D_METHOD("set_fog_transmit_curve", "curve"), &Environment::set_fog_transmit_curve); + ClassDB::bind_method(D_METHOD("get_fog_transmit_curve"), &Environment::get_fog_transmit_curve); + + ClassDB::bind_method(D_METHOD("set_fog_height_enabled", "enabled"), &Environment::set_fog_height_enabled); + ClassDB::bind_method(D_METHOD("is_fog_height_enabled"), &Environment::is_fog_height_enabled); + + ClassDB::bind_method(D_METHOD("set_fog_height_min", "height"), &Environment::set_fog_height_min); + ClassDB::bind_method(D_METHOD("get_fog_height_min"), &Environment::get_fog_height_min); + + ClassDB::bind_method(D_METHOD("set_fog_height_max", "height"), &Environment::set_fog_height_max); + ClassDB::bind_method(D_METHOD("get_fog_height_max"), &Environment::get_fog_height_max); + + ClassDB::bind_method(D_METHOD("set_fog_height_curve", "curve"), &Environment::set_fog_height_curve); + ClassDB::bind_method(D_METHOD("get_fog_height_curve"), &Environment::get_fog_height_curve); + + ADD_GROUP("Fog", "fog_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_enabled"), "set_fog_enabled", "is_fog_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "fog_color"), "set_fog_color", "get_fog_color"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "fog_sun_color"), "set_fog_sun_color", "get_fog_sun_color"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_sun_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_fog_sun_amount", "get_fog_sun_amount"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_depth_enabled"), "set_fog_depth_enabled", "is_fog_depth_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_depth_begin", PROPERTY_HINT_RANGE, "0,4000,0.1"), "set_fog_depth_begin", "get_fog_depth_begin"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_depth_curve", PROPERTY_HINT_EXP_EASING), "set_fog_depth_curve", "get_fog_depth_curve"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_transmit_enabled"), "set_fog_transmit_enabled", "is_fog_transmit_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_transmit_curve", PROPERTY_HINT_EXP_EASING), "set_fog_transmit_curve", "get_fog_transmit_curve"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_height_enabled"), "set_fog_height_enabled", "is_fog_height_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_height_min", PROPERTY_HINT_RANGE, "-4000,4000,0.1"), "set_fog_height_min", "get_fog_height_min"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_height_max", PROPERTY_HINT_RANGE, "-4000,4000,0.1"), "set_fog_height_max", "get_fog_height_max"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_height_curve", PROPERTY_HINT_EXP_EASING), "set_fog_height_curve", "get_fog_height_curve"); + + ClassDB::bind_method(D_METHOD("set_tonemapper", "mode"), &Environment::set_tonemapper); + ClassDB::bind_method(D_METHOD("get_tonemapper"), &Environment::get_tonemapper); + + ClassDB::bind_method(D_METHOD("set_tonemap_exposure", "exposure"), &Environment::set_tonemap_exposure); + ClassDB::bind_method(D_METHOD("get_tonemap_exposure"), &Environment::get_tonemap_exposure); + + ClassDB::bind_method(D_METHOD("set_tonemap_white", "white"), &Environment::set_tonemap_white); + ClassDB::bind_method(D_METHOD("get_tonemap_white"), &Environment::get_tonemap_white); + + ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure", "auto_exposure"), &Environment::set_tonemap_auto_exposure); + ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure"), &Environment::get_tonemap_auto_exposure); + + ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_max", "exposure_max"), &Environment::set_tonemap_auto_exposure_max); + ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_max"), &Environment::get_tonemap_auto_exposure_max); + + ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_min", "exposure_min"), &Environment::set_tonemap_auto_exposure_min); + ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_min"), &Environment::get_tonemap_auto_exposure_min); + + ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_speed", "exposure_speed"), &Environment::set_tonemap_auto_exposure_speed); + ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_speed"), &Environment::get_tonemap_auto_exposure_speed); + + ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_grey", "exposure_grey"), &Environment::set_tonemap_auto_exposure_grey); + ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_grey"), &Environment::get_tonemap_auto_exposure_grey); + + ADD_GROUP("Tonemap", "tonemap_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "tonemap_mode", PROPERTY_HINT_ENUM, "Linear,Reindhart,Filmic,Aces"), "set_tonemapper", "get_tonemapper"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "tonemap_exposure", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_exposure", "get_tonemap_exposure"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "tonemap_white", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_white", "get_tonemap_white"); + ADD_GROUP("Auto Exposure", "auto_exposure_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_exposure_enabled"), "set_tonemap_auto_exposure", "get_tonemap_auto_exposure"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "auto_exposure_scale", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_tonemap_auto_exposure_grey", "get_tonemap_auto_exposure_grey"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "auto_exposure_min_luma", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_auto_exposure_min", "get_tonemap_auto_exposure_min"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "auto_exposure_max_luma", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_auto_exposure_max", "get_tonemap_auto_exposure_max"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "auto_exposure_speed", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_tonemap_auto_exposure_speed", "get_tonemap_auto_exposure_speed"); ClassDB::bind_method(D_METHOD("set_ssr_enabled", "enabled"), &Environment::set_ssr_enabled); ClassDB::bind_method(D_METHOD("is_ssr_enabled"), &Environment::is_ssr_enabled); @@ -700,28 +945,24 @@ void Environment::_bind_methods() { ClassDB::bind_method(D_METHOD("set_ssr_max_steps", "max_steps"), &Environment::set_ssr_max_steps); ClassDB::bind_method(D_METHOD("get_ssr_max_steps"), &Environment::get_ssr_max_steps); - ClassDB::bind_method(D_METHOD("set_ssr_accel", "accel"), &Environment::set_ssr_accel); - ClassDB::bind_method(D_METHOD("get_ssr_accel"), &Environment::get_ssr_accel); + ClassDB::bind_method(D_METHOD("set_ssr_fade_in", "fade_in"), &Environment::set_ssr_fade_in); + ClassDB::bind_method(D_METHOD("get_ssr_fade_in"), &Environment::get_ssr_fade_in); - ClassDB::bind_method(D_METHOD("set_ssr_fade", "fade"), &Environment::set_ssr_fade); - ClassDB::bind_method(D_METHOD("get_ssr_fade"), &Environment::get_ssr_fade); + ClassDB::bind_method(D_METHOD("set_ssr_fade_out", "fade_out"), &Environment::set_ssr_fade_out); + ClassDB::bind_method(D_METHOD("get_ssr_fade_out"), &Environment::get_ssr_fade_out); ClassDB::bind_method(D_METHOD("set_ssr_depth_tolerance", "depth_tolerance"), &Environment::set_ssr_depth_tolerance); ClassDB::bind_method(D_METHOD("get_ssr_depth_tolerance"), &Environment::get_ssr_depth_tolerance); - ClassDB::bind_method(D_METHOD("set_ssr_smooth", "smooth"), &Environment::set_ssr_smooth); - ClassDB::bind_method(D_METHOD("is_ssr_smooth"), &Environment::is_ssr_smooth); - ClassDB::bind_method(D_METHOD("set_ssr_rough", "rough"), &Environment::set_ssr_rough); ClassDB::bind_method(D_METHOD("is_ssr_rough"), &Environment::is_ssr_rough); ADD_GROUP("SS Reflections", "ss_reflections_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ss_reflections_enabled"), "set_ssr_enabled", "is_ssr_enabled"); ADD_PROPERTY(PropertyInfo(Variant::INT, "ss_reflections_max_steps", PROPERTY_HINT_RANGE, "1,512,1"), "set_ssr_max_steps", "get_ssr_max_steps"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ss_reflections_accel", PROPERTY_HINT_RANGE, "0,4,0.01"), "set_ssr_accel", "get_ssr_accel"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ss_reflections_fade", PROPERTY_HINT_EXP_EASING), "set_ssr_fade", "get_ssr_fade"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "ss_reflections_fade_in", PROPERTY_HINT_EXP_EASING), "set_ssr_fade_in", "get_ssr_fade_in"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "ss_reflections_fade_out", PROPERTY_HINT_EXP_EASING), "set_ssr_fade_out", "get_ssr_fade_out"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "ss_reflections_depth_tolerance", PROPERTY_HINT_RANGE, "0.1,128,0.1"), "set_ssr_depth_tolerance", "get_ssr_depth_tolerance"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ss_reflections_accel_smooth"), "set_ssr_smooth", "is_ssr_smooth"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ss_reflections_roughness"), "set_ssr_rough", "is_ssr_rough"); ClassDB::bind_method(D_METHOD("set_ssao_enabled", "enabled"), &Environment::set_ssao_enabled); @@ -799,7 +1040,7 @@ void Environment::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "dof_blur_far_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_dof_blur_far_amount", "get_dof_blur_far_amount"); ADD_PROPERTY(PropertyInfo(Variant::INT, "dof_blur_far_quality", PROPERTY_HINT_ENUM, "Low,Medium,High"), "set_dof_blur_far_quality", "get_dof_blur_far_quality"); - ADD_GROUP("DOF Far Near", "dof_blur_near_"); + ADD_GROUP("DOF Near Blur", "dof_blur_near_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_near_enabled"), "set_dof_blur_near_enabled", "is_dof_blur_near_enabled"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "dof_blur_near_distance", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01"), "set_dof_blur_near_distance", "get_dof_blur_near_distance"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "dof_blur_near_transition", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01"), "set_dof_blur_near_transition", "get_dof_blur_near_transition"); @@ -824,8 +1065,8 @@ void Environment::_bind_methods() { ClassDB::bind_method(D_METHOD("set_glow_blend_mode", "mode"), &Environment::set_glow_blend_mode); ClassDB::bind_method(D_METHOD("get_glow_blend_mode"), &Environment::get_glow_blend_mode); - ClassDB::bind_method(D_METHOD("set_glow_hdr_bleed_treshold", "treshold"), &Environment::set_glow_hdr_bleed_treshold); - ClassDB::bind_method(D_METHOD("get_glow_hdr_bleed_treshold"), &Environment::get_glow_hdr_bleed_treshold); + ClassDB::bind_method(D_METHOD("set_glow_hdr_bleed_threshold", "threshold"), &Environment::set_glow_hdr_bleed_threshold); + ClassDB::bind_method(D_METHOD("get_glow_hdr_bleed_threshold"), &Environment::get_glow_hdr_bleed_threshold); ClassDB::bind_method(D_METHOD("set_glow_hdr_bleed_scale", "scale"), &Environment::set_glow_hdr_bleed_scale); ClassDB::bind_method(D_METHOD("get_glow_hdr_bleed_scale"), &Environment::get_glow_hdr_bleed_scale); @@ -847,45 +1088,10 @@ void Environment::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_strength", PROPERTY_HINT_RANGE, "0.0,2.0,0.01"), "set_glow_strength", "get_glow_strength"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_bloom", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_glow_bloom", "get_glow_bloom"); ADD_PROPERTY(PropertyInfo(Variant::INT, "glow_blend_mode", PROPERTY_HINT_ENUM, "Additive,Screen,Softlight,Replace"), "set_glow_blend_mode", "get_glow_blend_mode"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_hdr_treshold", PROPERTY_HINT_RANGE, "0.0,4.0,0.01"), "set_glow_hdr_bleed_treshold", "get_glow_hdr_bleed_treshold"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_hdr_threshold", PROPERTY_HINT_RANGE, "0.0,4.0,0.01"), "set_glow_hdr_bleed_threshold", "get_glow_hdr_bleed_threshold"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_hdr_scale", PROPERTY_HINT_RANGE, "0.0,4.0,0.01"), "set_glow_hdr_bleed_scale", "get_glow_hdr_bleed_scale"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "glow_bicubic_upscale"), "set_glow_bicubic_upscale", "is_glow_bicubic_upscale_enabled"); - ClassDB::bind_method(D_METHOD("set_tonemapper", "mode"), &Environment::set_tonemapper); - ClassDB::bind_method(D_METHOD("get_tonemapper"), &Environment::get_tonemapper); - - ClassDB::bind_method(D_METHOD("set_tonemap_exposure", "exposure"), &Environment::set_tonemap_exposure); - ClassDB::bind_method(D_METHOD("get_tonemap_exposure"), &Environment::get_tonemap_exposure); - - ClassDB::bind_method(D_METHOD("set_tonemap_white", "white"), &Environment::set_tonemap_white); - ClassDB::bind_method(D_METHOD("get_tonemap_white"), &Environment::get_tonemap_white); - - ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure", "auto_exposure"), &Environment::set_tonemap_auto_exposure); - ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure"), &Environment::get_tonemap_auto_exposure); - - ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_max", "exposure_max"), &Environment::set_tonemap_auto_exposure_max); - ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_max"), &Environment::get_tonemap_auto_exposure_max); - - ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_min", "exposure_min"), &Environment::set_tonemap_auto_exposure_min); - ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_min"), &Environment::get_tonemap_auto_exposure_min); - - ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_speed", "exposure_speed"), &Environment::set_tonemap_auto_exposure_speed); - ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_speed"), &Environment::get_tonemap_auto_exposure_speed); - - ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_grey", "exposure_grey"), &Environment::set_tonemap_auto_exposure_grey); - ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_grey"), &Environment::get_tonemap_auto_exposure_grey); - - ADD_GROUP("Tonemap", "tonemap_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "tonemap_mode", PROPERTY_HINT_ENUM, "Linear,Reindhart,Filmic,Aces"), "set_tonemapper", "get_tonemapper"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "tonemap_exposure", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_exposure", "get_tonemap_exposure"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "tonemap_white", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_white", "get_tonemap_white"); - ADD_GROUP("Auto Exposure", "auto_exposure_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_expoure_enabled"), "set_tonemap_auto_exposure", "get_tonemap_auto_exposure"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "auto_expoure_scale", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_tonemap_auto_exposure_grey", "get_tonemap_auto_exposure_grey"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "auto_expoure_min_luma", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_auto_exposure_min", "get_tonemap_auto_exposure_min"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "auto_expoure_max_luma", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_auto_exposure_max", "get_tonemap_auto_exposure_max"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "auto_expoure_speed", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_tonemap_auto_exposure_speed", "get_tonemap_auto_exposure_speed"); - ClassDB::bind_method(D_METHOD("set_adjustment_enable", "enabled"), &Environment::set_adjustment_enable); ClassDB::bind_method(D_METHOD("is_adjustment_enabled"), &Environment::is_adjustment_enabled); @@ -908,12 +1114,10 @@ void Environment::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "adjustment_saturation", PROPERTY_HINT_RANGE, "0.01,8,0.01"), "set_adjustment_saturation", "get_adjustment_saturation"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "adjustment_color_correction", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_adjustment_color_correction", "get_adjustment_color_correction"); - GLOBAL_DEF("rendering/skybox/irradiance_cube_resolution", 256); - BIND_CONSTANT(BG_KEEP); BIND_CONSTANT(BG_CLEAR_COLOR); BIND_CONSTANT(BG_COLOR); - BIND_CONSTANT(BG_SKYBOX); + BIND_CONSTANT(BG_SKY); BIND_CONSTANT(BG_CANVAS); BIND_CONSTANT(BG_MAX); BIND_CONSTANT(GLOW_BLEND_MODE_ADDITIVE); @@ -931,12 +1135,14 @@ void Environment::_bind_methods() { Environment::Environment() { + environment = VS::get_singleton()->environment_create(); + bg_mode = BG_CLEAR_COLOR; - bg_skybox_scale = 1.0; + bg_sky_scale = 1.0; bg_energy = 1.0; bg_canvas_max_layer = 0; ambient_energy = 1.0; - ambient_skybox_contribution = 0; + ambient_sky_contribution = 1.0; tone_mapper = TONE_MAPPER_LINEAR; tonemap_exposure = 1.0; @@ -956,14 +1162,11 @@ Environment::Environment() { set_adjustment_enable(adjustment_enabled); //update - environment = VS::get_singleton()->environment_create(); - ssr_enabled = false; ssr_max_steps = 64; - ssr_accel = 0.04; - ssr_fade = 2.0; + ssr_fade_in = 0.15; + ssr_fade_out = 2.0; ssr_depth_tolerance = 0.2; - ssr_smooth = true; ssr_roughness = true; ssao_enabled = false; @@ -981,7 +1184,7 @@ Environment::Environment() { glow_strength = 1.0; glow_bloom = 0.0; glow_blend_mode = GLOW_BLEND_MODE_SOFTLIGHT; - glow_hdr_bleed_treshold = 1.0; + glow_hdr_bleed_threshold = 1.0; glow_hdr_bleed_scale = 2.0; glow_bicubic_upscale = false; @@ -996,6 +1199,27 @@ Environment::Environment() { dof_blur_near_transition = 1; dof_blur_near_amount = 0.1; dof_blur_near_quality = DOF_BLUR_QUALITY_MEDIUM; + + fog_enabled = false; + fog_color = Color(0.5, 0.5, 0.5); + fog_sun_color = Color(0.8, 0.8, 0.0); + fog_sun_amount = 0; + + fog_depth_enabled = true; + + fog_depth_begin = 10; + fog_depth_curve = 1; + + fog_transmit_enabled = false; + fog_transmit_curve = 1; + + fog_height_enabled = false; + fog_height_min = 0; + fog_height_max = 100; + fog_height_curve = 1; + + set_fog_color(Color(0.5, 0.6, 0.7)); + set_fog_sun_color(Color(1.0, 0.9, 0.7)); } Environment::~Environment() { diff --git a/scene/resources/environment.h b/scene/resources/environment.h index 3ac311f4a..3a6906aa2 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -43,7 +44,7 @@ public: BG_CLEAR_COLOR, BG_COLOR, - BG_SKYBOX, + BG_SKY, BG_CANVAS, BG_KEEP, BG_MAX @@ -73,14 +74,14 @@ private: RID environment; BGMode bg_mode; - Ref<SkyBox> bg_skybox; - float bg_skybox_scale; + Ref<Sky> bg_sky; + float bg_sky_scale; Color bg_color; float bg_energy; int bg_canvas_max_layer; Color ambient_color; float ambient_energy; - float ambient_skybox_contribution; + float ambient_sky_contribution; ToneMapper tone_mapper; float tonemap_exposure; @@ -99,10 +100,9 @@ private: bool ssr_enabled; int ssr_max_steps; - float ssr_accel; - float ssr_fade; + float ssr_fade_in; + float ssr_fade_out; float ssr_depth_tolerance; - bool ssr_smooth; bool ssr_roughness; bool ssao_enabled; @@ -121,7 +121,7 @@ private: float glow_strength; float glow_bloom; GlowBlendMode glow_blend_mode; - float glow_hdr_bleed_treshold; + float glow_hdr_bleed_threshold; float glow_hdr_bleed_scale; bool glow_bicubic_upscale; @@ -137,30 +137,47 @@ private: float dof_blur_near_amount; DOFBlurQuality dof_blur_near_quality; + bool fog_enabled; + Color fog_color; + Color fog_sun_color; + float fog_sun_amount; + + bool fog_depth_enabled; + float fog_depth_begin; + float fog_depth_curve; + + bool fog_transmit_enabled; + float fog_transmit_curve; + + bool fog_height_enabled; + float fog_height_min; + float fog_height_max; + float fog_height_curve; + protected: static void _bind_methods(); virtual void _validate_property(PropertyInfo &property) const; public: void set_background(BGMode p_bg); - void set_skybox(const Ref<SkyBox> &p_skybox); - void set_skybox_scale(float p_scale); + void set_sky(const Ref<Sky> &p_sky); + void set_sky_scale(float p_scale); void set_bg_color(const Color &p_color); void set_bg_energy(float p_energy); void set_canvas_max_layer(int p_max_layer); void set_ambient_light_color(const Color &p_color); void set_ambient_light_energy(float p_energy); - void set_ambient_light_skybox_contribution(float p_energy); + void set_ambient_light_sky_contribution(float p_energy); BGMode get_background() const; - Ref<SkyBox> get_skybox() const; - float get_skybox_scale() const; + Ref<Sky> get_sky() const; + float get_sky_scale() const; Color get_bg_color() const; float get_bg_energy() const; int get_canvas_max_layer() const; Color get_ambient_light_color() const; float get_ambient_light_energy() const; - float get_ambient_light_skybox_contribution() const; + float get_ambient_light_sky_contribution() const; void set_tonemapper(ToneMapper p_tone_mapper); ToneMapper get_tonemapper() const; @@ -207,18 +224,15 @@ public: void set_ssr_max_steps(int p_steps); int get_ssr_max_steps() const; - void set_ssr_accel(float p_accel); - float get_ssr_accel() const; + void set_ssr_fade_in(float p_fade_in); + float get_ssr_fade_in() const; - void set_ssr_fade(float p_transition); - float get_ssr_fade() const; + void set_ssr_fade_out(float p_fade_out); + float get_ssr_fade_out() const; void set_ssr_depth_tolerance(float p_depth_tolerance); float get_ssr_depth_tolerance() const; - void set_ssr_smooth(bool p_enable); - bool is_ssr_smooth() const; - void set_ssr_rough(bool p_enable); bool is_ssr_rough() const; @@ -261,14 +275,14 @@ public: void set_glow_strength(float p_strength); float get_glow_strength() const; - void set_glow_bloom(float p_treshold); + void set_glow_bloom(float p_threshold); float get_glow_bloom() const; void set_glow_blend_mode(GlowBlendMode p_mode); GlowBlendMode get_glow_blend_mode() const; - void set_glow_hdr_bleed_treshold(float p_treshold); - float get_glow_hdr_bleed_treshold() const; + void set_glow_hdr_bleed_threshold(float p_threshold); + float get_glow_hdr_bleed_threshold() const; void set_glow_hdr_bleed_scale(float p_scale); float get_glow_hdr_bleed_scale() const; @@ -306,6 +320,45 @@ public: void set_dof_blur_near_quality(DOFBlurQuality p_quality); DOFBlurQuality get_dof_blur_near_quality() const; + void set_fog_enabled(bool p_enabled); + bool is_fog_enabled() const; + + void set_fog_color(const Color &p_color); + Color get_fog_color() const; + + void set_fog_sun_color(const Color &p_color); + Color get_fog_sun_color() const; + + void set_fog_sun_amount(float p_amount); + float get_fog_sun_amount() const; + + void set_fog_depth_enabled(bool p_enabled); + bool is_fog_depth_enabled() const; + + void set_fog_depth_begin(float p_distance); + float get_fog_depth_begin() const; + + void set_fog_depth_curve(float p_curve); + float get_fog_depth_curve() const; + + void set_fog_transmit_enabled(bool p_enabled); + bool is_fog_transmit_enabled() const; + + void set_fog_transmit_curve(float p_curve); + float get_fog_transmit_curve() const; + + void set_fog_height_enabled(bool p_enabled); + bool is_fog_height_enabled() const; + + void set_fog_height_min(float p_distance); + float get_fog_height_min() const; + + void set_fog_height_max(float p_distance); + float get_fog_height_max() const; + + void set_fog_height_curve(float p_distance); + float get_fog_height_curve() const; + virtual RID get_rid() const; Environment(); diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 9f30474a2..035e514ea 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -119,8 +120,8 @@ PoolVector<int> BitmapFont::_get_chars() const { const Character *c = char_map.getptr(*key); chars.push_back(*key); chars.push_back(c->texture_idx); - chars.push_back(c->rect.pos.x); - chars.push_back(c->rect.pos.y); + chars.push_back(c->rect.position.x); + chars.push_back(c->rect.position.y); chars.push_back(c->rect.size.x); chars.push_back(c->rect.size.y); @@ -178,14 +179,14 @@ Vector<Variant> BitmapFont::_get_textures() const { return rtextures; } -Error BitmapFont::create_from_fnt(const String &p_string) { +Error BitmapFont::create_from_fnt(const String &p_file) { //fnt format used by angelcode bmfont //http://www.angelcode.com/products/bmfont/ - FileAccess *f = FileAccess::open(p_string, FileAccess::READ); + FileAccess *f = FileAccess::open(p_file, FileAccess::READ); if (!f) { - ERR_EXPLAIN("Can't open font: " + p_string); + ERR_EXPLAIN("Can't open font: " + p_file); ERR_FAIL_V(ERR_FILE_NOT_FOUND); } @@ -254,7 +255,7 @@ Error BitmapFont::create_from_fnt(const String &p_string) { if (keys.has("file")) { String file = keys["file"]; - file = p_string.get_base_dir() + "/" + file; + file = p_file.get_base_dir() + "/" + file; Ref<Texture> tex = ResourceLoader::load(file); if (tex.is_null()) { ERR_PRINT("Can't load font texture!"); @@ -271,9 +272,9 @@ Error BitmapFont::create_from_fnt(const String &p_string) { Rect2 rect; if (keys.has("x")) - rect.pos.x = keys["x"].to_int(); + rect.position.x = keys["x"].to_int(); if (keys.has("y")) - rect.pos.y = keys["y"].to_int(); + rect.position.y = keys["y"].to_int(); if (keys.has("width")) rect.size.width = keys["width"].to_int(); if (keys.has("height")) @@ -505,7 +506,7 @@ float BitmapFont::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_c cpos.y += c->v_align; ERR_FAIL_COND_V(c->texture_idx < -1 || c->texture_idx >= textures.size(), 0); if (c->texture_idx != -1) - VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, c->rect.size), textures[c->texture_idx]->get_rid(), c->rect, p_modulate); + VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, c->rect.size), textures[c->texture_idx]->get_rid(), c->rect, p_modulate, false, RID(), false); return get_char_size(p_char, p_next).width; } @@ -548,11 +549,11 @@ void BitmapFont::_bind_methods() { ClassDB::bind_method(D_METHOD("add_kerning_pair", "char_a", "char_b", "kerning"), &BitmapFont::add_kerning_pair); ClassDB::bind_method(D_METHOD("get_kerning_pair", "char_a", "char_b"), &BitmapFont::get_kerning_pair); - ClassDB::bind_method(D_METHOD("add_texture", "texture:Texture"), &BitmapFont::add_texture); + ClassDB::bind_method(D_METHOD("add_texture", "texture"), &BitmapFont::add_texture); ClassDB::bind_method(D_METHOD("add_char", "character", "texture", "rect", "align", "advance"), &BitmapFont::add_char, DEFVAL(Point2()), DEFVAL(-1)); ClassDB::bind_method(D_METHOD("get_texture_count"), &BitmapFont::get_texture_count); - ClassDB::bind_method(D_METHOD("get_texture:Texture", "idx"), &BitmapFont::get_texture); + ClassDB::bind_method(D_METHOD("get_texture", "idx"), &BitmapFont::get_texture); ClassDB::bind_method(D_METHOD("get_char_size", "char", "next"), &BitmapFont::get_char_size, DEFVAL(0)); diff --git a/scene/resources/font.h b/scene/resources/font.h index 332017684..a04ffbdd4 100644 --- a/scene/resources/font.h +++ b/scene/resources/font.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -65,7 +66,7 @@ public: class BitmapFont : public Font { GDCLASS(BitmapFont, Font); - RES_BASE_EXTENSION("fnt"); + RES_BASE_EXTENSION("font"); Vector<Ref<Texture> > textures; diff --git a/scene/resources/gibberish_stream.cpp b/scene/resources/gibberish_stream.cpp index fdc5bf01e..e2994f141 100644 --- a/scene/resources/gibberish_stream.cpp +++ b/scene/resources/gibberish_stream.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/gibberish_stream.h b/scene/resources/gibberish_stream.h index 257a1faeb..ebe61382e 100644 --- a/scene/resources/gibberish_stream.h +++ b/scene/resources/gibberish_stream.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 410f4962f..bc23a41ed 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,11 +30,36 @@ #include "material.h" #include "scene/scene_string_names.h" +void Material::set_next_pass(const Ref<Material> &p_pass) { + + if (next_pass == p_pass) + return; + + next_pass = p_pass; + RID next_pass_rid; + if (next_pass.is_valid()) + next_pass_rid = next_pass->get_rid(); + VS::get_singleton()->material_set_next_pass(material, next_pass_rid); +} + +Ref<Material> Material::get_next_pass() const { + + return next_pass; +} + RID Material::get_rid() const { return material; } +void Material::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_next_pass", "next_pass"), &Material::set_next_pass); + ClassDB::bind_method(D_METHOD("get_next_pass"), &Material::get_next_pass); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "next_pass", PROPERTY_HINT_RESOURCE_TYPE, "Material"), "set_next_pass", "get_next_pass"); +} + Material::Material() { material = VisualServer::get_singleton()->material_create(); @@ -44,14 +70,132 @@ Material::~Material() { VisualServer::get_singleton()->free(material); } +/////////////////////////////////// + +bool ShaderMaterial::_set(const StringName &p_name, const Variant &p_value) { + + if (p_name == SceneStringNames::get_singleton()->shader) { + set_shader(p_value); + return true; + } else { + + if (shader.is_valid()) { + + StringName pr = shader->remap_param(p_name); + if (!pr) { + String n = p_name; + if (n.find("param/") == 0) { //backwards compatibility + pr = n.substr(6, n.length()); + } + } + if (pr) { + VisualServer::get_singleton()->material_set_param(_get_material(), pr, p_value); + return true; + } + } + } + + return false; +} + +bool ShaderMaterial::_get(const StringName &p_name, Variant &r_ret) const { + + if (p_name == SceneStringNames::get_singleton()->shader) { + + r_ret = get_shader(); + return true; + + } else { + + if (shader.is_valid()) { + + StringName pr = shader->remap_param(p_name); + if (pr) { + r_ret = VisualServer::get_singleton()->material_get_param(_get_material(), pr); + return true; + } + } + } + + return false; +} + +void ShaderMaterial::_get_property_list(List<PropertyInfo> *p_list) const { + + p_list->push_back(PropertyInfo(Variant::OBJECT, "shader", PROPERTY_HINT_RESOURCE_TYPE, "Shader,ShaderGraph")); + + if (!shader.is_null()) { + + shader->get_param_list(p_list); + } +} + +void ShaderMaterial::set_shader(const Ref<Shader> &p_shader) { + + shader = p_shader; + + RID rid; + if (shader.is_valid()) + rid = shader->get_rid(); + + VS::get_singleton()->material_set_shader(_get_material(), rid); + _change_notify(); //properties for shader exposed + emit_changed(); +} + +Ref<Shader> ShaderMaterial::get_shader() const { + + return shader; +} + +void ShaderMaterial::set_shader_param(const StringName &p_param, const Variant &p_value) { + + VS::get_singleton()->material_set_param(_get_material(), p_param, p_value); +} + +Variant ShaderMaterial::get_shader_param(const StringName &p_param) const { + + return VS::get_singleton()->material_get_param(_get_material(), p_param); +} + +void ShaderMaterial::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_shader", "shader"), &ShaderMaterial::set_shader); + ClassDB::bind_method(D_METHOD("get_shader"), &ShaderMaterial::get_shader); + ClassDB::bind_method(D_METHOD("set_shader_param", "param", "value"), &ShaderMaterial::set_shader_param); + ClassDB::bind_method(D_METHOD("get_shader_param", "param"), &ShaderMaterial::get_shader_param); +} + +void ShaderMaterial::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { + + String f = p_function.operator String(); + if ((f == "get_shader_param" || f == "set_shader_param") && p_idx == 0) { + + if (shader.is_valid()) { + List<PropertyInfo> pl; + shader->get_param_list(&pl); + for (List<PropertyInfo>::Element *E = pl.front(); E; E = E->next()) { + r_options->push_back("\"" + E->get().name.replace_first("shader_param/", "") + "\""); + } + } + } + Resource::get_argument_options(p_function, p_idx, r_options); +} + +ShaderMaterial::ShaderMaterial() { +} + +ShaderMaterial::~ShaderMaterial() { +} + ///////////////////////////////// -Mutex *FixedSpatialMaterial::material_mutex = NULL; -SelfList<FixedSpatialMaterial>::List FixedSpatialMaterial::dirty_materials; -Map<FixedSpatialMaterial::MaterialKey, FixedSpatialMaterial::ShaderData> FixedSpatialMaterial::shader_map; -FixedSpatialMaterial::ShaderNames *FixedSpatialMaterial::shader_names = NULL; +Mutex *SpatialMaterial::material_mutex = NULL; +SelfList<SpatialMaterial>::List SpatialMaterial::dirty_materials; +Map<SpatialMaterial::MaterialKey, SpatialMaterial::ShaderData> SpatialMaterial::shader_map; +SpatialMaterial::ShaderNames *SpatialMaterial::shader_names = NULL; -void FixedSpatialMaterial::init_shaders() { +void SpatialMaterial::init_shaders() { #ifndef NO_THREADS material_mutex = Mutex::create(); @@ -62,7 +206,7 @@ void FixedSpatialMaterial::init_shaders() { shader_names->albedo = "albedo"; shader_names->specular = "specular"; shader_names->roughness = "roughness"; - shader_names->metalness = "metalness"; + shader_names->metallic = "metallic"; shader_names->emission = "emission"; shader_names->emission_energy = "emission_energy"; shader_names->normal_scale = "normal_scale"; @@ -71,34 +215,58 @@ void FixedSpatialMaterial::init_shaders() { shader_names->clearcoat = "clearcoat"; shader_names->clearcoat_gloss = "clearcoat_gloss"; shader_names->anisotropy = "anisotropy_ratio"; - shader_names->height_scale = "height_scale"; + shader_names->depth_scale = "depth_scale"; shader_names->subsurface_scattering_strength = "subsurface_scattering_strength"; shader_names->refraction = "refraction"; - shader_names->refraction_roughness = "refraction_roughness"; shader_names->point_size = "point_size"; shader_names->uv1_scale = "uv1_scale"; shader_names->uv1_offset = "uv1_offset"; shader_names->uv2_scale = "uv2_scale"; shader_names->uv2_offset = "uv2_offset"; + shader_names->uv1_blend_sharpness = "uv1_blend_sharpness"; + shader_names->uv2_blend_sharpness = "uv2_blend_sharpness"; + + shader_names->particle_h_frames = "particle_h_frames"; + shader_names->particle_v_frames = "particle_v_frames"; + shader_names->particles_anim_loop = "particles_anim_loop"; + shader_names->depth_min_layers = "depth_min_layers"; + shader_names->depth_max_layers = "depth_max_layers"; + + shader_names->grow = "grow"; + + shader_names->metallic_texture_channel = "metallic_texture_channel"; + shader_names->roughness_texture_channel = "roughness_texture_channel"; + shader_names->ao_texture_channel = "ao_texture_channel"; + shader_names->clearcoat_texture_channel = "clearcoat_texture_channel"; + shader_names->rim_texture_channel = "rim_texture_channel"; + shader_names->depth_texture_channel = "depth_texture_channel"; + shader_names->refraction_texture_channel = "refraction_texture_channel"; + shader_names->alpha_scissor_threshold = "alpha_scissor_threshold"; shader_names->texture_names[TEXTURE_ALBEDO] = "texture_albedo"; - shader_names->texture_names[TEXTURE_SPECULAR] = "texture_specular"; + shader_names->texture_names[TEXTURE_METALLIC] = "texture_metallic"; + shader_names->texture_names[TEXTURE_ROUGHNESS] = "texture_roughness"; shader_names->texture_names[TEXTURE_EMISSION] = "texture_emission"; shader_names->texture_names[TEXTURE_NORMAL] = "texture_normal"; shader_names->texture_names[TEXTURE_RIM] = "texture_rim"; shader_names->texture_names[TEXTURE_CLEARCOAT] = "texture_clearcoat"; shader_names->texture_names[TEXTURE_FLOWMAP] = "texture_flowmap"; shader_names->texture_names[TEXTURE_AMBIENT_OCCLUSION] = "texture_ambient_occlusion"; - shader_names->texture_names[TEXTURE_HEIGHT] = "texture_height"; + shader_names->texture_names[TEXTURE_DEPTH] = "texture_depth"; shader_names->texture_names[TEXTURE_SUBSURFACE_SCATTERING] = "texture_subsurface_scattering"; shader_names->texture_names[TEXTURE_REFRACTION] = "texture_refraction"; - shader_names->texture_names[TEXTURE_REFRACTION_ROUGHNESS] = "texture_refraction_roughness"; shader_names->texture_names[TEXTURE_DETAIL_MASK] = "texture_detail_mask"; shader_names->texture_names[TEXTURE_DETAIL_ALBEDO] = "texture_detail_albedo"; shader_names->texture_names[TEXTURE_DETAIL_NORMAL] = "texture_detail_normal"; } -void FixedSpatialMaterial::finish_shaders() { +Ref<SpatialMaterial> SpatialMaterial::materials_for_2d[SpatialMaterial::MAX_MATERIALS_FOR_2D]; + +void SpatialMaterial::finish_shaders() { + + for (int i = 0; i < MAX_MATERIALS_FOR_2D; i++) { + materials_for_2d[i].unref(); + } #ifndef NO_THREADS memdelete(material_mutex); @@ -107,7 +275,7 @@ void FixedSpatialMaterial::finish_shaders() { memdelete(shader_names); } -void FixedSpatialMaterial::_update_shader() { +void SpatialMaterial::_update_shader() { dirty_materials.remove(&element); @@ -135,7 +303,7 @@ void FixedSpatialMaterial::_update_shader() { //must create a shader! - String code = "render_mode "; + String code = "shader_type spatial;\nrender_mode "; switch (blend_mode) { case BLEND_MODE_MIX: code += "blend_mix"; break; case BLEND_MODE_ADD: code += "blend_add"; break; @@ -143,7 +311,12 @@ void FixedSpatialMaterial::_update_shader() { case BLEND_MODE_MUL: code += "blend_mul"; break; } - switch (depth_draw_mode) { + DepthDrawMode ddm = depth_draw_mode; + if (features[FEATURE_REFRACTION]) { + ddm = DEPTH_DRAW_ALWAYS; + } + + switch (ddm) { case DEPTH_DRAW_OPAQUE_ONLY: code += ",depth_draw_opaque"; break; case DEPTH_DRAW_ALWAYS: code += ",depth_draw_always"; break; case DEPTH_DRAW_DISABLED: code += ",depth_draw_never"; break; @@ -155,6 +328,20 @@ void FixedSpatialMaterial::_update_shader() { case CULL_FRONT: code += ",cull_front"; break; case CULL_DISABLED: code += ",cull_disabled"; break; } + switch (diffuse_mode) { + case DIFFUSE_LAMBERT: code += ",diffuse_lambert"; break; + case DIFFUSE_HALF_LAMBERT: code += ",diffuse_half_lambert"; break; + case DIFFUSE_OREN_NAYAR: code += ",diffuse_oren_nayar"; break; + case DIFFUSE_BURLEY: code += ",diffuse_burley"; break; + case DIFFUSE_TOON: code += ",diffuse_toon"; break; + } + switch (specular_mode) { + case SPECULAR_SCHLICK_GGX: code += ",specular_schlick_ggx"; break; + case SPECULAR_BLINN: code += ",specular_blinn"; break; + case SPECULAR_PHONG: code += ",specular_phong"; break; + case SPECULAR_TOON: code += ",specular_toon"; break; + case SPECULAR_DISABLED: code += ",specular_disabled"; break; + } if (flags[FLAG_UNSHADED]) { code += ",unshaded"; @@ -162,24 +349,37 @@ void FixedSpatialMaterial::_update_shader() { if (flags[FLAG_ONTOP]) { code += ",ontop"; } + if (flags[FLAG_USE_VERTEX_LIGHTING]) { + code += ",vertex_lighting"; + } + if (flags[FLAG_UV1_USE_TRIPLANAR] || flags[FLAG_UV2_USE_TRIPLANAR]) { + code += ",world_vertex_coords"; + } code += ";\n"; code += "uniform vec4 albedo : hint_color;\n"; code += "uniform sampler2D texture_albedo : hint_albedo;\n"; - if (specular_mode == SPECULAR_MODE_SPECULAR) { - code += "uniform vec4 specular : hint_color;\n"; - } else { - code += "uniform float metalness;\n"; + code += "uniform float specular;\n"; + code += "uniform float metallic;\n"; + if (grow_enabled) { + code += "uniform float grow;\n"; } + if (flags[FLAG_USE_ALPHA_SCISSOR]) { + code += "uniform float alpha_scissor_threshold;\n"; + } code += "uniform float roughness : hint_range(0,1);\n"; code += "uniform float point_size : hint_range(0,128);\n"; - code += "uniform sampler2D texture_specular : hint_white;\n"; - code += "uniform vec2 uv1_scale;\n"; - code += "uniform vec2 uv1_offset;\n"; - code += "uniform vec2 uv2_scale;\n"; - code += "uniform vec2 uv2_offset;\n"; + code += "uniform sampler2D texture_metallic : hint_white;\n"; + code += "uniform vec4 metallic_texture_channel;\n"; + code += "uniform sampler2D texture_roughness : hint_white;\n"; + code += "uniform vec4 roughness_texture_channel;\n"; + if (billboard_mode == BILLBOARD_PARTICLES) { + code += "uniform int particles_anim_h_frames;\n"; + code += "uniform int particles_anim_v_frames;\n"; + code += "uniform bool particles_anim_loop;\n"; + } if (features[FEATURE_EMISSION]) { @@ -188,6 +388,12 @@ void FixedSpatialMaterial::_update_shader() { code += "uniform float emission_energy;\n"; } + if (features[FEATURE_REFRACTION]) { + code += "uniform sampler2D texture_refraction;\n"; + code += "uniform float refraction : hint_range(-16,16);\n"; + code += "uniform vec4 refraction_texture_channel;\n"; + } + if (features[FEATURE_NORMAL_MAPPING]) { code += "uniform sampler2D texture_normal : hint_normal;\n"; code += "uniform float normal_scale : hint_range(-16,16);\n"; @@ -208,6 +414,7 @@ void FixedSpatialMaterial::_update_shader() { } if (features[FEATURE_AMBIENT_OCCLUSION]) { code += "uniform sampler2D texture_ambient_occlusion : hint_white;\n"; + code += "uniform vec4 ao_texture_channel;\n"; } if (features[FEATURE_DETAIL]) { @@ -222,6 +429,33 @@ void FixedSpatialMaterial::_update_shader() { code += "uniform sampler2D texture_subsurface_scattering : hint_white;\n"; } + if (features[FEATURE_DEPTH_MAPPING]) { + code += "uniform sampler2D texture_depth : hint_black;\n"; + code += "uniform float depth_scale;\n"; + code += "uniform int depth_min_layers;\n"; + code += "uniform int depth_max_layers;\n"; + } + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "varying vec3 uv1_world_pos;\n"; + } + if (flags[FLAG_UV2_USE_TRIPLANAR]) { + code += "varying vec3 uv2_world_pos;\n"; + } + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "uniform float uv1_blend_sharpness;\n"; + code += "varying vec3 uv1_power_normal;\n"; + } + + if (flags[FLAG_UV2_USE_TRIPLANAR]) { + code += "uniform float uv2_blend_sharpness;\n"; + code += "varying vec3 uv2_power_normal;\n"; + } + + code += "uniform vec3 uv1_scale;\n"; + code += "uniform vec3 uv1_offset;\n"; + code += "uniform vec3 uv2_scale;\n"; + code += "uniform vec3 uv2_offset;\n"; + code += "\n\n"; code += "void vertex() {\n"; @@ -234,19 +468,169 @@ void FixedSpatialMaterial::_update_shader() { code += "\tPOINT_SIZE=point_size;\n"; } - code += "\tUV=UV*uv1_scale+uv1_offset;\n"; - if (detail_uv == DETAIL_UV_2) { + + if (flags[FLAG_USE_VERTEX_LIGHTING]) { + + code += "\tROUGHNESS=roughness;\n"; + } + + if (!flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tUV=UV*uv1_scale.xy+uv1_offset.xy;\n"; + } + + switch (billboard_mode) { + case BILLBOARD_DISABLED: { + + } break; + case BILLBOARD_ENABLED: { + + code += "\tMODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0],CAMERA_MATRIX[1],CAMERA_MATRIX[2],WORLD_MATRIX[3]);\n"; + } break; + case BILLBOARD_FIXED_Y: { + code += "\tMODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0],WORLD_MATRIX[1],vec4(normalize(cross(CAMERA_MATRIX[0].xyz,WORLD_MATRIX[1].xyz)),0.0),WORLD_MATRIX[3]);\n"; + } break; + case BILLBOARD_PARTICLES: { + + //make billboard + code += "\tmat4 mat_world = mat4(normalize(CAMERA_MATRIX[0])*length(WORLD_MATRIX[0]),normalize(CAMERA_MATRIX[1])*length(WORLD_MATRIX[0]),normalize(CAMERA_MATRIX[2])*length(WORLD_MATRIX[2]),WORLD_MATRIX[3]);\n"; + //rotate by rotation + code += "\tmat_world = mat_world * mat4( vec4(cos(INSTANCE_CUSTOM.x),-sin(INSTANCE_CUSTOM.x),0.0,0.0), vec4(sin(INSTANCE_CUSTOM.x),cos(INSTANCE_CUSTOM.x),0.0,0.0),vec4(0.0,0.0,1.0,0.0),vec4(0.0,0.0,0.0,1.0));\n"; + //set modelview + code += "\tMODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat_world;\n"; + + //handle animation + code += "\tint particle_total_frames = particles_anim_h_frames * particles_anim_v_frames;\n"; + code += "\tint particle_frame = int(INSTANCE_CUSTOM.y * float(particle_total_frames));\n"; + code += "\tif (particles_anim_loop) particle_frame=clamp(particle_frame,0,particle_total_frames-1); else particle_frame=abs(particle_frame)%particle_total_frames;\n"; + //code += "\tUV /= vec2(float(particles_anim_h_frames),float(particles_anim_v_frames));\n"; + //code += "\tUV+= UV * vec2(float(particle_frame % particles_anim_h_frames),float(particle_frame / particles_anim_v_frames));\n"; + //handle rotation + // code += "\tmat4 rotation = mat4(" + } break; + } + + if (flags[FLAG_FIXED_SIZE]) { + + code += "\tif (PROJECTION_MATRIX[3][3] != 0.0) {\n"; + //orthogonal matrix, try to do about the same + //with viewport size + code += "\t\tfloat h = abs(1.0 / (2.0 * PROJECTION_MATRIX[1][1]));\n"; + code += "\t\tfloat sc = (h * 2.0); //consistent with Y-fov\n"; + code += "\t\tMODELVIEW_MATRIX[0]*=sc;\n"; + code += "\t\tMODELVIEW_MATRIX[1]*=sc;\n"; + code += "\t\tMODELVIEW_MATRIX[2]*=sc;\n"; + code += "\t} else {\n"; + //just scale by depth + code += "\t\tfloat sc = -(MODELVIEW_MATRIX)[3].z;\n"; + code += "\t\tMODELVIEW_MATRIX[0]*=sc;\n"; + code += "\t\tMODELVIEW_MATRIX[1]*=sc;\n"; + code += "\t\tMODELVIEW_MATRIX[2]*=sc;\n"; + code += "\t}\n"; + } + + if (detail_uv == DETAIL_UV_2 && !flags[FLAG_UV2_USE_TRIPLANAR]) { code += "\tUV2=UV2*uv2_scale+uv2_offset;\n"; } + if (flags[FLAG_UV1_USE_TRIPLANAR] || flags[FLAG_UV2_USE_TRIPLANAR]) { + //generate tangent and binormal in world space + code += "\tTANGENT = vec3(0.0,0.0,-1.0) * abs(NORMAL.x);\n"; + code += "\tTANGENT+= vec3(1.0,0.0,0.0) * abs(NORMAL.y);\n"; + code += "\tTANGENT+= vec3(1.0,0.0,0.0) * abs(NORMAL.z);\n"; + code += "\tTANGENT = normalize(TANGENT);\n"; + + code += "\tBINORMAL = vec3(0.0,1.0,0.0) * abs(NORMAL.x);\n"; + code += "\tBINORMAL+= vec3(0.0,0.0,-1.0) * abs(NORMAL.y);\n"; + code += "\tBINORMAL+= vec3(0.0,1.0,0.0) * abs(NORMAL.z);\n"; + code += "\tBINORMAL = normalize(BINORMAL);\n"; + } + + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + + code += "\tuv1_power_normal=pow(abs(NORMAL),vec3(uv1_blend_sharpness));\n"; + code += "\tuv1_power_normal/=dot(uv1_power_normal,vec3(1.0));\n"; + code += "\tuv1_world_pos = VERTEX * uv1_scale + uv1_offset;\n"; + code += "\tuv1_world_pos *= vec3(1.0,-1.0, 1.0);\n"; + } + + if (flags[FLAG_UV2_USE_TRIPLANAR]) { + + code += "\tuv2_power_normal=pow(abs(NORMAL), vec3(uv2_blend_sharpness));\n"; + code += "\tuv2_power_normal/=dot(uv2_power_normal,vec3(1.0));\n"; + code += "\tuv2_world_pos = VERTEX * uv2_scale + uv2_offset;\n"; + code += "\tuv2_world_pos *= vec3(1.0,-1.0, 1.0);\n"; + } + + if (grow_enabled) { + code += "\tVERTEX+=NORMAL*grow;\n"; + } code += "}\n"; code += "\n\n"; + if (flags[FLAG_UV1_USE_TRIPLANAR] || flags[FLAG_UV2_USE_TRIPLANAR]) { + code += "vec4 triplanar_texture(sampler2D p_sampler,vec3 p_weights,vec3 p_world_pos) {\n"; + code += "\tvec4 samp=vec4(0.0);\n"; + code += "\tsamp+= texture(p_sampler,p_world_pos.xy) * p_weights.z;\n"; + code += "\tsamp+= texture(p_sampler,p_world_pos.xz) * p_weights.y;\n"; + code += "\tsamp+= texture(p_sampler,p_world_pos.zy * vec2(-1.0,1.0)) * p_weights.x;\n"; + code += "\treturn samp;\n"; + code += "}\n"; + } + code += "\n\n"; code += "void fragment() {\n"; + if (!flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tvec2 base_uv = UV;\n"; + } + + if ((features[FEATURE_DETAIL] && detail_uv == DETAIL_UV_2) || (features[FEATURE_AMBIENT_OCCLUSION] && flags[FLAG_AO_ON_UV2])) { + code += "\tvec2 base_uv2 = UV2;\n"; + } + + if (features[FEATURE_DEPTH_MAPPING] && !flags[FLAG_UV1_USE_TRIPLANAR]) { //depthmap not supported with triplanar + code += "\t{\n"; + code += "\t\tvec3 view_dir = normalize(normalize(-VERTEX)*mat3(TANGENT,-BINORMAL,NORMAL));\n"; //binormal is negative due to mikktpsace + + if (deep_parallax) { + code += "\t\tfloat num_layers = mix(float(depth_max_layers),float(depth_min_layers), abs(dot(vec3(0.0, 0.0, 1.0), view_dir)));\n"; + code += "\t\tfloat layer_depth = 1.0 / num_layers;\n"; + code += "\t\tfloat current_layer_depth = 0.0;\n"; + code += "\t\tvec2 P = view_dir.xy * depth_scale;\n"; + code += "\t\tvec2 delta = P / num_layers;\n"; + code += "\t\tvec2 ofs = base_uv;\n"; + code += "\t\tfloat depth = texture(texture_depth, ofs).r;\n"; + code += "\t\tfloat current_depth = 0.0;\n"; + code += "\t\twhile(current_depth < depth) {\n"; + code += "\t\t\tofs -= delta;\n"; + code += "\t\t\tdepth = texture(texture_depth, ofs).r;\n"; + code += "\t\t\tcurrent_depth += layer_depth;\n"; + code += "\t\t}\n"; + code += "\t\tvec2 prev_ofs = ofs + delta;\n"; + code += "\t\tfloat after_depth = depth - current_depth;\n"; + code += "\t\tfloat before_depth = texture(texture_depth, prev_ofs).r - current_depth + layer_depth;\n"; + code += "\t\tfloat weight = after_depth / (after_depth - before_depth);\n"; + code += "\t\tofs = mix(ofs,prev_ofs,weight);\n"; + + } else { + code += "\t\tfloat depth = texture(texture_depth, base_uv).r;\n"; + code += "\t\tvec2 ofs = base_uv - view_dir.xy / view_dir.z * (depth * depth_scale);\n"; + } + + code += "\t\tbase_uv=ofs;\n"; + if (features[FEATURE_DETAIL] && detail_uv == DETAIL_UV_2) { + code += "\t\tbase_uv2-=ofs;\n"; + } + + code += "\t}\n"; + } + if (flags[FLAG_USE_POINT_SIZE]) { code += "\tvec4 albedo_tex = texture(texture_albedo,POINT_COORD);\n"; } else { - code += "\tvec4 albedo_tex = texture(texture_albedo,UV);\n"; + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tvec4 albedo_tex = triplanar_texture(texture_albedo,uv1_power_normal,uv1_world_pos);\n"; + } else { + code += "\tvec4 albedo_tex = texture(texture_albedo,base_uv);\n"; + } } if (flags[FLAG_ALBEDO_FROM_VERTEX_COLOR]) { @@ -254,52 +638,133 @@ void FixedSpatialMaterial::_update_shader() { } code += "\tALBEDO = albedo.rgb * albedo_tex.rgb;\n"; - if (features[FEATURE_TRANSPARENT]) { - code += "\tALPHA = albedo.a * albedo_tex.a;\n"; + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tfloat metallic_tex = dot(triplanar_texture(texture_metallic,uv1_power_normal,uv1_world_pos),metallic_texture_channel);\n"; + } else { + code += "\tfloat metallic_tex = dot(texture(texture_metallic,base_uv),metallic_texture_channel);\n"; } - - if (features[FEATURE_EMISSION]) { - code += "\tEMISSION = (emission.rgb+texture(texture_emission,UV).rgb)*emission_energy;\n"; + code += "\tMETALLIC = metallic_tex * metallic;\n"; + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tfloat roughness_tex = dot(triplanar_texture(texture_roughness,uv1_power_normal,uv1_world_pos),roughness_texture_channel);\n"; + } else { + code += "\tfloat roughness_tex = dot(texture(texture_roughness,base_uv),roughness_texture_channel);\n"; } + code += "\tROUGHNESS = roughness_tex * roughness;\n"; + code += "\tSPECULAR = specular;\n"; if (features[FEATURE_NORMAL_MAPPING]) { - code += "\tNORMALMAP = texture(texture_normal,UV).rgb;\n"; + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tNORMALMAP = triplanar_texture(texture_normal,uv1_power_normal,uv1_world_pos).rgb;\n"; + } else { + code += "\tNORMALMAP = texture(texture_normal,base_uv).rgb;\n"; + } code += "\tNORMALMAP_DEPTH = normal_scale;\n"; } + if (features[FEATURE_EMISSION]) { + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tvec3 emission_tex = triplanar_texture(texture_emission,uv1_power_normal,uv1_world_pos).rgb;\n"; + } else { + code += "\tvec3 emission_tex = texture(texture_emission,base_uv).rgb;\n"; + } + code += "\tEMISSION = (emission.rgb+emission_tex)*emission_energy;\n"; + } + + if (features[FEATURE_REFRACTION] && !flags[FLAG_UV1_USE_TRIPLANAR]) { //refraction not supported with triplanar + + if (features[FEATURE_NORMAL_MAPPING]) { + code += "\tvec3 ref_normal = normalize( mix(NORMAL,TANGENT * NORMALMAP.x + BINORMAL * NORMALMAP.y + NORMAL * NORMALMAP.z,NORMALMAP_DEPTH) ) * SIDE;\n"; + } else { + code += "\tvec3 ref_normal = NORMAL;\n"; + } + + code += "\tvec2 ref_ofs = SCREEN_UV - ref_normal.xy * dot(texture(texture_refraction,base_uv),refraction_texture_channel) * refraction;\n"; + code += "\tfloat ref_amount = 1.0 - albedo.a * albedo_tex.a;\n"; + code += "\tEMISSION += textureLod(SCREEN_TEXTURE,ref_ofs,ROUGHNESS * 8.0).rgb * ref_amount;\n"; + code += "\tALBEDO *= 1.0 - ref_amount;\n"; + code += "\tALPHA = 1.0;\n"; + + } else if (features[FEATURE_TRANSPARENT] || features[FLAG_USE_ALPHA_SCISSOR]) { + code += "\tALPHA = albedo.a * albedo_tex.a;\n"; + } + if (features[FEATURE_RIM]) { - code += "\tvec2 rim_tex = texture(texture_rim,UV).xw;\n"; + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tvec2 rim_tex = triplanar_texture(texture_rim,uv1_power_normal,uv1_world_pos).xy;\n"; + } else { + code += "\tvec2 rim_tex = texture(texture_rim,base_uv).xy;\n"; + } code += "\tRIM = rim*rim_tex.x;"; code += "\tRIM_TINT = rim_tint*rim_tex.y;\n"; } if (features[FEATURE_CLEARCOAT]) { - code += "\tvec2 clearcoat_tex = texture(texture_clearcoat,UV).xw;\n"; + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tvec2 clearcoat_tex = triplanar_texture(texture_clearcoat,uv1_power_normal,uv1_world_pos).xy;\n"; + } else { + code += "\tvec2 clearcoat_tex = texture(texture_clearcoat,base_uv).xy;\n"; + } code += "\tCLEARCOAT = clearcoat*clearcoat_tex.x;"; code += "\tCLEARCOAT_GLOSS = clearcoat_gloss*clearcoat_tex.y;\n"; } if (features[FEATURE_ANISOTROPY]) { - code += "\tvec4 anisotropy_tex = texture(texture_flowmap,UV);\n"; - code += "\tANISOTROPY = anisotropy_ratio*anisotropy_tex.a;\n"; + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tvec3 anisotropy_tex = triplanar_texture(texture_flowmap,uv1_power_normal,uv1_world_pos).rga;\n"; + } else { + code += "\tvec3 anisotropy_tex = texture(texture_flowmap,base_uv).rga;\n"; + } + code += "\tANISOTROPY = anisotropy_ratio*anisotropy_tex.b;\n"; code += "\tANISOTROPY_FLOW = anisotropy_tex.rg*2.0-1.0;\n"; } if (features[FEATURE_AMBIENT_OCCLUSION]) { - code += "\tAO = texture(texture_ambient_occlusion,UV).r;\n"; + if (flags[FLAG_AO_ON_UV2]) { + if (flags[FLAG_UV2_USE_TRIPLANAR]) { + code += "\tAO = dot(triplanar_texture(texture_ambient_occlusion,uv2_power_normal,uv2_world_pos),ao_texture_channel);\n"; + } else { + code += "\tAO = dot(texture(texture_ambient_occlusion,base_uv2),ao_texture_channel);\n"; + } + } else { + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tAO = dot(triplanar_texture(texture_ambient_occlusion,uv1_power_normal,uv1_world_pos),ao_texture_channel);\n"; + } else { + code += "\tAO = dot(texture(texture_ambient_occlusion,base_uv),ao_texture_channel);\n"; + } + } } if (features[FEATURE_SUBSURACE_SCATTERING]) { - code += "\tfloat sss_tex = texture(texture_subsurface_scattering,UV).r;\n"; + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tfloat sss_tex = triplanar_texture(texture_subsurface_scattering,uv1_power_normal,uv1_world_pos).r;\n"; + } else { + code += "\tfloat sss_tex = texture(texture_subsurface_scattering,base_uv).r;\n"; + } code += "\tSSS_STRENGTH=subsurface_scattering_strength*sss_tex;\n"; } if (features[FEATURE_DETAIL]) { - String det_uv = detail_uv == DETAIL_UV_1 ? "UV" : "UV2"; - code += "\tvec4 detail_tex = texture(texture_detail_albedo," + det_uv + ");\n"; - code += "\tvec4 detail_norm_tex = texture(texture_detail_normal," + det_uv + ");\n"; - code += "\tvec4 detail_mask_tex = texture(texture_detail_mask,UV);\n"; + + bool triplanar = (flags[FLAG_UV1_USE_TRIPLANAR] && detail_uv == DETAIL_UV_1) || (flags[FLAG_UV2_USE_TRIPLANAR] && detail_uv == DETAIL_UV_2); + + if (triplanar) { + String tp_uv = detail_uv == DETAIL_UV_1 ? "uv1" : "uv2"; + code += "\tvec4 detail_tex = triplanar_texture(texture_detail_albedo," + tp_uv + "_power_normal," + tp_uv + "_world_pos);\n"; + code += "\tvec4 detail_norm_tex = triplanar_texture(texture_detail_normal," + tp_uv + "_power_normal," + tp_uv + "_world_pos);\n"; + + } else { + String det_uv = detail_uv == DETAIL_UV_1 ? "base_uv" : "base_uv2"; + code += "\tvec4 detail_tex = texture(texture_detail_albedo," + det_uv + ");\n"; + code += "\tvec4 detail_norm_tex = texture(texture_detail_normal," + det_uv + ");\n"; + } + + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + + code += "\tvec4 detail_mask_tex = triplanar_texture(texture_detail_mask,uv1_power_normal);\n"; + } else { + code += "\tvec4 detail_mask_tex = texture(texture_detail_mask,base_uv);\n"; + } switch (detail_blend_mode) { case BLEND_MODE_MIX: { @@ -317,26 +782,18 @@ void FixedSpatialMaterial::_update_shader() { } code += "\tvec3 detail_norm = mix(NORMALMAP,detail_norm_tex.rgb,detail_tex.a);\n"; - code += "\tNORMALMAP = mix(NORMALMAP,detail_norm,detail_mask_tex.r);\n"; code += "\tALBEDO.rgb = mix(ALBEDO.rgb,detail,detail_mask_tex.r);\n"; - } - - if (specular_mode == SPECULAR_MODE_SPECULAR) { - code += "\tvec4 specular_tex = texture(texture_specular,UV);\n"; - code += "\tSPECULAR = specular.rgb * specular_tex.rgb;\n"; - code += "\tROUGHNESS = specular_tex.a * roughness;\n"; - } else { - code += "\tvec4 specular_tex = texture(texture_specular,UV);\n"; - code += "\tSPECULAR = vec3(ALBEDO.rgb * metalness * specular_tex.r);\n"; - code += "\tROUGHNESS = specular_tex.a * roughness;\n"; + if (flags[FLAG_USE_ALPHA_SCISSOR]) { + code += "\tALPHA_SCISSOR=alpha_scissor_threshold;\n"; + } } code += "}\n"; ShaderData shader_data; - shader_data.shader = VS::get_singleton()->shader_create(VS::SHADER_SPATIAL); + shader_data.shader = VS::get_singleton()->shader_create(); shader_data.users = 1; VS::get_singleton()->shader_set_code(shader_data.shader, code); @@ -346,7 +803,7 @@ void FixedSpatialMaterial::_update_shader() { VS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); } -void FixedSpatialMaterial::flush_changes() { +void SpatialMaterial::flush_changes() { if (material_mutex) material_mutex->lock(); @@ -360,7 +817,7 @@ void FixedSpatialMaterial::flush_changes() { material_mutex->unlock(); } -void FixedSpatialMaterial::_queue_shader_change() { +void SpatialMaterial::_queue_shader_change() { if (material_mutex) material_mutex->lock(); @@ -373,7 +830,7 @@ void FixedSpatialMaterial::_queue_shader_change() { material_mutex->unlock(); } -bool FixedSpatialMaterial::_is_shader_dirty() const { +bool SpatialMaterial::_is_shader_dirty() const { bool dirty = false; @@ -387,187 +844,167 @@ bool FixedSpatialMaterial::_is_shader_dirty() const { return dirty; } -void FixedSpatialMaterial::set_albedo(const Color &p_albedo) { +void SpatialMaterial::set_albedo(const Color &p_albedo) { albedo = p_albedo; VS::get_singleton()->material_set_param(_get_material(), shader_names->albedo, p_albedo); } -Color FixedSpatialMaterial::get_albedo() const { +Color SpatialMaterial::get_albedo() const { return albedo; } -void FixedSpatialMaterial::set_specular_mode(SpecularMode p_mode) { - specular_mode = p_mode; - _change_notify(); - _queue_shader_change(); -} - -FixedSpatialMaterial::SpecularMode FixedSpatialMaterial::get_specular_mode() const { - - return specular_mode; -} - -void FixedSpatialMaterial::set_specular(const Color &p_specular) { +void SpatialMaterial::set_specular(float p_specular) { specular = p_specular; VS::get_singleton()->material_set_param(_get_material(), shader_names->specular, p_specular); } -Color FixedSpatialMaterial::get_specular() const { + +float SpatialMaterial::get_specular() const { return specular; } -void FixedSpatialMaterial::set_roughness(float p_roughness) { +void SpatialMaterial::set_roughness(float p_roughness) { roughness = p_roughness; VS::get_singleton()->material_set_param(_get_material(), shader_names->roughness, p_roughness); } -float FixedSpatialMaterial::get_roughness() const { +float SpatialMaterial::get_roughness() const { return roughness; } -void FixedSpatialMaterial::set_metalness(float p_metalness) { +void SpatialMaterial::set_metallic(float p_metallic) { - metalness = p_metalness; - VS::get_singleton()->material_set_param(_get_material(), shader_names->metalness, p_metalness); + metallic = p_metallic; + VS::get_singleton()->material_set_param(_get_material(), shader_names->metallic, p_metallic); } -float FixedSpatialMaterial::get_metalness() const { +float SpatialMaterial::get_metallic() const { - return metalness; + return metallic; } -void FixedSpatialMaterial::set_emission(const Color &p_emission) { +void SpatialMaterial::set_emission(const Color &p_emission) { emission = p_emission; VS::get_singleton()->material_set_param(_get_material(), shader_names->emission, p_emission); } -Color FixedSpatialMaterial::get_emission() const { +Color SpatialMaterial::get_emission() const { return emission; } -void FixedSpatialMaterial::set_emission_energy(float p_emission_energy) { +void SpatialMaterial::set_emission_energy(float p_emission_energy) { emission_energy = p_emission_energy; VS::get_singleton()->material_set_param(_get_material(), shader_names->emission_energy, p_emission_energy); } -float FixedSpatialMaterial::get_emission_energy() const { +float SpatialMaterial::get_emission_energy() const { return emission_energy; } -void FixedSpatialMaterial::set_normal_scale(float p_normal_scale) { +void SpatialMaterial::set_normal_scale(float p_normal_scale) { normal_scale = p_normal_scale; VS::get_singleton()->material_set_param(_get_material(), shader_names->normal_scale, p_normal_scale); } -float FixedSpatialMaterial::get_normal_scale() const { +float SpatialMaterial::get_normal_scale() const { return normal_scale; } -void FixedSpatialMaterial::set_rim(float p_rim) { +void SpatialMaterial::set_rim(float p_rim) { rim = p_rim; VS::get_singleton()->material_set_param(_get_material(), shader_names->rim, p_rim); } -float FixedSpatialMaterial::get_rim() const { +float SpatialMaterial::get_rim() const { return rim; } -void FixedSpatialMaterial::set_rim_tint(float p_rim_tint) { +void SpatialMaterial::set_rim_tint(float p_rim_tint) { rim_tint = p_rim_tint; VS::get_singleton()->material_set_param(_get_material(), shader_names->rim_tint, p_rim_tint); } -float FixedSpatialMaterial::get_rim_tint() const { +float SpatialMaterial::get_rim_tint() const { return rim_tint; } -void FixedSpatialMaterial::set_clearcoat(float p_clearcoat) { +void SpatialMaterial::set_clearcoat(float p_clearcoat) { clearcoat = p_clearcoat; VS::get_singleton()->material_set_param(_get_material(), shader_names->clearcoat, p_clearcoat); } -float FixedSpatialMaterial::get_clearcoat() const { +float SpatialMaterial::get_clearcoat() const { return clearcoat; } -void FixedSpatialMaterial::set_clearcoat_gloss(float p_clearcoat_gloss) { +void SpatialMaterial::set_clearcoat_gloss(float p_clearcoat_gloss) { clearcoat_gloss = p_clearcoat_gloss; VS::get_singleton()->material_set_param(_get_material(), shader_names->clearcoat_gloss, p_clearcoat_gloss); } -float FixedSpatialMaterial::get_clearcoat_gloss() const { +float SpatialMaterial::get_clearcoat_gloss() const { return clearcoat_gloss; } -void FixedSpatialMaterial::set_anisotropy(float p_anisotropy) { +void SpatialMaterial::set_anisotropy(float p_anisotropy) { anisotropy = p_anisotropy; VS::get_singleton()->material_set_param(_get_material(), shader_names->anisotropy, p_anisotropy); } -float FixedSpatialMaterial::get_anisotropy() const { +float SpatialMaterial::get_anisotropy() const { return anisotropy; } -void FixedSpatialMaterial::set_height_scale(float p_height_scale) { +void SpatialMaterial::set_depth_scale(float p_depth_scale) { - height_scale = p_height_scale; - VS::get_singleton()->material_set_param(_get_material(), shader_names->height_scale, p_height_scale); + depth_scale = p_depth_scale; + VS::get_singleton()->material_set_param(_get_material(), shader_names->depth_scale, p_depth_scale); } -float FixedSpatialMaterial::get_height_scale() const { +float SpatialMaterial::get_depth_scale() const { - return height_scale; + return depth_scale; } -void FixedSpatialMaterial::set_subsurface_scattering_strength(float p_subsurface_scattering_strength) { +void SpatialMaterial::set_subsurface_scattering_strength(float p_subsurface_scattering_strength) { subsurface_scattering_strength = p_subsurface_scattering_strength; VS::get_singleton()->material_set_param(_get_material(), shader_names->subsurface_scattering_strength, subsurface_scattering_strength); } -float FixedSpatialMaterial::get_subsurface_scattering_strength() const { +float SpatialMaterial::get_subsurface_scattering_strength() const { return subsurface_scattering_strength; } -void FixedSpatialMaterial::set_refraction(float p_refraction) { +void SpatialMaterial::set_refraction(float p_refraction) { refraction = p_refraction; VS::get_singleton()->material_set_param(_get_material(), shader_names->refraction, refraction); } -float FixedSpatialMaterial::get_refraction() const { +float SpatialMaterial::get_refraction() const { return refraction; } -void FixedSpatialMaterial::set_refraction_roughness(float p_refraction_roughness) { - - refraction_roughness = p_refraction_roughness; - VS::get_singleton()->material_set_param(_get_material(), shader_names->refraction_roughness, refraction_roughness); -} -float FixedSpatialMaterial::get_refraction_roughness() const { - - return refraction_roughness; -} - -void FixedSpatialMaterial::set_detail_uv(DetailUV p_detail_uv) { +void SpatialMaterial::set_detail_uv(DetailUV p_detail_uv) { if (detail_uv == p_detail_uv) return; @@ -575,12 +1012,12 @@ void FixedSpatialMaterial::set_detail_uv(DetailUV p_detail_uv) { detail_uv = p_detail_uv; _queue_shader_change(); } -FixedSpatialMaterial::DetailUV FixedSpatialMaterial::get_detail_uv() const { +SpatialMaterial::DetailUV SpatialMaterial::get_detail_uv() const { return detail_uv; } -void FixedSpatialMaterial::set_blend_mode(BlendMode p_mode) { +void SpatialMaterial::set_blend_mode(BlendMode p_mode) { if (blend_mode == p_mode) return; @@ -588,22 +1025,22 @@ void FixedSpatialMaterial::set_blend_mode(BlendMode p_mode) { blend_mode = p_mode; _queue_shader_change(); } -FixedSpatialMaterial::BlendMode FixedSpatialMaterial::get_blend_mode() const { +SpatialMaterial::BlendMode SpatialMaterial::get_blend_mode() const { return blend_mode; } -void FixedSpatialMaterial::set_detail_blend_mode(BlendMode p_mode) { +void SpatialMaterial::set_detail_blend_mode(BlendMode p_mode) { detail_blend_mode = p_mode; _queue_shader_change(); } -FixedSpatialMaterial::BlendMode FixedSpatialMaterial::get_detail_blend_mode() const { +SpatialMaterial::BlendMode SpatialMaterial::get_detail_blend_mode() const { return detail_blend_mode; } -void FixedSpatialMaterial::set_depth_draw_mode(DepthDrawMode p_mode) { +void SpatialMaterial::set_depth_draw_mode(DepthDrawMode p_mode) { if (depth_draw_mode == p_mode) return; @@ -611,12 +1048,12 @@ void FixedSpatialMaterial::set_depth_draw_mode(DepthDrawMode p_mode) { depth_draw_mode = p_mode; _queue_shader_change(); } -FixedSpatialMaterial::DepthDrawMode FixedSpatialMaterial::get_depth_draw_mode() const { +SpatialMaterial::DepthDrawMode SpatialMaterial::get_depth_draw_mode() const { return depth_draw_mode; } -void FixedSpatialMaterial::set_cull_mode(CullMode p_mode) { +void SpatialMaterial::set_cull_mode(CullMode p_mode) { if (cull_mode == p_mode) return; @@ -624,12 +1061,12 @@ void FixedSpatialMaterial::set_cull_mode(CullMode p_mode) { cull_mode = p_mode; _queue_shader_change(); } -FixedSpatialMaterial::CullMode FixedSpatialMaterial::get_cull_mode() const { +SpatialMaterial::CullMode SpatialMaterial::get_cull_mode() const { return cull_mode; } -void FixedSpatialMaterial::set_diffuse_mode(DiffuseMode p_mode) { +void SpatialMaterial::set_diffuse_mode(DiffuseMode p_mode) { if (diffuse_mode == p_mode) return; @@ -637,12 +1074,25 @@ void FixedSpatialMaterial::set_diffuse_mode(DiffuseMode p_mode) { diffuse_mode = p_mode; _queue_shader_change(); } -FixedSpatialMaterial::DiffuseMode FixedSpatialMaterial::get_diffuse_mode() const { +SpatialMaterial::DiffuseMode SpatialMaterial::get_diffuse_mode() const { return diffuse_mode; } -void FixedSpatialMaterial::set_flag(Flags p_flag, bool p_enabled) { +void SpatialMaterial::set_specular_mode(SpecularMode p_mode) { + + if (specular_mode == p_mode) + return; + + specular_mode = p_mode; + _queue_shader_change(); +} +SpatialMaterial::SpecularMode SpatialMaterial::get_specular_mode() const { + + return specular_mode; +} + +void SpatialMaterial::set_flag(Flags p_flag, bool p_enabled) { ERR_FAIL_INDEX(p_flag, FLAG_MAX); @@ -650,16 +1100,19 @@ void FixedSpatialMaterial::set_flag(Flags p_flag, bool p_enabled) { return; flags[p_flag] = p_enabled; + if (p_flag == FLAG_USE_ALPHA_SCISSOR) { + _change_notify(); + } _queue_shader_change(); } -bool FixedSpatialMaterial::get_flag(Flags p_flag) const { +bool SpatialMaterial::get_flag(Flags p_flag) const { ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); return flags[p_flag]; } -void FixedSpatialMaterial::set_feature(Feature p_feature, bool p_enabled) { +void SpatialMaterial::set_feature(Feature p_feature, bool p_enabled) { ERR_FAIL_INDEX(p_feature, FEATURE_MAX); if (features[p_feature] == p_enabled) @@ -670,13 +1123,13 @@ void FixedSpatialMaterial::set_feature(Feature p_feature, bool p_enabled) { _queue_shader_change(); } -bool FixedSpatialMaterial::get_feature(Feature p_feature) const { +bool SpatialMaterial::get_feature(Feature p_feature) const { ERR_FAIL_INDEX_V(p_feature, FEATURE_MAX, false); return features[p_feature]; } -void FixedSpatialMaterial::set_texture(TextureParam p_param, const Ref<Texture> &p_texture) { +void SpatialMaterial::set_texture(TextureParam p_param, const Ref<Texture> &p_texture) { ERR_FAIL_INDEX(p_param, TEXTURE_MAX); textures[p_param] = p_texture; @@ -684,265 +1137,554 @@ void FixedSpatialMaterial::set_texture(TextureParam p_param, const Ref<Texture> VS::get_singleton()->material_set_param(_get_material(), shader_names->texture_names[p_param], rid); } -Ref<Texture> FixedSpatialMaterial::get_texture(TextureParam p_param) const { +Ref<Texture> SpatialMaterial::get_texture(TextureParam p_param) const { ERR_FAIL_INDEX_V(p_param, TEXTURE_MAX, Ref<Texture>()); return textures[p_param]; } -void FixedSpatialMaterial::_validate_feature(const String &text, Feature feature, PropertyInfo &property) const { +void SpatialMaterial::_validate_feature(const String &text, Feature feature, PropertyInfo &property) const { if (property.name.begins_with(text) && property.name != text + "_enabled" && !features[feature]) { property.usage = 0; } } -void FixedSpatialMaterial::_validate_property(PropertyInfo &property) const { +void SpatialMaterial::_validate_property(PropertyInfo &property) const { _validate_feature("normal", FEATURE_NORMAL_MAPPING, property); _validate_feature("emission", FEATURE_EMISSION, property); _validate_feature("rim", FEATURE_RIM, property); _validate_feature("clearcoat", FEATURE_CLEARCOAT, property); _validate_feature("anisotropy", FEATURE_ANISOTROPY, property); _validate_feature("ao", FEATURE_AMBIENT_OCCLUSION, property); - _validate_feature("height", FEATURE_HEIGHT_MAPPING, property); + _validate_feature("depth", FEATURE_DEPTH_MAPPING, property); _validate_feature("subsurf_scatter", FEATURE_SUBSURACE_SCATTERING, property); _validate_feature("refraction", FEATURE_REFRACTION, property); _validate_feature("detail", FEATURE_DETAIL, property); - if (property.name == "specular/color" && specular_mode == SPECULAR_MODE_METALLIC) { + if (property.name.begins_with("particles_anim_") && billboard_mode != BILLBOARD_PARTICLES) { + property.usage = 0; + } + + if (property.name == "params_grow_amount" && !grow_enabled) { + property.usage = 0; + } + + if (property.name == "params_alpha_scissor_threshold" && !flags[FLAG_USE_ALPHA_SCISSOR]) { property.usage = 0; } - if (property.name == "specular/metalness" && specular_mode == SPECULAR_MODE_SPECULAR) { + + if ((property.name == "depth_min_layers" || property.name == "depth_max_layers") && !deep_parallax) { property.usage = 0; } } -void FixedSpatialMaterial::set_line_width(float p_line_width) { +void SpatialMaterial::set_line_width(float p_line_width) { line_width = p_line_width; VS::get_singleton()->material_set_line_width(_get_material(), line_width); } -float FixedSpatialMaterial::get_line_width() const { +float SpatialMaterial::get_line_width() const { return line_width; } -void FixedSpatialMaterial::set_point_size(float p_point_size) { +void SpatialMaterial::set_point_size(float p_point_size) { point_size = p_point_size; VS::get_singleton()->material_set_param(_get_material(), shader_names->point_size, p_point_size); } -float FixedSpatialMaterial::get_point_size() const { +float SpatialMaterial::get_point_size() const { return point_size; } -void FixedSpatialMaterial::set_uv1_scale(const Vector2 &p_scale) { +void SpatialMaterial::set_uv1_scale(const Vector3 &p_scale) { uv1_scale = p_scale; VS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_scale, p_scale); } -Vector2 FixedSpatialMaterial::get_uv1_scale() const { +Vector3 SpatialMaterial::get_uv1_scale() const { return uv1_scale; } -void FixedSpatialMaterial::set_uv1_offset(const Vector2 &p_offset) { +void SpatialMaterial::set_uv1_offset(const Vector3 &p_offset) { uv1_offset = p_offset; VS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_offset, p_offset); } -Vector2 FixedSpatialMaterial::get_uv1_offset() const { +Vector3 SpatialMaterial::get_uv1_offset() const { return uv1_offset; } -void FixedSpatialMaterial::set_uv2_scale(const Vector2 &p_scale) { +void SpatialMaterial::set_uv1_triplanar_blend_sharpness(float p_sharpness) { + + uv1_triplanar_sharpness = p_sharpness; + VS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_blend_sharpness, p_sharpness); +} + +float SpatialMaterial::get_uv1_triplanar_blend_sharpness() const { + + return uv1_triplanar_sharpness; +} + +void SpatialMaterial::set_uv2_scale(const Vector3 &p_scale) { uv2_scale = p_scale; VS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_scale, p_scale); } -Vector2 FixedSpatialMaterial::get_uv2_scale() const { +Vector3 SpatialMaterial::get_uv2_scale() const { return uv2_scale; } -void FixedSpatialMaterial::set_uv2_offset(const Vector2 &p_offset) { +void SpatialMaterial::set_uv2_offset(const Vector3 &p_offset) { uv2_offset = p_offset; VS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_offset, p_offset); } -Vector2 FixedSpatialMaterial::get_uv2_offset() const { +Vector3 SpatialMaterial::get_uv2_offset() const { return uv2_offset; } -void FixedSpatialMaterial::_bind_methods() { +void SpatialMaterial::set_uv2_triplanar_blend_sharpness(float p_sharpness) { + + uv2_triplanar_sharpness = p_sharpness; + VS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_blend_sharpness, p_sharpness); +} + +float SpatialMaterial::get_uv2_triplanar_blend_sharpness() const { + + return uv2_triplanar_sharpness; +} + +void SpatialMaterial::set_billboard_mode(BillboardMode p_mode) { + + billboard_mode = p_mode; + _queue_shader_change(); + _change_notify(); +} + +SpatialMaterial::BillboardMode SpatialMaterial::get_billboard_mode() const { + + return billboard_mode; +} + +void SpatialMaterial::set_particles_anim_h_frames(int p_frames) { - ClassDB::bind_method(D_METHOD("set_albedo", "albedo"), &FixedSpatialMaterial::set_albedo); - ClassDB::bind_method(D_METHOD("get_albedo"), &FixedSpatialMaterial::get_albedo); + particles_anim_h_frames = p_frames; + VS::get_singleton()->material_set_param(_get_material(), shader_names->particle_h_frames, p_frames); +} - ClassDB::bind_method(D_METHOD("set_specular_mode", "specular_mode"), &FixedSpatialMaterial::set_specular_mode); - ClassDB::bind_method(D_METHOD("get_specular_mode"), &FixedSpatialMaterial::get_specular_mode); +int SpatialMaterial::get_particles_anim_h_frames() const { - ClassDB::bind_method(D_METHOD("set_specular", "specular"), &FixedSpatialMaterial::set_specular); - ClassDB::bind_method(D_METHOD("get_specular"), &FixedSpatialMaterial::get_specular); + return particles_anim_h_frames; +} +void SpatialMaterial::set_particles_anim_v_frames(int p_frames) { - ClassDB::bind_method(D_METHOD("set_metalness", "metalness"), &FixedSpatialMaterial::set_metalness); - ClassDB::bind_method(D_METHOD("get_metalness"), &FixedSpatialMaterial::get_metalness); + particles_anim_v_frames = p_frames; + VS::get_singleton()->material_set_param(_get_material(), shader_names->particle_v_frames, p_frames); +} - ClassDB::bind_method(D_METHOD("set_roughness", "roughness"), &FixedSpatialMaterial::set_roughness); - ClassDB::bind_method(D_METHOD("get_roughness"), &FixedSpatialMaterial::get_roughness); +int SpatialMaterial::get_particles_anim_v_frames() const { - ClassDB::bind_method(D_METHOD("set_emission", "emission"), &FixedSpatialMaterial::set_emission); - ClassDB::bind_method(D_METHOD("get_emission"), &FixedSpatialMaterial::get_emission); + return particles_anim_v_frames; +} - ClassDB::bind_method(D_METHOD("set_emission_energy", "emission_energy"), &FixedSpatialMaterial::set_emission_energy); - ClassDB::bind_method(D_METHOD("get_emission_energy"), &FixedSpatialMaterial::get_emission_energy); +void SpatialMaterial::set_particles_anim_loop(int p_frames) { - ClassDB::bind_method(D_METHOD("set_normal_scale", "normal_scale"), &FixedSpatialMaterial::set_normal_scale); - ClassDB::bind_method(D_METHOD("get_normal_scale"), &FixedSpatialMaterial::get_normal_scale); + particles_anim_loop = p_frames; + VS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_loop, p_frames); +} - ClassDB::bind_method(D_METHOD("set_rim", "rim"), &FixedSpatialMaterial::set_rim); - ClassDB::bind_method(D_METHOD("get_rim"), &FixedSpatialMaterial::get_rim); +int SpatialMaterial::get_particles_anim_loop() const { - ClassDB::bind_method(D_METHOD("set_rim_tint", "rim_tint"), &FixedSpatialMaterial::set_rim_tint); - ClassDB::bind_method(D_METHOD("get_rim_tint"), &FixedSpatialMaterial::get_rim_tint); + return particles_anim_loop; +} - ClassDB::bind_method(D_METHOD("set_clearcoat", "clearcoat"), &FixedSpatialMaterial::set_clearcoat); - ClassDB::bind_method(D_METHOD("get_clearcoat"), &FixedSpatialMaterial::get_clearcoat); +void SpatialMaterial::set_depth_deep_parallax(bool p_enable) { - ClassDB::bind_method(D_METHOD("set_clearcoat_gloss", "clearcoat_gloss"), &FixedSpatialMaterial::set_clearcoat_gloss); - ClassDB::bind_method(D_METHOD("get_clearcoat_gloss"), &FixedSpatialMaterial::get_clearcoat_gloss); + deep_parallax = p_enable; + _queue_shader_change(); + _change_notify(); +} - ClassDB::bind_method(D_METHOD("set_anisotropy", "anisotropy"), &FixedSpatialMaterial::set_anisotropy); - ClassDB::bind_method(D_METHOD("get_anisotropy"), &FixedSpatialMaterial::get_anisotropy); +bool SpatialMaterial::is_depth_deep_parallax_enabled() const { - ClassDB::bind_method(D_METHOD("set_height_scale", "height_scale"), &FixedSpatialMaterial::set_height_scale); - ClassDB::bind_method(D_METHOD("get_height_scale"), &FixedSpatialMaterial::get_height_scale); + return deep_parallax; +} - ClassDB::bind_method(D_METHOD("set_subsurface_scattering_strength", "strength"), &FixedSpatialMaterial::set_subsurface_scattering_strength); - ClassDB::bind_method(D_METHOD("get_subsurface_scattering_strength"), &FixedSpatialMaterial::get_subsurface_scattering_strength); +void SpatialMaterial::set_depth_deep_parallax_min_layers(int p_layer) { - ClassDB::bind_method(D_METHOD("set_refraction", "refraction"), &FixedSpatialMaterial::set_refraction); - ClassDB::bind_method(D_METHOD("get_refraction"), &FixedSpatialMaterial::get_refraction); + deep_parallax_min_layers = p_layer; + VS::get_singleton()->material_set_param(_get_material(), shader_names->depth_min_layers, p_layer); +} +int SpatialMaterial::get_depth_deep_parallax_min_layers() const { - ClassDB::bind_method(D_METHOD("set_refraction_roughness", "refraction_roughness"), &FixedSpatialMaterial::set_refraction_roughness); - ClassDB::bind_method(D_METHOD("get_refraction_roughness"), &FixedSpatialMaterial::get_refraction_roughness); + return deep_parallax_min_layers; +} - ClassDB::bind_method(D_METHOD("set_line_width", "line_width"), &FixedSpatialMaterial::set_line_width); - ClassDB::bind_method(D_METHOD("get_line_width"), &FixedSpatialMaterial::get_line_width); +void SpatialMaterial::set_depth_deep_parallax_max_layers(int p_layer) { - ClassDB::bind_method(D_METHOD("set_point_size", "point_size"), &FixedSpatialMaterial::set_point_size); - ClassDB::bind_method(D_METHOD("get_point_size"), &FixedSpatialMaterial::get_point_size); + deep_parallax_max_layers = p_layer; + VS::get_singleton()->material_set_param(_get_material(), shader_names->depth_max_layers, p_layer); +} +int SpatialMaterial::get_depth_deep_parallax_max_layers() const { - ClassDB::bind_method(D_METHOD("set_detail_uv", "detail_uv"), &FixedSpatialMaterial::set_detail_uv); - ClassDB::bind_method(D_METHOD("get_detail_uv"), &FixedSpatialMaterial::get_detail_uv); + return deep_parallax_max_layers; +} - ClassDB::bind_method(D_METHOD("set_blend_mode", "blend_mode"), &FixedSpatialMaterial::set_blend_mode); - ClassDB::bind_method(D_METHOD("get_blend_mode"), &FixedSpatialMaterial::get_blend_mode); +void SpatialMaterial::set_grow_enabled(bool p_enable) { + grow_enabled = p_enable; + _queue_shader_change(); + _change_notify(); +} - ClassDB::bind_method(D_METHOD("set_depth_draw_mode", "depth_draw_mode"), &FixedSpatialMaterial::set_depth_draw_mode); - ClassDB::bind_method(D_METHOD("get_depth_draw_mode"), &FixedSpatialMaterial::get_depth_draw_mode); +bool SpatialMaterial::is_grow_enabled() const { + return grow_enabled; +} - ClassDB::bind_method(D_METHOD("set_cull_mode", "cull_mode"), &FixedSpatialMaterial::set_cull_mode); - ClassDB::bind_method(D_METHOD("get_cull_mode"), &FixedSpatialMaterial::get_cull_mode); +void SpatialMaterial::set_alpha_scissor_threshold(float p_treshold) { + alpha_scissor_threshold = p_treshold; + VS::get_singleton()->material_set_param(_get_material(), shader_names->alpha_scissor_threshold, p_treshold); +} - ClassDB::bind_method(D_METHOD("set_diffuse_mode", "diffuse_mode"), &FixedSpatialMaterial::set_diffuse_mode); - ClassDB::bind_method(D_METHOD("get_diffuse_mode"), &FixedSpatialMaterial::get_diffuse_mode); +float SpatialMaterial::get_alpha_scissor_threshold() const { - ClassDB::bind_method(D_METHOD("set_flag", "flag", "enable"), &FixedSpatialMaterial::set_flag); - ClassDB::bind_method(D_METHOD("get_flag"), &FixedSpatialMaterial::get_flag); + return alpha_scissor_threshold; +} - ClassDB::bind_method(D_METHOD("set_feature", "feature", "enable"), &FixedSpatialMaterial::set_feature); - ClassDB::bind_method(D_METHOD("get_feature", "feature"), &FixedSpatialMaterial::get_feature); +void SpatialMaterial::set_grow(float p_grow) { + grow = p_grow; + VS::get_singleton()->material_set_param(_get_material(), shader_names->grow, p_grow); +} - ClassDB::bind_method(D_METHOD("set_texture", "param:Texture", "texture"), &FixedSpatialMaterial::set_texture); - ClassDB::bind_method(D_METHOD("get_texture:Texture", "param:Texture"), &FixedSpatialMaterial::get_texture); +float SpatialMaterial::get_grow() const { - ClassDB::bind_method(D_METHOD("set_detail_blend_mode", "detail_blend_mode"), &FixedSpatialMaterial::set_detail_blend_mode); - ClassDB::bind_method(D_METHOD("get_detail_blend_mode"), &FixedSpatialMaterial::get_detail_blend_mode); + return grow; +} - ClassDB::bind_method(D_METHOD("set_uv1_scale", "scale"), &FixedSpatialMaterial::set_uv1_scale); - ClassDB::bind_method(D_METHOD("get_uv1_scale"), &FixedSpatialMaterial::get_uv1_scale); +static Plane _get_texture_mask(SpatialMaterial::TextureChannel p_channel) { + static const Plane masks[5] = { + Plane(1, 0, 0, 0), + Plane(0, 1, 0, 0), + Plane(0, 0, 1, 0), + Plane(0, 0, 0, 1), + Plane(0.3333333, 0.3333333, 0.3333333, 0), + }; - ClassDB::bind_method(D_METHOD("set_uv1_offset", "offset"), &FixedSpatialMaterial::set_uv1_offset); - ClassDB::bind_method(D_METHOD("get_uv1_offset"), &FixedSpatialMaterial::get_uv1_offset); + return masks[p_channel]; +} - ClassDB::bind_method(D_METHOD("set_uv2_scale", "scale"), &FixedSpatialMaterial::set_uv2_scale); - ClassDB::bind_method(D_METHOD("get_uv2_scale"), &FixedSpatialMaterial::get_uv2_scale); +void SpatialMaterial::set_metallic_texture_channel(TextureChannel p_channel) { - ClassDB::bind_method(D_METHOD("set_uv2_offset", "offset"), &FixedSpatialMaterial::set_uv2_offset); - ClassDB::bind_method(D_METHOD("get_uv2_offset"), &FixedSpatialMaterial::get_uv2_offset); + metallic_texture_channel = p_channel; + VS::get_singleton()->material_set_param(_get_material(), shader_names->metallic_texture_channel, _get_texture_mask(p_channel)); +} + +SpatialMaterial::TextureChannel SpatialMaterial::get_metallic_texture_channel() const { + return metallic_texture_channel; +} + +void SpatialMaterial::set_roughness_texture_channel(TextureChannel p_channel) { + + roughness_texture_channel = p_channel; + VS::get_singleton()->material_set_param(_get_material(), shader_names->roughness_texture_channel, _get_texture_mask(p_channel)); +} + +SpatialMaterial::TextureChannel SpatialMaterial::get_roughness_texture_channel() const { + return roughness_texture_channel; +} + +void SpatialMaterial::set_ao_texture_channel(TextureChannel p_channel) { + + ao_texture_channel = p_channel; + VS::get_singleton()->material_set_param(_get_material(), shader_names->ao_texture_channel, _get_texture_mask(p_channel)); +} + +SpatialMaterial::TextureChannel SpatialMaterial::get_ao_texture_channel() const { + return ao_texture_channel; +} + +void SpatialMaterial::set_refraction_texture_channel(TextureChannel p_channel) { + + refraction_texture_channel = p_channel; + VS::get_singleton()->material_set_param(_get_material(), shader_names->refraction_texture_channel, _get_texture_mask(p_channel)); +} + +SpatialMaterial::TextureChannel SpatialMaterial::get_refraction_texture_channel() const { + return refraction_texture_channel; +} + +RID SpatialMaterial::get_material_rid_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass) { + + int version = 0; + if (p_shaded) + version = 1; + if (p_transparent) + version |= 2; + if (p_cut_alpha) + version |= 4; + if (p_opaque_prepass) + version |= 8; + if (p_double_sided) + version |= 16; + + if (materials_for_2d[version].is_valid()) { + return materials_for_2d[version]->get_rid(); + } + + Ref<SpatialMaterial> material; + material.instance(); + + material->set_flag(FLAG_UNSHADED, !p_shaded); + material->set_feature(FEATURE_TRANSPARENT, p_transparent); + material->set_cull_mode(p_double_sided ? CULL_DISABLED : CULL_BACK); + material->set_depth_draw_mode(p_opaque_prepass ? DEPTH_DRAW_ALPHA_OPAQUE_PREPASS : DEPTH_DRAW_OPAQUE_ONLY); + material->set_flag(FLAG_SRGB_VERTEX_COLOR, true); + material->set_flag(FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + material->set_flag(FLAG_USE_ALPHA_SCISSOR, p_cut_alpha); + + materials_for_2d[version] = material; + + return materials_for_2d[version]->get_rid(); +} + +void SpatialMaterial::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_albedo", "albedo"), &SpatialMaterial::set_albedo); + ClassDB::bind_method(D_METHOD("get_albedo"), &SpatialMaterial::get_albedo); + + ClassDB::bind_method(D_METHOD("set_specular", "specular"), &SpatialMaterial::set_specular); + ClassDB::bind_method(D_METHOD("get_specular"), &SpatialMaterial::get_specular); + + ClassDB::bind_method(D_METHOD("set_metallic", "metallic"), &SpatialMaterial::set_metallic); + ClassDB::bind_method(D_METHOD("get_metallic"), &SpatialMaterial::get_metallic); + + ClassDB::bind_method(D_METHOD("set_roughness", "roughness"), &SpatialMaterial::set_roughness); + ClassDB::bind_method(D_METHOD("get_roughness"), &SpatialMaterial::get_roughness); + + ClassDB::bind_method(D_METHOD("set_emission", "emission"), &SpatialMaterial::set_emission); + ClassDB::bind_method(D_METHOD("get_emission"), &SpatialMaterial::get_emission); + + ClassDB::bind_method(D_METHOD("set_emission_energy", "emission_energy"), &SpatialMaterial::set_emission_energy); + ClassDB::bind_method(D_METHOD("get_emission_energy"), &SpatialMaterial::get_emission_energy); + + ClassDB::bind_method(D_METHOD("set_normal_scale", "normal_scale"), &SpatialMaterial::set_normal_scale); + ClassDB::bind_method(D_METHOD("get_normal_scale"), &SpatialMaterial::get_normal_scale); + + ClassDB::bind_method(D_METHOD("set_rim", "rim"), &SpatialMaterial::set_rim); + ClassDB::bind_method(D_METHOD("get_rim"), &SpatialMaterial::get_rim); + + ClassDB::bind_method(D_METHOD("set_rim_tint", "rim_tint"), &SpatialMaterial::set_rim_tint); + ClassDB::bind_method(D_METHOD("get_rim_tint"), &SpatialMaterial::get_rim_tint); + + ClassDB::bind_method(D_METHOD("set_clearcoat", "clearcoat"), &SpatialMaterial::set_clearcoat); + ClassDB::bind_method(D_METHOD("get_clearcoat"), &SpatialMaterial::get_clearcoat); + + ClassDB::bind_method(D_METHOD("set_clearcoat_gloss", "clearcoat_gloss"), &SpatialMaterial::set_clearcoat_gloss); + ClassDB::bind_method(D_METHOD("get_clearcoat_gloss"), &SpatialMaterial::get_clearcoat_gloss); + + ClassDB::bind_method(D_METHOD("set_anisotropy", "anisotropy"), &SpatialMaterial::set_anisotropy); + ClassDB::bind_method(D_METHOD("get_anisotropy"), &SpatialMaterial::get_anisotropy); + + ClassDB::bind_method(D_METHOD("set_depth_scale", "depth_scale"), &SpatialMaterial::set_depth_scale); + ClassDB::bind_method(D_METHOD("get_depth_scale"), &SpatialMaterial::get_depth_scale); + + ClassDB::bind_method(D_METHOD("set_subsurface_scattering_strength", "strength"), &SpatialMaterial::set_subsurface_scattering_strength); + ClassDB::bind_method(D_METHOD("get_subsurface_scattering_strength"), &SpatialMaterial::get_subsurface_scattering_strength); + + ClassDB::bind_method(D_METHOD("set_refraction", "refraction"), &SpatialMaterial::set_refraction); + ClassDB::bind_method(D_METHOD("get_refraction"), &SpatialMaterial::get_refraction); + + ClassDB::bind_method(D_METHOD("set_line_width", "line_width"), &SpatialMaterial::set_line_width); + ClassDB::bind_method(D_METHOD("get_line_width"), &SpatialMaterial::get_line_width); + + ClassDB::bind_method(D_METHOD("set_point_size", "point_size"), &SpatialMaterial::set_point_size); + ClassDB::bind_method(D_METHOD("get_point_size"), &SpatialMaterial::get_point_size); + + ClassDB::bind_method(D_METHOD("set_detail_uv", "detail_uv"), &SpatialMaterial::set_detail_uv); + ClassDB::bind_method(D_METHOD("get_detail_uv"), &SpatialMaterial::get_detail_uv); + + ClassDB::bind_method(D_METHOD("set_blend_mode", "blend_mode"), &SpatialMaterial::set_blend_mode); + ClassDB::bind_method(D_METHOD("get_blend_mode"), &SpatialMaterial::get_blend_mode); + + ClassDB::bind_method(D_METHOD("set_depth_draw_mode", "depth_draw_mode"), &SpatialMaterial::set_depth_draw_mode); + ClassDB::bind_method(D_METHOD("get_depth_draw_mode"), &SpatialMaterial::get_depth_draw_mode); + + ClassDB::bind_method(D_METHOD("set_cull_mode", "cull_mode"), &SpatialMaterial::set_cull_mode); + ClassDB::bind_method(D_METHOD("get_cull_mode"), &SpatialMaterial::get_cull_mode); + + ClassDB::bind_method(D_METHOD("set_diffuse_mode", "diffuse_mode"), &SpatialMaterial::set_diffuse_mode); + ClassDB::bind_method(D_METHOD("get_diffuse_mode"), &SpatialMaterial::get_diffuse_mode); + + ClassDB::bind_method(D_METHOD("set_specular_mode", "specular_mode"), &SpatialMaterial::set_specular_mode); + ClassDB::bind_method(D_METHOD("get_specular_mode"), &SpatialMaterial::get_specular_mode); + + ClassDB::bind_method(D_METHOD("set_flag", "flag", "enable"), &SpatialMaterial::set_flag); + ClassDB::bind_method(D_METHOD("get_flag", "flag"), &SpatialMaterial::get_flag); + + ClassDB::bind_method(D_METHOD("set_feature", "feature", "enable"), &SpatialMaterial::set_feature); + ClassDB::bind_method(D_METHOD("get_feature", "feature"), &SpatialMaterial::get_feature); + + ClassDB::bind_method(D_METHOD("set_texture", "param", "texture"), &SpatialMaterial::set_texture); + ClassDB::bind_method(D_METHOD("get_texture", "param"), &SpatialMaterial::get_texture); + + ClassDB::bind_method(D_METHOD("set_detail_blend_mode", "detail_blend_mode"), &SpatialMaterial::set_detail_blend_mode); + ClassDB::bind_method(D_METHOD("get_detail_blend_mode"), &SpatialMaterial::get_detail_blend_mode); + + ClassDB::bind_method(D_METHOD("set_uv1_scale", "scale"), &SpatialMaterial::set_uv1_scale); + ClassDB::bind_method(D_METHOD("get_uv1_scale"), &SpatialMaterial::get_uv1_scale); + + ClassDB::bind_method(D_METHOD("set_uv1_offset", "offset"), &SpatialMaterial::set_uv1_offset); + ClassDB::bind_method(D_METHOD("get_uv1_offset"), &SpatialMaterial::get_uv1_offset); + + ClassDB::bind_method(D_METHOD("set_uv1_triplanar_blend_sharpness", "sharpness"), &SpatialMaterial::set_uv1_triplanar_blend_sharpness); + ClassDB::bind_method(D_METHOD("get_uv1_triplanar_blend_sharpness"), &SpatialMaterial::get_uv1_triplanar_blend_sharpness); + + ClassDB::bind_method(D_METHOD("set_uv2_scale", "scale"), &SpatialMaterial::set_uv2_scale); + ClassDB::bind_method(D_METHOD("get_uv2_scale"), &SpatialMaterial::get_uv2_scale); + + ClassDB::bind_method(D_METHOD("set_uv2_offset", "offset"), &SpatialMaterial::set_uv2_offset); + ClassDB::bind_method(D_METHOD("get_uv2_offset"), &SpatialMaterial::get_uv2_offset); + + ClassDB::bind_method(D_METHOD("set_uv2_triplanar_blend_sharpness", "sharpness"), &SpatialMaterial::set_uv2_triplanar_blend_sharpness); + ClassDB::bind_method(D_METHOD("get_uv2_triplanar_blend_sharpness"), &SpatialMaterial::get_uv2_triplanar_blend_sharpness); + + ClassDB::bind_method(D_METHOD("set_billboard_mode", "mode"), &SpatialMaterial::set_billboard_mode); + ClassDB::bind_method(D_METHOD("get_billboard_mode"), &SpatialMaterial::get_billboard_mode); + + ClassDB::bind_method(D_METHOD("set_particles_anim_h_frames", "frames"), &SpatialMaterial::set_particles_anim_h_frames); + ClassDB::bind_method(D_METHOD("get_particles_anim_h_frames"), &SpatialMaterial::get_particles_anim_h_frames); + + ClassDB::bind_method(D_METHOD("set_particles_anim_v_frames", "frames"), &SpatialMaterial::set_particles_anim_v_frames); + ClassDB::bind_method(D_METHOD("get_particles_anim_v_frames"), &SpatialMaterial::get_particles_anim_v_frames); + + ClassDB::bind_method(D_METHOD("set_particles_anim_loop", "frames"), &SpatialMaterial::set_particles_anim_loop); + ClassDB::bind_method(D_METHOD("get_particles_anim_loop"), &SpatialMaterial::get_particles_anim_loop); + + ClassDB::bind_method(D_METHOD("set_depth_deep_parallax", "enable"), &SpatialMaterial::set_depth_deep_parallax); + ClassDB::bind_method(D_METHOD("is_depth_deep_parallax_enabled"), &SpatialMaterial::is_depth_deep_parallax_enabled); + + ClassDB::bind_method(D_METHOD("set_depth_deep_parallax_min_layers", "layer"), &SpatialMaterial::set_depth_deep_parallax_min_layers); + ClassDB::bind_method(D_METHOD("get_depth_deep_parallax_min_layers"), &SpatialMaterial::get_depth_deep_parallax_min_layers); + + ClassDB::bind_method(D_METHOD("set_depth_deep_parallax_max_layers", "layer"), &SpatialMaterial::set_depth_deep_parallax_max_layers); + ClassDB::bind_method(D_METHOD("get_depth_deep_parallax_max_layers"), &SpatialMaterial::get_depth_deep_parallax_max_layers); + + ClassDB::bind_method(D_METHOD("set_grow", "amount"), &SpatialMaterial::set_grow); + ClassDB::bind_method(D_METHOD("get_grow"), &SpatialMaterial::get_grow); + + ClassDB::bind_method(D_METHOD("set_alpha_scissor_threshold", "threshold"), &SpatialMaterial::set_alpha_scissor_threshold); + ClassDB::bind_method(D_METHOD("get_alpha_scissor_threshold"), &SpatialMaterial::get_alpha_scissor_threshold); + + ClassDB::bind_method(D_METHOD("set_grow_enabled", "enable"), &SpatialMaterial::set_grow_enabled); + ClassDB::bind_method(D_METHOD("is_grow_enabled"), &SpatialMaterial::is_grow_enabled); + + ClassDB::bind_method(D_METHOD("set_metallic_texture_channel", "channel"), &SpatialMaterial::set_metallic_texture_channel); + ClassDB::bind_method(D_METHOD("get_metallic_texture_channel"), &SpatialMaterial::get_metallic_texture_channel); + + ClassDB::bind_method(D_METHOD("set_roughness_texture_channel", "channel"), &SpatialMaterial::set_roughness_texture_channel); + ClassDB::bind_method(D_METHOD("get_roughness_texture_channel"), &SpatialMaterial::get_roughness_texture_channel); + + ClassDB::bind_method(D_METHOD("set_ao_texture_channel", "channel"), &SpatialMaterial::set_ao_texture_channel); + ClassDB::bind_method(D_METHOD("get_ao_texture_channel"), &SpatialMaterial::get_ao_texture_channel); + + ClassDB::bind_method(D_METHOD("set_refraction_texture_channel", "channel"), &SpatialMaterial::set_refraction_texture_channel); + ClassDB::bind_method(D_METHOD("get_refraction_texture_channel"), &SpatialMaterial::get_refraction_texture_channel); ADD_GROUP("Flags", "flags_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_transparent"), "set_feature", "get_feature", FEATURE_TRANSPARENT); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_unshaded"), "set_flag", "get_flag", FLAG_UNSHADED); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_vertex_lighting"), "set_flag", "get_flag", FLAG_USE_VERTEX_LIGHTING); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_on_top"), "set_flag", "get_flag", FLAG_ONTOP); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_use_point_size"), "set_flag", "get_flag", FLAG_USE_POINT_SIZE); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_fixed_size"), "set_flag", "get_flag", FLAG_FIXED_SIZE); ADD_GROUP("Vertex Color", "vertex_color"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "vertex_color_use_as_albedo"), "set_flag", "get_flag", FLAG_ALBEDO_FROM_VERTEX_COLOR); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "vertex_color_is_srgb"), "set_flag", "get_flag", FLAG_SRGB_VERTEX_COLOR); ADD_GROUP("Parameters", "params_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "params_diffuse_mode", PROPERTY_HINT_ENUM, "Labert,Lambert Wrap,Oren Nayar,Burley"), "set_diffuse_mode", "get_diffuse_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "params_diffuse_mode", PROPERTY_HINT_ENUM, "Lambert,Lambert Wrap,Oren Nayar,Burley,Toon"), "set_diffuse_mode", "get_diffuse_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "params_specular_mode", PROPERTY_HINT_ENUM, "SchlickGGX,Blinn,Phong,Toon,Disabled"), "set_specular_mode", "get_specular_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "params_blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul"), "set_blend_mode", "get_blend_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "params_cull_mode", PROPERTY_HINT_ENUM, "Back,Front,Disabled"), "set_cull_mode", "get_cull_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "params_depth_draw_mode", PROPERTY_HINT_ENUM, "Opaque Only,Always,Never,Opaque Pre-Pass"), "set_depth_draw_mode", "get_depth_draw_mode"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_line_width", PROPERTY_HINT_RANGE, "0.1,128,0.1"), "set_line_width", "get_line_width"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_point_size", PROPERTY_HINT_RANGE, "0.1,128,0.1"), "set_point_size", "get_point_size"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "params_billboard_mode", PROPERTY_HINT_ENUM, "Disabled,Enabled,Y-Billboard,Particle Billboard"), "set_billboard_mode", "get_billboard_mode"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "params_grow"), "set_grow_enabled", "is_grow_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_grow_amount", PROPERTY_HINT_RANGE, "-16,10,0.01"), "set_grow", "get_grow"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "params_use_alpha_scissor"), "set_flag", "get_flag", FLAG_USE_ALPHA_SCISSOR); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold"); + ADD_GROUP("Particles Anim", "particles_anim_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "particles_anim_h_frames", PROPERTY_HINT_RANGE, "1,128,1"), "set_particles_anim_h_frames", "get_particles_anim_h_frames"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "particles_anim_v_frames", PROPERTY_HINT_RANGE, "1,128,1"), "set_particles_anim_v_frames", "get_particles_anim_v_frames"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "particles_anim_loop"), "set_particles_anim_loop", "get_particles_anim_loop"); ADD_GROUP("Albedo", "albedo_"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "albedo_color"), "set_albedo", "get_albedo"); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "albedo_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_ALBEDO); - ADD_GROUP("Specular", "specular_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "specular_mode", PROPERTY_HINT_ENUM, "Metallic,Specular"), "set_specular_mode", "get_specular_mode"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "specular_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_specular", "get_specular"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "specular_metalness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_metalness", "get_metalness"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "specular_roughness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_roughness", "get_roughness"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "specular_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_SPECULAR); + ADD_GROUP("Metallic", "metallic_"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "metallic", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_metallic", "get_metallic"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "metallic_specular", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_specular", "get_specular"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "metallic_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_METALLIC); + ADD_PROPERTY(PropertyInfo(Variant::INT, "metallic_texture_channel", PROPERTY_HINT_ENUM, "Red,Green,Blue,Alpha,Gray"), "set_metallic_texture_channel", "get_metallic_texture_channel"); + + ADD_GROUP("Roughness", "roughness_"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "roughness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_roughness", "get_roughness"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "roughness_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_ROUGHNESS); + ADD_PROPERTY(PropertyInfo(Variant::INT, "roughness_texture_channel", PROPERTY_HINT_ENUM, "Red,Green,Blue,Alpha,Gray"), "set_roughness_texture_channel", "get_roughness_texture_channel"); ADD_GROUP("Emission", "emission_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "emission_enabled"), "set_feature", "get_feature", FEATURE_EMISSION); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "emission_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_emission", "get_emission"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "emission", PROPERTY_HINT_COLOR_NO_ALPHA), "set_emission", "get_emission"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_emission_energy", "get_emission_energy"); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "emission_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_EMISSION); - ADD_GROUP("NormapMap", "normal_"); + ADD_GROUP("NormalMap", "normal_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "normal_enabled"), "set_feature", "get_feature", FEATURE_NORMAL_MAPPING); ADD_PROPERTY(PropertyInfo(Variant::REAL, "normal_scale", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_normal_scale", "get_normal_scale"); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "normal_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_NORMAL); ADD_GROUP("Rim", "rim_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "rim_enabled"), "set_feature", "get_feature", FEATURE_RIM); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "rim_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_rim", "get_rim"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "rim", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_rim", "get_rim"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "rim_tint", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_rim_tint", "get_rim_tint"); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "rim_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_RIM); ADD_GROUP("Clearcoat", "clearcoat_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "clearcoat_enabled"), "set_feature", "get_feature", FEATURE_CLEARCOAT); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "clearcoat_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_clearcoat", "get_clearcoat"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "clearcoat", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_clearcoat", "get_clearcoat"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "clearcoat_gloss", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_clearcoat_gloss", "get_clearcoat_gloss"); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "clearcoat_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_CLEARCOAT); ADD_GROUP("Anisotropy", "anisotropy_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "anisotropy_enabled"), "set_feature", "get_feature", FEATURE_ANISOTROPY); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "anisotropy_anisotropy", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_anisotropy", "get_anisotropy"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "anisotropy", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_anisotropy", "get_anisotropy"); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anisotropy_flowmap", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_FLOWMAP); ADD_GROUP("Ambient Occlusion", "ao_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "ao_enabled"), "set_feature", "get_feature", FEATURE_AMBIENT_OCCLUSION); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "ao_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_AMBIENT_OCCLUSION); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "ao_on_uv2"), "set_flag", "get_flag", FLAG_AO_ON_UV2); + ADD_PROPERTY(PropertyInfo(Variant::INT, "ao_texture_channel", PROPERTY_HINT_ENUM, "Red,Green,Blue,Alpha,Gray"), "set_ao_texture_channel", "get_ao_texture_channel"); - ADD_GROUP("Height", "height_"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "height_enabled"), "set_feature", "get_feature", FEATURE_HEIGHT_MAPPING); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "height_scale", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_height_scale", "get_height_scale"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "height_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_HEIGHT); + ADD_GROUP("Depth", "depth_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "depth_enabled"), "set_feature", "get_feature", FEATURE_DEPTH_MAPPING); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "depth_scale", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_depth_scale", "get_depth_scale"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "depth_deep_parallax"), "set_depth_deep_parallax", "is_depth_deep_parallax_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "depth_min_layers", PROPERTY_HINT_RANGE, "1,32,1"), "set_depth_deep_parallax_min_layers", "get_depth_deep_parallax_min_layers"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "depth_max_layers", PROPERTY_HINT_RANGE, "1,32,1"), "set_depth_deep_parallax_max_layers", "get_depth_deep_parallax_max_layers"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "depth_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_DEPTH); ADD_GROUP("Subsurf Scatter", "subsurf_scatter_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "subsurf_scatter_enabled"), "set_feature", "get_feature", FEATURE_SUBSURACE_SCATTERING); @@ -951,9 +1693,9 @@ void FixedSpatialMaterial::_bind_methods() { ADD_GROUP("Refraction", "refraction_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "refraction_enabled"), "set_feature", "get_feature", FEATURE_REFRACTION); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "refraction_displacement", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_refraction", "get_refraction"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "refraction_roughness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_refraction_roughness", "get_refraction_roughness"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "refraction_scale", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_refraction", "get_refraction"); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "refraction_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_REFRACTION); + ADD_PROPERTY(PropertyInfo(Variant::INT, "refraction_texture_channel", PROPERTY_HINT_ENUM, "Red,Green,Blue,Alpha,Gray"), "set_refraction_texture_channel", "get_refraction_texture_channel"); ADD_GROUP("Detail", "detail_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "detail_enabled"), "set_feature", "get_feature", FEATURE_DETAIL); @@ -964,25 +1706,29 @@ void FixedSpatialMaterial::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "detail_normal", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_DETAIL_NORMAL); ADD_GROUP("UV1", "uv1_"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "uv1_scale"), "set_uv1_scale", "get_uv1_scale"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "uv1_offset"), "set_uv1_offset", "get_uv1_offset"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv1_scale"), "set_uv1_scale", "get_uv1_scale"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv1_offset"), "set_uv1_offset", "get_uv1_offset"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "uv1_triplanar"), "set_flag", "get_flag", FLAG_UV1_USE_TRIPLANAR); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "uv1_triplanar_sharpness", PROPERTY_HINT_EXP_EASING), "set_uv1_triplanar_blend_sharpness", "get_uv1_triplanar_blend_sharpness"); ADD_GROUP("UV2", "uv2_"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "uv2_scale"), "set_uv2_scale", "get_uv2_scale"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "uv2_offset"), "set_uv2_offset", "get_uv2_offset"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv2_scale"), "set_uv2_scale", "get_uv2_scale"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv2_offset"), "set_uv2_offset", "get_uv2_offset"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "uv2_triplanar"), "set_flag", "get_flag", FLAG_UV2_USE_TRIPLANAR); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "uv2_triplanar_sharpness", PROPERTY_HINT_EXP_EASING), "set_uv2_triplanar_blend_sharpness", "get_uv2_triplanar_blend_sharpness"); BIND_CONSTANT(TEXTURE_ALBEDO); - BIND_CONSTANT(TEXTURE_SPECULAR); + BIND_CONSTANT(TEXTURE_METALLIC); + BIND_CONSTANT(TEXTURE_ROUGHNESS); BIND_CONSTANT(TEXTURE_EMISSION); BIND_CONSTANT(TEXTURE_NORMAL); BIND_CONSTANT(TEXTURE_RIM); BIND_CONSTANT(TEXTURE_CLEARCOAT); BIND_CONSTANT(TEXTURE_FLOWMAP); BIND_CONSTANT(TEXTURE_AMBIENT_OCCLUSION); - BIND_CONSTANT(TEXTURE_HEIGHT); + BIND_CONSTANT(TEXTURE_DEPTH); BIND_CONSTANT(TEXTURE_SUBSURFACE_SCATTERING); BIND_CONSTANT(TEXTURE_REFRACTION); - BIND_CONSTANT(TEXTURE_REFRACTION_ROUGHNESS); BIND_CONSTANT(TEXTURE_DETAIL_MASK); BIND_CONSTANT(TEXTURE_DETAIL_ALBEDO); BIND_CONSTANT(TEXTURE_DETAIL_NORMAL); @@ -998,7 +1744,7 @@ void FixedSpatialMaterial::_bind_methods() { BIND_CONSTANT(FEATURE_CLEARCOAT); BIND_CONSTANT(FEATURE_ANISOTROPY); BIND_CONSTANT(FEATURE_AMBIENT_OCCLUSION); - BIND_CONSTANT(FEATURE_HEIGHT_MAPPING); + BIND_CONSTANT(FEATURE_DEPTH_MAPPING); BIND_CONSTANT(FEATURE_SUBSURACE_SCATTERING); BIND_CONSTANT(FEATURE_REFRACTION); BIND_CONSTANT(FEATURE_DETAIL); @@ -1019,30 +1765,50 @@ void FixedSpatialMaterial::_bind_methods() { BIND_CONSTANT(CULL_DISABLED); BIND_CONSTANT(FLAG_UNSHADED); + BIND_CONSTANT(FLAG_USE_VERTEX_LIGHTING); BIND_CONSTANT(FLAG_ONTOP); BIND_CONSTANT(FLAG_ALBEDO_FROM_VERTEX_COLOR); - BIND_CONSTANT(FLAG_SRGB_VERTEX_COLOR) - BIND_CONSTANT(FLAG_USE_POINT_SIZE) + BIND_CONSTANT(FLAG_SRGB_VERTEX_COLOR); + BIND_CONSTANT(FLAG_USE_POINT_SIZE); + BIND_CONSTANT(FLAG_FIXED_SIZE); + BIND_CONSTANT(FLAG_UV1_USE_TRIPLANAR); + BIND_CONSTANT(FLAG_UV2_USE_TRIPLANAR); + BIND_CONSTANT(FLAG_AO_ON_UV2); + BIND_CONSTANT(FLAG_USE_ALPHA_SCISSOR); BIND_CONSTANT(FLAG_MAX); BIND_CONSTANT(DIFFUSE_LAMBERT); - BIND_CONSTANT(DIFFUSE_LAMBERT_WRAP); + BIND_CONSTANT(DIFFUSE_HALF_LAMBERT); BIND_CONSTANT(DIFFUSE_OREN_NAYAR); BIND_CONSTANT(DIFFUSE_BURLEY); + BIND_CONSTANT(DIFFUSE_TOON); - BIND_CONSTANT(SPECULAR_MODE_METALLIC); - BIND_CONSTANT(SPECULAR_MODE_SPECULAR); + BIND_CONSTANT(SPECULAR_SCHLICK_GGX); + BIND_CONSTANT(SPECULAR_BLINN); + BIND_CONSTANT(SPECULAR_PHONG); + BIND_CONSTANT(SPECULAR_TOON); + BIND_CONSTANT(SPECULAR_DISABLED); + + BIND_CONSTANT(BILLBOARD_DISABLED); + BIND_CONSTANT(BILLBOARD_ENABLED); + BIND_CONSTANT(BILLBOARD_FIXED_Y); + BIND_CONSTANT(BILLBOARD_PARTICLES); + + BIND_CONSTANT(TEXTURE_CHANNEL_RED); + BIND_CONSTANT(TEXTURE_CHANNEL_GREEN); + BIND_CONSTANT(TEXTURE_CHANNEL_BLUE); + BIND_CONSTANT(TEXTURE_CHANNEL_ALPHA); + BIND_CONSTANT(TEXTURE_CHANNEL_GRAYSCALE); } -FixedSpatialMaterial::FixedSpatialMaterial() +SpatialMaterial::SpatialMaterial() : element(this) { //initialize to right values - specular_mode = SPECULAR_MODE_METALLIC; - set_albedo(Color(0.7, 0.7, 0.7, 1.0)); - set_specular(Color(0.1, 0.1, 0.1)); + set_albedo(Color(1.0, 1.0, 1.0, 1.0)); + set_specular(0.5); set_roughness(0.0); - set_metalness(0.1); + set_metallic(0.0); set_emission(Color(0, 0, 0)); set_emission_energy(1.0); set_normal_scale(1); @@ -1051,16 +1817,34 @@ FixedSpatialMaterial::FixedSpatialMaterial() set_clearcoat(1); set_clearcoat_gloss(0.5); set_anisotropy(0); - set_height_scale(1); + set_depth_scale(0.05); set_subsurface_scattering_strength(0); - set_refraction(0); - set_refraction_roughness(0); + set_refraction(0.05); set_line_width(1); set_point_size(1); - set_uv1_offset(Vector2(0, 0)); - set_uv1_scale(Vector2(1, 1)); - set_uv2_offset(Vector2(0, 0)); - set_uv2_scale(Vector2(1, 1)); + set_uv1_offset(Vector3(0, 0, 0)); + set_uv1_scale(Vector3(1, 1, 1)); + set_uv1_triplanar_blend_sharpness(1); + set_uv2_offset(Vector3(0, 0, 0)); + set_uv2_scale(Vector3(1, 1, 1)); + set_uv2_triplanar_blend_sharpness(1); + set_billboard_mode(BILLBOARD_DISABLED); + set_particles_anim_h_frames(1); + set_particles_anim_v_frames(1); + set_particles_anim_loop(false); + set_alpha_scissor_threshold(0.98); + + set_metallic_texture_channel(TEXTURE_CHANNEL_RED); + set_roughness_texture_channel(TEXTURE_CHANNEL_RED); + set_ao_texture_channel(TEXTURE_CHANNEL_RED); + set_refraction_texture_channel(TEXTURE_CHANNEL_RED); + + grow_enabled = false; + set_grow(0.0); + + deep_parallax = false; + set_depth_deep_parallax_min_layers(8); + set_depth_deep_parallax_max_layers(32); detail_uv = DETAIL_UV_1; blend_mode = BLEND_MODE_MIX; @@ -1071,6 +1855,7 @@ FixedSpatialMaterial::FixedSpatialMaterial() flags[i] = 0; } diffuse_mode = DIFFUSE_LAMBERT; + specular_mode = SPECULAR_SCHLICK_GGX; for (int i = 0; i < FEATURE_MAX; i++) { features[i] = false; @@ -1081,7 +1866,7 @@ FixedSpatialMaterial::FixedSpatialMaterial() _queue_shader_change(); } -FixedSpatialMaterial::~FixedSpatialMaterial() { +SpatialMaterial::~SpatialMaterial() { if (material_mutex) material_mutex->lock(); diff --git a/scene/resources/material.h b/scene/resources/material.h index a8288153c..140b2142c 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -41,39 +42,69 @@ class Material : public Resource { - GDCLASS(Material, Resource); - RES_BASE_EXTENSION("mtl"); - OBJ_SAVE_TYPE(Material); + GDCLASS(Material, Resource) + RES_BASE_EXTENSION("material") + OBJ_SAVE_TYPE(Material) RID material; + Ref<Material> next_pass; protected: _FORCE_INLINE_ RID _get_material() const { return material; } + static void _bind_methods(); public: + void set_next_pass(const Ref<Material> &p_pass); + Ref<Material> get_next_pass() const; + virtual RID get_rid() const; Material(); virtual ~Material(); }; -class FixedSpatialMaterial : public Material { +class ShaderMaterial : public Material { + + GDCLASS(ShaderMaterial, Material); + Ref<Shader> shader; + +protected: + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + void _get_property_list(List<PropertyInfo> *p_list) const; + + static void _bind_methods(); + + void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const; + +public: + void set_shader(const Ref<Shader> &p_shader); + Ref<Shader> get_shader() const; + + void set_shader_param(const StringName &p_param, const Variant &p_value); + Variant get_shader_param(const StringName &p_param) const; + + ShaderMaterial(); + ~ShaderMaterial(); +}; + +class SpatialMaterial : public Material { - GDCLASS(FixedSpatialMaterial, Material) + GDCLASS(SpatialMaterial, Material) public: enum TextureParam { TEXTURE_ALBEDO, - TEXTURE_SPECULAR, + TEXTURE_METALLIC, + TEXTURE_ROUGHNESS, TEXTURE_EMISSION, TEXTURE_NORMAL, TEXTURE_RIM, TEXTURE_CLEARCOAT, TEXTURE_FLOWMAP, TEXTURE_AMBIENT_OCCLUSION, - TEXTURE_HEIGHT, + TEXTURE_DEPTH, TEXTURE_SUBSURFACE_SCATTERING, TEXTURE_REFRACTION, - TEXTURE_REFRACTION_ROUGHNESS, TEXTURE_DETAIL_MASK, TEXTURE_DETAIL_ALBEDO, TEXTURE_DETAIL_NORMAL, @@ -94,7 +125,7 @@ public: FEATURE_CLEARCOAT, FEATURE_ANISOTROPY, FEATURE_AMBIENT_OCCLUSION, - FEATURE_HEIGHT_MAPPING, + FEATURE_DEPTH_MAPPING, FEATURE_SUBSURACE_SCATTERING, FEATURE_REFRACTION, FEATURE_DETAIL, @@ -124,42 +155,70 @@ public: enum Flags { FLAG_UNSHADED, + FLAG_USE_VERTEX_LIGHTING, FLAG_ONTOP, FLAG_ALBEDO_FROM_VERTEX_COLOR, FLAG_SRGB_VERTEX_COLOR, FLAG_USE_POINT_SIZE, + FLAG_FIXED_SIZE, + FLAG_UV1_USE_TRIPLANAR, + FLAG_UV2_USE_TRIPLANAR, + FLAG_AO_ON_UV2, + FLAG_USE_ALPHA_SCISSOR, FLAG_MAX }; enum DiffuseMode { DIFFUSE_LAMBERT, - DIFFUSE_LAMBERT_WRAP, + DIFFUSE_HALF_LAMBERT, DIFFUSE_OREN_NAYAR, DIFFUSE_BURLEY, + DIFFUSE_TOON, }; enum SpecularMode { - SPECULAR_MODE_METALLIC, - SPECULAR_MODE_SPECULAR, + SPECULAR_SCHLICK_GGX, + SPECULAR_BLINN, + SPECULAR_PHONG, + SPECULAR_TOON, + SPECULAR_DISABLED, + }; + + enum BillboardMode { + BILLBOARD_DISABLED, + BILLBOARD_ENABLED, + BILLBOARD_FIXED_Y, + BILLBOARD_PARTICLES, + }; + + enum TextureChannel { + TEXTURE_CHANNEL_RED, + TEXTURE_CHANNEL_GREEN, + TEXTURE_CHANNEL_BLUE, + TEXTURE_CHANNEL_ALPHA, + TEXTURE_CHANNEL_GRAYSCALE }; private: union MaterialKey { struct { - uint32_t feature_mask : 14; - uint32_t detail_uv : 1; - uint32_t blend_mode : 2; - uint32_t depth_draw_mode : 2; - uint32_t cull_mode : 2; - uint32_t flags : 5; - uint32_t detail_blend_mode : 2; - uint32_t diffuse_mode : 2; - uint32_t invalid_key : 1; - uint32_t specular_mode : 1; + uint64_t feature_mask : 11; + uint64_t detail_uv : 1; + uint64_t blend_mode : 2; + uint64_t depth_draw_mode : 2; + uint64_t cull_mode : 2; + uint64_t flags : 11; + uint64_t detail_blend_mode : 2; + uint64_t diffuse_mode : 3; + uint64_t specular_mode : 2; + uint64_t invalid_key : 1; + uint64_t deep_parallax : 1; + uint64_t billboard_mode : 2; + uint64_t grow : 1; }; - uint32_t key; + uint64_t key; bool operator<(const MaterialKey &p_key) const { return key < p_key.key; @@ -196,6 +255,9 @@ private: mk.detail_blend_mode = detail_blend_mode; mk.diffuse_mode = diffuse_mode; mk.specular_mode = specular_mode; + mk.billboard_mode = billboard_mode; + mk.deep_parallax = deep_parallax ? 1 : 0; + mk.grow = grow_enabled; return mk; } @@ -203,7 +265,7 @@ private: struct ShaderNames { StringName albedo; StringName specular; - StringName metalness; + StringName metallic; StringName roughness; StringName emission; StringName emission_energy; @@ -213,31 +275,48 @@ private: StringName clearcoat; StringName clearcoat_gloss; StringName anisotropy; - StringName height_scale; + StringName depth_scale; StringName subsurface_scattering_strength; StringName refraction; - StringName refraction_roughness; StringName point_size; StringName uv1_scale; StringName uv1_offset; StringName uv2_scale; StringName uv2_offset; + StringName particle_h_frames; + StringName particle_v_frames; + StringName particles_anim_loop; + StringName depth_min_layers; + StringName depth_max_layers; + StringName uv1_blend_sharpness; + StringName uv2_blend_sharpness; + StringName grow; + + StringName metallic_texture_channel; + StringName roughness_texture_channel; + StringName ao_texture_channel; + StringName clearcoat_texture_channel; + StringName rim_texture_channel; + StringName depth_texture_channel; + StringName refraction_texture_channel; + StringName alpha_scissor_threshold; + StringName texture_names[TEXTURE_MAX]; }; static Mutex *material_mutex; - static SelfList<FixedSpatialMaterial>::List dirty_materials; + static SelfList<SpatialMaterial>::List dirty_materials; static ShaderNames *shader_names; - SelfList<FixedSpatialMaterial> element; + SelfList<SpatialMaterial> element; void _update_shader(); _FORCE_INLINE_ void _queue_shader_change(); _FORCE_INLINE_ bool _is_shader_dirty() const; Color albedo; - Color specular; - float metalness; + float specular; + float metallic; float roughness; Color emission; float emission_energy; @@ -247,28 +326,45 @@ private: float clearcoat; float clearcoat_gloss; float anisotropy; - float height_scale; + float depth_scale; float subsurface_scattering_strength; float refraction; - float refraction_roughness; float line_width; float point_size; + float alpha_scissor_threshold; + bool grow_enabled; + float grow; + int particles_anim_h_frames; + int particles_anim_v_frames; + bool particles_anim_loop; - Vector2 uv1_scale; - Vector2 uv1_offset; + Vector3 uv1_scale; + Vector3 uv1_offset; + float uv1_triplanar_sharpness; - Vector2 uv2_scale; - Vector2 uv2_offset; + Vector3 uv2_scale; + Vector3 uv2_offset; + float uv2_triplanar_sharpness; DetailUV detail_uv; + bool deep_parallax; + int deep_parallax_min_layers; + int deep_parallax_max_layers; + BlendMode blend_mode; BlendMode detail_blend_mode; DepthDrawMode depth_draw_mode; CullMode cull_mode; bool flags[FLAG_MAX]; - DiffuseMode diffuse_mode; SpecularMode specular_mode; + DiffuseMode diffuse_mode; + BillboardMode billboard_mode; + + TextureChannel metallic_texture_channel; + TextureChannel roughness_texture_channel; + TextureChannel ao_texture_channel; + TextureChannel refraction_texture_channel; bool features[FEATURE_MAX]; @@ -276,6 +372,12 @@ private: _FORCE_INLINE_ void _validate_feature(const String &text, Feature feature, PropertyInfo &property) const; + enum { + MAX_MATERIALS_FOR_2D = 32 + }; + + static Ref<SpatialMaterial> materials_for_2d[MAX_MATERIALS_FOR_2D]; //used by Sprite3D and other stuff + protected: static void _bind_methods(); void _validate_property(PropertyInfo &property) const; @@ -284,14 +386,11 @@ public: void set_albedo(const Color &p_albedo); Color get_albedo() const; - void set_specular_mode(SpecularMode p_mode); - SpecularMode get_specular_mode() const; - - void set_specular(const Color &p_specular); - Color get_specular() const; + void set_specular(float p_specular); + float get_specular() const; - void set_metalness(float p_metalness); - float get_metalness() const; + void set_metallic(float p_metallic); + float get_metallic() const; void set_roughness(float p_roughness); float get_roughness() const; @@ -320,18 +419,24 @@ public: void set_anisotropy(float p_anisotropy); float get_anisotropy() const; - void set_height_scale(float p_height_scale); - float get_height_scale() const; + void set_depth_scale(float p_depth_scale); + float get_depth_scale() const; - void set_subsurface_scattering_strength(float p_strength); + void set_depth_deep_parallax(bool p_enable); + bool is_depth_deep_parallax_enabled() const; + + void set_depth_deep_parallax_min_layers(int p_layer); + int get_depth_deep_parallax_min_layers() const; + + void set_depth_deep_parallax_max_layers(int p_layer); + int get_depth_deep_parallax_max_layers() const; + + void set_subsurface_scattering_strength(float p_subsurface_scattering_strength); float get_subsurface_scattering_strength() const; void set_refraction(float p_refraction); float get_refraction() const; - void set_refraction_roughness(float p_refraction_roughness); - float get_refraction_roughness() const; - void set_line_width(float p_line_width); float get_line_width() const; @@ -356,6 +461,9 @@ public: void set_diffuse_mode(DiffuseMode p_mode); DiffuseMode get_diffuse_mode() const; + void set_specular_mode(SpecularMode p_mode); + SpecularMode get_specular_mode() const; + void set_flag(Flags p_flag, bool p_enabled); bool get_flag(Flags p_flag) const; @@ -365,35 +473,74 @@ public: void set_feature(Feature p_feature, bool p_enabled); bool get_feature(Feature p_feature) const; - void set_uv1_scale(const Vector2 &p_scale); - Vector2 get_uv1_scale() const; + void set_uv1_scale(const Vector3 &p_scale); + Vector3 get_uv1_scale() const; + + void set_uv1_offset(const Vector3 &p_offset); + Vector3 get_uv1_offset() const; + + void set_uv1_triplanar_blend_sharpness(float p_sharpness); + float get_uv1_triplanar_blend_sharpness() const; + + void set_uv2_scale(const Vector3 &p_scale); + Vector3 get_uv2_scale() const; + + void set_uv2_offset(const Vector3 &p_offset); + Vector3 get_uv2_offset() const; + + void set_uv2_triplanar_blend_sharpness(float p_sharpness); + float get_uv2_triplanar_blend_sharpness() const; - void set_uv1_offset(const Vector2 &p_offset); - Vector2 get_uv1_offset() const; + void set_billboard_mode(BillboardMode p_mode); + BillboardMode get_billboard_mode() const; - void set_uv2_scale(const Vector2 &p_scale); - Vector2 get_uv2_scale() const; + void set_particles_anim_h_frames(int p_frames); + int get_particles_anim_h_frames() const; + void set_particles_anim_v_frames(int p_frames); + int get_particles_anim_v_frames() const; - void set_uv2_offset(const Vector2 &p_offset); - Vector2 get_uv2_offset() const; + void set_particles_anim_loop(int p_frames); + int get_particles_anim_loop() const; + + void set_grow_enabled(bool p_enable); + bool is_grow_enabled() const; + + void set_grow(float p_grow); + float get_grow() const; + + void set_alpha_scissor_threshold(float p_treshold); + float get_alpha_scissor_threshold() const; + + void set_metallic_texture_channel(TextureChannel p_channel); + TextureChannel get_metallic_texture_channel() const; + void set_roughness_texture_channel(TextureChannel p_channel); + TextureChannel get_roughness_texture_channel() const; + void set_ao_texture_channel(TextureChannel p_channel); + TextureChannel get_ao_texture_channel() const; + void set_refraction_texture_channel(TextureChannel p_channel); + TextureChannel get_refraction_texture_channel() const; static void init_shaders(); static void finish_shaders(); static void flush_changes(); - FixedSpatialMaterial(); - virtual ~FixedSpatialMaterial(); + static RID get_material_rid_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass); + + SpatialMaterial(); + virtual ~SpatialMaterial(); }; -VARIANT_ENUM_CAST(FixedSpatialMaterial::TextureParam) -VARIANT_ENUM_CAST(FixedSpatialMaterial::DetailUV) -VARIANT_ENUM_CAST(FixedSpatialMaterial::Feature) -VARIANT_ENUM_CAST(FixedSpatialMaterial::BlendMode) -VARIANT_ENUM_CAST(FixedSpatialMaterial::DepthDrawMode) -VARIANT_ENUM_CAST(FixedSpatialMaterial::CullMode) -VARIANT_ENUM_CAST(FixedSpatialMaterial::Flags) -VARIANT_ENUM_CAST(FixedSpatialMaterial::DiffuseMode) -VARIANT_ENUM_CAST(FixedSpatialMaterial::SpecularMode) +VARIANT_ENUM_CAST(SpatialMaterial::TextureParam) +VARIANT_ENUM_CAST(SpatialMaterial::DetailUV) +VARIANT_ENUM_CAST(SpatialMaterial::Feature) +VARIANT_ENUM_CAST(SpatialMaterial::BlendMode) +VARIANT_ENUM_CAST(SpatialMaterial::DepthDrawMode) +VARIANT_ENUM_CAST(SpatialMaterial::CullMode) +VARIANT_ENUM_CAST(SpatialMaterial::Flags) +VARIANT_ENUM_CAST(SpatialMaterial::DiffuseMode) +VARIANT_ENUM_CAST(SpatialMaterial::SpecularMode) +VARIANT_ENUM_CAST(SpatialMaterial::BillboardMode) +VARIANT_ENUM_CAST(SpatialMaterial::TextureChannel) ////////////////////// diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index f951cf162..af30e75ae 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,6 +32,401 @@ #include "scene/resources/convex_polygon_shape.h" #include "surface_tool.h" +void Mesh::_clear_triangle_mesh() const { + + triangle_mesh.unref(); + ; +} + +Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { + + if (triangle_mesh.is_valid()) + return triangle_mesh; + + int facecount = 0; + + for (int i = 0; i < get_surface_count(); i++) { + + if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) + continue; + + if (surface_get_format(i) & ARRAY_FORMAT_INDEX) { + + facecount += surface_get_array_index_len(i); + } else { + + facecount += surface_get_array_len(i); + } + } + + if (facecount == 0 || (facecount % 3) != 0) + return triangle_mesh; + + PoolVector<Vector3> faces; + faces.resize(facecount); + PoolVector<Vector3>::Write facesw = faces.write(); + + int widx = 0; + + for (int i = 0; i < get_surface_count(); i++) { + + if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) + continue; + + Array a = surface_get_arrays(i); + + int vc = surface_get_array_len(i); + PoolVector<Vector3> vertices = a[ARRAY_VERTEX]; + PoolVector<Vector3>::Read vr = vertices.read(); + + if (surface_get_format(i) & ARRAY_FORMAT_INDEX) { + + int ic = surface_get_array_index_len(i); + PoolVector<int> indices = a[ARRAY_INDEX]; + PoolVector<int>::Read ir = indices.read(); + + for (int i = 0; i < ic; i++) { + int index = ir[i]; + facesw[widx++] = vr[index]; + } + + } else { + + for (int i = 0; i < vc; i++) + facesw[widx++] = vr[i]; + } + } + + facesw = PoolVector<Vector3>::Write(); + + triangle_mesh = Ref<TriangleMesh>(memnew(TriangleMesh)); + triangle_mesh->create(faces); + + return triangle_mesh; +} + +PoolVector<Face3> Mesh::get_faces() const { + + Ref<TriangleMesh> tm = generate_triangle_mesh(); + if (tm.is_valid()) + return tm->get_faces(); + return PoolVector<Face3>(); + /* + for (int i=0;i<surfaces.size();i++) { + + if (VisualServer::get_singleton()->mesh_surface_get_primitive_type( mesh, i ) != VisualServer::PRIMITIVE_TRIANGLES ) + continue; + + PoolVector<int> indices; + PoolVector<Vector3> vertices; + + vertices=VisualServer::get_singleton()->mesh_surface_get_array(mesh, i,VisualServer::ARRAY_VERTEX); + + int len=VisualServer::get_singleton()->mesh_surface_get_array_index_len(mesh, i); + bool has_indices; + + if (len>0) { + + indices=VisualServer::get_singleton()->mesh_surface_get_array(mesh, i,VisualServer::ARRAY_INDEX); + has_indices=true; + + } else { + + len=vertices.size(); + has_indices=false; + } + + if (len<=0) + continue; + + PoolVector<int>::Read indicesr = indices.read(); + const int *indicesptr = indicesr.ptr(); + + PoolVector<Vector3>::Read verticesr = vertices.read(); + const Vector3 *verticesptr = verticesr.ptr(); + + int old_faces=faces.size(); + int new_faces=old_faces+(len/3); + + faces.resize(new_faces); + + PoolVector<Face3>::Write facesw = faces.write(); + Face3 *facesptr=facesw.ptr(); + + + for (int i=0;i<len/3;i++) { + + Face3 face; + + for (int j=0;j<3;j++) { + + int idx=i*3+j; + face.vertex[j] = has_indices ? verticesptr[ indicesptr[ idx ] ] : verticesptr[idx]; + } + + facesptr[i+old_faces]=face; + } + + } +*/ +} + +Ref<Shape> Mesh::create_convex_shape() const { + + PoolVector<Vector3> vertices; + + for (int i = 0; i < get_surface_count(); i++) { + + Array a = surface_get_arrays(i); + PoolVector<Vector3> v = a[ARRAY_VERTEX]; + vertices.append_array(v); + } + + Ref<ConvexPolygonShape> shape = memnew(ConvexPolygonShape); + shape->set_points(vertices); + return shape; +} + +Ref<Shape> Mesh::create_trimesh_shape() const { + + PoolVector<Face3> faces = get_faces(); + if (faces.size() == 0) + return Ref<Shape>(); + + PoolVector<Vector3> face_points; + face_points.resize(faces.size() * 3); + + for (int i = 0; i < face_points.size(); i++) { + + Face3 f = faces.get(i / 3); + face_points.set(i, f.vertex[i % 3]); + } + + Ref<ConcavePolygonShape> shape = memnew(ConcavePolygonShape); + shape->set_faces(face_points); + return shape; +} + +Ref<Mesh> Mesh::create_outline(float p_margin) const { + + Array arrays; + int index_accum = 0; + for (int i = 0; i < get_surface_count(); i++) { + + if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) + continue; + + Array a = surface_get_arrays(i); + int vcount = 0; + + if (i == 0) { + arrays = a; + PoolVector<Vector3> v = a[ARRAY_VERTEX]; + index_accum += v.size(); + } else { + + for (int j = 0; j < arrays.size(); j++) { + + if (arrays[j].get_type() == Variant::NIL || a[j].get_type() == Variant::NIL) { + //mismatch, do not use + arrays[j] = Variant(); + continue; + } + + switch (j) { + + case ARRAY_VERTEX: + case ARRAY_NORMAL: { + + PoolVector<Vector3> dst = arrays[j]; + PoolVector<Vector3> src = a[j]; + if (j == ARRAY_VERTEX) + vcount = src.size(); + if (dst.size() == 0 || src.size() == 0) { + arrays[j] = Variant(); + continue; + } + dst.append_array(src); + arrays[j] = dst; + } break; + case ARRAY_TANGENT: + case ARRAY_BONES: + case ARRAY_WEIGHTS: { + + PoolVector<real_t> dst = arrays[j]; + PoolVector<real_t> src = a[j]; + if (dst.size() == 0 || src.size() == 0) { + arrays[j] = Variant(); + continue; + } + dst.append_array(src); + arrays[j] = dst; + + } break; + case ARRAY_COLOR: { + PoolVector<Color> dst = arrays[j]; + PoolVector<Color> src = a[j]; + if (dst.size() == 0 || src.size() == 0) { + arrays[j] = Variant(); + continue; + } + dst.append_array(src); + arrays[j] = dst; + + } break; + case ARRAY_TEX_UV: + case ARRAY_TEX_UV2: { + PoolVector<Vector2> dst = arrays[j]; + PoolVector<Vector2> src = a[j]; + if (dst.size() == 0 || src.size() == 0) { + arrays[j] = Variant(); + continue; + } + dst.append_array(src); + arrays[j] = dst; + + } break; + case ARRAY_INDEX: { + PoolVector<int> dst = arrays[j]; + PoolVector<int> src = a[j]; + if (dst.size() == 0 || src.size() == 0) { + arrays[j] = Variant(); + continue; + } + { + int ss = src.size(); + PoolVector<int>::Write w = src.write(); + for (int k = 0; k < ss; k++) { + w[k] += index_accum; + } + } + dst.append_array(src); + arrays[j] = dst; + index_accum += vcount; + + } break; + } + } + } + } + + { + PoolVector<int>::Write ir; + PoolVector<int> indices = arrays[ARRAY_INDEX]; + bool has_indices = false; + PoolVector<Vector3> vertices = arrays[ARRAY_VERTEX]; + int vc = vertices.size(); + ERR_FAIL_COND_V(!vc, Ref<ArrayMesh>()); + PoolVector<Vector3>::Write r = vertices.write(); + + if (indices.size()) { + vc = indices.size(); + ir = indices.write(); + has_indices = true; + } + + Map<Vector3, Vector3> normal_accum; + + //fill normals with triangle normals + for (int i = 0; i < vc; i += 3) { + + Vector3 t[3]; + + if (has_indices) { + t[0] = r[ir[i + 0]]; + t[1] = r[ir[i + 1]]; + t[2] = r[ir[i + 2]]; + } else { + t[0] = r[i + 0]; + t[1] = r[i + 1]; + t[2] = r[i + 2]; + } + + Vector3 n = Plane(t[0], t[1], t[2]).normal; + + for (int j = 0; j < 3; j++) { + + Map<Vector3, Vector3>::Element *E = normal_accum.find(t[j]); + if (!E) { + normal_accum[t[j]] = n; + } else { + float d = n.dot(E->get()); + if (d < 1.0) + E->get() += n * (1.0 - d); + //E->get()+=n; + } + } + } + + //normalize + + for (Map<Vector3, Vector3>::Element *E = normal_accum.front(); E; E = E->next()) { + E->get().normalize(); + } + + //displace normals + int vc2 = vertices.size(); + + for (int i = 0; i < vc2; i++) { + + Vector3 t = r[i]; + + Map<Vector3, Vector3>::Element *E = normal_accum.find(t); + ERR_CONTINUE(!E); + + t += E->get() * p_margin; + r[i] = t; + } + + r = PoolVector<Vector3>::Write(); + arrays[ARRAY_VERTEX] = vertices; + + if (!has_indices) { + + PoolVector<int> new_indices; + new_indices.resize(vertices.size()); + PoolVector<int>::Write iw = new_indices.write(); + + for (int j = 0; j < vc2; j += 3) { + + iw[j] = j; + iw[j + 1] = j + 2; + iw[j + 2] = j + 1; + } + + iw = PoolVector<int>::Write(); + arrays[ARRAY_INDEX] = new_indices; + + } else { + + for (int j = 0; j < vc; j += 3) { + + SWAP(ir[j + 1], ir[j + 2]); + } + ir = PoolVector<int>::Write(); + arrays[ARRAY_INDEX] = indices; + } + } + + Ref<ArrayMesh> newmesh = memnew(ArrayMesh); + newmesh->add_surface_from_arrays(PRIMITIVE_TRIANGLES, arrays); + return newmesh; +} + +void Mesh::_bind_methods() { + + BIND_CONSTANT(PRIMITIVE_POINTS); + BIND_CONSTANT(PRIMITIVE_LINES); + BIND_CONSTANT(PRIMITIVE_LINE_STRIP); + BIND_CONSTANT(PRIMITIVE_LINE_LOOP); + BIND_CONSTANT(PRIMITIVE_TRIANGLES); + BIND_CONSTANT(PRIMITIVE_TRIANGLE_STRIP); + BIND_CONSTANT(PRIMITIVE_TRIANGLE_FAN); +} + +Mesh::Mesh() { +} + static const char *_array_name[] = { "vertex_array", "normal_array", @@ -44,34 +440,34 @@ static const char *_array_name[] = { NULL }; -static const Mesh::ArrayType _array_types[] = { +static const ArrayMesh::ArrayType _array_types[] = { - Mesh::ARRAY_VERTEX, - Mesh::ARRAY_NORMAL, - Mesh::ARRAY_TANGENT, - Mesh::ARRAY_COLOR, - Mesh::ARRAY_TEX_UV, - Mesh::ARRAY_TEX_UV2, - Mesh::ARRAY_BONES, - Mesh::ARRAY_WEIGHTS, - Mesh::ARRAY_INDEX + ArrayMesh::ARRAY_VERTEX, + ArrayMesh::ARRAY_NORMAL, + ArrayMesh::ARRAY_TANGENT, + ArrayMesh::ARRAY_COLOR, + ArrayMesh::ARRAY_TEX_UV, + ArrayMesh::ARRAY_TEX_UV2, + ArrayMesh::ARRAY_BONES, + ArrayMesh::ARRAY_WEIGHTS, + ArrayMesh::ARRAY_INDEX }; /* compatibility */ static const int _format_translate[] = { - Mesh::ARRAY_FORMAT_VERTEX, - Mesh::ARRAY_FORMAT_NORMAL, - Mesh::ARRAY_FORMAT_TANGENT, - Mesh::ARRAY_FORMAT_COLOR, - Mesh::ARRAY_FORMAT_TEX_UV, - Mesh::ARRAY_FORMAT_TEX_UV2, - Mesh::ARRAY_FORMAT_BONES, - Mesh::ARRAY_FORMAT_WEIGHTS, - Mesh::ARRAY_FORMAT_INDEX, + ArrayMesh::ARRAY_FORMAT_VERTEX, + ArrayMesh::ARRAY_FORMAT_NORMAL, + ArrayMesh::ARRAY_FORMAT_TANGENT, + ArrayMesh::ARRAY_FORMAT_COLOR, + ArrayMesh::ARRAY_FORMAT_TEX_UV, + ArrayMesh::ARRAY_FORMAT_TEX_UV2, + ArrayMesh::ARRAY_FORMAT_BONES, + ArrayMesh::ARRAY_FORMAT_WEIGHTS, + ArrayMesh::ARRAY_FORMAT_INDEX, }; -bool Mesh::_set(const StringName &p_name, const Variant &p_value) { +bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { String sname = p_name; @@ -190,7 +586,10 @@ bool Mesh::_set(const StringName &p_name, const Variant &p_value) { return false; } -bool Mesh::_get(const StringName &p_name, Variant &r_ret) const { +bool ArrayMesh::_get(const StringName &p_name, Variant &r_ret) const { + + if (_is_generated()) + return false; String sname = p_name; @@ -266,7 +665,10 @@ bool Mesh::_get(const StringName &p_name, Variant &r_ret) const { return true; } -void Mesh::_get_property_list(List<PropertyInfo> *p_list) const { +void ArrayMesh::_get_property_list(List<PropertyInfo> *p_list) const { + + if (_is_generated()) + return; if (blend_shapes.size()) { p_list->push_back(PropertyInfo(Variant::POOL_STRING_ARRAY, "blend_shape/names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); @@ -277,13 +679,17 @@ void Mesh::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::DICTIONARY, "surfaces/" + itos(i), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); p_list->push_back(PropertyInfo(Variant::STRING, "surface_" + itos(i + 1) + "/name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i + 1) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "Material", PROPERTY_USAGE_EDITOR)); + if (surfaces[i].is_2d) { + p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i + 1) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,CanvasItemMaterial", PROPERTY_USAGE_EDITOR)); + } else { + p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i + 1) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,SpatialMaterial", PROPERTY_USAGE_EDITOR)); + } } p_list->push_back(PropertyInfo(Variant::RECT3, "custom_aabb/custom_aabb")); } -void Mesh::_recompute_aabb() { +void ArrayMesh::_recompute_aabb() { // regenerate AABB aabb = Rect3(); @@ -297,16 +703,18 @@ void Mesh::_recompute_aabb() { } } -void Mesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const Rect3 &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes, const Vector<Rect3> &p_bone_aabbs) { +void ArrayMesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const Rect3 &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes, const Vector<Rect3> &p_bone_aabbs) { Surface s; s.aabb = p_aabb; + s.is_2d = p_format & ARRAY_FLAG_USE_2D_VERTICES; surfaces.push_back(s); + _recompute_aabb(); VisualServer::get_singleton()->mesh_add_surface(mesh, p_format, (VS::PrimitiveType)p_primitive, p_array, p_vertex_count, p_index_array, p_index_count, p_aabb, p_blend_shapes, p_bone_aabbs); } -void Mesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, uint32_t p_flags) { +void ArrayMesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, uint32_t p_flags) { ERR_FAIL_COND(p_arrays.size() != ARRAY_MAX); @@ -317,7 +725,8 @@ void Mesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arr /* make aABB? */ { - PoolVector<Vector3> vertices = p_arrays[ARRAY_VERTEX]; + Variant arr = p_arrays[ARRAY_VERTEX]; + PoolVector<Vector3> vertices = arr; int len = vertices.size(); ERR_FAIL_COND(len == 0); PoolVector<Vector3>::Read r = vertices.read(); @@ -328,38 +737,39 @@ void Mesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arr for (int i = 0; i < len; i++) { if (i == 0) - aabb.pos = vtx[i]; + aabb.position = vtx[i]; else aabb.expand_to(vtx[i]); } surfaces[surfaces.size() - 1].aabb = aabb; + surfaces[surfaces.size() - 1].is_2d = arr.get_type() == Variant::POOL_VECTOR2_ARRAY; _recompute_aabb(); } - triangle_mesh = Ref<TriangleMesh>(); + _clear_triangle_mesh(); _change_notify(); emit_changed(); } -Array Mesh::surface_get_arrays(int p_surface) const { +Array ArrayMesh::surface_get_arrays(int p_surface) const { ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array()); return VisualServer::get_singleton()->mesh_surface_get_arrays(mesh, p_surface); } -Array Mesh::surface_get_blend_shape_arrays(int p_surface) const { +Array ArrayMesh::surface_get_blend_shape_arrays(int p_surface) const { ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array()); return Array(); } -int Mesh::get_surface_count() const { +int ArrayMesh::get_surface_count() const { return surfaces.size(); } -void Mesh::add_blend_shape(const StringName &p_name) { +void ArrayMesh::add_blend_shape(const StringName &p_name) { if (surfaces.size()) { ERR_EXPLAIN("Can't add a shape key count if surfaces are already created."); @@ -382,15 +792,15 @@ void Mesh::add_blend_shape(const StringName &p_name) { VS::get_singleton()->mesh_set_blend_shape_count(mesh, blend_shapes.size()); } -int Mesh::get_blend_shape_count() const { +int ArrayMesh::get_blend_shape_count() const { return blend_shapes.size(); } -StringName Mesh::get_blend_shape_name(int p_index) const { +StringName ArrayMesh::get_blend_shape_name(int p_index) const { ERR_FAIL_INDEX_V(p_index, blend_shapes.size(), StringName()); return blend_shapes[p_index]; } -void Mesh::clear_blend_shapes() { +void ArrayMesh::clear_blend_shapes() { if (surfaces.size()) { ERR_EXPLAIN("Can't set shape key count if surfaces are already created."); @@ -400,54 +810,54 @@ void Mesh::clear_blend_shapes() { blend_shapes.clear(); } -void Mesh::set_blend_shape_mode(BlendShapeMode p_mode) { +void ArrayMesh::set_blend_shape_mode(BlendShapeMode p_mode) { blend_shape_mode = p_mode; VS::get_singleton()->mesh_set_blend_shape_mode(mesh, (VS::BlendShapeMode)p_mode); } -Mesh::BlendShapeMode Mesh::get_blend_shape_mode() const { +ArrayMesh::BlendShapeMode ArrayMesh::get_blend_shape_mode() const { return blend_shape_mode; } -void Mesh::surface_remove(int p_idx) { +void ArrayMesh::surface_remove(int p_idx) { ERR_FAIL_INDEX(p_idx, surfaces.size()); VisualServer::get_singleton()->mesh_remove_surface(mesh, p_idx); surfaces.remove(p_idx); - triangle_mesh = Ref<TriangleMesh>(); + _clear_triangle_mesh(); _recompute_aabb(); _change_notify(); emit_changed(); } -int Mesh::surface_get_array_len(int p_idx) const { +int ArrayMesh::surface_get_array_len(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, surfaces.size(), -1); return VisualServer::get_singleton()->mesh_surface_get_array_len(mesh, p_idx); } -int Mesh::surface_get_array_index_len(int p_idx) const { +int ArrayMesh::surface_get_array_index_len(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, surfaces.size(), -1); return VisualServer::get_singleton()->mesh_surface_get_array_index_len(mesh, p_idx); } -uint32_t Mesh::surface_get_format(int p_idx) const { +uint32_t ArrayMesh::surface_get_format(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, surfaces.size(), 0); return VisualServer::get_singleton()->mesh_surface_get_format(mesh, p_idx); } -Mesh::PrimitiveType Mesh::surface_get_primitive_type(int p_idx) const { +ArrayMesh::PrimitiveType ArrayMesh::surface_get_primitive_type(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, surfaces.size(), PRIMITIVE_LINES); return (PrimitiveType)VisualServer::get_singleton()->mesh_surface_get_primitive_type(mesh, p_idx); } -void Mesh::surface_set_material(int p_idx, const Ref<Material> &p_material) { +void ArrayMesh::surface_set_material(int p_idx, const Ref<Material> &p_material) { ERR_FAIL_INDEX(p_idx, surfaces.size()); if (surfaces[p_idx].material == p_material) @@ -458,40 +868,40 @@ void Mesh::surface_set_material(int p_idx, const Ref<Material> &p_material) { _change_notify("material"); } -void Mesh::surface_set_name(int p_idx, const String &p_name) { +void ArrayMesh::surface_set_name(int p_idx, const String &p_name) { ERR_FAIL_INDEX(p_idx, surfaces.size()); surfaces[p_idx].name = p_name; } -String Mesh::surface_get_name(int p_idx) const { +String ArrayMesh::surface_get_name(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, surfaces.size(), String()); return surfaces[p_idx].name; } -void Mesh::surface_set_custom_aabb(int p_idx, const Rect3 &p_aabb) { +void ArrayMesh::surface_set_custom_aabb(int p_idx, const Rect3 &p_aabb) { ERR_FAIL_INDEX(p_idx, surfaces.size()); surfaces[p_idx].aabb = p_aabb; // set custom aabb too? } -Ref<Material> Mesh::surface_get_material(int p_idx) const { +Ref<Material> ArrayMesh::surface_get_material(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, surfaces.size(), Ref<Material>()); return surfaces[p_idx].material; } -void Mesh::add_surface_from_mesh_data(const Geometry::MeshData &p_mesh_data) { +void ArrayMesh::add_surface_from_mesh_data(const Geometry::MeshData &p_mesh_data) { VisualServer::get_singleton()->mesh_add_surface_from_mesh_data(mesh, p_mesh_data); Rect3 aabb; for (int i = 0; i < p_mesh_data.vertices.size(); i++) { if (i == 0) - aabb.pos = p_mesh_data.vertices[i]; + aabb.position = p_mesh_data.vertices[i]; else aabb.expand_to(p_mesh_data.vertices[i]); } @@ -503,7 +913,7 @@ void Mesh::add_surface_from_mesh_data(const Geometry::MeshData &p_mesh_data) { else aabb.merge_with(s.aabb); - triangle_mesh = Ref<TriangleMesh>(); + _clear_triangle_mesh(); surfaces.push_back(s); _change_notify(); @@ -511,129 +921,27 @@ void Mesh::add_surface_from_mesh_data(const Geometry::MeshData &p_mesh_data) { emit_changed(); } -RID Mesh::get_rid() const { +RID ArrayMesh::get_rid() const { return mesh; } -Rect3 Mesh::get_aabb() const { +Rect3 ArrayMesh::get_aabb() const { return aabb; } -void Mesh::set_custom_aabb(const Rect3 &p_custom) { +void ArrayMesh::set_custom_aabb(const Rect3 &p_custom) { custom_aabb = p_custom; VS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb); } -Rect3 Mesh::get_custom_aabb() const { +Rect3 ArrayMesh::get_custom_aabb() const { return custom_aabb; } -PoolVector<Face3> Mesh::get_faces() const { - - Ref<TriangleMesh> tm = generate_triangle_mesh(); - if (tm.is_valid()) - return tm->get_faces(); - return PoolVector<Face3>(); - /* - for (int i=0;i<surfaces.size();i++) { - - if (VisualServer::get_singleton()->mesh_surface_get_primitive_type( mesh, i ) != VisualServer::PRIMITIVE_TRIANGLES ) - continue; - - PoolVector<int> indices; - PoolVector<Vector3> vertices; - - vertices=VisualServer::get_singleton()->mesh_surface_get_array(mesh, i,VisualServer::ARRAY_VERTEX); - - int len=VisualServer::get_singleton()->mesh_surface_get_array_index_len(mesh, i); - bool has_indices; - - if (len>0) { - - indices=VisualServer::get_singleton()->mesh_surface_get_array(mesh, i,VisualServer::ARRAY_INDEX); - has_indices=true; - - } else { - - len=vertices.size(); - has_indices=false; - } - - if (len<=0) - continue; - - PoolVector<int>::Read indicesr = indices.read(); - const int *indicesptr = indicesr.ptr(); - - PoolVector<Vector3>::Read verticesr = vertices.read(); - const Vector3 *verticesptr = verticesr.ptr(); - - int old_faces=faces.size(); - int new_faces=old_faces+(len/3); - - faces.resize(new_faces); - - PoolVector<Face3>::Write facesw = faces.write(); - Face3 *facesptr=facesw.ptr(); - - - for (int i=0;i<len/3;i++) { - - Face3 face; - - for (int j=0;j<3;j++) { - - int idx=i*3+j; - face.vertex[j] = has_indices ? verticesptr[ indicesptr[ idx ] ] : verticesptr[idx]; - } - - facesptr[i+old_faces]=face; - } - - } -*/ -} - -Ref<Shape> Mesh::create_convex_shape() const { - - PoolVector<Vector3> vertices; - - for (int i = 0; i < get_surface_count(); i++) { - - Array a = surface_get_arrays(i); - PoolVector<Vector3> v = a[ARRAY_VERTEX]; - vertices.append_array(v); - } - - Ref<ConvexPolygonShape> shape = memnew(ConvexPolygonShape); - shape->set_points(vertices); - return shape; -} - -Ref<Shape> Mesh::create_trimesh_shape() const { - - PoolVector<Face3> faces = get_faces(); - if (faces.size() == 0) - return Ref<Shape>(); - - PoolVector<Vector3> face_points; - face_points.resize(faces.size() * 3); - - for (int i = 0; i < face_points.size(); i++) { - - Face3 f = faces.get(i / 3); - face_points.set(i, f.vertex[i % 3]); - } - - Ref<ConcavePolygonShape> shape = memnew(ConcavePolygonShape); - shape->set_faces(face_points); - return shape; -} - -void Mesh::center_geometry() { +void ArrayMesh::center_geometry() { /* Vector3 ofs = aabb.pos+aabb.size*0.5; @@ -661,13 +969,13 @@ void Mesh::center_geometry() { */ } -void Mesh::regen_normalmaps() { +void ArrayMesh::regen_normalmaps() { Vector<Ref<SurfaceTool> > surfs; for (int i = 0; i < get_surface_count(); i++) { Ref<SurfaceTool> st = memnew(SurfaceTool); - st->create_from(Ref<Mesh>(this), i); + st->create_from(Ref<ArrayMesh>(this), i); surfs.push_back(st); } @@ -678,310 +986,42 @@ void Mesh::regen_normalmaps() { for (int i = 0; i < surfs.size(); i++) { surfs[i]->generate_tangents(); - surfs[i]->commit(Ref<Mesh>(this)); - } -} - -Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { - - if (triangle_mesh.is_valid()) - return triangle_mesh; - - int facecount = 0; - - for (int i = 0; i < get_surface_count(); i++) { - - if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) - continue; - - if (surface_get_format(i) & ARRAY_FORMAT_INDEX) { - - facecount += surface_get_array_index_len(i); - } else { - - facecount += surface_get_array_len(i); - } - } - - if (facecount == 0 || (facecount % 3) != 0) - return triangle_mesh; - - PoolVector<Vector3> faces; - faces.resize(facecount); - PoolVector<Vector3>::Write facesw = faces.write(); - - int widx = 0; - - for (int i = 0; i < get_surface_count(); i++) { - - if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) - continue; - - Array a = surface_get_arrays(i); - - int vc = surface_get_array_len(i); - PoolVector<Vector3> vertices = a[ARRAY_VERTEX]; - PoolVector<Vector3>::Read vr = vertices.read(); - - if (surface_get_format(i) & ARRAY_FORMAT_INDEX) { - - int ic = surface_get_array_index_len(i); - PoolVector<int> indices = a[ARRAY_INDEX]; - PoolVector<int>::Read ir = indices.read(); - - for (int i = 0; i < ic; i++) { - int index = ir[i]; - facesw[widx++] = vr[index]; - } - - } else { - - for (int i = 0; i < vc; i++) - facesw[widx++] = vr[i]; - } - } - - facesw = PoolVector<Vector3>::Write(); - - triangle_mesh = Ref<TriangleMesh>(memnew(TriangleMesh)); - triangle_mesh->create(faces); - - return triangle_mesh; -} - -Ref<Mesh> Mesh::create_outline(float p_margin) const { - - Array arrays; - int index_accum = 0; - for (int i = 0; i < get_surface_count(); i++) { - - if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) - continue; - - Array a = surface_get_arrays(i); - int vcount = 0; - - if (i == 0) { - arrays = a; - PoolVector<Vector3> v = a[ARRAY_VERTEX]; - index_accum += v.size(); - } else { - - for (int j = 0; j < arrays.size(); j++) { - - if (arrays[j].get_type() == Variant::NIL || a[j].get_type() == Variant::NIL) { - //mismatch, do not use - arrays[j] = Variant(); - continue; - } - - switch (j) { - - case ARRAY_VERTEX: - case ARRAY_NORMAL: { - - PoolVector<Vector3> dst = arrays[j]; - PoolVector<Vector3> src = a[j]; - if (j == ARRAY_VERTEX) - vcount = src.size(); - if (dst.size() == 0 || src.size() == 0) { - arrays[j] = Variant(); - continue; - } - dst.append_array(src); - arrays[j] = dst; - } break; - case ARRAY_TANGENT: - case ARRAY_BONES: - case ARRAY_WEIGHTS: { - - PoolVector<real_t> dst = arrays[j]; - PoolVector<real_t> src = a[j]; - if (dst.size() == 0 || src.size() == 0) { - arrays[j] = Variant(); - continue; - } - dst.append_array(src); - arrays[j] = dst; - - } break; - case ARRAY_COLOR: { - PoolVector<Color> dst = arrays[j]; - PoolVector<Color> src = a[j]; - if (dst.size() == 0 || src.size() == 0) { - arrays[j] = Variant(); - continue; - } - dst.append_array(src); - arrays[j] = dst; - - } break; - case ARRAY_TEX_UV: - case ARRAY_TEX_UV2: { - PoolVector<Vector2> dst = arrays[j]; - PoolVector<Vector2> src = a[j]; - if (dst.size() == 0 || src.size() == 0) { - arrays[j] = Variant(); - continue; - } - dst.append_array(src); - arrays[j] = dst; - - } break; - case ARRAY_INDEX: { - PoolVector<int> dst = arrays[j]; - PoolVector<int> src = a[j]; - if (dst.size() == 0 || src.size() == 0) { - arrays[j] = Variant(); - continue; - } - { - int ss = src.size(); - PoolVector<int>::Write w = src.write(); - for (int k = 0; k < ss; k++) { - w[k] += index_accum; - } - } - dst.append_array(src); - arrays[j] = dst; - index_accum += vcount; - - } break; - } - } - } + surfs[i]->commit(Ref<ArrayMesh>(this)); } - - { - PoolVector<int>::Write ir; - PoolVector<int> indices = arrays[ARRAY_INDEX]; - bool has_indices = false; - PoolVector<Vector3> vertices = arrays[ARRAY_VERTEX]; - int vc = vertices.size(); - ERR_FAIL_COND_V(!vc, Ref<Mesh>()); - PoolVector<Vector3>::Write r = vertices.write(); - - if (indices.size()) { - vc = indices.size(); - ir = indices.write(); - has_indices = true; - } - - Map<Vector3, Vector3> normal_accum; - - //fill normals with triangle normals - for (int i = 0; i < vc; i += 3) { - - Vector3 t[3]; - - if (has_indices) { - t[0] = r[ir[i + 0]]; - t[1] = r[ir[i + 1]]; - t[2] = r[ir[i + 2]]; - } else { - t[0] = r[i + 0]; - t[1] = r[i + 1]; - t[2] = r[i + 2]; - } - - Vector3 n = Plane(t[0], t[1], t[2]).normal; - - for (int j = 0; j < 3; j++) { - - Map<Vector3, Vector3>::Element *E = normal_accum.find(t[j]); - if (!E) { - normal_accum[t[j]] = n; - } else { - float d = n.dot(E->get()); - if (d < 1.0) - E->get() += n * (1.0 - d); - //E->get()+=n; - } - } - } - - //normalize - - for (Map<Vector3, Vector3>::Element *E = normal_accum.front(); E; E = E->next()) { - E->get().normalize(); - } - - //displace normals - int vc2 = vertices.size(); - - for (int i = 0; i < vc2; i++) { - - Vector3 t = r[i]; - - Map<Vector3, Vector3>::Element *E = normal_accum.find(t); - ERR_CONTINUE(!E); - - t += E->get() * p_margin; - r[i] = t; - } - - r = PoolVector<Vector3>::Write(); - arrays[ARRAY_VERTEX] = vertices; - - if (!has_indices) { - - PoolVector<int> new_indices; - new_indices.resize(vertices.size()); - PoolVector<int>::Write iw = new_indices.write(); - - for (int j = 0; j < vc2; j += 3) { - - iw[j] = j; - iw[j + 1] = j + 2; - iw[j + 2] = j + 1; - } - - iw = PoolVector<int>::Write(); - arrays[ARRAY_INDEX] = new_indices; - - } else { - - for (int j = 0; j < vc; j += 3) { - - SWAP(ir[j + 1], ir[j + 2]); - } - ir = PoolVector<int>::Write(); - arrays[ARRAY_INDEX] = indices; - } - } - - Ref<Mesh> newmesh = memnew(Mesh); - newmesh->add_surface_from_arrays(PRIMITIVE_TRIANGLES, arrays); - return newmesh; } -void Mesh::_bind_methods() { +void ArrayMesh::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_blend_shape", "name"), &Mesh::add_blend_shape); - ClassDB::bind_method(D_METHOD("get_blend_shape_count"), &Mesh::get_blend_shape_count); - ClassDB::bind_method(D_METHOD("get_blend_shape_name", "index"), &Mesh::get_blend_shape_name); - ClassDB::bind_method(D_METHOD("clear_blend_shapes"), &Mesh::clear_blend_shapes); - ClassDB::bind_method(D_METHOD("set_blend_shape_mode", "mode"), &Mesh::set_blend_shape_mode); - ClassDB::bind_method(D_METHOD("get_blend_shape_mode"), &Mesh::get_blend_shape_mode); + ClassDB::bind_method(D_METHOD("add_blend_shape", "name"), &ArrayMesh::add_blend_shape); + ClassDB::bind_method(D_METHOD("get_blend_shape_count"), &ArrayMesh::get_blend_shape_count); + ClassDB::bind_method(D_METHOD("get_blend_shape_name", "index"), &ArrayMesh::get_blend_shape_name); + ClassDB::bind_method(D_METHOD("clear_blend_shapes"), &ArrayMesh::clear_blend_shapes); + ClassDB::bind_method(D_METHOD("set_blend_shape_mode", "mode"), &ArrayMesh::set_blend_shape_mode); + ClassDB::bind_method(D_METHOD("get_blend_shape_mode"), &ArrayMesh::get_blend_shape_mode); - ClassDB::bind_method(D_METHOD("add_surface_from_arrays", "primitive", "arrays", "blend_shapes", "compress_flags"), &Mesh::add_surface_from_arrays, DEFVAL(Array()), DEFVAL(ARRAY_COMPRESS_DEFAULT)); - ClassDB::bind_method(D_METHOD("get_surface_count"), &Mesh::get_surface_count); - ClassDB::bind_method(D_METHOD("surface_remove", "surf_idx"), &Mesh::surface_remove); - ClassDB::bind_method(D_METHOD("surface_get_array_len", "surf_idx"), &Mesh::surface_get_array_len); - ClassDB::bind_method(D_METHOD("surface_get_array_index_len", "surf_idx"), &Mesh::surface_get_array_index_len); - ClassDB::bind_method(D_METHOD("surface_get_format", "surf_idx"), &Mesh::surface_get_format); - ClassDB::bind_method(D_METHOD("surface_get_primitive_type", "surf_idx"), &Mesh::surface_get_primitive_type); - ClassDB::bind_method(D_METHOD("surface_set_material", "surf_idx", "material:Material"), &Mesh::surface_set_material); - ClassDB::bind_method(D_METHOD("surface_get_material:Material", "surf_idx"), &Mesh::surface_get_material); - ClassDB::bind_method(D_METHOD("surface_set_name", "surf_idx", "name"), &Mesh::surface_set_name); - ClassDB::bind_method(D_METHOD("surface_get_name", "surf_idx"), &Mesh::surface_get_name); - ClassDB::bind_method(D_METHOD("center_geometry"), &Mesh::center_geometry); + ClassDB::bind_method(D_METHOD("add_surface_from_arrays", "primitive", "arrays", "blend_shapes", "compress_flags"), &ArrayMesh::add_surface_from_arrays, DEFVAL(Array()), DEFVAL(ARRAY_COMPRESS_DEFAULT)); + ClassDB::bind_method(D_METHOD("get_surface_count"), &ArrayMesh::get_surface_count); + ClassDB::bind_method(D_METHOD("surface_remove", "surf_idx"), &ArrayMesh::surface_remove); + ClassDB::bind_method(D_METHOD("surface_get_array_len", "surf_idx"), &ArrayMesh::surface_get_array_len); + ClassDB::bind_method(D_METHOD("surface_get_array_index_len", "surf_idx"), &ArrayMesh::surface_get_array_index_len); + ClassDB::bind_method(D_METHOD("surface_get_format", "surf_idx"), &ArrayMesh::surface_get_format); + ClassDB::bind_method(D_METHOD("surface_get_primitive_type", "surf_idx"), &ArrayMesh::surface_get_primitive_type); + ClassDB::bind_method(D_METHOD("surface_set_material", "surf_idx", "material"), &ArrayMesh::surface_set_material); + ClassDB::bind_method(D_METHOD("surface_get_material", "surf_idx"), &ArrayMesh::surface_get_material); + ClassDB::bind_method(D_METHOD("surface_set_name", "surf_idx", "name"), &ArrayMesh::surface_set_name); + ClassDB::bind_method(D_METHOD("surface_get_name", "surf_idx"), &ArrayMesh::surface_get_name); + ClassDB::bind_method(D_METHOD("create_trimesh_shape"), &ArrayMesh::create_trimesh_shape); + ClassDB::bind_method(D_METHOD("create_convex_shape"), &ArrayMesh::create_convex_shape); + ClassDB::bind_method(D_METHOD("create_outline", "margin"), &ArrayMesh::create_outline); + ClassDB::bind_method(D_METHOD("center_geometry"), &ArrayMesh::center_geometry); ClassDB::set_method_flags(get_class_static(), _scs_create("center_geometry"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); - ClassDB::bind_method(D_METHOD("regen_normalmaps"), &Mesh::regen_normalmaps); + ClassDB::bind_method(D_METHOD("regen_normalmaps"), &ArrayMesh::regen_normalmaps); ClassDB::set_method_flags(get_class_static(), _scs_create("regen_normalmaps"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); + ClassDB::bind_method(D_METHOD("get_faces"), &ArrayMesh::get_faces); + ClassDB::bind_method(D_METHOD("generate_triangle_mesh"), &ArrayMesh::generate_triangle_mesh); - ClassDB::bind_method(D_METHOD("set_custom_aabb", "aabb"), &Mesh::set_custom_aabb); - ClassDB::bind_method(D_METHOD("get_custom_aabb"), &Mesh::get_custom_aabb); + ClassDB::bind_method(D_METHOD("set_custom_aabb", "aabb"), &ArrayMesh::set_custom_aabb); + ClassDB::bind_method(D_METHOD("get_custom_aabb"), &ArrayMesh::get_custom_aabb); BIND_CONSTANT(NO_INDEX_ARRAY); BIND_CONSTANT(ARRAY_WEIGHTS_SIZE); @@ -1005,23 +1045,15 @@ void Mesh::_bind_methods() { BIND_CONSTANT(ARRAY_FORMAT_BONES); BIND_CONSTANT(ARRAY_FORMAT_WEIGHTS); BIND_CONSTANT(ARRAY_FORMAT_INDEX); - - BIND_CONSTANT(PRIMITIVE_POINTS); - BIND_CONSTANT(PRIMITIVE_LINES); - BIND_CONSTANT(PRIMITIVE_LINE_STRIP); - BIND_CONSTANT(PRIMITIVE_LINE_LOOP); - BIND_CONSTANT(PRIMITIVE_TRIANGLES); - BIND_CONSTANT(PRIMITIVE_TRIANGLE_STRIP); - BIND_CONSTANT(PRIMITIVE_TRIANGLE_FAN); } -Mesh::Mesh() { +ArrayMesh::ArrayMesh() { mesh = VisualServer::get_singleton()->mesh_create(); blend_shape_mode = BLEND_SHAPE_MODE_RELATIVE; } -Mesh::~Mesh() { +ArrayMesh::~ArrayMesh() { VisualServer::get_singleton()->free(mesh); } diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index 8b1936ed0..ad3c10b6b 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -37,10 +38,15 @@ /** @author Juan Linietsky <reduzio@gmail.com> */ -class Mesh : public Resource { +class Mesh : public Resource { GDCLASS(Mesh, Resource); - RES_BASE_EXTENSION("msh"); + + mutable Ref<TriangleMesh> triangle_mesh; //cached +protected: + void _clear_triangle_mesh() const; + + static void _bind_methods(); public: enum { @@ -110,11 +116,40 @@ public: BLEND_SHAPE_MODE_RELATIVE = VS::BLEND_SHAPE_MODE_RELATIVE, }; + virtual int get_surface_count() const = 0; + virtual int surface_get_array_len(int p_idx) const = 0; + virtual int surface_get_array_index_len(int p_idx) const = 0; + virtual Array surface_get_arrays(int p_surface) const = 0; + virtual uint32_t surface_get_format(int p_idx) const = 0; + virtual PrimitiveType surface_get_primitive_type(int p_idx) const = 0; + virtual Ref<Material> surface_get_material(int p_idx) const = 0; + virtual int get_blend_shape_count() const = 0; + virtual StringName get_blend_shape_name(int p_index) const = 0; + + PoolVector<Face3> get_faces() const; + Ref<TriangleMesh> generate_triangle_mesh() const; + + Ref<Shape> create_trimesh_shape() const; + Ref<Shape> create_convex_shape() const; + + Ref<Mesh> create_outline(float p_margin) const; + + virtual Rect3 get_aabb() const = 0; + + Mesh(); +}; + +class ArrayMesh : public Mesh { + + GDCLASS(ArrayMesh, Mesh); + RES_BASE_EXTENSION("mesh"); + private: struct Surface { String name; Rect3 aabb; Ref<Material> material; + bool is_2d; }; Vector<Surface> surfaces; RID mesh; @@ -123,11 +158,11 @@ private: Vector<StringName> blend_shapes; Rect3 custom_aabb; - mutable Ref<TriangleMesh> triangle_mesh; - void _recompute_aabb(); protected: + virtual bool _is_generated() const { return false; } + 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; @@ -152,7 +187,7 @@ public: int get_surface_count() const; void surface_remove(int p_idx); - void surface_set_custom_aabb(int p_surface, const Rect3 &p_aabb); //only recognized by driver + void surface_set_custom_aabb(int p_idx, const Rect3 &p_aabb); //only recognized by driver int surface_get_array_len(int p_idx) const; int surface_get_array_index_len(int p_idx) const; @@ -174,19 +209,12 @@ public: Rect3 get_aabb() const; virtual RID get_rid() const; - Ref<Shape> create_trimesh_shape() const; - Ref<Shape> create_convex_shape() const; - - Ref<Mesh> create_outline(float p_margin) const; - void center_geometry(); void regen_normalmaps(); - PoolVector<Face3> get_faces() const; - Ref<TriangleMesh> generate_triangle_mesh() const; - Mesh(); + ArrayMesh(); - ~Mesh(); + ~ArrayMesh(); }; VARIANT_ENUM_CAST(Mesh::ArrayType); diff --git a/scene/resources/mesh_data_tool.cpp b/scene/resources/mesh_data_tool.cpp index fcc1f80d2..f1092a90c 100644 --- a/scene/resources/mesh_data_tool.cpp +++ b/scene/resources/mesh_data_tool.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -37,7 +38,7 @@ void MeshDataTool::clear() { format = 0; } -Error MeshDataTool::create_from_surface(const Ref<Mesh> &p_mesh, int p_surface) { +Error MeshDataTool::create_from_surface(const Ref<ArrayMesh> &p_mesh, int p_surface) { ERR_FAIL_COND_V(p_mesh.is_null(), ERR_INVALID_PARAMETER); @@ -178,7 +179,7 @@ Error MeshDataTool::create_from_surface(const Ref<Mesh> &p_mesh, int p_surface) return OK; } -Error MeshDataTool::commit_to_surface(const Ref<Mesh> &p_mesh) { +Error MeshDataTool::commit_to_surface(const Ref<ArrayMesh> &p_mesh) { ERR_FAIL_COND_V(p_mesh.is_null(), ERR_INVALID_PARAMETER); Array arr; @@ -308,7 +309,7 @@ Error MeshDataTool::commit_to_surface(const Ref<Mesh> &p_mesh) { if (w.size()) arr[Mesh::ARRAY_WEIGHTS] = w; - Ref<Mesh> ncmesh = p_mesh; + Ref<ArrayMesh> ncmesh = p_mesh; int sc = ncmesh->get_surface_count(); ncmesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, arr); ncmesh->surface_set_material(sc, material); @@ -559,7 +560,7 @@ void MeshDataTool::_bind_methods() { ClassDB::bind_method(D_METHOD("get_vertex_faces", "idx"), &MeshDataTool::get_vertex_faces); ClassDB::bind_method(D_METHOD("get_edge_vertex", "idx", "vertex"), &MeshDataTool::get_edge_vertex); - ClassDB::bind_method(D_METHOD("get_edge_faces", "idx", "faces"), &MeshDataTool::get_edge_faces); + ClassDB::bind_method(D_METHOD("get_edge_faces", "idx"), &MeshDataTool::get_edge_faces); ClassDB::bind_method(D_METHOD("set_edge_meta", "idx", "meta"), &MeshDataTool::set_edge_meta); ClassDB::bind_method(D_METHOD("get_edge_meta", "idx"), &MeshDataTool::get_edge_meta); @@ -572,8 +573,8 @@ void MeshDataTool::_bind_methods() { ClassDB::bind_method(D_METHOD("get_face_normal", "idx"), &MeshDataTool::get_face_normal); - ClassDB::bind_method(D_METHOD("set_material", "material:Material"), &MeshDataTool::set_material); - ClassDB::bind_method(D_METHOD("get_material", "material"), &MeshDataTool::get_material); + ClassDB::bind_method(D_METHOD("set_material", "material"), &MeshDataTool::set_material); + ClassDB::bind_method(D_METHOD("get_material"), &MeshDataTool::get_material); } MeshDataTool::MeshDataTool() { diff --git a/scene/resources/mesh_data_tool.h b/scene/resources/mesh_data_tool.h index 14318a9f8..ad771edbd 100644 --- a/scene/resources/mesh_data_tool.h +++ b/scene/resources/mesh_data_tool.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -77,8 +78,8 @@ protected: public: void clear(); - Error create_from_surface(const Ref<Mesh> &p_mesh, int p_surface); - Error commit_to_surface(const Ref<Mesh> &p_mesh); + Error create_from_surface(const Ref<ArrayMesh> &p_mesh, int p_surface); + Error commit_to_surface(const Ref<ArrayMesh> &p_mesh); int get_format() const; diff --git a/scene/resources/mesh_library.cpp b/scene/resources/mesh_library.cpp index 92ca921f2..7d51a2617 100644 --- a/scene/resources/mesh_library.cpp +++ b/scene/resources/mesh_library.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -229,13 +230,13 @@ void MeshLibrary::_bind_methods() { ClassDB::bind_method(D_METHOD("create_item", "id"), &MeshLibrary::create_item); ClassDB::bind_method(D_METHOD("set_item_name", "id", "name"), &MeshLibrary::set_item_name); - ClassDB::bind_method(D_METHOD("set_item_mesh", "id", "mesh:Mesh"), &MeshLibrary::set_item_mesh); - ClassDB::bind_method(D_METHOD("set_item_navmesh", "id", "navmesh:NavigationMesh"), &MeshLibrary::set_item_navmesh); - ClassDB::bind_method(D_METHOD("set_item_shape", "id", "shape:Shape"), &MeshLibrary::set_item_shape); + ClassDB::bind_method(D_METHOD("set_item_mesh", "id", "mesh"), &MeshLibrary::set_item_mesh); + ClassDB::bind_method(D_METHOD("set_item_navmesh", "id", "navmesh"), &MeshLibrary::set_item_navmesh); + ClassDB::bind_method(D_METHOD("set_item_shape", "id", "shape"), &MeshLibrary::set_item_shape); ClassDB::bind_method(D_METHOD("get_item_name", "id"), &MeshLibrary::get_item_name); - ClassDB::bind_method(D_METHOD("get_item_mesh:Mesh", "id"), &MeshLibrary::get_item_mesh); - ClassDB::bind_method(D_METHOD("get_item_navmesh:NavigationMesh", "id"), &MeshLibrary::get_item_navmesh); - ClassDB::bind_method(D_METHOD("get_item_shape:Shape", "id"), &MeshLibrary::get_item_shape); + ClassDB::bind_method(D_METHOD("get_item_mesh", "id"), &MeshLibrary::get_item_mesh); + ClassDB::bind_method(D_METHOD("get_item_navmesh", "id"), &MeshLibrary::get_item_navmesh); + ClassDB::bind_method(D_METHOD("get_item_shape", "id"), &MeshLibrary::get_item_shape); ClassDB::bind_method(D_METHOD("remove_item", "id"), &MeshLibrary::remove_item); ClassDB::bind_method(D_METHOD("clear"), &MeshLibrary::clear); ClassDB::bind_method(D_METHOD("get_item_list"), &MeshLibrary::get_item_list); diff --git a/scene/resources/mesh_library.h b/scene/resources/mesh_library.h index 5f4a695c5..cc39110a9 100644 --- a/scene/resources/mesh_library.h +++ b/scene/resources/mesh_library.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -38,7 +39,7 @@ class MeshLibrary : public Resource { GDCLASS(MeshLibrary, Resource); - RES_BASE_EXTENSION("gt"); + RES_BASE_EXTENSION("meshlib"); struct Item { String name; diff --git a/scene/resources/mikktspace.c b/scene/resources/mikktspace.c deleted file mode 100644 index 62aa2da25..000000000 --- a/scene/resources/mikktspace.c +++ /dev/null @@ -1,1890 +0,0 @@ -/** \file mikktspace/mikktspace.c - * \ingroup mikktspace - */ -/** - * Copyright (C) 2011 by Morten S. Mikkelsen - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#include <assert.h> -#include <stdio.h> -#include <math.h> -#include <string.h> -#include <float.h> -#include <stdlib.h> - -#include "mikktspace.h" - -#define TFALSE 0 -#define TTRUE 1 - -#ifndef M_PI -#define M_PI 3.1415926535897932384626433832795 -#endif - -#define INTERNAL_RND_SORT_SEED 39871946 - -// internal structure -typedef struct { - float x, y, z; -} SVec3; - -static tbool veq( const SVec3 v1, const SVec3 v2 ) -{ - return (v1.x == v2.x) && (v1.y == v2.y) && (v1.z == v2.z); -} - -static SVec3 vadd( const SVec3 v1, const SVec3 v2 ) -{ - SVec3 vRes; - - vRes.x = v1.x + v2.x; - vRes.y = v1.y + v2.y; - vRes.z = v1.z + v2.z; - - return vRes; -} - - -static SVec3 vsub( const SVec3 v1, const SVec3 v2 ) -{ - SVec3 vRes; - - vRes.x = v1.x - v2.x; - vRes.y = v1.y - v2.y; - vRes.z = v1.z - v2.z; - - return vRes; -} - -static SVec3 vscale(const float fS, const SVec3 v) -{ - SVec3 vRes; - - vRes.x = fS * v.x; - vRes.y = fS * v.y; - vRes.z = fS * v.z; - - return vRes; -} - -static float LengthSquared( const SVec3 v ) -{ - return v.x*v.x + v.y*v.y + v.z*v.z; -} - -static float Length( const SVec3 v ) -{ - return sqrtf(LengthSquared(v)); -} - -static SVec3 Normalize( const SVec3 v ) -{ - return vscale(1 / Length(v), v); -} - -static float vdot( const SVec3 v1, const SVec3 v2) -{ - return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z; -} - - -static tbool NotZero(const float fX) -{ - // could possibly use FLT_EPSILON instead - return fabsf(fX) > FLT_MIN; -} - -static tbool VNotZero(const SVec3 v) -{ - // might change this to an epsilon based test - return NotZero(v.x) || NotZero(v.y) || NotZero(v.z); -} - - - -typedef struct { - int iNrFaces; - int * pTriMembers; -} SSubGroup; - -typedef struct { - int iNrFaces; - int * pFaceIndices; - int iVertexRepresentitive; - tbool bOrientPreservering; -} SGroup; - -// -#define MARK_DEGENERATE 1 -#define QUAD_ONE_DEGEN_TRI 2 -#define GROUP_WITH_ANY 4 -#define ORIENT_PRESERVING 8 - - - -typedef struct { - int FaceNeighbors[3]; - SGroup * AssignedGroup[3]; - - // normalized first order face derivatives - SVec3 vOs, vOt; - float fMagS, fMagT; // original magnitudes - - // determines if the current and the next triangle are a quad. - int iOrgFaceNumber; - int iFlag, iTSpacesOffs; - unsigned char vert_num[4]; -} STriInfo; - -typedef struct { - SVec3 vOs; - float fMagS; - SVec3 vOt; - float fMagT; - int iCounter; // this is to average back into quads. - tbool bOrient; -} STSpace; - -static int GenerateInitialVerticesIndexList(STriInfo pTriInfos[], int piTriList_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn); -static void GenerateSharedVerticesIndexList(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn); -static void InitTriInfo(STriInfo pTriInfos[], const int piTriListIn[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn); -static int Build4RuleGroups(STriInfo pTriInfos[], SGroup pGroups[], int piGroupTrianglesBuffer[], const int piTriListIn[], const int iNrTrianglesIn); -static tbool GenerateTSpaces(STSpace psTspace[], const STriInfo pTriInfos[], const SGroup pGroups[], - const int iNrActiveGroups, const int piTriListIn[], const float fThresCos, - const SMikkTSpaceContext * pContext); - -static int MakeIndex(const int iFace, const int iVert) -{ - assert(iVert>=0 && iVert<4 && iFace>=0); - return (iFace<<2) | (iVert&0x3); -} - -static void IndexToData(int * piFace, int * piVert, const int iIndexIn) -{ - piVert[0] = iIndexIn&0x3; - piFace[0] = iIndexIn>>2; -} - -static STSpace AvgTSpace(const STSpace * pTS0, const STSpace * pTS1) -{ - STSpace ts_res; - - // this if is important. Due to floating point precision - // averaging when ts0==ts1 will cause a slight difference - // which results in tangent space splits later on - if (pTS0->fMagS==pTS1->fMagS && pTS0->fMagT==pTS1->fMagT && - veq(pTS0->vOs,pTS1->vOs) && veq(pTS0->vOt, pTS1->vOt)) - { - ts_res.fMagS = pTS0->fMagS; - ts_res.fMagT = pTS0->fMagT; - ts_res.vOs = pTS0->vOs; - ts_res.vOt = pTS0->vOt; - } - else - { - ts_res.fMagS = 0.5f*(pTS0->fMagS+pTS1->fMagS); - ts_res.fMagT = 0.5f*(pTS0->fMagT+pTS1->fMagT); - ts_res.vOs = vadd(pTS0->vOs,pTS1->vOs); - ts_res.vOt = vadd(pTS0->vOt,pTS1->vOt); - if ( VNotZero(ts_res.vOs) ) ts_res.vOs = Normalize(ts_res.vOs); - if ( VNotZero(ts_res.vOt) ) ts_res.vOt = Normalize(ts_res.vOt); - } - - return ts_res; -} - - - -static SVec3 GetPosition(const SMikkTSpaceContext * pContext, const int index); -static SVec3 GetNormal(const SMikkTSpaceContext * pContext, const int index); -static SVec3 GetTexCoord(const SMikkTSpaceContext * pContext, const int index); - - -// degen triangles -static void DegenPrologue(STriInfo pTriInfos[], int piTriList_out[], const int iNrTrianglesIn, const int iTotTris); -static void DegenEpilogue(STSpace psTspace[], STriInfo pTriInfos[], int piTriListIn[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn, const int iTotTris); - - -tbool genTangSpaceDefault(const SMikkTSpaceContext * pContext) -{ - return genTangSpace(pContext, 180.0f); -} - -tbool genTangSpace(const SMikkTSpaceContext * pContext, const float fAngularThreshold) -{ - // count nr_triangles - int * piTriListIn = NULL, * piGroupTrianglesBuffer = NULL; - STriInfo * pTriInfos = NULL; - SGroup * pGroups = NULL; - STSpace * psTspace = NULL; - int iNrTrianglesIn = 0, f=0, t=0, i=0; - int iNrTSPaces = 0, iTotTris = 0, iDegenTriangles = 0, iNrMaxGroups = 0; - int iNrActiveGroups = 0, index = 0; - const int iNrFaces = pContext->m_pInterface->m_getNumFaces(pContext); - tbool bRes = TFALSE; - const float fThresCos = (float) cos((fAngularThreshold*(float)M_PI)/180.0f); - - // verify all call-backs have been set - if ( pContext->m_pInterface->m_getNumFaces==NULL || - pContext->m_pInterface->m_getNumVerticesOfFace==NULL || - pContext->m_pInterface->m_getPosition==NULL || - pContext->m_pInterface->m_getNormal==NULL || - pContext->m_pInterface->m_getTexCoord==NULL ) - return TFALSE; - - // count triangles on supported faces - for (f=0; f<iNrFaces; f++) - { - const int verts = pContext->m_pInterface->m_getNumVerticesOfFace(pContext, f); - if (verts==3) ++iNrTrianglesIn; - else if (verts==4) iNrTrianglesIn += 2; - } - if (iNrTrianglesIn<=0) return TFALSE; - - // allocate memory for an index list - piTriListIn = (int *) malloc(sizeof(int)*3*iNrTrianglesIn); - pTriInfos = (STriInfo *) malloc(sizeof(STriInfo)*iNrTrianglesIn); - if (piTriListIn==NULL || pTriInfos==NULL) - { - if (piTriListIn!=NULL) free(piTriListIn); - if (pTriInfos!=NULL) free(pTriInfos); - return TFALSE; - } - - // make an initial triangle --> face index list - iNrTSPaces = GenerateInitialVerticesIndexList(pTriInfos, piTriListIn, pContext, iNrTrianglesIn); - - // make a welded index list of identical positions and attributes (pos, norm, texc) - //printf("gen welded index list begin\n"); - GenerateSharedVerticesIndexList(piTriListIn, pContext, iNrTrianglesIn); - //printf("gen welded index list end\n"); - - // Mark all degenerate triangles - iTotTris = iNrTrianglesIn; - iDegenTriangles = 0; - for (t=0; t<iTotTris; t++) - { - const int i0 = piTriListIn[t*3+0]; - const int i1 = piTriListIn[t*3+1]; - const int i2 = piTriListIn[t*3+2]; - const SVec3 p0 = GetPosition(pContext, i0); - const SVec3 p1 = GetPosition(pContext, i1); - const SVec3 p2 = GetPosition(pContext, i2); - if (veq(p0,p1) || veq(p0,p2) || veq(p1,p2)) // degenerate - { - pTriInfos[t].iFlag |= MARK_DEGENERATE; - ++iDegenTriangles; - } - } - iNrTrianglesIn = iTotTris - iDegenTriangles; - - // mark all triangle pairs that belong to a quad with only one - // good triangle. These need special treatment in DegenEpilogue(). - // Additionally, move all good triangles to the start of - // pTriInfos[] and piTriListIn[] without changing order and - // put the degenerate triangles last. - DegenPrologue(pTriInfos, piTriListIn, iNrTrianglesIn, iTotTris); - - - // evaluate triangle level attributes and neighbor list - //printf("gen neighbors list begin\n"); - InitTriInfo(pTriInfos, piTriListIn, pContext, iNrTrianglesIn); - //printf("gen neighbors list end\n"); - - - // based on the 4 rules, identify groups based on connectivity - iNrMaxGroups = iNrTrianglesIn*3; - pGroups = (SGroup *) malloc(sizeof(SGroup)*iNrMaxGroups); - piGroupTrianglesBuffer = (int *) malloc(sizeof(int)*iNrTrianglesIn*3); - if (pGroups==NULL || piGroupTrianglesBuffer==NULL) - { - if (pGroups!=NULL) free(pGroups); - if (piGroupTrianglesBuffer!=NULL) free(piGroupTrianglesBuffer); - free(piTriListIn); - free(pTriInfos); - return TFALSE; - } - //printf("gen 4rule groups begin\n"); - iNrActiveGroups = - Build4RuleGroups(pTriInfos, pGroups, piGroupTrianglesBuffer, piTriListIn, iNrTrianglesIn); - //printf("gen 4rule groups end\n"); - - // - - psTspace = (STSpace *) malloc(sizeof(STSpace)*iNrTSPaces); - if (psTspace==NULL) - { - free(piTriListIn); - free(pTriInfos); - free(pGroups); - free(piGroupTrianglesBuffer); - return TFALSE; - } - memset(psTspace, 0, sizeof(STSpace)*iNrTSPaces); - for (t=0; t<iNrTSPaces; t++) - { - psTspace[t].vOs.x=1.0f; psTspace[t].vOs.y=0.0f; psTspace[t].vOs.z=0.0f; psTspace[t].fMagS = 1.0f; - psTspace[t].vOt.x=0.0f; psTspace[t].vOt.y=1.0f; psTspace[t].vOt.z=0.0f; psTspace[t].fMagT = 1.0f; - } - - // make tspaces, each group is split up into subgroups if necessary - // based on fAngularThreshold. Finally a tangent space is made for - // every resulting subgroup - //printf("gen tspaces begin\n"); - bRes = GenerateTSpaces(psTspace, pTriInfos, pGroups, iNrActiveGroups, piTriListIn, fThresCos, pContext); - //printf("gen tspaces end\n"); - - // clean up - free(pGroups); - free(piGroupTrianglesBuffer); - - if (!bRes) // if an allocation in GenerateTSpaces() failed - { - // clean up and return false - free(pTriInfos); free(piTriListIn); free(psTspace); - return TFALSE; - } - - - // degenerate quads with one good triangle will be fixed by copying a space from - // the good triangle to the coinciding vertex. - // all other degenerate triangles will just copy a space from any good triangle - // with the same welded index in piTriListIn[]. - DegenEpilogue(psTspace, pTriInfos, piTriListIn, pContext, iNrTrianglesIn, iTotTris); - - free(pTriInfos); free(piTriListIn); - - index = 0; - for (f=0; f<iNrFaces; f++) - { - const int verts = pContext->m_pInterface->m_getNumVerticesOfFace(pContext, f); - if (verts!=3 && verts!=4) continue; - - - // I've decided to let degenerate triangles and group-with-anythings - // vary between left/right hand coordinate systems at the vertices. - // All healthy triangles on the other hand are built to always be either or. - - /*// force the coordinate system orientation to be uniform for every face. - // (this is already the case for good triangles but not for - // degenerate ones and those with bGroupWithAnything==true) - bool bOrient = psTspace[index].bOrient; - if (psTspace[index].iCounter == 0) // tspace was not derived from a group - { - // look for a space created in GenerateTSpaces() by iCounter>0 - bool bNotFound = true; - int i=1; - while (i<verts && bNotFound) - { - if (psTspace[index+i].iCounter > 0) bNotFound=false; - else ++i; - } - if (!bNotFound) bOrient = psTspace[index+i].bOrient; - }*/ - - // set data - for (i=0; i<verts; i++) - { - const STSpace * pTSpace = &psTspace[index]; - float tang[] = {pTSpace->vOs.x, pTSpace->vOs.y, pTSpace->vOs.z}; - float bitang[] = {pTSpace->vOt.x, pTSpace->vOt.y, pTSpace->vOt.z}; - if (pContext->m_pInterface->m_setTSpace!=NULL) - pContext->m_pInterface->m_setTSpace(pContext, tang, bitang, pTSpace->fMagS, pTSpace->fMagT, pTSpace->bOrient, f, i); - if (pContext->m_pInterface->m_setTSpaceBasic!=NULL) - pContext->m_pInterface->m_setTSpaceBasic(pContext, tang, pTSpace->bOrient==TTRUE ? 1.0f : (-1.0f), f, i); - - ++index; - } - } - - free(psTspace); - - - return TTRUE; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -typedef struct { - float vert[3]; - int index; -} STmpVert; - -static const int g_iCells = 2048; - -#ifdef _MSC_VER - #define NOINLINE __declspec(noinline) -#else - #define NOINLINE __attribute__ ((noinline)) -#endif - -// it is IMPORTANT that this function is called to evaluate the hash since -// inlining could potentially reorder instructions and generate different -// results for the same effective input value fVal. -static NOINLINE int FindGridCell(const float fMin, const float fMax, const float fVal) -{ - const float fIndex = g_iCells * ((fVal-fMin)/(fMax-fMin)); - const int iIndex = (int)fIndex; - return iIndex < g_iCells ? (iIndex >= 0 ? iIndex : 0) : (g_iCells - 1); -} - -static void MergeVertsFast(int piTriList_in_and_out[], STmpVert pTmpVert[], const SMikkTSpaceContext * pContext, const int iL_in, const int iR_in); -static void MergeVertsSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int pTable[], const int iEntries); -static void GenerateSharedVerticesIndexListSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn); - -static void GenerateSharedVerticesIndexList(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn) -{ - - // Generate bounding box - int * piHashTable=NULL, * piHashCount=NULL, * piHashOffsets=NULL, * piHashCount2=NULL; - STmpVert * pTmpVert = NULL; - int i=0, iChannel=0, k=0, e=0; - int iMaxCount=0; - SVec3 vMin = GetPosition(pContext, 0), vMax = vMin, vDim; - float fMin, fMax; - for (i=1; i<(iNrTrianglesIn*3); i++) - { - const int index = piTriList_in_and_out[i]; - - const SVec3 vP = GetPosition(pContext, index); - if (vMin.x > vP.x) vMin.x = vP.x; - else if (vMax.x < vP.x) vMax.x = vP.x; - if (vMin.y > vP.y) vMin.y = vP.y; - else if (vMax.y < vP.y) vMax.y = vP.y; - if (vMin.z > vP.z) vMin.z = vP.z; - else if (vMax.z < vP.z) vMax.z = vP.z; - } - - vDim = vsub(vMax,vMin); - iChannel = 0; - fMin = vMin.x; fMax=vMax.x; - if (vDim.y>vDim.x && vDim.y>vDim.z) - { - iChannel=1; - fMin = vMin.y, fMax=vMax.y; - } - else if (vDim.z>vDim.x) - { - iChannel=2; - fMin = vMin.z, fMax=vMax.z; - } - - // make allocations - piHashTable = (int *) malloc(sizeof(int)*iNrTrianglesIn*3); - piHashCount = (int *) malloc(sizeof(int)*g_iCells); - piHashOffsets = (int *) malloc(sizeof(int)*g_iCells); - piHashCount2 = (int *) malloc(sizeof(int)*g_iCells); - - if (piHashTable==NULL || piHashCount==NULL || piHashOffsets==NULL || piHashCount2==NULL) - { - if (piHashTable!=NULL) free(piHashTable); - if (piHashCount!=NULL) free(piHashCount); - if (piHashOffsets!=NULL) free(piHashOffsets); - if (piHashCount2!=NULL) free(piHashCount2); - GenerateSharedVerticesIndexListSlow(piTriList_in_and_out, pContext, iNrTrianglesIn); - return; - } - memset(piHashCount, 0, sizeof(int)*g_iCells); - memset(piHashCount2, 0, sizeof(int)*g_iCells); - - // count amount of elements in each cell unit - for (i=0; i<(iNrTrianglesIn*3); i++) - { - const int index = piTriList_in_and_out[i]; - const SVec3 vP = GetPosition(pContext, index); - const float fVal = iChannel==0 ? vP.x : (iChannel==1 ? vP.y : vP.z); - const int iCell = FindGridCell(fMin, fMax, fVal); - ++piHashCount[iCell]; - } - - // evaluate start index of each cell. - piHashOffsets[0]=0; - for (k=1; k<g_iCells; k++) - piHashOffsets[k]=piHashOffsets[k-1]+piHashCount[k-1]; - - // insert vertices - for (i=0; i<(iNrTrianglesIn*3); i++) - { - const int index = piTriList_in_and_out[i]; - const SVec3 vP = GetPosition(pContext, index); - const float fVal = iChannel==0 ? vP.x : (iChannel==1 ? vP.y : vP.z); - const int iCell = FindGridCell(fMin, fMax, fVal); - int * pTable = NULL; - - assert(piHashCount2[iCell]<piHashCount[iCell]); - pTable = &piHashTable[piHashOffsets[iCell]]; - pTable[piHashCount2[iCell]] = i; // vertex i has been inserted. - ++piHashCount2[iCell]; - } - for (k=0; k<g_iCells; k++) - assert(piHashCount2[k] == piHashCount[k]); // verify the count - free(piHashCount2); - - // find maximum amount of entries in any hash entry - iMaxCount = piHashCount[0]; - for (k=1; k<g_iCells; k++) - if (iMaxCount<piHashCount[k]) - iMaxCount=piHashCount[k]; - pTmpVert = (STmpVert *) malloc(sizeof(STmpVert)*iMaxCount); - - - // complete the merge - for (k=0; k<g_iCells; k++) - { - // extract table of cell k and amount of entries in it - int * pTable = &piHashTable[piHashOffsets[k]]; - const int iEntries = piHashCount[k]; - if (iEntries < 2) continue; - - if (pTmpVert!=NULL) - { - for (e=0; e<iEntries; e++) - { - int i = pTable[e]; - const SVec3 vP = GetPosition(pContext, piTriList_in_and_out[i]); - pTmpVert[e].vert[0] = vP.x; pTmpVert[e].vert[1] = vP.y; - pTmpVert[e].vert[2] = vP.z; pTmpVert[e].index = i; - } - MergeVertsFast(piTriList_in_and_out, pTmpVert, pContext, 0, iEntries-1); - } - else - MergeVertsSlow(piTriList_in_and_out, pContext, pTable, iEntries); - } - - if (pTmpVert!=NULL) { free(pTmpVert); } - free(piHashTable); - free(piHashCount); - free(piHashOffsets); -} - -static void MergeVertsFast(int piTriList_in_and_out[], STmpVert pTmpVert[], const SMikkTSpaceContext * pContext, const int iL_in, const int iR_in) -{ - // make bbox - int c=0, l=0, channel=0; - float fvMin[3], fvMax[3]; - float dx=0, dy=0, dz=0, fSep=0; - for (c=0; c<3; c++) - { fvMin[c]=pTmpVert[iL_in].vert[c]; fvMax[c]=fvMin[c]; } - for (l=(iL_in+1); l<=iR_in; l++) - for (c=0; c<3; c++) - if (fvMin[c]>pTmpVert[l].vert[c]) fvMin[c]=pTmpVert[l].vert[c]; - else if (fvMax[c]<pTmpVert[l].vert[c]) fvMax[c]=pTmpVert[l].vert[c]; - - dx = fvMax[0]-fvMin[0]; - dy = fvMax[1]-fvMin[1]; - dz = fvMax[2]-fvMin[2]; - - channel = 0; - if (dy>dx && dy>dz) channel=1; - else if (dz>dx) channel=2; - - fSep = 0.5f*(fvMax[channel]+fvMin[channel]); - - // terminate recursion when the separation/average value - // is no longer strictly between fMin and fMax values. - if (fSep>=fvMax[channel] || fSep<=fvMin[channel]) - { - // complete the weld - for (l=iL_in; l<=iR_in; l++) - { - int i = pTmpVert[l].index; - const int index = piTriList_in_and_out[i]; - const SVec3 vP = GetPosition(pContext, index); - const SVec3 vN = GetNormal(pContext, index); - const SVec3 vT = GetTexCoord(pContext, index); - - tbool bNotFound = TTRUE; - int l2=iL_in, i2rec=-1; - while (l2<l && bNotFound) - { - const int i2 = pTmpVert[l2].index; - const int index2 = piTriList_in_and_out[i2]; - const SVec3 vP2 = GetPosition(pContext, index2); - const SVec3 vN2 = GetNormal(pContext, index2); - const SVec3 vT2 = GetTexCoord(pContext, index2); - i2rec=i2; - - //if (vP==vP2 && vN==vN2 && vT==vT2) - if (vP.x==vP2.x && vP.y==vP2.y && vP.z==vP2.z && - vN.x==vN2.x && vN.y==vN2.y && vN.z==vN2.z && - vT.x==vT2.x && vT.y==vT2.y && vT.z==vT2.z) - bNotFound = TFALSE; - else - ++l2; - } - - // merge if previously found - if (!bNotFound) - piTriList_in_and_out[i] = piTriList_in_and_out[i2rec]; - } - } - else - { - int iL=iL_in, iR=iR_in; - assert((iR_in-iL_in)>0); // at least 2 entries - - // separate (by fSep) all points between iL_in and iR_in in pTmpVert[] - while (iL < iR) - { - tbool bReadyLeftSwap = TFALSE, bReadyRightSwap = TFALSE; - while ((!bReadyLeftSwap) && iL<iR) - { - assert(iL>=iL_in && iL<=iR_in); - bReadyLeftSwap = !(pTmpVert[iL].vert[channel]<fSep); - if (!bReadyLeftSwap) ++iL; - } - while ((!bReadyRightSwap) && iL<iR) - { - assert(iR>=iL_in && iR<=iR_in); - bReadyRightSwap = pTmpVert[iR].vert[channel]<fSep; - if (!bReadyRightSwap) --iR; - } - assert( (iL<iR) || !(bReadyLeftSwap && bReadyRightSwap) ); - - if (bReadyLeftSwap && bReadyRightSwap) - { - const STmpVert sTmp = pTmpVert[iL]; - assert(iL<iR); - pTmpVert[iL] = pTmpVert[iR]; - pTmpVert[iR] = sTmp; - ++iL; --iR; - } - } - - assert(iL==(iR+1) || (iL==iR)); - if (iL==iR) - { - const tbool bReadyRightSwap = pTmpVert[iR].vert[channel]<fSep; - if (bReadyRightSwap) ++iL; - else --iR; - } - - // only need to weld when there is more than 1 instance of the (x,y,z) - if (iL_in < iR) - MergeVertsFast(piTriList_in_and_out, pTmpVert, pContext, iL_in, iR); // weld all left of fSep - if (iL < iR_in) - MergeVertsFast(piTriList_in_and_out, pTmpVert, pContext, iL, iR_in); // weld all right of (or equal to) fSep - } -} - -static void MergeVertsSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int pTable[], const int iEntries) -{ - // this can be optimized further using a tree structure or more hashing. - int e=0; - for (e=0; e<iEntries; e++) - { - int i = pTable[e]; - const int index = piTriList_in_and_out[i]; - const SVec3 vP = GetPosition(pContext, index); - const SVec3 vN = GetNormal(pContext, index); - const SVec3 vT = GetTexCoord(pContext, index); - - tbool bNotFound = TTRUE; - int e2=0, i2rec=-1; - while (e2<e && bNotFound) - { - const int i2 = pTable[e2]; - const int index2 = piTriList_in_and_out[i2]; - const SVec3 vP2 = GetPosition(pContext, index2); - const SVec3 vN2 = GetNormal(pContext, index2); - const SVec3 vT2 = GetTexCoord(pContext, index2); - i2rec = i2; - - if (veq(vP,vP2) && veq(vN,vN2) && veq(vT,vT2)) - bNotFound = TFALSE; - else - ++e2; - } - - // merge if previously found - if (!bNotFound) - piTriList_in_and_out[i] = piTriList_in_and_out[i2rec]; - } -} - -static void GenerateSharedVerticesIndexListSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn) -{ - int iNumUniqueVerts = 0, t=0, i=0; - for (t=0; t<iNrTrianglesIn; t++) - { - for (i=0; i<3; i++) - { - const int offs = t*3 + i; - const int index = piTriList_in_and_out[offs]; - - const SVec3 vP = GetPosition(pContext, index); - const SVec3 vN = GetNormal(pContext, index); - const SVec3 vT = GetTexCoord(pContext, index); - - tbool bFound = TFALSE; - int t2=0, index2rec=-1; - while (!bFound && t2<=t) - { - int j=0; - while (!bFound && j<3) - { - const int index2 = piTriList_in_and_out[t2*3 + j]; - const SVec3 vP2 = GetPosition(pContext, index2); - const SVec3 vN2 = GetNormal(pContext, index2); - const SVec3 vT2 = GetTexCoord(pContext, index2); - - if (veq(vP,vP2) && veq(vN,vN2) && veq(vT,vT2)) - bFound = TTRUE; - else - ++j; - } - if (!bFound) ++t2; - } - - assert(bFound); - // if we found our own - if (index2rec == index) { ++iNumUniqueVerts; } - - piTriList_in_and_out[offs] = index2rec; - } - } -} - -static int GenerateInitialVerticesIndexList(STriInfo pTriInfos[], int piTriList_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn) -{ - int iTSpacesOffs = 0, f=0, t=0; - int iDstTriIndex = 0; - for (f=0; f<pContext->m_pInterface->m_getNumFaces(pContext); f++) - { - const int verts = pContext->m_pInterface->m_getNumVerticesOfFace(pContext, f); - if (verts!=3 && verts!=4) continue; - - pTriInfos[iDstTriIndex].iOrgFaceNumber = f; - pTriInfos[iDstTriIndex].iTSpacesOffs = iTSpacesOffs; - - if (verts==3) - { - unsigned char * pVerts = pTriInfos[iDstTriIndex].vert_num; - pVerts[0]=0; pVerts[1]=1; pVerts[2]=2; - piTriList_out[iDstTriIndex*3+0] = MakeIndex(f, 0); - piTriList_out[iDstTriIndex*3+1] = MakeIndex(f, 1); - piTriList_out[iDstTriIndex*3+2] = MakeIndex(f, 2); - ++iDstTriIndex; // next - } - else - { - { - pTriInfos[iDstTriIndex+1].iOrgFaceNumber = f; - pTriInfos[iDstTriIndex+1].iTSpacesOffs = iTSpacesOffs; - } - - { - // need an order independent way to evaluate - // tspace on quads. This is done by splitting - // along the shortest diagonal. - const int i0 = MakeIndex(f, 0); - const int i1 = MakeIndex(f, 1); - const int i2 = MakeIndex(f, 2); - const int i3 = MakeIndex(f, 3); - const SVec3 T0 = GetTexCoord(pContext, i0); - const SVec3 T1 = GetTexCoord(pContext, i1); - const SVec3 T2 = GetTexCoord(pContext, i2); - const SVec3 T3 = GetTexCoord(pContext, i3); - const float distSQ_02 = LengthSquared(vsub(T2,T0)); - const float distSQ_13 = LengthSquared(vsub(T3,T1)); - tbool bQuadDiagIs_02; - if (distSQ_02<distSQ_13) - bQuadDiagIs_02 = TTRUE; - else if (distSQ_13<distSQ_02) - bQuadDiagIs_02 = TFALSE; - else - { - const SVec3 P0 = GetPosition(pContext, i0); - const SVec3 P1 = GetPosition(pContext, i1); - const SVec3 P2 = GetPosition(pContext, i2); - const SVec3 P3 = GetPosition(pContext, i3); - const float distSQ_02 = LengthSquared(vsub(P2,P0)); - const float distSQ_13 = LengthSquared(vsub(P3,P1)); - - bQuadDiagIs_02 = distSQ_13<distSQ_02 ? TFALSE : TTRUE; - } - - if (bQuadDiagIs_02) - { - { - unsigned char * pVerts_A = pTriInfos[iDstTriIndex].vert_num; - pVerts_A[0]=0; pVerts_A[1]=1; pVerts_A[2]=2; - } - piTriList_out[iDstTriIndex*3+0] = i0; - piTriList_out[iDstTriIndex*3+1] = i1; - piTriList_out[iDstTriIndex*3+2] = i2; - ++iDstTriIndex; // next - { - unsigned char * pVerts_B = pTriInfos[iDstTriIndex].vert_num; - pVerts_B[0]=0; pVerts_B[1]=2; pVerts_B[2]=3; - } - piTriList_out[iDstTriIndex*3+0] = i0; - piTriList_out[iDstTriIndex*3+1] = i2; - piTriList_out[iDstTriIndex*3+2] = i3; - ++iDstTriIndex; // next - } - else - { - { - unsigned char * pVerts_A = pTriInfos[iDstTriIndex].vert_num; - pVerts_A[0]=0; pVerts_A[1]=1; pVerts_A[2]=3; - } - piTriList_out[iDstTriIndex*3+0] = i0; - piTriList_out[iDstTriIndex*3+1] = i1; - piTriList_out[iDstTriIndex*3+2] = i3; - ++iDstTriIndex; // next - { - unsigned char * pVerts_B = pTriInfos[iDstTriIndex].vert_num; - pVerts_B[0]=1; pVerts_B[1]=2; pVerts_B[2]=3; - } - piTriList_out[iDstTriIndex*3+0] = i1; - piTriList_out[iDstTriIndex*3+1] = i2; - piTriList_out[iDstTriIndex*3+2] = i3; - ++iDstTriIndex; // next - } - } - } - - iTSpacesOffs += verts; - assert(iDstTriIndex<=iNrTrianglesIn); - } - - for (t=0; t<iNrTrianglesIn; t++) - pTriInfos[t].iFlag = 0; - - // return total amount of tspaces - return iTSpacesOffs; -} - -static SVec3 GetPosition(const SMikkTSpaceContext * pContext, const int index) -{ - int iF, iI; - SVec3 res; float pos[3]; - IndexToData(&iF, &iI, index); - pContext->m_pInterface->m_getPosition(pContext, pos, iF, iI); - res.x=pos[0]; res.y=pos[1]; res.z=pos[2]; - return res; -} - -static SVec3 GetNormal(const SMikkTSpaceContext * pContext, const int index) -{ - int iF, iI; - SVec3 res; float norm[3]; - IndexToData(&iF, &iI, index); - pContext->m_pInterface->m_getNormal(pContext, norm, iF, iI); - res.x=norm[0]; res.y=norm[1]; res.z=norm[2]; - return res; -} - -static SVec3 GetTexCoord(const SMikkTSpaceContext * pContext, const int index) -{ - int iF, iI; - SVec3 res; float texc[2]; - IndexToData(&iF, &iI, index); - pContext->m_pInterface->m_getTexCoord(pContext, texc, iF, iI); - res.x=texc[0]; res.y=texc[1]; res.z=1.0f; - return res; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////// - -typedef union { - struct - { - int i0, i1, f; - }; - int array[3]; -} SEdge; - -static void BuildNeighborsFast(STriInfo pTriInfos[], SEdge * pEdges, const int piTriListIn[], const int iNrTrianglesIn); -static void BuildNeighborsSlow(STriInfo pTriInfos[], const int piTriListIn[], const int iNrTrianglesIn); - -// returns the texture area times 2 -static float CalcTexArea(const SMikkTSpaceContext * pContext, const int indices[]) -{ - const SVec3 t1 = GetTexCoord(pContext, indices[0]); - const SVec3 t2 = GetTexCoord(pContext, indices[1]); - const SVec3 t3 = GetTexCoord(pContext, indices[2]); - - const float t21x = t2.x-t1.x; - const float t21y = t2.y-t1.y; - const float t31x = t3.x-t1.x; - const float t31y = t3.y-t1.y; - - const float fSignedAreaSTx2 = t21x*t31y - t21y*t31x; - - return fSignedAreaSTx2<0 ? (-fSignedAreaSTx2) : fSignedAreaSTx2; -} - -static void InitTriInfo(STriInfo pTriInfos[], const int piTriListIn[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn) -{ - int f=0, i=0, t=0; - // pTriInfos[f].iFlag is cleared in GenerateInitialVerticesIndexList() which is called before this function. - - // generate neighbor info list - for (f=0; f<iNrTrianglesIn; f++) - for (i=0; i<3; i++) - { - pTriInfos[f].FaceNeighbors[i] = -1; - pTriInfos[f].AssignedGroup[i] = NULL; - - pTriInfos[f].vOs.x=0.0f; pTriInfos[f].vOs.y=0.0f; pTriInfos[f].vOs.z=0.0f; - pTriInfos[f].vOt.x=0.0f; pTriInfos[f].vOt.y=0.0f; pTriInfos[f].vOt.z=0.0f; - pTriInfos[f].fMagS = 0; - pTriInfos[f].fMagT = 0; - - // assumed bad - pTriInfos[f].iFlag |= GROUP_WITH_ANY; - } - - // evaluate first order derivatives - for (f=0; f<iNrTrianglesIn; f++) - { - // initial values - const SVec3 v1 = GetPosition(pContext, piTriListIn[f*3+0]); - const SVec3 v2 = GetPosition(pContext, piTriListIn[f*3+1]); - const SVec3 v3 = GetPosition(pContext, piTriListIn[f*3+2]); - const SVec3 t1 = GetTexCoord(pContext, piTriListIn[f*3+0]); - const SVec3 t2 = GetTexCoord(pContext, piTriListIn[f*3+1]); - const SVec3 t3 = GetTexCoord(pContext, piTriListIn[f*3+2]); - - const float t21x = t2.x-t1.x; - const float t21y = t2.y-t1.y; - const float t31x = t3.x-t1.x; - const float t31y = t3.y-t1.y; - const SVec3 d1 = vsub(v2,v1); - const SVec3 d2 = vsub(v3,v1); - - const float fSignedAreaSTx2 = t21x*t31y - t21y*t31x; - //assert(fSignedAreaSTx2!=0); - SVec3 vOs = vsub(vscale(t31y,d1), vscale(t21y,d2)); // eq 18 - SVec3 vOt = vadd(vscale(-t31x,d1), vscale(t21x,d2)); // eq 19 - - pTriInfos[f].iFlag |= (fSignedAreaSTx2>0 ? ORIENT_PRESERVING : 0); - - if ( NotZero(fSignedAreaSTx2) ) - { - const float fAbsArea = fabsf(fSignedAreaSTx2); - const float fLenOs = Length(vOs); - const float fLenOt = Length(vOt); - const float fS = (pTriInfos[f].iFlag&ORIENT_PRESERVING)==0 ? (-1.0f) : 1.0f; - if ( NotZero(fLenOs) ) pTriInfos[f].vOs = vscale(fS/fLenOs, vOs); - if ( NotZero(fLenOt) ) pTriInfos[f].vOt = vscale(fS/fLenOt, vOt); - - // evaluate magnitudes prior to normalization of vOs and vOt - pTriInfos[f].fMagS = fLenOs / fAbsArea; - pTriInfos[f].fMagT = fLenOt / fAbsArea; - - // if this is a good triangle - if ( NotZero(pTriInfos[f].fMagS) && NotZero(pTriInfos[f].fMagT)) - pTriInfos[f].iFlag &= (~GROUP_WITH_ANY); - } - } - - // force otherwise healthy quads to a fixed orientation - while (t<(iNrTrianglesIn-1)) - { - const int iFO_a = pTriInfos[t].iOrgFaceNumber; - const int iFO_b = pTriInfos[t+1].iOrgFaceNumber; - if (iFO_a==iFO_b) // this is a quad - { - const tbool bIsDeg_a = (pTriInfos[t].iFlag&MARK_DEGENERATE)!=0 ? TTRUE : TFALSE; - const tbool bIsDeg_b = (pTriInfos[t+1].iFlag&MARK_DEGENERATE)!=0 ? TTRUE : TFALSE; - - // bad triangles should already have been removed by - // DegenPrologue(), but just in case check bIsDeg_a and bIsDeg_a are false - if ((bIsDeg_a||bIsDeg_b)==TFALSE) - { - const tbool bOrientA = (pTriInfos[t].iFlag&ORIENT_PRESERVING)!=0 ? TTRUE : TFALSE; - const tbool bOrientB = (pTriInfos[t+1].iFlag&ORIENT_PRESERVING)!=0 ? TTRUE : TFALSE; - // if this happens the quad has extremely bad mapping!! - if (bOrientA!=bOrientB) - { - //printf("found quad with bad mapping\n"); - tbool bChooseOrientFirstTri = TFALSE; - if ((pTriInfos[t+1].iFlag&GROUP_WITH_ANY)!=0) bChooseOrientFirstTri = TTRUE; - else if ( CalcTexArea(pContext, &piTriListIn[t*3+0]) >= CalcTexArea(pContext, &piTriListIn[(t+1)*3+0]) ) - bChooseOrientFirstTri = TTRUE; - - // force match - { - const int t0 = bChooseOrientFirstTri ? t : (t+1); - const int t1 = bChooseOrientFirstTri ? (t+1) : t; - pTriInfos[t1].iFlag &= (~ORIENT_PRESERVING); // clear first - pTriInfos[t1].iFlag |= (pTriInfos[t0].iFlag&ORIENT_PRESERVING); // copy bit - } - } - } - t += 2; - } - else - ++t; - } - - // match up edge pairs - { - SEdge * pEdges = (SEdge *) malloc(sizeof(SEdge)*iNrTrianglesIn*3); - if (pEdges==NULL) - BuildNeighborsSlow(pTriInfos, piTriListIn, iNrTrianglesIn); - else - { - BuildNeighborsFast(pTriInfos, pEdges, piTriListIn, iNrTrianglesIn); - - free(pEdges); - } - } -} - -///////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////// - -static tbool AssignRecur(const int piTriListIn[], STriInfo psTriInfos[], const int iMyTriIndex, SGroup * pGroup); -static void AddTriToGroup(SGroup * pGroup, const int iTriIndex); - -static int Build4RuleGroups(STriInfo pTriInfos[], SGroup pGroups[], int piGroupTrianglesBuffer[], const int piTriListIn[], const int iNrTrianglesIn) -{ - const int iNrMaxGroups = iNrTrianglesIn*3; - int iNrActiveGroups = 0; - int iOffset = 0, f=0, i=0; - (void)iNrMaxGroups; /* quiet warnings in non debug mode */ - for (f=0; f<iNrTrianglesIn; f++) - { - for (i=0; i<3; i++) - { - // if not assigned to a group - if ((pTriInfos[f].iFlag&GROUP_WITH_ANY)==0 && pTriInfos[f].AssignedGroup[i]==NULL) - { - tbool bOrPre; - int neigh_indexL, neigh_indexR; - const int vert_index = piTriListIn[f*3+i]; - assert(iNrActiveGroups<iNrMaxGroups); - pTriInfos[f].AssignedGroup[i] = &pGroups[iNrActiveGroups]; - pTriInfos[f].AssignedGroup[i]->iVertexRepresentitive = vert_index; - pTriInfos[f].AssignedGroup[i]->bOrientPreservering = (pTriInfos[f].iFlag&ORIENT_PRESERVING)!=0; - pTriInfos[f].AssignedGroup[i]->iNrFaces = 0; - pTriInfos[f].AssignedGroup[i]->pFaceIndices = &piGroupTrianglesBuffer[iOffset]; - ++iNrActiveGroups; - - AddTriToGroup(pTriInfos[f].AssignedGroup[i], f); - bOrPre = (pTriInfos[f].iFlag&ORIENT_PRESERVING)!=0 ? TTRUE : TFALSE; - neigh_indexL = pTriInfos[f].FaceNeighbors[i]; - neigh_indexR = pTriInfos[f].FaceNeighbors[i>0?(i-1):2]; - if (neigh_indexL>=0) // neighbor - { - const tbool bAnswer = - AssignRecur(piTriListIn, pTriInfos, neigh_indexL, - pTriInfos[f].AssignedGroup[i] ); - - const tbool bOrPre2 = (pTriInfos[neigh_indexL].iFlag&ORIENT_PRESERVING)!=0 ? TTRUE : TFALSE; - const tbool bDiff = bOrPre!=bOrPre2 ? TTRUE : TFALSE; - assert(bAnswer || bDiff); - (void)bAnswer, (void)bDiff; /* quiet warnings in non debug mode */ - } - if (neigh_indexR>=0) // neighbor - { - const tbool bAnswer = - AssignRecur(piTriListIn, pTriInfos, neigh_indexR, - pTriInfos[f].AssignedGroup[i] ); - - const tbool bOrPre2 = (pTriInfos[neigh_indexR].iFlag&ORIENT_PRESERVING)!=0 ? TTRUE : TFALSE; - const tbool bDiff = bOrPre!=bOrPre2 ? TTRUE : TFALSE; - assert(bAnswer || bDiff); - (void)bAnswer, (void)bDiff; /* quiet warnings in non debug mode */ - } - - // update offset - iOffset += pTriInfos[f].AssignedGroup[i]->iNrFaces; - // since the groups are disjoint a triangle can never - // belong to more than 3 groups. Subsequently something - // is completely screwed if this assertion ever hits. - assert(iOffset <= iNrMaxGroups); - } - } - } - - return iNrActiveGroups; -} - -static void AddTriToGroup(SGroup * pGroup, const int iTriIndex) -{ - pGroup->pFaceIndices[pGroup->iNrFaces] = iTriIndex; - ++pGroup->iNrFaces; -} - -static tbool AssignRecur(const int piTriListIn[], STriInfo psTriInfos[], - const int iMyTriIndex, SGroup * pGroup) -{ - STriInfo * pMyTriInfo = &psTriInfos[iMyTriIndex]; - - // track down vertex - const int iVertRep = pGroup->iVertexRepresentitive; - const int * pVerts = &piTriListIn[3*iMyTriIndex+0]; - int i=-1; - if (pVerts[0]==iVertRep) i=0; - else if (pVerts[1]==iVertRep) i=1; - else if (pVerts[2]==iVertRep) i=2; - assert(i>=0 && i<3); - - // early out - if (pMyTriInfo->AssignedGroup[i] == pGroup) return TTRUE; - else if (pMyTriInfo->AssignedGroup[i]!=NULL) return TFALSE; - if ((pMyTriInfo->iFlag&GROUP_WITH_ANY)!=0) - { - // first to group with a group-with-anything triangle - // determines it's orientation. - // This is the only existing order dependency in the code!! - if ( pMyTriInfo->AssignedGroup[0] == NULL && - pMyTriInfo->AssignedGroup[1] == NULL && - pMyTriInfo->AssignedGroup[2] == NULL ) - { - pMyTriInfo->iFlag &= (~ORIENT_PRESERVING); - pMyTriInfo->iFlag |= (pGroup->bOrientPreservering ? ORIENT_PRESERVING : 0); - } - } - { - const tbool bOrient = (pMyTriInfo->iFlag&ORIENT_PRESERVING)!=0 ? TTRUE : TFALSE; - if (bOrient != pGroup->bOrientPreservering) return TFALSE; - } - - AddTriToGroup(pGroup, iMyTriIndex); - pMyTriInfo->AssignedGroup[i] = pGroup; - - { - const int neigh_indexL = pMyTriInfo->FaceNeighbors[i]; - const int neigh_indexR = pMyTriInfo->FaceNeighbors[i>0?(i-1):2]; - if (neigh_indexL>=0) - AssignRecur(piTriListIn, psTriInfos, neigh_indexL, pGroup); - if (neigh_indexR>=0) - AssignRecur(piTriListIn, psTriInfos, neigh_indexR, pGroup); - } - - - - return TTRUE; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////// - -static tbool CompareSubGroups(const SSubGroup * pg1, const SSubGroup * pg2); -static void QuickSort(int* pSortBuffer, int iLeft, int iRight, unsigned int uSeed); -static STSpace EvalTspace(int face_indices[], const int iFaces, const int piTriListIn[], const STriInfo pTriInfos[], const SMikkTSpaceContext * pContext, const int iVertexRepresentitive); - -static tbool GenerateTSpaces(STSpace psTspace[], const STriInfo pTriInfos[], const SGroup pGroups[], - const int iNrActiveGroups, const int piTriListIn[], const float fThresCos, - const SMikkTSpaceContext * pContext) -{ - STSpace * pSubGroupTspace = NULL; - SSubGroup * pUniSubGroups = NULL; - int * pTmpMembers = NULL; - int iMaxNrFaces=0, iUniqueTspaces=0, g=0, i=0; - for (g=0; g<iNrActiveGroups; g++) - if (iMaxNrFaces < pGroups[g].iNrFaces) - iMaxNrFaces = pGroups[g].iNrFaces; - - if (iMaxNrFaces == 0) return TTRUE; - - // make initial allocations - pSubGroupTspace = (STSpace *) malloc(sizeof(STSpace)*iMaxNrFaces); - pUniSubGroups = (SSubGroup *) malloc(sizeof(SSubGroup)*iMaxNrFaces); - pTmpMembers = (int *) malloc(sizeof(int)*iMaxNrFaces); - if (pSubGroupTspace==NULL || pUniSubGroups==NULL || pTmpMembers==NULL) - { - if (pSubGroupTspace!=NULL) free(pSubGroupTspace); - if (pUniSubGroups!=NULL) free(pUniSubGroups); - if (pTmpMembers!=NULL) free(pTmpMembers); - return TFALSE; - } - - - iUniqueTspaces = 0; - for (g=0; g<iNrActiveGroups; g++) - { - const SGroup * pGroup = &pGroups[g]; - int iUniqueSubGroups = 0, s=0; - - for (i=0; i<pGroup->iNrFaces; i++) // triangles - { - const int f = pGroup->pFaceIndices[i]; // triangle number - int index=-1, iVertIndex=-1, iOF_1=-1, iMembers=0, j=0, l=0; - SSubGroup tmp_group; - tbool bFound; - SVec3 n, vOs, vOt; - if (pTriInfos[f].AssignedGroup[0]==pGroup) index=0; - else if (pTriInfos[f].AssignedGroup[1]==pGroup) index=1; - else if (pTriInfos[f].AssignedGroup[2]==pGroup) index=2; - assert(index>=0 && index<3); - - iVertIndex = piTriListIn[f*3+index]; - assert(iVertIndex==pGroup->iVertexRepresentitive); - - // is normalized already - n = GetNormal(pContext, iVertIndex); - - // project - vOs = vsub(pTriInfos[f].vOs, vscale(vdot(n,pTriInfos[f].vOs), n)); - vOt = vsub(pTriInfos[f].vOt, vscale(vdot(n,pTriInfos[f].vOt), n)); - if ( VNotZero(vOs) ) vOs = Normalize(vOs); - if ( VNotZero(vOt) ) vOt = Normalize(vOt); - - // original face number - iOF_1 = pTriInfos[f].iOrgFaceNumber; - - iMembers = 0; - for (j=0; j<pGroup->iNrFaces; j++) - { - const int t = pGroup->pFaceIndices[j]; // triangle number - const int iOF_2 = pTriInfos[t].iOrgFaceNumber; - - // project - SVec3 vOs2 = vsub(pTriInfos[t].vOs, vscale(vdot(n,pTriInfos[t].vOs), n)); - SVec3 vOt2 = vsub(pTriInfos[t].vOt, vscale(vdot(n,pTriInfos[t].vOt), n)); - if ( VNotZero(vOs2) ) vOs2 = Normalize(vOs2); - if ( VNotZero(vOt2) ) vOt2 = Normalize(vOt2); - - { - const tbool bAny = ( (pTriInfos[f].iFlag | pTriInfos[t].iFlag) & GROUP_WITH_ANY )!=0 ? TTRUE : TFALSE; - // make sure triangles which belong to the same quad are joined. - const tbool bSameOrgFace = iOF_1==iOF_2 ? TTRUE : TFALSE; - - const float fCosS = vdot(vOs,vOs2); - const float fCosT = vdot(vOt,vOt2); - - assert(f!=t || bSameOrgFace); // sanity check - if (bAny || bSameOrgFace || (fCosS>fThresCos && fCosT>fThresCos)) - pTmpMembers[iMembers++] = t; - } - } - - // sort pTmpMembers - tmp_group.iNrFaces = iMembers; - tmp_group.pTriMembers = pTmpMembers; - if (iMembers>1) - { - unsigned int uSeed = INTERNAL_RND_SORT_SEED; // could replace with a random seed? - QuickSort(pTmpMembers, 0, iMembers-1, uSeed); - } - - // look for an existing match - bFound = TFALSE; - l=0; - while (l<iUniqueSubGroups && !bFound) - { - bFound = CompareSubGroups(&tmp_group, &pUniSubGroups[l]); - if (!bFound) ++l; - } - - // assign tangent space index - assert(bFound || l==iUniqueSubGroups); - //piTempTangIndices[f*3+index] = iUniqueTspaces+l; - - // if no match was found we allocate a new subgroup - if (!bFound) - { - // insert new subgroup - int * pIndices = (int *) malloc(sizeof(int)*iMembers); - if (pIndices==NULL) - { - // clean up and return false - int s=0; - for (s=0; s<iUniqueSubGroups; s++) - free(pUniSubGroups[s].pTriMembers); - free(pUniSubGroups); - free(pTmpMembers); - free(pSubGroupTspace); - return TFALSE; - } - pUniSubGroups[iUniqueSubGroups].iNrFaces = iMembers; - pUniSubGroups[iUniqueSubGroups].pTriMembers = pIndices; - memcpy(pIndices, tmp_group.pTriMembers, iMembers*sizeof(int)); - pSubGroupTspace[iUniqueSubGroups] = - EvalTspace(tmp_group.pTriMembers, iMembers, piTriListIn, pTriInfos, pContext, pGroup->iVertexRepresentitive); - ++iUniqueSubGroups; - } - - // output tspace - { - const int iOffs = pTriInfos[f].iTSpacesOffs; - const int iVert = pTriInfos[f].vert_num[index]; - STSpace * pTS_out = &psTspace[iOffs+iVert]; - assert(pTS_out->iCounter<2); - assert(((pTriInfos[f].iFlag&ORIENT_PRESERVING)!=0) == pGroup->bOrientPreservering); - if (pTS_out->iCounter==1) - { - *pTS_out = AvgTSpace(pTS_out, &pSubGroupTspace[l]); - pTS_out->iCounter = 2; // update counter - pTS_out->bOrient = pGroup->bOrientPreservering; - } - else - { - assert(pTS_out->iCounter==0); - *pTS_out = pSubGroupTspace[l]; - pTS_out->iCounter = 1; // update counter - pTS_out->bOrient = pGroup->bOrientPreservering; - } - } - } - - // clean up and offset iUniqueTspaces - for (s=0; s<iUniqueSubGroups; s++) - free(pUniSubGroups[s].pTriMembers); - iUniqueTspaces += iUniqueSubGroups; - } - - // clean up - free(pUniSubGroups); - free(pTmpMembers); - free(pSubGroupTspace); - - return TTRUE; -} - -static STSpace EvalTspace(int face_indices[], const int iFaces, const int piTriListIn[], const STriInfo pTriInfos[], - const SMikkTSpaceContext * pContext, const int iVertexRepresentitive) -{ - STSpace res; - float fAngleSum = 0; - int face=0; - res.vOs.x=0.0f; res.vOs.y=0.0f; res.vOs.z=0.0f; - res.vOt.x=0.0f; res.vOt.y=0.0f; res.vOt.z=0.0f; - res.fMagS = 0; res.fMagT = 0; - - for (face=0; face<iFaces; face++) - { - const int f = face_indices[face]; - - // only valid triangles get to add their contribution - if ( (pTriInfos[f].iFlag&GROUP_WITH_ANY)==0 ) - { - SVec3 n, vOs, vOt, p0, p1, p2, v1, v2; - float fCos, fAngle, fMagS, fMagT; - int i=-1, index=-1, i0=-1, i1=-1, i2=-1; - if (piTriListIn[3*f+0]==iVertexRepresentitive) i=0; - else if (piTriListIn[3*f+1]==iVertexRepresentitive) i=1; - else if (piTriListIn[3*f+2]==iVertexRepresentitive) i=2; - assert(i>=0 && i<3); - - // project - index = piTriListIn[3*f+i]; - n = GetNormal(pContext, index); - vOs = vsub(pTriInfos[f].vOs, vscale(vdot(n,pTriInfos[f].vOs), n)); - vOt = vsub(pTriInfos[f].vOt, vscale(vdot(n,pTriInfos[f].vOt), n)); - if ( VNotZero(vOs) ) vOs = Normalize(vOs); - if ( VNotZero(vOt) ) vOt = Normalize(vOt); - - i2 = piTriListIn[3*f + (i<2?(i+1):0)]; - i1 = piTriListIn[3*f + i]; - i0 = piTriListIn[3*f + (i>0?(i-1):2)]; - - p0 = GetPosition(pContext, i0); - p1 = GetPosition(pContext, i1); - p2 = GetPosition(pContext, i2); - v1 = vsub(p0,p1); - v2 = vsub(p2,p1); - - // project - v1 = vsub(v1, vscale(vdot(n,v1),n)); if ( VNotZero(v1) ) v1 = Normalize(v1); - v2 = vsub(v2, vscale(vdot(n,v2),n)); if ( VNotZero(v2) ) v2 = Normalize(v2); - - // weight contribution by the angle - // between the two edge vectors - fCos = vdot(v1,v2); fCos=fCos>1?1:(fCos<(-1) ? (-1) : fCos); - fAngle = (float) acos(fCos); - fMagS = pTriInfos[f].fMagS; - fMagT = pTriInfos[f].fMagT; - - res.vOs=vadd(res.vOs, vscale(fAngle,vOs)); - res.vOt=vadd(res.vOt,vscale(fAngle,vOt)); - res.fMagS+=(fAngle*fMagS); - res.fMagT+=(fAngle*fMagT); - fAngleSum += fAngle; - } - } - - // normalize - if ( VNotZero(res.vOs) ) res.vOs = Normalize(res.vOs); - if ( VNotZero(res.vOt) ) res.vOt = Normalize(res.vOt); - if (fAngleSum>0) - { - res.fMagS /= fAngleSum; - res.fMagT /= fAngleSum; - } - - return res; -} - -static tbool CompareSubGroups(const SSubGroup * pg1, const SSubGroup * pg2) -{ - tbool bStillSame=TTRUE; - int i=0; - if (pg1->iNrFaces!=pg2->iNrFaces) return TFALSE; - while (i<pg1->iNrFaces && bStillSame) - { - bStillSame = pg1->pTriMembers[i]==pg2->pTriMembers[i] ? TTRUE : TFALSE; - if (bStillSame) ++i; - } - return bStillSame; -} - -static void QuickSort(int* pSortBuffer, int iLeft, int iRight, unsigned int uSeed) -{ - int iL, iR, n, index, iMid, iTmp; - - // Random - unsigned int t=uSeed&31; - t=(uSeed<<t)|(uSeed>>(32-t)); - uSeed=uSeed+t+3; - // Random end - - iL=iLeft; iR=iRight; - n = (iR-iL)+1; - assert(n>=0); - index = (int) (uSeed%n); - - iMid=pSortBuffer[index + iL]; - - - do - { - while (pSortBuffer[iL] < iMid) - ++iL; - while (pSortBuffer[iR] > iMid) - --iR; - - if (iL <= iR) - { - iTmp = pSortBuffer[iL]; - pSortBuffer[iL] = pSortBuffer[iR]; - pSortBuffer[iR] = iTmp; - ++iL; --iR; - } - } - while (iL <= iR); - - if (iLeft < iR) - QuickSort(pSortBuffer, iLeft, iR, uSeed); - if (iL < iRight) - QuickSort(pSortBuffer, iL, iRight, uSeed); -} - -///////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////// - -static void QuickSortEdges(SEdge * pSortBuffer, int iLeft, int iRight, const int channel, unsigned int uSeed); -static void GetEdge(int * i0_out, int * i1_out, int * edgenum_out, const int indices[], const int i0_in, const int i1_in); - -static void BuildNeighborsFast(STriInfo pTriInfos[], SEdge * pEdges, const int piTriListIn[], const int iNrTrianglesIn) -{ - // build array of edges - unsigned int uSeed = INTERNAL_RND_SORT_SEED; // could replace with a random seed? - int iEntries=0, iCurStartIndex=-1, f=0, i=0; - for (f=0; f<iNrTrianglesIn; f++) - for (i=0; i<3; i++) - { - const int i0 = piTriListIn[f*3+i]; - const int i1 = piTriListIn[f*3+(i<2?(i+1):0)]; - pEdges[f*3+i].i0 = i0 < i1 ? i0 : i1; // put minimum index in i0 - pEdges[f*3+i].i1 = !(i0 < i1) ? i0 : i1; // put maximum index in i1 - pEdges[f*3+i].f = f; // record face number - } - - // sort over all edges by i0, this is the pricy one. - QuickSortEdges(pEdges, 0, iNrTrianglesIn*3-1, 0, uSeed); // sort channel 0 which is i0 - - // sub sort over i1, should be fast. - // could replace this with a 64 bit int sort over (i0,i1) - // with i0 as msb in the quicksort call above. - iEntries = iNrTrianglesIn*3; - iCurStartIndex = 0; - for (i=1; i<iEntries; i++) - { - if (pEdges[iCurStartIndex].i0 != pEdges[i].i0) - { - const int iL = iCurStartIndex; - const int iR = i-1; - //const int iElems = i-iL; - iCurStartIndex = i; - QuickSortEdges(pEdges, iL, iR, 1, uSeed); // sort channel 1 which is i1 - } - } - - // sub sort over f, which should be fast. - // this step is to remain compliant with BuildNeighborsSlow() when - // more than 2 triangles use the same edge (such as a butterfly topology). - iCurStartIndex = 0; - for (i=1; i<iEntries; i++) - { - if (pEdges[iCurStartIndex].i0 != pEdges[i].i0 || pEdges[iCurStartIndex].i1 != pEdges[i].i1) - { - const int iL = iCurStartIndex; - const int iR = i-1; - //const int iElems = i-iL; - iCurStartIndex = i; - QuickSortEdges(pEdges, iL, iR, 2, uSeed); // sort channel 2 which is f - } - } - - // pair up, adjacent triangles - for (i=0; i<iEntries; i++) - { - const int i0=pEdges[i].i0; - const int i1=pEdges[i].i1; - const int f = pEdges[i].f; - tbool bUnassigned_A; - - int i0_A, i1_A; - int edgenum_A, edgenum_B=0; // 0,1 or 2 - GetEdge(&i0_A, &i1_A, &edgenum_A, &piTriListIn[f*3], i0, i1); // resolve index ordering and edge_num - bUnassigned_A = pTriInfos[f].FaceNeighbors[edgenum_A] == -1 ? TTRUE : TFALSE; - - if (bUnassigned_A) - { - // get true index ordering - int j=i+1, t; - tbool bNotFound = TTRUE; - while (j<iEntries && i0==pEdges[j].i0 && i1==pEdges[j].i1 && bNotFound) - { - tbool bUnassigned_B; - int i0_B, i1_B; - t = pEdges[j].f; - // flip i0_B and i1_B - GetEdge(&i1_B, &i0_B, &edgenum_B, &piTriListIn[t*3], pEdges[j].i0, pEdges[j].i1); // resolve index ordering and edge_num - //assert(!(i0_A==i1_B && i1_A==i0_B)); - bUnassigned_B = pTriInfos[t].FaceNeighbors[edgenum_B]==-1 ? TTRUE : TFALSE; - if (i0_A==i0_B && i1_A==i1_B && bUnassigned_B) - bNotFound = TFALSE; - else - ++j; - } - - if (!bNotFound) - { - int t = pEdges[j].f; - pTriInfos[f].FaceNeighbors[edgenum_A] = t; - //assert(pTriInfos[t].FaceNeighbors[edgenum_B]==-1); - pTriInfos[t].FaceNeighbors[edgenum_B] = f; - } - } - } -} - -static void BuildNeighborsSlow(STriInfo pTriInfos[], const int piTriListIn[], const int iNrTrianglesIn) -{ - int f=0, i=0; - for (f=0; f<iNrTrianglesIn; f++) - { - for (i=0; i<3; i++) - { - // if unassigned - if (pTriInfos[f].FaceNeighbors[i] == -1) - { - const int i0_A = piTriListIn[f*3+i]; - const int i1_A = piTriListIn[f*3+(i<2?(i+1):0)]; - - // search for a neighbor - tbool bFound = TFALSE; - int t=0, j=0; - while (!bFound && t<iNrTrianglesIn) - { - if (t!=f) - { - j=0; - while (!bFound && j<3) - { - // in rev order - const int i1_B = piTriListIn[t*3+j]; - const int i0_B = piTriListIn[t*3+(j<2?(j+1):0)]; - //assert(!(i0_A==i1_B && i1_A==i0_B)); - if (i0_A==i0_B && i1_A==i1_B) - bFound = TTRUE; - else - ++j; - } - } - - if (!bFound) ++t; - } - - // assign neighbors - if (bFound) - { - pTriInfos[f].FaceNeighbors[i] = t; - //assert(pTriInfos[t].FaceNeighbors[j]==-1); - pTriInfos[t].FaceNeighbors[j] = f; - } - } - } - } -} - -static void QuickSortEdges(SEdge * pSortBuffer, int iLeft, int iRight, const int channel, unsigned int uSeed) -{ - unsigned int t; - int iL, iR, n, index, iMid; - - // early out - SEdge sTmp; - const int iElems = iRight-iLeft+1; - if (iElems<2) return; - else if (iElems==2) - { - if (pSortBuffer[iLeft].array[channel] > pSortBuffer[iRight].array[channel]) - { - sTmp = pSortBuffer[iLeft]; - pSortBuffer[iLeft] = pSortBuffer[iRight]; - pSortBuffer[iRight] = sTmp; - } - return; - } - - // Random - t=uSeed&31; - t=(uSeed<<t)|(uSeed>>(32-t)); - uSeed=uSeed+t+3; - // Random end - - iL=iLeft, iR=iRight; - n = (iR-iL)+1; - assert(n>=0); - index = (int) (uSeed%n); - - iMid=pSortBuffer[index + iL].array[channel]; - - do - { - while (pSortBuffer[iL].array[channel] < iMid) - ++iL; - while (pSortBuffer[iR].array[channel] > iMid) - --iR; - - if (iL <= iR) - { - sTmp = pSortBuffer[iL]; - pSortBuffer[iL] = pSortBuffer[iR]; - pSortBuffer[iR] = sTmp; - ++iL; --iR; - } - } - while (iL <= iR); - - if (iLeft < iR) - QuickSortEdges(pSortBuffer, iLeft, iR, channel, uSeed); - if (iL < iRight) - QuickSortEdges(pSortBuffer, iL, iRight, channel, uSeed); -} - -// resolve ordering and edge number -static void GetEdge(int * i0_out, int * i1_out, int * edgenum_out, const int indices[], const int i0_in, const int i1_in) -{ - *edgenum_out = -1; - - // test if first index is on the edge - if (indices[0]==i0_in || indices[0]==i1_in) - { - // test if second index is on the edge - if (indices[1]==i0_in || indices[1]==i1_in) - { - edgenum_out[0]=0; // first edge - i0_out[0]=indices[0]; - i1_out[0]=indices[1]; - } - else - { - edgenum_out[0]=2; // third edge - i0_out[0]=indices[2]; - i1_out[0]=indices[0]; - } - } - else - { - // only second and third index is on the edge - edgenum_out[0]=1; // second edge - i0_out[0]=indices[1]; - i1_out[0]=indices[2]; - } -} - - -///////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////// Degenerate triangles //////////////////////////////////// - -static void DegenPrologue(STriInfo pTriInfos[], int piTriList_out[], const int iNrTrianglesIn, const int iTotTris) -{ - int iNextGoodTriangleSearchIndex=-1; - tbool bStillFindingGoodOnes; - - // locate quads with only one good triangle - int t=0; - while (t<(iTotTris-1)) - { - const int iFO_a = pTriInfos[t].iOrgFaceNumber; - const int iFO_b = pTriInfos[t+1].iOrgFaceNumber; - if (iFO_a==iFO_b) // this is a quad - { - const tbool bIsDeg_a = (pTriInfos[t].iFlag&MARK_DEGENERATE)!=0 ? TTRUE : TFALSE; - const tbool bIsDeg_b = (pTriInfos[t+1].iFlag&MARK_DEGENERATE)!=0 ? TTRUE : TFALSE; - if ((bIsDeg_a^bIsDeg_b)!=0) - { - pTriInfos[t].iFlag |= QUAD_ONE_DEGEN_TRI; - pTriInfos[t+1].iFlag |= QUAD_ONE_DEGEN_TRI; - } - t += 2; - } - else - ++t; - } - - // reorder list so all degen triangles are moved to the back - // without reordering the good triangles - iNextGoodTriangleSearchIndex = 1; - t=0; - bStillFindingGoodOnes = TTRUE; - while (t<iNrTrianglesIn && bStillFindingGoodOnes) - { - const tbool bIsGood = (pTriInfos[t].iFlag&MARK_DEGENERATE)==0 ? TTRUE : TFALSE; - if (bIsGood) - { - if (iNextGoodTriangleSearchIndex < (t+2)) - iNextGoodTriangleSearchIndex = t+2; - } - else - { - int t0, t1; - // search for the first good triangle. - tbool bJustADegenerate = TTRUE; - while (bJustADegenerate && iNextGoodTriangleSearchIndex<iTotTris) - { - const tbool bIsGood = (pTriInfos[iNextGoodTriangleSearchIndex].iFlag&MARK_DEGENERATE)==0 ? TTRUE : TFALSE; - if (bIsGood) bJustADegenerate=TFALSE; - else ++iNextGoodTriangleSearchIndex; - } - - t0 = t; - t1 = iNextGoodTriangleSearchIndex; - ++iNextGoodTriangleSearchIndex; - assert(iNextGoodTriangleSearchIndex > (t+1)); - - // swap triangle t0 and t1 - if (!bJustADegenerate) - { - int i=0; - for (i=0; i<3; i++) - { - const int index = piTriList_out[t0*3+i]; - piTriList_out[t0*3+i] = piTriList_out[t1*3+i]; - piTriList_out[t1*3+i] = index; - } - { - const STriInfo tri_info = pTriInfos[t0]; - pTriInfos[t0] = pTriInfos[t1]; - pTriInfos[t1] = tri_info; - } - } - else - bStillFindingGoodOnes = TFALSE; // this is not supposed to happen - } - - if (bStillFindingGoodOnes) ++t; - } - - assert(bStillFindingGoodOnes); // code will still work. - assert(iNrTrianglesIn == t); -} - -static void DegenEpilogue(STSpace psTspace[], STriInfo pTriInfos[], int piTriListIn[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn, const int iTotTris) -{ - int t=0, i=0; - // deal with degenerate triangles - // punishment for degenerate triangles is O(N^2) - for (t=iNrTrianglesIn; t<iTotTris; t++) - { - // degenerate triangles on a quad with one good triangle are skipped - // here but processed in the next loop - const tbool bSkip = (pTriInfos[t].iFlag&QUAD_ONE_DEGEN_TRI)!=0 ? TTRUE : TFALSE; - - if (!bSkip) - { - for (i=0; i<3; i++) - { - const int index1 = piTriListIn[t*3+i]; - // search through the good triangles - tbool bNotFound = TTRUE; - int j=0; - while (bNotFound && j<(3*iNrTrianglesIn)) - { - const int index2 = piTriListIn[j]; - if (index1==index2) bNotFound=TFALSE; - else ++j; - } - - if (!bNotFound) - { - const int iTri = j/3; - const int iVert = j%3; - const int iSrcVert=pTriInfos[iTri].vert_num[iVert]; - const int iSrcOffs=pTriInfos[iTri].iTSpacesOffs; - const int iDstVert=pTriInfos[t].vert_num[i]; - const int iDstOffs=pTriInfos[t].iTSpacesOffs; - - // copy tspace - psTspace[iDstOffs+iDstVert] = psTspace[iSrcOffs+iSrcVert]; - } - } - } - } - - // deal with degenerate quads with one good triangle - for (t=0; t<iNrTrianglesIn; t++) - { - // this triangle belongs to a quad where the - // other triangle is degenerate - if ( (pTriInfos[t].iFlag&QUAD_ONE_DEGEN_TRI)!=0 ) - { - SVec3 vDstP; - int iOrgF=-1, i=0; - tbool bNotFound; - unsigned char * pV = pTriInfos[t].vert_num; - int iFlag = (1<<pV[0]) | (1<<pV[1]) | (1<<pV[2]); - int iMissingIndex = 0; - if ((iFlag&2)==0) iMissingIndex=1; - else if ((iFlag&4)==0) iMissingIndex=2; - else if ((iFlag&8)==0) iMissingIndex=3; - - iOrgF = pTriInfos[t].iOrgFaceNumber; - vDstP = GetPosition(pContext, MakeIndex(iOrgF, iMissingIndex)); - bNotFound = TTRUE; - i=0; - while (bNotFound && i<3) - { - const int iVert = pV[i]; - const SVec3 vSrcP = GetPosition(pContext, MakeIndex(iOrgF, iVert)); - if (veq(vSrcP, vDstP)==TTRUE) - { - const int iOffs = pTriInfos[t].iTSpacesOffs; - psTspace[iOffs+iMissingIndex] = psTspace[iOffs+iVert]; - bNotFound=TFALSE; - } - else - ++i; - } - assert(!bNotFound); - } - } -} diff --git a/scene/resources/mikktspace.h b/scene/resources/mikktspace.h deleted file mode 100644 index 52c44a713..000000000 --- a/scene/resources/mikktspace.h +++ /dev/null @@ -1,145 +0,0 @@ -/** \file mikktspace/mikktspace.h - * \ingroup mikktspace - */ -/** - * Copyright (C) 2011 by Morten S. Mikkelsen - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#ifndef __MIKKTSPACE_H__ -#define __MIKKTSPACE_H__ - - -#ifdef __cplusplus -extern "C" { -#endif - -/* Author: Morten S. Mikkelsen - * Version: 1.0 - * - * The files mikktspace.h and mikktspace.c are designed to be - * stand-alone files and it is important that they are kept this way. - * Not having dependencies on structures/classes/libraries specific - * to the program, in which they are used, allows them to be copied - * and used as is into any tool, program or plugin. - * The code is designed to consistently generate the same - * tangent spaces, for a given mesh, in any tool in which it is used. - * This is done by performing an internal welding step and subsequently an order-independent evaluation - * of tangent space for meshes consisting of triangles and quads. - * This means faces can be received in any order and the same is true for - * the order of vertices of each face. The generated result will not be affected - * by such reordering. Additionally, whether degenerate (vertices or texture coordinates) - * primitives are present or not will not affect the generated results either. - * Once tangent space calculation is done the vertices of degenerate primitives will simply - * inherit tangent space from neighboring non degenerate primitives. - * The analysis behind this implementation can be found in my master's thesis - * which is available for download --> http://image.diku.dk/projects/media/morten.mikkelsen.08.pdf - * Note that though the tangent spaces at the vertices are generated in an order-independent way, - * by this implementation, the interpolated tangent space is still affected by which diagonal is - * chosen to split each quad. A sensible solution is to have your tools pipeline always - * split quads by the shortest diagonal. This choice is order-independent and works with mirroring. - * If these have the same length then compare the diagonals defined by the texture coordinates. - * XNormal which is a tool for baking normal maps allows you to write your own tangent space plugin - * and also quad triangulator plugin. - */ - - -typedef int tbool; -typedef struct SMikkTSpaceContext SMikkTSpaceContext; - -typedef struct { - // Returns the number of faces (triangles/quads) on the mesh to be processed. - int (*m_getNumFaces)(const SMikkTSpaceContext * pContext); - - // Returns the number of vertices on face number iFace - // iFace is a number in the range {0, 1, ..., getNumFaces()-1} - int (*m_getNumVerticesOfFace)(const SMikkTSpaceContext * pContext, const int iFace); - - // returns the position/normal/texcoord of the referenced face of vertex number iVert. - // iVert is in the range {0,1,2} for triangles and {0,1,2,3} for quads. - void (*m_getPosition)(const SMikkTSpaceContext * pContext, float fvPosOut[], const int iFace, const int iVert); - void (*m_getNormal)(const SMikkTSpaceContext * pContext, float fvNormOut[], const int iFace, const int iVert); - void (*m_getTexCoord)(const SMikkTSpaceContext * pContext, float fvTexcOut[], const int iFace, const int iVert); - - // either (or both) of the two setTSpace callbacks can be set. - // The call-back m_setTSpaceBasic() is sufficient for basic normal mapping. - - // This function is used to return the tangent and fSign to the application. - // fvTangent is a unit length vector. - // For normal maps it is sufficient to use the following simplified version of the bitangent which is generated at pixel/vertex level. - // bitangent = fSign * cross(vN, tangent); - // Note that the results are returned unindexed. It is possible to generate a new index list - // But averaging/overwriting tangent spaces by using an already existing index list WILL produce INCRORRECT results. - // DO NOT! use an already existing index list. - void (*m_setTSpaceBasic)(const SMikkTSpaceContext * pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert); - - // This function is used to return tangent space results to the application. - // fvTangent and fvBiTangent are unit length vectors and fMagS and fMagT are their - // true magnitudes which can be used for relief mapping effects. - // fvBiTangent is the "real" bitangent and thus may not be perpendicular to fvTangent. - // However, both are perpendicular to the vertex normal. - // For normal maps it is sufficient to use the following simplified version of the bitangent which is generated at pixel/vertex level. - // fSign = bIsOrientationPreserving ? 1.0f : (-1.0f); - // bitangent = fSign * cross(vN, tangent); - // Note that the results are returned unindexed. It is possible to generate a new index list - // But averaging/overwriting tangent spaces by using an already existing index list WILL produce INCRORRECT results. - // DO NOT! use an already existing index list. - void (*m_setTSpace)(const SMikkTSpaceContext * pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT, - const tbool bIsOrientationPreserving, const int iFace, const int iVert); -} SMikkTSpaceInterface; - -struct SMikkTSpaceContext -{ - SMikkTSpaceInterface * m_pInterface; // initialized with callback functions - void * m_pUserData; // pointer to client side mesh data etc. (passed as the first parameter with every interface call) -}; - -// these are both thread safe! -tbool genTangSpaceDefault(const SMikkTSpaceContext * pContext); // Default (recommended) fAngularThreshold is 180 degrees (which means threshold disabled) -tbool genTangSpace(const SMikkTSpaceContext * pContext, const float fAngularThreshold); - - -// To avoid visual errors (distortions/unwanted hard edges in lighting), when using sampled normal maps, the -// normal map sampler must use the exact inverse of the pixel shader transformation. -// The most efficient transformation we can possibly do in the pixel shader is -// achieved by using, directly, the "unnormalized" interpolated tangent, bitangent and vertex normal: vT, vB and vN. -// pixel shader (fast transform out) -// vNout = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN ); -// where vNt is the tangent space normal. The normal map sampler must likewise use the -// interpolated and "unnormalized" tangent, bitangent and vertex normal to be compliant with the pixel shader. -// sampler does (exact inverse of pixel shader): -// float3 row0 = cross(vB, vN); -// float3 row1 = cross(vN, vT); -// float3 row2 = cross(vT, vB); -// float fSign = dot(vT, row0)<0 ? -1 : 1; -// vNt = normalize( fSign * float3(dot(vNout,row0), dot(vNout,row1), dot(vNout,row2)) ); -// where vNout is the sampled normal in some chosen 3D space. -// -// Should you choose to reconstruct the bitangent in the pixel shader instead -// of the vertex shader, as explained earlier, then be sure to do this in the normal map sampler also. -// Finally, beware of quad triangulations. If the normal map sampler doesn't use the same triangulation of -// quads as your renderer then problems will occur since the interpolated tangent spaces will differ -// eventhough the vertex level tangent spaces match. This can be solved either by triangulating before -// sampling/exporting or by using the order-independent choice of diagonal for splitting quads suggested earlier. -// However, this must be used both by the sampler and your tools/rendering pipeline. - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/scene/resources/multimesh.cpp b/scene/resources/multimesh.cpp index 6202109cd..231e59cdb 100644 --- a/scene/resources/multimesh.cpp +++ b/scene/resources/multimesh.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -185,8 +186,8 @@ MultiMesh::TransformFormat MultiMesh::get_transform_format() const { void MultiMesh::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_mesh", "mesh:Mesh"), &MultiMesh::set_mesh); - ClassDB::bind_method(D_METHOD("get_mesh:Mesh"), &MultiMesh::get_mesh); + ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &MultiMesh::set_mesh); + ClassDB::bind_method(D_METHOD("get_mesh"), &MultiMesh::get_mesh); ClassDB::bind_method(D_METHOD("set_color_format", "format"), &MultiMesh::set_color_format); ClassDB::bind_method(D_METHOD("get_color_format"), &MultiMesh::get_color_format); ClassDB::bind_method(D_METHOD("set_transform_format", "format"), &MultiMesh::set_transform_format); diff --git a/scene/resources/multimesh.h b/scene/resources/multimesh.h index 1ecf76142..7d6a0ce44 100644 --- a/scene/resources/multimesh.h +++ b/scene/resources/multimesh.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -35,7 +36,7 @@ class MultiMesh : public Resource { GDCLASS(MultiMesh, Resource); - RES_BASE_EXTENSION("mmsh"); + RES_BASE_EXTENSION("multimesh"); public: enum TransformFormat { diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index 2bb9eda19..169c95654 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -28,8 +29,8 @@ /*************************************************************************/ #include "packed_scene.h" #include "core/core_string_names.h" -#include "global_config.h" #include "io/resource_loader.h" +#include "project_settings.h" #include "scene/2d/node_2d.h" #include "scene/3d/spatial.h" #include "scene/gui/control.h" @@ -515,6 +516,9 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map bool isdefault = ((E->get().usage & PROPERTY_USAGE_STORE_IF_NONZERO) && value.is_zero()) || ((E->get().usage & PROPERTY_USAGE_STORE_IF_NONONE) && value.is_one()); + if (E->get().usage & PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE) { + isdefault = true; //is script default value + } /* if (nd.instance<0 && ((E->get().usage & PROPERTY_USAGE_STORE_IF_NONZERO) && value.is_zero()) || ((E->get().usage & PROPERTY_USAGE_STORE_IF_NONONE) && value.is_one())) { continue; @@ -1123,26 +1127,26 @@ bool SceneState::is_connection(int p_node, const StringName &p_signal, int p_to_ return false; } -void SceneState::set_bundled_scene(const Dictionary &d) { +void SceneState::set_bundled_scene(const Dictionary &p_dictionary) { - ERR_FAIL_COND(!d.has("names")); - ERR_FAIL_COND(!d.has("variants")); - ERR_FAIL_COND(!d.has("node_count")); - ERR_FAIL_COND(!d.has("nodes")); - ERR_FAIL_COND(!d.has("conn_count")); - ERR_FAIL_COND(!d.has("conns")); - //ERR_FAIL_COND( !d.has("path")); + ERR_FAIL_COND(!p_dictionary.has("names")); + ERR_FAIL_COND(!p_dictionary.has("variants")); + ERR_FAIL_COND(!p_dictionary.has("node_count")); + ERR_FAIL_COND(!p_dictionary.has("nodes")); + ERR_FAIL_COND(!p_dictionary.has("conn_count")); + ERR_FAIL_COND(!p_dictionary.has("conns")); + //ERR_FAIL_COND( !p_dictionary.has("path")); int version = 1; - if (d.has("version")) - version = d["version"]; + if (p_dictionary.has("version")) + version = p_dictionary["version"]; if (version > PACK_VERSION) { ERR_EXPLAIN("Save format version too new!"); ERR_FAIL(); } - PoolVector<String> snames = d["names"]; + PoolVector<String> snames = p_dictionary["names"]; if (snames.size()) { int namecount = snames.size(); @@ -1152,7 +1156,7 @@ void SceneState::set_bundled_scene(const Dictionary &d) { names[i] = r[i]; } - Array svariants = d["variants"]; + Array svariants = p_dictionary["variants"]; if (svariants.size()) { int varcount = svariants.size(); @@ -1166,10 +1170,10 @@ void SceneState::set_bundled_scene(const Dictionary &d) { variants.clear(); } - nodes.resize(d["node_count"]); + nodes.resize(p_dictionary["node_count"]); int nc = nodes.size(); if (nc) { - PoolVector<int> snodes = d["nodes"]; + PoolVector<int> snodes = p_dictionary["nodes"]; PoolVector<int>::Read r = snodes.read(); int idx = 0; for (int i = 0; i < nc; i++) { @@ -1193,12 +1197,12 @@ void SceneState::set_bundled_scene(const Dictionary &d) { } } - connections.resize(d["conn_count"]); + connections.resize(p_dictionary["conn_count"]); int cc = connections.size(); if (cc) { - PoolVector<int> sconns = d["conns"]; + PoolVector<int> sconns = p_dictionary["conns"]; PoolVector<int>::Read r = sconns.read(); int idx = 0; for (int i = 0; i < cc; i++) { @@ -1218,8 +1222,8 @@ void SceneState::set_bundled_scene(const Dictionary &d) { } Array np; - if (d.has("node_paths")) { - np = d["node_paths"]; + if (p_dictionary.has("node_paths")) { + np = p_dictionary["node_paths"]; } node_paths.resize(np.size()); for (int i = 0; i < np.size(); i++) { @@ -1227,12 +1231,12 @@ void SceneState::set_bundled_scene(const Dictionary &d) { } Array ei; - if (d.has("editable_instances")) { - ei = d["editable_instances"]; + if (p_dictionary.has("editable_instances")) { + ei = p_dictionary["editable_instances"]; } - if (d.has("base_scene")) { - base_scene_idx = d["base_scene"]; + if (p_dictionary.has("base_scene")) { + base_scene_idx = p_dictionary["base_scene"]; } editable_instances.resize(ei.size()); @@ -1240,7 +1244,7 @@ void SceneState::set_bundled_scene(const Dictionary &d) { editable_instances[i] = ei[i]; } - //path=d["path"]; + //path=p_dictionary["path"]; } Dictionary SceneState::get_bundled_scene() const { @@ -1666,7 +1670,7 @@ void SceneState::_bind_methods() { ClassDB::bind_method(D_METHOD("get_node_owner_path", "idx"), &SceneState::get_node_owner_path); ClassDB::bind_method(D_METHOD("is_node_instance_placeholder", "idx"), &SceneState::is_node_instance_placeholder); ClassDB::bind_method(D_METHOD("get_node_instance_placeholder", "idx"), &SceneState::get_node_instance_placeholder); - ClassDB::bind_method(D_METHOD("get_node_instance:PackedScene", "idx"), &SceneState::get_node_instance); + ClassDB::bind_method(D_METHOD("get_node_instance", "idx"), &SceneState::get_node_instance); ClassDB::bind_method(D_METHOD("get_node_groups", "idx"), &SceneState::_get_node_groups); ClassDB::bind_method(D_METHOD("get_node_property_count", "idx"), &SceneState::get_node_property_count); ClassDB::bind_method(D_METHOD("get_node_property_name", "idx", "prop_idx"), &SceneState::get_node_property_name); @@ -1692,9 +1696,9 @@ SceneState::SceneState() { //////////////// -void PackedScene::_set_bundled_scene(const Dictionary &d) { +void PackedScene::_set_bundled_scene(const Dictionary &p_scene) { - state->set_bundled_scene(d); + state->set_bundled_scene(p_scene); } Dictionary PackedScene::_get_bundled_scene() const { @@ -1773,12 +1777,12 @@ void PackedScene::set_path(const String &p_path, bool p_take_over) { void PackedScene::_bind_methods() { - ClassDB::bind_method(D_METHOD("pack", "path:Node"), &PackedScene::pack); - ClassDB::bind_method(D_METHOD("instance:Node", "edit_state"), &PackedScene::instance, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("pack", "path"), &PackedScene::pack); + ClassDB::bind_method(D_METHOD("instance", "edit_state"), &PackedScene::instance, DEFVAL(GEN_EDIT_STATE_DISABLED)); ClassDB::bind_method(D_METHOD("can_instance"), &PackedScene::can_instance); ClassDB::bind_method(D_METHOD("_set_bundled_scene"), &PackedScene::_set_bundled_scene); ClassDB::bind_method(D_METHOD("_get_bundled_scene"), &PackedScene::_get_bundled_scene); - ClassDB::bind_method(D_METHOD("get_state:SceneState"), &PackedScene::get_state); + ClassDB::bind_method(D_METHOD("get_state"), &PackedScene::get_state); ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_bundled"), "_set_bundled_scene", "_get_bundled_scene"); diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h index fe451884f..2f18f5c26 100644 --- a/scene/resources/packed_scene.h +++ b/scene/resources/packed_scene.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/plane_shape.cpp b/scene/resources/plane_shape.cpp index e3535b1a6..d3ad454af 100644 --- a/scene/resources/plane_shape.cpp +++ b/scene/resources/plane_shape.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/plane_shape.h b/scene/resources/plane_shape.h index 899aad7e0..2ed297a97 100644 --- a/scene/resources/plane_shape.h +++ b/scene/resources/plane_shape.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/polygon_path_finder.cpp b/scene/resources/polygon_path_finder.cpp index 44ef828d0..80b413630 100644 --- a/scene/resources/polygon_path_finder.cpp +++ b/scene/resources/polygon_path_finder.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -70,7 +71,7 @@ void PolygonPathFinder::setup(const Vector<Vector2> &p_points, const Vector<int> outside_point.y = i == 0 ? p_points[0].y : (MAX(p_points[i].y, outside_point.y)); if (i == 0) { - bounds.pos = points[i].pos; + bounds.position = points[i].pos; } else { bounds.expand_to(points[i].pos); } diff --git a/scene/resources/polygon_path_finder.h b/scene/resources/polygon_path_finder.h index cd2fea87d..2d2fb1678 100644 --- a/scene/resources/polygon_path_finder.h +++ b/scene/resources/polygon_path_finder.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp new file mode 100644 index 000000000..6a3ddde02 --- /dev/null +++ b/scene/resources/primitive_meshes.cpp @@ -0,0 +1,1478 @@ +/*************************************************************************/ +/* primitive_meshes.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "primitive_meshes.h" +#include "servers/visual_server.h" + +/** + PrimitiveMesh +*/ +void PrimitiveMesh::_update() const { + + Array arr; + arr.resize(VS::ARRAY_MAX); + _create_mesh_array(arr); + + PoolVector<Vector3> points = arr[VS::ARRAY_VERTEX]; + + aabb = Rect3(); + + int pc = points.size(); + ERR_FAIL_COND(pc == 0); + { + + PoolVector<Vector3>::Read r = points.read(); + for (int i = 0; i < pc; i++) { + if (i == 0) + aabb.position = r[i]; + else + aabb.expand_to(r[i]); + } + } + + // in with the new + VisualServer::get_singleton()->mesh_clear(mesh); + VisualServer::get_singleton()->mesh_add_surface_from_arrays(mesh, (VisualServer::PrimitiveType)primitive_type, arr); + VisualServer::get_singleton()->mesh_surface_set_material(mesh, 0, material.is_null() ? RID() : material->get_rid()); + + pending_request = false; + + _clear_triangle_mesh(); +} + +void PrimitiveMesh::_request_update() { + + if (pending_request) + return; + _update(); +} + +int PrimitiveMesh::get_surface_count() const { + return 1; +} + +int PrimitiveMesh::surface_get_array_len(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx, 1, -1); + if (pending_request) { + _update(); + } + + return VisualServer::get_singleton()->mesh_surface_get_array_len(mesh, 0); +} + +int PrimitiveMesh::surface_get_array_index_len(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx, 1, -1); + if (pending_request) { + _update(); + } + + return VisualServer::get_singleton()->mesh_surface_get_array_index_len(mesh, 0); +} + +Array PrimitiveMesh::surface_get_arrays(int p_surface) const { + ERR_FAIL_INDEX_V(p_surface, 1, Array()); + if (pending_request) { + _update(); + } + + return VisualServer::get_singleton()->mesh_surface_get_arrays(mesh, 0); +} + +uint32_t PrimitiveMesh::surface_get_format(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx, 1, 0); + if (pending_request) { + _update(); + } + + return VisualServer::get_singleton()->mesh_surface_get_format(mesh, 0); +} + +Mesh::PrimitiveType PrimitiveMesh::surface_get_primitive_type(int p_idx) const { + return primitive_type; +} + +Ref<Material> PrimitiveMesh::surface_get_material(int p_idx) const { + return material; +} + +int PrimitiveMesh::get_blend_shape_count() const { + return 0; +} + +StringName PrimitiveMesh::get_blend_shape_name(int p_index) const { + return StringName(); +} + +Rect3 PrimitiveMesh::get_aabb() const { + if (pending_request) { + _update(); + } + + return aabb; +} + +RID PrimitiveMesh::get_rid() const { + if (pending_request) { + _update(); + } + return mesh; +} + +void PrimitiveMesh::_bind_methods() { + ClassDB::bind_method(D_METHOD("_update"), &PrimitiveMesh::_update); + + ClassDB::bind_method(D_METHOD("set_material", "material"), &PrimitiveMesh::set_material); + ClassDB::bind_method(D_METHOD("get_material"), &PrimitiveMesh::get_material); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "Material"), "set_material", "get_material"); +} + +void PrimitiveMesh::set_material(const Ref<Material> &p_material) { + material = p_material; + if (!pending_request) { + // just apply it, else it'll happen when _update is called. + VisualServer::get_singleton()->mesh_surface_set_material(mesh, 0, material.is_null() ? RID() : material->get_rid()); + _change_notify(); + emit_changed(); + }; +} + +Ref<Material> PrimitiveMesh::get_material() const { + return material; +} + +PrimitiveMesh::PrimitiveMesh() { + // defaults + mesh = VisualServer::get_singleton()->mesh_create(); + + // assume primitive triangles as the type, correct for all but one and it will change this :) + primitive_type = Mesh::PRIMITIVE_TRIANGLES; + + // make sure we do an update after we've finished constructing our object + pending_request = true; +} + +PrimitiveMesh::~PrimitiveMesh() { + VisualServer::get_singleton()->free(mesh); +} + +/** + CapsuleMesh +*/ + +void CapsuleMesh::_create_mesh_array(Array &p_arr) const { + int i, j, prevrow, thisrow, point; + float x, y, z, u, v, w; + float onethird = 1.0 / 3.0; + float twothirds = 2.0 / 3.0; + + // note, this has been aligned with our collision shape but I've left the descriptions as top/middle/bottom + + PoolVector<Vector3> points; + PoolVector<Vector3> normals; + PoolVector<float> tangents; + PoolVector<Vector2> uvs; + PoolVector<int> indices; + point = 0; + +#define ADD_TANGENT(m_x, m_y, m_z, m_d) \ + tangents.push_back(m_x); \ + tangents.push_back(m_y); \ + tangents.push_back(m_z); \ + tangents.push_back(m_d); + + /* top hemisphere */ + thisrow = 0; + prevrow = 0; + for (j = 0; j <= (rings + 1); j++) { + v = j; + w; + + v /= (rings + 1); + w = sin(0.5 * Math_PI * v); + z = radius * cos(0.5 * Math_PI * v); + + for (i = 0; i <= radial_segments; i++) { + u = i; + u /= radial_segments; + + x = sin(u * (Math_PI * 2.0)); + y = -cos(u * (Math_PI * 2.0)); + + Vector3 p = Vector3(x * radius * w, y * radius * w, z); + points.push_back(p + Vector3(0.0, 0.0, 0.5 * mid_height)); + normals.push_back(p.normalized()); + ADD_TANGENT(y, -x, 0.0, -1.0) + uvs.push_back(Vector2(u, v * onethird)); + point++; + + if (i > 0 && j > 0) { + indices.push_back(prevrow + i - 1); + indices.push_back(prevrow + i); + indices.push_back(thisrow + i - 1); + + indices.push_back(prevrow + i); + indices.push_back(thisrow + i); + indices.push_back(thisrow + i - 1); + }; + }; + + prevrow = thisrow; + thisrow = point; + }; + + /* cylinder */ + thisrow = point; + prevrow = 0; + for (j = 0; j <= (rings + 1); j++) { + v = j; + v /= (rings + 1); + + z = mid_height * v; + z = (mid_height * 0.5) - z; + + for (i = 0; i <= radial_segments; i++) { + u = i; + u /= radial_segments; + + x = sin(u * (Math_PI * 2.0)); + y = -cos(u * (Math_PI * 2.0)); + + Vector3 p = Vector3(x * radius, y * radius, z); + points.push_back(p); + normals.push_back(Vector3(x, y, 0.0)); + ADD_TANGENT(y, -x, 0.0, -1.0) + uvs.push_back(Vector2(u, onethird + (v * onethird))); + point++; + + if (i > 0 && j > 0) { + indices.push_back(prevrow + i - 1); + indices.push_back(prevrow + i); + indices.push_back(thisrow + i - 1); + + indices.push_back(prevrow + i); + indices.push_back(thisrow + i); + indices.push_back(thisrow + i - 1); + }; + }; + + prevrow = thisrow; + thisrow = point; + }; + + /* bottom hemisphere */ + thisrow = point; + prevrow = 0; + for (j = 0; j <= (rings + 1); j++) { + v = j; + w; + + v /= (rings + 1); + v += 1.0; + w = sin(0.5 * Math_PI * v); + z = radius * cos(0.5 * Math_PI * v); + + for (i = 0; i <= radial_segments; i++) { + float u = i; + u /= radial_segments; + + x = sin(u * (Math_PI * 2.0)); + y = -cos(u * (Math_PI * 2.0)); + + Vector3 p = Vector3(x * radius * w, y * radius * w, z); + points.push_back(p + Vector3(0.0, 0.0, -0.5 * mid_height)); + normals.push_back(p.normalized()); + ADD_TANGENT(y, -x, 0.0, -1.0) + uvs.push_back(Vector2(u, twothirds + ((v - 1.0) * onethird))); + point++; + + if (i > 0 && j > 0) { + indices.push_back(prevrow + i - 1); + indices.push_back(prevrow + i); + indices.push_back(thisrow + i - 1); + + indices.push_back(prevrow + i); + indices.push_back(thisrow + i); + indices.push_back(thisrow + i - 1); + }; + }; + + prevrow = thisrow; + thisrow = point; + }; + + p_arr[VS::ARRAY_VERTEX] = points; + p_arr[VS::ARRAY_NORMAL] = normals; + p_arr[VS::ARRAY_TANGENT] = tangents; + p_arr[VS::ARRAY_TEX_UV] = uvs; + p_arr[VS::ARRAY_INDEX] = indices; +} + +void CapsuleMesh::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CapsuleMesh::set_radius); + ClassDB::bind_method(D_METHOD("get_radius"), &CapsuleMesh::get_radius); + ClassDB::bind_method(D_METHOD("set_mid_height", "mid_height"), &CapsuleMesh::set_mid_height); + ClassDB::bind_method(D_METHOD("get_mid_height"), &CapsuleMesh::get_mid_height); + + ClassDB::bind_method(D_METHOD("set_radial_segments", "segments"), &CapsuleMesh::set_radial_segments); + ClassDB::bind_method(D_METHOD("get_radial_segments"), &CapsuleMesh::get_radial_segments); + ClassDB::bind_method(D_METHOD("set_rings", "rings"), &CapsuleMesh::set_rings); + ClassDB::bind_method(D_METHOD("get_rings"), &CapsuleMesh::get_rings); + + ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0.1,100.0,0.1"), "set_radius", "get_radius"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "mid_height", PROPERTY_HINT_RANGE, "0.1,100.0,0.1"), "set_mid_height", "get_mid_height"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1"), "set_radial_segments", "get_radial_segments"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1"), "set_rings", "get_rings"); +} + +void CapsuleMesh::set_radius(const float p_radius) { + radius = p_radius; + _request_update(); +} + +float CapsuleMesh::get_radius() const { + return radius; +} + +void CapsuleMesh::set_mid_height(const float p_mid_height) { + mid_height = p_mid_height; + _request_update(); +} + +float CapsuleMesh::get_mid_height() const { + return mid_height; +} + +void CapsuleMesh::set_radial_segments(const int p_segments) { + radial_segments = p_segments > 4 ? p_segments : 4; + _request_update(); +} + +int CapsuleMesh::get_radial_segments() const { + return radial_segments; +} + +void CapsuleMesh::set_rings(const int p_rings) { + rings = p_rings > 1 ? p_rings : 1; + _request_update(); +} + +int CapsuleMesh::get_rings() const { + return rings; +} + +CapsuleMesh::CapsuleMesh() { + // defaults + radius = 1.0; + mid_height = 1.0; + radial_segments = 64; + rings = 8; +} + +/** + CubeMesh +*/ + +void CubeMesh::_create_mesh_array(Array &p_arr) const { + int i, j, prevrow, thisrow, point; + float x, y, z; + float onethird = 1.0 / 3.0; + float twothirds = 2.0 / 3.0; + + Vector3 start_pos = size * -0.5; + + // set our bounding box + + PoolVector<Vector3> points; + PoolVector<Vector3> normals; + PoolVector<float> tangents; + PoolVector<Vector2> uvs; + PoolVector<int> indices; + point = 0; + +#define ADD_TANGENT(m_x, m_y, m_z, m_d) \ + tangents.push_back(m_x); \ + tangents.push_back(m_y); \ + tangents.push_back(m_z); \ + tangents.push_back(m_d); + + // front + back + y = start_pos.y; + thisrow = point; + prevrow = 0; + for (j = 0; j <= subdivide_h + 1; j++) { + x = start_pos.x; + for (i = 0; i <= subdivide_w + 1; i++) { + float u = i; + float v = j; + u /= (3.0 * (subdivide_w + 1.0)); + v /= (2.0 * (subdivide_h + 1.0)); + + // front + points.push_back(Vector3(x, -y, -start_pos.z)); // double negative on the Z! + normals.push_back(Vector3(0.0, 0.0, 1.0)); + ADD_TANGENT(-1.0, 0.0, 0.0, -1.0); + uvs.push_back(Vector2(u, v)); + point++; + + // back + points.push_back(Vector3(-x, -y, start_pos.z)); + normals.push_back(Vector3(0.0, 0.0, -1.0)); + ADD_TANGENT(1.0, 0.0, 0.0, -1.0); + uvs.push_back(Vector2(twothirds + u, v)); + point++; + + if (i > 0 && j > 0) { + int i2 = i * 2; + + // front + indices.push_back(prevrow + i2 - 2); + indices.push_back(prevrow + i2); + indices.push_back(thisrow + i2 - 2); + indices.push_back(prevrow + i2); + indices.push_back(thisrow + i2); + indices.push_back(thisrow + i2 - 2); + + // back + indices.push_back(prevrow + i2 - 1); + indices.push_back(prevrow + i2 + 1); + indices.push_back(thisrow + i2 - 1); + indices.push_back(prevrow + i2 + 1); + indices.push_back(thisrow + i2 + 1); + indices.push_back(thisrow + i2 - 1); + }; + + x += size.x / (subdivide_w + 1.0); + }; + + y += size.y / (subdivide_h + 1.0); + prevrow = thisrow; + thisrow = point; + }; + + // left + right + y = start_pos.y; + thisrow = point; + prevrow = 0; + for (j = 0; j <= (subdivide_h + 1); j++) { + z = start_pos.z; + for (i = 0; i <= (subdivide_d + 1); i++) { + float u = i; + float v = j; + u /= (3.0 * (subdivide_d + 1.0)); + v /= (2.0 * (subdivide_h + 1.0)); + + // right + points.push_back(Vector3(-start_pos.x, -y, -z)); + normals.push_back(Vector3(1.0, 0.0, 0.0)); + ADD_TANGENT(0.0, 0.0, 1.0, -1.0); + uvs.push_back(Vector2(onethird + u, v)); + point++; + + // left + points.push_back(Vector3(start_pos.x, -y, z)); + normals.push_back(Vector3(-1.0, 0.0, 0.0)); + ADD_TANGENT(0.0, 0.0, -1.0, -1.0); + uvs.push_back(Vector2(u, 0.5 + v)); + point++; + + if (i > 0 && j > 0) { + int i2 = i * 2; + + // right + indices.push_back(prevrow + i2 - 2); + indices.push_back(prevrow + i2); + indices.push_back(thisrow + i2 - 2); + indices.push_back(prevrow + i2); + indices.push_back(thisrow + i2); + indices.push_back(thisrow + i2 - 2); + + // left + indices.push_back(prevrow + i2 - 1); + indices.push_back(prevrow + i2 + 1); + indices.push_back(thisrow + i2 - 1); + indices.push_back(prevrow + i2 + 1); + indices.push_back(thisrow + i2 + 1); + indices.push_back(thisrow + i2 - 1); + }; + + z += size.z / (subdivide_d + 1.0); + }; + + y += size.y / (subdivide_h + 1.0); + prevrow = thisrow; + thisrow = point; + }; + + // top + bottom + z = start_pos.z; + thisrow = point; + prevrow = 0; + for (j = 0; j <= (subdivide_d + 1); j++) { + x = start_pos.x; + for (i = 0; i <= (subdivide_w + 1); i++) { + float u = i; + float v = j; + u /= (3.0 * (subdivide_w + 1.0)); + v /= (2.0 * (subdivide_d + 1.0)); + + // top + points.push_back(Vector3(-x, -start_pos.y, -z)); + normals.push_back(Vector3(0.0, 1.0, 0.0)); + ADD_TANGENT(1.0, 0.0, 0.0, -1.0); + uvs.push_back(Vector2(onethird + u, 0.5 + v)); + point++; + + // bottom + points.push_back(Vector3(x, start_pos.y, -z)); + normals.push_back(Vector3(0.0, -1.0, 0.0)); + ADD_TANGENT(-1.0, 0.0, 0.0, -1.0); + uvs.push_back(Vector2(twothirds + u, 0.5 + v)); + point++; + + if (i > 0 && j > 0) { + int i2 = i * 2; + + // top + indices.push_back(prevrow + i2 - 2); + indices.push_back(prevrow + i2); + indices.push_back(thisrow + i2 - 2); + indices.push_back(prevrow + i2); + indices.push_back(thisrow + i2); + indices.push_back(thisrow + i2 - 2); + + // bottom + indices.push_back(prevrow + i2 - 1); + indices.push_back(prevrow + i2 + 1); + indices.push_back(thisrow + i2 - 1); + indices.push_back(prevrow + i2 + 1); + indices.push_back(thisrow + i2 + 1); + indices.push_back(thisrow + i2 - 1); + }; + + x += size.x / (subdivide_w + 1.0); + }; + + z += size.z / (subdivide_d + 1.0); + prevrow = thisrow; + thisrow = point; + }; + + p_arr[VS::ARRAY_VERTEX] = points; + p_arr[VS::ARRAY_NORMAL] = normals; + p_arr[VS::ARRAY_TANGENT] = tangents; + p_arr[VS::ARRAY_TEX_UV] = uvs; + p_arr[VS::ARRAY_INDEX] = indices; +} + +void CubeMesh::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_size", "size"), &CubeMesh::set_size); + ClassDB::bind_method(D_METHOD("get_size"), &CubeMesh::get_size); + + ClassDB::bind_method(D_METHOD("set_subdivide_width", "subdivide"), &CubeMesh::set_subdivide_width); + ClassDB::bind_method(D_METHOD("get_subdivide_width"), &CubeMesh::get_subdivide_width); + ClassDB::bind_method(D_METHOD("set_subdivide_height", "divisions"), &CubeMesh::set_subdivide_height); + ClassDB::bind_method(D_METHOD("get_subdivide_height"), &CubeMesh::get_subdivide_height); + ClassDB::bind_method(D_METHOD("set_subdivide_depth", "divisions"), &CubeMesh::set_subdivide_depth); + ClassDB::bind_method(D_METHOD("get_subdivide_depth"), &CubeMesh::get_subdivide_depth); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_width", PROPERTY_HINT_RANGE, "0,100,1"), "set_subdivide_width", "get_subdivide_width"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_height", PROPERTY_HINT_RANGE, "0,100,1"), "set_subdivide_height", "get_subdivide_height"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_depth", PROPERTY_HINT_RANGE, "0,100,1"), "set_subdivide_depth", "get_subdivide_depth"); +} + +void CubeMesh::set_size(const Vector3 &p_size) { + size = p_size; + _request_update(); +} + +Vector3 CubeMesh::get_size() const { + return size; +} + +void CubeMesh::set_subdivide_width(const int p_divisions) { + subdivide_w = p_divisions > 0 ? p_divisions : 0; + _request_update(); +} + +int CubeMesh::get_subdivide_width() const { + return subdivide_w; +} + +void CubeMesh::set_subdivide_height(const int p_divisions) { + subdivide_h = p_divisions > 0 ? p_divisions : 0; + _request_update(); +} + +int CubeMesh::get_subdivide_height() const { + return subdivide_h; +} + +void CubeMesh::set_subdivide_depth(const int p_divisions) { + subdivide_d = p_divisions > 0 ? p_divisions : 0; + _request_update(); +} + +int CubeMesh::get_subdivide_depth() const { + return subdivide_d; +} + +CubeMesh::CubeMesh() { + // defaults + size = Vector3(2.0, 2.0, 2.0); + subdivide_w = 0; + subdivide_h = 0; + subdivide_d = 0; +} + +/** + CylinderMesh +*/ + +void CylinderMesh::_create_mesh_array(Array &p_arr) const { + int i, j, prevrow, thisrow, point; + float x, y, z, u, v, radius; + + radius = bottom_radius > top_radius ? bottom_radius : top_radius; + + PoolVector<Vector3> points; + PoolVector<Vector3> normals; + PoolVector<float> tangents; + PoolVector<Vector2> uvs; + PoolVector<int> indices; + point = 0; + +#define ADD_TANGENT(m_x, m_y, m_z, m_d) \ + tangents.push_back(m_x); \ + tangents.push_back(m_y); \ + tangents.push_back(m_z); \ + tangents.push_back(m_d); + + thisrow = 0; + prevrow = 0; + for (j = 0; j <= (rings + 1); j++) { + v = j; + v /= (rings + 1); + + radius = top_radius + ((bottom_radius - top_radius) * v); + + y = height * v; + y = (height * 0.5) - y; + + for (i = 0; i <= radial_segments; i++) { + u = i; + u /= radial_segments; + + x = sin(u * (Math_PI * 2.0)); + z = cos(u * (Math_PI * 2.0)); + + Vector3 p = Vector3(x * radius, y, z * radius); + points.push_back(p); + normals.push_back(Vector3(x, 0.0, z)); + ADD_TANGENT(-z, 0.0, x, -1.0) + uvs.push_back(Vector2(u, v * 0.5)); + point++; + + if (i > 0 && j > 0) { + indices.push_back(prevrow + i - 1); + indices.push_back(prevrow + i); + indices.push_back(thisrow + i - 1); + + indices.push_back(prevrow + i); + indices.push_back(thisrow + i); + indices.push_back(thisrow + i - 1); + }; + }; + + prevrow = thisrow; + thisrow = point; + }; + + // add top + if (top_radius > 0.0) { + y = height * 0.5; + + thisrow = point; + points.push_back(Vector3(0.0, y, 0.0)); + normals.push_back(Vector3(0.0, 1.0, 0.0)); + ADD_TANGENT(1.0, 0.0, 0.0, 1.0) + uvs.push_back(Vector2(0.25, 0.75)); + point++; + + for (i = 0; i <= radial_segments; i++) { + float r = i; + r /= radial_segments; + + x = sin(r * (Math_PI * 2.0)); + z = cos(r * (Math_PI * 2.0)); + + u = ((x + 1.0) * 0.25); + v = 0.5 + ((z + 1.0) * 0.25); + + Vector3 p = Vector3(x * top_radius, y, z * top_radius); + points.push_back(p); + normals.push_back(Vector3(0.0, 1.0, 0.0)); + ADD_TANGENT(1.0, 0.0, 0.0, 1.0) + uvs.push_back(Vector2(u, v)); + point++; + + if (i > 0) { + indices.push_back(thisrow); + indices.push_back(point - 1); + indices.push_back(point - 2); + }; + }; + }; + + // add bottom + if (bottom_radius > 0.0) { + y = height * -0.5; + + thisrow = point; + points.push_back(Vector3(0.0, y, 0.0)); + normals.push_back(Vector3(0.0, -1.0, 0.0)); + ADD_TANGENT(-1.0, 0.0, 0.0, -1.0) + uvs.push_back(Vector2(0.75, 0.75)); + point++; + + for (i = 0; i <= radial_segments; i++) { + float r = i; + r /= radial_segments; + + x = sin(r * (Math_PI * 2.0)); + z = cos(r * (Math_PI * 2.0)); + + u = 0.5 + ((x + 1.0) * 0.25); + v = 1.0 - ((z + 1.0) * 0.25); + + Vector3 p = Vector3(x * bottom_radius, y, z * bottom_radius); + points.push_back(p); + normals.push_back(Vector3(0.0, -1.0, 0.0)); + ADD_TANGENT(-1.0, 0.0, 0.0, -1.0) + uvs.push_back(Vector2(u, v)); + point++; + + if (i > 0) { + indices.push_back(thisrow); + indices.push_back(point - 2); + indices.push_back(point - 1); + }; + }; + }; + + p_arr[VS::ARRAY_VERTEX] = points; + p_arr[VS::ARRAY_NORMAL] = normals; + p_arr[VS::ARRAY_TANGENT] = tangents; + p_arr[VS::ARRAY_TEX_UV] = uvs; + p_arr[VS::ARRAY_INDEX] = indices; +} + +void CylinderMesh::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_top_radius", "radius"), &CylinderMesh::set_top_radius); + ClassDB::bind_method(D_METHOD("get_top_radius"), &CylinderMesh::get_top_radius); + ClassDB::bind_method(D_METHOD("set_bottom_radius", "radius"), &CylinderMesh::set_bottom_radius); + ClassDB::bind_method(D_METHOD("get_bottom_radius"), &CylinderMesh::get_bottom_radius); + ClassDB::bind_method(D_METHOD("set_height", "height"), &CylinderMesh::set_height); + ClassDB::bind_method(D_METHOD("get_height"), &CylinderMesh::get_height); + + ClassDB::bind_method(D_METHOD("set_radial_segments", "segments"), &CylinderMesh::set_radial_segments); + ClassDB::bind_method(D_METHOD("get_radial_segments"), &CylinderMesh::get_radial_segments); + ClassDB::bind_method(D_METHOD("set_rings", "rings"), &CylinderMesh::set_rings); + ClassDB::bind_method(D_METHOD("get_rings"), &CylinderMesh::get_rings); + + ADD_PROPERTY(PropertyInfo(Variant::REAL, "top_radius", PROPERTY_HINT_RANGE, "0.1,100.0,0.1"), "set_top_radius", "get_top_radius"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "bottom_radius", PROPERTY_HINT_RANGE, "0.1,100.0,0.1"), "set_bottom_radius", "get_bottom_radius"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_RANGE, "0.1,100.0,0.1"), "set_height", "get_height"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1"), "set_radial_segments", "get_radial_segments"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1"), "set_rings", "get_rings"); +} + +void CylinderMesh::set_top_radius(const float p_radius) { + top_radius = p_radius; + _request_update(); +} + +float CylinderMesh::get_top_radius() const { + return top_radius; +} + +void CylinderMesh::set_bottom_radius(const float p_radius) { + bottom_radius = p_radius; + _request_update(); +} + +float CylinderMesh::get_bottom_radius() const { + return bottom_radius; +} + +void CylinderMesh::set_height(const float p_height) { + height = p_height; + _request_update(); +} + +float CylinderMesh::get_height() const { + return height; +} + +void CylinderMesh::set_radial_segments(const int p_segments) { + radial_segments = p_segments > 4 ? p_segments : 4; + _request_update(); +} + +int CylinderMesh::get_radial_segments() const { + return radial_segments; +} + +void CylinderMesh::set_rings(const int p_rings) { + rings = p_rings > 0 ? p_rings : 0; + _request_update(); +} + +int CylinderMesh::get_rings() const { + return rings; +} + +CylinderMesh::CylinderMesh() { + // defaults + top_radius = 1.0; + bottom_radius = 1.0; + height = 2.0; + radial_segments = 64; + rings = 4; +} + +/** + PlaneMesh +*/ + +void PlaneMesh::_create_mesh_array(Array &p_arr) const { + int i, j, prevrow, thisrow, point; + float x, z; + + Size2 start_pos = size * -0.5; + + PoolVector<Vector3> points; + PoolVector<Vector3> normals; + PoolVector<float> tangents; + PoolVector<Vector2> uvs; + PoolVector<int> indices; + point = 0; + +#define ADD_TANGENT(m_x, m_y, m_z, m_d) \ + tangents.push_back(m_x); \ + tangents.push_back(m_y); \ + tangents.push_back(m_z); \ + tangents.push_back(m_d); + + /* top + bottom */ + z = start_pos.y; + thisrow = point; + prevrow = 0; + for (j = 0; j <= (subdivide_d + 1); j++) { + x = start_pos.x; + for (i = 0; i <= (subdivide_w + 1); i++) { + float u = i; + float v = j; + u /= (subdivide_w + 1.0); + v /= (subdivide_d + 1.0); + + points.push_back(Vector3(-x, 0.0, -z)); + normals.push_back(Vector3(0.0, 1.0, 0.0)); + ADD_TANGENT(1.0, 0.0, 0.0, -1.0); + uvs.push_back(Vector2(u, v)); + point++; + + if (i > 0 && j > 0) { + indices.push_back(prevrow + i - 1); + indices.push_back(prevrow + i); + indices.push_back(thisrow + i - 1); + indices.push_back(prevrow + i); + indices.push_back(thisrow + i); + indices.push_back(thisrow + i - 1); + }; + + x += size.x / (subdivide_w + 1.0); + }; + + z += size.y / (subdivide_d + 1.0); + prevrow = thisrow; + thisrow = point; + }; + + p_arr[VS::ARRAY_VERTEX] = points; + p_arr[VS::ARRAY_NORMAL] = normals; + p_arr[VS::ARRAY_TANGENT] = tangents; + p_arr[VS::ARRAY_TEX_UV] = uvs; + p_arr[VS::ARRAY_INDEX] = indices; +} + +void PlaneMesh::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_size", "size"), &PlaneMesh::set_size); + ClassDB::bind_method(D_METHOD("get_size"), &PlaneMesh::get_size); + + ClassDB::bind_method(D_METHOD("set_subdivide_width", "subdivide"), &PlaneMesh::set_subdivide_width); + ClassDB::bind_method(D_METHOD("get_subdivide_width"), &PlaneMesh::get_subdivide_width); + ClassDB::bind_method(D_METHOD("set_subdivide_depth", "subdivide"), &PlaneMesh::set_subdivide_depth); + ClassDB::bind_method(D_METHOD("get_subdivide_depth"), &PlaneMesh::get_subdivide_depth); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_width", PROPERTY_HINT_RANGE, "0,100,1"), "set_subdivide_width", "get_subdivide_width"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_depth", PROPERTY_HINT_RANGE, "0,100,1"), "set_subdivide_depth", "get_subdivide_depth"); +} + +void PlaneMesh::set_size(const Size2 &p_size) { + size = p_size; + _request_update(); +} + +Size2 PlaneMesh::get_size() const { + return size; +} + +void PlaneMesh::set_subdivide_width(const int p_divisions) { + subdivide_w = p_divisions > 0 ? p_divisions : 0; + _request_update(); +} + +int PlaneMesh::get_subdivide_width() const { + return subdivide_w; +} + +void PlaneMesh::set_subdivide_depth(const int p_divisions) { + subdivide_d = p_divisions > 0 ? p_divisions : 0; + _request_update(); +} + +int PlaneMesh::get_subdivide_depth() const { + return subdivide_d; +} + +PlaneMesh::PlaneMesh() { + // defaults + size = Size2(2.0, 2.0); + subdivide_w = 0; + subdivide_d = 0; +} + +/** + PrismMesh +*/ + +void PrismMesh::_create_mesh_array(Array &p_arr) const { + int i, j, prevrow, thisrow, point; + float x, y, z; + float onethird = 1.0 / 3.0; + float twothirds = 2.0 / 3.0; + + Vector3 start_pos = size * -0.5; + + // set our bounding box + + PoolVector<Vector3> points; + PoolVector<Vector3> normals; + PoolVector<float> tangents; + PoolVector<Vector2> uvs; + PoolVector<int> indices; + point = 0; + +#define ADD_TANGENT(m_x, m_y, m_z, m_d) \ + tangents.push_back(m_x); \ + tangents.push_back(m_y); \ + tangents.push_back(m_z); \ + tangents.push_back(m_d); + + /* front + back */ + y = start_pos.y; + thisrow = point; + prevrow = 0; + for (j = 0; j <= (subdivide_h + 1); j++) { + float scale = (y - start_pos.y) / size.y; + float scaled_size_x = size.x * scale; + float start_x = start_pos.x; + float offset_front = 0.0; + float offset_back = 0.0; + + start_x += (1.0 - scale) * size.x * left_to_right; + offset_front += (1.0 - scale) * onethird * left_to_right; + offset_back = (1.0 - scale) * onethird * (1.0 - left_to_right); + + x = 0.0; + for (i = 0; i <= (subdivide_w + 1); i++) { + float u = i; + float v = j; + u /= (3.0 * (subdivide_w + 1.0)); + v /= (2.0 * (subdivide_h + 1.0)); + + u *= scale; + + /* front */ + points.push_back(Vector3(start_x + x, -y, -start_pos.z)); // double negative on the Z! + normals.push_back(Vector3(0.0, 0.0, 1.0)); + ADD_TANGENT(-1.0, 0.0, 0.0, -1.0); + uvs.push_back(Vector2(offset_front + u, v)); + point++; + + /* back */ + points.push_back(Vector3(start_x + scaled_size_x - x, -y, start_pos.z)); + normals.push_back(Vector3(0.0, 0.0, -1.0)); + ADD_TANGENT(1.0, 0.0, 0.0, -1.0); + uvs.push_back(Vector2(twothirds + offset_back + u, v)); + point++; + + if (i > 0 && j == 1) { + int i2 = i * 2; + + /* front */ + indices.push_back(prevrow + i2); + indices.push_back(thisrow + i2); + indices.push_back(thisrow + i2 - 2); + + /* back */ + indices.push_back(prevrow + i2 + 1); + indices.push_back(thisrow + i2 + 1); + indices.push_back(thisrow + i2 - 1); + } else if (i > 0 && j > 0) { + int i2 = i * 2; + + /* front */ + indices.push_back(prevrow + i2 - 2); + indices.push_back(prevrow + i2); + indices.push_back(thisrow + i2 - 2); + indices.push_back(prevrow + i2); + indices.push_back(thisrow + i2); + indices.push_back(thisrow + i2 - 2); + + /* back */ + indices.push_back(prevrow + i2 - 1); + indices.push_back(prevrow + i2 + 1); + indices.push_back(thisrow + i2 - 1); + indices.push_back(prevrow + i2 + 1); + indices.push_back(thisrow + i2 + 1); + indices.push_back(thisrow + i2 - 1); + }; + + x += scale * size.x / (subdivide_w + 1.0); + }; + + y += size.y / (subdivide_h + 1.0); + prevrow = thisrow; + thisrow = point; + }; + + /* left + right */ + Vector3 normal_left, normal_right; + + normal_left = Vector3(-size.y, size.x * left_to_right, 0.0); + normal_right = Vector3(size.y, size.x * left_to_right, 0.0); + normal_left.normalize(); + normal_right.normalize(); + + y = start_pos.y; + thisrow = point; + prevrow = 0; + for (j = 0; j <= (subdivide_h + 1); j++) { + float left, right; + float scale = (y - start_pos.y) / size.y; + + left = start_pos.x + (size.x * (1.0 - scale) * left_to_right); + right = left + (size.x * scale); + + z = start_pos.z; + for (i = 0; i <= (subdivide_d + 1); i++) { + float u = i; + float v = j; + u /= (3.0 * (subdivide_d + 1.0)); + v /= (2.0 * (subdivide_h + 1.0)); + + /* right */ + points.push_back(Vector3(right, -y, -z)); + normals.push_back(normal_right); + ADD_TANGENT(0.0, 0.0, 1.0, -1.0); + uvs.push_back(Vector2(onethird + u, v)); + point++; + + /* left */ + points.push_back(Vector3(left, -y, z)); + normals.push_back(normal_left); + ADD_TANGENT(0.0, 0.0, -1.0, -1.0); + uvs.push_back(Vector2(u, 0.5 + v)); + point++; + + if (i > 0 && j > 0) { + int i2 = i * 2; + + /* right */ + indices.push_back(prevrow + i2 - 2); + indices.push_back(prevrow + i2); + indices.push_back(thisrow + i2 - 2); + indices.push_back(prevrow + i2); + indices.push_back(thisrow + i2); + indices.push_back(thisrow + i2 - 2); + + /* left */ + indices.push_back(prevrow + i2 - 1); + indices.push_back(prevrow + i2 + 1); + indices.push_back(thisrow + i2 - 1); + indices.push_back(prevrow + i2 + 1); + indices.push_back(thisrow + i2 + 1); + indices.push_back(thisrow + i2 - 1); + }; + + z += size.z / (subdivide_d + 1.0); + }; + + y += size.y / (subdivide_h + 1.0); + prevrow = thisrow; + thisrow = point; + }; + + /* bottom */ + z = start_pos.z; + thisrow = point; + prevrow = 0; + for (j = 0; j <= (subdivide_d + 1); j++) { + x = start_pos.x; + for (i = 0; i <= (subdivide_w + 1); i++) { + float u = i; + float v = j; + u /= (3.0 * (subdivide_w + 1.0)); + v /= (2.0 * (subdivide_d + 1.0)); + + /* bottom */ + points.push_back(Vector3(x, start_pos.y, -z)); + normals.push_back(Vector3(0.0, -1.0, 0.0)); + ADD_TANGENT(-1.0, 0.0, 0.0, -1.0); + uvs.push_back(Vector2(twothirds + u, 0.5 + v)); + point++; + + if (i > 0 && j > 0) { + /* bottom */ + indices.push_back(prevrow + i - 1); + indices.push_back(prevrow + i); + indices.push_back(thisrow + i - 1); + indices.push_back(prevrow + i); + indices.push_back(thisrow + i); + indices.push_back(thisrow + i - 1); + }; + + x += size.x / (subdivide_w + 1.0); + }; + + z += size.z / (subdivide_d + 1.0); + prevrow = thisrow; + thisrow = point; + }; + + p_arr[VS::ARRAY_VERTEX] = points; + p_arr[VS::ARRAY_NORMAL] = normals; + p_arr[VS::ARRAY_TANGENT] = tangents; + p_arr[VS::ARRAY_TEX_UV] = uvs; + p_arr[VS::ARRAY_INDEX] = indices; +} + +void PrismMesh::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_left_to_right", "left_to_right"), &PrismMesh::set_left_to_right); + ClassDB::bind_method(D_METHOD("get_left_to_right"), &PrismMesh::get_left_to_right); + + ClassDB::bind_method(D_METHOD("set_size", "size"), &PrismMesh::set_size); + ClassDB::bind_method(D_METHOD("get_size"), &PrismMesh::get_size); + + ClassDB::bind_method(D_METHOD("set_subdivide_width", "segments"), &PrismMesh::set_subdivide_width); + ClassDB::bind_method(D_METHOD("get_subdivide_width"), &PrismMesh::get_subdivide_width); + ClassDB::bind_method(D_METHOD("set_subdivide_height", "segments"), &PrismMesh::set_subdivide_height); + ClassDB::bind_method(D_METHOD("get_subdivide_height"), &PrismMesh::get_subdivide_height); + ClassDB::bind_method(D_METHOD("set_subdivide_depth", "segments"), &PrismMesh::set_subdivide_depth); + ClassDB::bind_method(D_METHOD("get_subdivide_depth"), &PrismMesh::get_subdivide_depth); + + ADD_PROPERTY(PropertyInfo(Variant::REAL, "left_to_right", PROPERTY_HINT_RANGE, "-2.0,2.0,0.1"), "set_left_to_right", "get_left_to_right"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size", PROPERTY_HINT_RANGE, "0.1,100.0,0.1"), "set_size", "get_size"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_width", PROPERTY_HINT_RANGE, "0,100,1"), "set_subdivide_width", "get_subdivide_width"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_height", PROPERTY_HINT_RANGE, "0,100,1"), "set_subdivide_height", "get_subdivide_height"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_depth", PROPERTY_HINT_RANGE, "0,100,1"), "set_subdivide_depth", "get_subdivide_depth"); +} + +void PrismMesh::set_left_to_right(const float p_left_to_right) { + left_to_right = p_left_to_right; + _request_update(); +} + +float PrismMesh::get_left_to_right() const { + return left_to_right; +} + +void PrismMesh::set_size(const Vector3 &p_size) { + size = p_size; + _request_update(); +} + +Vector3 PrismMesh::get_size() const { + return size; +} + +void PrismMesh::set_subdivide_width(const int p_divisions) { + subdivide_w = p_divisions > 0 ? p_divisions : 0; + _request_update(); +} + +int PrismMesh::get_subdivide_width() const { + return subdivide_w; +} + +void PrismMesh::set_subdivide_height(const int p_divisions) { + subdivide_h = p_divisions > 0 ? p_divisions : 0; + _request_update(); +} + +int PrismMesh::get_subdivide_height() const { + return subdivide_h; +} + +void PrismMesh::set_subdivide_depth(const int p_divisions) { + subdivide_d = p_divisions > 0 ? p_divisions : 0; + _request_update(); +} + +int PrismMesh::get_subdivide_depth() const { + return subdivide_d; +} + +PrismMesh::PrismMesh() { + // defaults + left_to_right = 0.5; + size = Vector3(2.0, 2.0, 2.0); + subdivide_w = 0; + subdivide_h = 0; + subdivide_d = 0; +} + +/** + QuadMesh +*/ + +void QuadMesh::_create_mesh_array(Array &p_arr) const { + PoolVector<Vector3> faces; + PoolVector<Vector3> normals; + PoolVector<float> tangents; + PoolVector<Vector2> uvs; + + faces.resize(4); + normals.resize(4); + tangents.resize(4 * 4); + uvs.resize(4); + + for (int i = 0; i < 4; i++) { + + static const Vector3 quad_faces[4] = { + Vector3(-1, -1, 0), + Vector3(-1, 1, 0), + Vector3(1, 1, 0), + Vector3(1, -1, 0), + }; + + faces.set(i, quad_faces[i]); + normals.set(i, Vector3(0, 0, 1)); + tangents.set(i * 4 + 0, 1.0); + tangents.set(i * 4 + 1, 0.0); + tangents.set(i * 4 + 2, 0.0); + tangents.set(i * 4 + 3, 1.0); + + static const Vector2 quad_uv[4] = { + Vector2(0, 1), + Vector2(0, 0), + Vector2(1, 0), + Vector2(1, 1), + }; + + uvs.set(i, quad_uv[i]); + } + + p_arr[ARRAY_VERTEX] = faces; + p_arr[ARRAY_NORMAL] = normals; + p_arr[ARRAY_TANGENT] = tangents; + p_arr[ARRAY_TEX_UV] = uvs; +}; + +void QuadMesh::_bind_methods() { + // nothing here yet... +} + +QuadMesh::QuadMesh() { + primitive_type = PRIMITIVE_TRIANGLE_FAN; +} + +/** + SphereMesh +*/ + +void SphereMesh::_create_mesh_array(Array &p_arr) const { + int i, j, prevrow, thisrow, point; + float x, y, z; + + // set our bounding box + + PoolVector<Vector3> points; + PoolVector<Vector3> normals; + PoolVector<float> tangents; + PoolVector<Vector2> uvs; + PoolVector<int> indices; + point = 0; + +#define ADD_TANGENT(m_x, m_y, m_z, m_d) \ + tangents.push_back(m_x); \ + tangents.push_back(m_y); \ + tangents.push_back(m_z); \ + tangents.push_back(m_d); + + thisrow = 0; + prevrow = 0; + for (j = 0; j <= (rings + 1); j++) { + float v = j; + float w; + + v /= (rings + 1); + w = sin(Math_PI * v); + y = height * (is_hemisphere ? 1.0 : 0.5) * cos(Math_PI * v); + + for (i = 0; i <= radial_segments; i++) { + float u = i; + u /= radial_segments; + + x = sin(u * (Math_PI * 2.0)); + z = cos(u * (Math_PI * 2.0)); + + if (is_hemisphere && y < 0.0) { + points.push_back(Vector3(x * radius * w, 0.0, z * radius * w)); + normals.push_back(Vector3(0.0, -1.0, 0.0)); + } else { + Vector3 p = Vector3(x * radius * w, y, z * radius * w); + points.push_back(p); + normals.push_back(p.normalized()); + }; + ADD_TANGENT(-z, 0.0, x, -1.0) + uvs.push_back(Vector2(u, v)); + point++; + + if (i > 0 && j > 0) { + indices.push_back(prevrow + i - 1); + indices.push_back(prevrow + i); + indices.push_back(thisrow + i - 1); + + indices.push_back(prevrow + i); + indices.push_back(thisrow + i); + indices.push_back(thisrow + i - 1); + }; + }; + + prevrow = thisrow; + thisrow = point; + }; + + p_arr[VS::ARRAY_VERTEX] = points; + p_arr[VS::ARRAY_NORMAL] = normals; + p_arr[VS::ARRAY_TANGENT] = tangents; + p_arr[VS::ARRAY_TEX_UV] = uvs; + p_arr[VS::ARRAY_INDEX] = indices; +} + +void SphereMesh::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_radius", "radius"), &SphereMesh::set_radius); + ClassDB::bind_method(D_METHOD("get_radius"), &SphereMesh::get_radius); + ClassDB::bind_method(D_METHOD("set_height", "height"), &SphereMesh::set_height); + ClassDB::bind_method(D_METHOD("get_height"), &SphereMesh::get_height); + + ClassDB::bind_method(D_METHOD("set_radial_segments", "radial_segments"), &SphereMesh::set_radial_segments); + ClassDB::bind_method(D_METHOD("get_radial_segments"), &SphereMesh::get_radial_segments); + ClassDB::bind_method(D_METHOD("set_rings", "rings"), &SphereMesh::set_rings); + ClassDB::bind_method(D_METHOD("get_rings"), &SphereMesh::get_rings); + + ClassDB::bind_method(D_METHOD("set_is_hemisphere", "is_hemisphere"), &SphereMesh::set_is_hemisphere); + ClassDB::bind_method(D_METHOD("get_is_hemisphere"), &SphereMesh::get_is_hemisphere); + + ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0.1,100.0,0.1"), "set_radius", "get_radius"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_RANGE, "0.1,100.0,0.1"), "set_height", "get_height"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1"), "set_radial_segments", "get_radial_segments"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1"), "set_rings", "get_rings"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "is_hemisphere"), "set_is_hemisphere", "get_is_hemisphere"); +} + +void SphereMesh::set_radius(const float p_radius) { + radius = p_radius; + _request_update(); +} + +float SphereMesh::get_radius() const { + return radius; +} + +void SphereMesh::set_height(const float p_height) { + height = p_height; + _request_update(); +} + +float SphereMesh::get_height() const { + return height; +} + +void SphereMesh::set_radial_segments(const int p_radial_segments) { + radial_segments = p_radial_segments > 4 ? p_radial_segments : 4; + _request_update(); +} + +int SphereMesh::get_radial_segments() const { + return radial_segments; +} + +void SphereMesh::set_rings(const int p_rings) { + rings = p_rings > 1 ? p_rings : 1; + _request_update(); +} + +int SphereMesh::get_rings() const { + return rings; +} + +void SphereMesh::set_is_hemisphere(const bool p_is_hemisphere) { + is_hemisphere = p_is_hemisphere; + _request_update(); +} + +bool SphereMesh::get_is_hemisphere() const { + return is_hemisphere; +} + +SphereMesh::SphereMesh() { + // defaults + radius = 1.0; + height = 2.0; + radial_segments = 64; + rings = 32; + is_hemisphere = false; +} diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h new file mode 100644 index 000000000..bcd5d30dd --- /dev/null +++ b/scene/resources/primitive_meshes.h @@ -0,0 +1,310 @@ +/*************************************************************************/ +/* primitive_meshes.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef PRIMITIVE_MESHES_H +#define PRIMITIVE_MESHES_H + +#include "scene/resources/mesh.h" + +///@TODO probably should change a few integers to unsigned integers... + +/** + @author Bastiaan Olij <mux213@gmail.com> + + Base class for all the classes in this file, handles a number of code functions that are shared among all meshes. + This class is set appart that it assumes a single surface is always generated for our mesh. +*/ +class PrimitiveMesh : public Mesh { + + GDCLASS(PrimitiveMesh, Mesh); + +private: + RID mesh; + mutable Rect3 aabb; + + Ref<Material> material; + + mutable bool pending_request; + void _update() const; + +protected: + Mesh::PrimitiveType primitive_type; + + static void _bind_methods(); + + virtual void _create_mesh_array(Array &p_arr) const = 0; + void _request_update(); + +public: + virtual int get_surface_count() const; + virtual int surface_get_array_len(int p_idx) const; + virtual int surface_get_array_index_len(int p_idx) const; + virtual Array surface_get_arrays(int p_surface) const; + virtual uint32_t surface_get_format(int p_idx) const; + virtual Mesh::PrimitiveType surface_get_primitive_type(int p_idx) const; + virtual Ref<Material> surface_get_material(int p_idx) const; + virtual int get_blend_shape_count() const; + virtual StringName get_blend_shape_name(int p_index) const; + virtual Rect3 get_aabb() const; + virtual RID get_rid() const; + + void set_material(const Ref<Material> &p_material); + Ref<Material> get_material() const; + + PrimitiveMesh(); + ~PrimitiveMesh(); +}; + +/** + Mesh for a simple capsule +*/ +class CapsuleMesh : public PrimitiveMesh { + GDCLASS(CapsuleMesh, PrimitiveMesh); + +private: + float radius; + float mid_height; + int radial_segments; + int rings; + +protected: + static void _bind_methods(); + virtual void _create_mesh_array(Array &p_arr) const; + +public: + void set_radius(const float p_radius); + float get_radius() const; + + void set_mid_height(const float p_mid_height); + float get_mid_height() const; + + void set_radial_segments(const int p_segments); + int get_radial_segments() const; + + void set_rings(const int p_rings); + int get_rings() const; + + CapsuleMesh(); +}; + +/** + Similar to test cube but with subdivision support and different texture coordinates +*/ +class CubeMesh : public PrimitiveMesh { + + GDCLASS(CubeMesh, PrimitiveMesh); + +private: + Vector3 size; + int subdivide_w; + int subdivide_h; + int subdivide_d; + +protected: + static void _bind_methods(); + virtual void _create_mesh_array(Array &p_arr) const; + +public: + void set_size(const Vector3 &p_size); + Vector3 get_size() const; + + void set_subdivide_width(const int p_divisions); + int get_subdivide_width() const; + + void set_subdivide_height(const int p_divisions); + int get_subdivide_height() const; + + void set_subdivide_depth(const int p_divisions); + int get_subdivide_depth() const; + + CubeMesh(); +}; + +/** + A cylinder +*/ + +class CylinderMesh : public PrimitiveMesh { + + GDCLASS(CylinderMesh, PrimitiveMesh); + +private: + float top_radius; + float bottom_radius; + float height; + int radial_segments; + int rings; + +protected: + static void _bind_methods(); + virtual void _create_mesh_array(Array &p_arr) const; + +public: + void set_top_radius(const float p_radius); + float get_top_radius() const; + + void set_bottom_radius(const float p_radius); + float get_bottom_radius() const; + + void set_height(const float p_height); + float get_height() const; + + void set_radial_segments(const int p_segments); + int get_radial_segments() const; + + void set_rings(const int p_rings); + int get_rings() const; + + CylinderMesh(); +}; + +/** + Similar to quadmesh but with tesselation support +*/ +class PlaneMesh : public PrimitiveMesh { + + GDCLASS(PlaneMesh, PrimitiveMesh); + +private: + Size2 size; + int subdivide_w; + int subdivide_d; + +protected: + static void _bind_methods(); + virtual void _create_mesh_array(Array &p_arr) const; + +public: + void set_size(const Size2 &p_size); + Size2 get_size() const; + + void set_subdivide_width(const int p_divisions); + int get_subdivide_width() const; + + void set_subdivide_depth(const int p_divisions); + int get_subdivide_depth() const; + + PlaneMesh(); +}; + +/** + A prism shapen, handy for ramps, triangles, etc. +*/ +class PrismMesh : public PrimitiveMesh { + + GDCLASS(PrismMesh, PrimitiveMesh); + +private: + float left_to_right; + Vector3 size; + int subdivide_w; + int subdivide_h; + int subdivide_d; + +protected: + static void _bind_methods(); + virtual void _create_mesh_array(Array &p_arr) const; + +public: + void set_left_to_right(const float p_left_to_right); + float get_left_to_right() const; + + void set_size(const Vector3 &p_size); + Vector3 get_size() const; + + void set_subdivide_width(const int p_divisions); + int get_subdivide_width() const; + + void set_subdivide_height(const int p_divisions); + int get_subdivide_height() const; + + void set_subdivide_depth(const int p_divisions); + int get_subdivide_depth() const; + + PrismMesh(); +}; + +/** + Our original quadmesh... +*/ + +class QuadMesh : public PrimitiveMesh { + + GDCLASS(QuadMesh, PrimitiveMesh) + +private: + // nothing? really? Maybe add size some day atleast... :) + +protected: + static void _bind_methods(); + virtual void _create_mesh_array(Array &p_arr) const; + +public: + QuadMesh(); +}; + +/** + A sphere.. +*/ +class SphereMesh : public PrimitiveMesh { + + GDCLASS(SphereMesh, PrimitiveMesh); + +private: + float radius; + float height; + int radial_segments; + int rings; + bool is_hemisphere; + +protected: + static void _bind_methods(); + virtual void _create_mesh_array(Array &p_arr) const; + +public: + void set_radius(const float p_radius); + float get_radius() const; + + void set_height(const float p_height); + float get_height() const; + + void set_radial_segments(const int p_radial_segments); + int get_radial_segments() const; + + void set_rings(const int p_rings); + int get_rings() const; + + void set_is_hemisphere(const bool p_is_hemisphere); + bool get_is_hemisphere() const; + + SphereMesh(); +}; + +#endif diff --git a/scene/resources/ray_shape.cpp b/scene/resources/ray_shape.cpp index 8187b8b3f..3abb2a4fa 100644 --- a/scene/resources/ray_shape.cpp +++ b/scene/resources/ray_shape.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/ray_shape.h b/scene/resources/ray_shape.h index f8dbf89e0..5a17e9414 100644 --- a/scene/resources/ray_shape.h +++ b/scene/resources/ray_shape.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/rectangle_shape_2d.cpp b/scene/resources/rectangle_shape_2d.cpp index 06b5ac031..bd9ec8cbc 100644 --- a/scene/resources/rectangle_shape_2d.cpp +++ b/scene/resources/rectangle_shape_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/rectangle_shape_2d.h b/scene/resources/rectangle_shape_2d.h index 8de2f7580..23db58ba0 100644 --- a/scene/resources/rectangle_shape_2d.h +++ b/scene/resources/rectangle_shape_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/room.cpp b/scene/resources/room.cpp index 9ec8914e2..c89b7c72c 100644 --- a/scene/resources/room.cpp +++ b/scene/resources/room.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/room.h b/scene/resources/room.h index c7db4b13d..ba5c0eee1 100644 --- a/scene/resources/room.h +++ b/scene/resources/room.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -49,7 +50,7 @@ protected: public: virtual RID get_rid() const; - void set_geometry_hint(const PoolVector<Face3> &geometry_hint); + void set_geometry_hint(const PoolVector<Face3> &p_geometry_hint); PoolVector<Face3> get_geometry_hint() const; RoomBounds(); diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp index 7162c9fc1..49cd030a9 100644 --- a/scene/resources/scene_format_text.cpp +++ b/scene/resources/scene_format_text.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -28,8 +29,8 @@ /*************************************************************************/ #include "scene_format_text.h" -#include "global_config.h" #include "os/dir_access.h" +#include "project_settings.h" #include "version.h" //version 2: changed names for basis, rect3, poolvectors, etc. @@ -109,7 +110,7 @@ Error ResourceInteractiveLoaderText::_parse_ext_resource(VariantParser::Stream * if (path.find("://") == -1 && path.is_rel_path()) { // path is relative to file being loaded, so convert to a resource path - path = GlobalConfig::get_singleton()->localize_path(res_path.get_base_dir().plus_file(path)); + path = ProjectSettings::get_singleton()->localize_path(res_path.get_base_dir().plus_file(path)); } r_res = ResourceLoader::load(path, type); @@ -164,7 +165,7 @@ Error ResourceInteractiveLoaderText::poll() { if (path.find("://") == -1 && path.is_rel_path()) { // path is relative to file being loaded, so convert to a resource path - path = GlobalConfig::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path)); + path = ProjectSettings::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path)); } if (remaps.has(path)) { @@ -331,6 +332,7 @@ Error ResourceInteractiveLoaderText::poll() { if (!ResourceCache::has(res_path)) { resource->set_path(res_path); } + resource->set_as_translation_remapped(translation_remapped); } return error; } @@ -605,14 +607,23 @@ int ResourceInteractiveLoaderText::get_stage_count() const { return resources_total; //+ext_resources; } +void ResourceInteractiveLoaderText::set_translation_remapped(bool p_remapped) { + + translation_remapped = p_remapped; +} + +ResourceInteractiveLoaderText::ResourceInteractiveLoaderText() { + translation_remapped = false; +} + ResourceInteractiveLoaderText::~ResourceInteractiveLoaderText() { memdelete(f); } -void ResourceInteractiveLoaderText::get_dependencies(FileAccess *f, List<String> *p_dependencies, bool p_add_types) { +void ResourceInteractiveLoaderText::get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types) { - open(f); + open(p_f); ignore_resource_parsing = true; ERR_FAIL_COND(error != OK); @@ -637,7 +648,7 @@ void ResourceInteractiveLoaderText::get_dependencies(FileAccess *f, List<String> if (path.find("://") == -1 && path.is_rel_path()) { // path is relative to file being loaded, so convert to a resource path - path = GlobalConfig::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path)); + path = ProjectSettings::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path)); } if (p_add_types) { @@ -894,9 +905,9 @@ Ref<ResourceInteractiveLoader> ResourceFormatLoaderText::load_interactive(const } Ref<ResourceInteractiveLoaderText> ria = memnew(ResourceInteractiveLoaderText); - ria->local_path = GlobalConfig::get_singleton()->localize_path(p_path); + ria->local_path = ProjectSettings::get_singleton()->localize_path(p_path); ria->res_path = ria->local_path; - //ria->set_local_path( GlobalConfig::get_singleton()->localize_path(p_path) ); + //ria->set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) ); ria->open(f); return ria; @@ -942,9 +953,9 @@ String ResourceFormatLoaderText::get_resource_type(const String &p_path) const { } Ref<ResourceInteractiveLoaderText> ria = memnew(ResourceInteractiveLoaderText); - ria->local_path = GlobalConfig::get_singleton()->localize_path(p_path); + ria->local_path = ProjectSettings::get_singleton()->localize_path(p_path); ria->res_path = ria->local_path; - //ria->set_local_path( GlobalConfig::get_singleton()->localize_path(p_path) ); + //ria->set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) ); String r = ria->recognize(f); return r; } @@ -958,9 +969,9 @@ void ResourceFormatLoaderText::get_dependencies(const String &p_path, List<Strin } Ref<ResourceInteractiveLoaderText> ria = memnew(ResourceInteractiveLoaderText); - ria->local_path = GlobalConfig::get_singleton()->localize_path(p_path); + ria->local_path = ProjectSettings::get_singleton()->localize_path(p_path); ria->res_path = ria->local_path; - //ria->set_local_path( GlobalConfig::get_singleton()->localize_path(p_path) ); + //ria->set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) ); ria->get_dependencies(f, p_dependencies, p_add_types); } @@ -973,9 +984,9 @@ Error ResourceFormatLoaderText::rename_dependencies(const String &p_path, const } Ref<ResourceInteractiveLoaderText> ria = memnew(ResourceInteractiveLoaderText); - ria->local_path = GlobalConfig::get_singleton()->localize_path(p_path); + ria->local_path = ProjectSettings::get_singleton()->localize_path(p_path); ria->res_path = ria->local_path; - //ria->set_local_path( GlobalConfig::get_singleton()->localize_path(p_path) ); + //ria->set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) ); return ria->rename_dependencies(f, p_path, p_map); } @@ -1107,7 +1118,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r ERR_FAIL_COND_V(err, ERR_CANT_OPEN); FileAccessRef _fref(f); - local_path = GlobalConfig::get_singleton()->localize_path(p_path); + local_path = ProjectSettings::get_singleton()->localize_path(p_path); relative_paths = p_flags & ResourceSaver::FLAG_RELATIVE_PATHS; skip_editor = p_flags & ResourceSaver::FLAG_OMIT_EDITOR_PROPERTIES; diff --git a/scene/resources/scene_format_text.h b/scene/resources/scene_format_text.h index 99e7de623..1ea6465c2 100644 --- a/scene/resources/scene_format_text.h +++ b/scene/resources/scene_format_text.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -37,6 +38,7 @@ class ResourceInteractiveLoaderText : public ResourceInteractiveLoader { + bool translation_remapped; String local_path; String res_path; String error_text; @@ -93,12 +95,14 @@ public: virtual Error poll(); virtual int get_stage() const; virtual int get_stage_count() const; + virtual void set_translation_remapped(bool p_remapped); void open(FileAccess *p_f, bool p_skip_first_tag = false); String recognize(FileAccess *p_f); void get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types); Error rename_dependencies(FileAccess *p_f, const String &p_path, const Map<String, String> &p_map); + ResourceInteractiveLoaderText(); ~ResourceInteractiveLoaderText(); }; diff --git a/scene/resources/segment_shape_2d.cpp b/scene/resources/segment_shape_2d.cpp index 7a1114f89..99062d693 100644 --- a/scene/resources/segment_shape_2d.cpp +++ b/scene/resources/segment_shape_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -34,7 +35,7 @@ void SegmentShape2D::_update_shape() { Rect2 r; - r.pos = a; + r.position = a; r.size = b; Physics2DServer::get_singleton()->shape_set_data(get_rid(), r); emit_changed(); @@ -68,7 +69,7 @@ void SegmentShape2D::draw(const RID &p_to_rid, const Color &p_color) { Rect2 SegmentShape2D::get_rect() const { Rect2 rect; - rect.pos = a; + rect.position = a; rect.expand_to(b); return rect; } @@ -120,7 +121,7 @@ void RayShape2D::draw(const RID &p_to_rid, const Color &p_color) { Rect2 RayShape2D::get_rect() const { Rect2 rect; - rect.pos = Vector2(); + rect.position = Vector2(); rect.expand_to(Vector2(0, length)); rect = rect.grow(0.707 * 4); return rect; diff --git a/scene/resources/segment_shape_2d.h b/scene/resources/segment_shape_2d.h index e58ce6be6..22fc1ab6e 100644 --- a/scene/resources/segment_shape_2d.h +++ b/scene/resources/segment_shape_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index fd058a4a6..b72eb9fbe 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,6 +30,7 @@ #include "shader.h" #include "os/file_access.h" #include "scene/scene_string_names.h" +#include "servers/visual/shader_language.h" #include "servers/visual_server.h" #include "texture.h" @@ -39,6 +41,18 @@ Shader::Mode Shader::get_mode() const { void Shader::set_code(const String &p_code) { + String type = ShaderLanguage::get_shader_type(p_code); + + print_line("mode: " + type); + + if (type == "canvas_item") { + mode = MODE_CANVAS_ITEM; + } else if (type == "particles") { + mode = MODE_PARTICLES; + } else { + mode = MODE_SPATIAL; + } + VisualServer::get_singleton()->shader_set_code(shader, p_code); params_cache_dirty = true; emit_signal(SceneStringNames::get_singleton()->changed); @@ -114,8 +128,8 @@ void Shader::_bind_methods() { ClassDB::bind_method(D_METHOD("set_code", "code"), &Shader::set_code); ClassDB::bind_method(D_METHOD("get_code"), &Shader::get_code); - ClassDB::bind_method(D_METHOD("set_default_texture_param", "param", "texture:Texture"), &Shader::set_default_texture_param); - ClassDB::bind_method(D_METHOD("get_default_texture_param:Texture", "param"), &Shader::get_default_texture_param); + ClassDB::bind_method(D_METHOD("set_default_texture_param", "param", "texture"), &Shader::set_default_texture_param); + ClassDB::bind_method(D_METHOD("get_default_texture_param", "param"), &Shader::get_default_texture_param); ClassDB::bind_method(D_METHOD("has_param", "name"), &Shader::has_param); @@ -128,10 +142,10 @@ void Shader::_bind_methods() { BIND_CONSTANT(MODE_PARTICLES); } -Shader::Shader(Mode p_mode) { +Shader::Shader() { - mode = p_mode; - shader = VisualServer::get_singleton()->shader_create(VS::ShaderMode(p_mode)); + mode = MODE_SPATIAL; + shader = VisualServer::get_singleton()->shader_create(); params_cache_dirty = true; } diff --git a/scene/resources/shader.h b/scene/resources/shader.h index bc98fbf73..0e8e48d82 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -88,37 +89,10 @@ public: virtual RID get_rid() const; - Shader(Mode p_mode); + Shader(); ~Shader(); }; VARIANT_ENUM_CAST(Shader::Mode); -class SpatialShader : public Shader { - - GDCLASS(SpatialShader, Shader); - -public: - SpatialShader() - : Shader(MODE_SPATIAL){}; -}; - -class CanvasItemShader : public Shader { - - GDCLASS(CanvasItemShader, Shader); - -public: - CanvasItemShader() - : Shader(MODE_CANVAS_ITEM){}; -}; - -class ParticlesShader : public Shader { - - GDCLASS(ParticlesShader, Shader); - -public: - ParticlesShader() - : Shader(MODE_PARTICLES){}; -}; - #endif // SHADER_H diff --git a/scene/resources/shader_graph.cpp b/scene/resources/shader_graph.cpp index 28b8490cb..f68aed6af 100644 --- a/scene/resources/shader_graph.cpp +++ b/scene/resources/shader_graph.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -237,11 +238,11 @@ void ShaderGraph::_bind_methods() { ClassDB::bind_method(D_METHOD("xform_input_node_set_value","shader_type","id","value"),&ShaderGraph::xform_input_node_set_value); ClassDB::bind_method(D_METHOD("xform_input_node_get_value","shader_type","id"),&ShaderGraph::xform_input_node_get_value); - ClassDB::bind_method(D_METHOD("texture_input_node_set_value","shader_type","id","value:Texture"),&ShaderGraph::texture_input_node_set_value); - ClassDB::bind_method(D_METHOD("texture_input_node_get_value:Texture","shader_type","id"),&ShaderGraph::texture_input_node_get_value); + ClassDB::bind_method(D_METHOD("texture_input_node_set_value","shader_type","id","value"),&ShaderGraph::texture_input_node_set_value); + ClassDB::bind_method(D_METHOD("texture_input_node_get_value","shader_type","id"),&ShaderGraph::texture_input_node_get_value); - ClassDB::bind_method(D_METHOD("cubemap_input_node_set_value","shader_type","id","value:CubeMap"),&ShaderGraph::cubemap_input_node_set_value); - ClassDB::bind_method(D_METHOD("cubemap_input_node_get_value:CubeMap","shader_type","id"),&ShaderGraph::cubemap_input_node_get_value); + ClassDB::bind_method(D_METHOD("cubemap_input_node_set_value","shader_type","id","value"),&ShaderGraph::cubemap_input_node_set_value); + ClassDB::bind_method(D_METHOD("cubemap_input_node_get_value","shader_type","id"),&ShaderGraph::cubemap_input_node_get_value); ClassDB::bind_method(D_METHOD("comment_node_set_text","shader_type","id","text"),&ShaderGraph::comment_node_set_text); ClassDB::bind_method(D_METHOD("comment_node_get_text","shader_type","id"),&ShaderGraph::comment_node_get_text); @@ -253,7 +254,7 @@ void ShaderGraph::_bind_methods() { ClassDB::bind_method(D_METHOD("curve_map_node_set_points","shader_type","id","points"),&ShaderGraph::curve_map_node_set_points); ClassDB::bind_method(D_METHOD("curve_map_node_get_points","shader_type","id"),&ShaderGraph::curve_map_node_get_points); - ClassDB::bind_method(D_METHOD("connect_node:Error","shader_type","src_id","src_slot","dst_id","dst_slot"),&ShaderGraph::connect_node); + ClassDB::bind_method(D_METHOD("connect_node","shader_type","src_id","src_slot","dst_id","dst_slot"),&ShaderGraph::connect_node); ClassDB::bind_method(D_METHOD("is_node_connected","shader_type","src_id","src_slot","dst_id","dst_slot"),&ShaderGraph::is_node_connected); ClassDB::bind_method(D_METHOD("disconnect_node","shader_type","src_id","src_slot","dst_id","dst_slot"),&ShaderGraph::disconnect_node); ClassDB::bind_method(D_METHOD("get_node_connections","shader_type"),&ShaderGraph::_get_connections); @@ -261,7 +262,7 @@ void ShaderGraph::_bind_methods() { ClassDB::bind_method(D_METHOD("clear","shader_type"),&ShaderGraph::clear); ClassDB::bind_method(D_METHOD("node_set_state","shader_type","id","state"),&ShaderGraph::node_set_state); - ClassDB::bind_method(D_METHOD("node_get_state:Variant","shader_type","id"),&ShaderGraph::node_get_state); + ClassDB::bind_method(D_METHOD("node_get_state","shader_type","id"),&ShaderGraph::node_get_state); ClassDB::bind_method(D_METHOD("_set_data"),&ShaderGraph::_set_data); ClassDB::bind_method(D_METHOD("_get_data"),&ShaderGraph::_get_data); diff --git a/scene/resources/shader_graph.h b/scene/resources/shader_graph.h index 190d76fce..36578ce1f 100644 --- a/scene/resources/shader_graph.h +++ b/scene/resources/shader_graph.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -36,7 +37,7 @@ class ShaderGraph : public Shader { GDCLASS( ShaderGraph, Shader ); - RES_BASE_EXTENSION("sgp"); + RES_BASE_EXTENSION("vshader"); public: diff --git a/scene/resources/shape.cpp b/scene/resources/shape.cpp index c666ff0cd..6be88374e 100644 --- a/scene/resources/shape.cpp +++ b/scene/resources/shape.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,7 +30,7 @@ #include "shape.h" #include "os/os.h" -#include "scene/main/scene_main_loop.h" +#include "scene/main/scene_tree.h" #include "scene/resources/mesh.h" #include "servers/physics_server.h" @@ -48,14 +49,14 @@ void Shape::add_vertices_to_array(PoolVector<Vector3> &array, const Transform &p } } -Ref<Mesh> Shape::get_debug_mesh() { +Ref<ArrayMesh> Shape::get_debug_mesh() { if (debug_mesh_cache.is_valid()) return debug_mesh_cache; Vector<Vector3> lines = _gen_debug_mesh_lines(); - debug_mesh_cache = Ref<Mesh>(memnew(Mesh)); + debug_mesh_cache = Ref<ArrayMesh>(memnew(ArrayMesh)); if (!lines.empty()) { //make mesh diff --git a/scene/resources/shape.h b/scene/resources/shape.h index 8a8ecf122..c15638aee 100644 --- a/scene/resources/shape.h +++ b/scene/resources/shape.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,16 +31,16 @@ #define SHAPE_H #include "resource.h" -class Mesh; +class ArrayMesh; class Shape : public Resource { GDCLASS(Shape, Resource); OBJ_SAVE_TYPE(Shape); - RES_BASE_EXTENSION("shp"); + RES_BASE_EXTENSION("shape"); RID shape; - Ref<Mesh> debug_mesh_cache; + Ref<ArrayMesh> debug_mesh_cache; protected: _FORCE_INLINE_ RID get_shape() const { return shape; } @@ -49,7 +50,7 @@ protected: public: virtual RID get_rid() const { return shape; } - Ref<Mesh> get_debug_mesh(); + Ref<ArrayMesh> get_debug_mesh(); void add_vertices_to_array(PoolVector<Vector3> &array, const Transform &p_xform); diff --git a/scene/resources/shape_2d.cpp b/scene/resources/shape_2d.cpp index 497110c6f..818c749e8 100644 --- a/scene/resources/shape_2d.cpp +++ b/scene/resources/shape_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -98,10 +99,10 @@ void Shape2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_custom_solver_bias", "bias"), &Shape2D::set_custom_solver_bias); ClassDB::bind_method(D_METHOD("get_custom_solver_bias"), &Shape2D::get_custom_solver_bias); - ClassDB::bind_method(D_METHOD("collide", "local_xform", "with_shape:Shape2D", "shape_xform"), &Shape2D::collide); - ClassDB::bind_method(D_METHOD("collide_with_motion", "local_xform", "local_motion", "with_shape:Shape2D", "shape_xform", "shape_motion"), &Shape2D::collide_with_motion); - ClassDB::bind_method(D_METHOD("collide_and_get_contacts:Variant", "local_xform", "with_shape:Shape2D", "shape_xform"), &Shape2D::collide_and_get_contacts); - ClassDB::bind_method(D_METHOD("collide_with_motion_and_get_contacts:Variant", "local_xform", "local_motion", "with_shape:Shape2D", "shape_xform", "shape_motion"), &Shape2D::collide_with_motion_and_get_contacts); + ClassDB::bind_method(D_METHOD("collide", "local_xform", "with_shape", "shape_xform"), &Shape2D::collide); + ClassDB::bind_method(D_METHOD("collide_with_motion", "local_xform", "local_motion", "with_shape", "shape_xform", "shape_motion"), &Shape2D::collide_with_motion); + ClassDB::bind_method(D_METHOD("collide_and_get_contacts", "local_xform", "with_shape", "shape_xform"), &Shape2D::collide_and_get_contacts); + ClassDB::bind_method(D_METHOD("collide_with_motion_and_get_contacts", "local_xform", "local_motion", "with_shape", "shape_xform", "shape_motion"), &Shape2D::collide_with_motion_and_get_contacts); ADD_PROPERTY(PropertyInfo(Variant::REAL, "custom_solver_bias", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_custom_solver_bias", "get_custom_solver_bias"); } diff --git a/scene/resources/shape_2d.h b/scene/resources/shape_2d.h index afae74c38..c020fb914 100644 --- a/scene/resources/shape_2d.h +++ b/scene/resources/shape_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -46,10 +47,10 @@ public: void set_custom_solver_bias(real_t p_bias); real_t get_custom_solver_bias() const; - bool collide_with_motion(const Transform2D &p_local_xform, const Vector2 &p_local_motion, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform, const Vector2 &p_p_shape_motion); + bool collide_with_motion(const Transform2D &p_local_xform, const Vector2 &p_local_motion, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform, const Vector2 &p_shape_motion); bool collide(const Transform2D &p_local_xform, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform); - Variant collide_with_motion_and_get_contacts(const Transform2D &p_local_xform, const Vector2 &p_local_motion, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform, const Vector2 &p_p_shape_motion); + Variant collide_with_motion_and_get_contacts(const Transform2D &p_local_xform, const Vector2 &p_local_motion, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform, const Vector2 &p_shape_motion); Variant collide_and_get_contacts(const Transform2D &p_local_xform, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform); virtual void draw(const RID &p_to_rid, const Color &p_color) {} diff --git a/scene/resources/shape_line_2d.cpp b/scene/resources/shape_line_2d.cpp index 777dbead5..c38ae04ef 100644 --- a/scene/resources/shape_line_2d.cpp +++ b/scene/resources/shape_line_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -75,7 +76,7 @@ Rect2 LineShape2D::get_rect() const { Vector2 l1[2] = { point - get_normal().tangent() * 100, point + get_normal().tangent() * 100 }; Vector2 l2[2] = { point, point + get_normal() * 30 }; Rect2 rect; - rect.pos = l1[0]; + rect.position = l1[0]; rect.expand_to(l1[1]); rect.expand_to(l2[0]); rect.expand_to(l2[1]); diff --git a/scene/resources/shape_line_2d.h b/scene/resources/shape_line_2d.h index cd62504d8..3e59bbc68 100644 --- a/scene/resources/shape_line_2d.h +++ b/scene/resources/shape_line_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/sky_box.cpp b/scene/resources/sky_box.cpp index cb3b1cf60..575096084 100644 --- a/scene/resources/sky_box.cpp +++ b/scene/resources/sky_box.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,25 +30,28 @@ #include "sky_box.h" #include "io/image_loader.h" -void SkyBox::set_radiance_size(RadianceSize p_size) { +void Sky::set_radiance_size(RadianceSize p_size) { ERR_FAIL_INDEX(p_size, RADIANCE_SIZE_MAX); radiance_size = p_size; _radiance_changed(); } -SkyBox::RadianceSize SkyBox::get_radiance_size() const { +Sky::RadianceSize Sky::get_radiance_size() const { return radiance_size; } -void SkyBox::_bind_methods() { +void Sky::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_radiance_size", "size"), &SkyBox::set_radiance_size); - ClassDB::bind_method(D_METHOD("get_radiance_size"), &SkyBox::get_radiance_size); + ClassDB::bind_method(D_METHOD("set_radiance_size", "size"), &Sky::set_radiance_size); + ClassDB::bind_method(D_METHOD("get_radiance_size"), &Sky::get_radiance_size); - ADD_PROPERTY(PropertyInfo(Variant::INT, "radiance_size", PROPERTY_HINT_ENUM, "256,512,1024,2048"), "set_radiance_size", "get_radiance_size"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "radiance_size", PROPERTY_HINT_ENUM, "32,64,128,256,512,1024,2048"), "set_radiance_size", "get_radiance_size"); + BIND_CONSTANT(RADIANCE_SIZE_32); + BIND_CONSTANT(RADIANCE_SIZE_64); + BIND_CONSTANT(RADIANCE_SIZE_128); BIND_CONSTANT(RADIANCE_SIZE_256); BIND_CONSTANT(RADIANCE_SIZE_512); BIND_CONSTANT(RADIANCE_SIZE_1024); @@ -55,123 +59,456 @@ void SkyBox::_bind_methods() { BIND_CONSTANT(RADIANCE_SIZE_MAX); } -SkyBox::SkyBox() { +Sky::Sky() { radiance_size = RADIANCE_SIZE_512; } ///////////////////////////////////////// -void ImageSkyBox::_radiance_changed() { +void PanoramaSky::_radiance_changed() { - if (cube_map_valid) { + if (panorama.is_valid()) { static const int size[RADIANCE_SIZE_MAX] = { - 256, 512, 1024, 2048 + 32, 64, 128, 256, 512, 1024, 2048 }; - VS::get_singleton()->skybox_set_texture(sky_box, cube_map, size[get_radiance_size()]); + VS::get_singleton()->sky_set_texture(sky, panorama->get_rid(), size[get_radiance_size()]); } } -void ImageSkyBox::set_image_path(ImagePath p_image, const String &p_path) { +void PanoramaSky::set_panorama(const Ref<Texture> &p_panorama) { - ERR_FAIL_INDEX(p_image, IMAGE_PATH_MAX); - image_path[p_image] = p_path; + panorama = p_panorama; - bool all_ok = true; - for (int i = 0; i < IMAGE_PATH_MAX; i++) { - if (image_path[i] == String()) { - all_ok = false; - } + if (panorama.is_valid()) { + + _radiance_changed(); + + } else { + VS::get_singleton()->sky_set_texture(sky, RID(), 0); } +} - cube_map_valid = false; +Ref<Texture> PanoramaSky::get_panorama() const { - if (all_ok) { + return panorama; +} - Image images[IMAGE_PATH_MAX]; - int w = 0, h = 0; - Image::Format format; +RID PanoramaSky::get_rid() const { - for (int i = 0; i < IMAGE_PATH_MAX; i++) { - Error err = ImageLoader::load_image(image_path[i], &images[i]); - if (err) { - ERR_PRINTS("Error loading image for skybox: " + image_path[i]); - return; - } + return sky; +} + +void PanoramaSky::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_panorama", "texture"), &PanoramaSky::set_panorama); + ClassDB::bind_method(D_METHOD("get_panorama"), &PanoramaSky::get_panorama); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "panorama", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_panorama", "get_panorama"); +} + +PanoramaSky::PanoramaSky() { + + sky = VS::get_singleton()->sky_create(); +} + +PanoramaSky::~PanoramaSky() { + + VS::get_singleton()->free(sky); +} +////////////////////////////////// + +void ProceduralSky::_radiance_changed() { + + if (update_queued) + return; //do nothing yet + + static const int size[RADIANCE_SIZE_MAX] = { + 32, 64, 128, 256, 512, 1024, 2048 + }; + VS::get_singleton()->sky_set_texture(sky, texture, size[get_radiance_size()]); +} + +void ProceduralSky::_update_sky() { + + update_queued = false; + + PoolVector<uint8_t> imgdata; + + static const int size[TEXTURE_SIZE_MAX] = { + 256, 512, 1024, 2048, 4096 + }; + + int w = size[texture_size]; + int h = w / 2; + + imgdata.resize(w * h * 4); //RGBE + + { + PoolVector<uint8_t>::Write dataw = imgdata.write(); + + uint32_t *ptr = (uint32_t *)dataw.ptr(); + + Color sky_top_linear = sky_top_color.to_linear(); + Color sky_horizon_linear = sky_horizon_color.to_linear(); + + Color ground_bottom_linear = ground_bottom_color.to_linear(); + Color ground_horizon_linear = ground_horizon_color.to_linear(); + + //Color sun_linear = sun_color.to_linear(); + + Vector3 sun(0, 0, -1); + + sun = Basis(Vector3(1, 0, 0), Math::deg2rad(sun_latitude)).xform(sun); + sun = Basis(Vector3(0, 1, 0), Math::deg2rad(sun_longitude)).xform(sun); + + sun.normalize(); + + for (int i = 0; i < w; i++) { + + float u = float(i) / (w - 1); + float phi = u * 2.0 * Math_PI; + + for (int j = 0; j < h; j++) { + + float v = float(j) / (h - 1); + float theta = v * Math_PI; - if (i == 0) { - w = images[0].get_width(); - h = images[0].get_height(); - format = images[0].get_format(); - } else { - if (images[i].get_width() != w || images[i].get_height() != h || images[i].get_format() != format) { - ERR_PRINTS("Image size mismatch (" + itos(images[i].get_width()) + "," + itos(images[i].get_height()) + ":" + Image::get_format_name(images[i].get_format()) + " when it should be " + itos(w) + "," + itos(h) + ":" + Image::get_format_name(format) + "): " + image_path[i]); - return; + Vector3 normal( + Math::sin(phi) * Math::sin(theta) * -1.0, + Math::cos(theta), + Math::cos(phi) * Math::sin(theta) * -1.0); + + normal.normalize(); + + float v_angle = Math::acos(normal.y); + + Color color; + + if (normal.y < 0) { + //ground + + float c = (v_angle - (Math_PI * 0.5)) / (Math_PI * 0.5); + color = ground_horizon_linear.linear_interpolate(ground_bottom_linear, Math::ease(c, ground_curve)); + } else { + float c = v_angle / (Math_PI * 0.5); + color = sky_horizon_linear.linear_interpolate(sky_top_linear, Math::ease(1.0 - c, sky_curve)); + + float sun_angle = Math::rad2deg(Math::acos(sun.dot(normal))); + + if (sun_angle < sun_angle_min) { + color = color.blend(sun_color); + } else if (sun_angle < sun_angle_max) { + + float c2 = (sun_angle - sun_angle_min) / (sun_angle_max - sun_angle_min); + c2 = Math::ease(c2, sun_curve); + + color = color.blend(sun_color).linear_interpolate(color, c2); + } } + + ptr[j * w + i] = color.to_rgbe9995(); } } + } - VS::get_singleton()->texture_allocate(cube_map, w, h, format, VS::TEXTURE_FLAG_FILTER | VS::TEXTURE_FLAG_CUBEMAP | VS::TEXTURE_FLAG_MIPMAPS); - for (int i = 0; i < IMAGE_PATH_MAX; i++) { - VS::get_singleton()->texture_set_data(cube_map, images[i], VS::CubeMapSide(i)); - } + Ref<Image> image; + image.instance(); + image->create(w, h, false, Image::FORMAT_RGBE9995, imgdata); - cube_map_valid = true; - _radiance_changed(); - } + VS::get_singleton()->texture_allocate(texture, w, h, Image::FORMAT_RGBE9995, VS::TEXTURE_FLAG_FILTER | VS::TEXTURE_FLAG_REPEAT); + VS::get_singleton()->texture_set_data(texture, image); + _radiance_changed(); } -String ImageSkyBox::get_image_path(ImagePath p_image) const { +void ProceduralSky::set_sky_top_color(const Color &p_sky_top) { - ERR_FAIL_INDEX_V(p_image, IMAGE_PATH_MAX, String()); - return image_path[p_image]; + sky_top_color = p_sky_top; + _queue_update(); } -RID ImageSkyBox::get_rid() const { +Color ProceduralSky::get_sky_top_color() const { - return sky_box; + return sky_top_color; } -void ImageSkyBox::_bind_methods() { +void ProceduralSky::set_sky_horizon_color(const Color &p_sky_horizon) { - ClassDB::bind_method(D_METHOD("set_image_path", "image", "path"), &ImageSkyBox::set_image_path); - ClassDB::bind_method(D_METHOD("get_image_path", "image"), &ImageSkyBox::get_image_path); + sky_horizon_color = p_sky_horizon; + _queue_update(); +} +Color ProceduralSky::get_sky_horizon_color() const { - List<String> extensions; - ImageLoader::get_recognized_extensions(&extensions); - String hints; - for (List<String>::Element *E = extensions.front(); E; E = E->next()) { - if (hints != String()) { - hints += ","; - } - hints += "*." + E->get(); - } + return sky_horizon_color; +} + +void ProceduralSky::set_sky_curve(float p_curve) { + + sky_curve = p_curve; + _queue_update(); +} +float ProceduralSky::get_sky_curve() const { + + return sky_curve; +} + +void ProceduralSky::set_sky_energy(float p_energy) { + + sky_energy = p_energy; + _queue_update(); +} +float ProceduralSky::get_sky_energy() const { + + return sky_energy; +} + +void ProceduralSky::set_ground_bottom_color(const Color &p_ground_bottom) { + + ground_bottom_color = p_ground_bottom; + _queue_update(); +} +Color ProceduralSky::get_ground_bottom_color() const { + + return ground_bottom_color; +} + +void ProceduralSky::set_ground_horizon_color(const Color &p_ground_horizon) { + + ground_horizon_color = p_ground_horizon; + _queue_update(); +} +Color ProceduralSky::get_ground_horizon_color() const { + + return ground_horizon_color; +} + +void ProceduralSky::set_ground_curve(float p_curve) { - ADD_GROUP("Image Path", "image_path_"); - ADD_PROPERTYI(PropertyInfo(Variant::STRING, "image_path_negative_x", PROPERTY_HINT_FILE, hints), "set_image_path", "get_image_path", IMAGE_PATH_NEGATIVE_X); - ADD_PROPERTYI(PropertyInfo(Variant::STRING, "image_path_positive_x", PROPERTY_HINT_FILE, hints), "set_image_path", "get_image_path", IMAGE_PATH_POSITIVE_X); - ADD_PROPERTYI(PropertyInfo(Variant::STRING, "image_path_negative_y", PROPERTY_HINT_FILE, hints), "set_image_path", "get_image_path", IMAGE_PATH_NEGATIVE_Y); - ADD_PROPERTYI(PropertyInfo(Variant::STRING, "image_path_positive_y", PROPERTY_HINT_FILE, hints), "set_image_path", "get_image_path", IMAGE_PATH_POSITIVE_Y); - ADD_PROPERTYI(PropertyInfo(Variant::STRING, "image_path_negative_z", PROPERTY_HINT_FILE, hints), "set_image_path", "get_image_path", IMAGE_PATH_NEGATIVE_Z); - ADD_PROPERTYI(PropertyInfo(Variant::STRING, "image_path_positive_z", PROPERTY_HINT_FILE, hints), "set_image_path", "get_image_path", IMAGE_PATH_POSITIVE_Z); + ground_curve = p_curve; + _queue_update(); +} +float ProceduralSky::get_ground_curve() const { + + return ground_curve; +} + +void ProceduralSky::set_ground_energy(float p_energy) { + + ground_energy = p_energy; + _queue_update(); +} +float ProceduralSky::get_ground_energy() const { + + return ground_energy; +} + +void ProceduralSky::set_sun_color(const Color &p_sun) { + + sun_color = p_sun; + _queue_update(); +} +Color ProceduralSky::get_sun_color() const { + + return sun_color; +} + +void ProceduralSky::set_sun_latitude(float p_angle) { + + sun_latitude = p_angle; + _queue_update(); +} +float ProceduralSky::get_sun_latitude() const { + + return sun_latitude; +} + +void ProceduralSky::set_sun_longitude(float p_angle) { + + sun_longitude = p_angle; + _queue_update(); +} +float ProceduralSky::get_sun_longitude() const { + + return sun_longitude; +} + +void ProceduralSky::set_sun_angle_min(float p_angle) { + + sun_angle_min = p_angle; + _queue_update(); +} +float ProceduralSky::get_sun_angle_min() const { + + return sun_angle_min; +} + +void ProceduralSky::set_sun_angle_max(float p_angle) { + + sun_angle_max = p_angle; + _queue_update(); +} +float ProceduralSky::get_sun_angle_max() const { + + return sun_angle_max; +} + +void ProceduralSky::set_sun_curve(float p_curve) { + + sun_curve = p_curve; + _queue_update(); +} +float ProceduralSky::get_sun_curve() const { + + return sun_curve; +} + +void ProceduralSky::set_sun_energy(float p_energy) { + + sun_energy = p_energy; + _queue_update(); +} +float ProceduralSky::get_sun_energy() const { + + return sun_energy; +} + +void ProceduralSky::set_texture_size(TextureSize p_size) { + ERR_FAIL_INDEX(p_size, TEXTURE_SIZE_MAX); + + texture_size = p_size; + _queue_update(); +} +ProceduralSky::TextureSize ProceduralSky::get_texture_size() const { + return texture_size; +} + +RID ProceduralSky::get_rid() const { + return sky; +} + +void ProceduralSky::_queue_update() { + + if (update_queued) + return; + + update_queued = true; + call_deferred("_update_sky"); +} + +void ProceduralSky::_bind_methods() { + + ClassDB::bind_method(D_METHOD("_update_sky"), &ProceduralSky::_update_sky); + + ClassDB::bind_method(D_METHOD("set_sky_top_color", "color"), &ProceduralSky::set_sky_top_color); + ClassDB::bind_method(D_METHOD("get_sky_top_color"), &ProceduralSky::get_sky_top_color); + + ClassDB::bind_method(D_METHOD("set_sky_horizon_color", "color"), &ProceduralSky::set_sky_horizon_color); + ClassDB::bind_method(D_METHOD("get_sky_horizon_color"), &ProceduralSky::get_sky_horizon_color); + + ClassDB::bind_method(D_METHOD("set_sky_curve", "curve"), &ProceduralSky::set_sky_curve); + ClassDB::bind_method(D_METHOD("get_sky_curve"), &ProceduralSky::get_sky_curve); + + ClassDB::bind_method(D_METHOD("set_sky_energy", "energy"), &ProceduralSky::set_sky_energy); + ClassDB::bind_method(D_METHOD("get_sky_energy"), &ProceduralSky::get_sky_energy); + + ClassDB::bind_method(D_METHOD("set_ground_bottom_color", "color"), &ProceduralSky::set_ground_bottom_color); + ClassDB::bind_method(D_METHOD("get_ground_bottom_color"), &ProceduralSky::get_ground_bottom_color); - BIND_CONSTANT(IMAGE_PATH_NEGATIVE_X); - BIND_CONSTANT(IMAGE_PATH_POSITIVE_X); - BIND_CONSTANT(IMAGE_PATH_NEGATIVE_Y); - BIND_CONSTANT(IMAGE_PATH_POSITIVE_Y); - BIND_CONSTANT(IMAGE_PATH_NEGATIVE_Z); - BIND_CONSTANT(IMAGE_PATH_POSITIVE_Z); - BIND_CONSTANT(IMAGE_PATH_MAX); + ClassDB::bind_method(D_METHOD("set_ground_horizon_color", "color"), &ProceduralSky::set_ground_horizon_color); + ClassDB::bind_method(D_METHOD("get_ground_horizon_color"), &ProceduralSky::get_ground_horizon_color); + + ClassDB::bind_method(D_METHOD("set_ground_curve", "curve"), &ProceduralSky::set_ground_curve); + ClassDB::bind_method(D_METHOD("get_ground_curve"), &ProceduralSky::get_ground_curve); + + ClassDB::bind_method(D_METHOD("set_ground_energy", "energy"), &ProceduralSky::set_ground_energy); + ClassDB::bind_method(D_METHOD("get_ground_energy"), &ProceduralSky::get_ground_energy); + + ClassDB::bind_method(D_METHOD("set_sun_color", "color"), &ProceduralSky::set_sun_color); + ClassDB::bind_method(D_METHOD("get_sun_color"), &ProceduralSky::get_sun_color); + + ClassDB::bind_method(D_METHOD("set_sun_latitude", "degrees"), &ProceduralSky::set_sun_latitude); + ClassDB::bind_method(D_METHOD("get_sun_latitude"), &ProceduralSky::get_sun_latitude); + + ClassDB::bind_method(D_METHOD("set_sun_longitude", "degrees"), &ProceduralSky::set_sun_longitude); + ClassDB::bind_method(D_METHOD("get_sun_longitude"), &ProceduralSky::get_sun_longitude); + + ClassDB::bind_method(D_METHOD("set_sun_angle_min", "degrees"), &ProceduralSky::set_sun_angle_min); + ClassDB::bind_method(D_METHOD("get_sun_angle_min"), &ProceduralSky::get_sun_angle_min); + + ClassDB::bind_method(D_METHOD("set_sun_angle_max", "degrees"), &ProceduralSky::set_sun_angle_max); + ClassDB::bind_method(D_METHOD("get_sun_angle_max"), &ProceduralSky::get_sun_angle_max); + + ClassDB::bind_method(D_METHOD("set_sun_curve", "curve"), &ProceduralSky::set_sun_curve); + ClassDB::bind_method(D_METHOD("get_sun_curve"), &ProceduralSky::get_sun_curve); + + ClassDB::bind_method(D_METHOD("set_sun_energy", "energy"), &ProceduralSky::set_sun_energy); + ClassDB::bind_method(D_METHOD("get_sun_energy"), &ProceduralSky::get_sun_energy); + + ClassDB::bind_method(D_METHOD("set_texture_size", "size"), &ProceduralSky::set_texture_size); + ClassDB::bind_method(D_METHOD("get_texture_size"), &ProceduralSky::get_texture_size); + + ADD_GROUP("Sky", "sky_"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_top_color"), "set_sky_top_color", "get_sky_top_color"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_horizon_color"), "set_sky_horizon_color", "get_sky_horizon_color"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "sky_curve", PROPERTY_HINT_EXP_EASING), "set_sky_curve", "get_sky_curve"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "sky_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_sky_energy", "get_sky_energy"); + + ADD_GROUP("Ground", "ground_"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_bottom_color"), "set_ground_bottom_color", "get_ground_bottom_color"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_horizon_color"), "set_ground_horizon_color", "get_ground_horizon_color"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "ground_curve", PROPERTY_HINT_EXP_EASING), "set_ground_curve", "get_ground_curve"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "ground_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_ground_energy", "get_ground_energy"); + + ADD_GROUP("Sun", "sun_"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sun_color"), "set_sun_color", "get_sun_color"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_latitude", PROPERTY_HINT_RANGE, "-180,180,0.01"), "set_sun_latitude", "get_sun_latitude"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_longitude", PROPERTY_HINT_RANGE, "-180,180,0.01"), "set_sun_longitude", "get_sun_longitude"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_angle_min", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_angle_min", "get_sun_angle_min"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_angle_max", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_angle_max", "get_sun_angle_max"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_curve", PROPERTY_HINT_EXP_EASING), "set_sun_curve", "get_sun_curve"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_sun_energy", "get_sun_energy"); + + ADD_GROUP("Texture", "texture_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_size", PROPERTY_HINT_ENUM, "256,512,1024,2048,4096"), "set_texture_size", "get_texture_size"); + + BIND_CONSTANT(TEXTURE_SIZE_256); + BIND_CONSTANT(TEXTURE_SIZE_512); + BIND_CONSTANT(TEXTURE_SIZE_1024); + BIND_CONSTANT(TEXTURE_SIZE_2048); + BIND_CONSTANT(TEXTURE_SIZE_4096); + BIND_CONSTANT(TEXTURE_SIZE_MAX); } -ImageSkyBox::ImageSkyBox() { +ProceduralSky::ProceduralSky() { + + sky = VS::get_singleton()->sky_create(); + texture = VS::get_singleton()->texture_create(); + + update_queued = false; + sky_top_color = Color::hex(0x0c74f9ff); + sky_horizon_color = Color::hex(0x8ed2e8ff); + sky_curve = 0.25; + sky_energy = 1; + + ground_bottom_color = Color::hex(0x1a2530ff); + ground_horizon_color = Color::hex(0x7bc9f3ff); + ground_curve = 0.01; + ground_energy = 1; + + sun_color = Color(1, 1, 1); + sun_latitude = 35; + sun_longitude = 0; + sun_angle_min = 1; + sun_angle_max = 100; + sun_curve = 0.05; + sun_energy = 16; + + texture_size = TEXTURE_SIZE_1024; - cube_map = VS::get_singleton()->texture_create(); - sky_box = VS::get_singleton()->skybox_create(); - cube_map_valid = false; + _queue_update(); } -ImageSkyBox::~ImageSkyBox() { +ProceduralSky::~ProceduralSky() { - VS::get_singleton()->free(cube_map); - VS::get_singleton()->free(sky_box); + VS::get_singleton()->free(sky); + VS::get_singleton()->free(texture); } diff --git a/scene/resources/sky_box.h b/scene/resources/sky_box.h index 23ba077df..8298d1b3c 100644 --- a/scene/resources/sky_box.h +++ b/scene/resources/sky_box.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -26,16 +27,19 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SKYBOX_H -#define SKYBOX_H +#ifndef Sky_H +#define Sky_H #include "scene/resources/texture.h" -class SkyBox : public Resource { - GDCLASS(SkyBox, Resource); +class Sky : public Resource { + GDCLASS(Sky, Resource); public: enum RadianceSize { + RADIANCE_SIZE_32, + RADIANCE_SIZE_64, + RADIANCE_SIZE_128, RADIANCE_SIZE_256, RADIANCE_SIZE_512, RADIANCE_SIZE_1024, @@ -53,46 +57,133 @@ protected: public: void set_radiance_size(RadianceSize p_size); RadianceSize get_radiance_size() const; - SkyBox(); + Sky(); }; -VARIANT_ENUM_CAST(SkyBox::RadianceSize) +VARIANT_ENUM_CAST(Sky::RadianceSize) -class ImageSkyBox : public SkyBox { - GDCLASS(ImageSkyBox, SkyBox); +class PanoramaSky : public Sky { + GDCLASS(PanoramaSky, Sky); + +private: + RID sky; + Ref<Texture> panorama; + +protected: + static void _bind_methods(); + virtual void _radiance_changed(); public: - enum ImagePath { - IMAGE_PATH_NEGATIVE_X, - IMAGE_PATH_POSITIVE_X, - IMAGE_PATH_NEGATIVE_Y, - IMAGE_PATH_POSITIVE_Y, - IMAGE_PATH_NEGATIVE_Z, - IMAGE_PATH_POSITIVE_Z, - IMAGE_PATH_MAX + void set_panorama(const Ref<Texture> &p_panorama); + Ref<Texture> get_panorama() const; + + virtual RID get_rid() const; + + PanoramaSky(); + ~PanoramaSky(); +}; + +class ProceduralSky : public Sky { + GDCLASS(ProceduralSky, Sky); + +public: + enum TextureSize { + TEXTURE_SIZE_256, + TEXTURE_SIZE_512, + TEXTURE_SIZE_1024, + TEXTURE_SIZE_2048, + TEXTURE_SIZE_4096, + TEXTURE_SIZE_MAX }; private: - RID cube_map; - RID sky_box; - bool cube_map_valid; + Color sky_top_color; + Color sky_horizon_color; + float sky_curve; + float sky_energy; + + Color ground_bottom_color; + Color ground_horizon_color; + float ground_curve; + float ground_energy; + + Color sun_color; + float sun_latitude; + float sun_longitude; + float sun_angle_min; + float sun_angle_max; + float sun_curve; + float sun_energy; + + TextureSize texture_size; + + RID sky; + RID texture; - String image_path[IMAGE_PATH_MAX]; + bool update_queued; protected: static void _bind_methods(); virtual void _radiance_changed(); + void _update_sky(); + void _queue_update(); + public: - void set_image_path(ImagePath p_image, const String &p_path); - String get_image_path(ImagePath p_image) const; + void set_sky_top_color(const Color &p_sky_top); + Color get_sky_top_color() const; + + void set_sky_horizon_color(const Color &p_sky_horizon); + Color get_sky_horizon_color() const; + + void set_sky_curve(float p_curve); + float get_sky_curve() const; + + void set_sky_energy(float p_energy); + float get_sky_energy() const; + + void set_ground_bottom_color(const Color &p_ground_bottom); + Color get_ground_bottom_color() const; + + void set_ground_horizon_color(const Color &p_ground_horizon); + Color get_ground_horizon_color() const; + + void set_ground_curve(float p_curve); + float get_ground_curve() const; + + void set_ground_energy(float p_energy); + float get_ground_energy() const; + + void set_sun_color(const Color &p_sun); + Color get_sun_color() const; + + void set_sun_latitude(float p_angle); + float get_sun_latitude() const; + + void set_sun_longitude(float p_angle); + float get_sun_longitude() const; + + void set_sun_angle_min(float p_angle); + float get_sun_angle_min() const; + + void set_sun_angle_max(float p_angle); + float get_sun_angle_max() const; + + void set_sun_curve(float p_curve); + float get_sun_curve() const; + + void set_sun_energy(float p_energy); + float get_sun_energy() const; + + void set_texture_size(TextureSize p_size); + TextureSize get_texture_size() const; virtual RID get_rid() const; - ImageSkyBox(); - ~ImageSkyBox(); + ProceduralSky(); + ~ProceduralSky(); }; -VARIANT_ENUM_CAST(ImageSkyBox::ImagePath) +VARIANT_ENUM_CAST(ProceduralSky::TextureSize) -#endif // SKYBOX_H +#endif // Sky_H diff --git a/scene/resources/space_2d.cpp b/scene/resources/space_2d.cpp index d0a18b98b..2a618bb86 100644 --- a/scene/resources/space_2d.cpp +++ b/scene/resources/space_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/space_2d.h b/scene/resources/space_2d.h index b6c2607b1..3e08612d9 100644 --- a/scene/resources/space_2d.h +++ b/scene/resources/space_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/sphere_shape.cpp b/scene/resources/sphere_shape.cpp index c242e748a..960554562 100644 --- a/scene/resources/sphere_shape.cpp +++ b/scene/resources/sphere_shape.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/sphere_shape.h b/scene/resources/sphere_shape.h index 576c59ee7..a3b5d2424 100644 --- a/scene/resources/sphere_shape.h +++ b/scene/resources/sphere_shape.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/stb_truetype.h b/scene/resources/stb_truetype.h deleted file mode 100644 index 016972785..000000000 --- a/scene/resources/stb_truetype.h +++ /dev/null @@ -1,3267 +0,0 @@ -// stb_truetype.h - v1.11 - public domain -// authored from 2009-2015 by Sean Barrett / RAD Game Tools -// -// This library processes TrueType files: -// parse files -// extract glyph metrics -// extract glyph shapes -// render glyphs to one-channel bitmaps with antialiasing (box filter) -// -// Todo: -// non-MS cmaps -// crashproof on bad data -// hinting? (no longer patented) -// cleartype-style AA? -// optimize: use simple memory allocator for intermediates -// optimize: build edge-list directly from curves -// optimize: rasterize directly from curves? -// -// ADDITIONAL CONTRIBUTORS -// -// Mikko Mononen: compound shape support, more cmap formats -// Tor Andersson: kerning, subpixel rendering -// -// Misc other: -// Ryan Gordon -// Simon Glass -// -// Bug/warning reports/fixes: -// "Zer" on mollyrocket (with fix) -// Cass Everitt -// stoiko (Haemimont Games) -// Brian Hook -// Walter van Niftrik -// David Gow -// David Given -// Ivan-Assen Ivanov -// Anthony Pesch -// Johan Duparc -// Hou Qiming -// Fabian "ryg" Giesen -// Martins Mozeiko -// Cap Petschulat -// Omar Cornut -// github:aloucks -// Peter LaValle -// Sergey Popov -// Giumo X. Clanjor -// Higor Euripedes -// Thomas Fields -// Derek Vinyard -// -// VERSION HISTORY -// -// 1.11 (2016-04-02) fix unused-variable warning -// 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef -// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly -// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges -// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; -// variant PackFontRanges to pack and render in separate phases; -// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); -// fixed an assert() bug in the new rasterizer -// replace assert() with STBTT_assert() in new rasterizer -// 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine) -// also more precise AA rasterizer, except if shapes overlap -// remove need for STBTT_sort -// 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC -// 1.04 (2015-04-15) typo in example -// 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes -// -// Full history can be found at the end of this file. -// -// LICENSE -// -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. -// -// USAGE -// -// Include this file in whatever places neeed to refer to it. In ONE C/C++ -// file, write: -// #define STB_TRUETYPE_IMPLEMENTATION -// before the #include of this file. This expands out the actual -// implementation into that C/C++ file. -// -// To make the implementation private to the file that generates the implementation, -// #define STBTT_STATIC -// -// Simple 3D API (don't ship this, but it's fine for tools and quick start) -// stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture -// stbtt_GetBakedQuad() -- compute quad to draw for a given char -// -// Improved 3D API (more shippable): -// #include "stb_rect_pack.h" -- optional, but you really want it -// stbtt_PackBegin() -// stbtt_PackSetOversample() -- for improved quality on small fonts -// stbtt_PackFontRanges() -- pack and renders -// stbtt_PackEnd() -// stbtt_GetPackedQuad() -// -// "Load" a font file from a memory buffer (you have to keep the buffer loaded) -// stbtt_InitFont() -// stbtt_GetFontOffsetForIndex() -- use for TTC font collections -// -// Render a unicode codepoint to a bitmap -// stbtt_GetCodepointBitmap() -- allocates and returns a bitmap -// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide -// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be -// -// Character advance/positioning -// stbtt_GetCodepointHMetrics() -// stbtt_GetFontVMetrics() -// stbtt_GetCodepointKernAdvance() -// -// Starting with version 1.06, the rasterizer was replaced with a new, -// faster and generally-more-precise rasterizer. The new rasterizer more -// accurately measures pixel coverage for anti-aliasing, except in the case -// where multiple shapes overlap, in which case it overestimates the AA pixel -// coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If -// this turns out to be a problem, you can re-enable the old rasterizer with -// #define STBTT_RASTERIZER_VERSION 1 -// which will incur about a 15% speed hit. -// -// ADDITIONAL DOCUMENTATION -// -// Immediately after this block comment are a series of sample programs. -// -// After the sample programs is the "header file" section. This section -// includes documentation for each API function. -// -// Some important concepts to understand to use this library: -// -// Codepoint -// Characters are defined by unicode codepoints, e.g. 65 is -// uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is -// the hiragana for "ma". -// -// Glyph -// A visual character shape (every codepoint is rendered as -// some glyph) -// -// Glyph index -// A font-specific integer ID representing a glyph -// -// Baseline -// Glyph shapes are defined relative to a baseline, which is the -// bottom of uppercase characters. Characters extend both above -// and below the baseline. -// -// Current Point -// As you draw text to the screen, you keep track of a "current point" -// which is the origin of each character. The current point's vertical -// position is the baseline. Even "baked fonts" use this model. -// -// Vertical Font Metrics -// The vertical qualities of the font, used to vertically position -// and space the characters. See docs for stbtt_GetFontVMetrics. -// -// Font Size in Pixels or Points -// The preferred interface for specifying font sizes in stb_truetype -// is to specify how tall the font's vertical extent should be in pixels. -// If that sounds good enough, skip the next paragraph. -// -// Most font APIs instead use "points", which are a common typographic -// measurement for describing font size, defined as 72 points per inch. -// stb_truetype provides a point API for compatibility. However, true -// "per inch" conventions don't make much sense on computer displays -// since they different monitors have different number of pixels per -// inch. For example, Windows traditionally uses a convention that -// there are 96 pixels per inch, thus making 'inch' measurements have -// nothing to do with inches, and thus effectively defining a point to -// be 1.333 pixels. Additionally, the TrueType font data provides -// an explicit scale factor to scale a given font's glyphs to points, -// but the author has observed that this scale factor is often wrong -// for non-commercial fonts, thus making fonts scaled in points -// according to the TrueType spec incoherently sized in practice. -// -// ADVANCED USAGE -// -// Quality: -// -// - Use the functions with Subpixel at the end to allow your characters -// to have subpixel positioning. Since the font is anti-aliased, not -// hinted, this is very import for quality. (This is not possible with -// baked fonts.) -// -// - Kerning is now supported, and if you're supporting subpixel rendering -// then kerning is worth using to give your text a polished look. -// -// Performance: -// -// - Convert Unicode codepoints to glyph indexes and operate on the glyphs; -// if you don't do this, stb_truetype is forced to do the conversion on -// every call. -// -// - There are a lot of memory allocations. We should modify it to take -// a temp buffer and allocate from the temp buffer (without freeing), -// should help performance a lot. -// -// NOTES -// -// The system uses the raw data found in the .ttf file without changing it -// and without building auxiliary data structures. This is a bit inefficient -// on little-endian systems (the data is big-endian), but assuming you're -// caching the bitmaps or glyph shapes this shouldn't be a big deal. -// -// It appears to be very hard to programmatically determine what font a -// given file is in a general way. I provide an API for this, but I don't -// recommend it. -// -// -// SOURCE STATISTICS (based on v0.6c, 2050 LOC) -// -// Documentation & header file 520 LOC \___ 660 LOC documentation -// Sample code 140 LOC / -// Truetype parsing 620 LOC ---- 620 LOC TrueType -// Software rasterization 240 LOC \ . -// Curve tesselation 120 LOC \__ 550 LOC Bitmap creation -// Bitmap management 100 LOC / -// Baked bitmap interface 70 LOC / -// Font name matching & access 150 LOC ---- 150 -// C runtime library abstraction 60 LOC ---- 60 -// -// -// PERFORMANCE MEASUREMENTS FOR 1.06: -// -// 32-bit 64-bit -// Previous release: 8.83 s 7.68 s -// Pool allocations: 7.72 s 6.34 s -// Inline sort : 6.54 s 5.65 s -// New rasterizer : 5.63 s 5.00 s - -////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// -//// -//// SAMPLE PROGRAMS -//// -// -// Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless -// -#if 0 -#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation -#include "stb_truetype.h" - -unsigned char ttf_buffer[1<<20]; -unsigned char temp_bitmap[512*512]; - -stbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs -GLuint ftex; - -void my_stbtt_initfont(void) -{ - fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb")); - stbtt_BakeFontBitmap(ttf_buffer,0, 32.0, temp_bitmap,512,512, 32,96, cdata); // no guarantee this fits! - // can free ttf_buffer at this point - glGenTextures(1, &ftex); - glBindTexture(GL_TEXTURE_2D, ftex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512,512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap); - // can free temp_bitmap at this point - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); -} - -void my_stbtt_print(float x, float y, char *text) -{ - // assume orthographic projection with units = screen pixels, origin at top left - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, ftex); - glBegin(GL_QUADS); - while (*text) { - if (*text >= 32 && *text < 128) { - stbtt_aligned_quad q; - stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9 - glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0); - glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0); - glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1); - glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1); - } - ++text; - } - glEnd(); -} -#endif -// -// -////////////////////////////////////////////////////////////////////////////// -// -// Complete program (this compiles): get a single bitmap, print as ASCII art -// -#if 0 -#include <stdio.h> -#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation -#include "stb_truetype.h" - -char ttf_buffer[1<<25]; - -int main(int argc, char **argv) -{ - stbtt_fontinfo font; - unsigned char *bitmap; - int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20); - - fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb")); - - stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0)); - bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0); - - for (j=0; j < h; ++j) { - for (i=0; i < w; ++i) - putchar(" .:ioVM@"[bitmap[j*w+i]>>5]); - putchar('\n'); - } - return 0; -} -#endif -// -// Output: -// -// .ii. -// @@@@@@. -// V@Mio@@o -// :i. V@V -// :oM@@M -// :@@@MM@M -// @@o o@M -// :@@. M@M -// @@@o@@@@ -// :M@@V:@@. -// -////////////////////////////////////////////////////////////////////////////// -// -// Complete program: print "Hello World!" banner, with bugs -// -#if 0 -char buffer[24<<20]; -unsigned char screen[20][79]; - -int main(int arg, char **argv) -{ - stbtt_fontinfo font; - int i,j,ascent,baseline,ch=0; - float scale, xpos=2; // leave a little padding in case the character extends left - char *text = "Heljo World!"; // intentionally misspelled to show 'lj' brokenness - - fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb")); - stbtt_InitFont(&font, buffer, 0); - - scale = stbtt_ScaleForPixelHeight(&font, 15); - stbtt_GetFontVMetrics(&font, &ascent,0,0); - baseline = (int) (ascent*scale); - - while (text[ch]) { - int advance,lsb,x0,y0,x1,y1; - float x_shift = xpos - (float) floor(xpos); - stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb); - stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1); - stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]); - // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong - // because this API is really for baking character bitmaps into textures. if you want to render - // a sequence of characters, you really need to render each bitmap to a temp buffer, then - // "alpha blend" that into the working buffer - xpos += (advance * scale); - if (text[ch+1]) - xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]); - ++ch; - } - - for (j=0; j < 20; ++j) { - for (i=0; i < 78; ++i) - putchar(" .:ioVM@"[screen[j][i]>>5]); - putchar('\n'); - } - - return 0; -} -#endif - - -////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// -//// -//// INTEGRATION WITH YOUR CODEBASE -//// -//// The following sections allow you to supply alternate definitions -//// of C library functions used by stb_truetype. - -#ifdef STB_TRUETYPE_IMPLEMENTATION - // #define your own (u)stbtt_int8/16/32 before including to override this - #ifndef stbtt_uint8 - typedef unsigned char stbtt_uint8; - typedef signed char stbtt_int8; - typedef unsigned short stbtt_uint16; - typedef signed short stbtt_int16; - typedef unsigned int stbtt_uint32; - typedef signed int stbtt_int32; - #endif - - typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; - typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; - - // #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h - #ifndef STBTT_ifloor - #include <math.h> - #define STBTT_ifloor(x) ((int) floor(x)) - #define STBTT_iceil(x) ((int) ceil(x)) - #endif - - #ifndef STBTT_sqrt - #include <math.h> - #define STBTT_sqrt(x) sqrt(x) - #endif - - #ifndef STBTT_fabs - #include <math.h> - #define STBTT_fabs(x) fabs(x) - #endif - - // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h - #ifndef STBTT_malloc - #include <stdlib.h> - #define STBTT_malloc(x,u) ((void)(u),malloc(x)) - #define STBTT_free(x,u) ((void)(u),free(x)) - #endif - - #ifndef STBTT_assert - #include <assert.h> - #define STBTT_assert(x) assert(x) - #endif - - #ifndef STBTT_strlen - #include <string.h> - #define STBTT_strlen(x) strlen(x) - #endif - - #ifndef STBTT_memcpy - #include <memory.h> - #define STBTT_memcpy memcpy - #define STBTT_memset memset - #endif -#endif - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -//// -//// INTERFACE -//// -//// - -#ifndef __STB_INCLUDE_STB_TRUETYPE_H__ -#define __STB_INCLUDE_STB_TRUETYPE_H__ - -#ifdef STBTT_STATIC -#define STBTT_DEF static -#else -#define STBTT_DEF extern -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -////////////////////////////////////////////////////////////////////////////// -// -// TEXTURE BAKING API -// -// If you use this API, you only have to call two functions ever. -// - -typedef struct -{ - unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap - float xoff,yoff,xadvance; -} stbtt_bakedchar; - -STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) - float pixel_height, // height of font in pixels - unsigned char *pixels, int pw, int ph, // bitmap to be filled in - int first_char, int num_chars, // characters to bake - stbtt_bakedchar *chardata); // you allocate this, it's num_chars long -// if return is positive, the first unused row of the bitmap -// if return is negative, returns the negative of the number of characters that fit -// if return is 0, no characters fit and no rows were used -// This uses a very crappy packing. - -typedef struct -{ - float x0,y0,s0,t0; // top-left - float x1,y1,s1,t1; // bottom-right -} stbtt_aligned_quad; - -STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, // same data as above - int char_index, // character to display - float *xpos, float *ypos, // pointers to current position in screen pixel space - stbtt_aligned_quad *q, // output: quad to draw - int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier -// Call GetBakedQuad with char_index = 'character - first_char', and it -// creates the quad you need to draw and advances the current position. -// -// The coordinate system used assumes y increases downwards. -// -// Characters will extend both above and below the current position; -// see discussion of "BASELINE" above. -// -// It's inefficient; you might want to c&p it and optimize it. - - - -////////////////////////////////////////////////////////////////////////////// -// -// NEW TEXTURE BAKING API -// -// This provides options for packing multiple fonts into one atlas, not -// perfectly but better than nothing. - -typedef struct -{ - unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap - float xoff,yoff,xadvance; - float xoff2,yoff2; -} stbtt_packedchar; - -typedef struct stbtt_pack_context stbtt_pack_context; -typedef struct stbtt_fontinfo stbtt_fontinfo; -#ifndef STB_RECT_PACK_VERSION -typedef struct stbrp_rect stbrp_rect; -#endif - -STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context); -// Initializes a packing context stored in the passed-in stbtt_pack_context. -// Future calls using this context will pack characters into the bitmap passed -// in here: a 1-channel bitmap that is weight x height. stride_in_bytes is -// the distance from one row to the next (or 0 to mean they are packed tightly -// together). "padding" is the amount of padding to leave between each -// character (normally you want '1' for bitmaps you'll use as textures with -// bilinear filtering). -// -// Returns 0 on failure, 1 on success. - -STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc); -// Cleans up the packing context and frees all memory. - -#define STBTT_POINT_SIZE(x) (-(x)) - -STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size, - int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); -// Creates character bitmaps from the font_index'th font found in fontdata (use -// font_index=0 if you don't know what that is). It creates num_chars_in_range -// bitmaps for characters with unicode values starting at first_unicode_char_in_range -// and increasing. Data for how to render them is stored in chardata_for_range; -// pass these to stbtt_GetPackedQuad to get back renderable quads. -// -// font_size is the full height of the character from ascender to descender, -// as computed by stbtt_ScaleForPixelHeight. To use a point size as computed -// by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE() -// and pass that result as 'font_size': -// ..., 20 , ... // font max minus min y is 20 pixels tall -// ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall - -typedef struct -{ - float font_size; - int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint - int *array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints - int num_chars; - stbtt_packedchar *chardata_for_range; // output - unsigned char h_oversample, v_oversample; // don't set these, they're used internally -} stbtt_pack_range; - -STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); -// Creates character bitmaps from multiple ranges of characters stored in -// ranges. This will usually create a better-packed bitmap than multiple -// calls to stbtt_PackFontRange. Note that you can call this multiple -// times within a single PackBegin/PackEnd. - -STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample); -// Oversampling a font increases the quality by allowing higher-quality subpixel -// positioning, and is especially valuable at smaller text sizes. -// -// This function sets the amount of oversampling for all following calls to -// stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given -// pack context. The default (no oversampling) is achieved by h_oversample=1 -// and v_oversample=1. The total number of pixels required is -// h_oversample*v_oversample larger than the default; for example, 2x2 -// oversampling requires 4x the storage of 1x1. For best results, render -// oversampled textures with bilinear filtering. Look at the readme in -// stb/tests/oversample for information about oversampled fonts -// -// To use with PackFontRangesGather etc., you must set it before calls -// call to PackFontRangesGatherRects. - -STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, // same data as above - int char_index, // character to display - float *xpos, float *ypos, // pointers to current position in screen pixel space - stbtt_aligned_quad *q, // output: quad to draw - int align_to_integer); - -STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); -STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects); -STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); -// Calling these functions in sequence is roughly equivalent to calling -// stbtt_PackFontRanges(). If you more control over the packing of multiple -// fonts, or if you want to pack custom data into a font texture, take a look -// at the source to of stbtt_PackFontRanges() and create a custom version -// using these functions, e.g. call GatherRects multiple times, -// building up a single array of rects, then call PackRects once, -// then call RenderIntoRects repeatedly. This may result in a -// better packing than calling PackFontRanges multiple times -// (or it may not). - -// this is an opaque structure that you shouldn't mess with which holds -// all the context needed from PackBegin to PackEnd. -struct stbtt_pack_context { - void *user_allocator_context; - void *pack_info; - int width; - int height; - int stride_in_bytes; - int padding; - unsigned int h_oversample, v_oversample; - unsigned char *pixels; - void *nodes; -}; - -////////////////////////////////////////////////////////////////////////////// -// -// FONT LOADING -// -// - -STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); -// Each .ttf/.ttc file may have more than one font. Each font has a sequential -// index number starting from 0. Call this function to get the font offset for -// a given index; it returns -1 if the index is out of range. A regular .ttf -// file will only define one font and it always be at offset 0, so it will -// return '0' for index 0, and -1 for all other indices. You can just skip -// this step if you know it's that kind of font. - - -// The following structure is defined publically so you can declare one on -// the stack or as a global or etc, but you should treat it as opaque. -struct stbtt_fontinfo -{ - void * userdata; - unsigned char * data; // pointer to .ttf file - int fontstart; // offset of start of font - - int numGlyphs; // number of glyphs, needed for range checking - - int loca,head,glyf,hhea,hmtx,kern; // table locations as offset from start of .ttf - int index_map; // a cmap mapping for our chosen character encoding - int indexToLocFormat; // format needed to map from glyph index to glyph -}; - -STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); -// Given an offset into the file that defines a font, this function builds -// the necessary cached info for the rest of the system. You must allocate -// the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't -// need to do anything special to free it, because the contents are pure -// value data with no additional data structures. Returns 0 on failure. - - -////////////////////////////////////////////////////////////////////////////// -// -// CHARACTER TO GLYPH-INDEX CONVERSIOn - -STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint); -// If you're going to perform multiple operations on the same character -// and you want a speed-up, call this function with the character you're -// going to process, then use glyph-based functions instead of the -// codepoint-based functions. - - -////////////////////////////////////////////////////////////////////////////// -// -// CHARACTER PROPERTIES -// - -STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels); -// computes a scale factor to produce a font whose "height" is 'pixels' tall. -// Height is measured as the distance from the highest ascender to the lowest -// descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics -// and computing: -// scale = pixels / (ascent - descent) -// so if you prefer to measure height by the ascent only, use a similar calculation. - -STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels); -// computes a scale factor to produce a font whose EM size is mapped to -// 'pixels' tall. This is probably what traditional APIs compute, but -// I'm not positive. - -STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap); -// ascent is the coordinate above the baseline the font extends; descent -// is the coordinate below the baseline the font extends (i.e. it is typically negative) -// lineGap is the spacing between one row's descent and the next row's ascent... -// so you should advance the vertical position by "*ascent - *descent + *lineGap" -// these are expressed in unscaled coordinates, so you must multiply by -// the scale factor for a given size - -STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); -// the bounding box around all possible characters - -STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing); -// leftSideBearing is the offset from the current horizontal position to the left edge of the character -// advanceWidth is the offset from the current horizontal position to the next horizontal position -// these are expressed in unscaled coordinates - -STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2); -// an additional amount to add to the 'advance' value between ch1 and ch2 - -STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1); -// Gets the bounding box of the visible part of the glyph, in unscaled coordinates - -STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing); -STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2); -STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); -// as above, but takes one or more glyph indices for greater efficiency - - -////////////////////////////////////////////////////////////////////////////// -// -// GLYPH SHAPES (you probably don't need these, but they have to go before -// the bitmaps for C declaration-order reasons) -// - -#ifndef STBTT_vmove // you can predefine these to use different values (but why?) - enum { - STBTT_vmove=1, - STBTT_vline, - STBTT_vcurve - }; -#endif - -#ifndef stbtt_vertex // you can predefine this to use different values - // (we share this with other code at RAD) - #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file - typedef struct - { - stbtt_vertex_type x,y,cx,cy; - unsigned char type,padding; - } stbtt_vertex; -#endif - -STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index); -// returns non-zero if nothing is drawn for this glyph - -STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices); -STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices); -// returns # of vertices and fills *vertices with the pointer to them -// these are expressed in "unscaled" coordinates -// -// The shape is a series of countours. Each one starts with -// a STBTT_moveto, then consists of a series of mixed -// STBTT_lineto and STBTT_curveto segments. A lineto -// draws a line from previous endpoint to its x,y; a curveto -// draws a quadratic bezier from previous endpoint to -// its x,y, using cx,cy as the bezier control point. - -STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); -// frees the data allocated above - -////////////////////////////////////////////////////////////////////////////// -// -// BITMAP RENDERING -// - -STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata); -// frees the bitmap allocated below - -STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff); -// allocates a large-enough single-channel 8bpp bitmap and renders the -// specified character/glyph at the specified scale into it, with -// antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque). -// *width & *height are filled out with the width & height of the bitmap, -// which is stored left-to-right, top-to-bottom. -// -// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap - -STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff); -// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel -// shift for the character - -STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint); -// the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap -// in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap -// is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the -// width and height and positioning info for it first. - -STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint); -// same as stbtt_MakeCodepointBitmap, but you can specify a subpixel -// shift for the character - -STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); -// get the bbox of the bitmap centered around the glyph origin; so the -// bitmap width is ix1-ix0, height is iy1-iy0, and location to place -// the bitmap top left is (leftSideBearing*scale,iy0). -// (Note that the bitmap uses y-increases-down, but the shape uses -// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.) - -STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); -// same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel -// shift for the character - -// the following functions are equivalent to the above functions, but operate -// on glyph indices instead of Unicode codepoints (for efficiency) -STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff); -STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff); -STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph); -STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph); -STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); -STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); - - -// @TODO: don't expose this structure -typedef struct -{ - int w,h,stride; - unsigned char *pixels; -} stbtt__bitmap; - -// rasterize a shape with quadratic beziers into a bitmap -STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into - float flatness_in_pixels, // allowable error of curve in pixels - stbtt_vertex *vertices, // array of vertices defining shape - int num_verts, // number of vertices in above array - float scale_x, float scale_y, // scale applied to input vertices - float shift_x, float shift_y, // translation applied to input vertices - int x_off, int y_off, // another translation applied to input - int invert, // if non-zero, vertically flip shape - void *userdata); // context for to STBTT_MALLOC - -////////////////////////////////////////////////////////////////////////////// -// -// Finding the right font... -// -// You should really just solve this offline, keep your own tables -// of what font is what, and don't try to get it out of the .ttf file. -// That's because getting it out of the .ttf file is really hard, because -// the names in the file can appear in many possible encodings, in many -// possible languages, and e.g. if you need a case-insensitive comparison, -// the details of that depend on the encoding & language in a complex way -// (actually underspecified in truetype, but also gigantic). -// -// But you can use the provided functions in two possible ways: -// stbtt_FindMatchingFont() will use *case-sensitive* comparisons on -// unicode-encoded names to try to find the font you want; -// you can run this before calling stbtt_InitFont() -// -// stbtt_GetFontNameString() lets you get any of the various strings -// from the file yourself and do your own comparisons on them. -// You have to have called stbtt_InitFont() first. - - -STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags); -// returns the offset (not index) of the font that matches, or -1 if none -// if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold". -// if you use any other flag, use a font name like "Arial"; this checks -// the 'macStyle' header field; i don't know if fonts set this consistently -#define STBTT_MACSTYLE_DONTCARE 0 -#define STBTT_MACSTYLE_BOLD 1 -#define STBTT_MACSTYLE_ITALIC 2 -#define STBTT_MACSTYLE_UNDERSCORE 4 -#define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0 - -STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2); -// returns 1/0 whether the first string interpreted as utf8 is identical to -// the second string interpreted as big-endian utf16... useful for strings from next func - -STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID); -// returns the string (which may be big-endian double byte, e.g. for unicode) -// and puts the length in bytes in *length. -// -// some of the values for the IDs are below; for more see the truetype spec: -// http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html -// http://www.microsoft.com/typography/otspec/name.htm - -enum { // platformID - STBTT_PLATFORM_ID_UNICODE =0, - STBTT_PLATFORM_ID_MAC =1, - STBTT_PLATFORM_ID_ISO =2, - STBTT_PLATFORM_ID_MICROSOFT =3 -}; - -enum { // encodingID for STBTT_PLATFORM_ID_UNICODE - STBTT_UNICODE_EID_UNICODE_1_0 =0, - STBTT_UNICODE_EID_UNICODE_1_1 =1, - STBTT_UNICODE_EID_ISO_10646 =2, - STBTT_UNICODE_EID_UNICODE_2_0_BMP=3, - STBTT_UNICODE_EID_UNICODE_2_0_FULL=4 -}; - -enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT - STBTT_MS_EID_SYMBOL =0, - STBTT_MS_EID_UNICODE_BMP =1, - STBTT_MS_EID_SHIFTJIS =2, - STBTT_MS_EID_UNICODE_FULL =10 -}; - -enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes - STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4, - STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5, - STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6, - STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7 -}; - -enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID... - // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs - STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410, - STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411, - STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412, - STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419, - STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409, - STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D -}; - -enum { // languageID for STBTT_PLATFORM_ID_MAC - STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11, - STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23, - STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32, - STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 , - STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 , - STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33, - STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19 -}; - -#ifdef __cplusplus -} -#endif - -#endif // __STB_INCLUDE_STB_TRUETYPE_H__ - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -//// -//// IMPLEMENTATION -//// -//// - -#ifdef STB_TRUETYPE_IMPLEMENTATION - -#ifndef STBTT_MAX_OVERSAMPLE -#define STBTT_MAX_OVERSAMPLE 8 -#endif - -#if STBTT_MAX_OVERSAMPLE > 255 -#error "STBTT_MAX_OVERSAMPLE cannot be > 255" -#endif - -typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1]; - -#ifndef STBTT_RASTERIZER_VERSION -#define STBTT_RASTERIZER_VERSION 2 -#endif - -#ifdef _MSC_VER -#define STBTT__NOTUSED(v) (void)(v) -#else -#define STBTT__NOTUSED(v) (void)sizeof(v) -#endif - -////////////////////////////////////////////////////////////////////////// -// -// accessors to parse data from file -// - -// on platforms that don't allow misaligned reads, if we want to allow -// truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE - -#define ttBYTE(p) (* (stbtt_uint8 *) (p)) -#define ttCHAR(p) (* (stbtt_int8 *) (p)) -#define ttFixed(p) ttLONG(p) - -#if defined(STB_TRUETYPE_BIGENDIAN) && !defined(ALLOW_UNALIGNED_TRUETYPE) - - #define ttUSHORT(p) (* (stbtt_uint16 *) (p)) - #define ttSHORT(p) (* (stbtt_int16 *) (p)) - #define ttULONG(p) (* (stbtt_uint32 *) (p)) - #define ttLONG(p) (* (stbtt_int32 *) (p)) - -#else - - static stbtt_uint16 ttUSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; } - static stbtt_int16 ttSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; } - static stbtt_uint32 ttULONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } - static stbtt_int32 ttLONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } - -#endif - -#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) -#define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3]) - -static int stbtt__isfont(const stbtt_uint8 *font) -{ - // check the version number - if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1 - if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this! - if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF - if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0 - return 0; -} - -// @OPTIMIZE: binary search -static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag) -{ - stbtt_int32 num_tables = ttUSHORT(data+fontstart+4); - stbtt_uint32 tabledir = fontstart + 12; - stbtt_int32 i; - for (i=0; i < num_tables; ++i) { - stbtt_uint32 loc = tabledir + 16*i; - if (stbtt_tag(data+loc+0, tag)) - return ttULONG(data+loc+8); - } - return 0; -} - -STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *font_collection, int index) -{ - // if it's just a font, there's only one valid index - if (stbtt__isfont(font_collection)) - return index == 0 ? 0 : -1; - - // check if it's a TTC - if (stbtt_tag(font_collection, "ttcf")) { - // version 1? - if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { - stbtt_int32 n = ttLONG(font_collection+8); - if (index >= n) - return -1; - return ttULONG(font_collection+12+index*4); - } - } - return -1; -} - -STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, int fontstart) -{ - stbtt_uint8 *data = (stbtt_uint8 *) data2; - stbtt_uint32 cmap, t; - stbtt_int32 i,numTables; - - info->data = data; - info->fontstart = fontstart; - - cmap = stbtt__find_table(data, fontstart, "cmap"); // required - info->loca = stbtt__find_table(data, fontstart, "loca"); // required - info->head = stbtt__find_table(data, fontstart, "head"); // required - info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required - info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required - info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required - info->kern = stbtt__find_table(data, fontstart, "kern"); // not required - if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx) - return 0; - - t = stbtt__find_table(data, fontstart, "maxp"); - if (t) - info->numGlyphs = ttUSHORT(data+t+4); - else - info->numGlyphs = 0xffff; - - // find a cmap encoding table we understand *now* to avoid searching - // later. (todo: could make this installable) - // the same regardless of glyph. - numTables = ttUSHORT(data + cmap + 2); - info->index_map = 0; - for (i=0; i < numTables; ++i) { - stbtt_uint32 encoding_record = cmap + 4 + 8 * i; - // find an encoding we understand: - switch(ttUSHORT(data+encoding_record)) { - case STBTT_PLATFORM_ID_MICROSOFT: - switch (ttUSHORT(data+encoding_record+2)) { - case STBTT_MS_EID_UNICODE_BMP: - case STBTT_MS_EID_UNICODE_FULL: - // MS/Unicode - info->index_map = cmap + ttULONG(data+encoding_record+4); - break; - } - break; - case STBTT_PLATFORM_ID_UNICODE: - // Mac/iOS has these - // all the encodingIDs are unicode, so we don't bother to check it - info->index_map = cmap + ttULONG(data+encoding_record+4); - break; - } - } - if (info->index_map == 0) - return 0; - - info->indexToLocFormat = ttUSHORT(data+info->head + 50); - return 1; -} - -STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint) -{ - stbtt_uint8 *data = info->data; - stbtt_uint32 index_map = info->index_map; - - stbtt_uint16 format = ttUSHORT(data + index_map + 0); - if (format == 0) { // apple byte encoding - stbtt_int32 bytes = ttUSHORT(data + index_map + 2); - if (unicode_codepoint < bytes-6) - return ttBYTE(data + index_map + 6 + unicode_codepoint); - return 0; - } else if (format == 6) { - stbtt_uint32 first = ttUSHORT(data + index_map + 6); - stbtt_uint32 count = ttUSHORT(data + index_map + 8); - if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count) - return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2); - return 0; - } else if (format == 2) { - STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean - return 0; - } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges - stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1; - stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1; - stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10); - stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1; - - // do a binary search of the segments - stbtt_uint32 endCount = index_map + 14; - stbtt_uint32 search = endCount; - - if (unicode_codepoint > 0xffff) - return 0; - - // they lie from endCount .. endCount + segCount - // but searchRange is the nearest power of two, so... - if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2)) - search += rangeShift*2; - - // now decrement to bias correctly to find smallest - search -= 2; - while (entrySelector) { - stbtt_uint16 end; - searchRange >>= 1; - end = ttUSHORT(data + search + searchRange*2); - if (unicode_codepoint > end) - search += searchRange*2; - --entrySelector; - } - search += 2; - - { - stbtt_uint16 offset, start; - stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1); - - STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item)); - start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); - if (unicode_codepoint < start) - return 0; - - offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); - if (offset == 0) - return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item)); - - return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); - } - } else if (format == 12 || format == 13) { - stbtt_uint32 ngroups = ttULONG(data+index_map+12); - stbtt_int32 low,high; - low = 0; high = (stbtt_int32)ngroups; - // Binary search the right group. - while (low < high) { - stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high - stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12); - stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4); - if ((stbtt_uint32) unicode_codepoint < start_char) - high = mid; - else if ((stbtt_uint32) unicode_codepoint > end_char) - low = mid+1; - else { - stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8); - if (format == 12) - return start_glyph + unicode_codepoint-start_char; - else // format == 13 - return start_glyph; - } - } - return 0; // not found - } - // @TODO - STBTT_assert(0); - return 0; -} - -STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices) -{ - return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices); -} - -static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy) -{ - v->type = type; - v->x = (stbtt_int16) x; - v->y = (stbtt_int16) y; - v->cx = (stbtt_int16) cx; - v->cy = (stbtt_int16) cy; -} - -static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) -{ - int g1,g2; - - if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range - if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format - - if (info->indexToLocFormat == 0) { - g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2; - g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2; - } else { - g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4); - g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4); - } - - return g1==g2 ? -1 : g1; // if length is 0, return -1 -} - -STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) -{ - int g = stbtt__GetGlyfOffset(info, glyph_index); - if (g < 0) return 0; - - if (x0) *x0 = ttSHORT(info->data + g + 2); - if (y0) *y0 = ttSHORT(info->data + g + 4); - if (x1) *x1 = ttSHORT(info->data + g + 6); - if (y1) *y1 = ttSHORT(info->data + g + 8); - return 1; -} - -STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1) -{ - return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1); -} - -STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index) -{ - stbtt_int16 numberOfContours; - int g = stbtt__GetGlyfOffset(info, glyph_index); - if (g < 0) return 1; - numberOfContours = ttSHORT(info->data + g); - return numberOfContours == 0; -} - -static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off, - stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy) -{ - if (start_off) { - if (was_off) - stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy); - stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy); - } else { - if (was_off) - stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy); - else - stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0); - } - return num_vertices; -} - -STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) -{ - stbtt_int16 numberOfContours; - stbtt_uint8 *endPtsOfContours; - stbtt_uint8 *data = info->data; - stbtt_vertex *vertices=0; - int num_vertices=0; - int g = stbtt__GetGlyfOffset(info, glyph_index); - - *pvertices = NULL; - - if (g < 0) return 0; - - numberOfContours = ttSHORT(data + g); - - if (numberOfContours > 0) { - stbtt_uint8 flags=0,flagcount; - stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0; - stbtt_int32 x,y,cx,cy,sx,sy, scx,scy; - stbtt_uint8 *points; - endPtsOfContours = (data + g + 10); - ins = ttUSHORT(data + g + 10 + numberOfContours * 2); - points = data + g + 10 + numberOfContours * 2 + 2 + ins; - - n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2); - - m = n + 2*numberOfContours; // a loose bound on how many vertices we might need - vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata); - if (vertices == 0) - return 0; - - next_move = 0; - flagcount=0; - - // in first pass, we load uninterpreted data into the allocated array - // above, shifted to the end of the array so we won't overwrite it when - // we create our final data starting from the front - - off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated - - // first load flags - - for (i=0; i < n; ++i) { - if (flagcount == 0) { - flags = *points++; - if (flags & 8) - flagcount = *points++; - } else - --flagcount; - vertices[off+i].type = flags; - } - - // now load x coordinates - x=0; - for (i=0; i < n; ++i) { - flags = vertices[off+i].type; - if (flags & 2) { - stbtt_int16 dx = *points++; - x += (flags & 16) ? dx : -dx; // ??? - } else { - if (!(flags & 16)) { - x = x + (stbtt_int16) (points[0]*256 + points[1]); - points += 2; - } - } - vertices[off+i].x = (stbtt_int16) x; - } - - // now load y coordinates - y=0; - for (i=0; i < n; ++i) { - flags = vertices[off+i].type; - if (flags & 4) { - stbtt_int16 dy = *points++; - y += (flags & 32) ? dy : -dy; // ??? - } else { - if (!(flags & 32)) { - y = y + (stbtt_int16) (points[0]*256 + points[1]); - points += 2; - } - } - vertices[off+i].y = (stbtt_int16) y; - } - - // now convert them to our format - num_vertices=0; - sx = sy = cx = cy = scx = scy = 0; - for (i=0; i < n; ++i) { - flags = vertices[off+i].type; - x = (stbtt_int16) vertices[off+i].x; - y = (stbtt_int16) vertices[off+i].y; - - if (next_move == i) { - if (i != 0) - num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); - - // now start the new one - start_off = !(flags & 1); - if (start_off) { - // if we start off with an off-curve point, then when we need to find a point on the curve - // where we can start, and we need to save some state for when we wraparound. - scx = x; - scy = y; - if (!(vertices[off+i+1].type & 1)) { - // next point is also a curve point, so interpolate an on-point curve - sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1; - sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1; - } else { - // otherwise just use the next point as our start point - sx = (stbtt_int32) vertices[off+i+1].x; - sy = (stbtt_int32) vertices[off+i+1].y; - ++i; // we're using point i+1 as the starting point, so skip it - } - } else { - sx = x; - sy = y; - } - stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0); - was_off = 0; - next_move = 1 + ttUSHORT(endPtsOfContours+j*2); - ++j; - } else { - if (!(flags & 1)) { // if it's a curve - if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint - stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); - cx = x; - cy = y; - was_off = 1; - } else { - if (was_off) - stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy); - else - stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0); - was_off = 0; - } - } - } - num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); - } else if (numberOfContours == -1) { - // Compound shapes. - int more = 1; - stbtt_uint8 *comp = data + g + 10; - num_vertices = 0; - vertices = 0; - while (more) { - stbtt_uint16 flags, gidx; - int comp_num_verts = 0, i; - stbtt_vertex *comp_verts = 0, *tmp = 0; - float mtx[6] = {1,0,0,1,0,0}, m, n; - - flags = ttSHORT(comp); comp+=2; - gidx = ttSHORT(comp); comp+=2; - - if (flags & 2) { // XY values - if (flags & 1) { // shorts - mtx[4] = ttSHORT(comp); comp+=2; - mtx[5] = ttSHORT(comp); comp+=2; - } else { - mtx[4] = ttCHAR(comp); comp+=1; - mtx[5] = ttCHAR(comp); comp+=1; - } - } - else { - // @TODO handle matching point - STBTT_assert(0); - } - if (flags & (1<<3)) { // WE_HAVE_A_SCALE - mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; - mtx[1] = mtx[2] = 0; - } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE - mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; - mtx[1] = mtx[2] = 0; - mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; - } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO - mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; - mtx[1] = ttSHORT(comp)/16384.0f; comp+=2; - mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; - mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; - } - - // Find transformation scales. - m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); - n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); - - // Get indexed glyph. - comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts); - if (comp_num_verts > 0) { - // Transform vertices. - for (i = 0; i < comp_num_verts; ++i) { - stbtt_vertex* v = &comp_verts[i]; - stbtt_vertex_type x,y; - x=v->x; y=v->y; - v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); - v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); - x=v->cx; y=v->cy; - v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); - v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); - } - // Append vertices. - tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata); - if (!tmp) { - if (vertices) STBTT_free(vertices, info->userdata); - if (comp_verts) STBTT_free(comp_verts, info->userdata); - return 0; - } - if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); - STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex)); - if (vertices) STBTT_free(vertices, info->userdata); - vertices = tmp; - STBTT_free(comp_verts, info->userdata); - num_vertices += comp_num_verts; - } - // More components ? - more = flags & (1<<5); - } - } else if (numberOfContours < 0) { - // @TODO other compound variations? - STBTT_assert(0); - } else { - // numberOfCounters == 0, do nothing - } - - *pvertices = vertices; - return num_vertices; -} - -STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing) -{ - stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34); - if (glyph_index < numOfLongHorMetrics) { - if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index); - if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2); - } else { - if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1)); - if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics)); - } -} - -STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) -{ - stbtt_uint8 *data = info->data + info->kern; - stbtt_uint32 needle, straw; - int l, r, m; - - // we only look at the first table. it must be 'horizontal' and format 0. - if (!info->kern) - return 0; - if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 - return 0; - if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format - return 0; - - l = 0; - r = ttUSHORT(data+10) - 1; - needle = glyph1 << 16 | glyph2; - while (l <= r) { - m = (l + r) >> 1; - straw = ttULONG(data+18+(m*6)); // note: unaligned read - if (needle < straw) - r = m - 1; - else if (needle > straw) - l = m + 1; - else - return ttSHORT(data+22+(m*6)); - } - return 0; -} - -STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) -{ - if (!info->kern) // if no kerning table, don't waste time looking up both codepoint->glyphs - return 0; - return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); -} - -STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing) -{ - stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing); -} - -STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap) -{ - if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4); - if (descent) *descent = ttSHORT(info->data+info->hhea + 6); - if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8); -} - -STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1) -{ - *x0 = ttSHORT(info->data + info->head + 36); - *y0 = ttSHORT(info->data + info->head + 38); - *x1 = ttSHORT(info->data + info->head + 40); - *y1 = ttSHORT(info->data + info->head + 42); -} - -STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height) -{ - int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6); - return (float) height / fheight; -} - -STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels) -{ - int unitsPerEm = ttUSHORT(info->data + info->head + 18); - return pixels / unitsPerEm; -} - -STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) -{ - STBTT_free(v, info->userdata); -} - -////////////////////////////////////////////////////////////////////////////// -// -// antialiasing software rasterizer -// - -STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) -{ - int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning - if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { - // e.g. space character - if (ix0) *ix0 = 0; - if (iy0) *iy0 = 0; - if (ix1) *ix1 = 0; - if (iy1) *iy1 = 0; - } else { - // move to integral bboxes (treating pixels as little squares, what pixels get touched)? - if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x); - if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y); - if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x); - if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y); - } -} - -STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) -{ - stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); -} - -STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) -{ - stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1); -} - -STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) -{ - stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1); -} - -////////////////////////////////////////////////////////////////////////////// -// -// Rasterizer - -typedef struct stbtt__hheap_chunk -{ - struct stbtt__hheap_chunk *next; -} stbtt__hheap_chunk; - -typedef struct stbtt__hheap -{ - struct stbtt__hheap_chunk *head; - void *first_free; - int num_remaining_in_head_chunk; -} stbtt__hheap; - -static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) -{ - if (hh->first_free) { - void *p = hh->first_free; - hh->first_free = * (void **) p; - return p; - } else { - if (hh->num_remaining_in_head_chunk == 0) { - int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); - stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata); - if (c == NULL) - return NULL; - c->next = hh->head; - hh->head = c; - hh->num_remaining_in_head_chunk = count; - } - --hh->num_remaining_in_head_chunk; - return (char *) (hh->head) + size * hh->num_remaining_in_head_chunk; - } -} - -static void stbtt__hheap_free(stbtt__hheap *hh, void *p) -{ - *(void **) p = hh->first_free; - hh->first_free = p; -} - -static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata) -{ - stbtt__hheap_chunk *c = hh->head; - while (c) { - stbtt__hheap_chunk *n = c->next; - STBTT_free(c, userdata); - c = n; - } -} - -typedef struct stbtt__edge { - float x0,y0, x1,y1; - int invert; -} stbtt__edge; - - -typedef struct stbtt__active_edge -{ - struct stbtt__active_edge *next; - #if STBTT_RASTERIZER_VERSION==1 - int x,dx; - float ey; - int direction; - #elif STBTT_RASTERIZER_VERSION==2 - float fx,fdx,fdy; - float direction; - float sy; - float ey; - #else - #error "Unrecognized value of STBTT_RASTERIZER_VERSION" - #endif -} stbtt__active_edge; - -#if STBTT_RASTERIZER_VERSION == 1 -#define STBTT_FIXSHIFT 10 -#define STBTT_FIX (1 << STBTT_FIXSHIFT) -#define STBTT_FIXMASK (STBTT_FIX-1) - -static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) -{ - stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); - float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); - STBTT_assert(z != NULL); - if (!z) return z; - - // round dx down to avoid overshooting - if (dxdy < 0) - z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy); - else - z->dx = STBTT_ifloor(STBTT_FIX * dxdy); - - z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount - z->x -= off_x * STBTT_FIX; - - z->ey = e->y1; - z->next = 0; - z->direction = e->invert ? 1 : -1; - return z; -} -#elif STBTT_RASTERIZER_VERSION == 2 -static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) -{ - stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); - float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); - STBTT_assert(z != NULL); - //STBTT_assert(e->y0 <= start_point); - if (!z) return z; - z->fdx = dxdy; - z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f; - z->fx = e->x0 + dxdy * (start_point - e->y0); - z->fx -= off_x; - z->direction = e->invert ? 1.0f : -1.0f; - z->sy = e->y0; - z->ey = e->y1; - z->next = 0; - return z; -} -#else -#error "Unrecognized value of STBTT_RASTERIZER_VERSION" -#endif - -#if STBTT_RASTERIZER_VERSION == 1 -// note: this routine clips fills that extend off the edges... ideally this -// wouldn't happen, but it could happen if the truetype glyph bounding boxes -// are wrong, or if the user supplies a too-small bitmap -static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight) -{ - // non-zero winding fill - int x0=0, w=0; - - while (e) { - if (w == 0) { - // if we're currently at zero, we need to record the edge start point - x0 = e->x; w += e->direction; - } else { - int x1 = e->x; w += e->direction; - // if we went to zero, we need to draw - if (w == 0) { - int i = x0 >> STBTT_FIXSHIFT; - int j = x1 >> STBTT_FIXSHIFT; - - if (i < len && j >= 0) { - if (i == j) { - // x0,x1 are the same pixel, so compute combined coverage - scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT); - } else { - if (i >= 0) // add antialiasing for x0 - scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT); - else - i = -1; // clip - - if (j < len) // add antialiasing for x1 - scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT); - else - j = len; // clip - - for (++i; i < j; ++i) // fill pixels between x0 and x1 - scanline[i] = scanline[i] + (stbtt_uint8) max_weight; - } - } - } - } - - e = e->next; - } -} - -static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) -{ - stbtt__hheap hh = { 0, 0, 0 }; - stbtt__active_edge *active = NULL; - int y,j=0; - int max_weight = (255 / vsubsample); // weight per vertical scanline - int s; // vertical subsample index - unsigned char scanline_data[512], *scanline; - - if (result->w > 512) - scanline = (unsigned char *) STBTT_malloc(result->w, userdata); - else - scanline = scanline_data; - - y = off_y * vsubsample; - e[n].y0 = (off_y + result->h) * (float) vsubsample + 1; - - while (j < result->h) { - STBTT_memset(scanline, 0, result->w); - for (s=0; s < vsubsample; ++s) { - // find center of pixel for this scanline - float scan_y = y + 0.5f; - stbtt__active_edge **step = &active; - - // update all active edges; - // remove all active edges that terminate before the center of this scanline - while (*step) { - stbtt__active_edge * z = *step; - if (z->ey <= scan_y) { - *step = z->next; // delete from list - STBTT_assert(z->direction); - z->direction = 0; - stbtt__hheap_free(&hh, z); - } else { - z->x += z->dx; // advance to position for current scanline - step = &((*step)->next); // advance through list - } - } - - // resort the list if needed - for(;;) { - int changed=0; - step = &active; - while (*step && (*step)->next) { - if ((*step)->x > (*step)->next->x) { - stbtt__active_edge *t = *step; - stbtt__active_edge *q = t->next; - - t->next = q->next; - q->next = t; - *step = q; - changed = 1; - } - step = &(*step)->next; - } - if (!changed) break; - } - - // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline - while (e->y0 <= scan_y) { - if (e->y1 > scan_y) { - stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata); - if (z != NULL) { - // find insertion point - if (active == NULL) - active = z; - else if (z->x < active->x) { - // insert at front - z->next = active; - active = z; - } else { - // find thing to insert AFTER - stbtt__active_edge *p = active; - while (p->next && p->next->x < z->x) - p = p->next; - // at this point, p->next->x is NOT < z->x - z->next = p->next; - p->next = z; - } - } - } - ++e; - } - - // now process all active edges in XOR fashion - if (active) - stbtt__fill_active_edges(scanline, result->w, active, max_weight); - - ++y; - } - STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w); - ++j; - } - - stbtt__hheap_cleanup(&hh, userdata); - - if (scanline != scanline_data) - STBTT_free(scanline, userdata); -} - -#elif STBTT_RASTERIZER_VERSION == 2 - -// the edge passed in here does not cross the vertical line at x or the vertical line at x+1 -// (i.e. it has already been clipped to those) -static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1) -{ - if (y0 == y1) return; - STBTT_assert(y0 < y1); - STBTT_assert(e->sy <= e->ey); - if (y0 > e->ey) return; - if (y1 < e->sy) return; - if (y0 < e->sy) { - x0 += (x1-x0) * (e->sy - y0) / (y1-y0); - y0 = e->sy; - } - if (y1 > e->ey) { - x1 += (x1-x0) * (e->ey - y1) / (y1-y0); - y1 = e->ey; - } - - if (x0 == x) - STBTT_assert(x1 <= x+1); - else if (x0 == x+1) - STBTT_assert(x1 >= x); - else if (x0 <= x) - STBTT_assert(x1 <= x); - else if (x0 >= x+1) - STBTT_assert(x1 >= x+1); - else - STBTT_assert(x1 >= x && x1 <= x+1); - - if (x0 <= x && x1 <= x) - scanline[x] += e->direction * (y1-y0); - else if (x0 >= x+1 && x1 >= x+1) - ; - else { - STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1); - scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position - } -} - -static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top) -{ - float y_bottom = y_top+1; - - while (e) { - // brute force every pixel - - // compute intersection points with top & bottom - STBTT_assert(e->ey >= y_top); - - if (e->fdx == 0) { - float x0 = e->fx; - if (x0 < len) { - if (x0 >= 0) { - stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom); - stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom); - } else { - stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom); - } - } - } else { - float x0 = e->fx; - float dx = e->fdx; - float xb = x0 + dx; - float x_top, x_bottom; - float sy0,sy1; - float dy = e->fdy; - STBTT_assert(e->sy <= y_bottom && e->ey >= y_top); - - // compute endpoints of line segment clipped to this scanline (if the - // line segment starts on this scanline. x0 is the intersection of the - // line with y_top, but that may be off the line segment. - if (e->sy > y_top) { - x_top = x0 + dx * (e->sy - y_top); - sy0 = e->sy; - } else { - x_top = x0; - sy0 = y_top; - } - if (e->ey < y_bottom) { - x_bottom = x0 + dx * (e->ey - y_top); - sy1 = e->ey; - } else { - x_bottom = xb; - sy1 = y_bottom; - } - - if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) { - // from here on, we don't have to range check x values - - if ((int) x_top == (int) x_bottom) { - float height; - // simple case, only spans one pixel - int x = (int) x_top; - height = sy1 - sy0; - STBTT_assert(x >= 0 && x < len); - scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height; - scanline_fill[x] += e->direction * height; // everything right of this pixel is filled - } else { - int x,x1,x2; - float y_crossing, step, sign, area; - // covers 2+ pixels - if (x_top > x_bottom) { - // flip scanline vertically; signed area is the same - float t; - sy0 = y_bottom - (sy0 - y_top); - sy1 = y_bottom - (sy1 - y_top); - t = sy0, sy0 = sy1, sy1 = t; - t = x_bottom, x_bottom = x_top, x_top = t; - dx = -dx; - dy = -dy; - t = x0, x0 = xb, xb = t; - } - - x1 = (int) x_top; - x2 = (int) x_bottom; - // compute intersection with y axis at x1+1 - y_crossing = (x1+1 - x0) * dy + y_top; - - sign = e->direction; - // area of the rectangle covered from y0..y_crossing - area = sign * (y_crossing-sy0); - // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) - scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2); - - step = sign * dy; - for (x = x1+1; x < x2; ++x) { - scanline[x] += area + step/2; - area += step; - } - y_crossing += dy * (x2 - (x1+1)); - - STBTT_assert(STBTT_fabs(area) <= 1.01f); - - scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing); - - scanline_fill[x2] += sign * (sy1-sy0); - } - } else { - // if edge goes outside of box we're drawing, we require - // clipping logic. since this does not match the intended use - // of this library, we use a different, very slow brute - // force implementation - int x; - for (x=0; x < len; ++x) { - // cases: - // - // there can be up to two intersections with the pixel. any intersection - // with left or right edges can be handled by splitting into two (or three) - // regions. intersections with top & bottom do not necessitate case-wise logic. - // - // the old way of doing this found the intersections with the left & right edges, - // then used some simple logic to produce up to three segments in sorted order - // from top-to-bottom. however, this had a problem: if an x edge was epsilon - // across the x border, then the corresponding y position might not be distinct - // from the other y segment, and it might ignored as an empty segment. to avoid - // that, we need to explicitly produce segments based on x positions. - - // rename variables to clear pairs - float y0 = y_top; - float x1 = (float) (x); - float x2 = (float) (x+1); - float x3 = xb; - float y3 = y_bottom; - float y1,y2; - - // x = e->x + e->dx * (y-y_top) - // (y-y_top) = (x - e->x) / e->dx - // y = (x - e->x) / e->dx + y_top - y1 = (x - x0) / dx + y_top; - y2 = (x+1 - x0) / dx + y_top; - - if (x0 < x1 && x3 > x2) { // three segments descending down-right - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); - stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2); - stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); - } else if (x3 < x1 && x0 > x2) { // three segments descending down-left - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); - stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1); - stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); - } else if (x0 < x1 && x3 > x1) { // two segments across x, down-right - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); - stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); - } else if (x3 < x1 && x0 > x1) { // two segments across x, down-left - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); - stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); - } else if (x0 < x2 && x3 > x2) { // two segments across x+1, down-right - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); - stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); - } else if (x3 < x2 && x0 > x2) { // two segments across x+1, down-left - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); - stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); - } else { // one segment - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3); - } - } - } - } - e = e->next; - } -} - -// directly AA rasterize edges w/o supersampling -static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) -{ - stbtt__hheap hh = { 0, 0, 0 }; - stbtt__active_edge *active = NULL; - int y,j=0, i; - float scanline_data[129], *scanline, *scanline2; - - STBTT__NOTUSED(vsubsample); - - if (result->w > 64) - scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata); - else - scanline = scanline_data; - - scanline2 = scanline + result->w; - - y = off_y; - e[n].y0 = (float) (off_y + result->h) + 1; - - while (j < result->h) { - // find center of pixel for this scanline - float scan_y_top = y + 0.0f; - float scan_y_bottom = y + 1.0f; - stbtt__active_edge **step = &active; - - STBTT_memset(scanline , 0, result->w*sizeof(scanline[0])); - STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0])); - - // update all active edges; - // remove all active edges that terminate before the top of this scanline - while (*step) { - stbtt__active_edge * z = *step; - if (z->ey <= scan_y_top) { - *step = z->next; // delete from list - STBTT_assert(z->direction); - z->direction = 0; - stbtt__hheap_free(&hh, z); - } else { - step = &((*step)->next); // advance through list - } - } - - // insert all edges that start before the bottom of this scanline - while (e->y0 <= scan_y_bottom) { - if (e->y0 != e->y1) { - stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); - if (z != NULL) { - STBTT_assert(z->ey >= scan_y_top); - // insert at front - z->next = active; - active = z; - } - } - ++e; - } - - // now process all active edges - if (active) - stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top); - - { - float sum = 0; - for (i=0; i < result->w; ++i) { - float k; - int m; - sum += scanline2[i]; - k = scanline[i] + sum; - k = (float) STBTT_fabs(k)*255 + 0.5f; - m = (int) k; - if (m > 255) m = 255; - result->pixels[j*result->stride + i] = (unsigned char) m; - } - } - // advance all the edges - step = &active; - while (*step) { - stbtt__active_edge *z = *step; - z->fx += z->fdx; // advance to position for current scanline - step = &((*step)->next); // advance through list - } - - ++y; - ++j; - } - - stbtt__hheap_cleanup(&hh, userdata); - - if (scanline != scanline_data) - STBTT_free(scanline, userdata); -} -#else -#error "Unrecognized value of STBTT_RASTERIZER_VERSION" -#endif - -#define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0) - -static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n) -{ - int i,j; - for (i=1; i < n; ++i) { - stbtt__edge t = p[i], *a = &t; - j = i; - while (j > 0) { - stbtt__edge *b = &p[j-1]; - int c = STBTT__COMPARE(a,b); - if (!c) break; - p[j] = p[j-1]; - --j; - } - if (i != j) - p[j] = t; - } -} - -static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n) -{ - /* threshhold for transitioning to insertion sort */ - while (n > 12) { - stbtt__edge t; - int c01,c12,c,m,i,j; - - /* compute median of three */ - m = n >> 1; - c01 = STBTT__COMPARE(&p[0],&p[m]); - c12 = STBTT__COMPARE(&p[m],&p[n-1]); - /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ - if (c01 != c12) { - /* otherwise, we'll need to swap something else to middle */ - int z; - c = STBTT__COMPARE(&p[0],&p[n-1]); - /* 0>mid && mid<n: 0>n => n; 0<n => 0 */ - /* 0<mid && mid>n: 0>n => 0; 0<n => n */ - z = (c == c12) ? 0 : n-1; - t = p[z]; - p[z] = p[m]; - p[m] = t; - } - /* now p[m] is the median-of-three */ - /* swap it to the beginning so it won't move around */ - t = p[0]; - p[0] = p[m]; - p[m] = t; - - /* partition loop */ - i=1; - j=n-1; - for(;;) { - /* handling of equality is crucial here */ - /* for sentinels & efficiency with duplicates */ - for (;;++i) { - if (!STBTT__COMPARE(&p[i], &p[0])) break; - } - for (;;--j) { - if (!STBTT__COMPARE(&p[0], &p[j])) break; - } - /* make sure we haven't crossed */ - if (i >= j) break; - t = p[i]; - p[i] = p[j]; - p[j] = t; - - ++i; - --j; - } - /* recurse on smaller side, iterate on larger */ - if (j < (n-i)) { - stbtt__sort_edges_quicksort(p,j); - p = p+i; - n = n-i; - } else { - stbtt__sort_edges_quicksort(p+i, n-i); - n = j; - } - } -} - -static void stbtt__sort_edges(stbtt__edge *p, int n) -{ - stbtt__sort_edges_quicksort(p, n); - stbtt__sort_edges_ins_sort(p, n); -} - -typedef struct -{ - float x,y; -} stbtt__point; - -static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata) -{ - float y_scale_inv = invert ? -scale_y : scale_y; - stbtt__edge *e; - int n,i,j,k,m; -#if STBTT_RASTERIZER_VERSION == 1 - int vsubsample = result->h < 8 ? 15 : 5; -#elif STBTT_RASTERIZER_VERSION == 2 - int vsubsample = 1; -#else - #error "Unrecognized value of STBTT_RASTERIZER_VERSION" -#endif - // vsubsample should divide 255 evenly; otherwise we won't reach full opacity - - // now we have to blow out the windings into explicit edge lists - n = 0; - for (i=0; i < windings; ++i) - n += wcount[i]; - - e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel - if (e == 0) return; - n = 0; - - m=0; - for (i=0; i < windings; ++i) { - stbtt__point *p = pts + m; - m += wcount[i]; - j = wcount[i]-1; - for (k=0; k < wcount[i]; j=k++) { - int a=k,b=j; - // skip the edge if horizontal - if (p[j].y == p[k].y) - continue; - // add edge from j to k to the list - e[n].invert = 0; - if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { - e[n].invert = 1; - a=j,b=k; - } - e[n].x0 = p[a].x * scale_x + shift_x; - e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample; - e[n].x1 = p[b].x * scale_x + shift_x; - e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample; - ++n; - } - } - - // now sort the edges by their highest point (should snap to integer, and then by x) - //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); - stbtt__sort_edges(e, n); - - // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule - stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata); - - STBTT_free(e, userdata); -} - -static void stbtt__add_point(stbtt__point *points, int n, float x, float y) -{ - if (!points) return; // during first pass, it's unallocated - points[n].x = x; - points[n].y = y; -} - -// tesselate until threshhold p is happy... @TODO warped to compensate for non-linear stretching -static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n) -{ - // midpoint - float mx = (x0 + 2*x1 + x2)/4; - float my = (y0 + 2*y1 + y2)/4; - // versus directly drawn line - float dx = (x0+x2)/2 - mx; - float dy = (y0+y2)/2 - my; - if (n > 16) // 65536 segments on one curve better be enough! - return 1; - if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA - stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1); - stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1); - } else { - stbtt__add_point(points, *num_points,x2,y2); - *num_points = *num_points+1; - } - return 1; -} - -// returns number of contours -static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) -{ - stbtt__point *points=0; - int num_points=0; - - float objspace_flatness_squared = objspace_flatness * objspace_flatness; - int i,n=0,start=0, pass; - - // count how many "moves" there are to get the contour count - for (i=0; i < num_verts; ++i) - if (vertices[i].type == STBTT_vmove) - ++n; - - *num_contours = n; - if (n == 0) return 0; - - *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata); - - if (*contour_lengths == 0) { - *num_contours = 0; - return 0; - } - - // make two passes through the points so we don't need to realloc - for (pass=0; pass < 2; ++pass) { - float x=0,y=0; - if (pass == 1) { - points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata); - if (points == NULL) goto error; - } - num_points = 0; - n= -1; - for (i=0; i < num_verts; ++i) { - switch (vertices[i].type) { - case STBTT_vmove: - // start the next contour - if (n >= 0) - (*contour_lengths)[n] = num_points - start; - ++n; - start = num_points; - - x = vertices[i].x, y = vertices[i].y; - stbtt__add_point(points, num_points++, x,y); - break; - case STBTT_vline: - x = vertices[i].x, y = vertices[i].y; - stbtt__add_point(points, num_points++, x, y); - break; - case STBTT_vcurve: - stbtt__tesselate_curve(points, &num_points, x,y, - vertices[i].cx, vertices[i].cy, - vertices[i].x, vertices[i].y, - objspace_flatness_squared, 0); - x = vertices[i].x, y = vertices[i].y; - break; - } - } - (*contour_lengths)[n] = num_points - start; - } - - return points; -error: - STBTT_free(points, userdata); - STBTT_free(*contour_lengths, userdata); - *contour_lengths = 0; - *num_contours = 0; - return NULL; -} - -STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) -{ - float scale = scale_x > scale_y ? scale_y : scale_x; - int winding_count, *winding_lengths; - stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); - if (windings) { - stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); - STBTT_free(winding_lengths, userdata); - STBTT_free(windings, userdata); - } -} - -STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata) -{ - STBTT_free(bitmap, userdata); -} - -STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff) -{ - int ix0,iy0,ix1,iy1; - stbtt__bitmap gbm; - stbtt_vertex *vertices; - int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); - - if (scale_x == 0) scale_x = scale_y; - if (scale_y == 0) { - if (scale_x == 0) { - STBTT_free(vertices, info->userdata); - return NULL; - } - scale_y = scale_x; - } - - stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1); - - // now we get the size - gbm.w = (ix1 - ix0); - gbm.h = (iy1 - iy0); - gbm.pixels = NULL; // in case we error - - if (width ) *width = gbm.w; - if (height) *height = gbm.h; - if (xoff ) *xoff = ix0; - if (yoff ) *yoff = iy0; - - if (gbm.w && gbm.h) { - gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata); - if (gbm.pixels) { - gbm.stride = gbm.w; - - stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata); - } - } - STBTT_free(vertices, info->userdata); - return gbm.pixels; -} - -STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) -{ - return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff); -} - -STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph) -{ - int ix0,iy0; - stbtt_vertex *vertices; - int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); - stbtt__bitmap gbm; - - stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); - gbm.pixels = output; - gbm.w = out_w; - gbm.h = out_h; - gbm.stride = out_stride; - - if (gbm.w && gbm.h) - stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata); - - STBTT_free(vertices, info->userdata); -} - -STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph) -{ - stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph); -} - -STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff) -{ - return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); -} - -STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint) -{ - stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint)); -} - -STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff) -{ - return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff); -} - -STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint) -{ - stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint); -} - -////////////////////////////////////////////////////////////////////////////// -// -// bitmap baking -// -// This is SUPER-CRAPPY packing to keep source code small - -STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) - float pixel_height, // height of font in pixels - unsigned char *pixels, int pw, int ph, // bitmap to be filled in - int first_char, int num_chars, // characters to bake - stbtt_bakedchar *chardata) -{ - float scale; - int x,y,bottom_y, i; - stbtt_fontinfo f; - f.userdata = NULL; - if (!stbtt_InitFont(&f, data, offset)) - return -1; - STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels - x=y=1; - bottom_y = 1; - - scale = stbtt_ScaleForPixelHeight(&f, pixel_height); - - for (i=0; i < num_chars; ++i) { - int advance, lsb, x0,y0,x1,y1,gw,gh; - int g = stbtt_FindGlyphIndex(&f, first_char + i); - stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb); - stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1); - gw = x1-x0; - gh = y1-y0; - if (x + gw + 1 >= pw) - y = bottom_y, x = 1; // advance to next row - if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row - return -i; - STBTT_assert(x+gw < pw); - STBTT_assert(y+gh < ph); - stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g); - chardata[i].x0 = (stbtt_int16) x; - chardata[i].y0 = (stbtt_int16) y; - chardata[i].x1 = (stbtt_int16) (x + gw); - chardata[i].y1 = (stbtt_int16) (y + gh); - chardata[i].xadvance = scale * advance; - chardata[i].xoff = (float) x0; - chardata[i].yoff = (float) y0; - x = x + gw + 1; - if (y+gh+1 > bottom_y) - bottom_y = y+gh+1; - } - return bottom_y; -} - -STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) -{ - float d3d_bias = opengl_fillrule ? 0 : -0.5f; - float ipw = 1.0f / pw, iph = 1.0f / ph; - stbtt_bakedchar *b = chardata + char_index; - int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f); - int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f); - - q->x0 = round_x + d3d_bias; - q->y0 = round_y + d3d_bias; - q->x1 = round_x + b->x1 - b->x0 + d3d_bias; - q->y1 = round_y + b->y1 - b->y0 + d3d_bias; - - q->s0 = b->x0 * ipw; - q->t0 = b->y0 * iph; - q->s1 = b->x1 * ipw; - q->t1 = b->y1 * iph; - - *xpos += b->xadvance; -} - -////////////////////////////////////////////////////////////////////////////// -// -// rectangle packing replacement routines if you don't have stb_rect_pack.h -// - -#ifndef STB_RECT_PACK_VERSION - -typedef int stbrp_coord; - -//////////////////////////////////////////////////////////////////////////////////// -// // -// // -// COMPILER WARNING ?!?!? // -// // -// // -// if you get a compile warning due to these symbols being defined more than // -// once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" // -// // -//////////////////////////////////////////////////////////////////////////////////// - -typedef struct -{ - int width,height; - int x,y,bottom_y; -} stbrp_context; - -typedef struct -{ - unsigned char x; -} stbrp_node; - -struct stbrp_rect -{ - stbrp_coord x,y; - int id,w,h,was_packed; -}; - -static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes) -{ - con->width = pw; - con->height = ph; - con->x = 0; - con->y = 0; - con->bottom_y = 0; - STBTT__NOTUSED(nodes); - STBTT__NOTUSED(num_nodes); -} - -static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects) -{ - int i; - for (i=0; i < num_rects; ++i) { - if (con->x + rects[i].w > con->width) { - con->x = 0; - con->y = con->bottom_y; - } - if (con->y + rects[i].h > con->height) - break; - rects[i].x = con->x; - rects[i].y = con->y; - rects[i].was_packed = 1; - con->x += rects[i].w; - if (con->y + rects[i].h > con->bottom_y) - con->bottom_y = con->y + rects[i].h; - } - for ( ; i < num_rects; ++i) - rects[i].was_packed = 0; -} -#endif - -////////////////////////////////////////////////////////////////////////////// -// -// bitmap baking -// -// This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If -// stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy. - -STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context) -{ - stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context); - int num_nodes = pw - padding; - stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context); - - if (context == NULL || nodes == NULL) { - if (context != NULL) STBTT_free(context, alloc_context); - if (nodes != NULL) STBTT_free(nodes , alloc_context); - return 0; - } - - spc->user_allocator_context = alloc_context; - spc->width = pw; - spc->height = ph; - spc->pixels = pixels; - spc->pack_info = context; - spc->nodes = nodes; - spc->padding = padding; - spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw; - spc->h_oversample = 1; - spc->v_oversample = 1; - - stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); - - if (pixels) - STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels - - return 1; -} - -STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc) -{ - STBTT_free(spc->nodes , spc->user_allocator_context); - STBTT_free(spc->pack_info, spc->user_allocator_context); -} - -STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample) -{ - STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE); - STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE); - if (h_oversample <= STBTT_MAX_OVERSAMPLE) - spc->h_oversample = h_oversample; - if (v_oversample <= STBTT_MAX_OVERSAMPLE) - spc->v_oversample = v_oversample; -} - -#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1) - -static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) -{ - unsigned char buffer[STBTT_MAX_OVERSAMPLE]; - int safe_w = w - kernel_width; - int j; - STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze - for (j=0; j < h; ++j) { - int i; - unsigned int total; - STBTT_memset(buffer, 0, kernel_width); - - total = 0; - - // make kernel_width a constant in common cases so compiler can optimize out the divide - switch (kernel_width) { - case 2: - for (i=0; i <= safe_w; ++i) { - total += pixels[i] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / 2); - } - break; - case 3: - for (i=0; i <= safe_w; ++i) { - total += pixels[i] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / 3); - } - break; - case 4: - for (i=0; i <= safe_w; ++i) { - total += pixels[i] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / 4); - } - break; - case 5: - for (i=0; i <= safe_w; ++i) { - total += pixels[i] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / 5); - } - break; - default: - for (i=0; i <= safe_w; ++i) { - total += pixels[i] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / kernel_width); - } - break; - } - - for (; i < w; ++i) { - STBTT_assert(pixels[i] == 0); - total -= buffer[i & STBTT__OVER_MASK]; - pixels[i] = (unsigned char) (total / kernel_width); - } - - pixels += stride_in_bytes; - } -} - -static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) -{ - unsigned char buffer[STBTT_MAX_OVERSAMPLE]; - int safe_h = h - kernel_width; - int j; - STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze - for (j=0; j < w; ++j) { - int i; - unsigned int total; - STBTT_memset(buffer, 0, kernel_width); - - total = 0; - - // make kernel_width a constant in common cases so compiler can optimize out the divide - switch (kernel_width) { - case 2: - for (i=0; i <= safe_h; ++i) { - total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / 2); - } - break; - case 3: - for (i=0; i <= safe_h; ++i) { - total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / 3); - } - break; - case 4: - for (i=0; i <= safe_h; ++i) { - total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / 4); - } - break; - case 5: - for (i=0; i <= safe_h; ++i) { - total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / 5); - } - break; - default: - for (i=0; i <= safe_h; ++i) { - total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); - } - break; - } - - for (; i < h; ++i) { - STBTT_assert(pixels[i*stride_in_bytes] == 0); - total -= buffer[i & STBTT__OVER_MASK]; - pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); - } - - pixels += 1; - } -} - -static float stbtt__oversample_shift(int oversample) -{ - if (!oversample) - return 0.0f; - - // The prefilter is a box filter of width "oversample", - // which shifts phase by (oversample - 1)/2 pixels in - // oversampled space. We want to shift in the opposite - // direction to counter this. - return (float)-(oversample - 1) / (2.0f * (float)oversample); -} - -// rects array must be big enough to accommodate all characters in the given ranges -STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) -{ - int i,j,k; - - k=0; - for (i=0; i < num_ranges; ++i) { - float fh = ranges[i].font_size; - float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); - ranges[i].h_oversample = (unsigned char) spc->h_oversample; - ranges[i].v_oversample = (unsigned char) spc->v_oversample; - for (j=0; j < ranges[i].num_chars; ++j) { - int x0,y0,x1,y1; - int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; - int glyph = stbtt_FindGlyphIndex(info, codepoint); - stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, - scale * spc->h_oversample, - scale * spc->v_oversample, - 0,0, - &x0,&y0,&x1,&y1); - rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); - rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); - ++k; - } - } - - return k; -} - -// rects array must be big enough to accommodate all characters in the given ranges -STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) -{ - int i,j,k, return_value = 1; - - // save current values - int old_h_over = spc->h_oversample; - int old_v_over = spc->v_oversample; - - k = 0; - for (i=0; i < num_ranges; ++i) { - float fh = ranges[i].font_size; - float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); - float recip_h,recip_v,sub_x,sub_y; - spc->h_oversample = ranges[i].h_oversample; - spc->v_oversample = ranges[i].v_oversample; - recip_h = 1.0f / spc->h_oversample; - recip_v = 1.0f / spc->v_oversample; - sub_x = stbtt__oversample_shift(spc->h_oversample); - sub_y = stbtt__oversample_shift(spc->v_oversample); - for (j=0; j < ranges[i].num_chars; ++j) { - stbrp_rect *r = &rects[k]; - if (r->was_packed) { - stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; - int advance, lsb, x0,y0,x1,y1; - int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; - int glyph = stbtt_FindGlyphIndex(info, codepoint); - stbrp_coord pad = (stbrp_coord) spc->padding; - - // pad on left and top - r->x += pad; - r->y += pad; - r->w -= pad; - r->h -= pad; - stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb); - stbtt_GetGlyphBitmapBox(info, glyph, - scale * spc->h_oversample, - scale * spc->v_oversample, - &x0,&y0,&x1,&y1); - stbtt_MakeGlyphBitmapSubpixel(info, - spc->pixels + r->x + r->y*spc->stride_in_bytes, - r->w - spc->h_oversample+1, - r->h - spc->v_oversample+1, - spc->stride_in_bytes, - scale * spc->h_oversample, - scale * spc->v_oversample, - 0,0, - glyph); - - if (spc->h_oversample > 1) - stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, - r->w, r->h, spc->stride_in_bytes, - spc->h_oversample); - - if (spc->v_oversample > 1) - stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, - r->w, r->h, spc->stride_in_bytes, - spc->v_oversample); - - bc->x0 = (stbtt_int16) r->x; - bc->y0 = (stbtt_int16) r->y; - bc->x1 = (stbtt_int16) (r->x + r->w); - bc->y1 = (stbtt_int16) (r->y + r->h); - bc->xadvance = scale * advance; - bc->xoff = (float) x0 * recip_h + sub_x; - bc->yoff = (float) y0 * recip_v + sub_y; - bc->xoff2 = (x0 + r->w) * recip_h + sub_x; - bc->yoff2 = (y0 + r->h) * recip_v + sub_y; - } else { - return_value = 0; // if any fail, report failure - } - - ++k; - } - } - - // restore original values - spc->h_oversample = old_h_over; - spc->v_oversample = old_v_over; - - return return_value; -} - -STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects) -{ - stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects); -} - -STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) -{ - stbtt_fontinfo info; - int i,j,n, return_value = 1; - //stbrp_context *context = (stbrp_context *) spc->pack_info; - stbrp_rect *rects; - - // flag all characters as NOT packed - for (i=0; i < num_ranges; ++i) - for (j=0; j < ranges[i].num_chars; ++j) - ranges[i].chardata_for_range[j].x0 = - ranges[i].chardata_for_range[j].y0 = - ranges[i].chardata_for_range[j].x1 = - ranges[i].chardata_for_range[j].y1 = 0; - - n = 0; - for (i=0; i < num_ranges; ++i) - n += ranges[i].num_chars; - - rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); - if (rects == NULL) - return 0; - - info.userdata = spc->user_allocator_context; - stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index)); - - n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); - - stbtt_PackFontRangesPackRects(spc, rects, n); - - return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); - - STBTT_free(rects, spc->user_allocator_context); - return return_value; -} - -STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size, - int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) -{ - stbtt_pack_range range; - range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range; - range.array_of_unicode_codepoints = NULL; - range.num_chars = num_chars_in_range; - range.chardata_for_range = chardata_for_range; - range.font_size = font_size; - return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); -} - -STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) -{ - float ipw = 1.0f / pw, iph = 1.0f / ph; - stbtt_packedchar *b = chardata + char_index; - - if (align_to_integer) { - float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f); - float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f); - q->x0 = x; - q->y0 = y; - q->x1 = x + b->xoff2 - b->xoff; - q->y1 = y + b->yoff2 - b->yoff; - } else { - q->x0 = *xpos + b->xoff; - q->y0 = *ypos + b->yoff; - q->x1 = *xpos + b->xoff2; - q->y1 = *ypos + b->yoff2; - } - - q->s0 = b->x0 * ipw; - q->t0 = b->y0 * iph; - q->s1 = b->x1 * ipw; - q->t1 = b->y1 * iph; - - *xpos += b->xadvance; -} - - -////////////////////////////////////////////////////////////////////////////// -// -// font name matching -- recommended not to use this -// - -// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string -static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(const stbtt_uint8 *s1, stbtt_int32 len1, const stbtt_uint8 *s2, stbtt_int32 len2) -{ - stbtt_int32 i=0; - - // convert utf16 to utf8 and compare the results while converting - while (len2) { - stbtt_uint16 ch = s2[0]*256 + s2[1]; - if (ch < 0x80) { - if (i >= len1) return -1; - if (s1[i++] != ch) return -1; - } else if (ch < 0x800) { - if (i+1 >= len1) return -1; - if (s1[i++] != 0xc0 + (ch >> 6)) return -1; - if (s1[i++] != 0x80 + (ch & 0x3f)) return -1; - } else if (ch >= 0xd800 && ch < 0xdc00) { - stbtt_uint32 c; - stbtt_uint16 ch2 = s2[2]*256 + s2[3]; - if (i+3 >= len1) return -1; - c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000; - if (s1[i++] != 0xf0 + (c >> 18)) return -1; - if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1; - if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1; - if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1; - s2 += 2; // plus another 2 below - len2 -= 2; - } else if (ch >= 0xdc00 && ch < 0xe000) { - return -1; - } else { - if (i+2 >= len1) return -1; - if (s1[i++] != 0xe0 + (ch >> 12)) return -1; - if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1; - if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1; - } - s2 += 2; - len2 -= 2; - } - return i; -} - -STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) -{ - return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((const stbtt_uint8*) s1, len1, (const stbtt_uint8*) s2, len2); -} - -// returns results in whatever encoding you request... but note that 2-byte encodings -// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare -STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID) -{ - stbtt_int32 i,count,stringOffset; - stbtt_uint8 *fc = font->data; - stbtt_uint32 offset = font->fontstart; - stbtt_uint32 nm = stbtt__find_table(fc, offset, "name"); - if (!nm) return NULL; - - count = ttUSHORT(fc+nm+2); - stringOffset = nm + ttUSHORT(fc+nm+4); - for (i=0; i < count; ++i) { - stbtt_uint32 loc = nm + 6 + 12 * i; - if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2) - && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) { - *length = ttUSHORT(fc+loc+8); - return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10)); - } - } - return NULL; -} - -static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id) -{ - stbtt_int32 i; - stbtt_int32 count = ttUSHORT(fc+nm+2); - stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4); - - for (i=0; i < count; ++i) { - stbtt_uint32 loc = nm + 6 + 12 * i; - stbtt_int32 id = ttUSHORT(fc+loc+6); - if (id == target_id) { - // find the encoding - stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4); - - // is this a Unicode encoding? - if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) { - stbtt_int32 slen = ttUSHORT(fc+loc+8); - stbtt_int32 off = ttUSHORT(fc+loc+10); - - // check if there's a prefix match - stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen); - if (matchlen >= 0) { - // check for target_id+1 immediately following, with same encoding & language - if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) { - slen = ttUSHORT(fc+loc+12+8); - off = ttUSHORT(fc+loc+12+10); - if (slen == 0) { - if (matchlen == nlen) - return 1; - } else if (matchlen < nlen && name[matchlen] == ' ') { - ++matchlen; - if (stbtt_CompareUTF8toUTF16_bigendian((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen)) - return 1; - } - } else { - // if nothing immediately following - if (matchlen == nlen) - return 1; - } - } - } - - // @TODO handle other encodings - } - } - return 0; -} - -static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags) -{ - stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name); - stbtt_uint32 nm,hd; - if (!stbtt__isfont(fc+offset)) return 0; - - // check italics/bold/underline flags in macStyle... - if (flags) { - hd = stbtt__find_table(fc, offset, "head"); - if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0; - } - - nm = stbtt__find_table(fc, offset, "name"); - if (!nm) return 0; - - if (flags) { - // if we checked the macStyle flags, then just check the family and ignore the subfamily - if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1; - if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1; - if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; - } else { - if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1; - if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1; - if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; - } - - return 0; -} - -STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *font_collection, const char *name_utf8, stbtt_int32 flags) -{ - stbtt_int32 i; - for (i=0;;++i) { - stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i); - if (off < 0) return off; - if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags)) - return off; - } -} - -#endif // STB_TRUETYPE_IMPLEMENTATION - - -// FULL VERSION HISTORY -// -// 1.11 (2016-04-02) fix unused-variable warning -// 1.10 (2016-04-02) allow user-defined fabs() replacement -// fix memory leak if fontsize=0.0 -// fix warning from duplicate typedef -// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges -// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges -// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; -// allow PackFontRanges to pack and render in separate phases; -// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); -// fixed an assert() bug in the new rasterizer -// replace assert() with STBTT_assert() in new rasterizer -// 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine) -// also more precise AA rasterizer, except if shapes overlap -// remove need for STBTT_sort -// 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC -// 1.04 (2015-04-15) typo in example -// 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes -// 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++ -// 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match -// non-oversampled; STBTT_POINT_SIZE for packed case only -// 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling -// 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg) -// 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID -// 0.8b (2014-07-07) fix a warning -// 0.8 (2014-05-25) fix a few more warnings -// 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back -// 0.6c (2012-07-24) improve documentation -// 0.6b (2012-07-20) fix a few more warnings -// 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels, -// stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty -// 0.5 (2011-12-09) bugfixes: -// subpixel glyph renderer computed wrong bounding box -// first vertex of shape can be off-curve (FreeSans) -// 0.4b (2011-12-03) fixed an error in the font baking example -// 0.4 (2011-12-01) kerning, subpixel rendering (tor) -// bugfixes for: -// codepoint-to-glyph conversion using table fmt=12 -// codepoint-to-glyph conversion using table fmt=4 -// stbtt_GetBakedQuad with non-square texture (Zer) -// updated Hello World! sample to use kerning and subpixel -// fixed some warnings -// 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM) -// userdata, malloc-from-userdata, non-zero fill (stb) -// 0.2 (2009-03-11) Fix unsigned/signed char warnings -// 0.1 (2009-03-09) First public release -// diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp index 7a503207b..48efa242e 100644 --- a/scene/resources/style_box.cpp +++ b/scene/resources/style_box.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -27,6 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "style_box.h" +#include <limits.h> bool StyleBox::test_mask(const Point2 &p_point, const Rect2 &p_rect) const { @@ -103,14 +105,30 @@ void StyleBoxTexture::set_texture(RES p_texture) { if (texture == p_texture) return; texture = p_texture; + region_rect = Rect2(Point2(), texture->get_size()); emit_signal("texture_changed"); emit_changed(); + _change_notify("texture"); } + RES StyleBoxTexture::get_texture() const { return texture; } +void StyleBoxTexture::set_normal_map(RES p_normal_map) { + + if (normal_map == p_normal_map) + return; + normal_map = p_normal_map; + emit_changed(); +} + +RES StyleBoxTexture::get_normal_map() const { + + return normal_map; +} + void StyleBoxTexture::set_margin_size(Margin p_margin, float p_size) { margin[p_margin] = p_size; @@ -130,12 +148,21 @@ void StyleBoxTexture::draw(RID p_canvas_item, const Rect2 &p_rect) const { if (texture.is_null()) return; - Rect2 r = p_rect; - r.pos.x -= expand_margin[MARGIN_LEFT]; - r.pos.y -= expand_margin[MARGIN_TOP]; - r.size.x += expand_margin[MARGIN_LEFT] + expand_margin[MARGIN_RIGHT]; - r.size.y += expand_margin[MARGIN_TOP] + expand_margin[MARGIN_BOTTOM]; - VisualServer::get_singleton()->canvas_item_add_nine_patch(p_canvas_item, r, region_rect, texture->get_rid(), Vector2(margin[MARGIN_LEFT], margin[MARGIN_TOP]), Vector2(margin[MARGIN_RIGHT], margin[MARGIN_BOTTOM]), VS::NINE_PATCH_STRETCH, VS::NINE_PATCH_STRETCH, draw_center, modulate); + Rect2 rect = p_rect; + Rect2 src_rect = region_rect; + + texture->get_rect_region(rect, src_rect, rect, src_rect); + + rect.position.x -= expand_margin[MARGIN_LEFT]; + rect.position.y -= expand_margin[MARGIN_TOP]; + rect.size.x += expand_margin[MARGIN_LEFT] + expand_margin[MARGIN_RIGHT]; + rect.size.y += expand_margin[MARGIN_TOP] + expand_margin[MARGIN_BOTTOM]; + + RID normal_rid; + if (normal_map.is_valid()) + normal_rid = normal_map->get_rid(); + + VisualServer::get_singleton()->canvas_item_add_nine_patch(p_canvas_item, rect, src_rect, texture->get_rid(), Vector2(margin[MARGIN_LEFT], margin[MARGIN_TOP]), Vector2(margin[MARGIN_RIGHT], margin[MARGIN_BOTTOM]), VS::NinePatchAxisMode(axis_h), VS::NinePatchAxisMode(axis_v), draw_center, modulate, normal_rid); } void StyleBoxTexture::set_draw_center(bool p_draw) { @@ -184,6 +211,28 @@ Rect2 StyleBoxTexture::get_region_rect() const { return region_rect; } +void StyleBoxTexture::set_h_axis_stretch_mode(AxisStretchMode p_mode) { + + axis_h = p_mode; + emit_changed(); +} + +StyleBoxTexture::AxisStretchMode StyleBoxTexture::get_h_axis_stretch_mode() const { + + return axis_h; +} + +void StyleBoxTexture::set_v_axis_stretch_mode(AxisStretchMode p_mode) { + + axis_v = p_mode; + emit_changed(); +} + +StyleBoxTexture::AxisStretchMode StyleBoxTexture::get_v_axis_stretch_mode() const { + + return axis_v; +} + void StyleBoxTexture::set_modulate(const Color &p_modulate) { if (modulate == p_modulate) return; @@ -198,8 +247,11 @@ Color StyleBoxTexture::get_modulate() const { void StyleBoxTexture::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_texture", "texture:Texture"), &StyleBoxTexture::set_texture); - ClassDB::bind_method(D_METHOD("get_texture:Texture"), &StyleBoxTexture::get_texture); + ClassDB::bind_method(D_METHOD("set_texture", "texture"), &StyleBoxTexture::set_texture); + ClassDB::bind_method(D_METHOD("get_texture"), &StyleBoxTexture::get_texture); + + ClassDB::bind_method(D_METHOD("set_normal_map", "normal_map"), &StyleBoxTexture::set_normal_map); + ClassDB::bind_method(D_METHOD("get_normal_map"), &StyleBoxTexture::get_normal_map); ClassDB::bind_method(D_METHOD("set_margin_size", "margin", "size"), &StyleBoxTexture::set_margin_size); ClassDB::bind_method(D_METHOD("get_margin_size", "margin"), &StyleBoxTexture::get_margin_size); @@ -216,9 +268,16 @@ void StyleBoxTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("set_modulate", "color"), &StyleBoxTexture::set_modulate); ClassDB::bind_method(D_METHOD("get_modulate"), &StyleBoxTexture::get_modulate); + ClassDB::bind_method(D_METHOD("set_h_axis_stretch_mode", "mode"), &StyleBoxTexture::set_h_axis_stretch_mode); + ClassDB::bind_method(D_METHOD("get_h_axis_stretch_mode"), &StyleBoxTexture::get_h_axis_stretch_mode); + + ClassDB::bind_method(D_METHOD("set_v_axis_stretch_mode", "mode"), &StyleBoxTexture::set_v_axis_stretch_mode); + ClassDB::bind_method(D_METHOD("get_v_axis_stretch_mode"), &StyleBoxTexture::get_v_axis_stretch_mode); + ADD_SIGNAL(MethodInfo("texture_changed")); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_normal_map", "get_normal_map"); ADD_PROPERTYNZ(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect"); ADD_GROUP("Margin", "margin_"); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "margin_left", PROPERTY_HINT_RANGE, "0,2048,1"), "set_margin_size", "get_margin_size", MARGIN_LEFT); @@ -230,9 +289,16 @@ void StyleBoxTexture::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::REAL, "expand_margin_right", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin_size", "get_expand_margin_size", MARGIN_RIGHT); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "expand_margin_top", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin_size", "get_expand_margin_size", MARGIN_TOP); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "expand_margin_bottom", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin_size", "get_expand_margin_size", MARGIN_BOTTOM); + ADD_GROUP("Axis Stretch", "axis_stretch_"); + ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "axis_stretch_horizontal", PROPERTY_HINT_ENUM, "Stretch,Tile,Tile Fit"), "set_h_axis_stretch_mode", "get_h_axis_stretch_mode"); + ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "axis_stretch_vertical", PROPERTY_HINT_ENUM, "Stretch,Tile,Tile Fit"), "set_v_axis_stretch_mode", "get_v_axis_stretch_mode"); ADD_GROUP("Modulate", "modulate_"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "modulate_color"), "set_modulate", "get_modulate"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_center"), "set_draw_center", "get_draw_center"); + + BIND_CONSTANT(AXIS_STRETCH_MODE_STRETCH); + BIND_CONSTANT(AXIS_STRETCH_MODE_TILE); + BIND_CONSTANT(AXIS_STRETCH_MODE_TILE_FIT); } StyleBoxTexture::StyleBoxTexture() { @@ -243,6 +309,9 @@ StyleBoxTexture::StyleBoxTexture() { } draw_center = true; modulate = Color(1, 1, 1, 1); + + axis_h = AXIS_STRETCH_MODE_STRETCH; + axis_v = AXIS_STRETCH_MODE_STRETCH; } StyleBoxTexture::~StyleBoxTexture() { } @@ -255,137 +324,585 @@ void StyleBoxFlat::set_bg_color(const Color &p_color) { emit_changed(); } -void StyleBoxFlat::set_light_color(const Color &p_color) { +Color StyleBoxFlat::get_bg_color() const { - light_color = p_color; - emit_changed(); + return bg_color; } -void StyleBoxFlat::set_dark_color(const Color &p_color) { - dark_color = p_color; +void StyleBoxFlat::set_border_color_all(const Color &p_color) { + for (int i = 0; i < 4; i++) { + + border_color.write()[i] = p_color; + } emit_changed(); } +Color StyleBoxFlat::get_border_color_all() const { -Color StyleBoxFlat::get_bg_color() const { + return border_color[MARGIN_TOP]; +} +void StyleBoxFlat::set_border_color(Margin p_border, const Color &p_color) { - return bg_color; + border_color.write()[p_border] = p_color; + emit_changed(); } -Color StyleBoxFlat::get_light_color() const { +Color StyleBoxFlat::get_border_color(Margin p_border) const { - return light_color; + return border_color[p_border]; } -Color StyleBoxFlat::get_dark_color() const { - return dark_color; +void StyleBoxFlat::set_border_width_all(int p_size) { + border_width[0] = p_size; + border_width[1] = p_size; + border_width[2] = p_size; + border_width[3] = p_size; + emit_changed(); } +int StyleBoxFlat::get_border_width_min() const { -void StyleBoxFlat::set_border_size(int p_size) { + return MIN(MIN(border_width[0], border_width[1]), MIN(border_width[2], border_width[3])); +} - border_size = p_size; +void StyleBoxFlat::set_border_width(Margin p_margin, int p_width) { + border_width[p_margin] = p_width; emit_changed(); } -int StyleBoxFlat::get_border_size() const { - return border_size; +int StyleBoxFlat::get_border_width(Margin p_margin) const { + return border_width[p_margin]; } void StyleBoxFlat::set_border_blend(bool p_blend) { - blend = p_blend; + blend_border = p_blend; emit_changed(); } - bool StyleBoxFlat::get_border_blend() const { - return blend; + return blend_border; } -void StyleBoxFlat::set_draw_center(bool p_draw) { +void StyleBoxFlat::set_corner_radius_all(int radius) { + + for (int i = 0; i < 4; i++) { + corner_radius[i] = radius; + } - draw_center = p_draw; emit_changed(); } -bool StyleBoxFlat::get_draw_center() const { +void StyleBoxFlat::set_corner_radius_individual(const int radius_top_left, const int radius_top_right, const int radius_botton_right, const int radius_bottom_left) { + corner_radius[0] = radius_top_left; + corner_radius[1] = radius_top_right; + corner_radius[2] = radius_botton_right; + corner_radius[3] = radius_bottom_left; - return draw_center; + emit_changed(); +} +int StyleBoxFlat::get_corner_radius_min() const { + int smallest = corner_radius[0]; + for (int i = 1; i < 4; i++) { + if (smallest > corner_radius[i]) { + smallest = corner_radius[i]; + } + } + return smallest; +} + +void StyleBoxFlat::set_corner_radius(const Corner p_corner, const int radius) { + + corner_radius[p_corner] = radius; + emit_changed(); +} +int StyleBoxFlat::get_corner_radius(const Corner p_corner) const { + return corner_radius[p_corner]; +} + +void StyleBoxFlat::set_expand_margin_size(Margin p_expand_margin, float p_size) { + + expand_margin[p_expand_margin] = p_size; + emit_changed(); +} +float StyleBoxFlat::get_expand_margin_size(Margin p_expand_margin) const { + return expand_margin[p_expand_margin]; +} +void StyleBoxFlat::set_filled(bool p_filled) { + + filled = p_filled; + emit_changed(); +} +bool StyleBoxFlat::is_filled() const { + + return filled; +} + +void StyleBoxFlat::set_shadow_color(const Color &p_color) { + + shadow_color = p_color; + emit_changed(); } +Color StyleBoxFlat::get_shadow_color() const { + + return shadow_color; +} + +void StyleBoxFlat::set_shadow_size(const int &p_size) { + + shadow_size = p_size; + emit_changed(); +} +int StyleBoxFlat::get_shadow_size() const { + + return shadow_size; +} + +void StyleBoxFlat::set_anti_aliased(const bool &p_anti_aliased) { + anti_aliased = p_anti_aliased; + emit_changed(); +} +bool StyleBoxFlat::is_anti_aliased() const { + return anti_aliased; +} + +void StyleBoxFlat::set_aa_size(const int &p_aa_size) { + aa_size = p_aa_size; + emit_changed(); +} +int StyleBoxFlat::get_aa_size() const { + return aa_size; +} + +void StyleBoxFlat::set_corner_detail(const int &p_corner_detail) { + corner_detail = p_corner_detail; + emit_changed(); +} +int StyleBoxFlat::get_corner_detail() const { + return corner_detail; +} + Size2 StyleBoxFlat::get_center_size() const { return Size2(); } +inline void set_inner_corner_radius(const Rect2 style_rect, const Rect2 inner_rect, const int corner_radius[4], int *inner_corner_radius) { + int border_left = inner_rect.position.x - style_rect.position.x; + int border_top = inner_rect.position.y - style_rect.position.y; + int border_right = style_rect.size.width - inner_rect.size.width - border_left; + int border_bottom = style_rect.size.height - inner_rect.size.height - border_top; + + int rad; + //tl + rad = MIN(border_top, border_left); + inner_corner_radius[0] = MAX(corner_radius[0] - rad, 0); + + //tr + rad = MIN(border_top, border_bottom); + inner_corner_radius[1] = MAX(corner_radius[1] - rad, 0); + + //br + rad = MIN(border_bottom, border_right); + inner_corner_radius[2] = MAX(corner_radius[2] - rad, 0); + + //bl + rad = MIN(border_bottom, border_left); + inner_corner_radius[3] = MAX(corner_radius[3] - rad, 0); +} + +inline void draw_ring(Vector<Vector2> &verts, Vector<int> &indices, Vector<Color> &colors, const Rect2 style_rect, const int corner_radius[4], + const Rect2 ring_rect, const int border_width[4], const Color inner_color[4], const Color outer_color[4], const int corner_detail) { + + int vert_offset = verts.size(); + if (!vert_offset) { + vert_offset = 0; + } + int rings = (border_width[0] == 0 && border_width[1] == 0 && border_width[2] == 0 && border_width[3] == 0) ? 1 : 2; + rings = 2; + + int ring_corner_radius[4]; + set_inner_corner_radius(style_rect, ring_rect, corner_radius, ring_corner_radius); + + //corner radius center points + Vector<Point2> outer_points; + outer_points.push_back(ring_rect.position + Vector2(ring_corner_radius[0], ring_corner_radius[0])); //tl + outer_points.push_back(Point2(ring_rect.position.x + ring_rect.size.x - ring_corner_radius[1], ring_rect.position.y + ring_corner_radius[1])); //tr + outer_points.push_back(ring_rect.position + ring_rect.size - Vector2(ring_corner_radius[2], ring_corner_radius[2])); //br + outer_points.push_back(Point2(ring_rect.position.x + ring_corner_radius[3], ring_rect.position.y + ring_rect.size.y - ring_corner_radius[3])); //bl + + Rect2 inner_rect; + inner_rect = ring_rect.grow_individual(-border_width[MARGIN_LEFT], -border_width[MARGIN_TOP], -border_width[MARGIN_RIGHT], -border_width[MARGIN_BOTTOM]); + int inner_corner_radius[4]; + + Vector<Point2> inner_points; + set_inner_corner_radius(style_rect, inner_rect, corner_radius, inner_corner_radius); + inner_points.push_back(inner_rect.position + Vector2(inner_corner_radius[0], inner_corner_radius[0])); //tl + inner_points.push_back(Point2(inner_rect.position.x + inner_rect.size.x - inner_corner_radius[1], inner_rect.position.y + inner_corner_radius[1])); //tr + inner_points.push_back(inner_rect.position + inner_rect.size - Vector2(inner_corner_radius[2], inner_corner_radius[2])); //br + inner_points.push_back(Point2(inner_rect.position.x + inner_corner_radius[3], inner_rect.position.y + inner_rect.size.y - inner_corner_radius[3])); //bl + + //calculate the vert array + for (int corner_index = 0; corner_index < 4; corner_index++) { + for (int detail = 0; detail <= corner_detail; detail++) { + for (int inner_outer = (2 - rings); inner_outer < 2; inner_outer++) { + float radius; + Color color; + Point2 corner_point; + if (inner_outer == 0) { + radius = inner_corner_radius[corner_index]; + color = *inner_color; + corner_point = inner_points[corner_index]; + } else { + radius = ring_corner_radius[corner_index]; + color = *outer_color; + corner_point = outer_points[corner_index]; + } + float x = radius * (float)cos((double)corner_index * Math_PI / 2.0 + (double)detail / (double)corner_detail * Math_PI / 2.0 + Math_PI) + corner_point.x; + float y = radius * (float)sin((double)corner_index * Math_PI / 2.0 + (double)detail / (double)corner_detail * Math_PI / 2.0 + Math_PI) + corner_point.y; + verts.push_back(Vector2(x, y)); + colors.push_back(color); + } + } + } + + if (rings == 2) { + int vert_count = (corner_detail + 1) * 4 * rings; + //fill the indices and the colors for the border + for (int i = 0; i < vert_count; i++) { + //poly 1 + indices.push_back(vert_offset + ((i + 0) % vert_count)); + indices.push_back(vert_offset + ((i + 2) % vert_count)); + indices.push_back(vert_offset + ((i + 1) % vert_count)); + //poly 2 + indices.push_back(vert_offset + ((i + 1) % vert_count)); + indices.push_back(vert_offset + ((i + 2) % vert_count)); + indices.push_back(vert_offset + ((i + 3) % vert_count)); + } + } +} + +inline void adapt_values(int p_index_a, int p_index_b, int *adapted_values, const int *p_values, const real_t p_width, const int p_max_a, const int p_max_b) { + if (p_values[p_index_a] + p_values[p_index_b] > p_width) { + float factor; + int newValue; + + factor = (float)p_width / (float)(p_values[p_index_a] + p_values[p_index_b]); + + newValue = (int)(p_values[p_index_a] * factor); + if (newValue < adapted_values[p_index_a]) { + adapted_values[p_index_a] = newValue; + } + newValue = (int)(p_values[p_index_b] * factor); + if (newValue < adapted_values[p_index_b]) { + adapted_values[p_index_b] = newValue; + } + } else { + adapted_values[p_index_a] = MIN(p_values[p_index_a], adapted_values[p_index_a]); + adapted_values[p_index_b] = MIN(p_values[p_index_b], adapted_values[p_index_b]); + } + adapted_values[p_index_a] = MIN(p_max_a, adapted_values[p_index_a]); + adapted_values[p_index_b] = MIN(p_max_b, adapted_values[p_index_b]); +} void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const { - VisualServer *vs = VisualServer::get_singleton(); - Rect2i r = p_rect; + //PREPARATIONS + + bool rounded_corners = (corner_radius[0] > 0) || (corner_radius[1] > 0) || (corner_radius[2] > 0) || (corner_radius[3] > 0); + bool aa_on = rounded_corners && anti_aliased; - for (int i = 0; i < border_size; i++) { + Rect2 style_rect = p_rect.grow_individual(expand_margin[MARGIN_LEFT], expand_margin[MARGIN_TOP], expand_margin[MARGIN_RIGHT], expand_margin[MARGIN_BOTTOM]); + if (aa_on) { + style_rect = style_rect.grow(-((aa_size + 1) / 2)); + } + + //adapt borders (prevent weired overlapping/glitchy drawings) + int width = style_rect.size.width; + int height = style_rect.size.height; + int adapted_border[4] = { INT_MAX, INT_MAX, INT_MAX, INT_MAX }; + adapt_values(MARGIN_TOP, MARGIN_BOTTOM, adapted_border, border_width, height, height, height); + adapt_values(MARGIN_LEFT, MARGIN_RIGHT, adapted_border, border_width, width, width, width); - Color color_upleft = light_color; - Color color_downright = dark_color; + //adapt corners (prevent weired overlapping/glitchy drawings) + int adapted_corner[4] = { INT_MAX, INT_MAX, INT_MAX, INT_MAX }; + adapt_values(CORNER_TOP_RIGHT, CORNER_BOTTOM_RIGHT, adapted_corner, corner_radius, height, height - adapted_border[MARGIN_BOTTOM], height - adapted_border[MARGIN_TOP]); + adapt_values(CORNER_TOP_LEFT, CORNER_BOTTOM_LEFT, adapted_corner, corner_radius, height, height - adapted_border[MARGIN_BOTTOM], height - adapted_border[MARGIN_TOP]); + adapt_values(CORNER_TOP_LEFT, CORNER_TOP_RIGHT, adapted_corner, corner_radius, width, width - adapted_border[MARGIN_RIGHT], width - adapted_border[MARGIN_LEFT]); + adapt_values(CORNER_BOTTOM_LEFT, CORNER_BOTTOM_RIGHT, adapted_corner, corner_radius, width, width - adapted_border[MARGIN_RIGHT], width - adapted_border[MARGIN_LEFT]); - if (blend) { + Rect2 infill_rect = style_rect.grow_individual(-adapted_border[MARGIN_LEFT], -adapted_border[MARGIN_TOP], -adapted_border[MARGIN_RIGHT], -adapted_border[MARGIN_BOTTOM]); - color_upleft.r = (border_size - i) * color_upleft.r / border_size + i * bg_color.r / border_size; - color_upleft.g = (border_size - i) * color_upleft.g / border_size + i * bg_color.g / border_size; - color_upleft.b = (border_size - i) * color_upleft.b / border_size + i * bg_color.b / border_size; + Vector<Point2> verts; + Vector<int> indices; + Vector<Color> colors; + + //DRAWING + VisualServer *vs = VisualServer::get_singleton(); - color_downright.r = (border_size - i) * color_downright.r / border_size + i * bg_color.r / border_size; - color_downright.g = (border_size - i) * color_downright.g / border_size + i * bg_color.g / border_size; - color_downright.b = (border_size - i) * color_downright.b / border_size + i * bg_color.b / border_size; + //DRAW SHADOW + if (shadow_size > 0) { + int shadow_width[4] = { shadow_size, shadow_size, shadow_size, shadow_size }; + Color shadow_colors[4] = { shadow_color, shadow_color, shadow_color, shadow_color }; + Color shadow_colors_transparent[4]; + for (int i = 0; i < 4; i++) { + shadow_colors_transparent[i] = Color(shadow_color.r, shadow_color.g, shadow_color.b, 0); } + draw_ring(verts, indices, colors, style_rect, adapted_corner, + style_rect.grow(shadow_size), shadow_width, shadow_colors, shadow_colors_transparent, corner_detail); + } - vs->canvas_item_add_rect(p_canvas_item, Rect2(Point2i(r.pos.x, r.pos.y + r.size.y - 1), Size2(r.size.x, 1)), color_downright); - vs->canvas_item_add_rect(p_canvas_item, Rect2(Point2i(r.pos.x + r.size.x - 1, r.pos.y), Size2(1, r.size.y)), color_downright); + //DRAW border + Color bg_color_array[4] = { bg_color, bg_color, bg_color, bg_color }; + const Color *inner_color = ((blend_border) ? bg_color_array : border_color.read().ptr()); + draw_ring(verts, indices, colors, style_rect, adapted_corner, + style_rect, adapted_border, inner_color, border_color.read().ptr(), corner_detail); - vs->canvas_item_add_rect(p_canvas_item, Rect2(r.pos, Size2(r.size.x, 1)), color_upleft); - vs->canvas_item_add_rect(p_canvas_item, Rect2(r.pos, Size2(1, r.size.y)), color_upleft); + //DRAW INFILL + if (filled) { + int temp_vert_offset = verts.size(); + int no_border[4] = { 0, 0, 0, 0 }; + draw_ring(verts, indices, colors, style_rect, adapted_corner, + infill_rect, no_border, &bg_color, &bg_color, corner_detail); + int added_vert_count = verts.size() - temp_vert_offset; + //fill the indices and the colors for the center + for (int index = 0; index <= added_vert_count / 2; index += 2) { + int i = index; + //poly 1 + indices.push_back(temp_vert_offset + i); + indices.push_back(temp_vert_offset + added_vert_count - 4 - i); + indices.push_back(temp_vert_offset + i + 2); + //poly 1 + indices.push_back(temp_vert_offset + i); + indices.push_back(temp_vert_offset + added_vert_count - 2 - i); + indices.push_back(temp_vert_offset + added_vert_count - 4 - i); + } + } - r.pos.x++; - r.pos.y++; - r.size.x -= 2; - r.size.y -= 2; + if (aa_on) { + + //HELPER ARRAYS + Color border_color_alpha[4]; + for (int i = 0; i < 4; i++) { + Color c = border_color.read().ptr()[i]; + border_color_alpha[i] = Color(c.r, c.g, c.b, 0); + } + Color alpha_bg = Color(bg_color.r, bg_color.g, bg_color.b, 0); + Color bg_color_array_alpha[4] = { alpha_bg, alpha_bg, alpha_bg, alpha_bg }; + + int aa_border_width[4] = { aa_size, aa_size, aa_size, aa_size }; + + if (filled) { + if (!blend_border) { + //INFILL AA + draw_ring(verts, indices, colors, style_rect, adapted_corner, + infill_rect.grow(aa_size), aa_border_width, bg_color_array, bg_color_array_alpha, corner_detail); + } + } else if (!(border_width[0] == 0 && border_width[1] == 0 && border_width[2] == 0 && border_width[3] == 0)) { + //DRAW INNER BORDER AA + draw_ring(verts, indices, colors, style_rect, adapted_corner, + infill_rect, aa_border_width, border_color_alpha, border_color.read().ptr(), corner_detail); + } + //DRAW OUTER BORDER AA + if (!(border_width[0] == 0 && border_width[1] == 0 && border_width[2] == 0 && border_width[3] == 0)) { + draw_ring(verts, indices, colors, style_rect, adapted_corner, + style_rect.grow(aa_size), aa_border_width, border_color.read().ptr(), border_color_alpha, corner_detail); + } } - if (draw_center) - vs->canvas_item_add_rect(p_canvas_item, Rect2(r.pos, r.size), bg_color); + vs->canvas_item_add_triangle_array(p_canvas_item, indices, verts, colors); } float StyleBoxFlat::get_style_margin(Margin p_margin) const { - - return border_size; + return border_width[p_margin]; } void StyleBoxFlat::_bind_methods() { ClassDB::bind_method(D_METHOD("set_bg_color", "color"), &StyleBoxFlat::set_bg_color); ClassDB::bind_method(D_METHOD("get_bg_color"), &StyleBoxFlat::get_bg_color); - ClassDB::bind_method(D_METHOD("set_light_color", "color"), &StyleBoxFlat::set_light_color); - ClassDB::bind_method(D_METHOD("get_light_color"), &StyleBoxFlat::get_light_color); - ClassDB::bind_method(D_METHOD("set_dark_color", "color"), &StyleBoxFlat::set_dark_color); - ClassDB::bind_method(D_METHOD("get_dark_color"), &StyleBoxFlat::get_dark_color); - ClassDB::bind_method(D_METHOD("set_border_size", "size"), &StyleBoxFlat::set_border_size); - ClassDB::bind_method(D_METHOD("get_border_size"), &StyleBoxFlat::get_border_size); + + ClassDB::bind_method(D_METHOD("set_border_color", "color"), &StyleBoxFlat::set_border_color_all); + ClassDB::bind_method(D_METHOD("get_border_color", "color"), &StyleBoxFlat::get_border_color_all); + + ClassDB::bind_method(D_METHOD("set_border_width_all", "width"), &StyleBoxFlat::set_border_width_all); + ClassDB::bind_method(D_METHOD("get_border_width_min"), &StyleBoxFlat::get_border_width_min); + + ClassDB::bind_method(D_METHOD("set_border_width", "margin", "width"), &StyleBoxFlat::set_border_width); + ClassDB::bind_method(D_METHOD("get_border_width", "margin"), &StyleBoxFlat::get_border_width); + ClassDB::bind_method(D_METHOD("set_border_blend", "blend"), &StyleBoxFlat::set_border_blend); ClassDB::bind_method(D_METHOD("get_border_blend"), &StyleBoxFlat::get_border_blend); - ClassDB::bind_method(D_METHOD("set_draw_center", "size"), &StyleBoxFlat::set_draw_center); - ClassDB::bind_method(D_METHOD("get_draw_center"), &StyleBoxFlat::get_draw_center); + + ClassDB::bind_method(D_METHOD("set_corner_radius_individual", "radius_top_left", "radius_top_right", "radius_botton_right", "radius_bottom_left"), &StyleBoxFlat::set_corner_radius_individual); + ClassDB::bind_method(D_METHOD("set_corner_radius_all", "radius"), &StyleBoxFlat::set_corner_radius_all); + + ClassDB::bind_method(D_METHOD("set_corner_radius", "corner", "radius"), &StyleBoxFlat::set_corner_radius); + ClassDB::bind_method(D_METHOD("get_corner_radius", "corner"), &StyleBoxFlat::get_corner_radius); + + ClassDB::bind_method(D_METHOD("set_expand_margin", "margin", "size"), &StyleBoxFlat::set_expand_margin_size); + ClassDB::bind_method(D_METHOD("get_expand_margin", "margin"), &StyleBoxFlat::get_expand_margin_size); + + ClassDB::bind_method(D_METHOD("set_filled", "filled"), &StyleBoxFlat::set_filled); + ClassDB::bind_method(D_METHOD("is_filled"), &StyleBoxFlat::is_filled); + + ClassDB::bind_method(D_METHOD("set_shadow_color", "color"), &StyleBoxFlat::set_shadow_color); + ClassDB::bind_method(D_METHOD("get_shadow_color"), &StyleBoxFlat::get_shadow_color); + + ClassDB::bind_method(D_METHOD("set_shadow_size", "size"), &StyleBoxFlat::set_shadow_size); + ClassDB::bind_method(D_METHOD("get_shadow_size"), &StyleBoxFlat::get_shadow_size); + + ClassDB::bind_method(D_METHOD("set_anti_aliased", "anti_aliased"), &StyleBoxFlat::set_anti_aliased); + ClassDB::bind_method(D_METHOD("is_anti_aliased"), &StyleBoxFlat::is_anti_aliased); + + ClassDB::bind_method(D_METHOD("set_aa_size", "size"), &StyleBoxFlat::set_aa_size); + ClassDB::bind_method(D_METHOD("get_aa_size"), &StyleBoxFlat::get_aa_size); + + ClassDB::bind_method(D_METHOD("set_corner_detail", "detail"), &StyleBoxFlat::set_corner_detail); + ClassDB::bind_method(D_METHOD("get_corner_detail"), &StyleBoxFlat::get_corner_detail); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "bg_color"), "set_bg_color", "get_bg_color"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "light_color"), "set_light_color", "get_light_color"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "dark_color"), "set_dark_color", "get_dark_color"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "border_size", PROPERTY_HINT_RANGE, "0,4096"), "set_border_size", "get_border_size"); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filled"), "set_filled", "is_filled"); + + ADD_GROUP("Border Width", "border_width_"); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_left", PROPERTY_HINT_RANGE, "0,1024,1"), "set_border_width", "get_border_width", MARGIN_LEFT); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_top", PROPERTY_HINT_RANGE, "0,1024,1"), "set_border_width", "get_border_width", MARGIN_TOP); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_right", PROPERTY_HINT_RANGE, "0,1024,1"), "set_border_width", "get_border_width", MARGIN_RIGHT); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_bottom", PROPERTY_HINT_RANGE, "0,1024,1"), "set_border_width", "get_border_width", MARGIN_BOTTOM); + + ADD_GROUP("Border", "border_"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "border_color"), "set_border_color", "get_border_color"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "border_blend"), "set_border_blend", "get_border_blend"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_bg"), "set_draw_center", "get_draw_center"); + + ADD_GROUP("Corner Radius", "corner_radius_"); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_top_left", PROPERTY_HINT_RANGE, "0,1024,1"), "set_corner_radius", "get_corner_radius", CORNER_TOP_LEFT); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_top_right", PROPERTY_HINT_RANGE, "0,1024,1"), "set_corner_radius", "get_corner_radius", CORNER_TOP_RIGHT); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_bottom_right", PROPERTY_HINT_RANGE, "0,1024,1"), "set_corner_radius", "get_corner_radius", CORNER_BOTTOM_RIGHT); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_bottom_left", PROPERTY_HINT_RANGE, "0,1024,1"), "set_corner_radius", "get_corner_radius", CORNER_BOTTOM_LEFT); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "corner_detail"), "set_corner_detail", "get_corner_detail"); + + ADD_GROUP("Expand Margin", "expand_margin_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "expand_margin_left", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin", "get_expand_margin", MARGIN_LEFT); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "expand_margin_right", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin", "get_expand_margin", MARGIN_RIGHT); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "expand_margin_top", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin", "get_expand_margin", MARGIN_TOP); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "expand_margin_bottom", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin", "get_expand_margin", MARGIN_BOTTOM); + + ADD_GROUP("Shadow", "shadow_"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color"), "set_shadow_color", "get_shadow_color"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_size"), "set_shadow_size", "get_shadow_size"); + + ADD_GROUP("Anti Aliasing", "anti_aliasing_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "anti_aliasing"), "set_anti_aliased", "is_anti_aliased"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "anti_aliasing_size", PROPERTY_HINT_RANGE, "1,5,1"), "set_aa_size", "get_aa_size"); } StyleBoxFlat::StyleBoxFlat() { bg_color = Color(0.6, 0.6, 0.6); - light_color = Color(0.8, 0.8, 0.8); - dark_color = Color(0.8, 0.8, 0.8); - draw_center = true; - blend = true; - border_size = 0; + shadow_color = Color(0, 0, 0, 0.6); + + border_color.append(Color(0.8, 0.8, 0.8)); + border_color.append(Color(0.8, 0.8, 0.8)); + border_color.append(Color(0.8, 0.8, 0.8)); + border_color.append(Color(0.8, 0.8, 0.8)); + + blend_border = false; + filled = true; + anti_aliased = true; + + shadow_size = 0; + corner_detail = 8; + aa_size = 1; + + border_width[0] = 0; + border_width[1] = 0; + border_width[2] = 0; + border_width[3] = 0; + + expand_margin[0] = 0; + expand_margin[1] = 0; + expand_margin[2] = 0; + expand_margin[3] = 0; + + corner_radius[0] = 0; + corner_radius[1] = 0; + corner_radius[2] = 0; + corner_radius[3] = 0; } StyleBoxFlat::~StyleBoxFlat() { } + +void StyleBoxLine::set_color(const Color &p_color) { + color = p_color; + emit_changed(); +} +Color StyleBoxLine::get_color() const { + return color; +} + +void StyleBoxLine::set_thickness(int p_thickness) { + thickness = p_thickness; + emit_changed(); +} +int StyleBoxLine::get_thickness() const { + return thickness; +} + +void StyleBoxLine::set_vertical(bool p_vertical) { + vertical = p_vertical; +} +bool StyleBoxLine::is_vertical() const { + return vertical; +} + +void StyleBoxLine::set_grow(float p_grow) { + grow = p_grow; + emit_changed(); +} +float StyleBoxLine::get_grow() const { + return grow; +} + +void StyleBoxLine::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_color", "color"), &StyleBoxLine::set_color); + ClassDB::bind_method(D_METHOD("get_color"), &StyleBoxLine::get_color); + ClassDB::bind_method(D_METHOD("set_thickness", "thickness"), &StyleBoxLine::set_thickness); + ClassDB::bind_method(D_METHOD("get_thickness"), &StyleBoxLine::get_thickness); + ClassDB::bind_method(D_METHOD("set_grow", "grow"), &StyleBoxLine::set_grow); + ClassDB::bind_method(D_METHOD("get_grow"), &StyleBoxLine::get_grow); + ClassDB::bind_method(D_METHOD("set_vertical", "vertical"), &StyleBoxLine::set_vertical); + ClassDB::bind_method(D_METHOD("is_vertical"), &StyleBoxLine::is_vertical); + + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "thickness", PROPERTY_HINT_RANGE, "0,10"), "set_thickness", "get_thickness"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vertical"), "set_vertical", "is_vertical"); +} +float StyleBoxLine::get_style_margin(Margin p_margin) const { + return thickness; +} +Size2 StyleBoxLine::get_center_size() const { + return Size2(); +} + +void StyleBoxLine::draw(RID p_canvas_item, const Rect2 &p_rect) const { + VisualServer *vs = VisualServer::get_singleton(); + Rect2i r = p_rect; + + if (vertical) { + r.position.y -= grow; + r.size.y += grow * 2; + r.size.x = thickness; + } else { + r.position.x -= grow; + r.size.x += grow * 2; + r.size.y = thickness; + } + + vs->canvas_item_add_rect(p_canvas_item, r, color); +} + +StyleBoxLine::StyleBoxLine() { + grow = 1.0; + thickness = 1; + color = Color(0.0, 0.0, 0.0); + vertical = false; +} +StyleBoxLine::~StyleBoxLine() {} diff --git a/scene/resources/style_box.h b/scene/resources/style_box.h index f0107ed71..a750fae75 100644 --- a/scene/resources/style_box.h +++ b/scene/resources/style_box.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -38,7 +39,7 @@ class StyleBox : public Resource { GDCLASS(StyleBox, Resource); - RES_BASE_EXTENSION("sbx"); + RES_BASE_EXTENSION("stylebox"); OBJ_SAVE_TYPE(StyleBox); float margin[4]; @@ -76,12 +77,23 @@ class StyleBoxTexture : public StyleBox { GDCLASS(StyleBoxTexture, StyleBox); +public: + enum AxisStretchMode { + AXIS_STRETCH_MODE_STRETCH, + AXIS_STRETCH_MODE_TILE, + AXIS_STRETCH_MODE_TILE_FIT, + }; + +private: float expand_margin[4]; float margin[4]; Rect2 region_rect; Ref<Texture> texture; + Ref<Texture> normal_map; bool draw_center; Color modulate; + AxisStretchMode axis_h; + AxisStretchMode axis_v; protected: virtual float get_style_margin(Margin p_margin) const; @@ -100,10 +112,19 @@ public: void set_texture(RES p_texture); RES get_texture() const; + void set_normal_map(RES p_normal_map); + RES get_normal_map() const; + void set_draw_center(bool p_draw); bool get_draw_center() const; virtual Size2 get_center_size() const; + void set_h_axis_stretch_mode(AxisStretchMode p_mode); + AxisStretchMode get_h_axis_stretch_mode() const; + + void set_v_axis_stretch_mode(AxisStretchMode p_mode); + AxisStretchMode get_v_axis_stretch_mode() const; + void set_modulate(const Color &p_modulate); Color get_modulate() const; @@ -113,40 +134,88 @@ public: ~StyleBoxTexture(); }; +VARIANT_ENUM_CAST(StyleBoxTexture::AxisStretchMode) + class StyleBoxFlat : public StyleBox { GDCLASS(StyleBoxFlat, StyleBox); Color bg_color; - Color light_color; - Color dark_color; + Color shadow_color; + PoolVector<Color> border_color; - int border_size; + int border_width[4]; + int expand_margin[4]; + int corner_radius[4]; - bool draw_center; - bool blend; + bool filled; + bool blend_border; + bool anti_aliased; + + int corner_detail; + int shadow_size; + int aa_size; protected: virtual float get_style_margin(Margin p_margin) const; static void _bind_methods(); public: + //Color void set_bg_color(const Color &p_color); - void set_light_color(const Color &p_color); - void set_dark_color(const Color &p_color); - Color get_bg_color() const; - Color get_light_color() const; - Color get_dark_color() const; - void set_border_size(int p_size); - int get_border_size() const; + //Border Color + void set_border_color_all(const Color &p_color); + Color get_border_color_all() const; + void set_border_color(Margin p_border, const Color &p_color); + Color get_border_color(Margin p_border) const; + + //BORDER + //width + void set_border_width_all(int p_size); + int get_border_width_min() const; + void set_border_width(Margin p_margin, int p_size); + int get_border_width(Margin p_margin) const; + + //blend void set_border_blend(bool p_blend); bool get_border_blend() const; - void set_draw_center(bool p_draw); - bool get_draw_center() const; + //CORNER + void set_corner_radius_all(int radius); + void set_corner_radius_individual(const int radius_top_left, const int radius_top_right, const int radius_botton_right, const int radius_bottom_left); + int get_corner_radius_min() const; + + void set_corner_radius(Corner p_corner, const int radius); + int get_corner_radius(Corner p_corner) const; + + void set_corner_detail(const int &p_corner_detail); + int get_corner_detail() const; + + //EXPANDS + void set_expand_margin_size(Margin p_expand_margin, float p_size); + float get_expand_margin_size(Margin p_expand_margin) const; + + //FILLED + void set_filled(bool p_draw); + bool is_filled() const; + + //SHADOW + void set_shadow_color(const Color &p_color); + Color get_shadow_color() const; + + void set_shadow_size(const int &p_size); + int get_shadow_size() const; + + //ANTI_ALIASING + void set_anti_aliased(const bool &p_anit_aliasing); + bool is_anti_aliased() const; + //tempAA + void set_aa_size(const int &p_aa_size); + int get_aa_size() const; + virtual Size2 get_center_size() const; virtual void draw(RID p_canvas_item, const Rect2 &p_rect) const; @@ -155,4 +224,38 @@ public: ~StyleBoxFlat(); }; +// just used to draw lines. +class StyleBoxLine : public StyleBox { + + GDCLASS(StyleBoxLine, StyleBox); + Color color; + int thickness; + bool vertical; + float grow; + +protected: + virtual float get_style_margin(Margin p_margin) const; + static void _bind_methods(); + +public: + void set_color(const Color &p_color); + Color get_color() const; + + void set_thickness(int p_thickness); + int get_thickness() const; + + void set_vertical(bool p_vertical); + bool is_vertical() const; + + void set_grow(float p_grow); + float get_grow() const; + + virtual Size2 get_center_size() const; + + virtual void draw(RID p_canvas_item, const Rect2 &p_rect) const; + + StyleBoxLine(); + ~StyleBoxLine(); +}; + #endif diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index 7564735cf..932067601 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -27,41 +28,41 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "surface_tool.h" -#include "method_bind_ext.inc" +#include "method_bind_ext.gen.inc" #define _VERTEX_SNAP 0.0001 #define EQ_VERTEX_DIST 0.00001 -bool SurfaceTool::Vertex::operator==(const Vertex &p_b) const { +bool SurfaceTool::Vertex::operator==(const Vertex &p_vertex) const { - if (vertex != p_b.vertex) + if (vertex != p_vertex.vertex) return false; - if (uv != p_b.uv) + if (uv != p_vertex.uv) return false; - if (uv2 != p_b.uv2) + if (uv2 != p_vertex.uv2) return false; - if (normal != p_b.normal) + if (normal != p_vertex.normal) return false; - if (binormal != p_b.binormal) + if (binormal != p_vertex.binormal) return false; - if (color != p_b.color) + if (color != p_vertex.color) return false; - if (bones.size() != p_b.bones.size()) + if (bones.size() != p_vertex.bones.size()) return false; for (int i = 0; i < bones.size(); i++) { - if (bones[i] != p_b.bones[i]) + if (bones[i] != p_vertex.bones[i]) return false; } for (int i = 0; i < weights.size(); i++) { - if (weights[i] != p_b.weights[i]) + if (weights[i] != p_vertex.weights[i]) return false; } @@ -223,30 +224,22 @@ void SurfaceTool::add_index(int p_index) { index_array.push_back(p_index); } -Ref<Mesh> SurfaceTool::commit(const Ref<Mesh> &p_existing) { - - Ref<Mesh> mesh; - if (p_existing.is_valid()) - mesh = p_existing; - else - mesh = Ref<Mesh>(memnew(Mesh)); +Array SurfaceTool::commit_to_arrays() { int varr_len = vertex_array.size(); - if (varr_len == 0) - return mesh; - - int surface = mesh->get_surface_count(); - Array a; a.resize(Mesh::ARRAY_MAX); for (int i = 0; i < Mesh::ARRAY_MAX; i++) { - switch (format & (1 << i)) { + if (!(format & (1 << i))) + continue; //not in format - case Mesh::ARRAY_FORMAT_VERTEX: - case Mesh::ARRAY_FORMAT_NORMAL: { + switch (i) { + + case Mesh::ARRAY_VERTEX: + case Mesh::ARRAY_NORMAL: { PoolVector<Vector3> array; array.resize(varr_len); @@ -272,8 +265,8 @@ Ref<Mesh> SurfaceTool::commit(const Ref<Mesh> &p_existing) { } break; - case Mesh::ARRAY_FORMAT_TEX_UV: - case Mesh::ARRAY_FORMAT_TEX_UV2: { + case Mesh::ARRAY_TEX_UV: + case Mesh::ARRAY_TEX_UV2: { PoolVector<Vector2> array; array.resize(varr_len); @@ -298,7 +291,7 @@ Ref<Mesh> SurfaceTool::commit(const Ref<Mesh> &p_existing) { w = PoolVector<Vector2>::Write(); a[i] = array; } break; - case Mesh::ARRAY_FORMAT_TANGENT: { + case Mesh::ARRAY_TANGENT: { PoolVector<float> array; array.resize(varr_len * 4); @@ -322,7 +315,7 @@ Ref<Mesh> SurfaceTool::commit(const Ref<Mesh> &p_existing) { a[i] = array; } break; - case Mesh::ARRAY_FORMAT_COLOR: { + case Mesh::ARRAY_COLOR: { PoolVector<Color> array; array.resize(varr_len); @@ -338,7 +331,7 @@ Ref<Mesh> SurfaceTool::commit(const Ref<Mesh> &p_existing) { w = PoolVector<Color>::Write(); a[i] = array; } break; - case Mesh::ARRAY_FORMAT_BONES: { + case Mesh::ARRAY_BONES: { PoolVector<int> array; array.resize(varr_len * 4); @@ -360,7 +353,7 @@ Ref<Mesh> SurfaceTool::commit(const Ref<Mesh> &p_existing) { a[i] = array; } break; - case Mesh::ARRAY_FORMAT_WEIGHTS: { + case Mesh::ARRAY_WEIGHTS: { PoolVector<float> array; array.resize(varr_len * 4); @@ -382,7 +375,7 @@ Ref<Mesh> SurfaceTool::commit(const Ref<Mesh> &p_existing) { a[i] = array; } break; - case Mesh::ARRAY_FORMAT_INDEX: { + case Mesh::ARRAY_INDEX: { ERR_CONTINUE(index_array.size() == 0); @@ -397,6 +390,7 @@ Ref<Mesh> SurfaceTool::commit(const Ref<Mesh> &p_existing) { } w = PoolVector<int>::Write(); + a[i] = array; } break; @@ -404,6 +398,26 @@ Ref<Mesh> SurfaceTool::commit(const Ref<Mesh> &p_existing) { } } + return a; +} + +Ref<ArrayMesh> SurfaceTool::commit(const Ref<ArrayMesh> &p_existing) { + + Ref<ArrayMesh> mesh; + if (p_existing.is_valid()) + mesh = p_existing; + else + mesh.instance(); + + int varr_len = vertex_array.size(); + + if (varr_len == 0) + return mesh; + + int surface = mesh->get_surface_count(); + + Array a = commit_to_arrays(); + mesh->add_surface_from_arrays(primitive, a); if (material.is_valid()) mesh->surface_set_material(surface, material); @@ -458,12 +472,17 @@ void SurfaceTool::deindex() { vertex_array.push_back(varr[E->get()]); } format &= ~Mesh::ARRAY_FORMAT_INDEX; + index_array.clear(); } void SurfaceTool::_create_list(const Ref<Mesh> &p_existing, int p_surface, List<Vertex> *r_vertex, List<int> *r_index, int &lformat) { Array arr = p_existing->surface_get_arrays(p_surface); ERR_FAIL_COND(arr.size() != VS::ARRAY_MAX); + _create_list_from_arrays(arr, r_vertex, r_index, lformat); +} + +void SurfaceTool::_create_list_from_arrays(Array arr, List<Vertex> *r_vertex, List<int> *r_index, int &lformat) { PoolVector<Vector3> varr = arr[VS::ARRAY_VERTEX]; PoolVector<Vector3> narr = arr[VS::ARRAY_NORMAL]; @@ -535,7 +554,7 @@ void SurfaceTool::_create_list(const Ref<Mesh> &p_existing, int p_surface, List< if (lformat & VS::ARRAY_FORMAT_TANGENT) { Plane p(tarr[i * 4 + 0], tarr[i * 4 + 1], tarr[i * 4 + 2], tarr[i * 4 + 3]); v.tangent = p.normal; - v.binormal = p.normal.cross(last_normal).normalized() * p.d; + v.binormal = p.normal.cross(v.tangent).normalized() * p.d; } if (lformat & VS::ARRAY_FORMAT_COLOR) v.color = carr[i]; @@ -579,6 +598,13 @@ void SurfaceTool::_create_list(const Ref<Mesh> &p_existing, int p_surface, List< } } +void SurfaceTool::create_from_triangle_arrays(const Array &p_arrays) { + + clear(); + primitive = Mesh::PRIMITIVE_TRIANGLES; + _create_list_from_arrays(p_arrays, &vertex_array, &index_array, format); +} + void SurfaceTool::create_from(const Ref<Mesh> &p_existing, int p_surface) { clear(); @@ -710,8 +736,9 @@ void SurfaceTool::generate_tangents() { ERR_FAIL_COND(!res); format |= Mesh::ARRAY_FORMAT_TANGENT; - if (indexed) + if (indexed) { index(); + } } void SurfaceTool::generate_normals() { @@ -783,7 +810,6 @@ void SurfaceTool::generate_normals() { vertex_hash.clear(); if (E) { smooth = smooth_groups[count]; - print_line("SMOOTH AT " + itos(count) + ": " + itos(smooth)); } } } @@ -811,11 +837,13 @@ void SurfaceTool::clear() { index_array.clear(); vertex_array.clear(); smooth_groups.clear(); + material.unref(); } void SurfaceTool::_bind_methods() { ClassDB::bind_method(D_METHOD("begin", "primitive"), &SurfaceTool::begin); + ClassDB::bind_method(D_METHOD("add_vertex", "vertex"), &SurfaceTool::add_vertex); ClassDB::bind_method(D_METHOD("add_color", "color"), &SurfaceTool::add_color); ClassDB::bind_method(D_METHOD("add_normal", "normal"), &SurfaceTool::add_normal); @@ -825,15 +853,25 @@ void SurfaceTool::_bind_methods() { ClassDB::bind_method(D_METHOD("add_bones", "bones"), &SurfaceTool::add_bones); ClassDB::bind_method(D_METHOD("add_weights", "weights"), &SurfaceTool::add_weights); ClassDB::bind_method(D_METHOD("add_smooth_group", "smooth"), &SurfaceTool::add_smooth_group); + ClassDB::bind_method(D_METHOD("add_triangle_fan", "vertexes", "uvs", "colors", "uv2s", "normals", "tangents"), &SurfaceTool::add_triangle_fan, DEFVAL(Vector<Vector2>()), DEFVAL(Vector<Color>()), DEFVAL(Vector<Vector2>()), DEFVAL(Vector<Vector3>()), DEFVAL(Vector<Plane>())); - ClassDB::bind_method(D_METHOD("set_material", "material:Material"), &SurfaceTool::set_material); + + ClassDB::bind_method(D_METHOD("add_index", "index"), &SurfaceTool::add_index); + ClassDB::bind_method(D_METHOD("index"), &SurfaceTool::index); ClassDB::bind_method(D_METHOD("deindex"), &SurfaceTool::deindex); - ///ClassDB::bind_method(D_METHOD("generate_flat_normals"),&SurfaceTool::generate_flat_normals); ClassDB::bind_method(D_METHOD("generate_normals"), &SurfaceTool::generate_normals); - ClassDB::bind_method(D_METHOD("add_index", "index"), &SurfaceTool::add_index); - ClassDB::bind_method(D_METHOD("commit:Mesh", "existing:Mesh"), &SurfaceTool::commit, DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("generate_tangents"), &SurfaceTool::generate_tangents); + + ClassDB::bind_method(D_METHOD("add_to_format", "flags"), &SurfaceTool::add_to_format); + + ClassDB::bind_method(D_METHOD("set_material", "material"), &SurfaceTool::set_material); + ClassDB::bind_method(D_METHOD("clear"), &SurfaceTool::clear); + + ClassDB::bind_method(D_METHOD("create_from", "existing", "surface"), &SurfaceTool::create_from); + ClassDB::bind_method(D_METHOD("append_from", "existing", "surface", "transform"), &SurfaceTool::append_from); + ClassDB::bind_method(D_METHOD("commit", "existing"), &SurfaceTool::commit, DEFVAL(Variant())); } SurfaceTool::SurfaceTool() { diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h index 542c21e7b..fcc94753c 100644 --- a/scene/resources/surface_tool.h +++ b/scene/resources/surface_tool.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,9 +30,10 @@ #ifndef SURFACE_TOOL_H #define SURFACE_TOOL_H -#include "mikktspace.h" #include "scene/resources/mesh.h" +#include "thirdparty/misc/mikktspace.h" + class SurfaceTool : public Reference { GDCLASS(SurfaceTool, Reference); @@ -78,6 +80,7 @@ private: Vector<float> last_weights; Plane last_tangent; + void _create_list_from_arrays(Array arr, List<Vertex> *r_vertex, List<int> *r_index, int &lformat); void _create_list(const Ref<Mesh> &p_existing, int p_surface, List<Vertex> *r_vertex, List<int> *r_index, int &lformat); //mikktspace callbacks @@ -99,8 +102,8 @@ public: void add_normal(const Vector3 &p_normal); void add_tangent(const Plane &p_tangent); void add_uv(const Vector2 &p_uv); - void add_uv2(const Vector2 &p_uv); - void add_bones(const Vector<int> &p_indices); + void add_uv2(const Vector2 &p_uv2); + void add_bones(const Vector<int> &p_bones); void add_weights(const Vector<float> &p_weights); void add_smooth_group(bool p_smooth); @@ -121,9 +124,11 @@ public: List<Vertex> &get_vertex_array() { return vertex_array; } + void create_from_triangle_arrays(const Array &p_arrays); + Array commit_to_arrays(); void create_from(const Ref<Mesh> &p_existing, int p_surface); void append_from(const Ref<Mesh> &p_existing, int p_surface, const Transform &p_xform); - Ref<Mesh> commit(const Ref<Mesh> &p_existing = Ref<Mesh>()); + Ref<ArrayMesh> commit(const Ref<ArrayMesh> &p_existing = Ref<ArrayMesh>()); SurfaceTool(); }; diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index d08fc2634..9a251c029 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -27,7 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "texture.h" +#include "core/method_bind_ext.gen.inc" #include "core/os/os.h" +#include "core_string_names.h" #include "io/image_loader.h" Size2 Texture::get_size() const { @@ -35,17 +38,20 @@ Size2 Texture::get_size() const { return Size2(get_width(), get_height()); } -void Texture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose) const { +void Texture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { - VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, get_size()), get_rid(), false, p_modulate, p_transpose); + RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); + VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, get_size()), get_rid(), false, p_modulate, p_transpose, normal_rid); } -void Texture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) const { +void Texture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { - VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, get_rid(), p_tile, p_modulate, p_transpose); + RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); + VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, get_rid(), p_tile, p_modulate, p_transpose, normal_rid); } -void Texture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose) const { +void Texture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map, bool p_clip_uv) const { - VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, get_rid(), p_src_rect, p_modulate, p_transpose); + RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); + VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, get_rid(), p_src_rect, p_modulate, p_transpose, normal_rid, p_clip_uv); } bool Texture::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const { @@ -64,9 +70,10 @@ void Texture::_bind_methods() { ClassDB::bind_method(D_METHOD("has_alpha"), &Texture::has_alpha); ClassDB::bind_method(D_METHOD("set_flags", "flags"), &Texture::set_flags); ClassDB::bind_method(D_METHOD("get_flags"), &Texture::get_flags); - ClassDB::bind_method(D_METHOD("draw", "canvas_item", "pos", "modulate", "transpose"), &Texture::draw, DEFVAL(Color(1, 1, 1)), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("draw_rect", "canvas_item", "rect", "tile", "modulate", "transpose"), &Texture::draw_rect, DEFVAL(Color(1, 1, 1)), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("draw_rect_region", "canvas_item", "rect", "src_rect", "modulate", "transpose"), &Texture::draw_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("draw", "canvas_item", "pos", "modulate", "transpose", "normal_map"), &Texture::draw, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("draw_rect", "canvas_item", "rect", "tile", "modulate", "transpose", "normal_map"), &Texture::draw_rect, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("draw_rect_region", "canvas_item", "rect", "src_rect", "modulate", "transpose", "normal_map", "clip_uv"), &Texture::draw_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("get_data"), &Texture::get_data); BIND_CONSTANT(FLAG_MIPMAPS); BIND_CONSTANT(FLAG_REPEAT); @@ -85,14 +92,15 @@ Texture::Texture() { void ImageTexture::reload_from_file() { - String path = get_path(); + String path = ResourceLoader::path_remap(get_path()); if (!path.is_resource_file()) return; uint32_t flags = get_flags(); - Image img; + Ref<Image> img; + img.instance(); - Error err = ImageLoader::load_image(path, &img); + Error err = ImageLoader::load_image(path, img); ERR_FAIL_COND(err != OK); create_from_image(img, flags); @@ -100,7 +108,7 @@ void ImageTexture::reload_from_file() { bool ImageTexture::_set(const StringName &p_name, const Variant &p_value) { - if (p_name == "image" && p_value.get_type() == Variant::IMAGE) + if (p_name == "image") create_from_image(p_value, flags); else if (p_name == "flags") if (w * h == 0) @@ -154,7 +162,7 @@ void ImageTexture::_get_property_list(List<PropertyInfo> *p_list) const { } p_list->push_back(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Mipmaps,Repeat,Filter,Anisotropic,sRGB,Mirrored Repeat")); - p_list->push_back(PropertyInfo(Variant::IMAGE, "image", img_hint, String::num(lossy_storage_quality))); + p_list->push_back(PropertyInfo(Variant::OBJECT, "image", PROPERTY_HINT_RESOURCE_TYPE, "Image")); p_list->push_back(PropertyInfo(Variant::VECTOR2, "size", PROPERTY_HINT_NONE, "")); p_list->push_back(PropertyInfo(Variant::INT, "storage", PROPERTY_HINT_ENUM, "Uncompressed,Compress Lossy,Compress Lossless")); p_list->push_back(PropertyInfo(Variant::REAL, "lossy_quality", PROPERTY_HINT_RANGE, "0.0,1.0,0.01")); @@ -166,8 +174,9 @@ void ImageTexture::_reload_hook(const RID &p_hook) { if (!path.is_resource_file()) return; - Image img; - Error err = ImageLoader::load_image(path, &img); + Ref<Image> img; + img.instance(); + Error err = ImageLoader::load_image(path, img); ERR_FAIL_COND(err != OK); @@ -184,14 +193,15 @@ void ImageTexture::create(int p_width, int p_height, Image::Format p_format, uin w = p_width; h = p_height; } -void ImageTexture::create_from_image(const Image &p_image, uint32_t p_flags) { +void ImageTexture::create_from_image(const Ref<Image> &p_image, uint32_t p_flags) { + ERR_FAIL_COND(p_image.is_null()); flags = p_flags; - w = p_image.get_width(); - h = p_image.get_height(); - format = p_image.get_format(); + w = p_image->get_width(); + h = p_image->get_height(); + format = p_image->get_format(); - VisualServer::get_singleton()->texture_allocate(texture, p_image.get_width(), p_image.get_height(), p_image.get_format(), p_flags); + VisualServer::get_singleton()->texture_allocate(texture, p_image->get_width(), p_image->get_height(), p_image->get_format(), p_flags); VisualServer::get_singleton()->texture_set_data(texture, p_image); _change_notify(); } @@ -219,12 +229,13 @@ Image::Format ImageTexture::get_format() const { void ImageTexture::load(const String &p_path) { - Image img; - img.load(p_path); + Ref<Image> img; + img.instance(); + img->load(p_path); create_from_image(img); } -void ImageTexture::set_data(const Image &p_image) { +void ImageTexture::set_data(const Ref<Image> &p_image) { VisualServer::get_singleton()->texture_set_data(texture, p_image); @@ -236,7 +247,7 @@ void ImageTexture::_resource_path_changed() { String path = get_path(); } -Image ImageTexture::get_data() const { +Ref<Image> ImageTexture::get_data() const { return VisualServer::get_singleton()->texture_get_data(texture); } @@ -256,64 +267,31 @@ RID ImageTexture::get_rid() const { return texture; } -void ImageTexture::fix_alpha_edges() { - - if (format == Image::FORMAT_RGBA8 /*&& !(flags&FLAG_CUBEMAP)*/) { - - Image img = get_data(); - img.fix_alpha_edges(); - set_data(img); - } -} - -void ImageTexture::premultiply_alpha() { - - if (format == Image::FORMAT_RGBA8 /*&& !(flags&FLAG_CUBEMAP)*/) { - - Image img = get_data(); - img.premultiply_alpha(); - set_data(img); - } -} - -void ImageTexture::normal_to_xy() { - - Image img = get_data(); - img.normalmap_to_xy(); - create_from_image(img, flags); -} - -void ImageTexture::shrink_x2_and_keep_size() { - - Size2 sizeov = get_size(); - Image img = get_data(); - img.resize(img.get_width() / 2, img.get_height() / 2, Image::INTERPOLATE_BILINEAR); - create_from_image(img, flags); - set_size_override(sizeov); -} - bool ImageTexture::has_alpha() const { return (format == Image::FORMAT_LA8 || format == Image::FORMAT_RGBA8); } -void ImageTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose) const { +void ImageTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { if ((w | h) == 0) return; - VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, Size2(w, h)), texture, false, p_modulate, p_transpose); + RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); + VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, Size2(w, h)), texture, false, p_modulate, p_transpose, normal_rid); } -void ImageTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) const { +void ImageTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { if ((w | h) == 0) return; - VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, texture, p_tile, p_modulate, p_transpose); + RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); + VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, texture, p_tile, p_modulate, p_transpose, normal_rid); } -void ImageTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose) const { +void ImageTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map, bool p_clip_uv) const { if ((w | h) == 0) return; - VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose); + RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); + VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose, normal_rid, p_clip_uv); } void ImageTexture::set_size_override(const Size2 &p_size) { @@ -357,7 +335,8 @@ float ImageTexture::get_lossy_storage_quality() const { void ImageTexture::_set_data(Dictionary p_data) { - Image img = p_data["image"]; + Ref<Image> img = p_data["image"]; + ERR_FAIL_COND(!img.is_valid()); uint32_t flags = p_data["flags"]; create_from_image(img, flags); @@ -375,21 +354,12 @@ void ImageTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("get_format"), &ImageTexture::get_format); ClassDB::bind_method(D_METHOD("load", "path"), &ImageTexture::load); ClassDB::bind_method(D_METHOD("set_data", "image"), &ImageTexture::set_data); - ClassDB::bind_method(D_METHOD("get_data", "cube_side"), &ImageTexture::get_data); ClassDB::bind_method(D_METHOD("set_storage", "mode"), &ImageTexture::set_storage); ClassDB::bind_method(D_METHOD("get_storage"), &ImageTexture::get_storage); ClassDB::bind_method(D_METHOD("set_lossy_storage_quality", "quality"), &ImageTexture::set_lossy_storage_quality); ClassDB::bind_method(D_METHOD("get_lossy_storage_quality"), &ImageTexture::get_lossy_storage_quality); - ClassDB::bind_method(D_METHOD("fix_alpha_edges"), &ImageTexture::fix_alpha_edges); - ClassDB::bind_method(D_METHOD("premultiply_alpha"), &ImageTexture::premultiply_alpha); - ClassDB::bind_method(D_METHOD("normal_to_xy"), &ImageTexture::normal_to_xy); - ClassDB::bind_method(D_METHOD("shrink_x2_and_keep_size"), &ImageTexture::shrink_x2_and_keep_size); ClassDB::bind_method(D_METHOD("set_size_override", "size"), &ImageTexture::set_size_override); - ClassDB::set_method_flags(get_class_static(), _scs_create("fix_alpha_edges"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); - ClassDB::set_method_flags(get_class_static(), _scs_create("premultiply_alpha"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); - ClassDB::set_method_flags(get_class_static(), _scs_create("normal_to_xy"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); - ClassDB::set_method_flags(get_class_static(), _scs_create("shrink_x2_and_keep_size"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); ClassDB::bind_method(D_METHOD("_reload_hook", "rid"), &ImageTexture::_reload_hook); BIND_CONSTANT(STORAGE_RAW); @@ -429,8 +399,17 @@ void StreamTexture::_requested_srgb(void *p_ud) { request_srgb_callback(stex); } +void StreamTexture::_requested_normal(void *p_ud) { + + StreamTexture *st = (StreamTexture *)p_ud; + Ref<StreamTexture> stex(st); + ERR_FAIL_COND(!request_normal_callback); + request_normal_callback(stex); +} + StreamTexture::TextureFormatRequestCallback StreamTexture::request_3d_callback = NULL; StreamTexture::TextureFormatRequestCallback StreamTexture::request_srgb_callback = NULL; +StreamTexture::TextureFormatRequestCallback StreamTexture::request_normal_callback = NULL; uint32_t StreamTexture::get_flags() const { @@ -441,7 +420,9 @@ Image::Format StreamTexture::get_format() const { return format; } -Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &flags, Image &image, int p_size_limit) { +Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &flags, Ref<Image> &image, int p_size_limit) { + + ERR_FAIL_COND_V(image.is_null(), ERR_INVALID_PARAMETER); FileAccess *f = FileAccess::open(p_path, FileAccess::READ); ERR_FAIL_COND_V(!f, ERR_CANT_OPEN); @@ -458,27 +439,38 @@ Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &fla flags = f->get_32(); //texture flags! uint32_t df = f->get_32(); //data format +/* print_line("width: " + itos(tw)); print_line("height: " + itos(th)); print_line("flags: " + itos(flags)); print_line("df: " + itos(df)); + */ +#ifdef TOOLS_ENABLED if (request_3d_callback && df & FORMAT_BIT_DETECT_3D) { - print_line("request detect 3D at " + p_path); + //print_line("request detect 3D at " + p_path); VS::get_singleton()->texture_set_detect_3d_callback(texture, _requested_3d, this); } else { - print_line("not requesting detect 3D at " + p_path); + //print_line("not requesting detect 3D at " + p_path); VS::get_singleton()->texture_set_detect_3d_callback(texture, NULL, NULL); } if (request_srgb_callback && df & FORMAT_BIT_DETECT_SRGB) { - print_line("request detect srgb at " + p_path); + //print_line("request detect srgb at " + p_path); VS::get_singleton()->texture_set_detect_srgb_callback(texture, _requested_srgb, this); } else { + //print_line("not requesting detect srgb at " + p_path); VS::get_singleton()->texture_set_detect_srgb_callback(texture, NULL, NULL); - print_line("not requesting detect srgb at " + p_path); } + if (request_srgb_callback && df & FORMAT_BIT_DETECT_NORMAL) { + //print_line("request detect srgb at " + p_path); + VS::get_singleton()->texture_set_detect_normal_callback(texture, _requested_normal, this); + } else { + //print_line("not requesting detect normal at " + p_path); + VS::get_singleton()->texture_set_detect_normal_callback(texture, NULL, NULL); + } +#endif if (!(df & FORMAT_BIT_STREAM)) { p_size_limit = 0; } @@ -492,7 +484,7 @@ Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &fla uint32_t mipmaps = f->get_32(); uint32_t size = f->get_32(); - print_line("mipmaps: " + itos(mipmaps)); + //print_line("mipmaps: " + itos(mipmaps)); while (mipmaps > 1 && p_size_limit > 0 && (sw > p_size_limit || sh > p_size_limit)) { @@ -506,7 +498,7 @@ Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &fla } //mipmaps need to be read independently, they will be later combined - Vector<Image> mipmap_images; + Vector<Ref<Image> > mipmap_images; int total_size = 0; for (int i = 0; i < mipmaps; i++) { @@ -522,23 +514,24 @@ Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &fla f->get_buffer(w.ptr(), size); } - Image img; + Ref<Image> img; if (df & FORMAT_BIT_LOSSLESS) { img = Image::lossless_unpacker(pv); } else { img = Image::lossy_unpacker(pv); } - if (img.empty()) { + if (img.is_null() || img->empty()) { memdelete(f); - ERR_FAIL_COND_V(img.empty(), ERR_FILE_CORRUPT); + ERR_FAIL_COND_V(img.is_null() || img->empty(), ERR_FILE_CORRUPT); } - total_size += img.get_data().size(); + + total_size += img->get_data().size(); mipmap_images.push_back(img); } - print_line("mipmap read total: " + itos(mipmap_images.size())); + //print_line("mipmap read total: " + itos(mipmap_images.size())); memdelete(f); //no longer needed @@ -557,7 +550,7 @@ Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &fla int ofs = 0; for (int i = 0; i < mipmap_images.size(); i++) { - PoolVector<uint8_t> id = mipmap_images[i].get_data(); + PoolVector<uint8_t> id = mipmap_images[i]->get_data(); int len = id.size(); PoolVector<uint8_t>::Read r = id.read(); copymem(&w[ofs], r.ptr(), len); @@ -565,7 +558,7 @@ Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &fla } } - image = Image(sw, sh, true, mipmap_images[0].get_format(), img_data); + image->create(sw, sh, true, mipmap_images[0]->get_format(), img_data); return OK; } @@ -588,7 +581,7 @@ Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &fla memdelete(f); - image = Image(tw, th, false, format, img_data); + image->create(tw, th, false, format, img_data); return OK; } else { @@ -625,7 +618,7 @@ Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &fla { PoolVector<uint8_t>::Write w = img_data.write(); int bytes = f->get_buffer(w.ptr(), total_size - ofs); - print_line("requested read: " + itos(total_size - ofs) + " but got: " + itos(bytes)); + //print_line("requested read: " + itos(total_size - ofs) + " but got: " + itos(bytes)); memdelete(f); @@ -634,7 +627,7 @@ Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &fla } } - image = Image(sw, sh, true, format, img_data); + image->create(sw, sh, true, format, img_data); return OK; } @@ -646,19 +639,20 @@ Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &fla Error StreamTexture::load(const String &p_path) { int lw, lh, lflags; - Image image; + Ref<Image> image; + image.instance(); Error err = _load_data(p_path, lw, lh, lflags, image); if (err) return err; - VS::get_singleton()->texture_allocate(texture, image.get_width(), image.get_height(), image.get_format(), lflags); + VS::get_singleton()->texture_allocate(texture, image->get_width(), image->get_height(), image->get_format(), lflags); VS::get_singleton()->texture_set_data(texture, image); w = lw; h = lh; flags = lflags; path_to_file = p_path; - format = image.get_format(); + format = image->get_format(); return OK; } @@ -680,23 +674,26 @@ RID StreamTexture::get_rid() const { return texture; } -void StreamTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose) const { +void StreamTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { if ((w | h) == 0) return; - VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, Size2(w, h)), texture, false, p_modulate, p_transpose); + RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); + VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, Size2(w, h)), texture, false, p_modulate, p_transpose, normal_rid); } -void StreamTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) const { +void StreamTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { if ((w | h) == 0) return; - VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, texture, p_tile, p_modulate, p_transpose); + RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); + VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, texture, p_tile, p_modulate, p_transpose, normal_rid); } -void StreamTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose) const { +void StreamTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map, bool p_clip_uv) const { if ((w | h) == 0) return; - VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose); + RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); + VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose, normal_rid, p_clip_uv); } bool StreamTexture::has_alpha() const { @@ -704,7 +701,7 @@ bool StreamTexture::has_alpha() const { return false; } -Image StreamTexture::get_data() const { +Ref<Image> StreamTexture::get_data() const { return VS::get_singleton()->texture_get_data(texture); } @@ -714,13 +711,16 @@ void StreamTexture::set_flags(uint32_t p_flags) { void StreamTexture::reload_from_file() { -#ifdef TOOLS_ENABLED - String ipath = get_import_path(); - if (ipath.is_resource_file() && ipath != path_to_file) { - path_to_file = ipath; - } -#endif - load(path_to_file); + String path = get_path(); + if (!path.is_resource_file()) + return; + + path = ResourceLoader::path_remap(path); //remap for translation + path = ResourceLoader::import_remap(path); //remap for import + if (!path.is_resource_file()) + return; + + load(path); } void StreamTexture::_bind_methods() { @@ -831,7 +831,7 @@ void AtlasTexture::set_atlas(const Ref<Texture> &p_atlas) { return; atlas = p_atlas; emit_changed(); - emit_signal("atlas_changed"); + _change_notify("atlas"); } Ref<Texture> AtlasTexture::get_atlas() const { @@ -840,8 +840,11 @@ Ref<Texture> AtlasTexture::get_atlas() const { void AtlasTexture::set_region(const Rect2 &p_region) { + if (region == p_region) + return; region = p_region; emit_changed(); + _change_notify("region"); } Rect2 AtlasTexture::get_region() const { @@ -851,8 +854,11 @@ Rect2 AtlasTexture::get_region() const { void AtlasTexture::set_margin(const Rect2 &p_margin) { + if (margin == p_margin) + return; margin = p_margin; emit_changed(); + _change_notify("margin"); } Rect2 AtlasTexture::get_margin() const { @@ -862,8 +868,8 @@ Rect2 AtlasTexture::get_margin() const { void AtlasTexture::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_atlas", "atlas:Texture"), &AtlasTexture::set_atlas); - ClassDB::bind_method(D_METHOD("get_atlas:Texture"), &AtlasTexture::get_atlas); + ClassDB::bind_method(D_METHOD("set_atlas", "atlas"), &AtlasTexture::set_atlas); + ClassDB::bind_method(D_METHOD("get_atlas"), &AtlasTexture::get_atlas); ClassDB::bind_method(D_METHOD("set_region", "region"), &AtlasTexture::set_region); ClassDB::bind_method(D_METHOD("get_region"), &AtlasTexture::get_region); @@ -871,14 +877,12 @@ void AtlasTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("set_margin", "margin"), &AtlasTexture::set_margin); ClassDB::bind_method(D_METHOD("get_margin"), &AtlasTexture::get_margin); - ADD_SIGNAL(MethodInfo("atlas_changed")); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "atlas", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_atlas", "get_atlas"); ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region"), "set_region", "get_region"); ADD_PROPERTY(PropertyInfo(Variant::RECT2, "margin"), "set_margin", "get_margin"); } -void AtlasTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose) const { +void AtlasTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { Rect2 rc = region; @@ -893,10 +897,11 @@ void AtlasTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_m rc.size.height = atlas->get_height(); } - VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(p_pos + margin.pos, rc.size), atlas->get_rid(), rc, p_modulate, p_transpose); + RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); + VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(p_pos + margin.position, rc.size), atlas->get_rid(), rc, p_modulate, p_transpose, normal_rid); } -void AtlasTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) const { +void AtlasTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { Rect2 rc = region; @@ -912,11 +917,12 @@ void AtlasTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile } Vector2 scale = p_rect.size / (region.size + margin.size); - Rect2 dr(p_rect.pos + margin.pos * scale, rc.size * scale); + Rect2 dr(p_rect.position + margin.position * scale, rc.size * scale); - VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), rc, p_modulate, p_transpose); + RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); + VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), rc, p_modulate, p_transpose, normal_rid); } -void AtlasTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose) const { +void AtlasTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map, bool p_clip_uv) const { //this might not necessarily work well if using a rect, needs to be fixed properly Rect2 rc = region; @@ -925,26 +931,27 @@ void AtlasTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, cons return; Rect2 src = p_src_rect; - src.pos += (rc.pos - margin.pos); + src.position += (rc.position - margin.position); Rect2 src_c = rc.clip(src); if (src_c.size == Size2()) return; - Vector2 ofs = (src_c.pos - src.pos); + Vector2 ofs = (src_c.position - src.position); Vector2 scale = p_rect.size / p_src_rect.size; if (scale.x < 0) { - float mx = (margin.size.width - margin.pos.x); - mx -= margin.pos.x; + float mx = (margin.size.width - margin.position.x); + mx -= margin.position.x; ofs.x = -(ofs.x + mx); } if (scale.y < 0) { - float my = margin.size.height - margin.pos.y; - my -= margin.pos.y; + float my = margin.size.height - margin.position.y; + my -= margin.position.y; ofs.y = -(ofs.y + my); } - Rect2 dr(p_rect.pos + ofs * scale, src_c.size * scale); + Rect2 dr(p_rect.position + ofs * scale, src_c.size * scale); - VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), src_c, p_modulate, p_transpose); + RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); + VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), src_c, p_modulate, p_transpose, normal_rid, p_clip_uv); } bool AtlasTexture::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const { @@ -955,24 +962,24 @@ bool AtlasTexture::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, return false; Rect2 src = p_src_rect; - src.pos += (rc.pos - margin.pos); + src.position += (rc.position - margin.position); Rect2 src_c = rc.clip(src); if (src_c.size == Size2()) return false; - Vector2 ofs = (src_c.pos - src.pos); + Vector2 ofs = (src_c.position - src.position); Vector2 scale = p_rect.size / p_src_rect.size; if (scale.x < 0) { - float mx = (margin.size.width - margin.pos.x); - mx -= margin.pos.x; + float mx = (margin.size.width - margin.position.x); + mx -= margin.position.x; ofs.x = -(ofs.x + mx); } if (scale.y < 0) { - float my = margin.size.height - margin.pos.y; - my -= margin.pos.y; + float my = margin.size.height - margin.position.y; + my -= margin.position.y; ofs.y = -(ofs.y + my); } - Rect2 dr(p_rect.pos + ofs * scale, src_c.size * scale); + Rect2 dr(p_rect.position + ofs * scale, src_c.size * scale); r_rect = dr; r_src_rect = src_c; @@ -1093,15 +1100,15 @@ Ref<Texture> LargeTexture::get_piece_texture(int p_idx) const { void LargeTexture::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_piece", "ofs", "texture:Texture"), &LargeTexture::add_piece); + ClassDB::bind_method(D_METHOD("add_piece", "ofs", "texture"), &LargeTexture::add_piece); ClassDB::bind_method(D_METHOD("set_piece_offset", "idx", "ofs"), &LargeTexture::set_piece_offset); - ClassDB::bind_method(D_METHOD("set_piece_texture", "idx", "texture:Texture"), &LargeTexture::set_piece_texture); + ClassDB::bind_method(D_METHOD("set_piece_texture", "idx", "texture"), &LargeTexture::set_piece_texture); ClassDB::bind_method(D_METHOD("set_size", "size"), &LargeTexture::set_size); ClassDB::bind_method(D_METHOD("clear"), &LargeTexture::clear); ClassDB::bind_method(D_METHOD("get_piece_count"), &LargeTexture::get_piece_count); ClassDB::bind_method(D_METHOD("get_piece_offset", "idx"), &LargeTexture::get_piece_offset); - ClassDB::bind_method(D_METHOD("get_piece_texture:Texture", "idx"), &LargeTexture::get_piece_texture); + ClassDB::bind_method(D_METHOD("get_piece_texture", "idx"), &LargeTexture::get_piece_texture); ClassDB::bind_method(D_METHOD("_set_data", "data"), &LargeTexture::_set_data); ClassDB::bind_method(D_METHOD("_get_data"), &LargeTexture::_get_data); @@ -1109,16 +1116,16 @@ void LargeTexture::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_data", "_get_data"); } -void LargeTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose) const { +void LargeTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { for (int i = 0; i < pieces.size(); i++) { // TODO - pieces[i].texture->draw(p_canvas_item, pieces[i].offset + p_pos, p_modulate, p_transpose); + pieces[i].texture->draw(p_canvas_item, pieces[i].offset + p_pos, p_modulate, p_transpose, p_normal_map); } } -void LargeTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) const { +void LargeTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { //tiling not supported for this if (size.x == 0 || size.y == 0) @@ -1126,13 +1133,14 @@ void LargeTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile Size2 scale = p_rect.size / size; + RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); for (int i = 0; i < pieces.size(); i++) { // TODO - pieces[i].texture->draw_rect(p_canvas_item, Rect2(pieces[i].offset * scale + p_rect.pos, pieces[i].texture->get_size() * scale), false, p_modulate, p_transpose); + pieces[i].texture->draw_rect(p_canvas_item, Rect2(pieces[i].offset * scale + p_rect.position, pieces[i].texture->get_size() * scale), false, p_modulate, p_transpose, p_normal_map); } } -void LargeTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose) const { +void LargeTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map, bool p_clip_uv) const { //tiling not supported for this if (p_src_rect.size.x == 0 || p_src_rect.size.y == 0) @@ -1140,6 +1148,7 @@ void LargeTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, cons Size2 scale = p_rect.size / p_src_rect.size; + RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); for (int i = 0; i < pieces.size(); i++) { // TODO @@ -1149,9 +1158,9 @@ void LargeTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, cons Rect2 local = p_src_rect.clip(rect); Rect2 target = local; target.size *= scale; - target.pos = p_rect.pos + (p_src_rect.pos + rect.pos) * scale; - local.pos -= rect.pos; - pieces[i].texture->draw_rect_region(p_canvas_item, target, local, p_modulate, p_transpose); + target.position = p_rect.position + (p_src_rect.position + rect.position) * scale; + local.position -= rect.position; + pieces[i].texture->draw_rect_region(p_canvas_item, target, local, p_modulate, p_transpose, p_normal_map, false); } } @@ -1172,25 +1181,25 @@ uint32_t CubeMap::get_flags() const { return flags; } -void CubeMap::set_side(Side p_side, const Image &p_image) { +void CubeMap::set_side(Side p_side, const Ref<Image> &p_image) { - ERR_FAIL_COND(p_image.empty()); + ERR_FAIL_COND(p_image->empty()); ERR_FAIL_INDEX(p_side, 6); if (!_is_valid()) { - format = p_image.get_format(); - w = p_image.get_width(); - h = p_image.get_height(); - VS::get_singleton()->texture_allocate(cubemap, w, h, p_image.get_format(), flags | VS::TEXTURE_FLAG_CUBEMAP); + format = p_image->get_format(); + w = p_image->get_width(); + h = p_image->get_height(); + VS::get_singleton()->texture_allocate(cubemap, w, h, p_image->get_format(), flags | VS::TEXTURE_FLAG_CUBEMAP); } VS::get_singleton()->texture_set_data(cubemap, p_image, VS::CubeMapSide(p_side)); valid[p_side] = true; } -Image CubeMap::get_side(Side p_side) const { +Ref<Image> CubeMap::get_side(Side p_side) const { if (!valid[p_side]) - return Image(); + return Ref<Image>(); return VS::get_singleton()->texture_get_data(cubemap, VS::CubeMapSide(p_side)); } @@ -1303,14 +1312,12 @@ void CubeMap::_get_property_list(List<PropertyInfo> *p_list) const { } p_list->push_back(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Mipmaps,Repeat,Filter")); - p_list->push_back(PropertyInfo(Variant::IMAGE, "side/left", img_hint, String::num(lossy_storage_quality))); - p_list->push_back(PropertyInfo(Variant::IMAGE, "side/right", img_hint, String::num(lossy_storage_quality))); - p_list->push_back(PropertyInfo(Variant::IMAGE, "side/bottom", img_hint, String::num(lossy_storage_quality))); - p_list->push_back(PropertyInfo(Variant::IMAGE, "side/top", img_hint, String::num(lossy_storage_quality))); - p_list->push_back(PropertyInfo(Variant::IMAGE, "side/front", img_hint, String::num(lossy_storage_quality))); - p_list->push_back(PropertyInfo(Variant::IMAGE, "side/back", img_hint, String::num(lossy_storage_quality))); - p_list->push_back(PropertyInfo(Variant::INT, "storage", PROPERTY_HINT_ENUM, "Uncompressed,Compress Lossy,Compress Lossless", PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::REAL, "lossy_quality", PROPERTY_HINT_RANGE, "0.0,1.0,0.01")); + p_list->push_back(PropertyInfo(Variant::OBJECT, "side/left", PROPERTY_HINT_RESOURCE_TYPE, "Image")); + p_list->push_back(PropertyInfo(Variant::OBJECT, "side/right", PROPERTY_HINT_RESOURCE_TYPE, "Image")); + p_list->push_back(PropertyInfo(Variant::OBJECT, "side/bottom", PROPERTY_HINT_RESOURCE_TYPE, "Image")); + p_list->push_back(PropertyInfo(Variant::OBJECT, "side/top", PROPERTY_HINT_RESOURCE_TYPE, "Image")); + p_list->push_back(PropertyInfo(Variant::OBJECT, "side/front", PROPERTY_HINT_RESOURCE_TYPE, "Image")); + p_list->push_back(PropertyInfo(Variant::OBJECT, "side/back", PROPERTY_HINT_RESOURCE_TYPE, "Image")); } void CubeMap::_bind_methods() { @@ -1367,3 +1374,209 @@ CubeMap::~CubeMap() { BIND_CONSTANT( CUBEMAP_FRONT ); BIND_CONSTANT( CUBEMAP_BACK ); */ +/////////////////////////// + +void CurveTexture::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_width", "width"), &CurveTexture::set_width); + + ClassDB::bind_method(D_METHOD("set_curve", "curve"), &CurveTexture::set_curve); + ClassDB::bind_method(D_METHOD("get_curve"), &CurveTexture::get_curve); + + ClassDB::bind_method(D_METHOD("_update"), &CurveTexture::_update); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "32,4096"), "set_width", "get_width"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve", "get_curve"); +} + +void CurveTexture::set_width(int p_width) { + + ERR_FAIL_COND(p_width < 32 || p_width > 4096); + _width = p_width; + _update(); +} + +int CurveTexture::get_width() const { + + return _width; +} + +void CurveTexture::ensure_default_setup(float p_min, float p_max) { + if (_curve.is_null()) { + Ref<Curve> curve = Ref<Curve>(memnew(Curve)); + curve->add_point(Vector2(0, 1)); + curve->add_point(Vector2(1, 1)); + curve->set_min_value(p_min); + curve->set_max_value(p_max); + set_curve(curve); + // Min and max is 0..1 by default + } +} + +void CurveTexture::set_curve(Ref<Curve> p_curve) { + if (_curve != p_curve) { + if (_curve.is_valid()) { + _curve->disconnect(CoreStringNames::get_singleton()->changed, this, "_update"); + } + _curve = p_curve; + if (_curve.is_valid()) { + _curve->connect(CoreStringNames::get_singleton()->changed, this, "_update"); + } + _update(); + } +} + +void CurveTexture::_update() { + + PoolVector<uint8_t> data; + data.resize(_width * sizeof(float)); + + // The array is locked in that scope + { + PoolVector<uint8_t>::Write wd8 = data.write(); + float *wd = (float *)wd8.ptr(); + + if (_curve.is_valid()) { + Curve &curve = **_curve; + for (int i = 0; i < _width; ++i) { + float t = i / static_cast<float>(_width); + wd[i] = curve.interpolate_baked(t); + } + + } else { + for (int i = 0; i < _width; ++i) { + wd[i] = 0; + } + } + } + + Ref<Image> image = memnew(Image(_width, 1, false, Image::FORMAT_RF, data)); + + VS::get_singleton()->texture_allocate(_texture, _width, 1, Image::FORMAT_RF, VS::TEXTURE_FLAG_FILTER); + VS::get_singleton()->texture_set_data(_texture, image); + + emit_changed(); +} + +Ref<Curve> CurveTexture::get_curve() const { + + return _curve; +} + +RID CurveTexture::get_rid() const { + + return _texture; +} + +CurveTexture::CurveTexture() { + _width = 2048; + _texture = VS::get_singleton()->texture_create(); +} +CurveTexture::~CurveTexture() { + VS::get_singleton()->free(_texture); +} +////////////////// + +//setter and getter names for property serialization +#define COLOR_RAMP_GET_OFFSETS "get_offsets" +#define COLOR_RAMP_GET_COLORS "get_colors" +#define COLOR_RAMP_SET_OFFSETS "set_offsets" +#define COLOR_RAMP_SET_COLORS "set_colors" + +GradientTexture::GradientTexture() { + update_pending = false; + width = 2048; + + texture = VS::get_singleton()->texture_create(); + _queue_update(); +} + +GradientTexture::~GradientTexture() { + VS::get_singleton()->free(texture); +} + +void GradientTexture::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_gradient", "gradient"), &GradientTexture::set_gradient); + ClassDB::bind_method(D_METHOD("get_gradient"), &GradientTexture::get_gradient); + + ClassDB::bind_method(D_METHOD("set_width", "width"), &GradientTexture::set_width); + + ClassDB::bind_method(D_METHOD("_update"), &GradientTexture::_update); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gradient", PROPERTY_HINT_RESOURCE_TYPE, "Gradient"), "set_gradient", "get_gradient"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "width"), "set_width", "get_width"); +} + +void GradientTexture::set_gradient(Ref<Gradient> p_gradient) { + if (p_gradient == gradient) + return; + if (gradient.is_valid()) { + gradient->disconnect(CoreStringNames::get_singleton()->changed, this, "_update"); + } + gradient = p_gradient; + if (gradient.is_valid()) { + gradient->connect(CoreStringNames::get_singleton()->changed, this, "_update"); + } + _update(); + emit_changed(); +} + +Ref<Gradient> GradientTexture::get_gradient() const { + return gradient; +} + +void GradientTexture::_queue_update() { + + if (update_pending) + return; + + call_deferred("_update"); +} + +void GradientTexture::_update() { + + if (gradient.is_null()) + return; + + update_pending = false; + + PoolVector<uint8_t> data; + data.resize(width * 4); + { + PoolVector<uint8_t>::Write wd8 = data.write(); + Gradient &g = **gradient; + + for (int i = 0; i < width; i++) { + + float ofs = float(i) / (width - 1); + Color color = g.get_color_at_offset(ofs); + + wd8[i * 4 + 0] = uint8_t(CLAMP(color.r * 255.0, 0, 255)); + wd8[i * 4 + 1] = uint8_t(CLAMP(color.g * 255.0, 0, 255)); + wd8[i * 4 + 2] = uint8_t(CLAMP(color.b * 255.0, 0, 255)); + wd8[i * 4 + 3] = uint8_t(CLAMP(color.a * 255.0, 0, 255)); + } + } + + Ref<Image> image = memnew(Image(width, 1, false, Image::FORMAT_RGBA8, data)); + + VS::get_singleton()->texture_allocate(texture, width, 1, Image::FORMAT_RGBA8, VS::TEXTURE_FLAG_FILTER); + VS::get_singleton()->texture_set_data(texture, image); + + emit_changed(); +} + +void GradientTexture::set_width(int p_width) { + + width = p_width; + _queue_update(); +} +int GradientTexture::get_width() const { + + return width; +} + +Ref<Image> GradientTexture::get_data() const { + return VisualServer::get_singleton()->texture_get_data(texture); +} diff --git a/scene/resources/texture.h b/scene/resources/texture.h index 0092fee83..6c20c71af 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,9 +30,11 @@ #ifndef TEXTURE_H #define TEXTURE_H +#include "curve.h" #include "io/resource_loader.h" #include "math_2d.h" #include "resource.h" +#include "scene/resources/color_ramp.h" #include "servers/visual_server.h" /** @@ -67,12 +70,12 @@ public: virtual void set_flags(uint32_t p_flags) = 0; virtual uint32_t get_flags() const = 0; - virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const; - virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const; - virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const; + virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; + virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; + virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = true) const; virtual bool get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const; - virtual Image get_data() const { return Image(); } + virtual Ref<Image> get_data() const { return Ref<Image>(); } Texture(); }; @@ -115,14 +118,14 @@ protected: public: void create(int p_width, int p_height, Image::Format p_format, uint32_t p_flags = FLAGS_DEFAULT); - void create_from_image(const Image &p_image, uint32_t p_flags = FLAGS_DEFAULT); + void create_from_image(const Ref<Image> &p_image, uint32_t p_flags = FLAGS_DEFAULT); void set_flags(uint32_t p_flags); uint32_t get_flags() const; Image::Format get_format() const; void load(const String &p_path); - void set_data(const Image &p_image); - Image get_data() const; + void set_data(const Ref<Image> &p_image); + Ref<Image> get_data() const; int get_width() const; int get_height() const; @@ -130,20 +133,15 @@ public: virtual RID get_rid() const; bool has_alpha() const; - virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const; - virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const; - virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const; + virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; + virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; + virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = true) const; void set_storage(Storage p_storage); Storage get_storage() const; void set_lossy_storage_quality(float p_lossy_storage_quality); float get_lossy_storage_quality() const; - void fix_alpha_edges(); - void premultiply_alpha(); - void normal_to_xy(); - void shrink_x2_and_keep_size(); - void set_size_override(const Size2 &p_size); virtual void set_path(const String &p_path, bool p_take_over = false); @@ -171,10 +169,11 @@ public: FORMAT_BIT_HAS_MIPMAPS = 1 << 23, FORMAT_BIT_DETECT_3D = 1 << 24, FORMAT_BIT_DETECT_SRGB = 1 << 25, + FORMAT_BIT_DETECT_NORMAL = 1 << 26, }; private: - Error _load_data(const String &p_path, int &tw, int &th, int &flags, Image &image, int p_size_limit = 0); + Error _load_data(const String &p_path, int &tw, int &th, int &flags, Ref<Image> &image, int p_size_limit = 0); String path_to_file; RID texture; Image::Format format; @@ -185,6 +184,7 @@ private: static void _requested_3d(void *p_ud); static void _requested_srgb(void *p_ud); + static void _requested_normal(void *p_ud); protected: static void _bind_methods(); @@ -194,6 +194,7 @@ public: static TextureFormatRequestCallback request_3d_callback; static TextureFormatRequestCallback request_srgb_callback; + static TextureFormatRequestCallback request_normal_callback; uint32_t get_flags() const; Image::Format get_format() const; @@ -204,14 +205,14 @@ public: int get_height() const; virtual RID get_rid() const; - virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const; - virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const; - virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const; + virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; + virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; + virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = true) const; virtual bool has_alpha() const; virtual void set_flags(uint32_t p_flags); - virtual Image get_data() const; + virtual Ref<Image> get_data() const; StreamTexture(); ~StreamTexture(); @@ -230,7 +231,7 @@ VARIANT_ENUM_CAST(ImageTexture::Storage); class AtlasTexture : public Texture { GDCLASS(AtlasTexture, Texture); - RES_BASE_EXTENSION("atex"); + RES_BASE_EXTENSION("atlastex"); protected: Ref<Texture> atlas; @@ -258,9 +259,9 @@ public: void set_margin(const Rect2 &p_margin); Rect2 get_margin() const; - virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const; - virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const; - virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const; + virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; + virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; + virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = true) const; virtual bool get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const; AtlasTexture(); @@ -269,7 +270,7 @@ public: class LargeTexture : public Texture { GDCLASS(LargeTexture, Texture); - RES_BASE_EXTENSION("ltex"); + RES_BASE_EXTENSION("largetex"); protected: struct Piece { @@ -306,9 +307,9 @@ public: Vector2 get_piece_offset(int p_idx) const; Ref<Texture> get_piece_texture(int p_idx) const; - virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const; - virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const; - virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const; + virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; + virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; + virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = true) const; LargeTexture(); }; @@ -316,7 +317,7 @@ public: class CubeMap : public Resource { GDCLASS(CubeMap, Resource); - RES_BASE_EXTENSION("cbm"); + RES_BASE_EXTENSION("cubemap"); public: enum Storage { @@ -369,8 +370,8 @@ protected: public: void set_flags(uint32_t p_flags); uint32_t get_flags() const; - void set_side(Side p_side, const Image &p_image); - Image get_side(Side p_side) const; + void set_side(Side p_side, const Ref<Image> &p_image); + Ref<Image> get_side(Side p_side) const; Image::Format get_format() const; int get_width() const; @@ -390,10 +391,45 @@ public: ~CubeMap(); }; -VARIANT_ENUM_CAST(CubeMap::Flags); -VARIANT_ENUM_CAST(CubeMap::Side); -VARIANT_ENUM_CAST(CubeMap::Storage); +VARIANT_ENUM_CAST(CubeMap::Flags) +VARIANT_ENUM_CAST(CubeMap::Side) +VARIANT_ENUM_CAST(CubeMap::Storage) + +class CurveTexture : public Texture { + + GDCLASS(CurveTexture, Texture) + RES_BASE_EXTENSION("curvetex") + +private: + RID _texture; + Ref<Curve> _curve; + int _width; + + void _update(); +protected: + static void _bind_methods(); + +public: + void set_width(int p_width); + int get_width() const; + + void ensure_default_setup(float p_min = 0, float p_max = 1); + + void set_curve(Ref<Curve> p_curve); + Ref<Curve> get_curve() const; + + virtual RID get_rid() const; + + virtual int get_height() const { return 1; } + virtual bool has_alpha() const { return false; } + + virtual void set_flags(uint32_t p_flags) {} + virtual uint32_t get_flags() const { return FLAG_FILTER; } + + CurveTexture(); + ~CurveTexture(); +}; /* enum CubeMapSide { @@ -408,4 +444,49 @@ VARIANT_ENUM_CAST(CubeMap::Storage); */ //VARIANT_ENUM_CAST( Texture::CubeMapSide ); +class GradientTexture : public Texture { + GDCLASS(GradientTexture, Texture) + +public: + struct Point { + + float offset; + Color color; + bool operator<(const Point &p_ponit) const { + return offset < p_ponit.offset; + } + }; + +private: + Ref<Gradient> gradient; + bool update_pending; + RID texture; + int width; + + void _queue_update(); + void _update(); + +protected: + static void _bind_methods(); + +public: + void set_gradient(Ref<Gradient> p_gradient); + Ref<Gradient> get_gradient() const; + + void set_width(int p_width); + int get_width() const; + + virtual RID get_rid() const { return texture; } + virtual int get_height() const { return 1; } + virtual bool has_alpha() const { return true; } + + virtual void set_flags(uint32_t p_flags) {} + virtual uint32_t get_flags() const { return FLAG_FILTER; } + + virtual Ref<Image> get_data() const; + + GradientTexture(); + virtual ~GradientTexture(); +}; + #endif diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp index c1ef3e8c1..ac1bb105a 100644 --- a/scene/resources/theme.cpp +++ b/scene/resources/theme.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -628,21 +629,21 @@ void Theme::get_type_list(List<StringName> *p_list) const { void Theme::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_icon", "name", "type", "texture:Texture"), &Theme::set_icon); - ClassDB::bind_method(D_METHOD("get_icon:Texture", "name", "type"), &Theme::get_icon); + ClassDB::bind_method(D_METHOD("set_icon", "name", "type", "texture"), &Theme::set_icon); + ClassDB::bind_method(D_METHOD("get_icon", "name", "type"), &Theme::get_icon); ClassDB::bind_method(D_METHOD("has_icon", "name", "type"), &Theme::has_icon); ClassDB::bind_method(D_METHOD("clear_icon", "name", "type"), &Theme::clear_icon); ClassDB::bind_method(D_METHOD("get_icon_list", "type"), &Theme::_get_icon_list); - ClassDB::bind_method(D_METHOD("set_stylebox", "name", "type", "texture:StyleBox"), &Theme::set_stylebox); - ClassDB::bind_method(D_METHOD("get_stylebox:StyleBox", "name", "type"), &Theme::get_stylebox); + ClassDB::bind_method(D_METHOD("set_stylebox", "name", "type", "texture"), &Theme::set_stylebox); + ClassDB::bind_method(D_METHOD("get_stylebox", "name", "type"), &Theme::get_stylebox); ClassDB::bind_method(D_METHOD("has_stylebox", "name", "type"), &Theme::has_stylebox); ClassDB::bind_method(D_METHOD("clear_stylebox", "name", "type"), &Theme::clear_stylebox); ClassDB::bind_method(D_METHOD("get_stylebox_list", "type"), &Theme::_get_stylebox_list); ClassDB::bind_method(D_METHOD("get_stylebox_types"), &Theme::_get_stylebox_types); - ClassDB::bind_method(D_METHOD("set_font", "name", "type", "font:Font"), &Theme::set_font); - ClassDB::bind_method(D_METHOD("get_font:Font", "name", "type"), &Theme::get_font); + ClassDB::bind_method(D_METHOD("set_font", "name", "type", "font"), &Theme::set_font); + ClassDB::bind_method(D_METHOD("get_font", "name", "type"), &Theme::get_font); ClassDB::bind_method(D_METHOD("has_font", "name", "type"), &Theme::has_font); ClassDB::bind_method(D_METHOD("clear_font", "name", "type"), &Theme::clear_font); ClassDB::bind_method(D_METHOD("get_font_list", "type"), &Theme::_get_font_list); @@ -882,7 +883,7 @@ RES ResourceFormatLoaderTheme::load(const String &p_path, const String &p_origin ERR_FAIL_V(RES()); } - sbflat->set_border_size(params[0].to_int()); + sbflat->set_border_width_all(params[0].to_int()); if (!params[0].is_valid_integer()) { @@ -928,8 +929,8 @@ RES ResourceFormatLoaderTheme::load(const String &p_path, const String &p_origin dark = Color::html(params[3]); } - sbflat->set_dark_color(dark); - sbflat->set_light_color(bright); + sbflat->set_border_color_all(bright); + // sbflat->set_dark_color(dark); sbflat->set_bg_color(normal); if (params.size() == ccodes + 5) { diff --git a/scene/resources/theme.h b/scene/resources/theme.h index 4de6fd78c..5744c142d 100644 --- a/scene/resources/theme.h +++ b/scene/resources/theme.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -42,7 +43,7 @@ class Theme : public Resource { GDCLASS(Theme, Resource); - RES_BASE_EXTENSION("thm"); + RES_BASE_EXTENSION("theme"); static Ref<Theme> default_theme; @@ -142,8 +143,8 @@ public: static void set_default(const Ref<Theme> &p_default); static void set_default_icon(const Ref<Texture> &p_icon); - static void set_default_style(const Ref<StyleBox> &p_default_style); - static void set_default_font(const Ref<Font> &p_default_font); + static void set_default_style(const Ref<StyleBox> &p_style); + static void set_default_font(const Ref<Font> &p_font); void set_default_theme_font(const Ref<Font> &p_default_font); Ref<Font> get_default_theme_font() const; @@ -158,7 +159,7 @@ public: Ref<Shader> get_shader(const StringName &p_name, const StringName &p_type) const; bool has_shader(const StringName &p_name, const StringName &p_type) const; void clear_shader(const StringName &p_name, const StringName &p_type); - void get_shader_list(const StringName &p_name, List<StringName> *p_list) const; + void get_shader_list(const StringName &p_type, List<StringName> *p_list) const; void set_stylebox(const StringName &p_name, const StringName &p_type, const Ref<StyleBox> &p_style); Ref<StyleBox> get_stylebox(const StringName &p_name, const StringName &p_type) const; diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 3e128379a..44fe676dd 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -44,18 +45,26 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) { tile_set_name(id, p_value); else if (what == "texture") tile_set_texture(id, p_value); + else if (what == "normal_map") + tile_set_normal_map(id, p_value); else if (what == "tex_offset") tile_set_texture_offset(id, p_value); else if (what == "material") tile_set_material(id, p_value); else if (what == "modulate") tile_set_modulate(id, p_value); - else if (what == "shape_offset") - tile_set_shape_offset(id, p_value); else if (what == "region") tile_set_region(id, p_value); else if (what == "shape") - tile_set_shape(id, p_value); + tile_set_shape(id, 0, p_value); + else if (what == "shape_offset") { + Transform2D xform = tile_get_shape_transform(id, 0); + xform.set_origin(p_value); + tile_set_shape_transform(id, 0, xform); + } else if (what == "shape_transform") + tile_set_shape_transform(id, 0, p_value); + else if (what == "shape_one_way") + tile_set_shape_one_way(id, 0, p_value); else if (what == "shapes") _tile_set_shapes(id, p_value); else if (what == "occluder") @@ -88,18 +97,24 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const { r_ret = tile_get_name(id); else if (what == "texture") r_ret = tile_get_texture(id); + else if (what == "normal_map") + r_ret = tile_get_normal_map(id); else if (what == "tex_offset") r_ret = tile_get_texture_offset(id); else if (what == "material") r_ret = tile_get_material(id); else if (what == "modulate") r_ret = tile_get_modulate(id); - else if (what == "shape_offset") - r_ret = tile_get_shape_offset(id); else if (what == "region") r_ret = tile_get_region(id); else if (what == "shape") - r_ret = tile_get_shape(id); + r_ret = tile_get_shape(id, 0); + else if (what == "shape_offset") + r_ret = tile_get_shape_transform(id, 0).get_origin(); + else if (what == "shape_transform") + r_ret = tile_get_shape_transform(id, 0); + else if (what == "shape_one_way") + r_ret = tile_get_shape_one_way(id, 0); else if (what == "shapes") r_ret = _tile_get_shapes(id); else if (what == "occluder") @@ -118,22 +133,25 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const { void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { - for (Map<int, Data>::Element *E = tile_map.front(); E; E = E->next()) { + for (Map<int, TileData>::Element *E = tile_map.front(); E; E = E->next()) { int id = E->key(); String pre = itos(id) + "/"; p_list->push_back(PropertyInfo(Variant::STRING, pre + "name")); p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture")); + p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture")); p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "tex_offset")); - p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "material", PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial")); + p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial")); p_list->push_back(PropertyInfo(Variant::COLOR, pre + "modulate")); p_list->push_back(PropertyInfo(Variant::RECT2, pre + "region")); p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "occluder_offset")); p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "occluder", PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D")); p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "navigation_offset")); p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "navigation", PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon")); - p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "shape_offset")); + p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "shape_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "shape_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::BOOL, pre + "shape_one_way", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "shapes", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); } } @@ -141,7 +159,7 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { void TileSet::create_tile(int p_id) { ERR_FAIL_COND(tile_map.has(p_id)); - tile_map[p_id] = Data(); + tile_map[p_id] = TileData(); _change_notify(""); emit_changed(); } @@ -159,16 +177,29 @@ Ref<Texture> TileSet::tile_get_texture(int p_id) const { return tile_map[p_id].texture; } -void TileSet::tile_set_material(int p_id, const Ref<CanvasItemMaterial> &p_material) { +void TileSet::tile_set_normal_map(int p_id, const Ref<Texture> &p_normal_map) { + + ERR_FAIL_COND(!tile_map.has(p_id)); + tile_map[p_id].normal_map = p_normal_map; + emit_changed(); +} + +Ref<Texture> TileSet::tile_get_normal_map(int p_id) const { + + ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<Texture>()); + return tile_map[p_id].normal_map; +} + +void TileSet::tile_set_material(int p_id, const Ref<ShaderMaterial> &p_material) { ERR_FAIL_COND(!tile_map.has(p_id)); tile_map[p_id].material = p_material; emit_changed(); } -Ref<CanvasItemMaterial> TileSet::tile_get_material(int p_id) const { +Ref<ShaderMaterial> TileSet::tile_get_material(int p_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<CanvasItemMaterial>()); + ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<ShaderMaterial>()); return tile_map[p_id].material; } @@ -198,19 +229,6 @@ Vector2 TileSet::tile_get_texture_offset(int p_id) const { return tile_map[p_id].offset; } -void TileSet::tile_set_shape_offset(int p_id, const Vector2 &p_offset) { - - ERR_FAIL_COND(!tile_map.has(p_id)); - tile_map[p_id].shape_offset = p_offset; - emit_changed(); -} - -Vector2 TileSet::tile_get_shape_offset(int p_id) const { - - ERR_FAIL_COND_V(!tile_map.has(p_id), Vector2()); - return tile_map[p_id].shape_offset; -} - void TileSet::tile_set_region(int p_id, const Rect2 &p_region) { ERR_FAIL_COND(!tile_map.has(p_id)); @@ -237,23 +255,82 @@ String TileSet::tile_get_name(int p_id) const { return tile_map[p_id].name; } -void TileSet::tile_set_shape(int p_id, const Ref<Shape2D> &p_shape) { +void TileSet::tile_clear_shapes(int p_id) { + tile_map[p_id].shapes_data.clear(); +} + +void TileSet::tile_add_shape(int p_id, const Ref<Shape2D> &p_shape, const Transform2D &p_transform, bool p_one_way) { + + ERR_FAIL_COND(!tile_map.has(p_id)); + + ShapeData new_data = ShapeData(); + new_data.shape = p_shape; + new_data.shape_transform = p_transform; + new_data.one_way_collision = p_one_way; + + tile_map[p_id].shapes_data.push_back(new_data); +}; +int TileSet::tile_get_shape_count(int p_id) const { + + ERR_FAIL_COND_V(!tile_map.has(p_id), 0); + + return tile_map[p_id].shapes_data.size(); +}; + +void TileSet::tile_set_shape(int p_id, int p_shape_id, const Ref<Shape2D> &p_shape) { ERR_FAIL_COND(!tile_map.has(p_id)); - tile_map[p_id].shapes.resize(1); - tile_map[p_id].shapes[0] = p_shape; + if (tile_map[p_id].shapes_data.size() <= p_shape_id) + tile_map[p_id].shapes_data.resize(p_shape_id + 1); + tile_map[p_id].shapes_data[p_shape_id].shape = p_shape; emit_changed(); } -Ref<Shape2D> TileSet::tile_get_shape(int p_id) const { +Ref<Shape2D> TileSet::tile_get_shape(int p_id, int p_shape_id) const { ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<Shape2D>()); - if (tile_map[p_id].shapes.size() > 0) - return tile_map[p_id].shapes[0]; + if (tile_map[p_id].shapes_data.size() > p_shape_id) + return tile_map[p_id].shapes_data[p_shape_id].shape; return Ref<Shape2D>(); } +void TileSet::tile_set_shape_transform(int p_id, int p_shape_id, const Transform2D &p_offset) { + + ERR_FAIL_COND(!tile_map.has(p_id)); + if (tile_map[p_id].shapes_data.size() <= p_shape_id) + tile_map[p_id].shapes_data.resize(p_shape_id + 1); + tile_map[p_id].shapes_data[p_shape_id].shape_transform = p_offset; + emit_changed(); +} + +Transform2D TileSet::tile_get_shape_transform(int p_id, int p_shape_id) const { + + ERR_FAIL_COND_V(!tile_map.has(p_id), Transform2D()); + if (tile_map[p_id].shapes_data.size() > p_shape_id) + return tile_map[p_id].shapes_data[p_shape_id].shape_transform; + + return Transform2D(); +} + +void TileSet::tile_set_shape_one_way(int p_id, int p_shape_id, const bool p_one_way) { + + ERR_FAIL_COND(!tile_map.has(p_id)); + if (tile_map[p_id].shapes_data.size() <= p_shape_id) + tile_map[p_id].shapes_data.resize(p_shape_id + 1); + tile_map[p_id].shapes_data[p_shape_id].one_way_collision = p_one_way; + emit_changed(); +} + +bool TileSet::tile_get_shape_one_way(int p_id, int p_shape_id) const { + + ERR_FAIL_COND_V(!tile_map.has(p_id), false); + if (tile_map[p_id].shapes_data.size() > p_shape_id) + return tile_map[p_id].shapes_data[p_shape_id].one_way_collision; + + return false; +} + void TileSet::tile_set_light_occluder(int p_id, const Ref<OccluderPolygon2D> &p_light_occluder) { ERR_FAIL_COND(!tile_map.has(p_id)); @@ -300,31 +377,65 @@ Vector2 TileSet::tile_get_occluder_offset(int p_id) const { return tile_map[p_id].occluder_offset; } -void TileSet::tile_set_shapes(int p_id, const Vector<Ref<Shape2D> > &p_shapes) { +void TileSet::tile_set_shapes(int p_id, const Vector<ShapeData> &p_shapes) { ERR_FAIL_COND(!tile_map.has(p_id)); - tile_map[p_id].shapes = p_shapes; + tile_map[p_id].shapes_data = p_shapes; emit_changed(); } -Vector<Ref<Shape2D> > TileSet::tile_get_shapes(int p_id) const { +Vector<TileSet::ShapeData> TileSet::tile_get_shapes(int p_id) const { + + ERR_FAIL_COND_V(!tile_map.has(p_id), Vector<ShapeData>()); - ERR_FAIL_COND_V(!tile_map.has(p_id), Vector<Ref<Shape2D> >()); - return tile_map[p_id].shapes; + return tile_map[p_id].shapes_data; } void TileSet::_tile_set_shapes(int p_id, const Array &p_shapes) { ERR_FAIL_COND(!tile_map.has(p_id)); - Vector<Ref<Shape2D> > shapes; + Vector<ShapeData> shapes_data; + Transform2D default_transform = tile_get_shape_transform(p_id, 0); + bool default_one_way = tile_get_shape_one_way(p_id, 0); for (int i = 0; i < p_shapes.size(); i++) { + ShapeData s = ShapeData(); - Ref<Shape2D> s = p_shapes[i]; - if (s.is_valid()) - shapes.push_back(s); + if (p_shapes[i].get_type() == Variant::OBJECT) { + Ref<Shape2D> shape = p_shapes[i]; + if (shape.is_null()) continue; + + s.shape = shape; + s.shape_transform = default_transform; + s.one_way_collision = default_one_way; + } else if (p_shapes[i].get_type() == Variant::DICTIONARY) { + Dictionary d = p_shapes[i]; + + if (d.has("shape") && d["shape"].get_type() == Variant::OBJECT) + s.shape = d["shape"]; + else + continue; + + if (d.has("shape_transform") && d["shape_transform"].get_type() == Variant::TRANSFORM2D) + s.shape_transform = d["shape_transform"]; + else if (d.has("shape_offset") && d["shape_offset"].get_type() == Variant::VECTOR2) + s.shape_transform = Transform2D(0, (Vector2)d["shape_offset"]); + else + s.shape_transform = default_transform; + + if (d.has("one_way") && d["one_way"].get_type() == Variant::BOOL) + s.one_way_collision = d["one_way"]; + else + s.one_way_collision = default_one_way; + + } else { + ERR_EXPLAIN("Expected an array of objects or dictionaries for tile_set_shapes"); + ERR_CONTINUE(true); + } + + shapes_data.push_back(s); } - tile_set_shapes(p_id, shapes); + tile_map[p_id].shapes_data = shapes_data; } Array TileSet::_tile_get_shapes(int p_id) const { @@ -332,9 +443,14 @@ Array TileSet::_tile_get_shapes(int p_id) const { ERR_FAIL_COND_V(!tile_map.has(p_id), Array()); Array arr; - Vector<Ref<Shape2D> > shp = tile_map[p_id].shapes; - for (int i = 0; i < shp.size(); i++) - arr.push_back(shp[i]); + Vector<ShapeData> data = tile_map[p_id].shapes_data; + for (int i = 0; i < data.size(); i++) { + Dictionary shape_data; + shape_data["shape"] = data[i].shape; + shape_data["shape_transform"] = data[i].shape_transform; + shape_data["one_way"] = data[i].one_way_collision; + arr.push_back(shape_data); + } return arr; } @@ -343,7 +459,7 @@ Array TileSet::_get_tiles_ids() const { Array arr; - for (Map<int, Data>::Element *E = tile_map.front(); E; E = E->next()) { + for (Map<int, TileData>::Element *E = tile_map.front(); E; E = E->next()) { arr.push_back(E->key()); } @@ -352,7 +468,7 @@ Array TileSet::_get_tiles_ids() const { void TileSet::get_tile_list(List<int> *p_tiles) const { - for (Map<int, Data>::Element *E = tile_map.front(); E; E = E->next()) { + for (Map<int, TileData>::Element *E = tile_map.front(); E; E = E->next()) { p_tiles->push_back(E->key()); } @@ -381,7 +497,7 @@ int TileSet::get_last_unused_tile_id() const { int TileSet::find_tile_by_name(const String &p_name) const { - for (Map<int, Data>::Element *E = tile_map.front(); E; E = E->next()) { + for (Map<int, TileData>::Element *E = tile_map.front(); E; E = E->next()) { if (p_name == E->get().name) return E->key(); @@ -401,26 +517,32 @@ void TileSet::_bind_methods() { ClassDB::bind_method(D_METHOD("create_tile", "id"), &TileSet::create_tile); ClassDB::bind_method(D_METHOD("tile_set_name", "id", "name"), &TileSet::tile_set_name); ClassDB::bind_method(D_METHOD("tile_get_name", "id"), &TileSet::tile_get_name); - ClassDB::bind_method(D_METHOD("tile_set_texture", "id", "texture:Texture"), &TileSet::tile_set_texture); - ClassDB::bind_method(D_METHOD("tile_get_texture:Texture", "id"), &TileSet::tile_get_texture); - ClassDB::bind_method(D_METHOD("tile_set_material", "id", "material:CanvasItemMaterial"), &TileSet::tile_set_material); - ClassDB::bind_method(D_METHOD("tile_get_material:CanvasItemMaterial", "id"), &TileSet::tile_get_material); + ClassDB::bind_method(D_METHOD("tile_set_texture", "id", "texture"), &TileSet::tile_set_texture); + ClassDB::bind_method(D_METHOD("tile_get_texture", "id"), &TileSet::tile_get_texture); + ClassDB::bind_method(D_METHOD("tile_set_normal_map", "id", "normal_map"), &TileSet::tile_set_normal_map); + ClassDB::bind_method(D_METHOD("tile_get_normal_map", "id"), &TileSet::tile_get_normal_map); + ClassDB::bind_method(D_METHOD("tile_set_material", "id", "material"), &TileSet::tile_set_material); + ClassDB::bind_method(D_METHOD("tile_get_material", "id"), &TileSet::tile_get_material); ClassDB::bind_method(D_METHOD("tile_set_texture_offset", "id", "texture_offset"), &TileSet::tile_set_texture_offset); ClassDB::bind_method(D_METHOD("tile_get_texture_offset", "id"), &TileSet::tile_get_texture_offset); - ClassDB::bind_method(D_METHOD("tile_set_shape_offset", "id", "shape_offset"), &TileSet::tile_set_shape_offset); - ClassDB::bind_method(D_METHOD("tile_get_shape_offset", "id"), &TileSet::tile_get_shape_offset); ClassDB::bind_method(D_METHOD("tile_set_region", "id", "region"), &TileSet::tile_set_region); ClassDB::bind_method(D_METHOD("tile_get_region", "id"), &TileSet::tile_get_region); - ClassDB::bind_method(D_METHOD("tile_set_shape", "id", "shape:Shape2D"), &TileSet::tile_set_shape); - ClassDB::bind_method(D_METHOD("tile_get_shape:Shape2D", "id"), &TileSet::tile_get_shape); + ClassDB::bind_method(D_METHOD("tile_set_shape", "id", "shape_id", "shape"), &TileSet::tile_set_shape); + ClassDB::bind_method(D_METHOD("tile_get_shape", "id", "shape_id"), &TileSet::tile_get_shape); + ClassDB::bind_method(D_METHOD("tile_set_shape_transform", "id", "shape_id", "shape_transform"), &TileSet::tile_set_shape_transform); + ClassDB::bind_method(D_METHOD("tile_get_shape_transform", "id", "shape_id"), &TileSet::tile_get_shape_transform); + ClassDB::bind_method(D_METHOD("tile_set_shape_one_way", "id", "shape_id", "one_way"), &TileSet::tile_set_shape_one_way); + ClassDB::bind_method(D_METHOD("tile_get_shape_one_way", "id", "shape_id"), &TileSet::tile_get_shape_one_way); + ClassDB::bind_method(D_METHOD("tile_add_shape", "id", "shape", "shape_transform", "one_way"), &TileSet::tile_add_shape, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("tile_get_shape_count", "id"), &TileSet::tile_get_shape_count); ClassDB::bind_method(D_METHOD("tile_set_shapes", "id", "shapes"), &TileSet::_tile_set_shapes); ClassDB::bind_method(D_METHOD("tile_get_shapes", "id"), &TileSet::_tile_get_shapes); - ClassDB::bind_method(D_METHOD("tile_set_navigation_polygon", "id", "navigation_polygon:NavigationPolygon"), &TileSet::tile_set_navigation_polygon); - ClassDB::bind_method(D_METHOD("tile_get_navigation_polygon:NavigationPolygon", "id"), &TileSet::tile_get_navigation_polygon); + ClassDB::bind_method(D_METHOD("tile_set_navigation_polygon", "id", "navigation_polygon"), &TileSet::tile_set_navigation_polygon); + ClassDB::bind_method(D_METHOD("tile_get_navigation_polygon", "id"), &TileSet::tile_get_navigation_polygon); ClassDB::bind_method(D_METHOD("tile_set_navigation_polygon_offset", "id", "navigation_polygon_offset"), &TileSet::tile_set_navigation_polygon_offset); ClassDB::bind_method(D_METHOD("tile_get_navigation_polygon_offset", "id"), &TileSet::tile_get_navigation_polygon_offset); - ClassDB::bind_method(D_METHOD("tile_set_light_occluder", "id", "light_occluder:OccluderPolygon2D"), &TileSet::tile_set_light_occluder); - ClassDB::bind_method(D_METHOD("tile_get_light_occluder:OccluderPolygon2D", "id"), &TileSet::tile_get_light_occluder); + ClassDB::bind_method(D_METHOD("tile_set_light_occluder", "id", "light_occluder"), &TileSet::tile_set_light_occluder); + ClassDB::bind_method(D_METHOD("tile_get_light_occluder", "id"), &TileSet::tile_get_light_occluder); ClassDB::bind_method(D_METHOD("tile_set_occluder_offset", "id", "occluder_offset"), &TileSet::tile_set_occluder_offset); ClassDB::bind_method(D_METHOD("tile_get_occluder_offset", "id"), &TileSet::tile_get_occluder_offset); @@ -428,7 +550,7 @@ void TileSet::_bind_methods() { ClassDB::bind_method(D_METHOD("clear"), &TileSet::clear); ClassDB::bind_method(D_METHOD("get_last_unused_tile_id"), &TileSet::get_last_unused_tile_id); ClassDB::bind_method(D_METHOD("find_tile_by_name", "name"), &TileSet::find_tile_by_name); - ClassDB::bind_method(D_METHOD("get_tiles_ids", "name"), &TileSet::_get_tiles_ids); + ClassDB::bind_method(D_METHOD("get_tiles_ids"), &TileSet::_get_tiles_ids); } TileSet::TileSet() { diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h index 53f68d00a..7d7855811 100644 --- a/scene/resources/tile_set.h +++ b/scene/resources/tile_set.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -39,27 +40,39 @@ class TileSet : public Resource { GDCLASS(TileSet, Resource); - struct Data { +public: + struct ShapeData { + Ref<Shape2D> shape; + Transform2D shape_transform; + bool one_way_collision; + + ShapeData() { + one_way_collision = false; + } + }; + +private: + struct TileData { String name; Ref<Texture> texture; + Ref<Texture> normal_map; Vector2 offset; - Vector2 shape_offset; Rect2i region; - Vector<Ref<Shape2D> > shapes; + Vector<ShapeData> shapes_data; Vector2 occluder_offset; Ref<OccluderPolygon2D> occluder; Vector2 navigation_polygon_offset; Ref<NavigationPolygon> navigation_polygon; - Ref<CanvasItemMaterial> material; + Ref<ShaderMaterial> material; Color modulate; // Default modulate for back-compat - explicit Data() + explicit TileData() : modulate(1, 1, 1) {} }; - Map<int, Data> tile_map; + Map<int, TileData> tile_map; protected: bool _set(const StringName &p_name, const Variant &p_value); @@ -80,22 +93,35 @@ public: void tile_set_texture(int p_id, const Ref<Texture> &p_texture); Ref<Texture> tile_get_texture(int p_id) const; + void tile_set_normal_map(int p_id, const Ref<Texture> &p_normal_map); + Ref<Texture> tile_get_normal_map(int p_id) const; + void tile_set_texture_offset(int p_id, const Vector2 &p_offset); Vector2 tile_get_texture_offset(int p_id) const; - void tile_set_shape_offset(int p_id, const Vector2 &p_offset); - Vector2 tile_get_shape_offset(int p_id) const; - void tile_set_region(int p_id, const Rect2 &p_region); Rect2 tile_get_region(int p_id) const; - void tile_set_shape(int p_id, const Ref<Shape2D> &p_shape); - Ref<Shape2D> tile_get_shape(int p_id) const; + void tile_set_shape(int p_id, int p_shape_id, const Ref<Shape2D> &p_shape); + Ref<Shape2D> tile_get_shape(int p_id, int p_shape_id) const; - void tile_set_material(int p_id, const Ref<CanvasItemMaterial> &p_material); - Ref<CanvasItemMaterial> tile_get_material(int p_id) const; + void tile_set_shape_transform(int p_id, int p_shape_id, const Transform2D &p_offset); + Transform2D tile_get_shape_transform(int p_id, int p_shape_id) const; - void tile_set_modulate(int p_id, const Color &p_color); + void tile_set_shape_one_way(int p_id, int p_shape_id, bool p_one_way); + bool tile_get_shape_one_way(int p_id, int p_shape_id) const; + + void tile_clear_shapes(int p_id); + void tile_add_shape(int p_id, const Ref<Shape2D> &p_shape, const Transform2D &p_transform, bool p_one_way = false); + int tile_get_shape_count(int p_id) const; + + void tile_set_shapes(int p_id, const Vector<ShapeData> &p_shapes); + Vector<ShapeData> tile_get_shapes(int p_id) const; + + void tile_set_material(int p_id, const Ref<ShaderMaterial> &p_material); + Ref<ShaderMaterial> tile_get_material(int p_id) const; + + void tile_set_modulate(int p_id, const Color &p_modulate); Color tile_get_modulate(int p_id) const; void tile_set_occluder_offset(int p_id, const Vector2 &p_offset); @@ -110,9 +136,6 @@ public: void tile_set_navigation_polygon(int p_id, const Ref<NavigationPolygon> &p_navigation_polygon); Ref<NavigationPolygon> tile_get_navigation_polygon(int p_id) const; - void tile_set_shapes(int p_id, const Vector<Ref<Shape2D> > &p_shapes); - Vector<Ref<Shape2D> > tile_get_shapes(int p_id) const; - void remove_tile(int p_id); bool has_tile(int p_id) const; diff --git a/scene/resources/video_stream.cpp b/scene/resources/video_stream.cpp index 47c40e4e6..1b0e34b8d 100644 --- a/scene/resources/video_stream.cpp +++ b/scene/resources/video_stream.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/video_stream.h b/scene/resources/video_stream.h index 7c1bd94c8..544973f58 100644 --- a/scene/resources/video_stream.h +++ b/scene/resources/video_stream.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/resources/world.cpp b/scene/resources/world.cpp index dc62c2ab3..b0d14125a 100644 --- a/scene/resources/world.cpp +++ b/scene/resources/world.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -279,19 +280,43 @@ Ref<Environment> World::get_environment() const { return environment; } +void World::set_fallback_environment(const Ref<Environment> &p_environment) { + + fallback_environment = p_environment; + if (fallback_environment.is_valid()) + VS::get_singleton()->scenario_set_fallback_environment(scenario, p_environment->get_rid()); + else + VS::get_singleton()->scenario_set_fallback_environment(scenario, RID()); +} + +Ref<Environment> World::get_fallback_environment() const { + + return fallback_environment; +} + PhysicsDirectSpaceState *World::get_direct_space_state() { return PhysicsServer::get_singleton()->space_get_direct_state(space); } +void World::get_camera_list(List<Camera *> *r_cameras) { + + for (Map<Camera *, SpatialIndexer::CameraData>::Element *E = indexer->cameras.front(); E; E = E->next()) { + r_cameras->push_back(E->key()); + } +} + void World::_bind_methods() { ClassDB::bind_method(D_METHOD("get_space"), &World::get_space); ClassDB::bind_method(D_METHOD("get_scenario"), &World::get_scenario); - ClassDB::bind_method(D_METHOD("set_environment", "env:Environment"), &World::set_environment); - ClassDB::bind_method(D_METHOD("get_environment:Environment"), &World::get_environment); - ClassDB::bind_method(D_METHOD("get_direct_space_state:PhysicsDirectSpaceState"), &World::get_direct_space_state); + ClassDB::bind_method(D_METHOD("set_environment", "env"), &World::set_environment); + ClassDB::bind_method(D_METHOD("get_environment"), &World::get_environment); + ClassDB::bind_method(D_METHOD("set_fallback_environment", "env"), &World::set_fallback_environment); + ClassDB::bind_method(D_METHOD("get_fallback_environment"), &World::get_fallback_environment); + ClassDB::bind_method(D_METHOD("get_direct_space_state"), &World::get_direct_space_state); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_environment", "get_environment"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "fallback_environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_fallback_environment", "get_fallback_environment"); } World::World() { diff --git a/scene/resources/world.h b/scene/resources/world.h index a597633ca..158086974 100644 --- a/scene/resources/world.h +++ b/scene/resources/world.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -40,13 +41,14 @@ class VisibilityNotifier; class World : public Resource { GDCLASS(World, Resource); - RES_BASE_EXTENSION("wrd"); + RES_BASE_EXTENSION("world"); private: RID space; RID scenario; SpatialIndexer *indexer; Ref<Environment> environment; + Ref<Environment> fallback_environment; protected: static void _bind_methods(); @@ -67,9 +69,15 @@ protected: public: RID get_space() const; RID get_scenario() const; + void set_environment(const Ref<Environment> &p_environment); Ref<Environment> get_environment() const; + void set_fallback_environment(const Ref<Environment> &p_environment); + Ref<Environment> get_fallback_environment() const; + + void get_camera_list(List<Camera *> *r_cameras); + PhysicsDirectSpaceState *get_direct_space_state(); World(); diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp index cb346199c..2f43f903b 100644 --- a/scene/resources/world_2d.cpp +++ b/scene/resources/world_2d.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,8 +31,7 @@ #include "servers/physics_2d_server.h" #include "servers/visual_server.h" //#include "servers/spatial_sound_2d_server.h" -#include "global_config.h" -#include "global_config.h" +#include "project_settings.h" #include "scene/2d/camera_2d.h" #include "scene/2d/visibility_notifier_2d.h" #include "scene/main/viewport.h" @@ -96,9 +96,9 @@ struct SpatialIndexer2D { void _notifier_update_cells(VisibilityNotifier2D *p_notifier, const Rect2 &p_rect, bool p_add) { - Point2i begin = p_rect.pos; + Point2i begin = p_rect.position; begin /= cell_size; - Point2i end = p_rect.pos + p_rect.size; + Point2i end = p_rect.position + p_rect.size; end /= cell_size; for (int i = begin.x; i <= end.x; i++) { @@ -219,9 +219,9 @@ struct SpatialIndexer2D { for (Map<Viewport *, ViewportData>::Element *E = viewports.front(); E; E = E->next()) { - Point2i begin = E->get().rect.pos; + Point2i begin = E->get().rect.position; begin /= cell_size; - Point2i end = E->get().rect.pos + E->get().rect.size; + Point2i end = E->get().rect.position + E->get().rect.size; end /= cell_size; pass++; List<VisibilityNotifier2D *> added; @@ -359,18 +359,19 @@ RID World2D::get_space() { return space; } -RID World2D::get_sound_space() { +void World2D::get_viewport_list(List<Viewport *> *r_viewports) { - return sound_space; + for (Map<Viewport *, SpatialIndexer2D::ViewportData>::Element *E = indexer->viewports.front(); E; E = E->next()) { + r_viewports->push_back(E->key()); + } } void World2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_canvas"), &World2D::get_canvas); ClassDB::bind_method(D_METHOD("get_space"), &World2D::get_space); - ClassDB::bind_method(D_METHOD("get_sound_space"), &World2D::get_sound_space); - ClassDB::bind_method(D_METHOD("get_direct_space_state:Physics2DDirectSpaceState"), &World2D::get_direct_space_state); + ClassDB::bind_method(D_METHOD("get_direct_space_state"), &World2D::get_direct_space_state); } Physics2DDirectSpaceState *World2D::get_direct_space_state() { diff --git a/scene/resources/world_2d.h b/scene/resources/world_2d.h index 2bb5eb152..f968b08a1 100644 --- a/scene/resources/world_2d.h +++ b/scene/resources/world_2d.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,7 +30,7 @@ #ifndef WORLD_2D_H #define WORLD_2D_H -#include "global_config.h" +#include "project_settings.h" #include "resource.h" #include "servers/physics_2d_server.h" @@ -43,7 +44,6 @@ class World2D : public Resource { RID canvas; RID space; - RID sound_space; SpatialIndexer2D *indexer; @@ -65,10 +65,11 @@ protected: public: RID get_canvas(); RID get_space(); - RID get_sound_space(); Physics2DDirectSpaceState *get_direct_space_state(); + void get_viewport_list(List<Viewport *> *r_viewports); + World2D(); ~World2D(); }; diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp index f0a33e0d3..f247e7cde 100644 --- a/scene/scene_string_names.cpp +++ b/scene/scene_string_names.cpp @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,6 +33,9 @@ SceneStringNames *SceneStringNames::singleton = NULL; SceneStringNames::SceneStringNames() { + _estimate_cost = StaticCString::create("_estimate_cost"); + _compute_cost = StaticCString::create("_compute_cost"); + resized = StaticCString::create("resized"); dot = StaticCString::create("."); doubledot = StaticCString::create(".."); @@ -40,7 +44,7 @@ SceneStringNames::SceneStringNames() { hide = StaticCString::create("hide"); visibility_changed = StaticCString::create("visibility_changed"); input_event = StaticCString::create("input_event"); - shader_shader = StaticCString::create("shader/shader"); + shader = StaticCString::create("shader"); shader_unshaded = StaticCString::create("shader/unshaded"); shading_mode = StaticCString::create("shader/shading_mode"); tree_entered = StaticCString::create("tree_entered"); @@ -138,9 +142,9 @@ SceneStringNames::SceneStringNames() { h_offset = StaticCString::create("h_offset"); v_offset = StaticCString::create("v_offset"); - transform_pos = StaticCString::create("transform/pos"); - transform_rot = StaticCString::create("transform/rot"); - transform_scale = StaticCString::create("transform/scale"); + transform_pos = StaticCString::create("position"); + transform_rot = StaticCString::create("rotation_deg"); + transform_scale = StaticCString::create("scale"); _update_remote = StaticCString::create("_update_remote"); _update_pairs = StaticCString::create("_update_pairs"); @@ -154,8 +158,6 @@ SceneStringNames::SceneStringNames() { line_separation = StaticCString::create("line_separation"); - play_play = StaticCString::create("play/play"); - get_drag_data = StaticCString::create("get_drag_data"); drop_data = StaticCString::create("drop_data"); can_drop_data = StaticCString::create("can_drop_data"); diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h index 8900bbe1d..0b70cd36f 100644 --- a/scene/scene_string_names.h +++ b/scene/scene_string_names.h @@ -6,6 +6,7 @@ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,7 +30,7 @@ #ifndef SCENE_STRING_NAMES_H #define SCENE_STRING_NAMES_H -#include "path_db.h" +#include "node_path.h" #include "string_db.h" class SceneStringNames { @@ -49,6 +50,9 @@ class SceneStringNames { public: _FORCE_INLINE_ static SceneStringNames *get_singleton() { return singleton; } + StringName _estimate_cost; + StringName _compute_cost; + StringName resized; StringName dot; StringName doubledot; @@ -60,7 +64,7 @@ public: StringName gui_input; StringName _gui_input; StringName item_rect_changed; - StringName shader_shader; + StringName shader; StringName shader_unshaded; StringName shading_mode; StringName tree_entered; @@ -169,8 +173,6 @@ public: StringName _get_minimum_size; - StringName play_play; - StringName _im_update; StringName _queue_update; |
