diff options
Diffstat (limited to 'scene')
48 files changed, 2049 insertions, 192 deletions
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index b9cddfa572..d66f100b3f 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -447,7 +447,7 @@ float CanvasItem::get_self_opacity() const { void CanvasItem::set_blend_mode(BlendMode p_blend_mode) { - ERR_FAIL_INDEX(p_blend_mode,4); + ERR_FAIL_INDEX(p_blend_mode,5); blend_mode=p_blend_mode; VisualServer::get_singleton()->canvas_item_set_blend_mode(canvas_item,VS::MaterialBlendMode(blend_mode)); @@ -772,8 +772,8 @@ void CanvasItem::_bind_methods() { ObjectTypeDB::bind_method(_MD("draw_texture_rect_region","texture:Texture","rect","src_rect","modulate"),&CanvasItem::draw_texture_rect_region,DEFVAL(Color(1,1,1))); ObjectTypeDB::bind_method(_MD("draw_style_box","style_box:StyleBox","rect"),&CanvasItem::draw_style_box); ObjectTypeDB::bind_method(_MD("draw_primitive","points","colors","uvs","texture:Texture","width"),&CanvasItem::draw_primitive,DEFVAL(Array()),DEFVAL(Ref<Texture>()),DEFVAL(1.0)); - ObjectTypeDB::bind_method(_MD("draw_polygon","points","colors","uvs","texture:Texture"),&CanvasItem::draw_primitive,DEFVAL(Array()),DEFVAL(Ref<Texture>())); - ObjectTypeDB::bind_method(_MD("draw_colored_polygon","points","color","uvs","texture:Texture"),&CanvasItem::draw_primitive,DEFVAL(Array()),DEFVAL(Ref<Texture>())); + ObjectTypeDB::bind_method(_MD("draw_polygon","points","colors","uvs","texture:Texture"),&CanvasItem::draw_polygon,DEFVAL(Array()),DEFVAL(Ref<Texture>())); + ObjectTypeDB::bind_method(_MD("draw_colored_polygon","points","color","uvs","texture:Texture"),&CanvasItem::draw_colored_polygon,DEFVAL(Array()),DEFVAL(Ref<Texture>())); ObjectTypeDB::bind_method(_MD("draw_string","font:Font","pos","text","modulate","clip_w"),&CanvasItem::draw_string,DEFVAL(Color(1,1,1)),DEFVAL(-1)); ObjectTypeDB::bind_method(_MD("draw_char","font:Font","pos","char","next","modulate"),&CanvasItem::draw_char,DEFVAL(Color(1,1,1))); @@ -794,7 +794,7 @@ void CanvasItem::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/behind_parent"), _SCS("set_draw_behind_parent"),_SCS("is_draw_behind_parent_enabled") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/on_top",PROPERTY_HINT_NONE,"",0), _SCS("_set_on_top"),_SCS("_is_on_top") ); //compatibility - ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/blend_mode",PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul"), _SCS("set_blend_mode"),_SCS("get_blend_mode") ); + ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/blend_mode",PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul,PMAlpha"), _SCS("set_blend_mode"),_SCS("get_blend_mode") ); //exporting these two things doesn't really make much sense i think //ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transform/toplevel"), _SCS("set_as_toplevel"),_SCS("is_set_as_toplevel") ); //ADD_PROPERTY(PropertyInfo(Variant::BOOL,"transform/notify"),_SCS("set_transform_notify"),_SCS("is_transform_notify_enabled")); @@ -810,6 +810,7 @@ void CanvasItem::_bind_methods() { BIND_CONSTANT( BLEND_MODE_ADD ); BIND_CONSTANT( BLEND_MODE_SUB ); BIND_CONSTANT( BLEND_MODE_MUL ); + BIND_CONSTANT( BLEND_MODE_PREMULT_ALPHA ); BIND_CONSTANT( NOTIFICATION_DRAW); diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index 1c104c5fc2..604eef0527 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -49,7 +49,8 @@ public: BLEND_MODE_MIX, //default BLEND_MODE_ADD, BLEND_MODE_SUB, - BLEND_MODE_MUL + BLEND_MODE_MUL, + BLEND_MODE_PREMULT_ALPHA }; private: diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index a2bee43e58..85adfbbbde 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -224,6 +224,30 @@ Rect2 Node2D::get_item_rect() const { return Rect2(Point2(-32,-32),Size2(64,64)); } +void Node2D::rotate(float p_degrees) { + + set_rot( get_rot() + p_degrees); +} + +void Node2D::move_x(float p_delta,bool p_scaled){ + + Matrix32 t = get_transform(); + Vector2 m = t[0]; + if (!p_scaled) + m.normalize(); + set_pos(t[2]+m*p_delta); +} + +void Node2D::move_y(float p_delta,bool p_scaled){ + + Matrix32 t = get_transform(); + Vector2 m = t[1]; + if (!p_scaled) + m.normalize(); + set_pos(t[2]+m*p_delta); +} + + Point2 Node2D::get_global_pos() const { return get_global_transform().get_origin(); @@ -268,6 +292,10 @@ void Node2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_rot"),&Node2D::get_rot); ObjectTypeDB::bind_method(_MD("get_scale"),&Node2D::get_scale); + ObjectTypeDB::bind_method(_MD("rotate","degrees"),&Node2D::rotate); + ObjectTypeDB::bind_method(_MD("move_local_x","delta","scaled"),&Node2D::move_x,DEFVAL(false)); + ObjectTypeDB::bind_method(_MD("move_local_y","delta","scaled"),&Node2D::move_y,DEFVAL(false)); + ObjectTypeDB::bind_method(_MD("get_global_pos"),&Node2D::get_global_pos); ObjectTypeDB::bind_method(_MD("set_transform","xform"),&Node2D::set_transform); diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h index 8da441dc63..8e1f22c235 100644 --- a/scene/2d/node_2d.h +++ b/scene/2d/node_2d.h @@ -70,6 +70,10 @@ public: void set_rot(float p_angle); void set_scale(const Size2& p_scale); + void rotate(float p_degrees); + void move_x(float p_delta,bool p_scaled=false); + void move_y(float p_delta,bool p_scaled=false); + Point2 get_pos() const; float get_rot() const; Size2 get_scale() const; diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index a1e7195b0a..ecd147afde 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -43,9 +43,27 @@ void PhysicsBody2D::_notification(int p_what) { */ } -PhysicsBody2D::PhysicsBody2D(Physics2DServer::BodyMode p_mode) : CollisionObject2D( Physics2DServer::get_singleton()->body_create(p_mode), false) { +void PhysicsBody2D::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_layer_mask","mask"),&PhysicsBody2D::set_layer_mask); + ObjectTypeDB::bind_method(_MD("get_layer_mask"),&PhysicsBody2D::get_layer_mask); + ADD_PROPERTY(PropertyInfo(Variant::INT,"layers",PROPERTY_HINT_ALL_FLAGS),_SCS("set_layer_mask"),_SCS("get_layer_mask")); +} + +void PhysicsBody2D::set_layer_mask(uint32_t p_mask) { + + mask=p_mask; + Physics2DServer::get_singleton()->body_set_layer_mask(get_rid(),p_mask); +} + +uint32_t PhysicsBody2D::get_layer_mask() const { + return mask; +} + +PhysicsBody2D::PhysicsBody2D(Physics2DServer::BodyMode p_mode) : CollisionObject2D( Physics2DServer::get_singleton()->body_create(p_mode), false) { + mask=1; } @@ -789,7 +807,7 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { for(int i=0;i<get_shape_count();i++) { - if (dss->collide_shape(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i),Vector2(),margin,sr,max_shapes,res_shapes,exclude,0,mask)) + 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; } @@ -834,7 +852,7 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { 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,0,mask); + 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; @@ -865,7 +883,7 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { Matrix32 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,0,mask); + 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; @@ -927,7 +945,7 @@ bool KinematicBody2D::can_move_to(const Vector2& p_position, bool p_discrete) { for(int i=0;i<get_shape_count();i++) { - bool col = dss->intersect_shape(get_shape(i)->get_rid(), xform * get_shape_transform(i),motion,0,NULL,0,exclude,0,mask); + bool col = dss->intersect_shape(get_shape(i)->get_rid(), xform * get_shape_transform(i),motion,0,NULL,0,exclude,get_layer_mask(),mask); if (col) return false; } diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index e7b65b1ef3..1319d2e4f0 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -38,12 +38,18 @@ class PhysicsBody2D : public CollisionObject2D { OBJ_TYPE(PhysicsBody2D,CollisionObject2D); + uint32_t mask; protected: void _notification(int p_what); PhysicsBody2D(Physics2DServer::BodyMode p_mode); + + static void _bind_methods(); public: + void set_layer_mask(uint32_t p_mask); + uint32_t get_layer_mask() const; + PhysicsBody2D(); }; diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp index 540c825485..8479338521 100644 --- a/scene/2d/ray_cast_2d.cpp +++ b/scene/2d/ray_cast_2d.cpp @@ -43,6 +43,16 @@ Vector2 RayCast2D::get_cast_to() const{ return cast_to; } +void RayCast2D::set_layer_mask(uint32_t p_mask) { + + layer_mask=p_mask; +} + +uint32_t RayCast2D::get_layer_mask() const { + + return layer_mask; +} + bool RayCast2D::is_colliding() const{ return collided; @@ -152,7 +162,7 @@ void RayCast2D::_notification(int p_what) { Physics2DDirectSpaceState::RayResult rr; - if (dss->intersect_ray(gt.get_origin(),gt.xform(to),rr,exclude)) { + if (dss->intersect_ray(gt.get_origin(),gt.xform(to),rr,exclude,layer_mask)) { collided=true; against=rr.collider_id; @@ -228,8 +238,12 @@ void RayCast2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("clear_exceptions"),&RayCast2D::clear_exceptions); + ObjectTypeDB::bind_method(_MD("set_layer_mask","mask"),&RayCast2D::set_layer_mask); + ObjectTypeDB::bind_method(_MD("get_layer_mask"),&RayCast2D::get_layer_mask); + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled")); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"cast_to"),_SCS("set_cast_to"),_SCS("get_cast_to")); + ADD_PROPERTY(PropertyInfo(Variant::INT,"layer_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_layer_mask"),_SCS("get_layer_mask")); } RayCast2D::RayCast2D() { @@ -238,5 +252,6 @@ RayCast2D::RayCast2D() { against=0; collided=false; against_shape=0; + layer_mask=1; cast_to=Vector2(0,50); } diff --git a/scene/2d/ray_cast_2d.h b/scene/2d/ray_cast_2d.h index 32b95fbefe..b27fc4bf3d 100644 --- a/scene/2d/ray_cast_2d.h +++ b/scene/2d/ray_cast_2d.h @@ -43,6 +43,7 @@ class RayCast2D : public Node2D { Vector2 collision_point; Vector2 collision_normal; Set<RID> exclude; + uint32_t layer_mask; Vector2 cast_to; @@ -58,6 +59,9 @@ 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; + bool is_colliding() const; Object *get_collider() const; int get_collider_shape() const; diff --git a/scene/2d/screen_button.cpp b/scene/2d/screen_button.cpp index 32a5323419..9d0c9f3d1a 100644 --- a/scene/2d/screen_button.cpp +++ b/scene/2d/screen_button.cpp @@ -242,8 +242,8 @@ void TouchScreenButton::_input(const InputEvent& p_event) { touched=true; } } else { - - touched=Rect2(Point2(),texture->get_size()).has_point(coord); + if (!texture.is_null()) + touched=Rect2(Point2(),texture->get_size()).has_point(coord); } diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index c8711f10ac..6fe8b8c4c2 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -315,6 +315,7 @@ Map<TileMap::PosKey,TileMap::Quadrant>::Element *TileMap::_create_quadrant(const VisualServer::get_singleton()->canvas_item_set_parent( q.canvas_item, get_canvas_item() ); VisualServer::get_singleton()->canvas_item_set_transform( q.canvas_item, xform ); q.static_body=Physics2DServer::get_singleton()->body_create(Physics2DServer::BODY_MODE_STATIC); + Physics2DServer::get_singleton()->body_set_layer_mask(q.static_body,collision_layer); if (is_inside_scene()) { xform = get_global_transform() * xform; RID space = get_world_2d()->get_space(); @@ -545,6 +546,22 @@ Rect2 TileMap::get_item_rect() const { return rect_cache; } +void TileMap::set_collision_layer_mask(uint32_t p_layer) { + + collision_layer=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.static_body,collision_layer); + } +} + +uint32_t TileMap::get_collision_layer_mask() const { + + return collision_layer; +} + + void TileMap::_bind_methods() { @@ -564,6 +581,8 @@ void TileMap::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_center_y","enable"),&TileMap::set_center_y); ObjectTypeDB::bind_method(_MD("get_center_y"),&TileMap::get_center_y); + ObjectTypeDB::bind_method(_MD("set_collision_layer_mask","mask"),&TileMap::set_collision_layer_mask); + ObjectTypeDB::bind_method(_MD("get_collision_layer_mask"),&TileMap::get_collision_layer_mask); ObjectTypeDB::bind_method(_MD("set_cell","x","y","tile","flip_x","flip_y"),&TileMap::set_cell,DEFVAL(false),DEFVAL(false)); ObjectTypeDB::bind_method(_MD("get_cell","x","y"),&TileMap::get_cell); @@ -583,6 +602,7 @@ void TileMap::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::INT,"quadrant_size",PROPERTY_HINT_RANGE,"1,128,1"),_SCS("set_quadrant_size"),_SCS("get_quadrant_size")); ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"tile_set",PROPERTY_HINT_RESOURCE_TYPE,"TileSet"),_SCS("set_tileset"),_SCS("get_tileset")); ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"tile_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_tile_data"),_SCS("_get_tile_data")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"collision_layers",PROPERTY_HINT_ALL_FLAGS),_SCS("set_collision_layer_mask"),_SCS("get_collision_layer_mask")); ADD_SIGNAL(MethodInfo("settings_changed")); @@ -599,6 +619,7 @@ TileMap::TileMap() { cell_size=64; center_x=false; center_y=false; + collision_layer=1; fp_adjust=0.01; fp_adjust=0.01; diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index a2414382c6..9265a7b55e 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -98,6 +98,7 @@ class TileMap : public Node2D { Rect2 rect_cache; bool rect_cache_dirty; float fp_adjust; + uint32_t collision_layer; Map<PosKey,Quadrant>::Element *_create_quadrant(const PosKey& p_qk); @@ -145,6 +146,9 @@ public: Rect2 get_item_rect() const; + void set_collision_layer_mask(uint32_t p_layer); + uint32_t get_collision_layer_mask() const; + void clear(); TileMap(); diff --git a/scene/3d/baked_light.cpp b/scene/3d/baked_light.cpp new file mode 100644 index 0000000000..55832b7c18 --- /dev/null +++ b/scene/3d/baked_light.cpp @@ -0,0 +1,7 @@ +#include "baked_light.h" +#include "mesh_instance.h" + +BakedLight::BakedLight() { + + +} diff --git a/scene/3d/baked_light.h b/scene/3d/baked_light.h new file mode 100644 index 0000000000..a6f997afe9 --- /dev/null +++ b/scene/3d/baked_light.h @@ -0,0 +1,15 @@ +#ifndef BAKED_LIGHT_H +#define BAKED_LIGHT_H + +#include "scene/3d/spatial.h" +class BakedLightBaker; + + +class BakedLight : public Spatial { + OBJ_TYPE(BakedLight,Spatial); + +public: + BakedLight(); +}; + +#endif // BAKED_LIGHT_H diff --git a/scene/3d/immediate_geometry.cpp b/scene/3d/immediate_geometry.cpp new file mode 100644 index 0000000000..1459f2c362 --- /dev/null +++ b/scene/3d/immediate_geometry.cpp @@ -0,0 +1,102 @@ +#include "immediate_geometry.h" + + +void ImmediateGeometry::begin(Mesh::PrimitiveType p_primitive,const Ref<Texture>& p_texture) { + + VS::get_singleton()->immediate_begin(im,(VS::PrimitiveType)p_primitive,p_texture.is_valid()?p_texture->get_rid():RID()); + if (p_texture.is_valid()) + cached_textures.push_back(p_texture); + +} + +void ImmediateGeometry::set_normal(const Vector3& p_normal){ + + VS::get_singleton()->immediate_normal(im,p_normal); +} + +void ImmediateGeometry::set_tangent(const Plane& p_tangent){ + + VS::get_singleton()->immediate_tangent(im,p_tangent); + +} + +void ImmediateGeometry::set_color(const Color& p_color){ + + VS::get_singleton()->immediate_color(im,p_color); + +} + +void ImmediateGeometry::set_uv(const Vector2& p_uv){ + + VS::get_singleton()->immediate_uv(im,p_uv); + +} + +void ImmediateGeometry::set_uv2(const Vector2& p_uv2){ + + VS::get_singleton()->immediate_uv2(im,p_uv2); + +} + +void ImmediateGeometry::add_vertex(const Vector3& p_vertex){ + + VS::get_singleton()->immediate_vertex(im,p_vertex); + if (empty) { + aabb.pos=p_vertex; + aabb.size=Vector3(); + } else { + aabb.expand_to(p_vertex); + } +} + +void ImmediateGeometry::end(){ + + VS::get_singleton()->immediate_end(im); + +} + +void ImmediateGeometry::clear(){ + + VS::get_singleton()->immediate_clear(im); + empty=true; + cached_textures.clear(); + +} + +AABB ImmediateGeometry::get_aabb() const { + + return aabb; +} +DVector<Face3> ImmediateGeometry::get_faces(uint32_t p_usage_flags) const { + + return DVector<Face3>(); +} + +void ImmediateGeometry::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("begin","primitive","texture:Texture"),&ImmediateGeometry::begin); + ObjectTypeDB::bind_method(_MD("set_normal","normal"),&ImmediateGeometry::set_normal); + ObjectTypeDB::bind_method(_MD("set_tangent","tangent"),&ImmediateGeometry::set_tangent); + ObjectTypeDB::bind_method(_MD("set_color","color"),&ImmediateGeometry::set_color); + ObjectTypeDB::bind_method(_MD("set_uv","uv"),&ImmediateGeometry::set_uv); + ObjectTypeDB::bind_method(_MD("set_uv2","uv"),&ImmediateGeometry::set_uv2); + ObjectTypeDB::bind_method(_MD("add_vertex","color"),&ImmediateGeometry::add_vertex); + ObjectTypeDB::bind_method(_MD("end"),&ImmediateGeometry::end); + ObjectTypeDB::bind_method(_MD("clear"),&ImmediateGeometry::clear); + +} + +ImmediateGeometry::ImmediateGeometry() { + + im = VisualServer::get_singleton()->immediate_create(); + set_base(im); + empty=true; + +} + + +ImmediateGeometry::~ImmediateGeometry() { + + VisualServer::get_singleton()->free(im); + +} diff --git a/scene/3d/immediate_geometry.h b/scene/3d/immediate_geometry.h new file mode 100644 index 0000000000..2db81134c6 --- /dev/null +++ b/scene/3d/immediate_geometry.h @@ -0,0 +1,41 @@ +#ifndef IMMEDIATE_GEOMETRY_H +#define IMMEDIATE_GEOMETRY_H + +#include "scene/3d/visual_instance.h" +#include "scene/resources/mesh.h" + +class ImmediateGeometry : public GeometryInstance { + + OBJ_TYPE(ImmediateGeometry,GeometryInstance); + + + RID im; + List<Ref<Texture> > cached_textures; + bool empty; + AABB aabb; +protected: + + static void _bind_methods(); +public: + + + void begin(Mesh::PrimitiveType p_primitive,const Ref<Texture>& p_texture); + 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 add_vertex(const Vector3& p_vertex); + + void end(); + void clear(); + + virtual AABB get_aabb() const; + virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const; + + ImmediateGeometry(); + ~ImmediateGeometry(); +}; + +#endif // IMMEDIATE_GEOMETRY_H diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp index 94c56850ef..b4b7b400c6 100644 --- a/scene/3d/light.cpp +++ b/scene/3d/light.cpp @@ -540,14 +540,15 @@ void DirectionalLight::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_shadow_param","param","value"),&DirectionalLight::set_shadow_param); ObjectTypeDB::bind_method(_MD("get_shadow_param","param"),&DirectionalLight::get_shadow_param); - ADD_PROPERTY( PropertyInfo(Variant::INT,"shadow/mode",PROPERTY_HINT_ENUM,"Orthogonal,Perspective,PSSM"),_SCS("set_shadow_mode"),_SCS("get_shadow_mode")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"shadow/mode",PROPERTY_HINT_ENUM,"Orthogonal,Perspective,PSSM 2 Splits,PSSM 4 Splits"),_SCS("set_shadow_mode"),_SCS("get_shadow_mode")); ADD_PROPERTYI( PropertyInfo(Variant::REAL,"shadow/max_distance",PROPERTY_HINT_EXP_RANGE,"0.00,99999,0.01"),_SCS("set_shadow_param"),_SCS("get_shadow_param"), SHADOW_PARAM_MAX_DISTANCE); ADD_PROPERTYI( PropertyInfo(Variant::REAL,"shadow/split_weight",PROPERTY_HINT_RANGE,"0.01,1.0,0.01"),_SCS("set_shadow_param"),_SCS("get_shadow_param"), SHADOW_PARAM_PSSM_SPLIT_WEIGHT); ADD_PROPERTYI( PropertyInfo(Variant::REAL,"shadow/zoffset_scale",PROPERTY_HINT_RANGE,"0.01,1024.0,0.01"),_SCS("set_shadow_param"),_SCS("get_shadow_param"), SHADOW_PARAM_PSSM_ZOFFSET_SCALE); BIND_CONSTANT( SHADOW_ORTHOGONAL ); BIND_CONSTANT( SHADOW_PERSPECTIVE ); - BIND_CONSTANT( SHADOW_PARALLEL_SPLIT ); + BIND_CONSTANT( SHADOW_PARALLEL_2_SPLITS ); + BIND_CONSTANT( SHADOW_PARALLEL_4_SPLITS ); BIND_CONSTANT( SHADOW_PARAM_MAX_DISTANCE ); BIND_CONSTANT( SHADOW_PARAM_PSSM_SPLIT_WEIGHT ); BIND_CONSTANT( SHADOW_PARAM_PSSM_ZOFFSET_SCALE ); diff --git a/scene/3d/light.h b/scene/3d/light.h index 03bf336303..dea7dbee6c 100644 --- a/scene/3d/light.h +++ b/scene/3d/light.h @@ -138,7 +138,8 @@ public: enum ShadowMode { SHADOW_ORTHOGONAL, SHADOW_PERSPECTIVE, - SHADOW_PARALLEL_SPLIT + SHADOW_PARALLEL_2_SPLITS, + SHADOW_PARALLEL_4_SPLITS }; enum ShadowParam { SHADOW_PARAM_MAX_DISTANCE, diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp index 6387f5fdbc..40981d468e 100644 --- a/scene/3d/mesh_instance.cpp +++ b/scene/3d/mesh_instance.cpp @@ -113,6 +113,27 @@ Ref<Mesh> MeshInstance::get_mesh() const { return mesh; } +void MeshInstance::_resolve_skeleton_path(){ + + if (skeleton_path.is_empty()) + return; + + Skeleton *skeleton=get_node(skeleton_path)?get_node(skeleton_path)->cast_to<Skeleton>():NULL; + if (skeleton) + VisualServer::get_singleton()->instance_attach_skeleton( get_instance(), skeleton->get_skeleton() ); +} + +void MeshInstance::set_skeleton_path(const NodePath &p_skeleton) { + + skeleton_path = p_skeleton; + if (!is_inside_scene()) + return; + _resolve_skeleton_path(); +} + +NodePath MeshInstance::get_skeleton_path() { + return skeleton_path; +} AABB MeshInstance::get_aabb() const { @@ -192,22 +213,32 @@ void MeshInstance::create_convex_collision() { } +void MeshInstance::_notification(int p_what) { + + if (p_what==NOTIFICATION_ENTER_SCENE) { + _resolve_skeleton_path(); + } +} + + void MeshInstance::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_mesh","mesh:Mesh"),&MeshInstance::set_mesh); ObjectTypeDB::bind_method(_MD("get_mesh:Mesh"),&MeshInstance::get_mesh); + ObjectTypeDB::bind_method(_MD("set_skeleton_path","skeleton_path:NodePath"),&MeshInstance::set_skeleton_path); + ObjectTypeDB::bind_method(_MD("get_skeleton_path:NodePath"),&MeshInstance::get_skeleton_path); ObjectTypeDB::bind_method(_MD("get_aabb"),&MeshInstance::get_aabb); ObjectTypeDB::bind_method(_MD("create_trimesh_collision"),&MeshInstance::create_trimesh_collision); ObjectTypeDB::set_method_flags("MeshInstance","create_trimesh_collision",METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); ObjectTypeDB::bind_method(_MD("create_convex_collision"),&MeshInstance::create_convex_collision); ObjectTypeDB::set_method_flags("MeshInstance","create_convex_collision",METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "mesh/mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh" ), _SCS("set_mesh"), _SCS("get_mesh")); - - + ADD_PROPERTY( PropertyInfo (Variant::NODE_PATH, "mesh/skeleton"), _SCS("set_skeleton_path"), _SCS("get_skeleton_path")); } MeshInstance::MeshInstance() { + skeleton_path=NodePath(".."); } diff --git a/scene/3d/mesh_instance.h b/scene/3d/mesh_instance.h index 0e07109502..1b97564b4e 100644 --- a/scene/3d/mesh_instance.h +++ b/scene/3d/mesh_instance.h @@ -40,6 +40,7 @@ class MeshInstance : public GeometryInstance { OBJ_TYPE( MeshInstance, GeometryInstance ); Ref<Mesh> mesh; + NodePath skeleton_path; struct MorphTrack { @@ -50,6 +51,7 @@ class MeshInstance : public GeometryInstance { Map<StringName,MorphTrack> morph_tracks; + void _resolve_skeleton_path(); protected: @@ -57,12 +59,15 @@ protected: 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 set_mesh(const Ref<Mesh>& p_mesh); Ref<Mesh> get_mesh() const; + + void set_skeleton_path(const NodePath& p_skeleton); + NodePath get_skeleton_path(); Node* create_trimesh_collision_node(); void create_trimesh_collision(); diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 0733a9196e..2a1a5972a9 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -632,6 +632,16 @@ bool RigidBody::is_contact_monitor_enabled() const { return contact_monitor!=NULL; } +void RigidBody::set_axis_lock(AxisLock p_lock) { + + axis_lock=p_lock; + PhysicsServer::get_singleton()->body_set_axis_lock(get_rid(),PhysicsServer::BodyAxisLock(axis_lock)); +} + +RigidBody::AxisLock RigidBody::get_axis_lock() const { + + return axis_lock; +} void RigidBody::_bind_methods() { @@ -682,6 +692,9 @@ void RigidBody::_bind_methods() { ObjectTypeDB::bind_method(_MD("_body_enter_scene"),&RigidBody::_body_enter_scene); ObjectTypeDB::bind_method(_MD("_body_exit_scene"),&RigidBody::_body_exit_scene); + ObjectTypeDB::bind_method(_MD("set_axis_lock","axis_lock"),&RigidBody::set_axis_lock); + ObjectTypeDB::bind_method(_MD("get_axis_lock"),&RigidBody::get_axis_lock); + BIND_VMETHOD(MethodInfo("_integrate_forces",PropertyInfo(Variant::OBJECT,"state:PhysicsDirectBodyState"))); ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Rigid,Static,Character,Kinematic"),_SCS("set_mode"),_SCS("get_mode")); @@ -695,6 +708,7 @@ void RigidBody::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::BOOL,"contact_monitor"),_SCS("set_contact_monitor"),_SCS("is_contact_monitor_enabled")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"active"),_SCS("set_active"),_SCS("is_active")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"can_sleep"),_SCS("set_can_sleep"),_SCS("is_able_to_sleep")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"axis_lock",PROPERTY_HINT_ENUM,"Disabled,Lock X,Lock Y,Lock Z"),_SCS("set_axis_lock"),_SCS("get_axis_lock")); ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"velocity/linear"),_SCS("set_linear_velocity"),_SCS("get_linear_velocity")); ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"velocity/angular"),_SCS("set_angular_velocity"),_SCS("get_angular_velocity")); @@ -727,6 +741,8 @@ RigidBody::RigidBody() : PhysicsBody(PhysicsServer::BODY_MODE_RIGID) { contact_monitor=NULL; can_sleep=true; + axis_lock = AXIS_LOCK_DISABLED; + PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(),this,"_direct_state_changed"); } diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h index a5faa9857b..6695ee719a 100644 --- a/scene/3d/physics_body.h +++ b/scene/3d/physics_body.h @@ -94,6 +94,14 @@ public: MODE_CHARACTER, MODE_KINEMATIC, }; + + enum AxisLock { + AXIS_LOCK_DISABLED, + AXIS_LOCK_X, + AXIS_LOCK_Y, + AXIS_LOCK_Z, + }; + private: bool can_sleep; @@ -109,6 +117,8 @@ private: bool active; bool ccd; + AxisLock axis_lock; + int max_contacts_reported; @@ -208,6 +218,10 @@ public: void set_use_continuous_collision_detection(bool p_enable); bool is_using_continuous_collision_detection() const; + void set_axis_lock(AxisLock p_lock); + AxisLock get_axis_lock() const; + + void apply_impulse(const Vector3& p_pos, const Vector3& p_impulse); RigidBody(); @@ -216,4 +230,5 @@ public: }; VARIANT_ENUM_CAST(RigidBody::Mode); +VARIANT_ENUM_CAST(RigidBody::AxisLock); #endif // PHYSICS_BODY__H diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp new file mode 100644 index 0000000000..21fdb9abd3 --- /dev/null +++ b/scene/3d/sprite_3d.cpp @@ -0,0 +1,772 @@ +#include "sprite_3d.h" +#include "scene/scene_string_names.h" +#include "core_string_names.h" + + +Color SpriteBase3D::_get_color_accum() { + + if (!color_dirty) + return color_accum; + + if (parent_sprite) + color_accum=parent_sprite->_get_color_accum(); + else + color_accum=Color(1,1,1,1); + + color_accum.r*=modulate.r; + color_accum.g*=modulate.g; + color_accum.b*=modulate.b; + color_accum.a*=modulate.a; + color_dirty=false; + return color_accum; +} + +void SpriteBase3D::_propagate_color_changed() { + + if (color_dirty) + return; + + color_dirty=true; + _queue_update(); + + for (List<SpriteBase3D*>::Element *E=children.front();E;E=E->next()) { + + E->get()->_propagate_color_changed(); + } +} + +void SpriteBase3D::_notification(int p_what) { + + if (p_what==NOTIFICATION_ENTER_SCENE) { + + if (!pending_update) + _im_update(); + + Node *parent=get_parent(); + if (parent) { + + parent_sprite=parent->cast_to<SpriteBase3D>(); + if (parent_sprite) { + pI=parent_sprite->children.push_back(this); + } + } + } + + if (p_what==NOTIFICATION_EXIT_SCENE) { + + + if (parent_sprite) { + + parent_sprite->children.erase(pI); + pI=NULL; + parent_sprite=NULL; + } + } + +} + + +void SpriteBase3D::set_centered(bool p_center) { + + centered=p_center; + _queue_update(); + +} + +bool SpriteBase3D::is_centered() const { + + return centered; +} + +void SpriteBase3D::set_offset(const Point2& p_offset) { + + offset=p_offset; + _queue_update(); + +} +Point2 SpriteBase3D::get_offset() const { + + return offset; +} + +void SpriteBase3D::set_flip_h(bool p_flip) { + + hflip=p_flip; + _queue_update(); +} +bool SpriteBase3D::is_flipped_h() const { + + return hflip; +} + +void SpriteBase3D::set_flip_v(bool p_flip) { + + vflip=p_flip; + _queue_update(); +} +bool SpriteBase3D::is_flipped_v() const { + + return vflip; +} + + + +void SpriteBase3D::set_modulate(const Color& p_color) { + + modulate=p_color; + _propagate_color_changed(); + _queue_update(); +} + +Color SpriteBase3D::get_modulate() const{ + + return modulate; +} + + +void SpriteBase3D::set_pixel_size(float p_amount) { + + pixel_size=p_amount; + _queue_update(); +} +float SpriteBase3D::get_pixel_size() const { + + return pixel_size; +} + +void SpriteBase3D::set_opacity(float p_amount) { + + opacity=p_amount; + _queue_update(); +} +float SpriteBase3D::get_opacity() const { + + return opacity; +} + + +void SpriteBase3D::set_axis(Vector3::Axis p_axis) { + + axis=p_axis; + _queue_update(); +} +Vector3::Axis SpriteBase3D::get_axis() const { + + return axis; +} + + + +void SpriteBase3D::_im_update() { + + + _draw(); + + + pending_update=false; + + //texture->draw_rect_region(ci,dst_rect,src_rect,modulate); + +} + +void SpriteBase3D::_queue_update(){ + + if (pending_update) + return; + + pending_update=true; + call_deferred(SceneStringNames::get_singleton()->_im_update); +} + + +AABB SpriteBase3D::get_aabb() const { + + return aabb; +} +DVector<Face3> SpriteBase3D::get_faces(uint32_t p_usage_flags) const { + + return DVector<Face3>(); + +} + +void SpriteBase3D::set_draw_flag(DrawFlags p_flag,bool p_enable) { + + ERR_FAIL_INDEX(p_flag,FLAG_MAX); + flags[p_flag]=p_enable; + _queue_update(); +} + +bool SpriteBase3D::get_draw_flag(DrawFlags p_flag) const{ + ERR_FAIL_INDEX_V(p_flag,FLAG_MAX,false); + return flags[p_flag]; +} + +void SpriteBase3D::set_alpha_cut_mode(AlphaCutMode p_mode){ + + ERR_FAIL_INDEX(p_mode,3); + alpha_cut=p_mode; + _queue_update(); + +} + +SpriteBase3D::AlphaCutMode SpriteBase3D::get_alpha_cut_mode() const{ + + return alpha_cut; +} + + +void SpriteBase3D::_bind_methods() { + + + ObjectTypeDB::bind_method(_MD("set_centered","centered"),&SpriteBase3D::set_centered); + ObjectTypeDB::bind_method(_MD("is_centered"),&SpriteBase3D::is_centered); + + ObjectTypeDB::bind_method(_MD("set_offset","offset"),&SpriteBase3D::set_offset); + ObjectTypeDB::bind_method(_MD("get_offset"),&SpriteBase3D::get_offset); + + ObjectTypeDB::bind_method(_MD("set_flip_h","flip_h"),&SpriteBase3D::set_flip_h); + ObjectTypeDB::bind_method(_MD("is_flipped_h"),&SpriteBase3D::is_flipped_h); + + ObjectTypeDB::bind_method(_MD("set_flip_v","flip_v"),&SpriteBase3D::set_flip_v); + ObjectTypeDB::bind_method(_MD("is_flipped_v"),&SpriteBase3D::is_flipped_v); + + + ObjectTypeDB::bind_method(_MD("set_modulate","modulate"),&SpriteBase3D::set_modulate); + ObjectTypeDB::bind_method(_MD("get_modulate"),&SpriteBase3D::get_modulate); + + ObjectTypeDB::bind_method(_MD("set_opacity","opacity"),&SpriteBase3D::set_opacity); + ObjectTypeDB::bind_method(_MD("get_opacity"),&SpriteBase3D::get_opacity); + + ObjectTypeDB::bind_method(_MD("set_pixel_size","pixel_size"),&SpriteBase3D::set_pixel_size); + ObjectTypeDB::bind_method(_MD("get_pixel_size"),&SpriteBase3D::get_pixel_size); + + ObjectTypeDB::bind_method(_MD("set_axis","axis"),&SpriteBase3D::set_axis); + ObjectTypeDB::bind_method(_MD("get_axis"),&SpriteBase3D::get_axis); + + ObjectTypeDB::bind_method(_MD("set_draw_flag","flag","enabled"),&SpriteBase3D::set_draw_flag); + ObjectTypeDB::bind_method(_MD("get_draw_flag","flag"),&SpriteBase3D::get_draw_flag); + + ObjectTypeDB::bind_method(_MD("set_alpha_cut_mode","mode"),&SpriteBase3D::set_alpha_cut_mode); + ObjectTypeDB::bind_method(_MD("get_alpha_cut_mode"),&SpriteBase3D::get_alpha_cut_mode); + + ObjectTypeDB::bind_method(_MD("get_item_rect"),&SpriteBase3D::get_item_rect); + + ObjectTypeDB::bind_method(_MD("_queue_update"),&SpriteBase3D::_queue_update); + ObjectTypeDB::bind_method(_MD("_im_update"),&SpriteBase3D::_im_update); + + + ADD_PROPERTY( PropertyInfo( Variant::BOOL, "centered"), _SCS("set_centered"),_SCS("is_centered")); + ADD_PROPERTY( PropertyInfo( Variant::VECTOR2, "offset"), _SCS("set_offset"),_SCS("get_offset")); + ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flip_h"), _SCS("set_flip_h"),_SCS("is_flipped_h")); + ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flip_v"), _SCS("set_flip_v"),_SCS("is_flipped_v")); + ADD_PROPERTY( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate")); + ADD_PROPERTY( PropertyInfo( Variant::REAL, "opacity",PROPERTY_HINT_RANGE,"0,1,0.01"), _SCS("set_opacity"),_SCS("get_opacity")); + ADD_PROPERTY( PropertyInfo( Variant::REAL, "pixel_size",PROPERTY_HINT_RANGE,"0.0001,128,0.0001"), _SCS("set_pixel_size"),_SCS("get_pixel_size")); + ADD_PROPERTY( PropertyInfo( Variant::INT, "axis",PROPERTY_HINT_ENUM,"X-Axis,Y-Axis,Z-Axis"), _SCS("set_axis"),_SCS("get_axis")); + ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "flags/transparent"), _SCS("set_draw_flag"),_SCS("get_draw_flag"),FLAG_TRANSPARENT); + ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "flags/shaded"), _SCS("set_draw_flag"),_SCS("get_draw_flag"),FLAG_SHADED); + ADD_PROPERTY( PropertyInfo( Variant::INT, "flags/alpha_cut",PROPERTY_HINT_ENUM,"Disabled,Discard,Opaque Pre-Pass"), _SCS("set_alpha_cut_mode"),_SCS("get_alpha_cut_mode")); + + + BIND_CONSTANT( FLAG_TRANSPARENT ); + BIND_CONSTANT( FLAG_SHADED ); + BIND_CONSTANT( FLAG_MAX ); + + BIND_CONSTANT( ALPHA_CUT_DISABLED ); + BIND_CONSTANT( ALPHA_CUT_DISCARD ); + BIND_CONSTANT( ALPHA_CUT_OPAQUE_PREPASS ); +} + + + + +SpriteBase3D::SpriteBase3D() { + + color_dirty=true; + centered=true; + hflip=false; + vflip=false; + parent_sprite=NULL; + pI=NULL; + + for(int i=0;i<4;i++) + flags[i]=i==FLAG_TRANSPARENT; + + axis=Vector3::AXIS_Z; + pixel_size=0.01; + modulate=Color(1,1,1,1); + pending_update=false; + opacity=1.0; + immediate = VisualServer::get_singleton()->immediate_create(); + set_base(immediate); +} + + +SpriteBase3D::~SpriteBase3D() { + + VisualServer::get_singleton()->free(immediate); +} + + +/////////////////////////////////////////// + + +void Sprite3D::_draw() { + + RID immediate = get_immediate(); + + VS::get_singleton()->immediate_clear(immediate); + if (!texture.is_valid()) + return; //no texuture no life + Vector2 tsize = texture->get_size(); + if (tsize.x==0 || tsize.y==0) + return; + + Size2i s; + Rect2i src_rect; + + if (region) { + + s=region_rect.size; + src_rect=region_rect; + } else { + s = texture->get_size(); + 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; + + } + + Point2i ofs=get_offset(); + if (is_centered()) + ofs-=s/2; + + Rect2i dst_rect(ofs,s); + + + Rect2 final_rect; + Rect2 final_src_rect; + if (!texture->get_rect_region(dst_rect,src_rect,final_rect,final_src_rect)) + return; + + + if (final_rect.size.x==0 || final_rect.size.y==0) + return; + + Color color=_get_color_accum(); + color.a*=get_opacity(); + + float pixel_size=get_pixel_size(); + + 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, + + + }; + 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, + }; + + if (is_flipped_h()) { + SWAP(uvs[0],uvs[1]); + SWAP(uvs[2],uvs[3]); + } + if (is_flipped_v()) { + + SWAP(uvs[0],uvs[3]); + SWAP(uvs[1],uvs[2]); + } + + + Vector3 normal; + 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); + VS::get_singleton()->immediate_set_material(immediate,mat); + + VS::get_singleton()->immediate_begin(immediate,VS::PRIMITIVE_TRIANGLE_FAN,texture->get_rid()); + + int x_axis = ((axis + 1) % 3); + int y_axis = ((axis + 2) % 3); + + AABB aabb; + + for(int i=0;i<4;i++) { + VS::get_singleton()->immediate_normal(immediate,normal); + VS::get_singleton()->immediate_color(immediate,color); + VS::get_singleton()->immediate_uv(immediate,uvs[i]); + + Vector3 vtx; + vtx[x_axis]=vertices[i][x_axis]; + vtx[y_axis]=vertices[i][y_axis]; + VS::get_singleton()->immediate_vertex(immediate,vtx); + if (i==0) { + aabb.pos=vtx; + aabb.size=Vector3(); + } else { + aabb.expand_to(vtx); + } + } + set_aabb(aabb); + VS::get_singleton()->immediate_end(immediate); + + +} + +void Sprite3D::set_texture(const Ref<Texture>& p_texture) { + + if (p_texture==texture) + return; + if (texture.is_valid()) { + texture->disconnect(CoreStringNames::get_singleton()->changed,this,SceneStringNames::get_singleton()->_queue_update); + } + texture=p_texture; + 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()->_queue_update); + } + _queue_update(); + +} + +Ref<Texture> Sprite3D::get_texture() const { + + return texture; +} + +void Sprite3D::set_region(bool p_region) { + + if (p_region==region) + return; + + region=p_region; + _queue_update(); +} + +bool Sprite3D::is_region() const{ + + return region; +} + +void Sprite3D::set_region_rect(const Rect2& p_region_rect) { + + bool changed=region_rect!=p_region_rect; + region_rect=p_region_rect; + if (region && changed) { + _queue_update(); + } +} + +Rect2 Sprite3D::get_region_rect() const { + + return region_rect; +} + +void Sprite3D::set_frame(int p_frame) { + + ERR_FAIL_INDEX(p_frame,vframes*hframes); + + if (frame != p_frame) + + frame=p_frame; +} + +int Sprite3D::get_frame() const { + + return frame; +} + +void Sprite3D::set_vframes(int p_amount) { + + ERR_FAIL_COND(p_amount<1); + vframes=p_amount; + _queue_update(); + _change_notify("frame"); +} +int Sprite3D::get_vframes() const { + + return vframes; +} + +void Sprite3D::set_hframes(int p_amount) { + + ERR_FAIL_COND(p_amount<1); + hframes=p_amount; + _queue_update(); + _change_notify("frame"); +} +int Sprite3D::get_hframes() const { + + return hframes; +} + +Rect2 Sprite3D::get_item_rect() const { + + if (texture.is_null()) + return Rect2(0,0,1,1); + //if (texture.is_null()) + // return CanvasItem::get_item_rect(); + + Size2i s; + + if (region) { + + s=region_rect.size; + } else { + s = texture->get_size(); + s=s/Point2(hframes,vframes); + } + + Point2i ofs=get_offset(); + if (is_centered()) + ofs-=s/2; + + if (s==Size2(0,0)) + s=Size2(1,1); + + return Rect2(ofs,s); +} + +void Sprite3D::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_texture","texture:Texture"),&Sprite3D::set_texture); + ObjectTypeDB::bind_method(_MD("get_texture:Texture"),&Sprite3D::get_texture); + + ObjectTypeDB::bind_method(_MD("set_region","enabled"),&Sprite3D::set_region); + ObjectTypeDB::bind_method(_MD("is_region"),&Sprite3D::is_region); + + ObjectTypeDB::bind_method(_MD("set_region_rect","rect"),&Sprite3D::set_region_rect); + ObjectTypeDB::bind_method(_MD("get_region_rect"),&Sprite3D::get_region_rect); + + ObjectTypeDB::bind_method(_MD("set_frame","frame"),&Sprite3D::set_frame); + ObjectTypeDB::bind_method(_MD("get_frame"),&Sprite3D::get_frame); + + ObjectTypeDB::bind_method(_MD("set_vframes","vframes"),&Sprite3D::set_vframes); + ObjectTypeDB::bind_method(_MD("get_vframes"),&Sprite3D::get_vframes); + + ObjectTypeDB::bind_method(_MD("set_hframes","hframes"),&Sprite3D::set_hframes); + ObjectTypeDB::bind_method(_MD("get_hframes"),&Sprite3D::get_hframes); + + ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_texture"),_SCS("get_texture")); + ADD_PROPERTY( PropertyInfo( Variant::INT, "vframes"), _SCS("set_vframes"),_SCS("get_vframes")); + ADD_PROPERTY( PropertyInfo( Variant::INT, "hframes"), _SCS("set_hframes"),_SCS("get_hframes")); + ADD_PROPERTY( PropertyInfo( Variant::INT, "frame"), _SCS("set_frame"),_SCS("get_frame")); + ADD_PROPERTY( PropertyInfo( Variant::BOOL, "region"), _SCS("set_region"),_SCS("is_region")); + ADD_PROPERTY( PropertyInfo( Variant::RECT2, "region_rect"), _SCS("set_region_rect"),_SCS("get_region_rect")); + +} + +Sprite3D::Sprite3D() { + + + region=false; + frame=0; + vframes=1; + hframes=1; + +} + +//////////////////////////////////////// + + +void AnimatedSprite3D::_draw() { + + RID immediate = get_immediate(); + VS::get_singleton()->immediate_clear(immediate); + + if (!frames.is_valid() || !frames->get_frame_count() || frame<0 || frame>=frames->get_frame_count()) { + return; + } + + Ref<Texture> texture = frames->get_frame(frame); + if (!texture.is_valid()) + return; //no texuture no life + Vector2 tsize = texture->get_size(); + if (tsize.x==0 || tsize.y==0) + return; + + Size2i s=tsize; + Rect2i src_rect; + + src_rect.size=s; + + Point2i ofs=get_offset(); + if (is_centered()) + ofs-=s/2; + + Rect2i dst_rect(ofs,s); + + + Rect2 final_rect; + Rect2 final_src_rect; + if (!texture->get_rect_region(dst_rect,src_rect,final_rect,final_src_rect)) + return; + + + if (final_rect.size.x==0 || final_rect.size.y==0) + return; + + Color color=_get_color_accum(); + color.a*=get_opacity(); + + float pixel_size=get_pixel_size(); + + 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, + + + }; + 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, + }; + + if (is_flipped_h()) { + SWAP(uvs[0],uvs[1]); + SWAP(uvs[2],uvs[3]); + } + if (is_flipped_v()) { + + SWAP(uvs[0],uvs[3]); + SWAP(uvs[1],uvs[2]); + } + + + Vector3 normal; + 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); + VS::get_singleton()->immediate_set_material(immediate,mat); + + VS::get_singleton()->immediate_begin(immediate,VS::PRIMITIVE_TRIANGLE_FAN,texture->get_rid()); + + int x_axis = ((axis + 1) % 3); + int y_axis = ((axis + 2) % 3); + + AABB aabb; + + for(int i=0;i<4;i++) { + VS::get_singleton()->immediate_normal(immediate,normal); + VS::get_singleton()->immediate_color(immediate,color); + VS::get_singleton()->immediate_uv(immediate,uvs[i]); + + Vector3 vtx; + vtx[x_axis]=vertices[i][x_axis]; + vtx[y_axis]=vertices[i][y_axis]; + VS::get_singleton()->immediate_vertex(immediate,vtx); + if (i==0) { + aabb.pos=vtx; + aabb.size=Vector3(); + } else { + aabb.expand_to(vtx); + } + } + set_aabb(aabb); + VS::get_singleton()->immediate_end(immediate); + +} + +void AnimatedSprite3D::_bind_methods(){ + + ObjectTypeDB::bind_method(_MD("set_sprite_frames","sprite_frames:SpriteFrames"),&AnimatedSprite3D::set_sprite_frames); + ObjectTypeDB::bind_method(_MD("get_sprite_frames:Texture"),&AnimatedSprite3D::get_sprite_frames); + ObjectTypeDB::bind_method(_MD("set_frame","frame"),&AnimatedSprite3D::set_frame); + ObjectTypeDB::bind_method(_MD("get_frame"),&AnimatedSprite3D::get_frame); + + ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "frames", PROPERTY_HINT_RESOURCE_TYPE,"SpriteFrames"), _SCS("set_sprite_frames"),_SCS("get_sprite_frames")); + ADD_PROPERTY( PropertyInfo( Variant::INT, "frame"), _SCS("set_frame"),_SCS("get_frame")); + +} + + + + +void AnimatedSprite3D::set_sprite_frames(const Ref<SpriteFrames>& p_sprite_frames) { + + + if (frames==p_sprite_frames) + return; + + if (frames.is_valid()) + frames->disconnect("changed",this,"_queue_update"); + frames=p_sprite_frames; + if (frames.is_valid()) + frames->connect("changed",this,"_queue_update"); + + if (!frames.is_valid() || frame >=frames->get_frame_count()) { + frame=0; + + } + _queue_update(); + +} + +Ref<SpriteFrames> AnimatedSprite3D::get_sprite_frames() const{ + + return frames; +} + +void AnimatedSprite3D::set_frame(int p_frame){ + + if (frames.is_null()) + return; + + ERR_FAIL_INDEX(p_frame,frames->get_frame_count()); + + if (frame==p_frame) + return; + + frame=p_frame; + _queue_update(); + +} +int AnimatedSprite3D::get_frame() const{ + + return frame; +} + +Rect2 AnimatedSprite3D::get_item_rect() const { + + if (!frames.is_valid() || !frames->get_frame_count() || frame<0 || frame>=frames->get_frame_count()) { + return Rect2(0,0,1,1); + } + + Ref<Texture> t = frames->get_frame(frame); + if (t.is_null()) + return Rect2(0,0,1,1); + Size2i s = t->get_size(); + + Point2i ofs=get_offset(); + if (is_centered()) + ofs-=s/2; + + if (s==Size2(0,0)) + s=Size2(1,1); + + return Rect2(ofs,s); +} + + + +AnimatedSprite3D::AnimatedSprite3D() { + + frame=0; +} + diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h new file mode 100644 index 0000000000..1330cd1c30 --- /dev/null +++ b/scene/3d/sprite_3d.h @@ -0,0 +1,191 @@ +#ifndef SPRITE_3D_H +#define SPRITE_3D_H + +#include "scene/3d/visual_instance.h" +#include "scene/2d/animated_sprite.h" + + +class SpriteBase3D : public VisualInstance { + + OBJ_TYPE(SpriteBase3D,VisualInstance); +public: + + enum DrawFlags { + FLAG_TRANSPARENT, + FLAG_SHADED, + FLAG_MAX + + }; + + enum AlphaCutMode { + ALPHA_CUT_DISABLED, + ALPHA_CUT_DISCARD, + ALPHA_CUT_OPAQUE_PREPASS + }; + +private: + + + bool color_dirty; + Color color_accum; + + SpriteBase3D *parent_sprite; + List<SpriteBase3D*> children; + List<SpriteBase3D*>::Element *pI; + + bool centered; + Point2 offset; + + bool hflip; + bool vflip; + + + Color modulate; + float opacity; + + Vector3::Axis axis; + float pixel_size; + AABB aabb; + + RID immediate; + + bool flags[FLAG_MAX]; + AlphaCutMode alpha_cut; + bool pending_update; + void _im_update(); + + + void _propagate_color_changed(); + +protected: + + Color _get_color_accum(); + void _notification(int p_what); + static void _bind_methods(); + virtual void _draw()=0; + _FORCE_INLINE_ void set_aabb(const AABB& p_aabb) { aabb=p_aabb; } + _FORCE_INLINE_ RID& get_immediate() { return immediate; } + void _queue_update(); +public: + + void set_centered(bool p_center); + bool is_centered() const; + + void set_offset(const Point2& p_offset); + Point2 get_offset() 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_region(bool p_region); + bool is_region() const; + + void set_region_rect(const Rect2& p_region_rect); + Rect2 get_region_rect() const; + + void set_modulate(const Color& p_color); + Color get_modulate() const; + + void set_opacity(float p_amount); + float get_opacity() const; + + void set_pixel_size(float p_amount); + float get_pixel_size() const; + + void set_axis(Vector3::Axis p_amount); + Vector3::Axis get_axis() const; + + void set_draw_flag(DrawFlags p_flag,bool p_enable); + bool get_draw_flag(DrawFlags p_flag) const; + + void set_alpha_cut_mode(AlphaCutMode p_mode); + AlphaCutMode get_alpha_cut_mode() const; + + virtual Rect2 get_item_rect() const=0; + + virtual AABB get_aabb() const; + virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const; + + SpriteBase3D(); + ~SpriteBase3D(); +}; + + +class Sprite3D : public SpriteBase3D { + + OBJ_TYPE(Sprite3D,SpriteBase3D); + Ref<Texture> texture; + + + bool region; + Rect2 region_rect; + + int frame; + + int vframes; + int hframes; +protected: + virtual void _draw(); + static void _bind_methods(); +public: + + + + void set_texture(const Ref<Texture>& p_texture); + Ref<Texture> get_texture() const; + + void set_region(bool p_region); + bool is_region() const; + + void set_region_rect(const Rect2& p_region_rect); + Rect2 get_region_rect() const; + + void set_frame(int p_frame); + int get_frame() const; + + void set_vframes(int p_amount); + int get_vframes() const; + + void set_hframes(int p_amount); + int get_hframes() const; + + virtual Rect2 get_item_rect() const; + + Sprite3D(); +// ~Sprite3D(); +}; + +class AnimatedSprite3D : public SpriteBase3D { + + OBJ_TYPE(AnimatedSprite3D,SpriteBase3D); + Ref<SpriteFrames> frames; + + + int frame; + +protected: + virtual void _draw(); + static void _bind_methods(); +public: + + + + void set_sprite_frames(const Ref<SpriteFrames>& p_sprite_frames); + Ref<SpriteFrames> get_sprite_frames() const; + + void set_frame(int p_frame); + int get_frame() const; + + + virtual Rect2 get_item_rect() const; + + AnimatedSprite3D(); +// ~AnimatedSprite3D(); +}; + +VARIANT_ENUM_CAST(SpriteBase3D::DrawFlags); +VARIANT_ENUM_CAST(SpriteBase3D::AlphaCutMode); +#endif // SPRITE_3D_H diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp index 9419996187..96f16ab8c8 100644 --- a/scene/3d/visual_instance.cpp +++ b/scene/3d/visual_instance.cpp @@ -65,10 +65,12 @@ void VisualInstance::_notification(int p_what) { VisualServer::get_singleton()->instance_set_room(instance,room->get_instance()); } - // CHECK SKELETON + // CHECK SKELETON => moving skeleton attaching logic to MeshInstance + /* Skeleton *skeleton=get_parent()?get_parent()->cast_to<Skeleton>():NULL; if (skeleton) VisualServer::get_singleton()->instance_attach_skeleton( instance, skeleton->get_skeleton() ); + */ VisualServer::get_singleton()->instance_set_scenario( instance, get_world()->get_scenario() ); diff --git a/scene/3d/visual_instance.h b/scene/3d/visual_instance.h index 4e652912c6..afb9ed70f8 100644 --- a/scene/3d/visual_instance.h +++ b/scene/3d/visual_instance.h @@ -91,6 +91,7 @@ public: 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_VOLUME=VS::INSTANCE_FLAG_USE_BAKED_LIGHT_VOLUME, FLAG_MAX=VS::INSTANCE_FLAG_MAX, }; diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index c659447c23..15d3dccb71 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -907,8 +907,8 @@ void AnimationPlayer::play(const StringName& p_name, float p_custom_blend, float } } - c.current.pos=p_from_end ? c.current.from->animation->get_length() : 0; c.current.from=&animation_set[name]; + c.current.pos=p_from_end ? c.current.from->animation->get_length() : 0; c.current.speed_scale=p_custom_scale; c.assigned=p_name; diff --git a/scene/audio/sample_player.cpp b/scene/audio/sample_player.cpp index be53b8243e..90994f01b4 100644 --- a/scene/audio/sample_player.cpp +++ b/scene/audio/sample_player.cpp @@ -52,7 +52,7 @@ bool SamplePlayer::_set(const StringName& p_name, const Variant& p_value) { set_voice_count(p_value); else if (name.begins_with("default/")) { - String what=name.right(7); + String what=name.right(8); if (what=="volume_db") set_default_volume_db(p_value); diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 6c9db7484b..e822cfef13 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -323,9 +323,12 @@ bool LineEdit::can_drop_data(const Point2& p_point,const Variant& p_data) const{ void LineEdit::drop_data(const Point2& p_point,const Variant& p_data){ if (p_data.get_type()==Variant::STRING) { - set_cursor_at_pixel_pos(p_point.x); + int selected = selection.end - selection.begin; + text.erase(selection.begin, selected); append_at_cursor(p_data); + selection.begin = cursor_pos-selected; + selection.end = cursor_pos; } } diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index 0a5b72d2ed..65ad02723c 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -38,7 +38,13 @@ void Popup::_input_event(InputEvent p_event) { void Popup::_notification(int p_what) { - + if (p_what==NOTIFICATION_VISIBILITY_CHANGED) { + if (popped_up && !is_visible()) { + popped_up=false; + notification(NOTIFICATION_POPUP_HIDE); + emit_signal("popup_hide"); + } + } } void Popup::_fix_size() { @@ -101,6 +107,7 @@ void Popup::popup_centered_minsize(const Size2& p_minsize) { popup_centered( total_minsize ); + popped_up=true; } @@ -127,6 +134,7 @@ void Popup::popup_centered(const Size2& p_size) { _post_popup(); notification(NOTIFICATION_POST_POPUP); + popped_up=true; } void Popup::popup_centered_ratio(float p_screen_ratio) { @@ -153,6 +161,7 @@ void Popup::popup_centered_ratio(float p_screen_ratio) { _post_popup(); notification(NOTIFICATION_POST_POPUP); + popped_up=true; } @@ -171,6 +180,7 @@ void Popup::popup() { _post_popup(); notification(NOTIFICATION_POST_POPUP); + popped_up=true; } void Popup::set_exclusive(bool p_exclusive) { @@ -193,8 +203,11 @@ void Popup::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_exclusive","enable"),&Popup::set_exclusive); ObjectTypeDB::bind_method(_MD("is_exclusive"),&Popup::is_exclusive); ADD_SIGNAL( MethodInfo("about_to_show") ); + ADD_SIGNAL( MethodInfo("popup_hide") ); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "popup/exclusive"), _SCS("set_exclusive"),_SCS("is_exclusive") ); BIND_CONSTANT(NOTIFICATION_POST_POPUP); + BIND_CONSTANT(NOTIFICATION_POPUP_HIDE); + } @@ -202,6 +215,7 @@ Popup::Popup() { set_as_toplevel(true); exclusive=false; + popped_up=false; hide(); } diff --git a/scene/gui/popup.h b/scene/gui/popup.h index 3744ff283f..072b66c2c7 100644 --- a/scene/gui/popup.h +++ b/scene/gui/popup.h @@ -39,6 +39,7 @@ class Popup : public Control { OBJ_TYPE( Popup, Control ); bool exclusive; + bool popped_up; protected: @@ -51,7 +52,8 @@ protected: public: enum { - NOTIFICATION_POST_POPUP=80 + NOTIFICATION_POST_POPUP=80, + NOTIFICATION_POPUP_HIDE=81 }; void set_exclusive(bool p_exclusive); diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 5ac278a38e..241d66fce4 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -1512,6 +1512,10 @@ void RichTextLabel::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_selection_enabled","enabled"),&RichTextLabel::set_selection_enabled); ObjectTypeDB::bind_method(_MD("is_selection_enabled"),&RichTextLabel::is_selection_enabled); + ObjectTypeDB::bind_method(_MD("parse_bbcode", "bbcode"),&RichTextLabel::parse_bbcode); + ObjectTypeDB::bind_method(_MD("append_bbcode", "bbcode"),&RichTextLabel::append_bbcode); + + ADD_SIGNAL( MethodInfo("meta_clicked",PropertyInfo(Variant::NIL,"meta"))); BIND_CONSTANT( ALIGN_LEFT ); diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index a6207c5611..3566c1bfc4 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -46,7 +46,6 @@ #define TAB_PIXELS - static bool _is_text_char(CharType c) { return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_'; @@ -57,6 +56,42 @@ static bool _is_symbol(CharType c) { return c!='_' && ((c>='!' && c<='/') || (c>=':' && c<='@') || (c>='[' && c<='`') || (c>='{' && c<='~') || c=='\t'); } +static bool _is_pair_right_symbol(CharType c) { + return + c == '"' || + c == '\'' || + c == ')' || + c == ']' || + c == '}'; +} + +static bool _is_pair_left_symbol(CharType c) { + return + c == '"' || + c == '\'' || + c == '(' || + c == '[' || + c == '{'; +} + +static bool _is_pair_symbol(CharType c) { + return _is_pair_left_symbol(c) || _is_pair_right_symbol(c); +} + +static CharType _get_right_pair_symbol(CharType c) { + if(c == '"') + return '"'; + if(c == '\'') + return '\''; + if(c == '(') + return ')'; + if(c == '[') + return ']'; + if(c == '{') + return '}'; + return 0; +} + void TextEdit::Text::set_font(const Ref<Font>& p_font) { font=p_font; @@ -301,7 +336,7 @@ void TextEdit::_update_scrollbars() { v_scroll->set_val(cursor.line_ofs); } else { - + cursor.line_ofs = 0; v_scroll->hide(); } @@ -707,6 +742,93 @@ void TextEdit::_notification(int p_what) { } } +void TextEdit::_consume_pair_symbol(CharType ch) { + + int cursor_position_to_move = cursor_get_column() + 1; + + CharType ch_single[2] = {ch, 0}; + CharType ch_single_pair[2] = {_get_right_pair_symbol(ch), 0}; + CharType ch_pair[3] = {ch, _get_right_pair_symbol(ch), 0}; + + if(is_selection_active()) { + + int new_column,new_line; + + _begin_compex_operation(); + _insert_text(get_selection_from_line(), get_selection_from_column(), + ch_single, + &new_line, &new_column); + + int to_col_offset = 0; + if(get_selection_from_line() == get_selection_to_line()) + to_col_offset = 1; + + _insert_text(get_selection_to_line(), + get_selection_to_column() + to_col_offset, + ch_single_pair, + &new_line,&new_column); + _end_compex_operation(); + + cursor_set_line(get_selection_to_line()); + cursor_set_column(get_selection_to_column() + to_col_offset); + + deselect(); + update(); + return; + } + + if( (ch == '\'' || ch == '"') && + cursor_get_column() > 0 && + _is_text_char(text[cursor.line][cursor_get_column() - 1]) + ) { + insert_text_at_cursor(ch_single); + cursor_set_column(cursor_position_to_move); + return; + } + + if(cursor_get_column() < text[cursor.line].length()) { + if(_is_text_char(text[cursor.line][cursor_get_column()])) { + insert_text_at_cursor(ch_single); + cursor_set_column(cursor_position_to_move); + return; + } + if( _is_pair_right_symbol(ch) && + text[cursor.line][cursor_get_column()] == ch + ) { + cursor_set_column(cursor_position_to_move); + return; + } + } + + + insert_text_at_cursor(ch_pair); + cursor_set_column(cursor_position_to_move); + return; + +} + +void TextEdit::_consume_backspace_for_pair_symbol(int prev_line, int prev_column) { + + bool remove_right_symbol = false; + + if(cursor.column < text[cursor.line].length() && cursor.column > 0) { + + CharType left_char = text[cursor.line][cursor.column - 1]; + CharType right_char = text[cursor.line][cursor.column]; + + if(right_char == _get_right_pair_symbol(left_char)) { + remove_right_symbol = true; + } + + } + if(remove_right_symbol) { + _remove_text(prev_line,prev_column,cursor.line,cursor.column + 1); + } else { + _remove_text(prev_line,prev_column,cursor.line,cursor.column); + } + +} + void TextEdit::backspace_at_cursor() { if (cursor.column==0 && cursor.line==0) @@ -714,7 +836,14 @@ void TextEdit::backspace_at_cursor() { int prev_line = cursor.column?cursor.line:cursor.line-1; int prev_column = cursor.column?(cursor.column-1):(text[cursor.line-1].length()); - _remove_text(prev_line,prev_column,cursor.line,cursor.column); + if(auto_brace_completion_enabled && + cursor.column > 0 && + _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); + } + cursor_set_line(prev_line); cursor_set_column(prev_column); @@ -976,7 +1105,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { return; } - if (k.scancode==KEY_RETURN) { + if (k.scancode==KEY_RETURN || k.scancode==KEY_TAB) { _confirm_completion(); accept_event(); @@ -1002,11 +1131,17 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { if (cursor.column<text[cursor.line].length() && text[cursor.line][cursor.column]==k.unicode) { //same char, move ahead cursor_set_column(cursor.column+1); + } else { //different char, go back const CharType chr[2] = {k.unicode, 0}; - _insert_text_at_cursor(chr); + if(auto_brace_completion_enabled && _is_pair_symbol(chr[0])) { + _consume_pair_symbol(chr[0]); + } else { + _insert_text_at_cursor(chr); + } } + _update_completion_candidates(); accept_event(); @@ -1113,7 +1248,8 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { 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; } if (unselect) { @@ -1522,14 +1658,35 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { if (readonly) break; + accept_event(); + } else { + + break; + } + } + + if (!scancode_handled && !k.mod.command && !k.mod.alt) { + + if (k.unicode>=32) { + + if (readonly) + break; + const CharType chr[2] = {k.unicode, 0}; - _insert_text_at_cursor(chr); + + if(auto_brace_completion_enabled && _is_pair_symbol(chr[0])) { + _consume_pair_symbol(chr[0]); + } else { + _insert_text_at_cursor(chr); + } + accept_event(); } else { break; } } + if (!selection.selecting_test) { @@ -1866,7 +2023,6 @@ void TextEdit::adjust_viewport_to_cursor() { } - void TextEdit::cursor_set_column(int p_col) { if (p_col<0) @@ -2334,6 +2490,27 @@ String TextEdit::get_selection_text() const { } +String TextEdit::get_word_under_cursor() const { + + int prev_cc = cursor.column; + while(prev_cc >0) { + bool is_char = _is_text_char(text[cursor.line][prev_cc-1]); + if (!is_char) + break; + --prev_cc; + } + + int next_cc = cursor.column; + while(next_cc<text[cursor.line].length()) { + bool is_char = _is_text_char(text[cursor.line][next_cc]); + if(!is_char) + break; + ++ next_cc; + } + if (prev_cc == cursor.column || next_cc == cursor.column) + return ""; + return text[cursor.line].substr(prev_cc, next_cc-prev_cc); +} DVector<int> TextEdit::_search_bind(const String &p_key,uint32_t p_search_flags, int p_from_line,int p_from_column) const { @@ -2724,6 +2901,7 @@ void TextEdit::_update_completion_candidates() { completion_current=completion_options[completion_index]; +#if 0 // even there's only one option, user still get the chance to choose using it or not if (completion_options.size()==1) { //one option to complete, just complete it automagically _confirm_completion(); @@ -2732,6 +2910,9 @@ void TextEdit::_update_completion_candidates() { return; } +#endif + if (completion_options.size()==1 && s==completion_options[0]) + _cancel_completion(); completion_enabled=true; @@ -2886,6 +3067,7 @@ void TextEdit::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_selection_to_line"),&TextEdit::get_selection_to_line); ObjectTypeDB::bind_method(_MD("get_selection_to_column"),&TextEdit::get_selection_to_column); ObjectTypeDB::bind_method(_MD("get_selection_text"),&TextEdit::get_selection_text); + ObjectTypeDB::bind_method(_MD("get_word_under_cursor"),&TextEdit::get_word_under_cursor); ObjectTypeDB::bind_method(_MD("search","flags","from_line","from_column","to_line","to_column"),&TextEdit::_search_bind); ObjectTypeDB::bind_method(_MD("undo"),&TextEdit::undo); @@ -2989,6 +3171,7 @@ TextEdit::TextEdit() { tooltip_obj=NULL; line_numbers=false; next_operation_is_complex=false; + auto_brace_completion_enabled=false; } TextEdit::~TextEdit(){ diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 8e9651668b..7700bfd4d3 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -206,6 +206,8 @@ class TextEdit : public Control { bool text_changed_dirty; bool undo_enabled; bool line_numbers; + + bool auto_brace_completion_enabled; uint64_t last_dblclk; @@ -272,6 +274,10 @@ protected: void _insert_text_at_cursor(const String& p_text); void _input_event(const InputEvent& p_input); void _notification(int p_what); + + void _consume_pair_symbol(CharType ch); + void _consume_backspace_for_pair_symbol(int prev_line, int prev_column); + static void _bind_methods(); @@ -300,8 +306,11 @@ public: String get_text(); String get_line(int line) const; void backspace_at_cursor(); - - + + inline void set_auto_brace_completion(bool p_enabled) { + auto_brace_completion_enabled = p_enabled; + } + void cursor_set_column(int p_col); void cursor_set_line(int p_row); @@ -332,6 +341,8 @@ public: int get_selection_to_column() const; String get_selection_text() const; + String get_word_under_cursor() const; + bool search(const String &p_key,uint32_t p_search_flags, int p_from_line, int p_from_column,int &r_line,int &r_column) const; void undo(); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 0bbc2dc695..91769bbb82 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -728,6 +728,7 @@ void Viewport::set_as_render_target(bool p_enable){ render_target_texture_rid=RID(); } + render_target_texture->set_flags(render_target_texture->flags); render_target_texture->emit_changed(); } @@ -773,6 +774,18 @@ bool Viewport::get_render_target_vflip() const{ } +void Viewport::set_render_target_filter(bool p_enable) { + + render_target_texture->set_flags(p_enable?int(Texture::FLAG_FILTER):int(0)); + +} + +bool Viewport::get_render_target_filter() const{ + + return (render_target_texture->get_flags()&Texture::FLAG_FILTER)!=0; +} + + Matrix32 Viewport::_get_input_pre_xform() const { Matrix32 pre_xf; @@ -990,6 +1003,9 @@ void Viewport::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_render_target_vflip","enable"), &Viewport::set_render_target_vflip); ObjectTypeDB::bind_method(_MD("get_render_target_vflip"), &Viewport::get_render_target_vflip); + ObjectTypeDB::bind_method(_MD("set_render_target_filter","enable"), &Viewport::set_render_target_filter); + ObjectTypeDB::bind_method(_MD("get_render_target_filter"), &Viewport::get_render_target_filter); + ObjectTypeDB::bind_method(_MD("set_render_target_update_mode","mode"), &Viewport::set_render_target_update_mode); ObjectTypeDB::bind_method(_MD("get_render_target_update_mode"), &Viewport::get_render_target_update_mode); @@ -1020,6 +1036,7 @@ void Viewport::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transparent_bg"), _SCS("set_transparent_background"), _SCS("has_transparent_background") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/enabled"), _SCS("set_as_render_target"), _SCS("is_set_as_render_target") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/v_flip"), _SCS("set_render_target_vflip"), _SCS("get_render_target_vflip") ); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/filter"), _SCS("set_render_target_filter"), _SCS("get_render_target_filter") ); ADD_PROPERTY( PropertyInfo(Variant::INT,"render_target/update_mode",PROPERTY_HINT_ENUM,"Disabled,Once,When Visible,Always"), _SCS("set_render_target_update_mode"), _SCS("get_render_target_update_mode") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"audio_listener/enable_2d"), _SCS("set_as_audio_listener_2d"), _SCS("is_audio_listener_2d") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"audio_listener/enable_3d"), _SCS("set_as_audio_listener"), _SCS("is_audio_listener") ); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index cc7f93cfa3..d54b489843 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -113,6 +113,7 @@ friend class RenderTargetTexture; bool transparent_bg; bool render_target_vflip; + bool render_target_filter; void _update_rect(); @@ -210,6 +211,9 @@ public: void set_render_target_vflip(bool p_enable); bool get_render_target_vflip() const; + void set_render_target_filter(bool p_enable); + bool get_render_target_filter() const; + void set_render_target_update_mode(RenderTargetUpdateMode p_mode); RenderTargetUpdateMode get_render_target_update_mode() const; Ref<RenderTargetTexture> get_render_target_texture() const; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 8fd39b0d74..f3d757b601 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -187,7 +187,10 @@ #include "scene/3d/area.h" #include "scene/3d/physics_joint.h" #include "scene/3d/multimesh_instance.h" +#include "scene/3d/baked_light.h" #include "scene/3d/ray_cast.h" +#include "scene/3d/immediate_geometry.h" +#include "scene/3d/sprite_3d.h" #include "scene/3d/spatial_sample_player.h" #include "scene/3d/spatial_stream_player.h" #include "scene/3d/proximity_group.h" @@ -371,6 +374,9 @@ void register_scene_types() { ObjectTypeDB::register_type<InterpolatedCamera>(); ObjectTypeDB::register_type<TestCube>(); ObjectTypeDB::register_type<MeshInstance>(); + ObjectTypeDB::register_type<ImmediateGeometry>(); + ObjectTypeDB::register_type<Sprite3D>(); + ObjectTypeDB::register_type<AnimatedSprite3D>(); ObjectTypeDB::register_virtual_type<Light>(); ObjectTypeDB::register_type<DirectionalLight>(); ObjectTypeDB::register_type<OmniLight>(); @@ -401,7 +407,7 @@ void register_scene_types() { ObjectTypeDB::register_type<PathFollow>(); ObjectTypeDB::register_type<VisibilityNotifier>(); ObjectTypeDB::register_type<VisibilityEnabler>(); - + ObjectTypeDB::register_type<BakedLight>(); ObjectTypeDB::register_type<WorldEnvironment>(); //scenariofx diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index 3e12c7a5b5..99447c0a0e 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -101,15 +101,21 @@ void Environment::_bind_methods() { ObjectTypeDB::bind_method(_MD("fx_set_param","param","value"),&Environment::fx_set_param); ObjectTypeDB::bind_method(_MD("fx_get_param","param"),&Environment::fx_get_param); + ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"fxaa/enabled"),_SCS("set_enable_fx"),_SCS("is_fx_enabled"), FX_FXAA); + ADD_PROPERTY( PropertyInfo(Variant::INT,"background/mode",PROPERTY_HINT_ENUM,"Keep,Default Color,Color,Texture,Cubemap,Texture RGBE,Cubemap RGBE"),_SCS("set_background"),_SCS("get_background")); ADD_PROPERTYI( PropertyInfo(Variant::COLOR,"background/color"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_COLOR); ADD_PROPERTYI( PropertyInfo(Variant::OBJECT,"background/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_TEXTURE); ADD_PROPERTYI( PropertyInfo(Variant::OBJECT,"background/cubemap",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_CUBEMAP); ADD_PROPERTYI( PropertyInfo(Variant::REAL,"background/energy",PROPERTY_HINT_RANGE,"0,128,0.01"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_ENERGY); ADD_PROPERTYI( PropertyInfo(Variant::REAL,"background/scale",PROPERTY_HINT_RANGE,"0.001,16,0.001"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_SCALE); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"background/glow",PROPERTY_HINT_RANGE,"0.00,8,0.01"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_GLOW); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"glow/enabled"),_SCS("set_enable_fx"),_SCS("is_fx_enabled"), FX_GLOW); ADD_PROPERTYI( PropertyInfo(Variant::INT,"glow/blur_passes",PROPERTY_HINT_RANGE,"1,4,1"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_GLOW_BLUR_PASSES); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"glow/blur_scale",PROPERTY_HINT_RANGE,"0.01,4,0.01"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_GLOW_BLUR_SCALE); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"glow/blur_strength",PROPERTY_HINT_RANGE,"0.01,4,0.01"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_GLOW_BLUR_STRENGTH); + ADD_PROPERTYI( PropertyInfo(Variant::INT,"glow/blur_blend_mode",PROPERTY_HINT_ENUM,"Additive,Screen,SoftLight"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_GLOW_BLUR_BLEND_MODE); ADD_PROPERTYI( PropertyInfo(Variant::REAL,"glow/bloom",PROPERTY_HINT_RANGE,"0,8,0.01"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_GLOW_BLOOM); ADD_PROPERTYI( PropertyInfo(Variant::REAL,"glow/bloom_treshold",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_GLOW_BLOOM_TRESHOLD); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"dof_blur/enabled"),_SCS("set_enable_fx"),_SCS("is_fx_enabled"), FX_DOF_BLUR); @@ -178,9 +184,11 @@ void Environment::_bind_methods() { BIND_CONSTANT( BG_PARAM_TEXTURE ); BIND_CONSTANT( BG_PARAM_CUBEMAP ); BIND_CONSTANT( BG_PARAM_ENERGY ); + BIND_CONSTANT( BG_PARAM_GLOW ); BIND_CONSTANT( BG_PARAM_MAX ); + BIND_CONSTANT( FX_FXAA ); BIND_CONSTANT( FX_GLOW ); BIND_CONSTANT( FX_DOF_BLUR ); BIND_CONSTANT( FX_HDR ); @@ -190,7 +198,14 @@ void Environment::_bind_methods() { BIND_CONSTANT( FX_MAX ); + BIND_CONSTANT( FX_BLUR_BLEND_MODE_ADDITIVE ); + BIND_CONSTANT( FX_BLUR_BLEND_MODE_SCREEN ); + BIND_CONSTANT( FX_BLUR_BLEND_MODE_SOFTLIGHT ); + BIND_CONSTANT( FX_PARAM_GLOW_BLUR_PASSES ); + BIND_CONSTANT( FX_PARAM_GLOW_BLUR_SCALE ); + BIND_CONSTANT( FX_PARAM_GLOW_BLUR_STRENGTH ); + BIND_CONSTANT( FX_PARAM_GLOW_BLUR_BLEND_MODE ); BIND_CONSTANT( FX_PARAM_GLOW_BLOOM); BIND_CONSTANT( FX_PARAM_GLOW_BLOOM_TRESHOLD); BIND_CONSTANT( FX_PARAM_DOF_BLUR_PASSES ); @@ -226,11 +241,14 @@ Environment::Environment() { set_background_param(BG_PARAM_CUBEMAP,Ref<CubeMap>()); set_background_param(BG_PARAM_ENERGY,1.0); set_background_param(BG_PARAM_SCALE,1.0); + set_background_param(BG_PARAM_GLOW,0.0); for(int i=0;i<FX_MAX;i++) set_enable_fx(Fx(i),false); fx_set_param(FX_PARAM_GLOW_BLUR_PASSES,1); + fx_set_param(FX_PARAM_GLOW_BLUR_SCALE,1); + fx_set_param(FX_PARAM_GLOW_BLUR_STRENGTH,1); fx_set_param(FX_PARAM_GLOW_BLOOM,0.0); fx_set_param(FX_PARAM_GLOW_BLOOM_TRESHOLD,0.5); fx_set_param(FX_PARAM_DOF_BLUR_PASSES,1); diff --git a/scene/resources/environment.h b/scene/resources/environment.h index c94c81b694..627fbb7cc0 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -56,10 +56,12 @@ public: BG_PARAM_CUBEMAP=VS::ENV_BG_PARAM_CUBEMAP, BG_PARAM_ENERGY=VS::ENV_BG_PARAM_ENERGY, BG_PARAM_SCALE=VS::ENV_BG_PARAM_SCALE, + BG_PARAM_GLOW=VS::ENV_BG_PARAM_GLOW, BG_PARAM_MAX=VS::ENV_BG_PARAM_MAX }; enum Fx { + FX_FXAA=VS::ENV_FX_FXAA, FX_GLOW=VS::ENV_FX_GLOW, FX_DOF_BLUR=VS::ENV_FX_DOF_BLUR, FX_HDR=VS::ENV_FX_HDR, @@ -69,8 +71,17 @@ public: FX_MAX=VS::ENV_FX_MAX, }; + enum FxBlurBlendMode { + FX_BLUR_BLEND_MODE_ADDITIVE, + FX_BLUR_BLEND_MODE_SCREEN, + FX_BLUR_BLEND_MODE_SOFTLIGHT, + }; + enum FxParam { FX_PARAM_GLOW_BLUR_PASSES=VS::ENV_FX_PARAM_GLOW_BLUR_PASSES, + FX_PARAM_GLOW_BLUR_SCALE=VS::ENV_FX_PARAM_GLOW_BLUR_SCALE, + FX_PARAM_GLOW_BLUR_STRENGTH=VS::ENV_FX_PARAM_GLOW_BLUR_STRENGTH, + FX_PARAM_GLOW_BLUR_BLEND_MODE=VS::ENV_FX_PARAM_GLOW_BLUR_BLEND_MODE, FX_PARAM_GLOW_BLOOM=VS::ENV_FX_PARAM_GLOW_BLOOM, FX_PARAM_GLOW_BLOOM_TRESHOLD=VS::ENV_FX_PARAM_GLOW_BLOOM_TRESHOLD, FX_PARAM_DOF_BLUR_PASSES=VS::ENV_FX_PARAM_DOF_BLUR_PASSES, diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 637a816112..091a46d4ab 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -45,6 +45,7 @@ static const char*_hint_names[Material::HINT_MAX]={ "opaque_pre_zpass", "no_shadow", "no_depth_draw", + "no_alpha_depth_draw", }; static const Material::Flag _flag_indices[Material::FLAG_MAX]={ @@ -158,7 +159,7 @@ void Material::_bind_methods() { for(int i=0;i<HINT_MAX;i++) ADD_PROPERTYI( PropertyInfo( Variant::BOOL, String()+"hints/"+_hint_names[i] ),_SCS("set_hint"),_SCS("get_hint"),_hint_indices[i]); - ADD_PROPERTY( PropertyInfo( Variant::INT, "params/blend_mode",PROPERTY_HINT_ENUM,"Mix,Add,Sub" ), _SCS("set_blend_mode"),_SCS("get_blend_mode")); + ADD_PROPERTY( PropertyInfo( Variant::INT, "params/blend_mode",PROPERTY_HINT_ENUM,"Mix,Add,Sub,PMAlpha" ), _SCS("set_blend_mode"),_SCS("get_blend_mode")); ADD_PROPERTY( PropertyInfo( Variant::REAL, "params/line_width",PROPERTY_HINT_RANGE,"0.1,32.0,0.1" ), _SCS("set_line_width"),_SCS("get_line_width")); @@ -175,6 +176,7 @@ void Material::_bind_methods() { BIND_CONSTANT( HINT_OPAQUE_PRE_PASS ); BIND_CONSTANT( HINT_NO_SHADOW ); BIND_CONSTANT( HINT_NO_DEPTH_DRAW ); + BIND_CONSTANT( HINT_NO_DEPTH_DRAW_FOR_ALPHA ); BIND_CONSTANT( HINT_MAX ); BIND_CONSTANT( SHADE_MODEL_LAMBERT ); @@ -189,6 +191,8 @@ void Material::_bind_methods() { 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 ); } @@ -206,6 +210,7 @@ Material::Material(const RID& p_material) { for(int i=0;i<HINT_MAX;i++) hints[i]=false; + hints[HINT_NO_DEPTH_DRAW_FOR_ALPHA]=true; blend_mode=BLEND_MODE_MIX; shade_model = SHADE_MODEL_LAMBERT; @@ -363,14 +368,14 @@ Material::BlendMode FixedMaterial::get_detail_blend_mode() const { } void FixedMaterial::set_fixed_flag(FixedFlag p_flag, bool p_value) { - ERR_FAIL_INDEX(p_flag,3); + ERR_FAIL_INDEX(p_flag,4); fixed_flags[p_flag]=p_value; VisualServer::get_singleton()->fixed_material_set_flag(material,(VS::FixedMaterialFlags)p_flag,p_value); } bool FixedMaterial::get_fixed_flag(FixedFlag p_flag) const { - ERR_FAIL_INDEX_V(p_flag,3,false); + ERR_FAIL_INDEX_V(p_flag,4,false); return fixed_flags[p_flag]; } @@ -417,6 +422,7 @@ void FixedMaterial::_bind_methods() { ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "fixed_flags/use_alpha" ), _SCS("set_fixed_flag"), _SCS("get_fixed_flag"), FLAG_USE_ALPHA); ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "fixed_flags/use_color_array" ), _SCS("set_fixed_flag"), _SCS("get_fixed_flag"), FLAG_USE_COLOR_ARRAY); ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "fixed_flags/use_point_size" ), _SCS("set_fixed_flag"), _SCS("get_fixed_flag"), FLAG_USE_POINT_SIZE); + ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "fixed_flags/discard_alpha" ), _SCS("set_fixed_flag"), _SCS("get_fixed_flag"), FLAG_DISCARD_ALPHA); ADD_PROPERTYI( PropertyInfo( Variant::COLOR, "params/diffuse" ), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_DIFFUSE); ADD_PROPERTYI( PropertyInfo( Variant::COLOR, "params/specular", PROPERTY_HINT_COLOR_NO_ALPHA ), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SPECULAR ); ADD_PROPERTYI( PropertyInfo( Variant::COLOR, "params/emission", PROPERTY_HINT_COLOR_NO_ALPHA ), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_EMISSION ); @@ -455,6 +461,7 @@ void FixedMaterial::_bind_methods() { BIND_CONSTANT( FLAG_USE_ALPHA ); BIND_CONSTANT( FLAG_USE_COLOR_ARRAY ); BIND_CONSTANT( FLAG_USE_POINT_SIZE ); + BIND_CONSTANT( FLAG_DISCARD_ALPHA ); } diff --git a/scene/resources/material.h b/scene/resources/material.h index 7bd8b70fa4..2057b3cac9 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -75,6 +75,7 @@ public: BLEND_MODE_MUL = VS::MATERIAL_BLEND_MODE_MUL, BLEND_MODE_ADD = VS::MATERIAL_BLEND_MODE_ADD, BLEND_MODE_SUB = VS::MATERIAL_BLEND_MODE_SUB, + BLEND_MODE_PREMULT_ALPHA = VS::MATERIAL_BLEND_MODE_PREMULT_ALPHA, }; @@ -84,6 +85,7 @@ public: HINT_OPAQUE_PRE_PASS=VS::MATERIAL_HINT_OPAQUE_PRE_PASS, HINT_NO_SHADOW=VS::MATERIAL_HINT_NO_SHADOW, HINT_NO_DEPTH_DRAW=VS::MATERIAL_HINT_NO_DEPTH_DRAW, + HINT_NO_DEPTH_DRAW_FOR_ALPHA=VS::MATERIAL_HINT_NO_DEPTH_DRAW_FOR_ALPHA, HINT_MAX=VS::MATERIAL_HINT_MAX }; @@ -158,6 +160,7 @@ public: FLAG_USE_ALPHA=VS::FIXED_MATERIAL_FLAG_USE_ALPHA, FLAG_USE_COLOR_ARRAY=VS::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY, FLAG_USE_POINT_SIZE=VS::FIXED_MATERIAL_FLAG_USE_POINT_SIZE, + FLAG_DISCARD_ALPHA=VS::FIXED_MATERIAL_FLAG_DISCARD_ALPHA }; private: diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 244ee09c22..c6e492fcb3 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -92,10 +92,23 @@ bool Mesh::_set(const StringName& p_name, const Variant& p_value) { return true; } - if (sname.begins_with("materials/")) { + if (sname.begins_with("surface_")) { + + int sl=sname.find("/"); + if (sl==-1) + return false; + int idx=sname.substr(8,sl-8).to_int()-1; + String what = sname.get_slice("/",1); + if (what=="material") + surface_set_material(idx,p_value); + else if (what=="name") + surface_set_name(idx,p_value); + return true; + } - int idx=sname.get_slice("/",1).to_int()-1; - surface_set_material(idx,p_value); + if (sname=="custom_aabb/custom_aabb") { + + set_custom_aabb(p_value); return true; } @@ -160,10 +173,21 @@ bool Mesh::_get(const StringName& p_name,Variant &r_ret) const { r_ret = get_morph_target_mode(); return true; - } else if (sname.begins_with("materials/")) { + } else if (sname.begins_with("surface_")) { + + int sl=sname.find("/"); + if (sl==-1) + return false; + int idx=sname.substr(8,sl-8).to_int()-1; + String what = sname.get_slice("/",1); + if (what=="material") + r_ret=surface_get_material(idx); + else if (what=="name") + r_ret=surface_get_name(idx); + return true; + } else if (sname=="custom_aabb/custom_aabb") { - int idx=sname.get_slice("/",1).to_int()-1; - r_ret=surface_get_material(idx); + r_ret=custom_aabb; return true; } else if (!sname.begins_with("surfaces")) @@ -200,8 +224,12 @@ void Mesh::_get_property_list( List<PropertyInfo> *p_list) const { for (int i=0;i<surfaces.size();i++) { p_list->push_back( PropertyInfo( Variant::DICTIONARY,"surfaces/"+itos(i), PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR ) ); - p_list->push_back( PropertyInfo( Variant::OBJECT,"materials/"+itos(i+1), PROPERTY_HINT_RESOURCE_TYPE,"Material",PROPERTY_USAGE_EDITOR ) ); + 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 ) ); } + + p_list->push_back( PropertyInfo( Variant::_AABB,"custom_aabb/custom_aabb" ) ); + } @@ -473,6 +501,19 @@ AABB Mesh::get_aabb() const { return aabb; } + +void Mesh::set_custom_aabb(const AABB& p_custom) { + + custom_aabb=p_custom; + VS::get_singleton()->mesh_set_custom_aabb(mesh,custom_aabb); +} + +AABB Mesh::get_custom_aabb() const { + + return custom_aabb; +} + + DVector<Face3> Mesh::get_faces() const { @@ -700,6 +741,8 @@ void Mesh::_bind_methods() { ObjectTypeDB::bind_method(_MD("center_geometry"),&Mesh::center_geometry); ObjectTypeDB::set_method_flags(get_type_static(),_SCS("center_geometry"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); + ObjectTypeDB::bind_method(_MD("set_custom_aabb","aabb"),&Mesh::set_custom_aabb); + ObjectTypeDB::bind_method(_MD("get_custom_aabb"),&Mesh::get_custom_aabb); BIND_CONSTANT( NO_INDEX_ARRAY ); diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index 3a11a8e171..5243163a4d 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -107,6 +107,7 @@ private: AABB aabb; MorphTargetMode morph_target_mode; Vector<StringName> morph_targets; + AABB custom_aabb; mutable Ref<TriangleMesh> triangle_mesh; @@ -156,6 +157,9 @@ public: void add_surface_from_mesh_data(const Geometry::MeshData& p_mesh_data); + void set_custom_aabb(const AABB& p_custom); + AABB get_custom_aabb() const; + AABB get_aabb() const; virtual RID get_rid() const; diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index d0c159e9f0..2856101674 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -32,57 +32,56 @@ #define EQ_VERTEX_DIST 0.00001 +bool SurfaceTool::Vertex::operator==(const Vertex& p_b) const { -bool SurfaceTool::compare(const Vertex& p_a,const Vertex& p_b) const { - if (p_a.vertex.distance_to(p_b.vertex)>EQ_VERTEX_DIST) + if (vertex!=p_b.vertex) return false; - if (format&Mesh::ARRAY_FORMAT_TEX_UV) { + if (uv!=p_b.uv) + return false; - if (p_a.uv.distance_to(p_b.uv)>EQ_VERTEX_DIST) - return false; - } + if (uv2!=p_b.uv2) + return false; - if (format&Mesh::ARRAY_FORMAT_TEX_UV2) { + if (normal!=p_b.normal) + return false; - if (p_a.uv2.distance_to(p_b.uv2)>EQ_VERTEX_DIST) - return false; - } + if (binormal!=p_b.binormal) + return false; - if (format&Mesh::ARRAY_FORMAT_NORMAL) { - if (p_a.normal.distance_to(p_b.normal)>EQ_VERTEX_DIST) - return false; - } + if (color!=p_b.color) + return false; - if (format&Mesh::ARRAY_FORMAT_TANGENT) { - if (p_a.binormal.distance_to(p_b.binormal)>EQ_VERTEX_DIST) - return false; - if (p_a.tangent.distance_to(p_b.tangent)>EQ_VERTEX_DIST) + if (bones.size()!=p_b.bones.size()) + return false; + + for(int i=0;i<bones.size();i++) { + if (bones[i]!=p_b.bones[i]) return false; } - if (format&Mesh::ARRAY_FORMAT_COLOR) { - if (p_a.color!=p_b.color) + for(int i=0;i<weights.size();i++) { + if (weights[i]!=p_b.weights[i]) return false; } - if (format&Mesh::ARRAY_FORMAT_BONES) { - for(int i=0;i<4;i++) { - if (Math::abs(p_a.bones[i]-p_b.bones[i])>CMP_EPSILON) - return false; - } - } + return true; +} - if (format&Mesh::ARRAY_FORMAT_WEIGHTS) { - for(int i=0;i<4;i++) { - if (Math::abs(p_a.weights[i]-p_b.weights[i])>CMP_EPSILON) - return false; - } - } +uint32_t SurfaceTool::VertexHasher::hash(const Vertex &p_vtx) { - return true; + uint32_t h = hash_djb2_buffer((const uint8_t*)&p_vtx.vertex,sizeof(real_t)*3); + h = hash_djb2_buffer((const uint8_t*)&p_vtx.normal,sizeof(real_t)*3,h); + h = hash_djb2_buffer((const uint8_t*)&p_vtx.binormal,sizeof(real_t)*3,h); + h = hash_djb2_buffer((const uint8_t*)&p_vtx.tangent,sizeof(real_t)*3,h); + h = hash_djb2_buffer((const uint8_t*)&p_vtx.uv,sizeof(real_t)*2,h); + h = hash_djb2_buffer((const uint8_t*)&p_vtx.uv2,sizeof(real_t)*2,h); + h = hash_djb2_buffer((const uint8_t*)&p_vtx.color,sizeof(real_t)*4,h); + h = hash_djb2_buffer((const uint8_t*)p_vtx.bones.ptr(),p_vtx.bones.size()*sizeof(int),h); + h = hash_djb2_buffer((const uint8_t*)p_vtx.weights.ptr(),p_vtx.weights.size()*sizeof(float),h); + return h; } void SurfaceTool::begin(Mesh::PrimitiveType p_primitive) { @@ -186,6 +185,17 @@ void SurfaceTool::add_weights( const Vector<float>& p_weights) { } +void SurfaceTool::add_smooth_group(bool p_smooth) { + + ERR_FAIL_COND(!begun); + if (index_array.size()) { + smooth_groups[index_array.size()]=p_smooth; + } else { + + smooth_groups[vertex_array.size()]=p_smooth; + } +} + void SurfaceTool::add_index( int p_index) { @@ -377,79 +387,53 @@ Ref<Mesh> SurfaceTool::commit(const Ref<Mesh>& p_existing) { void SurfaceTool::index() { -#if 0 - printf("indexing..\n"); - ERR_FAIL_COND( format & Surface::ARRAY_FORMAT_INDEX ); // already indexed - - index_array.clear(); - DVector< Vertex > indexed_vertex_array; + if (index_array.size()) + return; //already indexed - int vertex_array_len = vertex_array.size(); - vertex_array.read_lock(); - const Vertex*vertex_array_ptr = vertex_array.read(); - for (int i=0;i<vertex_array_len;i++) { + HashMap<Vertex,int,VertexHasher> indices; + List<Vertex> new_vertices; - int index_pos=-1; + for(List< Vertex >::Element *E=vertex_array.front();E;E=E->next()) { - int indexed_vertex_array_len=indexed_vertex_array.size(); - - if (indexed_vertex_array_len) { - - indexed_vertex_array.read_lock(); - const Vertex* indexed_vertex_array_ptr=indexed_vertex_array.read(); - - for (int j=0;j<indexed_vertex_array_len;j++) { - - if (vertex_array_ptr[i].same_as(indexed_vertex_array_ptr[j])) { - - index_pos=j; - break; - } - } - - indexed_vertex_array.read_unlock(); - } - - if (index_pos==-1) { - - index_pos=indexed_vertex_array.size(); - indexed_vertex_array.push_back(vertex_array_ptr[i]); + int *idxptr=indices.getptr(E->get()); + int idx; + if (!idxptr) { + idx=indices.size(); + new_vertices.push_back(E->get()); + indices[E->get()]=idx; } else { - - indexed_vertex_array.write_lock(); - indexed_vertex_array.write()[index_pos].normal+=vertex_array_ptr[i].normal; - indexed_vertex_array.write()[index_pos].binormal+=vertex_array_ptr[i].binormal; - indexed_vertex_array.write()[index_pos].tangent+=vertex_array_ptr[i].tangent; - indexed_vertex_array.write_unlock(); + idx=*idxptr; } - index_array.push_back(index_pos); - } - - int idxvertsize=indexed_vertex_array.size(); - indexed_vertex_array.write_lock(); - Vertex* idxvert=indexed_vertex_array.write(); - for (int i=0;i<idxvertsize;i++) { + index_array.push_back(idx); - idxvert[i].normal.normalize(); - idxvert[i].tangent.normalize(); - idxvert[i].binormal.normalize(); } - indexed_vertex_array.write_unlock(); - vertex_array.read_unlock(); - - format|=Surface::ARRAY_FORMAT_INDEX; - vertex_array=indexed_vertex_array; + vertex_array.clear(); + vertex_array=new_vertices; - printf("indexing.. end\n"); -#endif + format|=Mesh::ARRAY_FORMAT_INDEX; } void SurfaceTool::deindex() { + if (index_array.size()==0) + return; //nothing to deindex + Vector< Vertex > varr; + varr.resize(vertex_array.size()); + int idx=0; + for (List< Vertex >::Element *E=vertex_array.front();E;E=E->next()) { + varr[idx++]=E->get(); + } + vertex_array.clear(); + for (List<int>::Element *E=index_array.front();E;E=E->next()) { + + ERR_FAIL_INDEX(E->get(),varr.size()); + vertex_array.push_back(varr[E->get()]); + } + format&=~Mesh::ARRAY_FORMAT_INDEX; } @@ -631,80 +615,250 @@ void SurfaceTool::append_from(const Ref<Mesh>& p_existing, int p_surface,const T void SurfaceTool::generate_tangents() { ERR_FAIL_COND(!(format&Mesh::ARRAY_FORMAT_TEX_UV)); + ERR_FAIL_COND(!(format&Mesh::ARRAY_FORMAT_NORMAL)); -#if 0 - int len=vertex_array.size(); - vertex_array.write_lock(); - Vertex *vertexptr=vertex_array.write(); - - for (int i=0;i<len/3;i++) { + if (index_array.size()) { + Vector<List<Vertex>::Element*> vtx; + vtx.resize(vertex_array.size()); + int idx=0; + for (List<Vertex>::Element *E=vertex_array.front();E;E=E->next()) { + vtx[idx++]=E; + E->get().binormal=Vector3(); + E->get().tangent=Vector3(); + } - Vector3 v1 = vertexptr[i*3+0].vertex; - Vector3 v2 = vertexptr[i*3+1].vertex; - Vector3 v3 = vertexptr[i*3+2].vertex; + for (List<int>::Element *E=index_array.front();E;) { + + int i[3]; + i[0]=E->get(); + E=E->next(); + ERR_FAIL_COND(!E); + i[1]=E->get(); + E=E->next(); + ERR_FAIL_COND(!E); + i[2]=E->get(); + E=E->next(); + ERR_FAIL_COND(!E); + + + Vector3 v1 = vtx[ i[0] ]->get().vertex; + Vector3 v2 = vtx[ i[1] ]->get().vertex; + Vector3 v3 = vtx[ i[2] ]->get().vertex; + + Vector2 w1 = vtx[ i[0] ]->get().uv; + Vector2 w2 = vtx[ i[1] ]->get().uv; + Vector2 w3 = vtx[ i[2] ]->get().uv; + + + float x1 = v2.x - v1.x; + float x2 = v3.x - v1.x; + float y1 = v2.y - v1.y; + float y2 = v3.y - v1.y; + float z1 = v2.z - v1.z; + float z2 = v3.z - v1.z; + + float s1 = w2.x - w1.x; + float s2 = w3.x - w1.x; + float t1 = w2.y - w1.y; + float t2 = w3.y - w1.y; + + float r = (s1 * t2 - s2 * t1); + + Vector3 binormal,tangent; + + if (r==0) { + binormal=Vector3(0,0,0); + tangent=Vector3(0,0,0); + } else { + tangent = Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, + (t2 * z1 - t1 * z2) * r); + binormal = Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, + (s1 * z2 - s2 * z1) * r); + } - Vector3 w1 = vertexptr[i*3+0].uv[0]; - Vector3 w2 = vertexptr[i*3+1].uv[0]; - Vector3 w3 = vertexptr[i*3+2].uv[0]; + tangent.normalize(); + binormal.normalize(); + Vector3 normal=Plane( v1, v2, v3 ).normal; + Vector3 tangentp = tangent - normal * normal.dot( tangent ); + Vector3 binormalp = binormal - normal * (normal.dot(binormal)) - tangent * (tangent.dot(binormal)); - float x1 = v2.x - v1.x; - float x2 = v3.x - v1.x; - float y1 = v2.y - v1.y; - float y2 = v3.y - v1.y; - float z1 = v2.z - v1.z; - float z2 = v3.z - v1.z; + tangentp.normalize(); + binormalp.normalize(); - float s1 = w2.x - w1.x; - float s2 = w3.x - w1.x; - float t1 = w2.y - w1.y; - float t2 = w3.y - w1.y; - float r = (s1 * t2 - s2 * t1); + for (int j=0;j<3;j++) { + vtx[ i[j] ]->get().binormal+=binormalp; + vtx[ i[j] ]->get().tangent+=tangentp; - Vector3 binormal,tangent; + } + } - if (r==0) { - binormal=Vector3(0,0,0); - tangent=Vector3(0,0,0); - } else { - tangent = Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, - (t2 * z1 - t1 * z2) * r); - binormal = Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, - (s1 * z2 - s2 * z1) * r); + for (List<Vertex>::Element *E=vertex_array.front();E;E=E->next()) { + E->get().binormal.normalize(); + E->get().tangent.normalize(); } - tangent.normalize(); - binormal.normalize(); - Vector3 normal=Plane( v1, v2, v3 ).normal; - Vector3 tangentp = tangent - normal * normal.dot( tangent ); - Vector3 binormalp = binormal - normal * (normal.dot(binormal)) - tangent * (tangent.dot(binormal)); + } else { + - tangentp.normalize(); - binormalp.normalize(); + for (List<Vertex>::Element *E=vertex_array.front();E;) { + List< Vertex >::Element *v[3]; + v[0]=E; + v[1]=v[0]->next(); + ERR_FAIL_COND(!v[1]); + v[2]=v[1]->next(); + ERR_FAIL_COND(!v[2]); + E=v[2]->next(); - for (int j=0;j<3;j++) { - vertexptr[i*3+j].normal=normal; - vertexptr[i*3+j].binormal=binormalp; - vertexptr[i*3+j].tangent=tangentp; + Vector3 v1 = v[0]->get().vertex; + Vector3 v2 = v[1]->get().vertex; + Vector3 v3 = v[2]->get().vertex; + + Vector2 w1 = v[0]->get().uv; + Vector2 w2 = v[1]->get().uv; + Vector2 w3 = v[2]->get().uv; + + + float x1 = v2.x - v1.x; + float x2 = v3.x - v1.x; + float y1 = v2.y - v1.y; + float y2 = v3.y - v1.y; + float z1 = v2.z - v1.z; + float z2 = v3.z - v1.z; + + float s1 = w2.x - w1.x; + float s2 = w3.x - w1.x; + float t1 = w2.y - w1.y; + float t2 = w3.y - w1.y; + + float r = (s1 * t2 - s2 * t1); + + Vector3 binormal,tangent; + + if (r==0) { + binormal=Vector3(0,0,0); + tangent=Vector3(0,0,0); + } else { + tangent = Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, + (t2 * z1 - t1 * z2) * r); + binormal = Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, + (s1 * z2 - s2 * z1) * r); + } + + tangent.normalize(); + binormal.normalize(); + Vector3 normal=Plane( v1, v2, v3 ).normal; + + Vector3 tangentp = tangent - normal * normal.dot( tangent ); + Vector3 binormalp = binormal - normal * (normal.dot(binormal)) - tangent * (tangent.dot(binormal)); + + tangentp.normalize(); + binormalp.normalize(); + + + for (int j=0;j<3;j++) { + v[j]->get().binormal=binormalp; + v[j]->get().tangent=tangentp; + + } } } - format|=Surface::ARRAY_FORMAT_TANGENT; - printf("adding tangents to the format\n"); + format|=Mesh::ARRAY_FORMAT_TANGENT; - vertex_array.write_unlock(); -#endif } -void SurfaceTool::generate_flat_normals() { +void SurfaceTool::generate_normals() { -} -void SurfaceTool::generate_smooth_normals() { + ERR_FAIL_COND(primitive!=Mesh::PRIMITIVE_TRIANGLES); + + bool was_indexed=index_array.size(); + + deindex(); + + HashMap<Vertex,Vector3,VertexHasher> vertex_hash; + + int count=0; + bool smooth=false; + if (smooth_groups.has(0)) + smooth=smooth_groups[0]; + + print_line("SMOOTH BEGIN? "+itos(smooth)); + + List< Vertex >::Element *B=vertex_array.front(); + for(List< Vertex >::Element *E=B;E;) { + + List< Vertex >::Element *v[3]; + v[0]=E; + v[1]=v[0]->next(); + ERR_FAIL_COND(!v[1]); + v[2]=v[1]->next(); + ERR_FAIL_COND(!v[2]); + E=v[2]->next(); + + Vector3 normal = Plane(v[0]->get().vertex,v[1]->get().vertex,v[2]->get().vertex).normal; + + if (smooth) { + + for(int i=0;i<3;i++) { + + Vector3 *lv=vertex_hash.getptr(v[i]->get()); + if (!lv) { + vertex_hash.set(v[i]->get(),normal); + } else { + (*lv)+=normal; + } + } + } else { + + for(int i=0;i<3;i++) { + + v[i]->get().normal=normal; + + } + } + count+=3; + + if (smooth_groups.has(count) || !E) { + + if (vertex_hash.size()) { + + while (B!=E) { + + + Vector3* lv=vertex_hash.getptr(B->get()); + if (lv) { + B->get().normal=lv->normalized(); + } + + B=B->next(); + } + + } else { + B=E; + } + + vertex_hash.clear(); + if (E) { + smooth=smooth_groups[count]; + print_line("SMOOTH AT "+itos(count)+": "+itos(smooth)); + + } + } + + } + + format|=Mesh::ARRAY_FORMAT_NORMAL; + + if (was_indexed) { + index(); + smooth_groups.clear(); + } } @@ -722,6 +876,7 @@ void SurfaceTool::clear() { last_weights.clear(); index_array.clear(); vertex_array.clear(); + smooth_groups.clear(); } @@ -736,12 +891,12 @@ void SurfaceTool::_bind_methods() { ObjectTypeDB::bind_method(_MD("add_uv2","uv2"),&SurfaceTool::add_uv2); ObjectTypeDB::bind_method(_MD("add_bones","bones"),&SurfaceTool::add_bones); ObjectTypeDB::bind_method(_MD("add_weights","weights"),&SurfaceTool::add_weights); + ObjectTypeDB::bind_method(_MD("add_smooth_group","smooth"),&SurfaceTool::add_smooth_group); ObjectTypeDB::bind_method(_MD("set_material","material:Material"),&SurfaceTool::set_material); ObjectTypeDB::bind_method(_MD("index"),&SurfaceTool::index); ObjectTypeDB::bind_method(_MD("deindex"),&SurfaceTool::deindex); - ObjectTypeDB::bind_method(_MD("generate_flat_normals"),&SurfaceTool::generate_flat_normals); - ObjectTypeDB::bind_method(_MD("generate_smooth_normals"),&SurfaceTool::generate_smooth_normals); - ObjectTypeDB::bind_method(_MD("generate_tangents"),&SurfaceTool::generate_tangents); + ///ObjectTypeDB::bind_method(_MD("generate_flat_normals"),&SurfaceTool::generate_flat_normals); + ObjectTypeDB::bind_method(_MD("generate_normals"),&SurfaceTool::generate_normals); ObjectTypeDB::bind_method(_MD("commit:Mesh","existing:Mesh"),&SurfaceTool::commit,DEFVAL( RefPtr() )); ObjectTypeDB::bind_method(_MD("clear"),&SurfaceTool::clear); diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h index 8f0fcaa01a..fe82d3a4ce 100644 --- a/scene/resources/surface_tool.h +++ b/scene/resources/surface_tool.h @@ -49,12 +49,17 @@ public: Vector<int> bones; Vector<float> weights; + bool operator==(const Vertex& p_vertex) const; + Vertex() { } }; private: - bool compare(const Vertex& p_a,const Vertex& p_b) const; + + struct VertexHasher { + static _FORCE_INLINE_ uint32_t hash(const Vertex &p_vtx); + }; bool begun; bool first; @@ -64,6 +69,7 @@ private: //arrays List< Vertex > vertex_array; List< int > index_array; + Map<int,bool> smooth_groups; //memory Color last_color; @@ -92,13 +98,13 @@ public: void add_uv2( const Vector2& p_uv); void add_bones( const Vector<int>& p_indices); void add_weights( const Vector<float>& p_weights); + void add_smooth_group(bool p_smooth); void add_index( int p_index); void index(); void deindex(); - void generate_flat_normals(); - void generate_smooth_normals(); + void generate_normals(); void generate_tangents(); void add_to_format(int p_flags) { format|=p_flags; } diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index baf6fa9d8d..5b31ba1f1b 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -53,6 +53,13 @@ void Texture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,p_rect,get_rid(),p_src_rect,p_modulate); } +bool Texture::get_rect_region(const Rect2& p_rect, const Rect2& p_src_rect,Rect2& r_rect,Rect2& r_src_rect) const { + + r_rect=p_rect; + r_src_rect=p_src_rect; + + return true; +} void Texture::_bind_methods() { @@ -302,6 +309,16 @@ void ImageTexture::fix_alpha_edges() { } } +void ImageTexture::premultiply_alpha() { + + if (format==Image::FORMAT_RGBA /*&& !(flags&FLAG_CUBEMAP)*/) { + + Image img = get_data(); + img.premultiply_alpha(); + set_data(img); + } +} + bool ImageTexture::has_alpha() const { return ( format==Image::FORMAT_GRAYSCALE_ALPHA || format==Image::FORMAT_INDEXED_ALPHA || format==Image::FORMAT_RGBA ); @@ -386,8 +403,10 @@ void ImageTexture::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_lossy_storage_quality","quality"),&ImageTexture::set_lossy_storage_quality); ObjectTypeDB::bind_method(_MD("get_lossy_storage_quality"),&ImageTexture::get_lossy_storage_quality); ObjectTypeDB::bind_method(_MD("fix_alpha_edges"),&ImageTexture::fix_alpha_edges); + ObjectTypeDB::bind_method(_MD("premultiply_alpha"),&ImageTexture::premultiply_alpha); ObjectTypeDB::bind_method(_MD("set_size_override","size"),&ImageTexture::set_size_override); ObjectTypeDB::set_method_flags(get_type_static(),_SCS("fix_alpha_edges"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); + ObjectTypeDB::set_method_flags(get_type_static(),_SCS("premultiply_alpha"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); ObjectTypeDB::bind_method(_MD("_reload_hook","rid"),&ImageTexture::_reload_hook); @@ -597,6 +616,42 @@ void AtlasTexture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,dr,atlas->get_rid(),src_c,p_modulate); } +bool AtlasTexture::get_rect_region(const Rect2& p_rect, const Rect2& p_src_rect,Rect2& r_rect,Rect2& r_src_rect) const { + + Rect2 rc=region; + + if (!atlas.is_valid()) + return false; + + Rect2 src=p_src_rect; + src.pos+=(rc.pos-margin.pos); + Rect2 src_c = rc.clip(src); + if (src_c.size==Size2()) + return false; + Vector2 ofs = (src_c.pos-src.pos); + + 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; + ofs.x = -(ofs.x + mx); + } + if(scale.y < 0) + { + float my = margin.size.height - margin.pos.y; + my -= margin.pos.y; + ofs.y = -(ofs.y + my); + } + Rect2 dr( p_rect.pos+ofs*scale,src_c.size*scale ); + + + + r_rect=dr; + r_src_rect=src_c; + return true; +} + AtlasTexture::AtlasTexture() { diff --git a/scene/resources/texture.h b/scene/resources/texture.h index 6259362882..86ff246498 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -70,6 +70,7 @@ public: virtual void draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate=Color(1,1,1)) 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)) 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)) const; + virtual bool get_rect_region(const Rect2& p_rect, const Rect2& p_src_rect,Rect2& r_rect,Rect2& r_src_rect) const; @@ -143,6 +144,7 @@ public: float get_lossy_storage_quality() const; void fix_alpha_edges(); + void premultiply_alpha(); void set_size_override(const Size2& p_size); @@ -190,6 +192,7 @@ public: virtual void draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate=Color(1,1,1)) 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)) 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)) const; + virtual bool get_rect_region(const Rect2& p_rect, const Rect2& p_src_rect,Rect2& r_rect,Rect2& r_src_rect) const; AtlasTexture(); diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp index 5c54bd74e3..a8e4c80f89 100644 --- a/scene/scene_string_names.cpp +++ b/scene/scene_string_names.cpp @@ -137,5 +137,7 @@ SceneStringNames::SceneStringNames() { drop_data = StaticCString::create("drop_data"); can_drop_data = StaticCString::create("can_drop_data"); + _im_update = StaticCString::create("_im_update"); + _queue_update = StaticCString::create("_queue_update"); } diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h index 6a4e58ed54..2286712250 100644 --- a/scene/scene_string_names.h +++ b/scene/scene_string_names.h @@ -145,6 +145,10 @@ public: StringName play_play; + StringName _im_update; + StringName _queue_update; + + }; |