GODOT IS OPEN SOURCE
This commit is contained in:
7
scene/2d/SCsub
Normal file
7
scene/2d/SCsub
Normal file
@ -0,0 +1,7 @@
|
||||
Import('env')
|
||||
|
||||
env.add_source_files(env.scene_sources,"*.cpp")
|
||||
|
||||
Export('env')
|
||||
|
||||
|
||||
352
scene/2d/animated_sprite.cpp
Normal file
352
scene/2d/animated_sprite.cpp
Normal file
@ -0,0 +1,352 @@
|
||||
/*************************************************************************/
|
||||
/* animated_sprite.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "animated_sprite.h"
|
||||
|
||||
void AnimatedSprite::edit_set_pivot(const Point2& p_pivot) {
|
||||
|
||||
set_offset(p_pivot);
|
||||
}
|
||||
|
||||
Point2 AnimatedSprite::edit_get_pivot() const {
|
||||
|
||||
return get_offset();
|
||||
}
|
||||
bool AnimatedSprite::edit_has_pivot() const {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void SpriteFrames::add_frame(const Ref<Texture>& p_frame,int p_at_pos) {
|
||||
|
||||
if (p_at_pos>=0 && p_at_pos<frames.size())
|
||||
frames.insert(p_at_pos,p_frame);
|
||||
else
|
||||
frames.push_back(p_frame);
|
||||
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
int SpriteFrames::get_frame_count() const {
|
||||
|
||||
return frames.size();
|
||||
}
|
||||
|
||||
void SpriteFrames::remove_frame(int p_idx) {
|
||||
|
||||
frames.remove(p_idx);
|
||||
emit_changed();
|
||||
}
|
||||
void SpriteFrames::clear() {
|
||||
|
||||
frames.clear();
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
|
||||
Array SpriteFrames::_get_frames() const {
|
||||
|
||||
Array arr;
|
||||
arr.resize(frames.size());
|
||||
for(int i=0;i<frames.size();i++)
|
||||
arr[i]=frames[i];
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
void SpriteFrames::_set_frames(const Array& p_frames) {
|
||||
|
||||
frames.resize(p_frames.size());
|
||||
for(int i=0;i<frames.size();i++)
|
||||
frames[i]=p_frames[i];
|
||||
|
||||
}
|
||||
|
||||
|
||||
void SpriteFrames::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("add_frame","frame","atpos"),&SpriteFrames::add_frame,DEFVAL(-1));
|
||||
ObjectTypeDB::bind_method(_MD("get_frame_count"),&SpriteFrames::get_frame_count);
|
||||
ObjectTypeDB::bind_method(_MD("get_frame","idx"),&SpriteFrames::get_frame);
|
||||
ObjectTypeDB::bind_method(_MD("set_frame","idx","txt"),&SpriteFrames::set_frame);
|
||||
ObjectTypeDB::bind_method(_MD("remove_frame","idx"),&SpriteFrames::remove_frame);
|
||||
ObjectTypeDB::bind_method(_MD("clear"),&SpriteFrames::clear);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_set_frames"),&SpriteFrames::_set_frames);
|
||||
ObjectTypeDB::bind_method(_MD("_get_frames"),&SpriteFrames::_get_frames);
|
||||
|
||||
ADD_PROPERTYNZ( PropertyInfo(Variant::ARRAY,"frames",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_frames"),_SCS("_get_frames"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
SpriteFrames::SpriteFrames() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////
|
||||
|
||||
|
||||
void AnimatedSprite::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_DRAW: {
|
||||
|
||||
if (frames.is_null())
|
||||
return;
|
||||
|
||||
if (frame<0 || frame>=frames->get_frame_count())
|
||||
return;
|
||||
|
||||
Ref<Texture> texture = frames->get_frame(frame);
|
||||
if (texture.is_null())
|
||||
return;
|
||||
|
||||
//print_line("DECIDED TO DRAW");
|
||||
|
||||
RID ci = get_canvas_item();
|
||||
|
||||
/*
|
||||
texture->draw(ci,Point2());
|
||||
break;
|
||||
*/
|
||||
|
||||
Size2i s;
|
||||
s = texture->get_size();
|
||||
Point2i ofs=offset;
|
||||
if (centered)
|
||||
ofs-=s/2;
|
||||
|
||||
Rect2i dst_rect(ofs,s);
|
||||
|
||||
if (hflip)
|
||||
dst_rect.size.x=-dst_rect.size.x;
|
||||
if (vflip)
|
||||
dst_rect.size.y=-dst_rect.size.y;
|
||||
|
||||
texture->draw_rect(ci,dst_rect,false,modulate);
|
||||
// VisualServer::get_singleton()->canvas_item_add_texture_rect_region(ci,dst_rect,texture->get_rid(),src_rect,modulate);
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void AnimatedSprite::set_sprite_frames(const Ref<SpriteFrames> &p_frames) {
|
||||
|
||||
if (frames.is_valid())
|
||||
frames->disconnect("changed",this,"_res_changed");
|
||||
frames=p_frames;
|
||||
if (frames.is_valid())
|
||||
frames->connect("changed",this,"_res_changed");
|
||||
|
||||
if (!frames.is_valid()) {
|
||||
frame=0;
|
||||
|
||||
} else {
|
||||
set_frame(frame);
|
||||
}
|
||||
update();
|
||||
|
||||
}
|
||||
|
||||
Ref<SpriteFrames> AnimatedSprite::get_sprite_frames() const {
|
||||
|
||||
return frames;
|
||||
}
|
||||
|
||||
void AnimatedSprite::set_frame(int p_frame) {
|
||||
|
||||
if (!frames.is_valid()) {
|
||||
return;
|
||||
}
|
||||
if (p_frame>=frames->get_frame_count())
|
||||
p_frame=frames->get_frame_count()-1;
|
||||
if (p_frame<0)
|
||||
p_frame=0;
|
||||
|
||||
if (frame==p_frame)
|
||||
return;
|
||||
|
||||
frame=p_frame;
|
||||
update();
|
||||
_change_notify("frame");
|
||||
|
||||
|
||||
}
|
||||
int AnimatedSprite::get_frame() const {
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
|
||||
void AnimatedSprite::set_centered(bool p_center) {
|
||||
|
||||
centered=p_center;
|
||||
update();
|
||||
item_rect_changed();
|
||||
}
|
||||
|
||||
bool AnimatedSprite::is_centered() const {
|
||||
|
||||
return centered;
|
||||
}
|
||||
|
||||
void AnimatedSprite::set_offset(const Point2& p_offset) {
|
||||
|
||||
offset=p_offset;
|
||||
update();
|
||||
item_rect_changed();
|
||||
}
|
||||
Point2 AnimatedSprite::get_offset() const {
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
void AnimatedSprite::set_flip_h(bool p_flip) {
|
||||
|
||||
hflip=p_flip;
|
||||
update();
|
||||
}
|
||||
bool AnimatedSprite::is_flipped_h() const {
|
||||
|
||||
return hflip;
|
||||
}
|
||||
|
||||
void AnimatedSprite::set_flip_v(bool p_flip) {
|
||||
|
||||
vflip=p_flip;
|
||||
update();
|
||||
}
|
||||
bool AnimatedSprite::is_flipped_v() const {
|
||||
|
||||
return vflip;
|
||||
}
|
||||
|
||||
|
||||
void AnimatedSprite::set_modulate(const Color& p_color) {
|
||||
|
||||
modulate=p_color;
|
||||
update();
|
||||
}
|
||||
|
||||
Color AnimatedSprite::get_modulate() const{
|
||||
|
||||
return modulate;
|
||||
}
|
||||
|
||||
|
||||
Rect2 AnimatedSprite::get_item_rect() const {
|
||||
|
||||
if (!frames.is_valid() || !frames->get_frame_count() || frame<0 || frame>=frames->get_frame_count()) {
|
||||
return Node2D::get_item_rect();
|
||||
}
|
||||
|
||||
Ref<Texture> t = frames->get_frame(frame);
|
||||
if (t.is_null())
|
||||
return Node2D::get_item_rect();
|
||||
Size2i s = t->get_size();
|
||||
|
||||
Point2i ofs=offset;
|
||||
if (centered)
|
||||
ofs-=s/2;
|
||||
|
||||
if (s==Size2(0,0))
|
||||
s=Size2(1,1);
|
||||
|
||||
return Rect2(ofs,s);
|
||||
}
|
||||
|
||||
void AnimatedSprite::_res_changed() {
|
||||
|
||||
set_frame(frame);
|
||||
update();
|
||||
}
|
||||
|
||||
void AnimatedSprite::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_sprite_frames","sprite_frames:SpriteFrames"),&AnimatedSprite::set_sprite_frames);
|
||||
ObjectTypeDB::bind_method(_MD("get_sprite_frames:SpriteFrames"),&AnimatedSprite::get_sprite_frames);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_centered","centered"),&AnimatedSprite::set_centered);
|
||||
ObjectTypeDB::bind_method(_MD("is_centered"),&AnimatedSprite::is_centered);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_offset","offset"),&AnimatedSprite::set_offset);
|
||||
ObjectTypeDB::bind_method(_MD("get_offset"),&AnimatedSprite::get_offset);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_flip_h","flip_h"),&AnimatedSprite::set_flip_h);
|
||||
ObjectTypeDB::bind_method(_MD("is_flipped_h"),&AnimatedSprite::is_flipped_h);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_flip_v","flip_v"),&AnimatedSprite::set_flip_v);
|
||||
ObjectTypeDB::bind_method(_MD("is_flipped_v"),&AnimatedSprite::is_flipped_v);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_frame","frame"),&AnimatedSprite::set_frame);
|
||||
ObjectTypeDB::bind_method(_MD("get_frame"),&AnimatedSprite::get_frame);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_modulate","modulate"),&AnimatedSprite::set_modulate);
|
||||
ObjectTypeDB::bind_method(_MD("get_modulate"),&AnimatedSprite::get_modulate);
|
||||
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_res_changed"),&AnimatedSprite::_res_changed);
|
||||
|
||||
ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "frames",PROPERTY_HINT_RESOURCE_TYPE,"SpriteFrames"), _SCS("set_sprite_frames"),_SCS("get_sprite_frames"));
|
||||
ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "frame"), _SCS("set_frame"),_SCS("get_frame"));
|
||||
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "centered"), _SCS("set_centered"),_SCS("is_centered"));
|
||||
ADD_PROPERTYNZ( 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"));
|
||||
|
||||
}
|
||||
|
||||
AnimatedSprite::AnimatedSprite() {
|
||||
|
||||
centered=true;
|
||||
hflip=false;
|
||||
vflip=false;
|
||||
|
||||
frame=0;
|
||||
|
||||
|
||||
modulate=Color(1,1,1,1);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
119
scene/2d/animated_sprite.h
Normal file
119
scene/2d/animated_sprite.h
Normal file
@ -0,0 +1,119 @@
|
||||
/*************************************************************************/
|
||||
/* animated_sprite.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef ANIMATED_SPRITE_H
|
||||
#define ANIMATED_SPRITE_H
|
||||
|
||||
#include "scene/2d/node_2d.h"
|
||||
#include "scene/resources/texture.h"
|
||||
|
||||
|
||||
class SpriteFrames : public Resource {
|
||||
|
||||
OBJ_TYPE(SpriteFrames,Resource);
|
||||
|
||||
Vector< Ref<Texture> > frames;
|
||||
|
||||
Array _get_frames() const;
|
||||
void _set_frames(const Array& p_frames);
|
||||
protected:
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
|
||||
void add_frame(const Ref<Texture>& p_frame,int p_at_pos=-1);
|
||||
int get_frame_count() const;
|
||||
_FORCE_INLINE_ Ref<Texture> get_frame(int p_idx) const { ERR_FAIL_INDEX_V(p_idx,frames.size(),Ref<Texture>()); return frames[p_idx]; }
|
||||
void set_frame(int p_idx,const Ref<Texture>& p_frame){ ERR_FAIL_INDEX(p_idx,frames.size()); frames[p_idx]=p_frame; }
|
||||
void remove_frame(int p_idx);
|
||||
void clear();
|
||||
|
||||
SpriteFrames();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
class AnimatedSprite : public Node2D {
|
||||
|
||||
OBJ_TYPE(AnimatedSprite,Node2D);
|
||||
|
||||
Ref<SpriteFrames> frames;
|
||||
int frame;
|
||||
|
||||
bool centered;
|
||||
Point2 offset;
|
||||
|
||||
bool hflip;
|
||||
bool vflip;
|
||||
|
||||
Color modulate;
|
||||
|
||||
void _res_changed();
|
||||
protected:
|
||||
|
||||
static void _bind_methods();
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
|
||||
|
||||
virtual void edit_set_pivot(const Point2& p_pivot);
|
||||
virtual Point2 edit_get_pivot() const;
|
||||
virtual bool edit_has_pivot() const;
|
||||
|
||||
void set_sprite_frames(const Ref<SpriteFrames> &p_frames);
|
||||
Ref<SpriteFrames> get_sprite_frames() const;
|
||||
|
||||
void set_frame(int p_frame);
|
||||
int get_frame() const;
|
||||
|
||||
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_modulate(const Color& p_color);
|
||||
Color get_modulate() const;
|
||||
|
||||
virtual Rect2 get_item_rect() const;
|
||||
|
||||
|
||||
AnimatedSprite();
|
||||
};
|
||||
|
||||
#endif // ANIMATED_SPRITE_H
|
||||
326
scene/2d/area_2d.cpp
Normal file
326
scene/2d/area_2d.cpp
Normal file
@ -0,0 +1,326 @@
|
||||
/*************************************************************************/
|
||||
/* area_2d.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "area_2d.h"
|
||||
#include "scene/scene_string_names.h"
|
||||
#include "servers/physics_2d_server.h"
|
||||
void Area2D::set_space_override_mode(SpaceOverride p_mode) {
|
||||
|
||||
space_override=p_mode;
|
||||
Physics2DServer::get_singleton()->area_set_space_override_mode(get_rid(),Physics2DServer::AreaSpaceOverrideMode(p_mode));
|
||||
|
||||
|
||||
}
|
||||
Area2D::SpaceOverride Area2D::get_space_override_mode() const{
|
||||
|
||||
return space_override;
|
||||
}
|
||||
|
||||
void Area2D::set_gravity_is_point(bool p_enabled){
|
||||
|
||||
gravity_is_point=p_enabled;
|
||||
Physics2DServer::get_singleton()->area_set_param(get_rid(),Physics2DServer::AREA_PARAM_GRAVITY_IS_POINT,p_enabled);
|
||||
|
||||
}
|
||||
bool Area2D::is_gravity_a_point() const{
|
||||
|
||||
return gravity_is_point;
|
||||
}
|
||||
|
||||
void Area2D::set_gravity_vector(const Vector2& p_vec){
|
||||
|
||||
gravity_vec=p_vec;
|
||||
Physics2DServer::get_singleton()->area_set_param(get_rid(),Physics2DServer::AREA_PARAM_GRAVITY_VECTOR,p_vec);
|
||||
|
||||
}
|
||||
Vector2 Area2D::get_gravity_vector() const{
|
||||
|
||||
return gravity_vec;
|
||||
}
|
||||
|
||||
void Area2D::set_gravity(real_t p_gravity){
|
||||
|
||||
gravity=p_gravity;
|
||||
Physics2DServer::get_singleton()->area_set_param(get_rid(),Physics2DServer::AREA_PARAM_GRAVITY,p_gravity);
|
||||
}
|
||||
real_t Area2D::get_gravity() const{
|
||||
|
||||
return gravity;
|
||||
}
|
||||
|
||||
void Area2D::set_density(real_t p_density){
|
||||
|
||||
density=p_density;
|
||||
Physics2DServer::get_singleton()->area_set_param(get_rid(),Physics2DServer::AREA_PARAM_DENSITY,p_density);
|
||||
}
|
||||
real_t Area2D::get_density() const{
|
||||
|
||||
return density;
|
||||
}
|
||||
|
||||
void Area2D::set_priority(real_t p_priority){
|
||||
|
||||
priority=p_priority;
|
||||
Physics2DServer::get_singleton()->area_set_param(get_rid(),Physics2DServer::AREA_PARAM_PRIORITY,p_priority);
|
||||
}
|
||||
real_t Area2D::get_priority() const{
|
||||
|
||||
return priority;
|
||||
}
|
||||
|
||||
|
||||
void Area2D::_body_enter_scene(ObjectID p_id) {
|
||||
|
||||
Object *obj = ObjectDB::get_instance(p_id);
|
||||
Node *node = obj ? obj->cast_to<Node>() : NULL;
|
||||
ERR_FAIL_COND(!node);
|
||||
|
||||
Map<ObjectID,BodyState>::Element *E=body_map.find(p_id);
|
||||
ERR_FAIL_COND(!E);
|
||||
ERR_FAIL_COND(E->get().in_scene);
|
||||
|
||||
E->get().in_scene=true;
|
||||
emit_signal(SceneStringNames::get_singleton()->body_enter,node);
|
||||
for(int i=0;i<E->get().shapes.size();i++) {
|
||||
|
||||
emit_signal(SceneStringNames::get_singleton()->body_enter_shape,p_id,node,E->get().shapes[i].body_shape,E->get().shapes[i].area_shape);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Area2D::_body_exit_scene(ObjectID p_id) {
|
||||
|
||||
Object *obj = ObjectDB::get_instance(p_id);
|
||||
Node *node = obj ? obj->cast_to<Node>() : NULL;
|
||||
ERR_FAIL_COND(!node);
|
||||
Map<ObjectID,BodyState>::Element *E=body_map.find(p_id);
|
||||
ERR_FAIL_COND(!E);
|
||||
ERR_FAIL_COND(!E->get().in_scene);
|
||||
E->get().in_scene=false;
|
||||
emit_signal(SceneStringNames::get_singleton()->body_exit,node);
|
||||
for(int i=0;i<E->get().shapes.size();i++) {
|
||||
|
||||
emit_signal(SceneStringNames::get_singleton()->body_exit_shape,p_id,node,E->get().shapes[i].body_shape,E->get().shapes[i].area_shape);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Area2D::_body_inout(int p_status,const RID& p_body, int p_instance, int p_body_shape,int p_area_shape) {
|
||||
|
||||
bool body_in = p_status==Physics2DServer::AREA_BODY_ADDED;
|
||||
ObjectID objid=p_instance;
|
||||
|
||||
Object *obj = ObjectDB::get_instance(objid);
|
||||
Node *node = obj ? obj->cast_to<Node>() : NULL;
|
||||
|
||||
Map<ObjectID,BodyState>::Element *E=body_map.find(objid);
|
||||
|
||||
ERR_FAIL_COND(!body_in && !E);
|
||||
|
||||
if (body_in) {
|
||||
if (!E) {
|
||||
|
||||
E = body_map.insert(objid,BodyState());
|
||||
E->get().rc=0;
|
||||
E->get().in_scene=node && node->is_inside_scene();
|
||||
if (node) {
|
||||
node->connect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene,make_binds(objid));
|
||||
node->connect(SceneStringNames::get_singleton()->exit_scene,this,SceneStringNames::get_singleton()->_body_exit_scene,make_binds(objid));
|
||||
if (E->get().in_scene) {
|
||||
emit_signal(SceneStringNames::get_singleton()->body_enter,node);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
E->get().rc++;
|
||||
if (node)
|
||||
E->get().shapes.insert(ShapePair(p_body_shape,p_area_shape));
|
||||
|
||||
|
||||
if (E->get().in_scene) {
|
||||
emit_signal(SceneStringNames::get_singleton()->body_enter_shape,objid,node,p_body_shape,p_area_shape);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
E->get().rc--;
|
||||
|
||||
if (node)
|
||||
E->get().shapes.erase(ShapePair(p_body_shape,p_area_shape));
|
||||
|
||||
bool eraseit=false;
|
||||
|
||||
if (E->get().rc==0) {
|
||||
|
||||
if (node) {
|
||||
node->disconnect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene);
|
||||
node->disconnect(SceneStringNames::get_singleton()->exit_scene,this,SceneStringNames::get_singleton()->_body_exit_scene);
|
||||
if (E->get().in_scene)
|
||||
emit_signal(SceneStringNames::get_singleton()->body_exit,obj);
|
||||
|
||||
}
|
||||
|
||||
eraseit=true;
|
||||
|
||||
}
|
||||
if (node && E->get().in_scene) {
|
||||
emit_signal(SceneStringNames::get_singleton()->body_exit_shape,objid,obj,p_body_shape,p_area_shape);
|
||||
}
|
||||
|
||||
if (eraseit)
|
||||
body_map.erase(E);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Area2D::_clear_monitoring() {
|
||||
|
||||
|
||||
Map<ObjectID,BodyState> bmcopy = body_map;
|
||||
body_map.clear();
|
||||
//disconnect all monitored stuff
|
||||
|
||||
for (Map<ObjectID,BodyState>::Element *E=bmcopy.front();E;E=E->next()) {
|
||||
|
||||
Object *obj = ObjectDB::get_instance(E->key());
|
||||
Node *node = obj ? obj->cast_to<Node>() : NULL;
|
||||
ERR_CONTINUE(!node);
|
||||
if (!E->get().in_scene)
|
||||
continue;
|
||||
|
||||
for(int i=0;i<E->get().shapes.size();i++) {
|
||||
|
||||
emit_signal(SceneStringNames::get_singleton()->body_exit_shape,E->key(),node,E->get().shapes[i].body_shape,E->get().shapes[i].area_shape);
|
||||
}
|
||||
|
||||
emit_signal(SceneStringNames::get_singleton()->body_exit,obj);
|
||||
|
||||
node->disconnect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene);
|
||||
node->disconnect(SceneStringNames::get_singleton()->exit_scene,this,SceneStringNames::get_singleton()->_body_exit_scene);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Area2D::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_EXIT_SCENE: {
|
||||
|
||||
_clear_monitoring();
|
||||
} break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Area2D::set_enable_monitoring(bool p_enable) {
|
||||
|
||||
if (p_enable==monitoring)
|
||||
return;
|
||||
|
||||
monitoring=p_enable;
|
||||
|
||||
if (monitoring) {
|
||||
|
||||
Physics2DServer::get_singleton()->area_set_monitor_callback(get_rid(),this,"_body_inout");
|
||||
} else {
|
||||
Physics2DServer::get_singleton()->area_set_monitor_callback(get_rid(),NULL,StringName());
|
||||
_clear_monitoring();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool Area2D::is_monitoring_enabled() const {
|
||||
|
||||
return monitoring;
|
||||
}
|
||||
|
||||
|
||||
void Area2D::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_body_enter_scene","id"),&Area2D::_body_enter_scene);
|
||||
ObjectTypeDB::bind_method(_MD("_body_exit_scene","id"),&Area2D::_body_exit_scene);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_space_override_mode","enable"),&Area2D::set_space_override_mode);
|
||||
ObjectTypeDB::bind_method(_MD("get_space_override_mode"),&Area2D::get_space_override_mode);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_gravity_is_point","enable"),&Area2D::set_gravity_is_point);
|
||||
ObjectTypeDB::bind_method(_MD("is_gravity_a_point"),&Area2D::is_gravity_a_point);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_gravity_vector","vector"),&Area2D::set_gravity_vector);
|
||||
ObjectTypeDB::bind_method(_MD("get_gravity_vector"),&Area2D::get_gravity_vector);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_gravity","gravity"),&Area2D::set_gravity);
|
||||
ObjectTypeDB::bind_method(_MD("get_gravity"),&Area2D::get_gravity);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_density","density"),&Area2D::set_density);
|
||||
ObjectTypeDB::bind_method(_MD("get_density"),&Area2D::get_density);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_priority","priority"),&Area2D::set_priority);
|
||||
ObjectTypeDB::bind_method(_MD("get_priority"),&Area2D::get_priority);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_enable_monitoring","enable"),&Area2D::set_enable_monitoring);
|
||||
ObjectTypeDB::bind_method(_MD("is_monitoring_enabled"),&Area2D::is_monitoring_enabled);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_body_inout"),&Area2D::_body_inout);
|
||||
|
||||
|
||||
ADD_SIGNAL( MethodInfo("body_enter_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"area_shape")));
|
||||
ADD_SIGNAL( MethodInfo("body_exit_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"area_shape")));
|
||||
ADD_SIGNAL( MethodInfo("body_enter",PropertyInfo(Variant::OBJECT,"body")));
|
||||
ADD_SIGNAL( MethodInfo("body_exit",PropertyInfo(Variant::OBJECT,"body")));
|
||||
|
||||
ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"space_override",PROPERTY_HINT_ENUM,"Disabled,Combine,Replace"),_SCS("set_space_override_mode"),_SCS("get_space_override_mode"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"gravity_point"),_SCS("set_gravity_is_point"),_SCS("is_gravity_a_point"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"gravity_vec"),_SCS("set_gravity_vector"),_SCS("get_gravity_vector"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity",PROPERTY_HINT_RANGE,"-1024,1024,0.01"),_SCS("set_gravity"),_SCS("get_gravity"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"density",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_density"),_SCS("get_density"));
|
||||
ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"priority",PROPERTY_HINT_RANGE,"0,128,1"),_SCS("set_priority"),_SCS("get_priority"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"monitoring"),_SCS("set_enable_monitoring"),_SCS("is_monitoring_enabled"));
|
||||
|
||||
}
|
||||
|
||||
Area2D::Area2D() : CollisionObject2D(Physics2DServer::get_singleton()->area_create(),true) {
|
||||
|
||||
space_override=SPACE_OVERRIDE_DISABLED;
|
||||
set_gravity(98);;
|
||||
set_gravity_vector(Vector2(0,1));
|
||||
gravity_is_point=false;
|
||||
density=0.1;
|
||||
priority=0;
|
||||
monitoring=false;
|
||||
|
||||
}
|
||||
|
||||
Area2D::~Area2D() {
|
||||
|
||||
|
||||
}
|
||||
122
scene/2d/area_2d.h
Normal file
122
scene/2d/area_2d.h
Normal file
@ -0,0 +1,122 @@
|
||||
/*************************************************************************/
|
||||
/* area_2d.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef AREA_2D_H
|
||||
#define AREA_2D_H
|
||||
|
||||
#include "scene/2d/collision_object_2d.h"
|
||||
#include "vset.h"
|
||||
|
||||
class Area2D : public CollisionObject2D {
|
||||
|
||||
OBJ_TYPE( Area2D, CollisionObject2D );
|
||||
public:
|
||||
|
||||
enum SpaceOverride {
|
||||
SPACE_OVERRIDE_DISABLED,
|
||||
SPACE_OVERRIDE_COMBINE,
|
||||
SPACE_OVERRIDE_REPLACE
|
||||
};
|
||||
private:
|
||||
|
||||
|
||||
SpaceOverride space_override;
|
||||
Vector2 gravity_vec;
|
||||
real_t gravity;
|
||||
bool gravity_is_point;
|
||||
real_t density;
|
||||
int priority;
|
||||
bool monitoring;
|
||||
|
||||
void _body_inout(int p_status,const RID& p_body, int p_instance, int p_body_shape,int p_area_shape);
|
||||
|
||||
void _body_enter_scene(ObjectID p_id);
|
||||
void _body_exit_scene(ObjectID p_id);
|
||||
|
||||
struct ShapePair {
|
||||
|
||||
int body_shape;
|
||||
int area_shape;
|
||||
bool operator<(const ShapePair& p_sp) const {
|
||||
if (body_shape==p_sp.body_shape)
|
||||
return area_shape < p_sp.area_shape;
|
||||
else
|
||||
return body_shape < p_sp.body_shape;
|
||||
}
|
||||
|
||||
ShapePair() {}
|
||||
ShapePair(int p_bs, int p_as) { body_shape=p_bs; area_shape=p_as; }
|
||||
};
|
||||
|
||||
struct BodyState {
|
||||
|
||||
int rc;
|
||||
bool in_scene;
|
||||
VSet<ShapePair> shapes;
|
||||
};
|
||||
|
||||
Map<ObjectID,BodyState> body_map;
|
||||
|
||||
void _clear_monitoring();
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_space_override_mode(SpaceOverride p_mode);
|
||||
SpaceOverride get_space_override_mode() const;
|
||||
|
||||
void set_gravity_is_point(bool p_enabled);
|
||||
bool is_gravity_a_point() const;
|
||||
|
||||
void set_gravity_vector(const Vector2& p_vec);
|
||||
Vector2 get_gravity_vector() const;
|
||||
|
||||
void set_gravity(real_t p_gravity);
|
||||
real_t get_gravity() const;
|
||||
|
||||
void set_density(real_t p_density);
|
||||
real_t get_density() const;
|
||||
|
||||
void set_priority(real_t p_priority);
|
||||
real_t get_priority() const;
|
||||
|
||||
void set_enable_monitoring(bool p_enable);
|
||||
bool is_monitoring_enabled() const;
|
||||
|
||||
|
||||
Area2D();
|
||||
~Area2D();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(Area2D::SpaceOverride);
|
||||
|
||||
#endif // AREA_2D_H
|
||||
484
scene/2d/camera_2d.cpp
Normal file
484
scene/2d/camera_2d.cpp
Normal file
@ -0,0 +1,484 @@
|
||||
/*************************************************************************/
|
||||
/* camera_2d.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "camera_2d.h"
|
||||
#include "scene/scene_string_names.h"
|
||||
#include "servers/visual_server.h"
|
||||
|
||||
void Camera2D::_update_scroll() {
|
||||
|
||||
|
||||
if (!is_inside_scene())
|
||||
return;
|
||||
|
||||
if (get_scene()->is_editor_hint()) {
|
||||
update(); //will just be drawn
|
||||
return;
|
||||
}
|
||||
|
||||
if (current) {
|
||||
Matrix32 xform = get_camera_transform();
|
||||
|
||||
RID vp = viewport->get_viewport();
|
||||
if (viewport) {
|
||||
viewport->set_canvas_transform( xform );
|
||||
}
|
||||
get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,group_name,"_camera_moved",xform);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void Camera2D::set_zoom(const Vector2 &p_zoom) {
|
||||
|
||||
zoom = p_zoom;
|
||||
_update_scroll();
|
||||
};
|
||||
|
||||
Vector2 Camera2D::get_zoom() const {
|
||||
|
||||
return zoom;
|
||||
};
|
||||
|
||||
|
||||
Matrix32 Camera2D::get_camera_transform() {
|
||||
|
||||
if (!get_scene())
|
||||
return Matrix32();
|
||||
|
||||
Size2 screen_size = get_viewport_rect().size;
|
||||
screen_size=get_viewport_rect().size;
|
||||
|
||||
|
||||
Point2 new_camera_pos = get_global_transform().get_origin();
|
||||
Point2 ret_camera_pos;
|
||||
|
||||
if (!first) {
|
||||
|
||||
|
||||
if (centered) {
|
||||
|
||||
if (h_drag_enabled) {
|
||||
camera_pos.x = MIN( camera_pos.x, (new_camera_pos.x + screen_size.x * 0.5 * drag_margin[MARGIN_RIGHT]));
|
||||
camera_pos.x = MAX( camera_pos.x, (new_camera_pos.x - screen_size.x * 0.5 * drag_margin[MARGIN_LEFT]));
|
||||
} else {
|
||||
|
||||
if (h_ofs<0) {
|
||||
camera_pos.x = new_camera_pos.x + screen_size.x * 0.5 * drag_margin[MARGIN_RIGHT] * h_ofs;
|
||||
} else {
|
||||
camera_pos.x = new_camera_pos.x + screen_size.x * 0.5 * drag_margin[MARGIN_LEFT] * h_ofs;
|
||||
}
|
||||
}
|
||||
|
||||
if (v_drag_enabled) {
|
||||
|
||||
camera_pos.y = MIN( camera_pos.y, (new_camera_pos.y + screen_size.y * 0.5 * drag_margin[MARGIN_BOTTOM]));
|
||||
camera_pos.y = MAX( camera_pos.y, (new_camera_pos.y - screen_size.y * 0.5 * drag_margin[MARGIN_TOP]));
|
||||
|
||||
} else {
|
||||
|
||||
if (v_ofs<0) {
|
||||
camera_pos.y = new_camera_pos.y + screen_size.y * 0.5 * drag_margin[MARGIN_TOP] * v_ofs;
|
||||
} else {
|
||||
camera_pos.y = new_camera_pos.y + screen_size.y * 0.5 * drag_margin[MARGIN_BOTTOM] * v_ofs;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (smoothing>0.0) {
|
||||
|
||||
float c = smoothing*get_fixed_process_delta_time();
|
||||
smoothed_camera_pos = ((new_camera_pos-smoothed_camera_pos)*c)+smoothed_camera_pos;
|
||||
ret_camera_pos=smoothed_camera_pos;
|
||||
// camera_pos=camera_pos*(1.0-smoothing)+new_camera_pos*smoothing;
|
||||
} else {
|
||||
|
||||
ret_camera_pos=smoothed_camera_pos=camera_pos;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
} else {
|
||||
ret_camera_pos=smoothed_camera_pos=camera_pos=new_camera_pos;
|
||||
first=false;
|
||||
}
|
||||
|
||||
|
||||
Point2 screen_offset = (centered ? (screen_size * 0.5 * zoom) : Point2());;
|
||||
screen_offset+=offset;
|
||||
|
||||
Rect2 screen_rect(-screen_offset+ret_camera_pos,screen_size);
|
||||
if (screen_rect.pos.x + screen_rect.size.x > limit[MARGIN_RIGHT])
|
||||
screen_rect.pos.x = limit[MARGIN_RIGHT] - screen_rect.size.x;
|
||||
|
||||
if (screen_rect.pos.y + screen_rect.size.y > limit[MARGIN_BOTTOM])
|
||||
screen_rect.pos.y = limit[MARGIN_BOTTOM] - screen_rect.size.y;
|
||||
|
||||
|
||||
if (screen_rect.pos.x < limit[MARGIN_LEFT])
|
||||
screen_rect.pos.x=limit[MARGIN_LEFT];
|
||||
|
||||
if (screen_rect.pos.y < limit[MARGIN_TOP])
|
||||
screen_rect.pos.y =limit[MARGIN_TOP];
|
||||
|
||||
camera_screen_center=screen_rect.pos+screen_rect.size*0.5;
|
||||
|
||||
Matrix32 xform;
|
||||
xform.scale_basis(zoom);
|
||||
xform.set_origin(screen_rect.pos/*.floor()*/);
|
||||
|
||||
|
||||
/*
|
||||
if (0) {
|
||||
|
||||
xform = get_global_transform() * xform;
|
||||
} else {
|
||||
|
||||
xform.elements[2]+=get_global_transform().get_origin();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
return (xform).affine_inverse();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Camera2D::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_FIXED_PROCESS: {
|
||||
|
||||
_update_scroll();
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
|
||||
|
||||
if (!is_fixed_processing())
|
||||
_update_scroll();
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_ENTER_SCENE: {
|
||||
|
||||
viewport = NULL;
|
||||
Node *n=this;
|
||||
while(n){
|
||||
|
||||
viewport = n->cast_to<Viewport>();
|
||||
if (viewport)
|
||||
break;
|
||||
n=n->get_parent();
|
||||
}
|
||||
|
||||
canvas = get_canvas();
|
||||
|
||||
RID vp = viewport->get_viewport();
|
||||
|
||||
group_name = "__cameras_"+itos(vp.get_id());
|
||||
canvas_group_name ="__cameras_c"+itos(canvas.get_id());
|
||||
add_to_group(group_name);
|
||||
add_to_group(canvas_group_name);
|
||||
|
||||
_update_scroll();
|
||||
first=true;
|
||||
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_SCENE: {
|
||||
|
||||
if (is_current()) {
|
||||
if (viewport) {
|
||||
viewport->set_canvas_transform( Matrix32() );
|
||||
}
|
||||
}
|
||||
remove_from_group(group_name);
|
||||
remove_from_group(canvas_group_name);
|
||||
viewport=NULL;
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void Camera2D::set_offset(const Vector2& p_offset) {
|
||||
|
||||
offset=p_offset;
|
||||
_update_scroll();
|
||||
|
||||
}
|
||||
|
||||
Vector2 Camera2D::get_offset() const{
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
void Camera2D::set_centered(bool p_centered){
|
||||
|
||||
centered=p_centered;
|
||||
_update_scroll();
|
||||
}
|
||||
|
||||
bool Camera2D::is_centered() const {
|
||||
|
||||
return centered;
|
||||
}
|
||||
|
||||
|
||||
void Camera2D::_make_current(Object *p_which) {
|
||||
|
||||
if (p_which==this) {
|
||||
|
||||
current=true;
|
||||
_update_scroll();
|
||||
} else {
|
||||
current=false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Camera2D::_set_current(bool p_current) {
|
||||
|
||||
if (p_current)
|
||||
make_current();
|
||||
|
||||
current=p_current;
|
||||
}
|
||||
|
||||
bool Camera2D::is_current() const {
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
void Camera2D::make_current() {
|
||||
|
||||
if (!is_inside_scene()) {
|
||||
current=true;
|
||||
} else {
|
||||
get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,group_name,"_make_current",this);
|
||||
}
|
||||
}
|
||||
|
||||
void Camera2D::set_limit(Margin p_margin,int p_limit) {
|
||||
|
||||
ERR_FAIL_INDEX(p_margin,4);
|
||||
limit[p_margin]=p_limit;
|
||||
}
|
||||
|
||||
int Camera2D::get_limit(Margin p_margin) const{
|
||||
|
||||
ERR_FAIL_INDEX_V(p_margin,4,0);
|
||||
return limit[p_margin];
|
||||
|
||||
}
|
||||
|
||||
void Camera2D::set_drag_margin(Margin p_margin,float p_drag_margin) {
|
||||
|
||||
ERR_FAIL_INDEX(p_margin,4);
|
||||
drag_margin[p_margin]=p_drag_margin;
|
||||
}
|
||||
|
||||
float Camera2D::get_drag_margin(Margin p_margin) const{
|
||||
|
||||
ERR_FAIL_INDEX_V(p_margin,4,0);
|
||||
return drag_margin[p_margin];
|
||||
|
||||
}
|
||||
|
||||
|
||||
Vector2 Camera2D::get_camera_pos() const {
|
||||
|
||||
|
||||
return camera_pos;
|
||||
}
|
||||
|
||||
void Camera2D::force_update_scroll() {
|
||||
|
||||
|
||||
_update_scroll();
|
||||
}
|
||||
|
||||
|
||||
void Camera2D::set_follow_smoothing(float p_speed) {
|
||||
|
||||
smoothing=p_speed;
|
||||
if (smoothing>0)
|
||||
set_fixed_process(true);
|
||||
else
|
||||
set_fixed_process(false);
|
||||
}
|
||||
|
||||
float Camera2D::get_follow_smoothing() const{
|
||||
|
||||
return smoothing;
|
||||
}
|
||||
|
||||
Point2 Camera2D::get_camera_screen_center() const {
|
||||
|
||||
return camera_screen_center;
|
||||
}
|
||||
|
||||
|
||||
void Camera2D::set_h_drag_enabled(bool p_enabled) {
|
||||
|
||||
h_drag_enabled=p_enabled;
|
||||
}
|
||||
|
||||
bool Camera2D::is_h_drag_enabled() const{
|
||||
|
||||
return h_drag_enabled;
|
||||
}
|
||||
|
||||
void Camera2D::set_v_drag_enabled(bool p_enabled){
|
||||
|
||||
v_drag_enabled=p_enabled;
|
||||
}
|
||||
|
||||
bool Camera2D::is_v_drag_enabled() const{
|
||||
|
||||
return v_drag_enabled;
|
||||
}
|
||||
|
||||
void Camera2D::set_v_offset(float p_offset) {
|
||||
|
||||
v_ofs=p_offset;
|
||||
}
|
||||
|
||||
float Camera2D::get_v_offset() const{
|
||||
|
||||
return v_ofs;
|
||||
}
|
||||
|
||||
void Camera2D::set_h_offset(float p_offset){
|
||||
|
||||
h_ofs=p_offset;
|
||||
}
|
||||
float Camera2D::get_h_offset() const{
|
||||
|
||||
return h_ofs;
|
||||
}
|
||||
|
||||
|
||||
void Camera2D::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_offset","offset"),&Camera2D::set_offset);
|
||||
ObjectTypeDB::bind_method(_MD("get_offset"),&Camera2D::get_offset);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_centered","centered"),&Camera2D::set_centered);
|
||||
ObjectTypeDB::bind_method(_MD("is_centered"),&Camera2D::is_centered);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("make_current"),&Camera2D::make_current);
|
||||
ObjectTypeDB::bind_method(_MD("_make_current"),&Camera2D::_make_current);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_update_scroll"),&Camera2D::_update_scroll);
|
||||
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_set_current","current"),&Camera2D::_set_current);
|
||||
ObjectTypeDB::bind_method(_MD("is_current"),&Camera2D::is_current);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_limit","margin","limit"),&Camera2D::set_limit);
|
||||
ObjectTypeDB::bind_method(_MD("get_limit","margin"),&Camera2D::get_limit);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_v_drag_enabled","enabled"),&Camera2D::set_v_drag_enabled);
|
||||
ObjectTypeDB::bind_method(_MD("is_v_drag_enabled"),&Camera2D::is_v_drag_enabled);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_h_drag_enabled","enabled"),&Camera2D::set_h_drag_enabled);
|
||||
ObjectTypeDB::bind_method(_MD("is_h_drag_enabled"),&Camera2D::is_h_drag_enabled);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_v_offset","ofs"),&Camera2D::set_v_offset);
|
||||
ObjectTypeDB::bind_method(_MD("get_v_offset"),&Camera2D::get_v_offset);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_h_offset","ofs"),&Camera2D::set_h_offset);
|
||||
ObjectTypeDB::bind_method(_MD("get_h_offset"),&Camera2D::get_h_offset);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_drag_margin","margin","drag_margin"),&Camera2D::set_drag_margin);
|
||||
ObjectTypeDB::bind_method(_MD("get_drag_margin","margin"),&Camera2D::get_drag_margin);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("get_camera_pos"),&Camera2D::get_camera_pos);
|
||||
ObjectTypeDB::bind_method(_MD("get_camera_screen_center"),&Camera2D::get_camera_screen_center);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_zoom"),&Camera2D::set_zoom);
|
||||
ObjectTypeDB::bind_method(_MD("get_zoom"),&Camera2D::get_zoom);
|
||||
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_follow_smoothing","follow_smoothing"),&Camera2D::set_follow_smoothing);
|
||||
ObjectTypeDB::bind_method(_MD("get_follow_smoothing"),&Camera2D::get_follow_smoothing);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("force_update_scroll"),&Camera2D::force_update_scroll);
|
||||
|
||||
|
||||
ADD_PROPERTYNZ( PropertyInfo(Variant::VECTOR2,"offset"),_SCS("set_offset"),_SCS("get_offset"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"centered"),_SCS("set_centered"),_SCS("is_centered"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"current"),_SCS("_set_current"),_SCS("is_current"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"smoothing"),_SCS("set_follow_smoothing"),_SCS("get_follow_smoothing") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"zoom"),_SCS("set_zoom"),_SCS("get_zoom") );
|
||||
|
||||
ADD_PROPERTYI( PropertyInfo(Variant::INT,"limit/left"),_SCS("set_limit"),_SCS("get_limit"),MARGIN_LEFT);
|
||||
ADD_PROPERTYI( PropertyInfo(Variant::INT,"limit/top"),_SCS("set_limit"),_SCS("get_limit"),MARGIN_TOP);
|
||||
ADD_PROPERTYI( PropertyInfo(Variant::INT,"limit/right"),_SCS("set_limit"),_SCS("get_limit"),MARGIN_RIGHT);
|
||||
ADD_PROPERTYI( PropertyInfo(Variant::INT,"limit/bottom"),_SCS("set_limit"),_SCS("get_limit"),MARGIN_BOTTOM);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"drag_margin/h_enabled"),_SCS("set_h_drag_enabled"),_SCS("is_h_drag_enabled") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"drag_margin/v_enabled"),_SCS("set_v_drag_enabled"),_SCS("is_v_drag_enabled") );
|
||||
|
||||
ADD_PROPERTYI( PropertyInfo(Variant::REAL,"drag_margin/left",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_drag_margin"),_SCS("get_drag_margin"),MARGIN_LEFT);
|
||||
ADD_PROPERTYI( PropertyInfo(Variant::REAL,"drag_margin/top",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_drag_margin"),_SCS("get_drag_margin"),MARGIN_TOP);
|
||||
ADD_PROPERTYI( PropertyInfo(Variant::REAL,"drag_margin/right",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_drag_margin"),_SCS("get_drag_margin"),MARGIN_RIGHT);
|
||||
ADD_PROPERTYI( PropertyInfo(Variant::REAL,"drag_margin/bottom",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_drag_margin"),_SCS("get_drag_margin"),MARGIN_BOTTOM);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Camera2D::Camera2D() {
|
||||
|
||||
|
||||
|
||||
centered=true;
|
||||
current=false;
|
||||
limit[MARGIN_LEFT]=-10000000;
|
||||
limit[MARGIN_TOP]=-10000000;
|
||||
limit[MARGIN_RIGHT]=10000000;
|
||||
limit[MARGIN_BOTTOM]=10000000;
|
||||
drag_margin[MARGIN_LEFT]=0.2;
|
||||
drag_margin[MARGIN_TOP]=0.2;
|
||||
drag_margin[MARGIN_RIGHT]=0.2;
|
||||
drag_margin[MARGIN_BOTTOM]=0.2;
|
||||
camera_pos=Vector2();
|
||||
|
||||
smoothing=0.0;
|
||||
zoom = Vector2(1, 1);
|
||||
|
||||
h_drag_enabled=true;
|
||||
v_drag_enabled=true;
|
||||
h_ofs=0;
|
||||
v_ofs=0;
|
||||
|
||||
}
|
||||
118
scene/2d/camera_2d.h
Normal file
118
scene/2d/camera_2d.h
Normal file
@ -0,0 +1,118 @@
|
||||
/*************************************************************************/
|
||||
/* camera_2d.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef CAMERA_2D_H
|
||||
#define CAMERA_2D_H
|
||||
|
||||
#include "scene/2d/node_2d.h"
|
||||
#include "scene/main/viewport.h"
|
||||
|
||||
|
||||
class Camera2D : public Node2D {
|
||||
|
||||
OBJ_TYPE( Camera2D, Node2D );
|
||||
|
||||
protected:
|
||||
Point2 camera_pos;
|
||||
Point2 smoothed_camera_pos;
|
||||
bool first;
|
||||
|
||||
Viewport *viewport;
|
||||
|
||||
StringName group_name;
|
||||
StringName canvas_group_name;
|
||||
RID canvas;
|
||||
Vector2 offset;
|
||||
Vector2 zoom;
|
||||
bool centered;
|
||||
bool current;
|
||||
float smoothing;
|
||||
int limit[4];
|
||||
float drag_margin[4];
|
||||
|
||||
bool h_drag_enabled;
|
||||
bool v_drag_enabled;
|
||||
float h_ofs;
|
||||
float v_ofs;
|
||||
|
||||
|
||||
Point2 camera_screen_center;
|
||||
void _update_scroll();
|
||||
|
||||
void _make_current(Object *p_which);
|
||||
void _set_current(bool p_current);
|
||||
protected:
|
||||
|
||||
virtual Matrix32 get_camera_transform();
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_offset(const Vector2& p_offset);
|
||||
Vector2 get_offset() const;
|
||||
|
||||
void set_centered(bool p_centered);
|
||||
bool is_centered() const;
|
||||
|
||||
void set_limit(Margin p_margin,int p_limit);
|
||||
int get_limit(Margin p_margin) const;
|
||||
|
||||
|
||||
void set_h_drag_enabled(bool p_enabled);
|
||||
bool is_h_drag_enabled() const;
|
||||
|
||||
void set_v_drag_enabled(bool p_enabled);
|
||||
bool is_v_drag_enabled() const;
|
||||
|
||||
void set_drag_margin(Margin p_margin,float p_drag_margin);
|
||||
float get_drag_margin(Margin p_margin) const;
|
||||
|
||||
void set_v_offset(float p_offset);
|
||||
float get_v_offset() const;
|
||||
|
||||
void set_h_offset(float p_offset);
|
||||
float get_h_offset() const;
|
||||
|
||||
void set_follow_smoothing(float p_speed);
|
||||
float get_follow_smoothing() const;
|
||||
|
||||
void make_current();
|
||||
bool is_current() const;
|
||||
|
||||
void set_zoom(const Vector2& p_zoom);
|
||||
Vector2 get_zoom() const;
|
||||
|
||||
Point2 get_camera_screen_center() const;
|
||||
|
||||
Vector2 get_camera_pos() const;
|
||||
void force_update_scroll();
|
||||
|
||||
Camera2D();
|
||||
};
|
||||
|
||||
#endif // CAMERA_2D_H
|
||||
875
scene/2d/canvas_item.cpp
Normal file
875
scene/2d/canvas_item.cpp
Normal file
@ -0,0 +1,875 @@
|
||||
/*************************************************************************/
|
||||
/* canvas_item.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "canvas_item.h"
|
||||
#include "servers/visual_server.h"
|
||||
#include "scene/main/viewport.h"
|
||||
#include "scene/main/canvas_layer.h"
|
||||
#include "message_queue.h"
|
||||
#include "scene/scene_string_names.h"
|
||||
#include "scene/resources/font.h"
|
||||
#include "scene/resources/texture.h"
|
||||
#include "scene/resources/style_box.h"
|
||||
|
||||
bool CanvasItem::is_visible() const {
|
||||
|
||||
if (!is_inside_scene())
|
||||
return false;
|
||||
|
||||
const CanvasItem *p=this;
|
||||
|
||||
while(p) {
|
||||
if (p->hidden)
|
||||
return false;
|
||||
p=p->get_parent_item();
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CanvasItem::is_hidden() const {
|
||||
|
||||
/*if (!is_inside_scene())
|
||||
return false;*/
|
||||
|
||||
return hidden;
|
||||
}
|
||||
|
||||
void CanvasItem::_propagate_visibility_changed(bool p_visible) {
|
||||
|
||||
notification(NOTIFICATION_VISIBILITY_CHANGED);
|
||||
|
||||
if (p_visible)
|
||||
update(); //todo optimize
|
||||
else
|
||||
emit_signal(SceneStringNames::get_singleton()->hide);
|
||||
_block();
|
||||
|
||||
for(int i=0;i<get_child_count();i++) {
|
||||
|
||||
CanvasItem *c=get_child(i)->cast_to<CanvasItem>();
|
||||
|
||||
if (c && c->hidden!=p_visible) //should the toplevels stop propagation? i think so but..
|
||||
c->_propagate_visibility_changed(p_visible);
|
||||
}
|
||||
|
||||
_unblock();
|
||||
|
||||
}
|
||||
|
||||
void CanvasItem::show() {
|
||||
|
||||
if (!hidden)
|
||||
return;
|
||||
|
||||
|
||||
hidden=false;
|
||||
VisualServer::get_singleton()->canvas_item_set_visible(canvas_item,true);
|
||||
|
||||
if (!is_inside_scene())
|
||||
return;
|
||||
|
||||
if (is_visible()) {
|
||||
_propagate_visibility_changed(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CanvasItem::hide() {
|
||||
|
||||
if (hidden)
|
||||
return;
|
||||
|
||||
bool propagate=is_inside_scene() && is_visible();
|
||||
hidden=true;
|
||||
VisualServer::get_singleton()->canvas_item_set_visible(canvas_item,false);
|
||||
|
||||
if (!is_inside_scene())
|
||||
return;
|
||||
if (propagate)
|
||||
_propagate_visibility_changed(false);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Variant CanvasItem::edit_get_state() const {
|
||||
|
||||
|
||||
return Variant();
|
||||
}
|
||||
void CanvasItem::edit_set_state(const Variant& p_state) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CanvasItem::edit_set_rect(const Rect2& p_edit_rect) {
|
||||
|
||||
//used by editors, implement at will
|
||||
}
|
||||
|
||||
void CanvasItem::edit_rotate(float p_rot) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
Size2 CanvasItem::edit_get_minimum_size() const {
|
||||
|
||||
return Size2(-1,-1); //no limit
|
||||
}
|
||||
|
||||
void CanvasItem::_update_callback() {
|
||||
|
||||
|
||||
|
||||
if (!is_inside_scene()) {
|
||||
pending_update=false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
VisualServer::get_singleton()->canvas_item_clear(get_canvas_item());
|
||||
//todo updating = true - only allow drawing here
|
||||
if (is_visible()) { //todo optimize this!!
|
||||
if (first_draw) {
|
||||
notification(NOTIFICATION_VISIBILITY_CHANGED);
|
||||
first_draw=false;
|
||||
}
|
||||
drawing=true;
|
||||
notification(NOTIFICATION_DRAW);
|
||||
emit_signal(SceneStringNames::get_singleton()->draw);
|
||||
if (get_script_instance()) {
|
||||
Variant::CallError err;
|
||||
get_script_instance()->call_multilevel_reversed(SceneStringNames::get_singleton()->_draw,NULL,0);
|
||||
}
|
||||
drawing=false;
|
||||
|
||||
}
|
||||
//todo updating = false
|
||||
pending_update=false; // don't change to false until finished drawing (avoid recursive update)
|
||||
}
|
||||
|
||||
Matrix32 CanvasItem::get_global_transform_with_canvas() const {
|
||||
|
||||
const CanvasItem *ci = this;
|
||||
Matrix32 xform;
|
||||
const CanvasItem *last_valid=NULL;
|
||||
|
||||
while(ci) {
|
||||
|
||||
last_valid=ci;
|
||||
xform = ci->get_transform() * xform;
|
||||
ci=ci->get_parent_item();
|
||||
}
|
||||
|
||||
if (last_valid->canvas_layer)
|
||||
return last_valid->canvas_layer->get_transform() * xform;
|
||||
else
|
||||
return xform;
|
||||
}
|
||||
|
||||
Matrix32 CanvasItem::get_global_transform() const {
|
||||
|
||||
|
||||
if (global_invalid) {
|
||||
|
||||
const CanvasItem *pi = get_parent_item();
|
||||
if (pi)
|
||||
global_transform = pi->get_global_transform() * get_transform();
|
||||
else
|
||||
global_transform = get_transform();
|
||||
|
||||
global_invalid=false;
|
||||
}
|
||||
|
||||
return global_transform;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CanvasItem::_queue_sort_children() {
|
||||
|
||||
if (pending_children_sort)
|
||||
return;
|
||||
|
||||
pending_children_sort=true;
|
||||
MessageQueue::get_singleton()->push_call(this,"_sort_children");
|
||||
}
|
||||
|
||||
void CanvasItem::_sort_children() {
|
||||
|
||||
pending_children_sort=false;
|
||||
|
||||
if (!is_inside_scene())
|
||||
return;
|
||||
|
||||
for(int i=0;i<get_child_count();i++) {
|
||||
|
||||
Node *n = get_child(i);
|
||||
CanvasItem *ci=n->cast_to<CanvasItem>();
|
||||
|
||||
if (ci) {
|
||||
if (ci->toplevel || ci->group!="")
|
||||
continue;
|
||||
VisualServer::get_singleton()->canvas_item_raise(n->cast_to<CanvasItem>()->canvas_item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasItem::_raise_self() {
|
||||
|
||||
if (!is_inside_scene())
|
||||
return;
|
||||
|
||||
VisualServer::get_singleton()->canvas_item_raise(canvas_item);
|
||||
}
|
||||
|
||||
|
||||
void CanvasItem::_enter_canvas() {
|
||||
|
||||
if ((!get_parent() || !get_parent()->cast_to<CanvasItem>()) || toplevel) {
|
||||
|
||||
Node *n = this;
|
||||
viewport=NULL;
|
||||
canvas_layer=NULL;
|
||||
|
||||
while(n) {
|
||||
|
||||
if (n->cast_to<Viewport>()) {
|
||||
|
||||
viewport = n->cast_to<Viewport>();
|
||||
break;
|
||||
}
|
||||
if (!canvas_layer && n->cast_to<CanvasLayer>()) {
|
||||
|
||||
canvas_layer = n->cast_to<CanvasLayer>();
|
||||
}
|
||||
n=n->get_parent();
|
||||
}
|
||||
|
||||
RID canvas;
|
||||
if (canvas_layer)
|
||||
canvas=canvas_layer->get_world_2d()->get_canvas();
|
||||
else
|
||||
canvas=viewport->find_world_2d()->get_canvas();
|
||||
|
||||
VisualServer::get_singleton()->canvas_item_set_parent(canvas_item,canvas);
|
||||
|
||||
group = "root_canvas"+itos(canvas.get_id());
|
||||
|
||||
add_to_group(group);
|
||||
get_scene()->call_group(SceneMainLoop::GROUP_CALL_UNIQUE,group,"_raise_self");
|
||||
|
||||
} else {
|
||||
|
||||
CanvasItem *parent = get_parent_item();
|
||||
viewport=parent->viewport;
|
||||
VisualServer::get_singleton()->canvas_item_set_parent(canvas_item,parent->get_canvas_item());
|
||||
parent->_queue_sort_children();
|
||||
}
|
||||
|
||||
if (!viewport) {
|
||||
|
||||
print_line("no viewport wtf!");
|
||||
}
|
||||
pending_update=false;
|
||||
update();
|
||||
|
||||
notification(NOTIFICATION_ENTER_CANVAS);
|
||||
|
||||
}
|
||||
|
||||
void CanvasItem::_exit_canvas() {
|
||||
|
||||
notification(NOTIFICATION_EXIT_CANVAS,true); //reverse the notification
|
||||
VisualServer::get_singleton()->canvas_item_set_parent(canvas_item,RID());
|
||||
viewport=NULL;
|
||||
canvas_layer=NULL;
|
||||
group="";
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CanvasItem::_notification(int p_what) {
|
||||
|
||||
|
||||
switch(p_what) {
|
||||
case NOTIFICATION_ENTER_SCENE: {
|
||||
|
||||
first_draw=true;
|
||||
pending_children_sort=false;
|
||||
if (get_parent()) {
|
||||
CanvasItem *ci = get_parent()->cast_to<CanvasItem>();
|
||||
if (ci)
|
||||
C=ci->children_items.push_back(this);
|
||||
}
|
||||
_enter_canvas();
|
||||
if (!block_transform_notify && !xform_change.in_list()) {
|
||||
get_scene()->xform_change_list.add(&xform_change);
|
||||
}
|
||||
} break;
|
||||
case NOTIFICATION_MOVED_IN_PARENT: {
|
||||
|
||||
|
||||
if (group!="") {
|
||||
get_scene()->call_group(SceneMainLoop::GROUP_CALL_UNIQUE,group,"_raise_self");
|
||||
} else {
|
||||
CanvasItem *p = get_parent_item();
|
||||
ERR_FAIL_COND(!p);
|
||||
p->_queue_sort_children();
|
||||
}
|
||||
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_SCENE: {
|
||||
if (xform_change.in_list())
|
||||
get_scene()->xform_change_list.remove(&xform_change);
|
||||
_exit_canvas();
|
||||
if (C)
|
||||
get_parent()->cast_to<CanvasItem>()->children_items.erase(C);
|
||||
} break;
|
||||
case NOTIFICATION_DRAW: {
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_VISIBILITY_CHANGED: {
|
||||
|
||||
emit_signal(SceneStringNames::get_singleton()->visibility_changed);
|
||||
} break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasItem::_set_visible_(bool p_visible) {
|
||||
|
||||
if (p_visible)
|
||||
show();
|
||||
else
|
||||
hide();
|
||||
}
|
||||
bool CanvasItem::_is_visible_() const {
|
||||
|
||||
return !is_hidden();
|
||||
}
|
||||
|
||||
|
||||
void CanvasItem::update() {
|
||||
|
||||
if (!is_inside_scene())
|
||||
return;
|
||||
if (pending_update)
|
||||
return;
|
||||
|
||||
pending_update=true;
|
||||
|
||||
MessageQueue::get_singleton()->push_call(this,"_update_callback");
|
||||
}
|
||||
|
||||
void CanvasItem::set_opacity(float p_opacity) {
|
||||
|
||||
opacity=p_opacity;
|
||||
VisualServer::get_singleton()->canvas_item_set_opacity(canvas_item,opacity);
|
||||
|
||||
}
|
||||
float CanvasItem::get_opacity() const {
|
||||
|
||||
return opacity;
|
||||
}
|
||||
|
||||
|
||||
void CanvasItem::set_as_toplevel(bool p_toplevel) {
|
||||
|
||||
if (toplevel==p_toplevel)
|
||||
return;
|
||||
|
||||
if (!is_inside_scene()) {
|
||||
toplevel=p_toplevel;
|
||||
return;
|
||||
}
|
||||
|
||||
_exit_canvas();
|
||||
toplevel=p_toplevel;
|
||||
_enter_canvas();
|
||||
}
|
||||
|
||||
bool CanvasItem::is_set_as_toplevel() const {
|
||||
|
||||
return toplevel;
|
||||
}
|
||||
|
||||
CanvasItem *CanvasItem::get_parent_item() const {
|
||||
|
||||
if (toplevel)
|
||||
return NULL;
|
||||
|
||||
Node *parent = get_parent();
|
||||
if (!parent)
|
||||
return NULL;
|
||||
|
||||
return parent->cast_to<CanvasItem>();
|
||||
}
|
||||
|
||||
|
||||
void CanvasItem::set_self_opacity(float p_self_opacity) {
|
||||
|
||||
self_opacity=p_self_opacity;
|
||||
VisualServer::get_singleton()->canvas_item_set_self_opacity(canvas_item,self_opacity);
|
||||
|
||||
}
|
||||
float CanvasItem::get_self_opacity() const {
|
||||
|
||||
return self_opacity;
|
||||
}
|
||||
|
||||
void CanvasItem::set_blend_mode(BlendMode p_blend_mode) {
|
||||
|
||||
ERR_FAIL_INDEX(p_blend_mode,4);
|
||||
blend_mode=p_blend_mode;
|
||||
VisualServer::get_singleton()->canvas_item_set_blend_mode(canvas_item,VS::MaterialBlendMode(blend_mode));
|
||||
|
||||
}
|
||||
|
||||
CanvasItem::BlendMode CanvasItem::get_blend_mode() const {
|
||||
|
||||
return blend_mode;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CanvasItem::item_rect_changed() {
|
||||
|
||||
update();
|
||||
emit_signal(SceneStringNames::get_singleton()->item_rect_changed);
|
||||
}
|
||||
|
||||
|
||||
void CanvasItem::draw_line(const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width) {
|
||||
|
||||
if (!drawing) {
|
||||
ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
VisualServer::get_singleton()->canvas_item_add_line(canvas_item,p_from,p_to,p_color,p_width);
|
||||
}
|
||||
|
||||
void CanvasItem::draw_rect(const Rect2& p_rect, const Color& p_color) {
|
||||
|
||||
if (!drawing) {
|
||||
ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
VisualServer::get_singleton()->canvas_item_add_rect(canvas_item,p_rect,p_color);
|
||||
|
||||
}
|
||||
|
||||
void CanvasItem::draw_circle(const Point2& p_pos, float p_radius, const Color& p_color) {
|
||||
|
||||
if (!drawing) {
|
||||
ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
VisualServer::get_singleton()->canvas_item_add_circle(canvas_item,p_pos,p_radius,p_color);
|
||||
|
||||
}
|
||||
|
||||
void CanvasItem::draw_texture(const Ref<Texture>& p_texture,const Point2& p_pos) {
|
||||
|
||||
if (!drawing) {
|
||||
ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
ERR_FAIL_COND(p_texture.is_null());
|
||||
|
||||
p_texture->draw(canvas_item,p_pos);
|
||||
}
|
||||
|
||||
void CanvasItem::draw_texture_rect(const Ref<Texture>& p_texture,const Rect2& p_rect, bool p_tile,const Color& p_modulate) {
|
||||
|
||||
if (!drawing) {
|
||||
ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
ERR_FAIL_COND(p_texture.is_null());
|
||||
p_texture->draw_rect(canvas_item,p_rect,p_tile,p_modulate);
|
||||
|
||||
}
|
||||
void CanvasItem::draw_texture_rect_region(const Ref<Texture>& p_texture,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate) {
|
||||
|
||||
if (!drawing) {
|
||||
ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
|
||||
ERR_FAIL();
|
||||
}
|
||||
ERR_FAIL_COND(p_texture.is_null());
|
||||
p_texture->draw_rect_region(canvas_item,p_rect,p_src_rect,p_modulate);
|
||||
}
|
||||
|
||||
void CanvasItem::draw_style_box(const Ref<StyleBox>& p_style_box,const Rect2& p_rect) {
|
||||
if (!drawing) {
|
||||
ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
ERR_FAIL_COND(p_style_box.is_null());
|
||||
|
||||
p_style_box->draw(canvas_item,p_rect);
|
||||
|
||||
}
|
||||
void CanvasItem::draw_primitive(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, Ref<Texture> p_texture,float p_width) {
|
||||
|
||||
if (!drawing) {
|
||||
ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
RID rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
|
||||
|
||||
VisualServer::get_singleton()->canvas_item_add_primitive(canvas_item,p_points,p_colors,p_uvs,rid,p_width);
|
||||
}
|
||||
void CanvasItem::draw_set_transform(const Point2& p_offset, float p_rot, const Size2& p_scale) {
|
||||
|
||||
if (!drawing) {
|
||||
ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
Matrix32 xform(p_rot,p_offset);
|
||||
xform.scale_basis(p_scale);
|
||||
VisualServer::get_singleton()->canvas_item_set_transform(canvas_item,xform);
|
||||
}
|
||||
|
||||
void CanvasItem::draw_polygon(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, Ref<Texture> p_texture) {
|
||||
|
||||
if (!drawing) {
|
||||
ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
RID rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
|
||||
|
||||
VisualServer::get_singleton()->canvas_item_add_polygon(canvas_item,p_points,p_colors,p_uvs,rid);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CanvasItem::draw_colored_polygon(const Vector<Point2>& p_points, const Color& p_color,const Vector<Point2>& p_uvs, Ref<Texture> p_texture) {
|
||||
|
||||
if (!drawing) {
|
||||
ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
Vector<Color> colors;
|
||||
colors.push_back(p_color);
|
||||
RID rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
|
||||
|
||||
VisualServer::get_singleton()->canvas_item_add_polygon(canvas_item,p_points,colors,p_uvs,rid);
|
||||
}
|
||||
|
||||
void CanvasItem::draw_string(const Ref<Font>& p_font,const Point2& p_pos, const String& p_text,const Color& p_modulate,int p_clip_w) {
|
||||
|
||||
if (!drawing) {
|
||||
ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
ERR_FAIL_COND(p_font.is_null());
|
||||
p_font->draw(canvas_item,p_pos,p_text,p_modulate,p_clip_w);
|
||||
|
||||
}
|
||||
|
||||
float CanvasItem::draw_char(const Ref<Font>& p_font,const Point2& p_pos, const String& p_char,const String& p_next,const Color& p_modulate) {
|
||||
|
||||
if (!drawing) {
|
||||
ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
|
||||
ERR_FAIL_V(0);
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V(p_char.length()!=1,0);
|
||||
ERR_FAIL_COND_V(p_font.is_null(),0);
|
||||
|
||||
return p_font->draw_char(canvas_item,p_pos,p_char[0],p_next.c_str()[0],p_modulate);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CanvasItem::_notify_transform(CanvasItem *p_node) {
|
||||
|
||||
if (p_node->xform_change.in_list() && p_node->global_invalid)
|
||||
return; //nothing to do
|
||||
|
||||
p_node->global_invalid=true;
|
||||
|
||||
if (!p_node->xform_change.in_list()) {
|
||||
if (!p_node->block_transform_notify) {
|
||||
if (p_node->is_inside_scene())
|
||||
get_scene()->xform_change_list.add(&p_node->xform_change);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for(List<CanvasItem*>::Element *E=p_node->children_items.front();E;E=E->next()) {
|
||||
|
||||
CanvasItem* ci=E->get();
|
||||
if (ci->toplevel)
|
||||
continue;
|
||||
_notify_transform(ci);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rect2 CanvasItem::get_viewport_rect() const {
|
||||
|
||||
ERR_FAIL_COND_V(!is_inside_scene(),Rect2());
|
||||
return viewport->get_visible_rect();
|
||||
}
|
||||
|
||||
RID CanvasItem::get_canvas() const {
|
||||
|
||||
ERR_FAIL_COND_V(!is_inside_scene(),RID());
|
||||
|
||||
if (canvas_layer)
|
||||
return canvas_layer->get_world_2d()->get_canvas();
|
||||
else
|
||||
return viewport->find_world_2d()->get_canvas();
|
||||
|
||||
|
||||
}
|
||||
|
||||
CanvasItem *CanvasItem::get_toplevel() const {
|
||||
|
||||
CanvasItem *ci=const_cast<CanvasItem*>(this);
|
||||
while(!ci->toplevel && ci->get_parent() && ci->get_parent()->cast_to<CanvasItem>()) {
|
||||
ci=ci->get_parent()->cast_to<CanvasItem>();
|
||||
}
|
||||
|
||||
return ci;
|
||||
}
|
||||
|
||||
Viewport *CanvasItem::get_viewport() const {
|
||||
|
||||
return viewport;
|
||||
}
|
||||
|
||||
|
||||
Ref<World2D> CanvasItem::get_world_2d() const {
|
||||
|
||||
ERR_FAIL_COND_V(!is_inside_scene(),Ref<World2D>());
|
||||
|
||||
CanvasItem *tl=get_toplevel();
|
||||
|
||||
if (tl->canvas_layer) {
|
||||
return tl->canvas_layer->get_world_2d();
|
||||
} else if (tl->viewport) {
|
||||
return tl->viewport->find_world_2d();
|
||||
} else {
|
||||
return Ref<World2D>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RID CanvasItem::get_viewport_rid() const {
|
||||
|
||||
ERR_FAIL_COND_V(!is_inside_scene(),RID());
|
||||
return viewport->get_viewport();
|
||||
}
|
||||
|
||||
void CanvasItem::set_block_transform_notify(bool p_enable) {
|
||||
block_transform_notify=p_enable;
|
||||
}
|
||||
|
||||
bool CanvasItem::is_block_transform_notify_enabled() const {
|
||||
|
||||
return block_transform_notify;
|
||||
}
|
||||
|
||||
void CanvasItem::set_on_top(bool p_on_top) {
|
||||
|
||||
if (on_top==p_on_top)
|
||||
return;
|
||||
on_top=p_on_top;
|
||||
VisualServer::get_singleton()->canvas_item_set_on_top(canvas_item,on_top);
|
||||
}
|
||||
|
||||
bool CanvasItem::is_on_top() const {
|
||||
|
||||
return on_top;
|
||||
}
|
||||
|
||||
|
||||
void CanvasItem::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_sort_children"),&CanvasItem::_sort_children);
|
||||
ObjectTypeDB::bind_method(_MD("_raise_self"),&CanvasItem::_raise_self);
|
||||
ObjectTypeDB::bind_method(_MD("_update_callback"),&CanvasItem::_update_callback);
|
||||
ObjectTypeDB::bind_method(_MD("_set_visible_"),&CanvasItem::_set_visible_);
|
||||
ObjectTypeDB::bind_method(_MD("_is_visible_"),&CanvasItem::_is_visible_);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("edit_set_state","state"),&CanvasItem::edit_set_state);
|
||||
ObjectTypeDB::bind_method(_MD("edit_get"),&CanvasItem::edit_get_state);
|
||||
ObjectTypeDB::bind_method(_MD("edit_set_rect","rect"),&CanvasItem::edit_set_rect);
|
||||
ObjectTypeDB::bind_method(_MD("edit_rotate","degrees"),&CanvasItem::edit_rotate);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("get_item_rect"),&CanvasItem::get_item_rect);
|
||||
//ObjectTypeDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform);
|
||||
ObjectTypeDB::bind_method(_MD("get_canvas_item"),&CanvasItem::get_canvas_item);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("is_visible"),&CanvasItem::is_visible);
|
||||
ObjectTypeDB::bind_method(_MD("is_hidden"),&CanvasItem::is_hidden);
|
||||
ObjectTypeDB::bind_method(_MD("show"),&CanvasItem::show);
|
||||
ObjectTypeDB::bind_method(_MD("hide"),&CanvasItem::hide);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("update"),&CanvasItem::update);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_as_toplevel","enable"),&CanvasItem::set_as_toplevel);
|
||||
ObjectTypeDB::bind_method(_MD("is_set_as_toplevel"),&CanvasItem::is_set_as_toplevel);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_blend_mode","blend_mode"),&CanvasItem::set_blend_mode);
|
||||
ObjectTypeDB::bind_method(_MD("get_blend_mode"),&CanvasItem::get_blend_mode);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_opacity","opacity"),&CanvasItem::set_opacity);
|
||||
ObjectTypeDB::bind_method(_MD("get_opacity"),&CanvasItem::get_opacity);
|
||||
ObjectTypeDB::bind_method(_MD("set_self_opacity","self_opacity"),&CanvasItem::set_self_opacity);
|
||||
ObjectTypeDB::bind_method(_MD("get_self_opacity"),&CanvasItem::get_self_opacity);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_on_top","on_top"),&CanvasItem::set_on_top);
|
||||
ObjectTypeDB::bind_method(_MD("is_on_top"),&CanvasItem::is_on_top);
|
||||
|
||||
//ObjectTypeDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("draw_line","from","to","color","width"),&CanvasItem::draw_line,DEFVAL(1.0));
|
||||
ObjectTypeDB::bind_method(_MD("draw_rect","rect","color"),&CanvasItem::draw_rect);
|
||||
ObjectTypeDB::bind_method(_MD("draw_circle","pos","radius","color"),&CanvasItem::draw_circle);
|
||||
ObjectTypeDB::bind_method(_MD("draw_texture","texture:Texture","pos"),&CanvasItem::draw_texture);
|
||||
ObjectTypeDB::bind_method(_MD("draw_texture_rect","texture:Texture","rect","tile","modulate"),&CanvasItem::draw_texture_rect,DEFVAL(false),DEFVAL(Color(1,1,1)));
|
||||
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_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)));
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("draw_set_transform","pos","rot","scale"),&CanvasItem::draw_set_transform);
|
||||
ObjectTypeDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform);
|
||||
ObjectTypeDB::bind_method(_MD("get_global_transform"),&CanvasItem::get_global_transform);
|
||||
ObjectTypeDB::bind_method(_MD("get_viewport_transform"),&CanvasItem::get_viewport_transform);
|
||||
ObjectTypeDB::bind_method(_MD("get_viewport_rect"),&CanvasItem::get_viewport_rect);
|
||||
ObjectTypeDB::bind_method(_MD("get_canvas"),&CanvasItem::get_canvas);
|
||||
ObjectTypeDB::bind_method(_MD("get_world_2d"),&CanvasItem::get_world_2d);
|
||||
ObjectTypeDB::bind_method(_MD("get_viewport"),&CanvasItem::get_viewport);
|
||||
|
||||
BIND_VMETHOD(MethodInfo("_draw"));
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/visible"), _SCS("_set_visible_"),_SCS("_is_visible_") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"visibility/opacity",PROPERTY_HINT_RANGE, "0,1,0.01"), _SCS("set_opacity"),_SCS("get_opacity") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"visibility/self_opacity",PROPERTY_HINT_RANGE, "0,1,0.01"), _SCS("set_self_opacity"),_SCS("get_self_opacity") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/on_top"), _SCS("set_on_top"),_SCS("is_on_top") );
|
||||
|
||||
ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/blend_mode",PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul"), _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"));
|
||||
|
||||
ADD_SIGNAL( MethodInfo("draw") );
|
||||
ADD_SIGNAL( MethodInfo("visibility_changed") );
|
||||
ADD_SIGNAL( MethodInfo("hide") );
|
||||
ADD_SIGNAL( MethodInfo("item_rect_changed") );
|
||||
|
||||
|
||||
|
||||
BIND_CONSTANT( BLEND_MODE_MIX );
|
||||
BIND_CONSTANT( BLEND_MODE_ADD );
|
||||
BIND_CONSTANT( BLEND_MODE_SUB );
|
||||
BIND_CONSTANT( BLEND_MODE_MUL );
|
||||
|
||||
|
||||
BIND_CONSTANT( NOTIFICATION_DRAW);
|
||||
BIND_CONSTANT( NOTIFICATION_VISIBILITY_CHANGED );
|
||||
BIND_CONSTANT( NOTIFICATION_ENTER_CANVAS );
|
||||
BIND_CONSTANT( NOTIFICATION_EXIT_CANVAS );
|
||||
BIND_CONSTANT( NOTIFICATION_TRANSFORM_CHANGED );
|
||||
|
||||
|
||||
}
|
||||
|
||||
Matrix32 CanvasItem::get_viewport_transform() const {
|
||||
|
||||
ERR_FAIL_COND_V(!is_inside_scene(),Matrix32());
|
||||
|
||||
if (canvas_layer) {
|
||||
|
||||
if (viewport) {
|
||||
return viewport->get_final_transform() * canvas_layer->get_transform();
|
||||
} else {
|
||||
return canvas_layer->get_transform();
|
||||
}
|
||||
|
||||
} else if (viewport) {
|
||||
return viewport->get_final_transform() * viewport->get_canvas_transform();
|
||||
}
|
||||
|
||||
return Matrix32();
|
||||
|
||||
}
|
||||
|
||||
|
||||
CanvasItem::CanvasItem() : xform_change(this) {
|
||||
|
||||
|
||||
canvas_item=VisualServer::get_singleton()->canvas_item_create();
|
||||
hidden=false;
|
||||
pending_update=false;
|
||||
opacity=1;
|
||||
self_opacity=1;
|
||||
toplevel=false;
|
||||
pending_children_sort=false;
|
||||
first_draw=false;
|
||||
blend_mode=BLEND_MODE_MIX;
|
||||
drawing=false;
|
||||
on_top=true;
|
||||
block_transform_notify=false;
|
||||
viewport=NULL;
|
||||
canvas_layer=NULL;
|
||||
global_invalid=true;
|
||||
|
||||
C=NULL;
|
||||
|
||||
}
|
||||
|
||||
CanvasItem::~CanvasItem() {
|
||||
|
||||
VisualServer::get_singleton()->free(canvas_item);
|
||||
}
|
||||
209
scene/2d/canvas_item.h
Normal file
209
scene/2d/canvas_item.h
Normal file
@ -0,0 +1,209 @@
|
||||
/*************************************************************************/
|
||||
/* canvas_item.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef CANVAS_ITEM_H
|
||||
#define CANVAS_ITEM_H
|
||||
|
||||
#include "scene/main/node.h"
|
||||
#include "scene/resources/texture.h"
|
||||
#include "scene/main/scene_main_loop.h"
|
||||
|
||||
class CanvasLayer;
|
||||
class Viewport;
|
||||
class Font;
|
||||
|
||||
class StyleBox;
|
||||
|
||||
class CanvasItem : public Node {
|
||||
|
||||
OBJ_TYPE( CanvasItem, Node );
|
||||
public:
|
||||
|
||||
enum BlendMode {
|
||||
|
||||
BLEND_MODE_MIX, //default
|
||||
BLEND_MODE_ADD,
|
||||
BLEND_MODE_SUB,
|
||||
BLEND_MODE_MUL
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
mutable SelfList<Node> xform_change;
|
||||
|
||||
RID canvas_item;
|
||||
String group;
|
||||
|
||||
Viewport *viewport;
|
||||
CanvasLayer *canvas_layer;
|
||||
|
||||
float opacity;
|
||||
float self_opacity;
|
||||
|
||||
List<CanvasItem*> children_items;
|
||||
List<CanvasItem*>::Element *C;
|
||||
|
||||
BlendMode blend_mode;
|
||||
|
||||
bool first_draw;
|
||||
bool hidden;
|
||||
bool pending_update;
|
||||
bool toplevel;
|
||||
bool pending_children_sort;
|
||||
bool drawing;
|
||||
bool block_transform_notify;
|
||||
bool on_top;
|
||||
|
||||
mutable Matrix32 global_transform;
|
||||
mutable bool global_invalid;
|
||||
|
||||
|
||||
void _raise_self();
|
||||
|
||||
void _propagate_visibility_changed(bool p_visible);
|
||||
|
||||
void _set_visible_(bool p_visible);
|
||||
bool _is_visible_() const;
|
||||
|
||||
void _update_callback();
|
||||
|
||||
void _enter_canvas();
|
||||
void _exit_canvas();
|
||||
|
||||
void _queue_sort_children();
|
||||
void _sort_children();
|
||||
|
||||
|
||||
|
||||
void _notify_transform(CanvasItem *p_node);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
||||
_FORCE_INLINE_ void _notify_transform() { if (!is_inside_scene()) return; _notify_transform(this); if (!block_transform_notify) notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); }
|
||||
|
||||
void item_rect_changed();
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
|
||||
enum {
|
||||
NOTIFICATION_TRANSFORM_CHANGED=SceneMainLoop::NOTIFICATION_TRANSFORM_CHANGED, //unique
|
||||
NOTIFICATION_DRAW=30,
|
||||
NOTIFICATION_VISIBILITY_CHANGED=31,
|
||||
NOTIFICATION_ENTER_CANVAS=32,
|
||||
NOTIFICATION_EXIT_CANVAS=33,
|
||||
NOTIFICATION_LOCAL_TRANSFORM_CHANGED=35,
|
||||
NOTIFICATION_WORLD_2D_CHANGED=36,
|
||||
|
||||
};
|
||||
|
||||
/* EDITOR */
|
||||
|
||||
virtual Variant edit_get_state() const;
|
||||
virtual void edit_set_state(const Variant& p_state);
|
||||
virtual void edit_set_rect(const Rect2& p_edit_rect);
|
||||
virtual void edit_rotate(float p_rot);
|
||||
virtual Size2 edit_get_minimum_size() const;
|
||||
|
||||
/* VISIBILITY */
|
||||
|
||||
bool is_visible() const;
|
||||
bool is_hidden() const;
|
||||
void show();
|
||||
void hide();
|
||||
|
||||
void update();
|
||||
|
||||
void set_blend_mode(BlendMode p_blend_mode);
|
||||
BlendMode get_blend_mode() const;
|
||||
|
||||
void set_opacity(float p_opacity);
|
||||
float get_opacity() const;
|
||||
|
||||
void set_self_opacity(float p_self_opacity);
|
||||
float get_self_opacity() const;
|
||||
|
||||
/* DRAWING API */
|
||||
|
||||
void draw_line(const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width=1.0);
|
||||
void draw_rect(const Rect2& p_rect, const Color& p_color);
|
||||
void draw_circle(const Point2& p_pos, float p_radius, const Color& p_color);
|
||||
void draw_texture(const Ref<Texture>& p_texture,const Point2& p_pos);
|
||||
void draw_texture_rect(const Ref<Texture>& p_texture, const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1));
|
||||
void draw_texture_rect_region(const Ref<Texture>& p_texture,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1));
|
||||
void draw_style_box(const Ref<StyleBox>& p_style_box,const Rect2& p_rect);
|
||||
void draw_primitive(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, Ref<Texture> p_texture=Ref<Texture>(),float p_width=1);
|
||||
void draw_polygon(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), Ref<Texture> p_texture=Ref<Texture>());
|
||||
void draw_colored_polygon(const Vector<Point2>& p_points, const Color& p_color,const Vector<Point2>& p_uvs=Vector<Point2>(), Ref<Texture> p_texture=Ref<Texture>());
|
||||
|
||||
void draw_string(const Ref<Font>& p_font, const Point2& p_pos, const String& p_text,const Color& p_modulate=Color(1,1,1),int p_clip_w=-1);
|
||||
float draw_char(const Ref<Font>& p_font,const Point2& p_pos, const String& p_char,const String& p_next="",const Color& p_modulate=Color(1,1,1));
|
||||
|
||||
void draw_set_transform(const Point2& p_offset, float p_rot, const Size2& p_scale);
|
||||
|
||||
/* RECT / TRANSFORM */
|
||||
|
||||
void set_as_toplevel(bool p_toplevel);
|
||||
bool is_set_as_toplevel() const;
|
||||
|
||||
void set_on_top(bool p_on_top);
|
||||
bool is_on_top() const;
|
||||
|
||||
CanvasItem *get_parent_item() const;
|
||||
|
||||
virtual Rect2 get_item_rect() const=0;
|
||||
virtual Matrix32 get_transform() const=0;
|
||||
|
||||
virtual Matrix32 get_global_transform() const;
|
||||
virtual Matrix32 get_global_transform_with_canvas() const;
|
||||
|
||||
CanvasItem *get_toplevel() const;
|
||||
_FORCE_INLINE_ RID get_canvas_item() const { return canvas_item; }
|
||||
|
||||
void set_block_transform_notify(bool p_enable);
|
||||
bool is_block_transform_notify_enabled() const;
|
||||
|
||||
Matrix32 get_viewport_transform() const;
|
||||
Rect2 get_viewport_rect() const;
|
||||
RID get_viewport_rid() const;
|
||||
RID get_canvas() const;
|
||||
Ref<World2D> get_world_2d() const;
|
||||
Viewport *get_viewport() const;
|
||||
|
||||
|
||||
CanvasItem();
|
||||
~CanvasItem();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST( CanvasItem::BlendMode );
|
||||
|
||||
#endif // CANVAS_ITEM_H
|
||||
282
scene/2d/collision_object_2d.cpp
Normal file
282
scene/2d/collision_object_2d.cpp
Normal file
@ -0,0 +1,282 @@
|
||||
/*************************************************************************/
|
||||
/* collision_object_2d.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "collision_object_2d.h"
|
||||
#include "servers/physics_2d_server.h"
|
||||
|
||||
void CollisionObject2D::_update_shapes_from_children() {
|
||||
|
||||
shapes.resize(0);
|
||||
for(int i=0;i<get_child_count();i++) {
|
||||
|
||||
Node* n = get_child(i);
|
||||
n->call("_add_to_collision_object",this);
|
||||
}
|
||||
|
||||
// _update_shapes();
|
||||
}
|
||||
|
||||
void CollisionObject2D::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_ENTER_SCENE: {
|
||||
|
||||
|
||||
RID space = get_world_2d()->get_space();
|
||||
if (area) {
|
||||
Physics2DServer::get_singleton()->area_set_space(rid,space);
|
||||
} else
|
||||
Physics2DServer::get_singleton()->body_set_space(rid,space);
|
||||
|
||||
//get space
|
||||
}
|
||||
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
|
||||
if (area)
|
||||
Physics2DServer::get_singleton()->area_set_transform(rid,get_global_transform());
|
||||
else
|
||||
Physics2DServer::get_singleton()->body_set_state(rid,Physics2DServer::BODY_STATE_TRANSFORM,get_global_transform());
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_SCENE: {
|
||||
|
||||
if (area) {
|
||||
Physics2DServer::get_singleton()->area_set_space(rid,RID());
|
||||
} else
|
||||
Physics2DServer::get_singleton()->body_set_space(rid,RID());
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void CollisionObject2D::_update_shapes() {
|
||||
|
||||
if (!rid.is_valid())
|
||||
return;
|
||||
|
||||
if (area)
|
||||
Physics2DServer::get_singleton()->area_clear_shapes(rid);
|
||||
else
|
||||
Physics2DServer::get_singleton()->body_clear_shapes(rid);
|
||||
|
||||
for(int i=0;i<shapes.size();i++) {
|
||||
|
||||
if (shapes[i].shape.is_null())
|
||||
continue;
|
||||
if (area)
|
||||
Physics2DServer::get_singleton()->area_add_shape(rid,shapes[i].shape->get_rid(),shapes[i].xform);
|
||||
else {
|
||||
Physics2DServer::get_singleton()->body_add_shape(rid,shapes[i].shape->get_rid(),shapes[i].xform);
|
||||
if (shapes[i].trigger)
|
||||
Physics2DServer::get_singleton()->body_set_shape_as_trigger(rid,i,shapes[i].trigger);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CollisionObject2D::_set(const StringName& p_name, const Variant& p_value) {
|
||||
String name=p_name;
|
||||
|
||||
if (name=="shape_count") {
|
||||
|
||||
shapes.resize(p_value);
|
||||
_update_shapes();
|
||||
_change_notify();
|
||||
|
||||
} else if (name.begins_with("shapes/")) {
|
||||
|
||||
int idx=name.get_slice("/",1).to_int();
|
||||
String what=name.get_slice("/",2);
|
||||
if (what=="shape")
|
||||
set_shape(idx,RefPtr(p_value));
|
||||
else if (what=="transform")
|
||||
set_shape_transform(idx,p_value);
|
||||
else if (what=="trigger")
|
||||
set_shape_as_trigger(idx,p_value);
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool CollisionObject2D::_get(const StringName& p_name,Variant &r_ret) const {
|
||||
|
||||
String name=p_name;
|
||||
|
||||
if (name=="shape_count") {
|
||||
r_ret= shapes.size();
|
||||
} else if (name.begins_with("shapes/")) {
|
||||
|
||||
int idx=name.get_slice("/",1).to_int();
|
||||
String what=name.get_slice("/",2);
|
||||
if (what=="shape")
|
||||
r_ret= get_shape(idx);
|
||||
else if (what=="transform")
|
||||
r_ret= get_shape_transform(idx);
|
||||
else if (what=="trigger")
|
||||
r_ret= is_shape_set_as_trigger(idx);
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CollisionObject2D::_get_property_list( List<PropertyInfo> *p_list) const {
|
||||
|
||||
p_list->push_back( PropertyInfo(Variant::INT,"shape_count",PROPERTY_HINT_RANGE,"0,256,1",PROPERTY_USAGE_NOEDITOR) );
|
||||
|
||||
for(int i=0;i<shapes.size();i++) {
|
||||
String path="shapes/"+itos(i)+"/";
|
||||
p_list->push_back( PropertyInfo(Variant::OBJECT,path+"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape2D",PROPERTY_USAGE_NOEDITOR) );
|
||||
p_list->push_back( PropertyInfo(Variant::TRANSFORM,path+"transform",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
|
||||
p_list->push_back( PropertyInfo(Variant::BOOL,path+"trigger",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
|
||||
}
|
||||
}
|
||||
|
||||
void CollisionObject2D::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("add_shape","shape:Shape2D","transform"),&CollisionObject2D::add_shape,DEFVAL(Matrix32()));
|
||||
ObjectTypeDB::bind_method(_MD("get_shape_count"),&CollisionObject2D::get_shape_count);
|
||||
ObjectTypeDB::bind_method(_MD("set_shape","shape_idx","shape:Shape"),&CollisionObject2D::set_shape);
|
||||
ObjectTypeDB::bind_method(_MD("set_shape_transform","shape_idx","transform"),&CollisionObject2D::set_shape_transform);
|
||||
ObjectTypeDB::bind_method(_MD("set_shape_as_trigger","shape_idx","enable"),&CollisionObject2D::set_shape_as_trigger);
|
||||
ObjectTypeDB::bind_method(_MD("get_shape:Shape2D","shape_idx"),&CollisionObject2D::get_shape);
|
||||
ObjectTypeDB::bind_method(_MD("get_shape_transform","shape_idx"),&CollisionObject2D::get_shape_transform);
|
||||
ObjectTypeDB::bind_method(_MD("is_shape_set_as_trigger","shape_idx"),&CollisionObject2D::is_shape_set_as_trigger);
|
||||
ObjectTypeDB::bind_method(_MD("remove_shape","shape_idx"),&CollisionObject2D::remove_shape);
|
||||
ObjectTypeDB::bind_method(_MD("clear_shapes"),&CollisionObject2D::clear_shapes);
|
||||
ObjectTypeDB::bind_method(_MD("get_rid"),&CollisionObject2D::get_rid);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CollisionObject2D::add_shape(const Ref<Shape2D>& p_shape, const Matrix32& p_transform) {
|
||||
|
||||
ShapeData sdata;
|
||||
sdata.shape=p_shape;
|
||||
sdata.xform=p_transform;
|
||||
sdata.trigger=false;
|
||||
shapes.push_back(sdata);
|
||||
_update_shapes();
|
||||
|
||||
}
|
||||
int CollisionObject2D::get_shape_count() const {
|
||||
|
||||
return shapes.size();
|
||||
|
||||
}
|
||||
void CollisionObject2D::set_shape(int p_shape_idx, const Ref<Shape2D>& p_shape) {
|
||||
|
||||
ERR_FAIL_INDEX(p_shape_idx,shapes.size());
|
||||
shapes[p_shape_idx].shape=p_shape;
|
||||
_update_shapes();
|
||||
}
|
||||
|
||||
void CollisionObject2D::set_shape_transform(int p_shape_idx, const Matrix32& p_transform) {
|
||||
|
||||
ERR_FAIL_INDEX(p_shape_idx,shapes.size());
|
||||
shapes[p_shape_idx].xform=p_transform;
|
||||
|
||||
_update_shapes();
|
||||
}
|
||||
|
||||
Ref<Shape2D> CollisionObject2D::get_shape(int p_shape_idx) const {
|
||||
|
||||
ERR_FAIL_INDEX_V(p_shape_idx,shapes.size(),Ref<Shape2D>());
|
||||
return shapes[p_shape_idx].shape;
|
||||
|
||||
}
|
||||
Matrix32 CollisionObject2D::get_shape_transform(int p_shape_idx) const {
|
||||
|
||||
ERR_FAIL_INDEX_V(p_shape_idx,shapes.size(),Matrix32());
|
||||
return shapes[p_shape_idx].xform;
|
||||
|
||||
}
|
||||
void CollisionObject2D::remove_shape(int p_shape_idx) {
|
||||
|
||||
ERR_FAIL_INDEX(p_shape_idx,shapes.size());
|
||||
shapes.remove(p_shape_idx);
|
||||
|
||||
_update_shapes();
|
||||
}
|
||||
|
||||
void CollisionObject2D::set_shape_as_trigger(int p_shape_idx, bool p_trigger) {
|
||||
|
||||
ERR_FAIL_INDEX(p_shape_idx,shapes.size());
|
||||
shapes[p_shape_idx].trigger=p_trigger;
|
||||
if (!area && rid.is_valid()) {
|
||||
|
||||
Physics2DServer::get_singleton()->body_set_shape_as_trigger(rid,p_shape_idx,p_trigger);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool CollisionObject2D::is_shape_set_as_trigger(int p_shape_idx) const {
|
||||
|
||||
ERR_FAIL_INDEX_V(p_shape_idx,shapes.size(),false);
|
||||
return shapes[p_shape_idx].trigger;
|
||||
}
|
||||
|
||||
void CollisionObject2D::clear_shapes() {
|
||||
|
||||
shapes.clear();
|
||||
|
||||
_update_shapes();
|
||||
}
|
||||
|
||||
|
||||
CollisionObject2D::CollisionObject2D(RID p_rid, bool p_area) {
|
||||
|
||||
rid=p_rid;
|
||||
area=p_area;
|
||||
if (p_area) {
|
||||
Physics2DServer::get_singleton()->area_attach_object_instance_ID(rid,get_instance_ID());
|
||||
} else {
|
||||
Physics2DServer::get_singleton()->body_attach_object_instance_ID(rid,get_instance_ID());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
CollisionObject2D::CollisionObject2D() {
|
||||
|
||||
|
||||
//owner=
|
||||
|
||||
|
||||
}
|
||||
|
||||
CollisionObject2D::~CollisionObject2D() {
|
||||
|
||||
Physics2DServer::get_singleton()->free(rid);
|
||||
}
|
||||
89
scene/2d/collision_object_2d.h
Normal file
89
scene/2d/collision_object_2d.h
Normal file
@ -0,0 +1,89 @@
|
||||
/*************************************************************************/
|
||||
/* collision_object_2d.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef COLLISION_OBJECT_2D_H
|
||||
#define COLLISION_OBJECT_2D_H
|
||||
|
||||
#include "scene/2d/node_2d.h"
|
||||
#include "scene/resources/shape_2d.h"
|
||||
|
||||
class CollisionObject2D : public Node2D {
|
||||
|
||||
OBJ_TYPE( CollisionObject2D, Node2D );
|
||||
|
||||
bool area;
|
||||
RID rid;
|
||||
|
||||
struct ShapeData {
|
||||
Matrix32 xform;
|
||||
Ref<Shape2D> shape;
|
||||
bool trigger;
|
||||
|
||||
ShapeData() {
|
||||
trigger=false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Vector<ShapeData> shapes;
|
||||
|
||||
void _update_shapes();
|
||||
|
||||
friend class CollisionShape2D;
|
||||
friend class CollisionPolygon2D;
|
||||
void _update_shapes_from_children();
|
||||
protected:
|
||||
|
||||
CollisionObject2D(RID p_rid, bool p_area);
|
||||
|
||||
void _notification(int p_what);
|
||||
bool _set(const StringName& p_name, const Variant& p_value);
|
||||
bool _get(const StringName& p_name,Variant &r_ret) const;
|
||||
void _get_property_list( List<PropertyInfo> *p_list) const;
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
|
||||
void add_shape(const Ref<Shape2D>& p_shape, const Matrix32& p_transform=Matrix32());
|
||||
int get_shape_count() const;
|
||||
void set_shape(int p_shape_idx, const Ref<Shape2D>& p_shape);
|
||||
void set_shape_transform(int p_shape_idx, const Matrix32& p_transform);
|
||||
Ref<Shape2D> get_shape(int p_shape_idx) const;
|
||||
Matrix32 get_shape_transform(int p_shape_idx) const;
|
||||
void set_shape_as_trigger(int p_shape_idx, bool p_trigger);
|
||||
bool is_shape_set_as_trigger(int p_shape_idx) const;
|
||||
void remove_shape(int p_shape_idx);
|
||||
void clear_shapes();
|
||||
|
||||
_FORCE_INLINE_ RID get_rid() const { return rid; }
|
||||
|
||||
CollisionObject2D();
|
||||
~CollisionObject2D();
|
||||
};
|
||||
|
||||
#endif // COLLISION_OBJECT_2D_H
|
||||
187
scene/2d/collision_polygon_2d.cpp
Normal file
187
scene/2d/collision_polygon_2d.cpp
Normal file
@ -0,0 +1,187 @@
|
||||
/*************************************************************************/
|
||||
/* collision_polygon_2d.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "collision_polygon_2d.h"
|
||||
#include "collision_object_2d.h"
|
||||
#include "scene/resources/concave_polygon_shape_2d.h"
|
||||
#include "scene/resources/convex_polygon_shape_2d.h"
|
||||
|
||||
void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) {
|
||||
|
||||
CollisionObject2D *co = p_obj->cast_to<CollisionObject2D>();
|
||||
ERR_FAIL_COND(!co);
|
||||
|
||||
if (polygon.size()==0)
|
||||
return;
|
||||
|
||||
bool solids=build_mode==BUILD_SOLIDS;
|
||||
|
||||
|
||||
if (solids) {
|
||||
|
||||
//here comes the sun, lalalala
|
||||
//decompose concave into multiple convex polygons and add them
|
||||
Vector< Vector<Vector2> > decomp = Geometry::decompose_polygon(polygon);
|
||||
for(int i=0;i<decomp.size();i++) {
|
||||
Ref<ConvexPolygonShape2D> convex = memnew( ConvexPolygonShape2D );
|
||||
convex->set_points(decomp[i]);
|
||||
co->add_shape(convex,get_transform());
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
Ref<ConcavePolygonShape2D> concave = memnew( ConcavePolygonShape2D );
|
||||
|
||||
DVector<Vector2> segments;
|
||||
segments.resize(polygon.size()*2);
|
||||
DVector<Vector2>::Write w=segments.write();
|
||||
|
||||
for(int i=0;i<polygon.size();i++) {
|
||||
w[(i<<1)+0]=polygon[i];
|
||||
w[(i<<1)+1]=polygon[(i+1)%polygon.size()];
|
||||
}
|
||||
|
||||
w=DVector<Vector2>::Write();
|
||||
concave->set_segments(segments);
|
||||
|
||||
co->add_shape(concave,get_transform());
|
||||
|
||||
}
|
||||
|
||||
|
||||
//co->add_shape(shape,get_transform());
|
||||
}
|
||||
|
||||
void CollisionPolygon2D::_update_parent() {
|
||||
|
||||
Node *parent = get_parent();
|
||||
if (!parent)
|
||||
return;
|
||||
CollisionObject2D *co = parent->cast_to<CollisionObject2D>();
|
||||
if (!co)
|
||||
return;
|
||||
co->_update_shapes_from_children();
|
||||
}
|
||||
|
||||
void CollisionPolygon2D::_notification(int p_what) {
|
||||
|
||||
|
||||
switch(p_what) {
|
||||
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
|
||||
|
||||
if (!is_inside_scene())
|
||||
break;
|
||||
_update_parent();
|
||||
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_DRAW: {
|
||||
for(int i=0;i<polygon.size();i++) {
|
||||
|
||||
Vector2 p = polygon[i];
|
||||
Vector2 n = polygon[(i+1)%polygon.size()];
|
||||
draw_line(p,n,Color(0,0.6,0.7,0.5),3);
|
||||
}
|
||||
|
||||
Vector< Vector<Vector2> > decomp = Geometry::decompose_polygon(polygon);
|
||||
#define DEBUG_DECOMPOSE
|
||||
#ifdef DEBUG_DECOMPOSE
|
||||
Color c(0.4,0.9,0.1);
|
||||
for(int i=0;i<decomp.size();i++) {
|
||||
|
||||
c.set_hsv( Math::fmod(c.get_h() + 0.738,1),c.get_s(),c.get_v(),0.5);
|
||||
draw_colored_polygon(decomp[i],c);
|
||||
}
|
||||
#endif
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void CollisionPolygon2D::set_polygon(const Vector<Point2>& p_polygon) {
|
||||
|
||||
polygon=p_polygon;
|
||||
|
||||
for(int i=0;i<polygon.size();i++) {
|
||||
if (i==0)
|
||||
aabb=Rect2(polygon[i],Size2());
|
||||
else
|
||||
aabb.expand_to(polygon[i]);
|
||||
}
|
||||
if (aabb==Rect2()) {
|
||||
|
||||
aabb=Rect2(-10,-10,20,20);
|
||||
} else {
|
||||
aabb.pos-=aabb.size*0.3;
|
||||
aabb.size+=aabb.size*0.6;
|
||||
}
|
||||
_update_parent();
|
||||
update();
|
||||
}
|
||||
|
||||
Vector<Point2> CollisionPolygon2D::get_polygon() const {
|
||||
|
||||
return polygon;
|
||||
}
|
||||
|
||||
void CollisionPolygon2D::set_build_mode(BuildMode p_mode) {
|
||||
|
||||
ERR_FAIL_INDEX(p_mode,2);
|
||||
build_mode=p_mode;
|
||||
}
|
||||
|
||||
CollisionPolygon2D::BuildMode CollisionPolygon2D::get_build_mode() const{
|
||||
|
||||
return build_mode;
|
||||
}
|
||||
|
||||
Rect2 CollisionPolygon2D::get_item_rect() const {
|
||||
|
||||
return aabb;
|
||||
}
|
||||
|
||||
void CollisionPolygon2D::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_add_to_collision_object"),&CollisionPolygon2D::_add_to_collision_object);
|
||||
ObjectTypeDB::bind_method(_MD("set_polygon","polygon"),&CollisionPolygon2D::set_polygon);
|
||||
ObjectTypeDB::bind_method(_MD("get_polygon"),&CollisionPolygon2D::get_polygon);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_build_mode"),&CollisionPolygon2D::set_build_mode);
|
||||
ObjectTypeDB::bind_method(_MD("get_build_mode"),&CollisionPolygon2D::get_build_mode);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"build_mode",PROPERTY_HINT_ENUM,"Automatic,Segments,Solids"),_SCS("set_build_mode"),_SCS("get_build_mode"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon"));
|
||||
}
|
||||
|
||||
CollisionPolygon2D::CollisionPolygon2D() {
|
||||
|
||||
aabb=Rect2(-10,-10,20,20);
|
||||
build_mode=BUILD_SOLIDS;
|
||||
|
||||
|
||||
}
|
||||
75
scene/2d/collision_polygon_2d.h
Normal file
75
scene/2d/collision_polygon_2d.h
Normal file
@ -0,0 +1,75 @@
|
||||
/*************************************************************************/
|
||||
/* collision_polygon_2d.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef COLLISION_POLYGON_2D_H
|
||||
#define COLLISION_POLYGON_2D_H
|
||||
|
||||
#include "scene/2d/node_2d.h"
|
||||
#include "scene/resources/shape_2d.h"
|
||||
|
||||
|
||||
|
||||
class CollisionPolygon2D : public Node2D {
|
||||
|
||||
OBJ_TYPE(CollisionPolygon2D,Node2D);
|
||||
public:
|
||||
|
||||
enum BuildMode {
|
||||
BUILD_SOLIDS,
|
||||
BUILD_SEGMENTS,
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
Rect2 aabb;
|
||||
BuildMode build_mode;
|
||||
Vector<Point2> polygon;
|
||||
|
||||
void _add_to_collision_object(Object *p_obj);
|
||||
void _update_parent();
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_build_mode(BuildMode p_mode);
|
||||
BuildMode get_build_mode() const;
|
||||
|
||||
void set_polygon(const Vector<Point2>& p_polygon);
|
||||
Vector<Point2> get_polygon() const;
|
||||
|
||||
virtual Rect2 get_item_rect() const;
|
||||
CollisionPolygon2D();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST( CollisionPolygon2D::BuildMode );
|
||||
|
||||
#endif // COLLISION_POLYGON_2D_H
|
||||
248
scene/2d/collision_shape_2d.cpp
Normal file
248
scene/2d/collision_shape_2d.cpp
Normal file
@ -0,0 +1,248 @@
|
||||
/*************************************************************************/
|
||||
/* collision_shape_2d.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "collision_shape_2d.h"
|
||||
#include "collision_object_2d.h"
|
||||
#include "scene/resources/segment_shape_2d.h"
|
||||
#include "scene/resources/shape_line_2d.h"
|
||||
#include "scene/resources/circle_shape_2d.h"
|
||||
#include "scene/resources/rectangle_shape_2d.h"
|
||||
#include "scene/resources/capsule_shape_2d.h"
|
||||
#include "scene/resources/convex_polygon_shape_2d.h"
|
||||
#include "scene/resources/concave_polygon_shape_2d.h"
|
||||
|
||||
|
||||
void CollisionShape2D::_add_to_collision_object(Object *p_obj) {
|
||||
|
||||
CollisionObject2D *co = p_obj->cast_to<CollisionObject2D>();
|
||||
ERR_FAIL_COND(!co);
|
||||
co->add_shape(shape,get_transform());
|
||||
if (trigger)
|
||||
co->set_shape_as_trigger(co->get_shape_count()-1,true);
|
||||
|
||||
}
|
||||
|
||||
void CollisionShape2D::_shape_changed() {
|
||||
|
||||
update();
|
||||
_update_parent();
|
||||
}
|
||||
|
||||
void CollisionShape2D::_update_parent() {
|
||||
|
||||
|
||||
Node *parent = get_parent();
|
||||
if (!parent)
|
||||
return;
|
||||
CollisionObject2D *co = parent->cast_to<CollisionObject2D>();
|
||||
if (!co)
|
||||
return;
|
||||
co->_update_shapes_from_children();
|
||||
}
|
||||
|
||||
void CollisionShape2D::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
|
||||
|
||||
if (!is_inside_scene())
|
||||
break;
|
||||
_update_parent();
|
||||
|
||||
} break;
|
||||
/*
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
|
||||
if (!is_inside_scene())
|
||||
break;
|
||||
_update_parent();
|
||||
|
||||
} break;*/
|
||||
case NOTIFICATION_DRAW: {
|
||||
|
||||
rect=Rect2();
|
||||
|
||||
Color draw_col=Color(0,0.6,0.7,0.5);
|
||||
|
||||
if (shape->cast_to<LineShape2D>()) {
|
||||
|
||||
LineShape2D *l = shape->cast_to<LineShape2D>();
|
||||
Vector2 point = l->get_d() * l->get_normal();
|
||||
|
||||
Vector2 l1[2]={point-l->get_normal().tangent()*100,point+l->get_normal().tangent()*100};
|
||||
draw_line(l1[0],l1[1],draw_col,3);
|
||||
Vector2 l2[2]={point,point+l->get_normal()*30};
|
||||
draw_line(l2[0],l2[1],draw_col,3);
|
||||
rect.pos=l1[0];
|
||||
rect.expand_to(l1[1]);
|
||||
rect.expand_to(l2[0]);
|
||||
rect.expand_to(l2[1]);
|
||||
|
||||
} else if (shape->cast_to<SegmentShape2D>()) {
|
||||
|
||||
SegmentShape2D *s = shape->cast_to<SegmentShape2D>();
|
||||
draw_line(s->get_a(),s->get_b(),draw_col,3);
|
||||
rect.pos=s->get_a();
|
||||
rect.expand_to(s->get_b());
|
||||
|
||||
} else if (shape->cast_to<RayShape2D>()) {
|
||||
|
||||
RayShape2D *s = shape->cast_to<RayShape2D>();
|
||||
|
||||
Vector2 tip = Vector2(0,s->get_length());
|
||||
draw_line(Vector2(),tip,draw_col,3);
|
||||
Vector<Vector2> pts;
|
||||
float tsize=4;
|
||||
pts.push_back(tip+Vector2(0,tsize));
|
||||
pts.push_back(tip+Vector2(0.707*tsize,0));
|
||||
pts.push_back(tip+Vector2(-0.707*tsize,0));
|
||||
Vector<Color> cols;
|
||||
for(int i=0;i<3;i++)
|
||||
cols.push_back(draw_col);
|
||||
|
||||
draw_primitive(pts,cols,Vector<Vector2>()); //small arrow
|
||||
|
||||
rect.pos=Vector2();
|
||||
rect.expand_to(tip);
|
||||
rect=rect.grow(0.707*tsize);
|
||||
|
||||
} else if (shape->cast_to<CircleShape2D>()) {
|
||||
|
||||
CircleShape2D *s = shape->cast_to<CircleShape2D>();
|
||||
Vector<Vector2> points;
|
||||
for(int i=0;i<24;i++) {
|
||||
|
||||
points.push_back(Vector2(Math::cos(i*Math_PI*2/24.0),Math::sin(i*Math_PI*2/24.0))*s->get_radius());
|
||||
}
|
||||
|
||||
draw_colored_polygon(points,draw_col);
|
||||
rect.pos=-Point2(s->get_radius(),s->get_radius());
|
||||
rect.size=Point2(s->get_radius(),s->get_radius())*2.0;
|
||||
|
||||
} else if (shape->cast_to<RectangleShape2D>()) {
|
||||
|
||||
RectangleShape2D *s = shape->cast_to<RectangleShape2D>();
|
||||
Vector2 he = s->get_extents();
|
||||
rect=Rect2(-he,he*2.0);
|
||||
draw_rect(rect,draw_col);;
|
||||
|
||||
} else if (shape->cast_to<CapsuleShape2D>()) {
|
||||
|
||||
CapsuleShape2D *s = shape->cast_to<CapsuleShape2D>();
|
||||
|
||||
Vector<Vector2> points;
|
||||
for(int i=0;i<24;i++) {
|
||||
Vector2 ofs = Vector2(0,(i>6 && i<=18) ? -s->get_height()*0.5 : s->get_height()*0.5);
|
||||
|
||||
points.push_back(Vector2(Math::sin(i*Math_PI*2/24.0),Math::cos(i*Math_PI*2/24.0))*s->get_radius() + ofs);
|
||||
if (i==6 || i==18)
|
||||
points.push_back(Vector2(Math::sin(i*Math_PI*2/24.0),Math::cos(i*Math_PI*2/24.0))*s->get_radius() - ofs);
|
||||
}
|
||||
|
||||
draw_colored_polygon(points,draw_col);
|
||||
Vector2 he=Point2(s->get_radius(),s->get_radius()+s->get_height()*0.5);
|
||||
rect.pos=-he;
|
||||
rect.size=he*2.0;
|
||||
|
||||
} else if (shape->cast_to<ConvexPolygonShape2D>()) {
|
||||
|
||||
ConvexPolygonShape2D *s = shape->cast_to<ConvexPolygonShape2D>();
|
||||
|
||||
Vector<Vector2> points = s->get_points();
|
||||
for(int i=0;i<points.size();i++) {
|
||||
if (i==0)
|
||||
rect.pos=points[i];
|
||||
else
|
||||
rect.expand_to(points[i]);
|
||||
}
|
||||
|
||||
draw_colored_polygon(points,draw_col);
|
||||
|
||||
}
|
||||
|
||||
rect=rect.grow(3);
|
||||
|
||||
} break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CollisionShape2D::set_shape(const Ref<Shape2D>& p_shape) {
|
||||
|
||||
if (shape.is_valid())
|
||||
shape->disconnect("changed",this,"_shape_changed");
|
||||
shape=p_shape;
|
||||
update();
|
||||
_update_parent();
|
||||
if (shape.is_valid())
|
||||
shape->connect("changed",this,"_shape_changed");
|
||||
|
||||
}
|
||||
|
||||
Ref<Shape2D> CollisionShape2D::get_shape() const {
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
Rect2 CollisionShape2D::get_item_rect() const {
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
void CollisionShape2D::set_trigger(bool p_trigger) {
|
||||
|
||||
trigger=p_trigger;
|
||||
_update_parent();
|
||||
}
|
||||
|
||||
bool CollisionShape2D::is_trigger() const{
|
||||
|
||||
return trigger;
|
||||
}
|
||||
|
||||
void CollisionShape2D::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_shape","shape"),&CollisionShape2D::set_shape);
|
||||
ObjectTypeDB::bind_method(_MD("get_shape"),&CollisionShape2D::get_shape);
|
||||
ObjectTypeDB::bind_method(_MD("_shape_changed"),&CollisionShape2D::_shape_changed);
|
||||
ObjectTypeDB::bind_method(_MD("_add_to_collision_object"),&CollisionShape2D::_add_to_collision_object);
|
||||
ObjectTypeDB::bind_method(_MD("set_trigger","enable"),&CollisionShape2D::set_trigger);
|
||||
ObjectTypeDB::bind_method(_MD("is_trigger"),&CollisionShape2D::is_trigger);
|
||||
|
||||
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape2D"),_SCS("set_shape"),_SCS("get_shape"));
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"trigger"),_SCS("set_trigger"),_SCS("is_trigger"));
|
||||
}
|
||||
|
||||
CollisionShape2D::CollisionShape2D() {
|
||||
|
||||
rect=Rect2(-Point2(10,10),Point2(20,20));
|
||||
|
||||
trigger=false;
|
||||
}
|
||||
61
scene/2d/collision_shape_2d.h
Normal file
61
scene/2d/collision_shape_2d.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*************************************************************************/
|
||||
/* collision_shape_2d.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef COLLISION_SHAPE_2D_H
|
||||
#define COLLISION_SHAPE_2D_H
|
||||
|
||||
#include "scene/2d/node_2d.h"
|
||||
#include "scene/resources/shape_2d.h"
|
||||
|
||||
class CollisionShape2D : public Node2D {
|
||||
|
||||
OBJ_TYPE(CollisionShape2D,Node2D);
|
||||
Ref<Shape2D> shape;
|
||||
Rect2 rect;
|
||||
bool trigger;
|
||||
|
||||
void _shape_changed();
|
||||
protected:
|
||||
|
||||
void _update_parent();
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
void _add_to_collision_object(Object *p_obj);
|
||||
public:
|
||||
|
||||
void set_shape(const Ref<Shape2D>& p_shape);
|
||||
Ref<Shape2D> get_shape() const;
|
||||
virtual Rect2 get_item_rect() const;
|
||||
void set_trigger(bool p_trigger);
|
||||
bool is_trigger() const;
|
||||
|
||||
CollisionShape2D();
|
||||
};
|
||||
|
||||
#endif // COLLISION_SHAPE_2D_H
|
||||
412
scene/2d/joints_2d.cpp
Normal file
412
scene/2d/joints_2d.cpp
Normal file
@ -0,0 +1,412 @@
|
||||
/*************************************************************************/
|
||||
/* joints_2d.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "joints_2d.h"
|
||||
#include "servers/physics_2d_server.h"
|
||||
#include "physics_body_2d.h"
|
||||
|
||||
void Joint2D::_update_joint() {
|
||||
|
||||
if (!is_inside_scene())
|
||||
return;
|
||||
|
||||
if (joint.is_valid()) {
|
||||
Physics2DServer::get_singleton()->free(joint);
|
||||
}
|
||||
|
||||
joint=RID();
|
||||
|
||||
|
||||
joint = _configure_joint();
|
||||
Physics2DServer::get_singleton()->get_singleton()->joint_set_param(joint,Physics2DServer::JOINT_PARAM_BIAS,bias);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Joint2D::set_node_a(const NodePath& p_node_a) {
|
||||
|
||||
|
||||
if (a==p_node_a)
|
||||
return;
|
||||
|
||||
a=p_node_a;
|
||||
_update_joint();
|
||||
}
|
||||
|
||||
NodePath Joint2D::get_node_a() const{
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
void Joint2D::set_node_b(const NodePath& p_node_b){
|
||||
|
||||
if (b==p_node_b)
|
||||
return;
|
||||
b=p_node_b;
|
||||
_update_joint();
|
||||
|
||||
}
|
||||
NodePath Joint2D::get_node_b() const{
|
||||
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
void Joint2D::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_READY: {
|
||||
_update_joint();
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_SCENE: {
|
||||
if (joint.is_valid()) {
|
||||
|
||||
Physics2DServer::get_singleton()->free(joint);
|
||||
joint=RID();
|
||||
}
|
||||
} break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Joint2D::set_bias(real_t p_bias) {
|
||||
|
||||
bias=p_bias;
|
||||
if (joint.is_valid())
|
||||
Physics2DServer::get_singleton()->get_singleton()->joint_set_param(joint,Physics2DServer::JOINT_PARAM_BIAS,bias);
|
||||
}
|
||||
|
||||
real_t Joint2D::get_bias() const{
|
||||
|
||||
|
||||
return bias;
|
||||
}
|
||||
|
||||
|
||||
void Joint2D::_bind_methods() {
|
||||
|
||||
|
||||
ObjectTypeDB::bind_method( _MD("set_node_a","node"), &Joint2D::set_node_a );
|
||||
ObjectTypeDB::bind_method( _MD("get_node_a"), &Joint2D::get_node_a );
|
||||
|
||||
ObjectTypeDB::bind_method( _MD("set_node_b","node"), &Joint2D::set_node_b );
|
||||
ObjectTypeDB::bind_method( _MD("get_node_b"), &Joint2D::get_node_b );
|
||||
|
||||
ObjectTypeDB::bind_method( _MD("set_bias","bias"), &Joint2D::set_bias );
|
||||
ObjectTypeDB::bind_method( _MD("get_bias"), &Joint2D::get_bias );
|
||||
|
||||
ADD_PROPERTY( PropertyInfo( Variant::NODE_PATH, "node_a"), _SCS("set_node_a"),_SCS("get_node_a") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::NODE_PATH, "node_b"), _SCS("set_node_b"),_SCS("get_node_b") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "bias/bias",PROPERTY_HINT_RANGE,"0,0.9,0.01"), _SCS("set_bias"),_SCS("get_bias") );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Joint2D::Joint2D() {
|
||||
|
||||
bias=0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void PinJoint2D::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
case NOTIFICATION_DRAW: {
|
||||
if (is_inside_scene() && get_scene()->is_editor_hint()) {
|
||||
|
||||
draw_line(Point2(-10,0),Point2(+10,0),Color(0.7,0.6,0.0,0.5),3);
|
||||
draw_line(Point2(0,-10),Point2(0,+10),Color(0.7,0.6,0.0,0.5),3);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RID PinJoint2D::_configure_joint() {
|
||||
|
||||
Node *node_a = has_node( get_node_a() ) ? get_node( get_node_a() ) : (Node*)NULL;
|
||||
Node *node_b = has_node( get_node_b() ) ? get_node( get_node_b() ) : (Node*)NULL;
|
||||
|
||||
if (!node_a && !node_b)
|
||||
return RID();
|
||||
|
||||
PhysicsBody2D *body_a=node_a ? node_a->cast_to<PhysicsBody2D>() : (PhysicsBody2D*)NULL;
|
||||
PhysicsBody2D *body_b=node_b ? node_b->cast_to<PhysicsBody2D>() : (PhysicsBody2D*)NULL;
|
||||
|
||||
if (!body_a && !body_b)
|
||||
return RID();
|
||||
|
||||
if (!body_a) {
|
||||
SWAP(body_a,body_b);
|
||||
} else if (body_b) {
|
||||
//add a collision exception between both
|
||||
Physics2DServer::get_singleton()->body_add_collision_exception(body_a->get_rid(),body_b->get_rid());
|
||||
}
|
||||
|
||||
return Physics2DServer::get_singleton()->pin_joint_create(get_global_transform().get_origin(),body_a->get_rid(),body_b?body_b->get_rid():RID());
|
||||
|
||||
}
|
||||
|
||||
|
||||
PinJoint2D::PinJoint2D() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void GrooveJoint2D::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
case NOTIFICATION_DRAW: {
|
||||
if (is_inside_scene() && get_scene()->is_editor_hint()) {
|
||||
|
||||
draw_line(Point2(-10,0),Point2(+10,0),Color(0.7,0.6,0.0,0.5),3);
|
||||
draw_line(Point2(-10,length),Point2(+10,length),Color(0.7,0.6,0.0,0.5),3);
|
||||
draw_line(Point2(0,0),Point2(0,length),Color(0.7,0.6,0.0,0.5),3);
|
||||
draw_line(Point2(-10,initial_offset),Point2(+10,initial_offset),Color(0.8,0.8,0.9,0.5),5);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
RID GrooveJoint2D::_configure_joint(){
|
||||
|
||||
|
||||
Node *node_a = has_node( get_node_a() ) ? get_node( get_node_a() ) : (Node*)NULL;
|
||||
Node *node_b = has_node( get_node_b() ) ? get_node( get_node_b() ) : (Node*)NULL;
|
||||
|
||||
if (!node_a || !node_b)
|
||||
return RID();
|
||||
|
||||
PhysicsBody2D *body_a=node_a->cast_to<PhysicsBody2D>();
|
||||
PhysicsBody2D *body_b=node_b->cast_to<PhysicsBody2D>();
|
||||
|
||||
if (!body_a || !body_b)
|
||||
return RID();
|
||||
|
||||
Physics2DServer::get_singleton()->body_add_collision_exception(body_a->get_rid(),body_b->get_rid());
|
||||
|
||||
Matrix32 gt = get_global_transform();
|
||||
Vector2 groove_A1 = gt.get_origin();
|
||||
Vector2 groove_A2 = gt.xform( Vector2(0,length) );
|
||||
Vector2 anchor_B = gt.xform( Vector2(0,initial_offset) );
|
||||
|
||||
|
||||
return Physics2DServer::get_singleton()->groove_joint_create(groove_A1,groove_A2,anchor_B,body_a->get_rid(),body_b->get_rid());
|
||||
}
|
||||
|
||||
|
||||
void GrooveJoint2D::set_length(real_t p_length) {
|
||||
|
||||
length=p_length;
|
||||
update();
|
||||
}
|
||||
|
||||
real_t GrooveJoint2D::get_length() const {
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
void GrooveJoint2D::set_initial_offset(real_t p_initial_offset) {
|
||||
|
||||
initial_offset=p_initial_offset;
|
||||
update();
|
||||
}
|
||||
|
||||
real_t GrooveJoint2D::get_initial_offset() const {
|
||||
|
||||
return initial_offset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GrooveJoint2D::_bind_methods() {
|
||||
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_length","length"),&GrooveJoint2D::set_length);
|
||||
ObjectTypeDB::bind_method(_MD("get_length"),&GrooveJoint2D::get_length);
|
||||
ObjectTypeDB::bind_method(_MD("set_initial_offset","offset"),&GrooveJoint2D::set_initial_offset);
|
||||
ObjectTypeDB::bind_method(_MD("get_initial_offset"),&GrooveJoint2D::get_initial_offset);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "length", PROPERTY_HINT_EXP_RANGE,"1,65535,1"), _SCS("set_length"),_SCS("get_length"));
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "initial_offset", PROPERTY_HINT_EXP_RANGE,"1,65535,1"), _SCS("set_initial_offset"),_SCS("get_initial_offset"));
|
||||
}
|
||||
|
||||
GrooveJoint2D::GrooveJoint2D() {
|
||||
|
||||
length=50;
|
||||
initial_offset=25;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
void DampedSpringJoint2D::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
case NOTIFICATION_DRAW: {
|
||||
if (is_inside_scene() && get_scene()->is_editor_hint()) {
|
||||
|
||||
draw_line(Point2(-10,0),Point2(+10,0),Color(0.7,0.6,0.0,0.5),3);
|
||||
draw_line(Point2(-10,length),Point2(+10,length),Color(0.7,0.6,0.0,0.5),3);
|
||||
draw_line(Point2(0,0),Point2(0,length),Color(0.7,0.6,0.0,0.5),3);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
RID DampedSpringJoint2D::_configure_joint(){
|
||||
|
||||
|
||||
Node *node_a = has_node( get_node_a() ) ? get_node( get_node_a() ) : (Node*)NULL;
|
||||
Node *node_b = has_node( get_node_b() ) ? get_node( get_node_b() ) : (Node*)NULL;
|
||||
|
||||
if (!node_a || !node_b)
|
||||
return RID();
|
||||
|
||||
PhysicsBody2D *body_a=node_a->cast_to<PhysicsBody2D>();
|
||||
PhysicsBody2D *body_b=node_b->cast_to<PhysicsBody2D>();
|
||||
|
||||
if (!body_a || !body_b)
|
||||
return RID();
|
||||
|
||||
Physics2DServer::get_singleton()->body_add_collision_exception(body_a->get_rid(),body_b->get_rid());
|
||||
|
||||
Matrix32 gt = get_global_transform();
|
||||
Vector2 anchor_A = gt.get_origin();
|
||||
Vector2 anchor_B = gt.xform( Vector2(0,length) );
|
||||
|
||||
RID dsj = Physics2DServer::get_singleton()->damped_spring_joint_create(anchor_A,anchor_B,body_a->get_rid(),body_b->get_rid());
|
||||
if (rest_length)
|
||||
Physics2DServer::get_singleton()->damped_string_joint_set_param(dsj,Physics2DServer::DAMPED_STRING_REST_LENGTH,rest_length);
|
||||
Physics2DServer::get_singleton()->damped_string_joint_set_param(dsj,Physics2DServer::DAMPED_STRING_STIFFNESS,stiffness);
|
||||
Physics2DServer::get_singleton()->damped_string_joint_set_param(dsj,Physics2DServer::DAMPED_STRING_DAMPING,damping);
|
||||
|
||||
return dsj;
|
||||
}
|
||||
|
||||
|
||||
void DampedSpringJoint2D::set_length(real_t p_length) {
|
||||
|
||||
length=p_length;
|
||||
update();
|
||||
}
|
||||
|
||||
real_t DampedSpringJoint2D::get_length() const {
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
void DampedSpringJoint2D::set_rest_length(real_t p_rest_length) {
|
||||
|
||||
rest_length=p_rest_length;
|
||||
update();
|
||||
if (get_joint().is_valid())
|
||||
Physics2DServer::get_singleton()->damped_string_joint_set_param(get_joint(),Physics2DServer::DAMPED_STRING_REST_LENGTH,p_rest_length?p_rest_length:length);
|
||||
|
||||
}
|
||||
|
||||
real_t DampedSpringJoint2D::get_rest_length() const {
|
||||
|
||||
return rest_length;
|
||||
}
|
||||
|
||||
void DampedSpringJoint2D::set_stiffness(real_t p_stiffness) {
|
||||
|
||||
stiffness=p_stiffness;
|
||||
update();
|
||||
if (get_joint().is_valid())
|
||||
Physics2DServer::get_singleton()->damped_string_joint_set_param(get_joint(),Physics2DServer::DAMPED_STRING_STIFFNESS,p_stiffness);
|
||||
}
|
||||
|
||||
real_t DampedSpringJoint2D::get_stiffness() const {
|
||||
|
||||
return stiffness;
|
||||
}
|
||||
|
||||
void DampedSpringJoint2D::set_damping(real_t p_damping) {
|
||||
|
||||
damping=p_damping;
|
||||
update();
|
||||
if (get_joint().is_valid())
|
||||
Physics2DServer::get_singleton()->damped_string_joint_set_param(get_joint(),Physics2DServer::DAMPED_STRING_DAMPING,p_damping);
|
||||
}
|
||||
|
||||
real_t DampedSpringJoint2D::get_damping() const {
|
||||
|
||||
return damping;
|
||||
}
|
||||
|
||||
|
||||
void DampedSpringJoint2D::_bind_methods() {
|
||||
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_length","length"),&DampedSpringJoint2D::set_length);
|
||||
ObjectTypeDB::bind_method(_MD("get_length"),&DampedSpringJoint2D::get_length);
|
||||
ObjectTypeDB::bind_method(_MD("set_rest_length","rest_length"),&DampedSpringJoint2D::set_rest_length);
|
||||
ObjectTypeDB::bind_method(_MD("get_rest_length"),&DampedSpringJoint2D::get_rest_length);
|
||||
ObjectTypeDB::bind_method(_MD("set_stiffness","stiffness"),&DampedSpringJoint2D::set_stiffness);
|
||||
ObjectTypeDB::bind_method(_MD("get_stiffness"),&DampedSpringJoint2D::get_stiffness);
|
||||
ObjectTypeDB::bind_method(_MD("set_damping","damping"),&DampedSpringJoint2D::set_damping);
|
||||
ObjectTypeDB::bind_method(_MD("get_damping"),&DampedSpringJoint2D::get_damping);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "length", PROPERTY_HINT_EXP_RANGE,"1,65535,1"), _SCS("set_length"),_SCS("get_length"));
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "rest_length", PROPERTY_HINT_EXP_RANGE,"0,65535,1"), _SCS("set_rest_length"),_SCS("get_rest_length"));
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "stiffness", PROPERTY_HINT_EXP_RANGE,"0.1,64,0.1"), _SCS("set_stiffness"),_SCS("get_stiffness"));
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "damping", PROPERTY_HINT_EXP_RANGE,"0.01,16,0.01"), _SCS("set_damping"),_SCS("get_damping"));
|
||||
|
||||
}
|
||||
|
||||
DampedSpringJoint2D::DampedSpringJoint2D() {
|
||||
|
||||
length=50;
|
||||
rest_length=0;
|
||||
stiffness=20;
|
||||
damping=1;
|
||||
}
|
||||
141
scene/2d/joints_2d.h
Normal file
141
scene/2d/joints_2d.h
Normal file
@ -0,0 +1,141 @@
|
||||
/*************************************************************************/
|
||||
/* joints_2d.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef JOINTS_2D_H
|
||||
#define JOINTS_2D_H
|
||||
|
||||
|
||||
#include "node_2d.h"
|
||||
|
||||
class Joint2D : public Node2D {
|
||||
|
||||
OBJ_TYPE(Joint2D,Node2D);
|
||||
|
||||
RID joint;
|
||||
|
||||
NodePath a;
|
||||
NodePath b;
|
||||
real_t bias;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
void _update_joint();
|
||||
|
||||
void _notification(int p_what);
|
||||
virtual RID _configure_joint()=0;
|
||||
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_node_a(const NodePath& p_node_a);
|
||||
NodePath get_node_a() const;
|
||||
|
||||
void set_node_b(const NodePath& p_node_b);
|
||||
NodePath get_node_b() const;
|
||||
|
||||
void set_bias(real_t p_bias);
|
||||
real_t get_bias() const;
|
||||
|
||||
RID get_joint() const { return joint; }
|
||||
Joint2D();
|
||||
|
||||
};
|
||||
|
||||
|
||||
class PinJoint2D : public Joint2D {
|
||||
|
||||
OBJ_TYPE(PinJoint2D,Joint2D);
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
virtual RID _configure_joint();
|
||||
public:
|
||||
|
||||
|
||||
|
||||
PinJoint2D();
|
||||
};
|
||||
|
||||
class GrooveJoint2D : public Joint2D {
|
||||
|
||||
OBJ_TYPE(GrooveJoint2D,Joint2D);
|
||||
|
||||
real_t length;
|
||||
real_t initial_offset;
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
virtual RID _configure_joint();
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_length(real_t p_length);
|
||||
real_t get_length() const;
|
||||
|
||||
void set_initial_offset(real_t p_initial_offset);
|
||||
real_t get_initial_offset() const;
|
||||
|
||||
GrooveJoint2D();
|
||||
};
|
||||
|
||||
class DampedSpringJoint2D : public Joint2D {
|
||||
|
||||
OBJ_TYPE(DampedSpringJoint2D,Joint2D);
|
||||
|
||||
real_t stiffness;
|
||||
real_t damping;
|
||||
real_t rest_length;
|
||||
real_t length;
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
virtual RID _configure_joint();
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_length(real_t p_length);
|
||||
real_t get_length() const;
|
||||
|
||||
void set_rest_length(real_t p_rest_length);
|
||||
real_t get_rest_length() const;
|
||||
|
||||
void set_damping(real_t p_damping);
|
||||
real_t get_damping() const;
|
||||
|
||||
void set_stiffness(real_t p_stiffness);
|
||||
real_t get_stiffness() const;
|
||||
|
||||
DampedSpringJoint2D();
|
||||
};
|
||||
|
||||
|
||||
#endif // JOINTS_2D_H
|
||||
291
scene/2d/node_2d.cpp
Normal file
291
scene/2d/node_2d.cpp
Normal file
@ -0,0 +1,291 @@
|
||||
/*************************************************************************/
|
||||
/* node_2d.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "node_2d.h"
|
||||
|
||||
#include "servers/visual_server.h"
|
||||
#include "scene/gui/control.h"
|
||||
#include "scene/main/viewport.h"
|
||||
#include "message_queue.h"
|
||||
|
||||
|
||||
void Node2D::edit_set_pivot(const Point2& p_pivot) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
Point2 Node2D::edit_get_pivot() const {
|
||||
|
||||
return Point2();
|
||||
}
|
||||
bool Node2D::edit_has_pivot() const {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Variant Node2D::edit_get_state() const {
|
||||
|
||||
Array state;
|
||||
state.push_back(pos);
|
||||
state.push_back(angle);
|
||||
state.push_back(scale);
|
||||
|
||||
return state;
|
||||
|
||||
}
|
||||
void Node2D::edit_set_state(const Variant& p_state) {
|
||||
|
||||
Array state = p_state;
|
||||
ERR_FAIL_COND( state.size() != 3);
|
||||
|
||||
pos = state[0];
|
||||
angle = state[1];
|
||||
scale = state[2];
|
||||
_update_transform();
|
||||
_change_notify("transform/rot");
|
||||
_change_notify("transform/scale");
|
||||
_change_notify("transform/pos");
|
||||
|
||||
}
|
||||
|
||||
void Node2D::edit_set_rect(const Rect2& p_edit_rect) {
|
||||
|
||||
Rect2 r = get_item_rect();
|
||||
|
||||
Vector2 zero_offset;
|
||||
if (r.size.x!=0)
|
||||
zero_offset.x = -r.pos.x / r.size.x;
|
||||
if (r.size.y!=0)
|
||||
zero_offset.y = -r.pos.y / r.size.y;
|
||||
|
||||
Size2 new_scale(1,1);
|
||||
|
||||
if (r.size.x!=0)
|
||||
new_scale.x = p_edit_rect.size.x / r.size.x;
|
||||
if (r.size.y!=0)
|
||||
new_scale.y = p_edit_rect.size.y / r.size.y;
|
||||
|
||||
Point2 new_pos = p_edit_rect.pos + p_edit_rect.size*zero_offset;//p_edit_rect.pos - r.pos;
|
||||
|
||||
Matrix32 postxf;
|
||||
postxf.set_rotation_and_scale(angle,scale);
|
||||
new_pos = postxf.xform(new_pos);
|
||||
|
||||
pos+=new_pos;
|
||||
scale*=new_scale;
|
||||
|
||||
_update_transform();
|
||||
_change_notify("transform/scale");
|
||||
_change_notify("transform/pos");
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Node2D::edit_rotate(float p_rot) {
|
||||
|
||||
angle+=p_rot;
|
||||
_update_transform();
|
||||
_change_notify("transform/rot");
|
||||
}
|
||||
|
||||
|
||||
void Node2D::_update_xform_values() {
|
||||
|
||||
pos=_mat.elements[2];
|
||||
angle=_mat.get_rotation();
|
||||
scale=_mat.get_scale();
|
||||
_xform_dirty=false;
|
||||
}
|
||||
|
||||
void Node2D::_update_transform() {
|
||||
|
||||
Matrix32 mat(angle,pos);
|
||||
_mat.set_rotation_and_scale(angle,scale);
|
||||
_mat.elements[2]=pos;
|
||||
|
||||
VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(),_mat);
|
||||
|
||||
if (!is_inside_scene())
|
||||
return;
|
||||
|
||||
|
||||
_notify_transform();
|
||||
}
|
||||
|
||||
void Node2D::set_pos(const Point2& p_pos) {
|
||||
|
||||
if (_xform_dirty)
|
||||
((Node2D*)this)->_update_xform_values();
|
||||
pos=p_pos;
|
||||
_update_transform();
|
||||
_change_notify("transform/pos");
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Node2D::set_rot(float p_angle) {
|
||||
|
||||
if (_xform_dirty)
|
||||
((Node2D*)this)->_update_xform_values();
|
||||
angle=p_angle;
|
||||
_update_transform();
|
||||
_change_notify("transform/rot");
|
||||
}
|
||||
|
||||
void Node2D::set_scale(const Size2& p_scale) {
|
||||
|
||||
if (_xform_dirty)
|
||||
((Node2D*)this)->_update_xform_values();
|
||||
scale=p_scale;
|
||||
_update_transform();
|
||||
_change_notify("transform/scale");
|
||||
|
||||
}
|
||||
|
||||
Point2 Node2D::get_pos() const {
|
||||
|
||||
if (_xform_dirty)
|
||||
((Node2D*)this)->_update_xform_values();
|
||||
return pos;
|
||||
}
|
||||
float Node2D::get_rot() const {
|
||||
if (_xform_dirty)
|
||||
((Node2D*)this)->_update_xform_values();
|
||||
|
||||
return angle;
|
||||
}
|
||||
Size2 Node2D::get_scale() const {
|
||||
if (_xform_dirty)
|
||||
((Node2D*)this)->_update_xform_values();
|
||||
|
||||
return scale;
|
||||
}
|
||||
|
||||
void Node2D::_set_rotd(float p_angle) {
|
||||
|
||||
set_rot(Math::deg2rad(p_angle));
|
||||
}
|
||||
|
||||
float Node2D::_get_rotd() const {
|
||||
|
||||
return Math::rad2deg(get_rot());
|
||||
}
|
||||
|
||||
|
||||
void Node2D::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Matrix32 Node2D::get_transform() const {
|
||||
|
||||
return _mat;
|
||||
}
|
||||
|
||||
Rect2 Node2D::get_item_rect() const {
|
||||
|
||||
if (get_script_instance()) {
|
||||
Variant::CallError err;
|
||||
Rect2 r = get_script_instance()->call("_get_item_rect",NULL,0,err);
|
||||
if (err.error==Variant::CallError::CALL_OK)
|
||||
return r;
|
||||
}
|
||||
return Rect2(Point2(-32,-32),Size2(64,64));
|
||||
}
|
||||
|
||||
Point2 Node2D::get_global_pos() const {
|
||||
|
||||
return get_global_transform().get_origin();
|
||||
}
|
||||
|
||||
void Node2D::set_transform(const Matrix32& p_transform) {
|
||||
|
||||
_mat=p_transform;
|
||||
_xform_dirty=true;
|
||||
|
||||
VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(),_mat);
|
||||
|
||||
if (!is_inside_scene())
|
||||
return;
|
||||
|
||||
_notify_transform();
|
||||
}
|
||||
|
||||
void Node2D::set_global_transform(const Matrix32& p_transform) {
|
||||
|
||||
CanvasItem *pi = get_parent_item();
|
||||
if (pi)
|
||||
set_transform( pi->get_global_transform().affine_inverse() * p_transform);
|
||||
else
|
||||
set_transform(p_transform);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Node2D::_bind_methods() {
|
||||
|
||||
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_get_rotd"),&Node2D::_get_rotd);
|
||||
ObjectTypeDB::bind_method(_MD("_set_rotd"),&Node2D::_set_rotd);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_pos","pos"),&Node2D::set_pos);
|
||||
ObjectTypeDB::bind_method(_MD("set_rot","rot"),&Node2D::set_rot);
|
||||
ObjectTypeDB::bind_method(_MD("set_scale","scale"),&Node2D::set_scale);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("get_pos"),&Node2D::get_pos);
|
||||
ObjectTypeDB::bind_method(_MD("get_rot"),&Node2D::get_rot);
|
||||
ObjectTypeDB::bind_method(_MD("get_scale"),&Node2D::get_scale);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("get_global_pos"),&Node2D::get_global_pos);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_transform","xform"),&Node2D::set_transform);
|
||||
ObjectTypeDB::bind_method(_MD("set_global_transform","xform"),&Node2D::set_global_transform);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("edit_set_pivot"),&Node2D::edit_set_pivot);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"transform/pos"),_SCS("set_pos"),_SCS("get_pos"));
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL,"transform/rot",PROPERTY_HINT_RANGE,"-1440,1440,0.1"),_SCS("_set_rotd"),_SCS("_get_rotd"));
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"transform/scale"),_SCS("set_scale"),_SCS("get_scale"));
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
Node2D::Node2D() {
|
||||
|
||||
|
||||
angle=0;
|
||||
scale=Vector2(1,1);
|
||||
_xform_dirty=false;
|
||||
|
||||
}
|
||||
|
||||
89
scene/2d/node_2d.h
Normal file
89
scene/2d/node_2d.h
Normal file
@ -0,0 +1,89 @@
|
||||
/*************************************************************************/
|
||||
/* node_2d.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef NODE2D_H
|
||||
#define NODE2D_H
|
||||
|
||||
#include "scene/2d/canvas_item.h"
|
||||
|
||||
class Node2D : public CanvasItem {
|
||||
|
||||
OBJ_TYPE(Node2D, CanvasItem );
|
||||
|
||||
Point2 pos;
|
||||
float angle;
|
||||
Size2 scale;
|
||||
|
||||
Matrix32 _mat;
|
||||
|
||||
bool _xform_dirty;
|
||||
|
||||
void _update_transform();
|
||||
|
||||
void _set_rotd(float p_angle);
|
||||
float _get_rotd() const;
|
||||
|
||||
void _update_xform_values();
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
void _notification(int p_what);
|
||||
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
virtual Variant edit_get_state() const;
|
||||
virtual void edit_set_state(const Variant& p_state);
|
||||
virtual void edit_set_rect(const Rect2& p_edit_rect);
|
||||
virtual void edit_rotate(float p_rot);
|
||||
virtual void edit_set_pivot(const Point2& p_pivot);
|
||||
virtual Point2 edit_get_pivot() const;
|
||||
virtual bool edit_has_pivot() const;
|
||||
|
||||
void set_pos(const Point2& p_pos);
|
||||
void set_rot(float p_angle);
|
||||
void set_scale(const Size2& p_scale);
|
||||
|
||||
Point2 get_pos() const;
|
||||
float get_rot() const;
|
||||
Size2 get_scale() const;
|
||||
|
||||
Point2 get_global_pos() const;
|
||||
virtual Rect2 get_item_rect() const;
|
||||
|
||||
void set_transform(const Matrix32& p_transform);
|
||||
void set_global_transform(const Matrix32& p_transform);
|
||||
|
||||
|
||||
Matrix32 get_transform() const;
|
||||
|
||||
Node2D();
|
||||
};
|
||||
|
||||
#endif // NODE2D_H
|
||||
30
scene/2d/node_2d_singleton.cpp
Normal file
30
scene/2d/node_2d_singleton.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
/*************************************************************************/
|
||||
/* node_2d_singleton.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "node_2d_singleton.h"
|
||||
|
||||
33
scene/2d/node_2d_singleton.h
Normal file
33
scene/2d/node_2d_singleton.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*************************************************************************/
|
||||
/* node_2d_singleton.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef NODE_2D_SINGLETON_H
|
||||
#define NODE_2D_SINGLETON_H
|
||||
|
||||
|
||||
#endif // NODE_2D_SINGLETON_H
|
||||
200
scene/2d/parallax_background.cpp
Normal file
200
scene/2d/parallax_background.cpp
Normal file
@ -0,0 +1,200 @@
|
||||
/*************************************************************************/
|
||||
/* parallax_background.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "parallax_background.h"
|
||||
#include "parallax_layer.h"
|
||||
|
||||
|
||||
|
||||
void ParallaxBackground::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
|
||||
case NOTIFICATION_ENTER_SCENE: {
|
||||
|
||||
group_name = "__cameras_"+itos(get_viewport().get_id());
|
||||
add_to_group(group_name);
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_SCENE: {
|
||||
|
||||
remove_from_group(group_name);
|
||||
} break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ParallaxBackground::_camera_moved(const Matrix32& p_transform) {
|
||||
|
||||
|
||||
set_scroll_offset(p_transform.get_origin());
|
||||
set_scroll_scale(p_transform.get_scale().dot(Vector2(0.5,0.5)));
|
||||
}
|
||||
|
||||
|
||||
void ParallaxBackground::set_scroll_scale(float p_scale) {
|
||||
|
||||
scale=p_scale;
|
||||
}
|
||||
|
||||
float ParallaxBackground::get_scroll_scale() const{
|
||||
|
||||
return scale;
|
||||
}
|
||||
|
||||
|
||||
void ParallaxBackground::set_scroll_offset(const Point2& p_ofs) {
|
||||
|
||||
offset=p_ofs;
|
||||
|
||||
_update_scroll();
|
||||
}
|
||||
|
||||
void ParallaxBackground::_update_scroll() {
|
||||
|
||||
if (!is_inside_scene())
|
||||
return;
|
||||
|
||||
Vector2 ofs = base_offset+offset*base_scale;
|
||||
|
||||
Size2 vps = get_viewport_size();
|
||||
|
||||
ofs = -ofs;
|
||||
if (limit_begin.x < limit_end.x) {
|
||||
|
||||
if (ofs.x < limit_begin.x)
|
||||
ofs.x=limit_begin.x;
|
||||
else if (ofs.x+vps.x > limit_end.x)
|
||||
ofs.x=limit_end.x-vps.x;
|
||||
}
|
||||
|
||||
|
||||
if (limit_begin.y < limit_end.y) {
|
||||
|
||||
if (ofs.y < limit_begin.y)
|
||||
ofs.y=limit_begin.y;
|
||||
else if (ofs.y+vps.y > limit_end.y)
|
||||
ofs.y=limit_end.y-vps.y;
|
||||
}
|
||||
ofs = -ofs;
|
||||
|
||||
for(int i=0;i<get_child_count();i++) {
|
||||
|
||||
ParallaxLayer *l=get_child(i)->cast_to<ParallaxLayer>();
|
||||
if (!l)
|
||||
continue;
|
||||
|
||||
l->set_base_offset_and_scale(ofs,scale);
|
||||
}
|
||||
}
|
||||
|
||||
Point2 ParallaxBackground::get_scroll_offset() const {
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
void ParallaxBackground::set_scroll_base_offset(const Point2& p_ofs) {
|
||||
|
||||
base_offset=p_ofs;
|
||||
_update_scroll();
|
||||
}
|
||||
|
||||
Point2 ParallaxBackground::get_scroll_base_offset() const{
|
||||
|
||||
return base_offset;
|
||||
}
|
||||
|
||||
void ParallaxBackground::set_scroll_base_scale(const Point2& p_ofs) {
|
||||
|
||||
base_scale=p_ofs;
|
||||
_update_scroll();
|
||||
}
|
||||
|
||||
Point2 ParallaxBackground::get_scroll_base_scale() const{
|
||||
|
||||
return base_scale;
|
||||
}
|
||||
|
||||
|
||||
void ParallaxBackground::set_limit_begin(const Point2& p_ofs) {
|
||||
|
||||
limit_begin=p_ofs;
|
||||
_update_scroll();
|
||||
}
|
||||
|
||||
Point2 ParallaxBackground::get_limit_begin() const {
|
||||
|
||||
return limit_begin;
|
||||
}
|
||||
|
||||
void ParallaxBackground::set_limit_end(const Point2& p_ofs) {
|
||||
|
||||
limit_end=p_ofs;
|
||||
_update_scroll();
|
||||
|
||||
}
|
||||
|
||||
Point2 ParallaxBackground::get_limit_end() const {
|
||||
|
||||
return limit_end;
|
||||
}
|
||||
|
||||
void ParallaxBackground::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_camera_moved"),&ParallaxBackground::_camera_moved);
|
||||
ObjectTypeDB::bind_method(_MD("set_scroll_offset","ofs"),&ParallaxBackground::set_scroll_offset);
|
||||
ObjectTypeDB::bind_method(_MD("get_scroll_offset"),&ParallaxBackground::get_scroll_offset);
|
||||
ObjectTypeDB::bind_method(_MD("set_scroll_base_offset","ofs"),&ParallaxBackground::set_scroll_base_offset);
|
||||
ObjectTypeDB::bind_method(_MD("get_scroll_base_offset"),&ParallaxBackground::get_scroll_base_offset);
|
||||
ObjectTypeDB::bind_method(_MD("set_scroll_base_scale","scale"),&ParallaxBackground::set_scroll_base_scale);
|
||||
ObjectTypeDB::bind_method(_MD("get_scroll_base_scale"),&ParallaxBackground::get_scroll_base_scale);
|
||||
ObjectTypeDB::bind_method(_MD("set_limit_begin","ofs"),&ParallaxBackground::set_limit_begin);
|
||||
ObjectTypeDB::bind_method(_MD("get_limit_begin"),&ParallaxBackground::get_limit_begin);
|
||||
ObjectTypeDB::bind_method(_MD("set_limit_end","ofs"),&ParallaxBackground::set_limit_end);
|
||||
ObjectTypeDB::bind_method(_MD("get_limit_end"),&ParallaxBackground::get_limit_end);
|
||||
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"scroll/offset"),_SCS("set_scroll_offset"),_SCS("get_scroll_offset"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"scroll/base_offset"),_SCS("set_scroll_base_offset"),_SCS("get_scroll_base_offset"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"scroll/base_scale"),_SCS("set_scroll_base_scale"),_SCS("get_scroll_base_scale"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"scroll/limit_begin"),_SCS("set_limit_begin"),_SCS("get_limit_begin"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"scroll/limit_end"),_SCS("set_limit_end"),_SCS("get_limit_end"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ParallaxBackground::ParallaxBackground() {
|
||||
|
||||
base_scale=Vector2(1,1);
|
||||
scale=1.0;
|
||||
set_layer(-1); //behind all by default
|
||||
}
|
||||
78
scene/2d/parallax_background.h
Normal file
78
scene/2d/parallax_background.h
Normal file
@ -0,0 +1,78 @@
|
||||
/*************************************************************************/
|
||||
/* parallax_background.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef PARALLAX_BACKGROUND_H
|
||||
#define PARALLAX_BACKGROUND_H
|
||||
|
||||
#include "scene/main/canvas_layer.h"
|
||||
#include "scene/2d/node_2d.h"
|
||||
#include "scene/2d/camera_2d.h"
|
||||
|
||||
class ParallaxBackground : public CanvasLayer {
|
||||
|
||||
OBJ_TYPE( ParallaxBackground, CanvasLayer );
|
||||
|
||||
Point2 offset;
|
||||
float scale;
|
||||
Point2 base_offset;
|
||||
Point2 base_scale;
|
||||
String group_name;
|
||||
Point2 limit_begin;
|
||||
Point2 limit_end;
|
||||
|
||||
void _update_scroll();
|
||||
protected:
|
||||
|
||||
void _camera_moved(const Matrix32& p_transform);
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_scroll_offset(const Point2& p_ofs);
|
||||
Point2 get_scroll_offset() const;
|
||||
|
||||
void set_scroll_scale(float p_ofs);
|
||||
float get_scroll_scale() const;
|
||||
|
||||
void set_scroll_base_offset(const Point2& p_ofs);
|
||||
Point2 get_scroll_base_offset() const;
|
||||
|
||||
void set_scroll_base_scale(const Point2& p_ofs);
|
||||
Point2 get_scroll_base_scale() const;
|
||||
|
||||
void set_limit_begin(const Point2& p_ofs);
|
||||
Point2 get_limit_begin() const;
|
||||
|
||||
void set_limit_end(const Point2& p_ofs);
|
||||
Point2 get_limit_end() const;
|
||||
|
||||
ParallaxBackground();
|
||||
};
|
||||
|
||||
#endif // PARALLAX_BACKGROUND_H
|
||||
138
scene/2d/parallax_layer.cpp
Normal file
138
scene/2d/parallax_layer.cpp
Normal file
@ -0,0 +1,138 @@
|
||||
/*************************************************************************/
|
||||
/* parallax_layer.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "parallax_layer.h"
|
||||
#include "parallax_background.h"
|
||||
|
||||
void ParallaxLayer::set_motion_scale(const Size2& p_scale) {
|
||||
|
||||
motion_scale=p_scale;
|
||||
}
|
||||
|
||||
Size2 ParallaxLayer::get_motion_scale() const {
|
||||
|
||||
return motion_scale;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ParallaxLayer::_update_mirroring() {
|
||||
|
||||
if (!get_parent())
|
||||
return;
|
||||
|
||||
ParallaxBackground *pb = get_parent()->cast_to<ParallaxBackground>();
|
||||
if (pb) {
|
||||
|
||||
RID c = pb->get_world_2d()->get_canvas();
|
||||
RID ci = get_canvas_item();
|
||||
VisualServer::get_singleton()->canvas_set_item_mirroring(c,ci,mirroring);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ParallaxLayer::set_mirroring(const Size2& p_mirroring) {
|
||||
|
||||
mirroring=p_mirroring;
|
||||
_update_mirroring();
|
||||
|
||||
}
|
||||
|
||||
Size2 ParallaxLayer::get_mirroring() const{
|
||||
|
||||
return mirroring;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ParallaxLayer::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_ENTER_SCENE: {
|
||||
|
||||
orig_offset=get_pos();
|
||||
orig_scale=get_scale();
|
||||
_update_mirroring();
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void ParallaxLayer::set_base_offset_and_scale(const Point2& p_offset,float p_scale) {
|
||||
|
||||
if (!is_inside_scene())
|
||||
return;
|
||||
if (get_scene()->is_editor_hint())
|
||||
return;
|
||||
Point2 new_ofs = ((orig_offset+p_offset)*motion_scale)*p_scale;
|
||||
|
||||
if (mirroring.x) {
|
||||
|
||||
while( new_ofs.x>=0) {
|
||||
new_ofs.x -= mirroring.x*p_scale;
|
||||
}
|
||||
while(new_ofs.x < -mirroring.x*p_scale) {
|
||||
new_ofs.x += mirroring.x*p_scale;
|
||||
}
|
||||
}
|
||||
|
||||
if (mirroring.y) {
|
||||
|
||||
while( new_ofs.y>=0) {
|
||||
new_ofs.y -= mirroring.y*p_scale;
|
||||
}
|
||||
while(new_ofs.y < -mirroring.y*p_scale) {
|
||||
new_ofs.y += mirroring.y*p_scale;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
set_pos(new_ofs);
|
||||
set_scale(Vector2(1,1)*p_scale);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ParallaxLayer::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_motion_scale","scale"),&ParallaxLayer::set_motion_scale);
|
||||
ObjectTypeDB::bind_method(_MD("get_motion_scale"),&ParallaxLayer::get_motion_scale);
|
||||
ObjectTypeDB::bind_method(_MD("set_mirroring","mirror"),&ParallaxLayer::set_mirroring);
|
||||
ObjectTypeDB::bind_method(_MD("get_mirroring"),&ParallaxLayer::get_mirroring);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"motion/scale"),_SCS("set_motion_scale"),_SCS("get_motion_scale"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"motion/mirroring"),_SCS("set_mirroring"),_SCS("get_mirroring"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
ParallaxLayer::ParallaxLayer()
|
||||
{
|
||||
motion_scale=Size2(1,1);
|
||||
}
|
||||
62
scene/2d/parallax_layer.h
Normal file
62
scene/2d/parallax_layer.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*************************************************************************/
|
||||
/* parallax_layer.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef PARALLAX_LAYER_H
|
||||
#define PARALLAX_LAYER_H
|
||||
|
||||
#include "scene/2d/node_2d.h"
|
||||
|
||||
class ParallaxLayer : public Node2D {
|
||||
|
||||
OBJ_TYPE( ParallaxLayer, Node2D );
|
||||
|
||||
Point2 orig_offset;
|
||||
Point2 orig_scale;
|
||||
Size2 motion_scale;
|
||||
Vector2 mirroring;
|
||||
void _update_mirroring();
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
void set_motion_scale(const Size2& p_scale);
|
||||
Size2 get_motion_scale() const;
|
||||
|
||||
void set_mirroring(const Size2& p_mirroring);
|
||||
Size2 get_mirroring() const;
|
||||
|
||||
void set_base_offset_and_scale(const Point2& p_offsetf,float p_scale);
|
||||
|
||||
ParallaxLayer();
|
||||
};
|
||||
|
||||
#endif // PARALLAX_LAYER_H
|
||||
1045
scene/2d/particles_2d.cpp
Normal file
1045
scene/2d/particles_2d.cpp
Normal file
File diff suppressed because it is too large
Load Diff
231
scene/2d/particles_2d.h
Normal file
231
scene/2d/particles_2d.h
Normal file
@ -0,0 +1,231 @@
|
||||
/*************************************************************************/
|
||||
/* particles_2d.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef PARTICLES_FRAME_H
|
||||
#define PARTICLES_FRAME_H
|
||||
|
||||
#include "scene/2d/node_2d.h"
|
||||
#include "scene/resources/texture.h"
|
||||
|
||||
class Particles2D;
|
||||
class ParticleAttractor2D : public Node2D {
|
||||
|
||||
OBJ_TYPE(ParticleAttractor2D,Node2D);
|
||||
|
||||
|
||||
friend class Particles2D;
|
||||
bool enabled;
|
||||
float radius;
|
||||
float disable_radius;
|
||||
float gravity;
|
||||
float absorption;
|
||||
NodePath path;
|
||||
|
||||
Particles2D *owner;
|
||||
|
||||
void _update_owner();
|
||||
void _owner_exited();
|
||||
void _set_owner(Particles2D* p_owner);
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_enabled(bool p_enabled);
|
||||
bool is_enabled() const;
|
||||
|
||||
void set_radius(float p_radius);
|
||||
float get_radius() const;
|
||||
|
||||
void set_disable_radius(float p_disable_radius);
|
||||
float get_disable_radius() const;
|
||||
|
||||
void set_gravity(float p_gravity);
|
||||
float get_gravity() const;
|
||||
|
||||
void set_absorption(float p_absorption);
|
||||
float get_absorption() const;
|
||||
|
||||
void set_particles_path(NodePath p_path);
|
||||
NodePath get_particles_path() const;
|
||||
|
||||
ParticleAttractor2D();
|
||||
};
|
||||
|
||||
|
||||
|
||||
class Particles2D : public Node2D {
|
||||
|
||||
OBJ_TYPE(Particles2D, Node2D);
|
||||
public:
|
||||
|
||||
enum Parameter {
|
||||
PARAM_DIRECTION,
|
||||
PARAM_SPREAD,
|
||||
PARAM_LINEAR_VELOCITY,
|
||||
PARAM_SPIN_VELOCITY,
|
||||
PARAM_ORBIT_VELOCITY,
|
||||
PARAM_GRAVITY_DIRECTION,
|
||||
PARAM_GRAVITY_STRENGTH,
|
||||
PARAM_RADIAL_ACCEL,
|
||||
PARAM_TANGENTIAL_ACCEL,
|
||||
PARAM_DAMPING,
|
||||
PARAM_INITIAL_SIZE,
|
||||
PARAM_FINAL_SIZE,
|
||||
PARAM_HUE_VARIATION,
|
||||
PARAM_MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
MAX_COLOR_PHASES=4
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
float param[PARAM_MAX];
|
||||
float randomness[PARAM_MAX];
|
||||
|
||||
struct Particle {
|
||||
|
||||
bool active;
|
||||
Point2 pos;
|
||||
Vector2 velocity;
|
||||
float rot;
|
||||
uint32_t seed;
|
||||
Particle() { active=false; seed=123465789; rot=0;}
|
||||
};
|
||||
|
||||
Vector<Particle> particles;
|
||||
int color_phase_count;
|
||||
struct ColorPhase {
|
||||
Color color;
|
||||
float pos;
|
||||
} color_phases[MAX_COLOR_PHASES];
|
||||
|
||||
struct AttractorCache {
|
||||
|
||||
Vector2 pos;
|
||||
ParticleAttractor2D *attractor;
|
||||
};
|
||||
|
||||
Vector<AttractorCache> attractor_cache;
|
||||
|
||||
float explosiveness;
|
||||
float preprocess;
|
||||
float lifetime;
|
||||
bool emitting;
|
||||
bool local_space;
|
||||
float emit_timeout;
|
||||
float time_to_live;
|
||||
float time_scale;
|
||||
Point2 emissor_offset;
|
||||
Vector2 initial_velocity;
|
||||
Vector2 extents;
|
||||
DVector<Vector2> emission_points;
|
||||
|
||||
float time;
|
||||
int active_count;
|
||||
|
||||
Ref<Texture> texture;
|
||||
|
||||
|
||||
void testee(int a, int b, int c, int d, int e);
|
||||
void _process_particles(float p_delta);
|
||||
friend class ParticleAttractor2D;
|
||||
|
||||
Set<ParticleAttractor2D*> attractors;
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
void set_emitting(bool p_emitting);
|
||||
bool is_emitting() const;
|
||||
|
||||
void set_amount(int p_amount);
|
||||
int get_amount() const;
|
||||
|
||||
void set_lifetime(float p_lifetime);
|
||||
float get_lifetime() const;
|
||||
|
||||
void set_time_scale(float p_time_scale);
|
||||
float get_time_scale() const;
|
||||
|
||||
void set_pre_process_time(float p_pre_process_time);
|
||||
float get_pre_process_time() const;
|
||||
|
||||
void set_emit_timeout(float p_timeout);
|
||||
float get_emit_timeout() const;
|
||||
|
||||
void set_emission_half_extents(const Vector2& p_extents);
|
||||
Vector2 get_emission_half_extents() const;
|
||||
|
||||
void set_param(Parameter p_param, float p_value);
|
||||
float get_param(Parameter p_param) const;
|
||||
|
||||
void set_randomness(Parameter p_randomness, float p_value);
|
||||
float get_randomness(Parameter p_randomness) const;
|
||||
|
||||
void set_explosiveness(float p_value);
|
||||
float get_explosiveness() const;
|
||||
|
||||
void set_color_phases(int p_phases);
|
||||
int get_color_phases() const;
|
||||
|
||||
void set_color_phase_color(int p_phase,const Color& p_color);
|
||||
Color get_color_phase_color(int p_phase) const;
|
||||
|
||||
void set_color_phase_pos(int p_phase,float p_pos);
|
||||
float get_color_phase_pos(int p_phase) const;
|
||||
|
||||
void set_texture(const Ref<Texture>& p_texture);
|
||||
Ref<Texture> get_texture() const;
|
||||
|
||||
void set_emissor_offset(const Point2& p_offset);
|
||||
Point2 get_emissor_offset() const;
|
||||
|
||||
void set_use_local_space(bool p_use);
|
||||
bool is_using_local_space() const;
|
||||
|
||||
void set_initial_velocity(const Vector2& p_velocity);
|
||||
Vector2 get_initial_velocity() const;
|
||||
|
||||
void set_emission_points(const DVector<Vector2>& p_points);
|
||||
DVector<Vector2> get_emission_points() const;
|
||||
|
||||
void pre_process(float p_delta);
|
||||
|
||||
Particles2D();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST( Particles2D::Parameter );
|
||||
|
||||
#endif // PARTICLES_FRAME_H
|
||||
92
scene/2d/path_2d.cpp
Normal file
92
scene/2d/path_2d.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
/*************************************************************************/
|
||||
/* path_2d.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "path_2d.h"
|
||||
|
||||
|
||||
void Path2D::_notification(int p_what) {
|
||||
|
||||
if (p_what==NOTIFICATION_DRAW && curve.is_valid() && is_inside_scene() && get_scene()->is_editor_hint()) {
|
||||
//draw the curve!!
|
||||
|
||||
for(int i=0;i<curve->get_point_count();i++) {
|
||||
|
||||
Vector2 prev_p=curve->get_point_pos(i);
|
||||
|
||||
for(int j=1;j<=8;j++) {
|
||||
|
||||
real_t frac = j/8.0;
|
||||
Vector2 p = curve->interpolate(i,frac);
|
||||
draw_line(prev_p,p,Color(0.5,0.6,1.0,0.7),2);
|
||||
prev_p=p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Path2D::_curve_changed() {
|
||||
|
||||
|
||||
if (is_inside_scene() && get_scene()->is_editor_hint())
|
||||
update();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Path2D::set_curve(const Ref<Curve2D>& p_curve) {
|
||||
|
||||
if (curve.is_valid()) {
|
||||
curve->disconnect("changed",this,"_curve_changed");
|
||||
}
|
||||
|
||||
curve=p_curve;
|
||||
|
||||
if (curve.is_valid()) {
|
||||
curve->connect("changed",this,"_curve_changed");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Ref<Curve2D> Path2D::get_curve() const{
|
||||
|
||||
return curve;
|
||||
}
|
||||
|
||||
void Path2D::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_curve","curve:Curve2D"),&Path2D::set_curve);
|
||||
ObjectTypeDB::bind_method(_MD("get_curve:Curve2D","curve"),&Path2D::get_curve);
|
||||
ObjectTypeDB::bind_method(_MD("_curve_changed"),&Path2D::_curve_changed);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve2D"), _SCS("set_curve"),_SCS("get_curve"));
|
||||
}
|
||||
|
||||
Path2D::Path2D() {
|
||||
|
||||
set_curve(Ref<Curve2D>( memnew( Curve2D ))); //create one by default
|
||||
}
|
||||
57
scene/2d/path_2d.h
Normal file
57
scene/2d/path_2d.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*************************************************************************/
|
||||
/* path_2d.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef PATH_2D_H
|
||||
#define PATH_2D_H
|
||||
|
||||
#include "scene/resources/curve.h"
|
||||
#include "scene/2d/node_2d.h"
|
||||
|
||||
class Path2D : public Node2D {
|
||||
|
||||
OBJ_TYPE( Path2D, Node2D );
|
||||
|
||||
Ref<Curve2D> curve;
|
||||
|
||||
void _curve_changed();
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_curve(const Ref<Curve2D>& p_curve);
|
||||
Ref<Curve2D> get_curve() const;
|
||||
|
||||
|
||||
Path2D();
|
||||
};
|
||||
|
||||
#endif // PATH_2D_H
|
||||
794
scene/2d/physics_body_2d.cpp
Normal file
794
scene/2d/physics_body_2d.cpp
Normal file
@ -0,0 +1,794 @@
|
||||
/*************************************************************************/
|
||||
/* physics_body_2d.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "physics_body_2d.h"
|
||||
#include "scene/scene_string_names.h"
|
||||
|
||||
void PhysicsBody2D::_notification(int p_what) {
|
||||
|
||||
/*
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
|
||||
Physics2DServer::get_singleton()->body_set_state(get_rid(),Physics2DServer::BODY_STATE_TRANSFORM,get_global_transform());
|
||||
|
||||
} break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
PhysicsBody2D::PhysicsBody2D(Physics2DServer::BodyMode p_mode) : CollisionObject2D( Physics2DServer::get_singleton()->body_create(p_mode), false) {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void StaticBody2D::set_constant_linear_velocity(const Vector2& p_vel) {
|
||||
|
||||
constant_linear_velocity=p_vel;
|
||||
Physics2DServer::get_singleton()->body_set_state(get_rid(),Physics2DServer::BODY_STATE_LINEAR_VELOCITY,constant_linear_velocity);
|
||||
|
||||
}
|
||||
|
||||
void StaticBody2D::set_constant_angular_velocity(real_t p_vel) {
|
||||
|
||||
constant_angular_velocity=p_vel;
|
||||
Physics2DServer::get_singleton()->body_set_state(get_rid(),Physics2DServer::BODY_STATE_ANGULAR_VELOCITY,constant_angular_velocity);
|
||||
}
|
||||
|
||||
Vector2 StaticBody2D::get_constant_linear_velocity() const {
|
||||
|
||||
return constant_linear_velocity;
|
||||
}
|
||||
real_t StaticBody2D::get_constant_angular_velocity() const {
|
||||
|
||||
return constant_angular_velocity;
|
||||
}
|
||||
|
||||
|
||||
void StaticBody2D::_state_notify(Object *p_object) {
|
||||
|
||||
if (!pre_xform)
|
||||
return;
|
||||
|
||||
Physics2DDirectBodyState *p2d = (Physics2DDirectBodyState*)p_object;
|
||||
setting=true;
|
||||
|
||||
Matrix32 new_xform = p2d->get_transform();
|
||||
*pre_xform=new_xform;
|
||||
set_block_transform_notify(true);
|
||||
set_global_transform(new_xform);
|
||||
set_block_transform_notify(false);
|
||||
|
||||
setting=false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void StaticBody2D::_update_xform() {
|
||||
|
||||
if (!pre_xform || !pending)
|
||||
return;
|
||||
|
||||
setting=true;
|
||||
|
||||
|
||||
Matrix32 new_xform = get_global_transform(); //obtain the new one
|
||||
|
||||
set_block_transform_notify(true);
|
||||
Physics2DServer::get_singleton()->body_set_state(get_rid(),Physics2DServer::BODY_STATE_TRANSFORM,*pre_xform); //then simulate motion!
|
||||
set_global_transform(*pre_xform); //but restore state to previous one in both visual and physics
|
||||
set_block_transform_notify(false);
|
||||
|
||||
Physics2DServer::get_singleton()->body_static_simulate_motion(get_rid(),new_xform); //then simulate motion!
|
||||
|
||||
setting=false;
|
||||
pending=false;
|
||||
|
||||
}
|
||||
|
||||
void StaticBody2D::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_ENTER_SCENE: {
|
||||
|
||||
if (pre_xform)
|
||||
*pre_xform = get_global_transform();
|
||||
pending=false;
|
||||
} break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
|
||||
if (simulating_motion && !pending && is_inside_scene() && !setting && !get_scene()->is_editor_hint()) {
|
||||
|
||||
|
||||
call_deferred(SceneStringNames::get_singleton()->_update_xform);
|
||||
pending=true;
|
||||
}
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void StaticBody2D::set_simulate_motion(bool p_enable) {
|
||||
|
||||
if (p_enable==simulating_motion)
|
||||
return;
|
||||
simulating_motion=p_enable;
|
||||
|
||||
if (p_enable) {
|
||||
pre_xform = memnew( Matrix32 );
|
||||
if (is_inside_scene())
|
||||
*pre_xform=get_transform();
|
||||
// query = Physics2DServer::get_singleton()->query_create(this,"_state_notify",Variant());
|
||||
// Physics2DServer::get_singleton()->query_body_direct_state(query,get_rid());
|
||||
Physics2DServer::get_singleton()->body_set_force_integration_callback(get_rid(),this,"_state_notify");
|
||||
|
||||
} else {
|
||||
memdelete( pre_xform );
|
||||
pre_xform=NULL;
|
||||
Physics2DServer::get_singleton()->body_set_force_integration_callback(get_rid(),NULL,StringName());
|
||||
pending=false;
|
||||
}
|
||||
}
|
||||
|
||||
bool StaticBody2D::is_simulating_motion() const {
|
||||
|
||||
return simulating_motion;
|
||||
}
|
||||
|
||||
|
||||
void StaticBody2D::set_friction(real_t p_friction){
|
||||
|
||||
ERR_FAIL_COND(p_friction<0 || p_friction>1);
|
||||
|
||||
friction=p_friction;
|
||||
Physics2DServer::get_singleton()->body_set_param(get_rid(),Physics2DServer::BODY_PARAM_FRICTION,friction);
|
||||
|
||||
}
|
||||
real_t StaticBody2D::get_friction() const{
|
||||
|
||||
return friction;
|
||||
}
|
||||
|
||||
void StaticBody2D::set_bounce(real_t p_bounce){
|
||||
|
||||
ERR_FAIL_COND(p_bounce<0 || p_bounce>1);
|
||||
|
||||
bounce=p_bounce;
|
||||
Physics2DServer::get_singleton()->body_set_param(get_rid(),Physics2DServer::BODY_PARAM_BOUNCE,bounce);
|
||||
|
||||
}
|
||||
real_t StaticBody2D::get_bounce() const{
|
||||
|
||||
return bounce;
|
||||
}
|
||||
|
||||
void StaticBody2D::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_simulate_motion","enabled"),&StaticBody2D::set_simulate_motion);
|
||||
ObjectTypeDB::bind_method(_MD("is_simulating_motion"),&StaticBody2D::is_simulating_motion);
|
||||
ObjectTypeDB::bind_method(_MD("_update_xform"),&StaticBody2D::_update_xform);
|
||||
ObjectTypeDB::bind_method(_MD("_state_notify"),&StaticBody2D::_state_notify);
|
||||
ObjectTypeDB::bind_method(_MD("set_constant_linear_velocity","vel"),&StaticBody2D::set_constant_linear_velocity);
|
||||
ObjectTypeDB::bind_method(_MD("set_constant_angular_velocity","vel"),&StaticBody2D::set_constant_angular_velocity);
|
||||
ObjectTypeDB::bind_method(_MD("get_constant_linear_velocity"),&StaticBody2D::get_constant_linear_velocity);
|
||||
ObjectTypeDB::bind_method(_MD("get_constant_angular_velocity"),&StaticBody2D::get_constant_angular_velocity);
|
||||
ObjectTypeDB::bind_method(_MD("set_friction","friction"),&StaticBody2D::set_friction);
|
||||
ObjectTypeDB::bind_method(_MD("get_friction"),&StaticBody2D::get_friction);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_bounce","bounce"),&StaticBody2D::set_bounce);
|
||||
ObjectTypeDB::bind_method(_MD("get_bounce"),&StaticBody2D::get_bounce);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"simulate_motion"),_SCS("set_simulate_motion"),_SCS("is_simulating_motion"));
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"constant_linear_velocity"),_SCS("set_constant_linear_velocity"),_SCS("get_constant_linear_velocity"));
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL,"constant_angular_velocity"),_SCS("set_constant_angular_velocity"),_SCS("get_constant_angular_velocity"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_friction"),_SCS("get_friction"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_bounce"),_SCS("get_bounce"));
|
||||
}
|
||||
|
||||
StaticBody2D::StaticBody2D() : PhysicsBody2D(Physics2DServer::BODY_MODE_STATIC) {
|
||||
|
||||
simulating_motion=false;
|
||||
pre_xform=NULL;
|
||||
setting=false;
|
||||
pending=false;
|
||||
constant_angular_velocity=0;
|
||||
bounce=0;
|
||||
friction=1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
StaticBody2D::~StaticBody2D() {
|
||||
|
||||
if (pre_xform)
|
||||
memdelete(pre_xform);
|
||||
//if (query.is_valid())
|
||||
// Physics2DServer::get_singleton()->free(query);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void RigidBody2D::_body_enter_scene(ObjectID p_id) {
|
||||
|
||||
Object *obj = ObjectDB::get_instance(p_id);
|
||||
Node *node = obj ? obj->cast_to<Node>() : NULL;
|
||||
ERR_FAIL_COND(!node);
|
||||
|
||||
Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.find(p_id);
|
||||
ERR_FAIL_COND(!E);
|
||||
ERR_FAIL_COND(E->get().in_scene);
|
||||
|
||||
E->get().in_scene=true;
|
||||
emit_signal(SceneStringNames::get_singleton()->body_enter,node);
|
||||
|
||||
for(int i=0;i<E->get().shapes.size();i++) {
|
||||
|
||||
emit_signal(SceneStringNames::get_singleton()->body_enter_shape,p_id,node,E->get().shapes[i].body_shape,E->get().shapes[i].local_shape);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RigidBody2D::_body_exit_scene(ObjectID p_id) {
|
||||
|
||||
Object *obj = ObjectDB::get_instance(p_id);
|
||||
Node *node = obj ? obj->cast_to<Node>() : NULL;
|
||||
ERR_FAIL_COND(!node);
|
||||
Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.find(p_id);
|
||||
ERR_FAIL_COND(!E);
|
||||
ERR_FAIL_COND(!E->get().in_scene);
|
||||
E->get().in_scene=false;
|
||||
emit_signal(SceneStringNames::get_singleton()->body_exit,node);
|
||||
for(int i=0;i<E->get().shapes.size();i++) {
|
||||
|
||||
emit_signal(SceneStringNames::get_singleton()->body_exit_shape,p_id,node,E->get().shapes[i].body_shape,E->get().shapes[i].local_shape);
|
||||
}
|
||||
}
|
||||
|
||||
void RigidBody2D::_body_inout(int p_status, ObjectID p_instance, int p_body_shape,int p_local_shape) {
|
||||
|
||||
bool body_in = p_status==1;
|
||||
ObjectID objid=p_instance;
|
||||
|
||||
Object *obj = ObjectDB::get_instance(objid);
|
||||
Node *node = obj ? obj->cast_to<Node>() : NULL;
|
||||
|
||||
Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.find(objid);
|
||||
|
||||
ERR_FAIL_COND(!body_in && !E);
|
||||
|
||||
if (body_in) {
|
||||
if (!E) {
|
||||
|
||||
E = contact_monitor->body_map.insert(objid,BodyState());
|
||||
E->get().rc=0;
|
||||
E->get().in_scene=node && node->is_inside_scene();
|
||||
if (node) {
|
||||
node->connect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene,make_binds(objid));
|
||||
node->connect(SceneStringNames::get_singleton()->exit_scene,this,SceneStringNames::get_singleton()->_body_exit_scene,make_binds(objid));
|
||||
if (E->get().in_scene) {
|
||||
emit_signal(SceneStringNames::get_singleton()->body_enter,node);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
E->get().rc++;
|
||||
if (node)
|
||||
E->get().shapes.insert(ShapePair(p_body_shape,p_local_shape));
|
||||
|
||||
|
||||
if (E->get().in_scene) {
|
||||
emit_signal(SceneStringNames::get_singleton()->body_enter_shape,objid,node,p_body_shape,p_local_shape);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
E->get().rc--;
|
||||
|
||||
if (node)
|
||||
E->get().shapes.erase(ShapePair(p_body_shape,p_local_shape));
|
||||
|
||||
if (E->get().rc==0) {
|
||||
|
||||
if (node) {
|
||||
node->disconnect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene);
|
||||
node->disconnect(SceneStringNames::get_singleton()->exit_scene,this,SceneStringNames::get_singleton()->_body_exit_scene);
|
||||
if (E->get().in_scene)
|
||||
emit_signal(SceneStringNames::get_singleton()->body_exit,obj);
|
||||
|
||||
}
|
||||
|
||||
contact_monitor->body_map.erase(E);
|
||||
}
|
||||
if (node && E->get().in_scene) {
|
||||
emit_signal(SceneStringNames::get_singleton()->body_exit_shape,objid,obj,p_body_shape,p_local_shape);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
struct _RigidBody2DInOut {
|
||||
|
||||
ObjectID id;
|
||||
int shape;
|
||||
int local_shape;
|
||||
};
|
||||
|
||||
void RigidBody2D::_direct_state_changed(Object *p_state) {
|
||||
|
||||
//eh.. fuck
|
||||
#ifdef DEBUG_ENABLED
|
||||
|
||||
state=p_state->cast_to<Physics2DDirectBodyState>();
|
||||
#else
|
||||
state=(Physics2DDirectBodyState*)p_state; //trust it
|
||||
#endif
|
||||
|
||||
if (contact_monitor) {
|
||||
|
||||
//untag all
|
||||
int rc=0;
|
||||
for( Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.front();E;E=E->next()) {
|
||||
|
||||
for(int i=0;i<E->get().shapes.size();i++) {
|
||||
|
||||
E->get().shapes[i].tagged=false;
|
||||
rc++;
|
||||
}
|
||||
}
|
||||
|
||||
_RigidBody2DInOut *toadd=(_RigidBody2DInOut*)alloca(state->get_contact_count()*sizeof(_RigidBody2DInOut));
|
||||
int toadd_count=0;//state->get_contact_count();
|
||||
RigidBody2D_RemoveAction *toremove=(RigidBody2D_RemoveAction*)alloca(rc*sizeof(RigidBody2D_RemoveAction));
|
||||
int toremove_count=0;
|
||||
|
||||
//put the ones to add
|
||||
|
||||
for(int i=0;i<state->get_contact_count();i++) {
|
||||
|
||||
ObjectID obj = state->get_contact_collider_id(i);
|
||||
int local_shape = state->get_contact_local_shape(i);
|
||||
int shape = state->get_contact_collider_shape(i);
|
||||
toadd[i].local_shape=local_shape;
|
||||
toadd[i].id=obj;
|
||||
toadd[i].shape=shape;
|
||||
|
||||
bool found=false;
|
||||
|
||||
Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.find(obj);
|
||||
if (!E) {
|
||||
toadd_count++;
|
||||
continue;
|
||||
}
|
||||
|
||||
ShapePair sp( shape,local_shape );
|
||||
int idx = E->get().shapes.find(sp);
|
||||
if (idx==-1) {
|
||||
|
||||
toadd_count++;
|
||||
continue;
|
||||
}
|
||||
|
||||
E->get().shapes[idx].tagged=true;
|
||||
}
|
||||
|
||||
//put the ones to remove
|
||||
|
||||
for( Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.front();E;E=E->next()) {
|
||||
|
||||
for(int i=0;i<E->get().shapes.size();i++) {
|
||||
|
||||
if (!E->get().shapes[i].tagged) {
|
||||
|
||||
toremove[toremove_count].body_id=E->key();
|
||||
toremove[toremove_count].pair=E->get().shapes[i];
|
||||
toremove_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//process remotions
|
||||
|
||||
for(int i=0;i<toremove_count;i++) {
|
||||
|
||||
_body_inout(0,toremove[i].body_id,toremove[i].pair.body_shape,toremove[i].pair.local_shape);
|
||||
}
|
||||
|
||||
//process aditions
|
||||
|
||||
for(int i=0;i<toadd_count;i++) {
|
||||
|
||||
_body_inout(1,toadd[i].id,toadd[i].shape,toadd[i].local_shape);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
set_block_transform_notify(true); // don't want notify (would feedback loop)
|
||||
set_global_transform(state->get_transform());
|
||||
linear_velocity=state->get_linear_velocity();
|
||||
angular_velocity=state->get_angular_velocity();
|
||||
active=!state->is_sleeping();
|
||||
if (get_script_instance())
|
||||
get_script_instance()->call("_integrate_forces",state);
|
||||
set_block_transform_notify(false); // want it back
|
||||
|
||||
state=NULL;
|
||||
}
|
||||
|
||||
void RigidBody2D::_notification(int p_what) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
void RigidBody2D::set_mode(Mode p_mode) {
|
||||
|
||||
mode=p_mode;
|
||||
switch(p_mode) {
|
||||
|
||||
case MODE_RIGID: {
|
||||
|
||||
Physics2DServer::get_singleton()->body_set_mode(get_rid(),Physics2DServer::BODY_MODE_RIGID);
|
||||
} break;
|
||||
case MODE_STATIC: {
|
||||
|
||||
Physics2DServer::get_singleton()->body_set_mode(get_rid(),Physics2DServer::BODY_MODE_STATIC);
|
||||
|
||||
} break;
|
||||
case MODE_STATIC_ACTIVE: {
|
||||
|
||||
Physics2DServer::get_singleton()->body_set_mode(get_rid(),Physics2DServer::BODY_MODE_STATIC_ACTIVE);
|
||||
|
||||
} break;
|
||||
case MODE_CHARACTER: {
|
||||
Physics2DServer::get_singleton()->body_set_mode(get_rid(),Physics2DServer::BODY_MODE_CHARACTER);
|
||||
|
||||
} break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
RigidBody2D::Mode RigidBody2D::get_mode() const{
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
void RigidBody2D::set_mass(real_t p_mass){
|
||||
|
||||
ERR_FAIL_COND(p_mass<=0);
|
||||
mass=p_mass;
|
||||
_change_notify("mass");
|
||||
_change_notify("weight");
|
||||
Physics2DServer::get_singleton()->body_set_param(get_rid(),Physics2DServer::BODY_PARAM_MASS,mass);
|
||||
|
||||
}
|
||||
real_t RigidBody2D::get_mass() const{
|
||||
|
||||
return mass;
|
||||
}
|
||||
|
||||
void RigidBody2D::set_weight(real_t p_weight){
|
||||
|
||||
set_mass(p_weight/9.8);
|
||||
}
|
||||
real_t RigidBody2D::get_weight() const{
|
||||
|
||||
return mass*9.8;
|
||||
}
|
||||
|
||||
|
||||
void RigidBody2D::set_friction(real_t p_friction){
|
||||
|
||||
ERR_FAIL_COND(p_friction<0 || p_friction>1);
|
||||
|
||||
friction=p_friction;
|
||||
Physics2DServer::get_singleton()->body_set_param(get_rid(),Physics2DServer::BODY_PARAM_FRICTION,friction);
|
||||
|
||||
}
|
||||
real_t RigidBody2D::get_friction() const{
|
||||
|
||||
return friction;
|
||||
}
|
||||
|
||||
void RigidBody2D::set_bounce(real_t p_bounce){
|
||||
|
||||
ERR_FAIL_COND(p_bounce<0 || p_bounce>1);
|
||||
|
||||
bounce=p_bounce;
|
||||
Physics2DServer::get_singleton()->body_set_param(get_rid(),Physics2DServer::BODY_PARAM_BOUNCE,bounce);
|
||||
|
||||
}
|
||||
real_t RigidBody2D::get_bounce() const{
|
||||
|
||||
return bounce;
|
||||
}
|
||||
|
||||
void RigidBody2D::set_axis_velocity(const Vector2& p_axis) {
|
||||
|
||||
Vector2 v = state? state->get_linear_velocity() : linear_velocity;
|
||||
Vector2 axis = p_axis.normalized();
|
||||
v-=axis*axis.dot(v);
|
||||
v+=p_axis;
|
||||
if (state) {
|
||||
set_linear_velocity(v);
|
||||
} else {
|
||||
Physics2DServer::get_singleton()->body_set_axis_velocity(get_rid(),p_axis);
|
||||
linear_velocity=v;
|
||||
}
|
||||
}
|
||||
|
||||
void RigidBody2D::set_linear_velocity(const Vector2& p_velocity){
|
||||
|
||||
linear_velocity=p_velocity;
|
||||
if (state)
|
||||
state->set_linear_velocity(linear_velocity);
|
||||
else {
|
||||
|
||||
Physics2DServer::get_singleton()->body_set_state(get_rid(),Physics2DServer::BODY_STATE_LINEAR_VELOCITY,linear_velocity);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Vector2 RigidBody2D::get_linear_velocity() const{
|
||||
|
||||
return linear_velocity;
|
||||
}
|
||||
|
||||
void RigidBody2D::set_angular_velocity(real_t p_velocity){
|
||||
|
||||
angular_velocity=p_velocity;
|
||||
if (state)
|
||||
state->set_angular_velocity(angular_velocity);
|
||||
else
|
||||
Physics2DServer::get_singleton()->body_set_state(get_rid(),Physics2DServer::BODY_STATE_ANGULAR_VELOCITY,angular_velocity);
|
||||
}
|
||||
real_t RigidBody2D::get_angular_velocity() const{
|
||||
|
||||
return angular_velocity;
|
||||
}
|
||||
|
||||
void RigidBody2D::set_use_custom_integrator(bool p_enable){
|
||||
|
||||
if (custom_integrator==p_enable)
|
||||
return;
|
||||
|
||||
custom_integrator=p_enable;
|
||||
Physics2DServer::get_singleton()->body_set_omit_force_integration(get_rid(),p_enable);
|
||||
|
||||
|
||||
}
|
||||
bool RigidBody2D::is_using_custom_integrator(){
|
||||
|
||||
return custom_integrator;
|
||||
}
|
||||
|
||||
void RigidBody2D::set_active(bool p_active) {
|
||||
|
||||
active=p_active;
|
||||
Physics2DServer::get_singleton()->body_set_state(get_rid(),Physics2DServer::BODY_STATE_SLEEPING,!active);
|
||||
|
||||
}
|
||||
|
||||
void RigidBody2D::set_can_sleep(bool p_active) {
|
||||
|
||||
can_sleep=p_active;
|
||||
Physics2DServer::get_singleton()->body_set_state(get_rid(),Physics2DServer::BODY_STATE_CAN_SLEEP,p_active);
|
||||
}
|
||||
|
||||
bool RigidBody2D::is_able_to_sleep() const {
|
||||
|
||||
return can_sleep;
|
||||
}
|
||||
|
||||
bool RigidBody2D::is_active() const {
|
||||
|
||||
return active;
|
||||
}
|
||||
|
||||
void RigidBody2D::set_max_contacts_reported(int p_amount) {
|
||||
|
||||
max_contacts_reported=p_amount;
|
||||
Physics2DServer::get_singleton()->body_set_max_contacts_reported(get_rid(),p_amount);
|
||||
}
|
||||
|
||||
int RigidBody2D::get_max_contacts_reported() const{
|
||||
|
||||
return max_contacts_reported;
|
||||
}
|
||||
|
||||
void RigidBody2D::apply_impulse(const Vector2& p_pos, const Vector2& p_impulse) {
|
||||
|
||||
Physics2DServer::get_singleton()->body_apply_impulse(get_rid(),p_pos,p_impulse);
|
||||
}
|
||||
|
||||
void RigidBody2D::set_applied_force(const Vector2& p_force) {
|
||||
|
||||
Physics2DServer::get_singleton()->body_set_applied_force(get_rid(), p_force);
|
||||
};
|
||||
|
||||
Vector2 RigidBody2D::get_applied_force() const {
|
||||
|
||||
return Physics2DServer::get_singleton()->body_get_applied_force(get_rid());
|
||||
};
|
||||
|
||||
void RigidBody2D::set_use_continuous_collision_detection(bool p_enable) {
|
||||
|
||||
ccd=p_enable;
|
||||
Physics2DServer::get_singleton()->body_set_enable_continuous_collision_detection(get_rid(),p_enable);
|
||||
}
|
||||
|
||||
bool RigidBody2D::is_using_continuous_collision_detection() const {
|
||||
|
||||
|
||||
return ccd;
|
||||
}
|
||||
|
||||
|
||||
void RigidBody2D::set_contact_monitor(bool p_enabled) {
|
||||
|
||||
if (p_enabled==is_contact_monitor_enabled())
|
||||
return;
|
||||
|
||||
if (!p_enabled) {
|
||||
|
||||
for(Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.front();E;E=E->next()) {
|
||||
|
||||
//clean up mess
|
||||
}
|
||||
|
||||
memdelete( contact_monitor );
|
||||
contact_monitor=NULL;
|
||||
} else {
|
||||
|
||||
contact_monitor = memnew( ContactMonitor );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool RigidBody2D::is_contact_monitor_enabled() const {
|
||||
|
||||
return contact_monitor!=NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void RigidBody2D::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_mode","mode"),&RigidBody2D::set_mode);
|
||||
ObjectTypeDB::bind_method(_MD("get_mode"),&RigidBody2D::get_mode);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_mass","mass"),&RigidBody2D::set_mass);
|
||||
ObjectTypeDB::bind_method(_MD("get_mass"),&RigidBody2D::get_mass);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_weight","weight"),&RigidBody2D::set_weight);
|
||||
ObjectTypeDB::bind_method(_MD("get_weight"),&RigidBody2D::get_weight);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_friction","friction"),&RigidBody2D::set_friction);
|
||||
ObjectTypeDB::bind_method(_MD("get_friction"),&RigidBody2D::get_friction);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_bounce","bounce"),&RigidBody2D::set_bounce);
|
||||
ObjectTypeDB::bind_method(_MD("get_bounce"),&RigidBody2D::get_bounce);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_linear_velocity","linear_velocity"),&RigidBody2D::set_linear_velocity);
|
||||
ObjectTypeDB::bind_method(_MD("get_linear_velocity"),&RigidBody2D::get_linear_velocity);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_angular_velocity","angular_velocity"),&RigidBody2D::set_angular_velocity);
|
||||
ObjectTypeDB::bind_method(_MD("get_angular_velocity"),&RigidBody2D::get_angular_velocity);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_max_contacts_reported","amount"),&RigidBody2D::set_max_contacts_reported);
|
||||
ObjectTypeDB::bind_method(_MD("get_max_contacts_reported"),&RigidBody2D::get_max_contacts_reported);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_use_custom_integrator","enable"),&RigidBody2D::set_use_custom_integrator);
|
||||
ObjectTypeDB::bind_method(_MD("is_using_custom_integrator"),&RigidBody2D::is_using_custom_integrator);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_contact_monitor","enabled"),&RigidBody2D::set_contact_monitor);
|
||||
ObjectTypeDB::bind_method(_MD("is_contact_monitor_enabled"),&RigidBody2D::is_contact_monitor_enabled);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_use_continuous_collision_detection","enable"),&RigidBody2D::set_use_continuous_collision_detection);
|
||||
ObjectTypeDB::bind_method(_MD("is_using_continuous_collision_detection"),&RigidBody2D::is_using_continuous_collision_detection);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_axis_velocity","axis_velocity"),&RigidBody2D::set_axis_velocity);
|
||||
ObjectTypeDB::bind_method(_MD("apply_impulse","pos","impulse"),&RigidBody2D::apply_impulse);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_applied_force","force"),&RigidBody2D::set_applied_force);
|
||||
ObjectTypeDB::bind_method(_MD("get_applied_force"),&RigidBody2D::get_applied_force);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_active","active"),&RigidBody2D::set_active);
|
||||
ObjectTypeDB::bind_method(_MD("is_active"),&RigidBody2D::is_active);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_can_sleep","able_to_sleep"),&RigidBody2D::set_can_sleep);
|
||||
ObjectTypeDB::bind_method(_MD("is_able_to_sleep"),&RigidBody2D::is_able_to_sleep);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_direct_state_changed"),&RigidBody2D::_direct_state_changed);
|
||||
ObjectTypeDB::bind_method(_MD("_body_enter_scene"),&RigidBody2D::_body_enter_scene);
|
||||
ObjectTypeDB::bind_method(_MD("_body_exit_scene"),&RigidBody2D::_body_exit_scene);
|
||||
|
||||
BIND_VMETHOD(MethodInfo("_integrate_forces",PropertyInfo(Variant::OBJECT,"state:Physics2DDirectBodyState")));
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Rigid,Static,Character,Static Active"),_SCS("set_mode"),_SCS("get_mode"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"mass",PROPERTY_HINT_EXP_RANGE,"0.01,65535,0.01"),_SCS("set_mass"),_SCS("get_mass"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"weight",PROPERTY_HINT_EXP_RANGE,"0.01,65535,0.01",PROPERTY_USAGE_EDITOR),_SCS("set_weight"),_SCS("get_weight"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_friction"),_SCS("get_friction"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_bounce"),_SCS("get_bounce"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"custom_integrator"),_SCS("set_use_custom_integrator"),_SCS("is_using_custom_integrator"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"continuous_cd"),_SCS("set_use_continuous_collision_detection"),_SCS("is_using_continuous_collision_detection"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"contacts_reported"),_SCS("set_max_contacts_reported"),_SCS("get_max_contacts_reported"));
|
||||
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::VECTOR2,"velocity/linear"),_SCS("set_linear_velocity"),_SCS("get_linear_velocity"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"velocity/angular"),_SCS("set_angular_velocity"),_SCS("get_angular_velocity"));
|
||||
|
||||
ADD_SIGNAL( MethodInfo("body_enter_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"local_shape")));
|
||||
ADD_SIGNAL( MethodInfo("body_exit_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"local_shape")));
|
||||
ADD_SIGNAL( MethodInfo("body_enter",PropertyInfo(Variant::OBJECT,"body")));
|
||||
ADD_SIGNAL( MethodInfo("body_exit",PropertyInfo(Variant::OBJECT,"body")));
|
||||
|
||||
BIND_CONSTANT( MODE_STATIC );
|
||||
BIND_CONSTANT( MODE_STATIC_ACTIVE );
|
||||
BIND_CONSTANT( MODE_RIGID );
|
||||
BIND_CONSTANT( MODE_CHARACTER );
|
||||
}
|
||||
|
||||
RigidBody2D::RigidBody2D() : PhysicsBody2D(Physics2DServer::BODY_MODE_RIGID) {
|
||||
|
||||
mode=MODE_RIGID;
|
||||
|
||||
bounce=0;
|
||||
mass=1;
|
||||
friction=1;
|
||||
max_contacts_reported=0;
|
||||
state=NULL;
|
||||
|
||||
angular_velocity=0;
|
||||
active=true;
|
||||
ccd=false;
|
||||
|
||||
custom_integrator=false;
|
||||
contact_monitor=NULL;
|
||||
can_sleep=true;
|
||||
|
||||
Physics2DServer::get_singleton()->body_set_force_integration_callback(get_rid(),this,"_direct_state_changed");
|
||||
}
|
||||
|
||||
RigidBody2D::~RigidBody2D() {
|
||||
|
||||
if (contact_monitor)
|
||||
memdelete( contact_monitor );
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
232
scene/2d/physics_body_2d.h
Normal file
232
scene/2d/physics_body_2d.h
Normal file
@ -0,0 +1,232 @@
|
||||
/*************************************************************************/
|
||||
/* physics_body_2d.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef PHYSICS_BODY_2D_H
|
||||
#define PHYSICS_BODY_2D_H
|
||||
|
||||
#include "scene/2d/collision_object_2d.h"
|
||||
#include "servers/physics_2d_server.h"
|
||||
#include "vset.h"
|
||||
|
||||
|
||||
class PhysicsBody2D : public CollisionObject2D {
|
||||
|
||||
OBJ_TYPE(PhysicsBody2D,CollisionObject2D);
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
PhysicsBody2D(Physics2DServer::BodyMode p_mode);
|
||||
public:
|
||||
|
||||
PhysicsBody2D();
|
||||
|
||||
};
|
||||
|
||||
class StaticBody2D : public PhysicsBody2D {
|
||||
|
||||
OBJ_TYPE(StaticBody2D,PhysicsBody2D);
|
||||
|
||||
Matrix32 *pre_xform;
|
||||
//RID query;
|
||||
bool setting;
|
||||
bool pending;
|
||||
bool simulating_motion;
|
||||
Vector2 constant_linear_velocity;
|
||||
real_t constant_angular_velocity;
|
||||
void _update_xform();
|
||||
void _state_notify(Object *p_object);
|
||||
|
||||
real_t bounce;
|
||||
real_t friction;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
void set_friction(real_t p_friction);
|
||||
real_t get_friction() const;
|
||||
|
||||
void set_bounce(real_t p_bounce);
|
||||
real_t get_bounce() const;
|
||||
|
||||
void set_simulate_motion(bool p_enable);
|
||||
bool is_simulating_motion() const;
|
||||
|
||||
void set_constant_linear_velocity(const Vector2& p_vel);
|
||||
void set_constant_angular_velocity(real_t p_vel);
|
||||
|
||||
Vector2 get_constant_linear_velocity() const;
|
||||
real_t get_constant_angular_velocity() const;
|
||||
|
||||
StaticBody2D();
|
||||
~StaticBody2D();
|
||||
|
||||
};
|
||||
|
||||
class RigidBody2D : public PhysicsBody2D {
|
||||
|
||||
OBJ_TYPE(RigidBody2D,PhysicsBody2D);
|
||||
public:
|
||||
|
||||
enum Mode {
|
||||
MODE_RIGID,
|
||||
MODE_STATIC,
|
||||
MODE_CHARACTER,
|
||||
MODE_STATIC_ACTIVE,
|
||||
};
|
||||
private:
|
||||
|
||||
bool can_sleep;
|
||||
Physics2DDirectBodyState *state;
|
||||
Mode mode;
|
||||
|
||||
real_t bounce;
|
||||
real_t mass;
|
||||
real_t friction;
|
||||
|
||||
Vector2 linear_velocity;
|
||||
real_t angular_velocity;
|
||||
bool active;
|
||||
bool ccd;
|
||||
|
||||
|
||||
int max_contacts_reported;
|
||||
|
||||
bool custom_integrator;
|
||||
|
||||
|
||||
struct ShapePair {
|
||||
|
||||
int body_shape;
|
||||
int local_shape;
|
||||
bool tagged;
|
||||
bool operator<(const ShapePair& p_sp) const {
|
||||
if (body_shape==p_sp.body_shape)
|
||||
return local_shape < p_sp.local_shape;
|
||||
else
|
||||
return body_shape < p_sp.body_shape;
|
||||
}
|
||||
|
||||
ShapePair() {}
|
||||
ShapePair(int p_bs, int p_ls) { body_shape=p_bs; local_shape=p_ls; }
|
||||
};
|
||||
struct RigidBody2D_RemoveAction {
|
||||
|
||||
|
||||
ObjectID body_id;
|
||||
ShapePair pair;
|
||||
|
||||
};
|
||||
struct BodyState {
|
||||
|
||||
int rc;
|
||||
bool in_scene;
|
||||
VSet<ShapePair> shapes;
|
||||
};
|
||||
|
||||
struct ContactMonitor {
|
||||
|
||||
|
||||
Map<ObjectID,BodyState> body_map;
|
||||
|
||||
};
|
||||
|
||||
|
||||
ContactMonitor *contact_monitor;
|
||||
void _body_enter_scene(ObjectID p_id);
|
||||
void _body_exit_scene(ObjectID p_id);
|
||||
|
||||
|
||||
void _body_inout(int p_status, ObjectID p_instance, int p_body_shape,int p_local_shape);
|
||||
void _direct_state_changed(Object *p_state);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_mode(Mode p_mode);
|
||||
Mode get_mode() const;
|
||||
|
||||
void set_mass(real_t p_mass);
|
||||
real_t get_mass() const;
|
||||
|
||||
void set_weight(real_t p_weight);
|
||||
real_t get_weight() const;
|
||||
|
||||
void set_friction(real_t p_friction);
|
||||
real_t get_friction() const;
|
||||
|
||||
void set_bounce(real_t p_bounce);
|
||||
real_t get_bounce() const;
|
||||
|
||||
void set_linear_velocity(const Vector2& p_velocity);
|
||||
Vector2 get_linear_velocity() const;
|
||||
|
||||
void set_axis_velocity(const Vector2& p_axis);
|
||||
|
||||
void set_angular_velocity(real_t p_velocity);
|
||||
real_t get_angular_velocity() const;
|
||||
|
||||
void set_use_custom_integrator(bool p_enable);
|
||||
bool is_using_custom_integrator();
|
||||
|
||||
void set_active(bool p_active);
|
||||
bool is_active() const;
|
||||
|
||||
void set_can_sleep(bool p_active);
|
||||
bool is_able_to_sleep() const;
|
||||
|
||||
void set_contact_monitor(bool p_enabled);
|
||||
bool is_contact_monitor_enabled() const;
|
||||
|
||||
void set_max_contacts_reported(int p_amount);
|
||||
int get_max_contacts_reported() const;
|
||||
|
||||
void set_use_continuous_collision_detection(bool p_enable);
|
||||
bool is_using_continuous_collision_detection() const;
|
||||
|
||||
void apply_impulse(const Vector2& p_pos, const Vector2& p_impulse);
|
||||
|
||||
void set_applied_force(const Vector2& p_force);
|
||||
Vector2 get_applied_force() const;
|
||||
|
||||
RigidBody2D();
|
||||
~RigidBody2D();
|
||||
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(RigidBody2D::Mode);
|
||||
#endif // PHYSICS_BODY_2D_H
|
||||
65
scene/2d/position_2d.cpp
Normal file
65
scene/2d/position_2d.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
/*************************************************************************/
|
||||
/* position_2d.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "position_2d.h"
|
||||
#include "scene/resources/texture.h"
|
||||
|
||||
void Position2D::_draw_cross() {
|
||||
|
||||
draw_line(Point2(-10,0),Point2(+10,0),Color(1,0.5,0.5));
|
||||
draw_line(Point2(0,-10),Point2(0,+10),Color(0.5,1,0.5));
|
||||
|
||||
}
|
||||
|
||||
Rect2 Position2D::get_item_rect() const {
|
||||
|
||||
return Rect2(Point2(-10,-10),Size2(20,20));
|
||||
}
|
||||
|
||||
void Position2D::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_ENTER_SCENE: {
|
||||
|
||||
update();
|
||||
} break;
|
||||
case NOTIFICATION_DRAW: {
|
||||
if (!is_inside_scene())
|
||||
break;
|
||||
if (get_scene()->is_editor_hint())
|
||||
_draw_cross();
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Position2D::Position2D()
|
||||
{
|
||||
}
|
||||
49
scene/2d/position_2d.h
Normal file
49
scene/2d/position_2d.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*************************************************************************/
|
||||
/* position_2d.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef POSITION_2D_H
|
||||
#define POSITION_2D_H
|
||||
|
||||
|
||||
#include "scene/2d/node_2d.h"
|
||||
|
||||
class Position2D : public Node2D {
|
||||
|
||||
OBJ_TYPE(Position2D,Node2D)
|
||||
|
||||
void _draw_cross();
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
public:
|
||||
|
||||
virtual Rect2 get_item_rect() const;
|
||||
Position2D();
|
||||
};
|
||||
|
||||
#endif // POSITION_2D_H
|
||||
198
scene/2d/ray_cast_2d.cpp
Normal file
198
scene/2d/ray_cast_2d.cpp
Normal file
@ -0,0 +1,198 @@
|
||||
/*************************************************************************/
|
||||
/* ray_cast_2d.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "ray_cast_2d.h"
|
||||
#include "servers/physics_2d_server.h"
|
||||
|
||||
void RayCast2D::set_cast_to(const Vector2& p_point) {
|
||||
|
||||
cast_to=p_point;
|
||||
if (is_inside_scene() && get_scene()->is_editor_hint())
|
||||
update();
|
||||
|
||||
}
|
||||
|
||||
Vector2 RayCast2D::get_cast_to() const{
|
||||
|
||||
return cast_to;
|
||||
}
|
||||
|
||||
bool RayCast2D::is_colliding() const{
|
||||
|
||||
return collided;
|
||||
}
|
||||
Object *RayCast2D::get_collider() const{
|
||||
|
||||
if (against==0)
|
||||
return NULL;
|
||||
|
||||
return ObjectDB::get_instance(against);
|
||||
}
|
||||
|
||||
int RayCast2D::get_collider_shape() const {
|
||||
|
||||
return against_shape;
|
||||
}
|
||||
Vector2 RayCast2D::get_collision_point() const{
|
||||
|
||||
return collision_point;
|
||||
}
|
||||
Vector2 RayCast2D::get_collision_normal() const{
|
||||
|
||||
return collision_normal;
|
||||
}
|
||||
|
||||
|
||||
void RayCast2D::set_enabled(bool p_enabled) {
|
||||
|
||||
enabled=p_enabled;
|
||||
if (is_inside_scene() && !get_scene()->is_editor_hint())
|
||||
set_fixed_process(p_enabled);
|
||||
if (!p_enabled)
|
||||
collided=false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool RayCast2D::is_enabled() const {
|
||||
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
|
||||
void RayCast2D::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_ENTER_SCENE: {
|
||||
|
||||
if (enabled && !get_scene()->is_editor_hint())
|
||||
set_fixed_process(true);
|
||||
else
|
||||
set_fixed_process(false);
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_SCENE: {
|
||||
|
||||
if (enabled)
|
||||
set_fixed_process(false);
|
||||
|
||||
} break;
|
||||
#ifdef TOOLS_ENABLED
|
||||
case NOTIFICATION_DRAW: {
|
||||
|
||||
if (!get_scene()->is_editor_hint())
|
||||
break;
|
||||
Matrix32 xf;
|
||||
xf.rotate(cast_to.atan2());
|
||||
xf.translate(Vector2(0,cast_to.length()));
|
||||
|
||||
//Vector2 tip = Vector2(0,s->get_length());
|
||||
Color dcol(0.9,0.2,0.2,0.4);
|
||||
draw_line(Vector2(),cast_to,dcol,3);
|
||||
Vector<Vector2> pts;
|
||||
float tsize=4;
|
||||
pts.push_back(xf.xform(Vector2(0,tsize)));
|
||||
pts.push_back(xf.xform(Vector2(0.707*tsize,0)));
|
||||
pts.push_back(xf.xform(Vector2(-0.707*tsize,0)));
|
||||
Vector<Color> cols;
|
||||
for(int i=0;i<3;i++)
|
||||
cols.push_back(dcol);
|
||||
|
||||
draw_primitive(pts,cols,Vector<Vector2>()); //small arrow
|
||||
|
||||
} break;
|
||||
#endif
|
||||
|
||||
case NOTIFICATION_FIXED_PROCESS: {
|
||||
|
||||
if (!enabled)
|
||||
break;
|
||||
|
||||
|
||||
|
||||
Ref<World2D> w2d = get_world_2d();
|
||||
ERR_BREAK( w2d.is_null() );
|
||||
|
||||
Physics2DDirectSpaceState *dss = Physics2DServer::get_singleton()->space_get_direct_state(w2d->get_space());
|
||||
ERR_BREAK( !dss );
|
||||
|
||||
Matrix32 gt = get_global_transform();
|
||||
|
||||
Vector2 to = cast_to;
|
||||
if (to==Vector2())
|
||||
to=Vector2(0,0.01);
|
||||
|
||||
Physics2DDirectSpaceState::RayResult rr;
|
||||
|
||||
if (dss->intersect_ray(gt.get_origin(),gt.xform(to),rr)) {
|
||||
|
||||
collided=true;
|
||||
against=rr.collider_id;
|
||||
collision_point=rr.position;
|
||||
collision_normal=rr.normal;
|
||||
against_shape=rr.shape;
|
||||
} else {
|
||||
collided=false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void RayCast2D::_bind_methods() {
|
||||
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_enabled","enabled"),&RayCast2D::set_enabled);
|
||||
ObjectTypeDB::bind_method(_MD("is_enabled"),&RayCast2D::is_enabled);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_cast_to","local_point"),&RayCast2D::set_cast_to);
|
||||
ObjectTypeDB::bind_method(_MD("get_cast_to"),&RayCast2D::get_cast_to);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("is_colliding"),&RayCast2D::is_colliding);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("get_collider"),&RayCast2D::get_collider);
|
||||
ObjectTypeDB::bind_method(_MD("get_collider_shape"),&RayCast2D::get_collider_shape);
|
||||
ObjectTypeDB::bind_method(_MD("get_collision_point"),&RayCast2D::get_collision_point);
|
||||
ObjectTypeDB::bind_method(_MD("get_collision_normal"),&RayCast2D::get_collision_normal);
|
||||
|
||||
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"));
|
||||
}
|
||||
|
||||
RayCast2D::RayCast2D() {
|
||||
|
||||
enabled=false;
|
||||
against=0;
|
||||
collided=false;
|
||||
against_shape=0;
|
||||
cast_to=Vector2(0,50);
|
||||
}
|
||||
68
scene/2d/ray_cast_2d.h
Normal file
68
scene/2d/ray_cast_2d.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*************************************************************************/
|
||||
/* ray_cast_2d.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef RAY_CAST_2D_H
|
||||
#define RAY_CAST_2D_H
|
||||
|
||||
#include "scene/2d/node_2d.h"
|
||||
|
||||
class RayCast2D : public Node2D {
|
||||
|
||||
OBJ_TYPE(RayCast2D,Node2D);
|
||||
|
||||
|
||||
bool enabled;
|
||||
bool collided;
|
||||
ObjectID against;
|
||||
int against_shape;
|
||||
Vector2 collision_point;
|
||||
Vector2 collision_normal;
|
||||
|
||||
Vector2 cast_to;
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_enabled(bool p_enabled);
|
||||
bool is_enabled() const;
|
||||
|
||||
void set_cast_to(const Vector2& p_point);
|
||||
Vector2 get_cast_to() const;
|
||||
|
||||
bool is_colliding() const;
|
||||
Object *get_collider() const;
|
||||
int get_collider_shape() const;
|
||||
Vector2 get_collision_point() const;
|
||||
Vector2 get_collision_normal() const;
|
||||
|
||||
RayCast2D();
|
||||
};
|
||||
|
||||
#endif // RAY_CAST_2D_H
|
||||
122
scene/2d/remote_transform_2d.cpp
Normal file
122
scene/2d/remote_transform_2d.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
/*************************************************************************/
|
||||
/* remote_transform_2d.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "remote_transform_2d.h"
|
||||
#include "scene/scene_string_names.h"
|
||||
|
||||
void RemoteTransform2D::_update_cache() {
|
||||
|
||||
cache=0;
|
||||
if (has_node(remote_node)) {
|
||||
Node *node = get_node(remote_node);
|
||||
if (!node || this==node || node->is_a_parent_of(this) || this->is_a_parent_of(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
cache=node->get_instance_ID();
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteTransform2D::_update_remote() {
|
||||
|
||||
|
||||
if (!is_inside_scene())
|
||||
return;
|
||||
|
||||
if (!cache)
|
||||
return;
|
||||
|
||||
Object *obj = ObjectDB::get_instance(cache);
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
Node2D *n = obj->cast_to<Node2D>();
|
||||
if (!n)
|
||||
return;
|
||||
|
||||
if (!n->is_inside_scene())
|
||||
return;
|
||||
|
||||
//todo make faster
|
||||
n->set_global_transform(get_global_transform());
|
||||
|
||||
}
|
||||
|
||||
void RemoteTransform2D::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_READY: {
|
||||
|
||||
_update_cache();
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
if (!is_inside_scene())
|
||||
break;
|
||||
|
||||
if (cache) {
|
||||
|
||||
_update_remote();
|
||||
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RemoteTransform2D::set_remote_node(const NodePath& p_remote_node) {
|
||||
|
||||
remote_node=p_remote_node;
|
||||
if (is_inside_scene())
|
||||
_update_cache();
|
||||
}
|
||||
|
||||
NodePath RemoteTransform2D::get_remote_node() const{
|
||||
|
||||
return remote_node;
|
||||
}
|
||||
|
||||
|
||||
void RemoteTransform2D::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_remote_node","path"),&RemoteTransform2D::set_remote_node);
|
||||
ObjectTypeDB::bind_method(_MD("get_remote_node"),&RemoteTransform2D::get_remote_node);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::NODE_PATH,"remote_path"),_SCS("set_remote_node"),_SCS("get_remote_node"));
|
||||
}
|
||||
|
||||
RemoteTransform2D::RemoteTransform2D() {
|
||||
|
||||
cache=0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
52
scene/2d/remote_transform_2d.h
Normal file
52
scene/2d/remote_transform_2d.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*************************************************************************/
|
||||
/* remote_transform_2d.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "scene/2d/node_2d.h"
|
||||
|
||||
class RemoteTransform2D : public Node2D {
|
||||
|
||||
OBJ_TYPE(RemoteTransform2D,Node2D);
|
||||
|
||||
NodePath remote_node;
|
||||
|
||||
ObjectID cache;
|
||||
|
||||
void _update_remote();
|
||||
void _update_cache();
|
||||
void _node_exited_scene();
|
||||
protected:
|
||||
|
||||
static void _bind_methods();
|
||||
void _notification(int p_what);
|
||||
public:
|
||||
|
||||
void set_remote_node(const NodePath& p_remote_node);
|
||||
NodePath get_remote_node() const;
|
||||
|
||||
RemoteTransform2D();
|
||||
};
|
||||
252
scene/2d/sample_player_2d.cpp
Normal file
252
scene/2d/sample_player_2d.cpp
Normal file
@ -0,0 +1,252 @@
|
||||
/*************************************************************************/
|
||||
/* sample_player_2d.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "sample_player_2d.h"
|
||||
|
||||
#include "servers/audio_server.h"
|
||||
#include "servers/audio_server.h"
|
||||
#include "servers/spatial_sound_server.h"
|
||||
|
||||
|
||||
bool SamplePlayer2D::_set(const StringName& p_name, const Variant& p_value) {
|
||||
|
||||
String name=p_name;
|
||||
|
||||
if (name=="play/play") {
|
||||
if (library.is_valid()) {
|
||||
|
||||
String what=p_value;
|
||||
if (what=="")
|
||||
stop_all();
|
||||
else
|
||||
play(what);
|
||||
|
||||
played_back=what;
|
||||
}
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SamplePlayer2D::_get(const StringName& p_name,Variant &r_ret) const {
|
||||
|
||||
|
||||
String name=p_name;
|
||||
|
||||
if (name=="play/play") {
|
||||
r_ret=played_back;
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SamplePlayer2D::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||
|
||||
String en="";
|
||||
if (library.is_valid()) {
|
||||
List<StringName> samples;
|
||||
Ref<SampleLibrary> ncl=library;
|
||||
ncl->get_sample_list(&samples);
|
||||
for (List<StringName>::Element *E=samples.front();E;E=E->next()) {
|
||||
|
||||
en+=",";
|
||||
en+=E->get();
|
||||
}
|
||||
}
|
||||
|
||||
p_list->push_back( PropertyInfo( Variant::STRING, "play/play", PROPERTY_HINT_ENUM, en,PROPERTY_USAGE_EDITOR));
|
||||
}
|
||||
|
||||
void SamplePlayer2D::_notification(int p_what) {
|
||||
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_ENTER_SCENE: {
|
||||
|
||||
SpatialSound2DServer::get_singleton()->source_set_polyphony(get_source_rid(),polyphony);
|
||||
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SamplePlayer2D::set_sample_library(const Ref<SampleLibrary>& p_library) {
|
||||
|
||||
library=p_library;
|
||||
}
|
||||
|
||||
Ref<SampleLibrary> SamplePlayer2D::get_sample_library() const {
|
||||
|
||||
return library;
|
||||
}
|
||||
|
||||
void SamplePlayer2D::set_polyphony(int p_voice_count) {
|
||||
|
||||
ERR_FAIL_COND(p_voice_count<0 || p_voice_count>64);
|
||||
polyphony=p_voice_count;
|
||||
if (get_source_rid().is_valid())
|
||||
SpatialSound2DServer::get_singleton()->source_set_polyphony(get_source_rid(),polyphony);
|
||||
|
||||
}
|
||||
|
||||
int SamplePlayer2D::get_polyphony() const {
|
||||
|
||||
return polyphony;
|
||||
}
|
||||
|
||||
SamplePlayer2D::VoiceID SamplePlayer2D::play(const String& p_sample,int p_voice) {
|
||||
|
||||
if (!get_source_rid().is_valid())
|
||||
return INVALID_VOICE;
|
||||
if (library.is_null())
|
||||
return INVALID_VOICE;
|
||||
if (!library->has_sample(p_sample))
|
||||
return INVALID_VOICE;
|
||||
Ref<Sample> sample = library->get_sample(p_sample);
|
||||
float vol_change = library->sample_get_volume_db(p_sample);
|
||||
float pitch_change = library->sample_get_pitch_scale(p_sample);
|
||||
|
||||
VoiceID vid = SpatialSound2DServer::get_singleton()->source_play_sample(get_source_rid(),sample->get_rid(),sample->get_mix_rate()*pitch_change,p_voice);
|
||||
if (vol_change)
|
||||
SpatialSound2DServer::get_singleton()->source_voice_set_volume_scale_db(get_source_rid(),vid,vol_change);
|
||||
|
||||
|
||||
if (random_pitch_scale) {
|
||||
float ps = Math::random(-random_pitch_scale,random_pitch_scale);
|
||||
if (ps>0)
|
||||
ps=1.0+ps;
|
||||
else
|
||||
ps=1.0/(1.0-ps);
|
||||
SpatialSound2DServer::get_singleton()->source_voice_set_pitch_scale(get_source_rid(),vid,ps*pitch_change);
|
||||
|
||||
}
|
||||
|
||||
return vid;
|
||||
}
|
||||
//voices
|
||||
void SamplePlayer2D::voice_set_pitch_scale(VoiceID p_voice, float p_pitch_scale) {
|
||||
|
||||
if (!get_source_rid().is_valid())
|
||||
return;
|
||||
|
||||
SpatialSound2DServer::get_singleton()->source_voice_set_pitch_scale(get_source_rid(),p_voice,p_pitch_scale);
|
||||
|
||||
}
|
||||
|
||||
void SamplePlayer2D::voice_set_volume_scale_db(VoiceID p_voice, float p_volume_db) {
|
||||
|
||||
if (!get_source_rid().is_valid())
|
||||
return;
|
||||
SpatialSound2DServer::get_singleton()->source_voice_set_volume_scale_db(get_source_rid(),p_voice,p_volume_db);
|
||||
|
||||
}
|
||||
|
||||
bool SamplePlayer2D::is_voice_active(VoiceID p_voice) const {
|
||||
|
||||
if (!get_source_rid().is_valid())
|
||||
return false;
|
||||
return SpatialSound2DServer::get_singleton()->source_is_voice_active(get_source_rid(),p_voice);
|
||||
|
||||
}
|
||||
|
||||
void SamplePlayer2D::stop_voice(VoiceID p_voice) {
|
||||
|
||||
if (!get_source_rid().is_valid())
|
||||
return;
|
||||
SpatialSound2DServer::get_singleton()->source_stop_voice(get_source_rid(),p_voice);
|
||||
|
||||
}
|
||||
|
||||
void SamplePlayer2D::stop_all() {
|
||||
|
||||
if (!get_source_rid().is_valid())
|
||||
return;
|
||||
|
||||
for(int i=0;i<polyphony;i++) {
|
||||
|
||||
SpatialSound2DServer::get_singleton()->source_stop_voice(get_source_rid(),i);
|
||||
}
|
||||
}
|
||||
|
||||
void SamplePlayer2D::set_random_pitch_scale(float p_scale) {
|
||||
random_pitch_scale=p_scale;
|
||||
}
|
||||
|
||||
float SamplePlayer2D::get_random_pitch_scale() const {
|
||||
|
||||
return random_pitch_scale;
|
||||
}
|
||||
|
||||
|
||||
void SamplePlayer2D::_bind_methods() {
|
||||
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_sample_library","library:SampleLibrary"),&SamplePlayer2D::set_sample_library);
|
||||
ObjectTypeDB::bind_method(_MD("get_sample_library:SampleLibrary"),&SamplePlayer2D::get_sample_library);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_polyphony","voices"),&SamplePlayer2D::set_polyphony);
|
||||
ObjectTypeDB::bind_method(_MD("get_polyphony"),&SamplePlayer2D::get_polyphony);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("play","sample","voice"),&SamplePlayer2D::play,DEFVAL(NEXT_VOICE));
|
||||
//voices,DEV
|
||||
ObjectTypeDB::bind_method(_MD("voice_set_pitch_scale","voice","ratio"),&SamplePlayer2D::voice_set_pitch_scale);
|
||||
ObjectTypeDB::bind_method(_MD("voice_set_volume_scale_db","voice","db"),&SamplePlayer2D::voice_set_volume_scale_db);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("is_voice_active","voice"),&SamplePlayer2D::is_voice_active);
|
||||
ObjectTypeDB::bind_method(_MD("stop_voice","voice"),&SamplePlayer2D::stop_voice);
|
||||
ObjectTypeDB::bind_method(_MD("stop_all"),&SamplePlayer2D::stop_all);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_random_pitch_scale","val"),&SamplePlayer2D::set_random_pitch_scale);
|
||||
ObjectTypeDB::bind_method(_MD("get_random_pitch_scale"),&SamplePlayer2D::get_random_pitch_scale);
|
||||
|
||||
BIND_CONSTANT( INVALID_VOICE );
|
||||
BIND_CONSTANT( NEXT_VOICE );
|
||||
|
||||
ADD_PROPERTY( PropertyInfo( Variant::INT, "config/polyphony", PROPERTY_HINT_RANGE, "1,64,1"),_SCS("set_polyphony"),_SCS("get_polyphony"));
|
||||
ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "config/samples", PROPERTY_HINT_RESOURCE_TYPE,"SampleLibrary"),_SCS("set_sample_library"),_SCS("get_sample_library"));
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "config/pitch_random", PROPERTY_HINT_RESOURCE_TYPE,"SampleLibrary"),_SCS("set_random_pitch_scale"),_SCS("get_random_pitch_scale"));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
SamplePlayer2D::SamplePlayer2D() {
|
||||
|
||||
polyphony=1;
|
||||
random_pitch_scale=0;
|
||||
|
||||
}
|
||||
|
||||
SamplePlayer2D::~SamplePlayer2D() {
|
||||
|
||||
|
||||
}
|
||||
92
scene/2d/sample_player_2d.h
Normal file
92
scene/2d/sample_player_2d.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*************************************************************************/
|
||||
/* sample_player_2d.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef SAMPLE_PLAYER_2D_H
|
||||
#define SAMPLE_PLAYER_2D_H
|
||||
|
||||
#include "scene/2d/sound_player_2d.h"
|
||||
#include "scene/resources/sample_library.h"
|
||||
|
||||
class SamplePlayer2D : public SoundPlayer2D {
|
||||
|
||||
OBJ_TYPE(SamplePlayer2D,SoundPlayer2D);
|
||||
public:
|
||||
|
||||
enum {
|
||||
|
||||
INVALID_VOICE=SpatialSoundServer::SOURCE_INVALID_VOICE,
|
||||
NEXT_VOICE=SpatialSoundServer::SOURCE_NEXT_VOICE
|
||||
};
|
||||
|
||||
typedef int VoiceID;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
Ref<SampleLibrary> library;
|
||||
int polyphony;
|
||||
String played_back;
|
||||
float random_pitch_scale;
|
||||
|
||||
protected:
|
||||
|
||||
bool _set(const StringName& p_name, const Variant& p_value);
|
||||
bool _get(const StringName& p_name,Variant &r_ret) const;
|
||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
|
||||
void _notification(int p_what);
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
void set_sample_library(const Ref<SampleLibrary>& p_library);
|
||||
Ref<SampleLibrary> get_sample_library() const;
|
||||
|
||||
void set_polyphony(int p_voice_count);
|
||||
int get_polyphony() const;
|
||||
|
||||
VoiceID play(const String& p_sample,int p_voice=NEXT_VOICE);
|
||||
//voices
|
||||
void voice_set_pitch_scale(VoiceID p_voice, float p_pitch_scale);
|
||||
void voice_set_volume_scale_db(VoiceID p_voice, float p_volume_db);
|
||||
|
||||
bool is_voice_active(VoiceID p_voice) const;
|
||||
void stop_voice(VoiceID p_voice);
|
||||
void stop_all();
|
||||
|
||||
void set_random_pitch_scale(float p_scale);
|
||||
float get_random_pitch_scale() const;
|
||||
|
||||
SamplePlayer2D();
|
||||
~SamplePlayer2D();
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // SAMPLE_PLAYER_2D_H
|
||||
372
scene/2d/screen_button.cpp
Normal file
372
scene/2d/screen_button.cpp
Normal file
@ -0,0 +1,372 @@
|
||||
/*************************************************************************/
|
||||
/* screen_button.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "screen_button.h"
|
||||
#include "os/os.h"
|
||||
#include "input_map.h"
|
||||
#include "os/input.h"
|
||||
|
||||
void TouchScreenButton::set_texture(const Ref<Texture>& p_texture) {
|
||||
|
||||
texture=p_texture;
|
||||
update();
|
||||
}
|
||||
|
||||
Ref<Texture> TouchScreenButton::get_texture() const{
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
void TouchScreenButton::set_texture_pressed(const Ref<Texture>& p_texture_pressed) {
|
||||
|
||||
texture_pressed=p_texture_pressed;
|
||||
update();
|
||||
}
|
||||
|
||||
Ref<Texture> TouchScreenButton::get_texture_pressed() const{
|
||||
|
||||
return texture_pressed;
|
||||
}
|
||||
|
||||
void TouchScreenButton::set_bitmask(const Ref<BitMap>& p_bitmask){
|
||||
|
||||
bitmask=p_bitmask;
|
||||
}
|
||||
|
||||
Ref<BitMap> TouchScreenButton::get_bitmask() const{
|
||||
|
||||
return bitmask;
|
||||
}
|
||||
|
||||
void TouchScreenButton::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_DRAW: {
|
||||
|
||||
if (!is_inside_scene())
|
||||
return;
|
||||
if (!get_scene()->is_editor_hint() && !OS::get_singleton()->has_touchscreen_ui_hint() && visibility==VISIBILITY_TOUCHSCREEN_ONLY)
|
||||
return;
|
||||
|
||||
if (finger_pressed!=-1) {
|
||||
|
||||
if (texture_pressed.is_valid())
|
||||
draw_texture(texture_pressed,Point2());
|
||||
else if (texture.is_valid())
|
||||
draw_texture(texture,Point2());
|
||||
|
||||
} else {
|
||||
if (texture.is_valid())
|
||||
draw_texture(texture,Point2());
|
||||
}
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_ENTER_SCENE: {
|
||||
|
||||
if (!get_scene()->is_editor_hint() && !OS::get_singleton()->has_touchscreen_ui_hint() && visibility==VISIBILITY_TOUCHSCREEN_ONLY)
|
||||
return;
|
||||
update();
|
||||
set_process_input(true);
|
||||
if (action.operator String()!="" && InputMap::get_singleton()->has_action(action)) {
|
||||
action_id=InputMap::get_singleton()->get_action_id(action);
|
||||
} else {
|
||||
action_id=-1;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool TouchScreenButton::is_pressed() const{
|
||||
|
||||
return finger_pressed!=-1;
|
||||
}
|
||||
|
||||
void TouchScreenButton::set_action(const String& p_action) {
|
||||
|
||||
action=p_action;
|
||||
if (action.operator String()!="" && InputMap::get_singleton()->has_action(action)) {
|
||||
action_id=InputMap::get_singleton()->get_action_id(action);
|
||||
} else {
|
||||
action_id=-1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
String TouchScreenButton::get_action() const {
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
void TouchScreenButton::_input(const InputEvent& p_event) {
|
||||
|
||||
if (!get_scene())
|
||||
return;
|
||||
|
||||
if (passby_press) {
|
||||
|
||||
if (p_event.type==InputEvent::SCREEN_TOUCH && !p_event.screen_touch.pressed && finger_pressed==p_event.screen_touch.index) {
|
||||
|
||||
emit_signal("released");
|
||||
|
||||
if (action_id!=-1) {
|
||||
|
||||
Input::get_singleton()->action_release(action);
|
||||
InputEvent ie;
|
||||
ie.type=InputEvent::ACTION;
|
||||
ie.ID=0;
|
||||
ie.action.action=action_id;
|
||||
ie.action.pressed=false;
|
||||
get_scene()->input_event(ie);
|
||||
}
|
||||
finger_pressed=-1;
|
||||
|
||||
update();
|
||||
|
||||
}
|
||||
|
||||
if ((p_event.type==InputEvent::SCREEN_TOUCH && p_event.screen_touch.pressed)|| p_event.type==InputEvent::SCREEN_DRAG) {
|
||||
|
||||
if (finger_pressed==-1 || p_event.screen_touch.index==finger_pressed) {
|
||||
|
||||
Point2 coord = (get_viewport_transform() * get_global_transform()).affine_inverse().xform(Point2(p_event.screen_touch.x,p_event.screen_touch.y));
|
||||
|
||||
bool touched=false;
|
||||
if (bitmask.is_valid()) {
|
||||
|
||||
if (Rect2(Point2(),bitmask->get_size()).has_point(coord)) {
|
||||
|
||||
if (bitmask->get_bit(coord))
|
||||
touched=true;
|
||||
}
|
||||
} else {
|
||||
|
||||
touched=Rect2(Point2(),texture->get_size()).has_point(coord);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (touched) {
|
||||
|
||||
if (finger_pressed==-1) {
|
||||
finger_pressed=p_event.screen_touch.index;
|
||||
//emit change stuff
|
||||
emit_signal("pressed");
|
||||
if (action_id!=-1) {
|
||||
|
||||
Input::get_singleton()->action_press(action);
|
||||
InputEvent ie;
|
||||
ie.type=InputEvent::ACTION;
|
||||
ie.ID=0;
|
||||
ie.action.action=action_id;
|
||||
ie.action.pressed=true;
|
||||
get_scene()->input_event(ie);
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (finger_pressed!=-1) {
|
||||
|
||||
emit_signal("released");
|
||||
|
||||
if (action_id!=-1) {
|
||||
|
||||
Input::get_singleton()->action_release(action);
|
||||
InputEvent ie;
|
||||
ie.type=InputEvent::ACTION;
|
||||
ie.ID=0;
|
||||
ie.action.action=action_id;
|
||||
ie.action.pressed=false;
|
||||
get_scene()->input_event(ie);
|
||||
}
|
||||
finger_pressed=-1;
|
||||
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (p_event.type==InputEvent::SCREEN_TOUCH) {
|
||||
|
||||
if (p_event.screen_touch.pressed) {
|
||||
|
||||
if (!is_visible())
|
||||
return;
|
||||
|
||||
if (finger_pressed!=-1)
|
||||
return; //already fingering
|
||||
|
||||
Point2 coord = (get_viewport_transform() * get_global_transform()).affine_inverse().xform(Point2(p_event.screen_touch.x,p_event.screen_touch.y));
|
||||
|
||||
bool touched=false;
|
||||
if (bitmask.is_valid()) {
|
||||
|
||||
if (Rect2(Point2(),bitmask->get_size()).has_point(coord)) {
|
||||
|
||||
if (bitmask->get_bit(coord))
|
||||
touched=true;
|
||||
}
|
||||
} else {
|
||||
|
||||
touched=Rect2(Point2(),texture->get_size()).has_point(coord);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (touched) {
|
||||
|
||||
finger_pressed=p_event.screen_touch.index;
|
||||
//emit change stuff
|
||||
emit_signal("pressed");
|
||||
if (action_id!=-1) {
|
||||
|
||||
Input::get_singleton()->action_press(action);
|
||||
InputEvent ie;
|
||||
ie.type=InputEvent::ACTION;
|
||||
ie.ID=0;
|
||||
ie.action.action=action_id;
|
||||
ie.action.pressed=true;
|
||||
get_scene()->input_event(ie);
|
||||
}
|
||||
update();
|
||||
|
||||
}
|
||||
} else {
|
||||
|
||||
|
||||
if (p_event.screen_touch.index==finger_pressed) {
|
||||
//untouch
|
||||
|
||||
emit_signal("released");
|
||||
|
||||
if (action_id!=-1) {
|
||||
|
||||
Input::get_singleton()->action_release(action);
|
||||
InputEvent ie;
|
||||
ie.type=InputEvent::ACTION;
|
||||
ie.ID=0;
|
||||
ie.action.action=action_id;
|
||||
ie.action.pressed=false;
|
||||
get_scene()->input_event(ie);
|
||||
}
|
||||
finger_pressed=-1;
|
||||
update();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rect2 TouchScreenButton::get_item_rect() const {
|
||||
|
||||
if (texture.is_null())
|
||||
return Rect2(0,0,1,1);
|
||||
//if (texture.is_null())
|
||||
// return CanvasItem::get_item_rect();
|
||||
|
||||
return Rect2(Size2(),texture->get_size());
|
||||
}
|
||||
|
||||
|
||||
void TouchScreenButton::set_visibility_mode(VisibilityMode p_mode) {
|
||||
visibility=p_mode;
|
||||
update();
|
||||
}
|
||||
|
||||
TouchScreenButton::VisibilityMode TouchScreenButton::get_visibility_mode() const {
|
||||
|
||||
return visibility;
|
||||
}
|
||||
|
||||
void TouchScreenButton::set_passby_press(bool p_enable) {
|
||||
|
||||
passby_press=p_enable;
|
||||
}
|
||||
|
||||
bool TouchScreenButton::is_passby_press_enabled() const{
|
||||
|
||||
return passby_press;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void TouchScreenButton::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_texture","texture"),&TouchScreenButton::set_texture);
|
||||
ObjectTypeDB::bind_method(_MD("get_texture"),&TouchScreenButton::get_texture);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_texture_pressed","texture_pressed"),&TouchScreenButton::set_texture_pressed);
|
||||
ObjectTypeDB::bind_method(_MD("get_texture_pressed"),&TouchScreenButton::get_texture_pressed);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_bitmask","bitmask"),&TouchScreenButton::set_bitmask);
|
||||
ObjectTypeDB::bind_method(_MD("get_bitmask"),&TouchScreenButton::get_bitmask);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_action","action"),&TouchScreenButton::set_action);
|
||||
ObjectTypeDB::bind_method(_MD("get_action"),&TouchScreenButton::get_action);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_visibility_mode","mode"),&TouchScreenButton::set_visibility_mode);
|
||||
ObjectTypeDB::bind_method(_MD("get_visibility_mode"),&TouchScreenButton::get_visibility_mode);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_passby_press","enabled"),&TouchScreenButton::set_passby_press);
|
||||
ObjectTypeDB::bind_method(_MD("is_passby_press_enabled"),&TouchScreenButton::is_passby_press_enabled);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("is_pressed"),&TouchScreenButton::is_pressed);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_input"),&TouchScreenButton::_input);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"normal",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"pressed",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture_pressed"),_SCS("get_texture_pressed"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"bitmask",PROPERTY_HINT_RESOURCE_TYPE,"BitMap"),_SCS("set_bitmask"),_SCS("get_bitmask"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"passby_press"),_SCS("set_passby_press"),_SCS("is_passby_press_enabled"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::STRING,"action"),_SCS("set_action"),_SCS("get_action"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"visibility_mode",PROPERTY_HINT_ENUM,"Always,TouchScreen Only"),_SCS("set_visibility_mode"),_SCS("get_visibility_mode"));
|
||||
|
||||
ADD_SIGNAL( MethodInfo("pressed" ) );
|
||||
ADD_SIGNAL( MethodInfo("release" ) );
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
TouchScreenButton::TouchScreenButton() {
|
||||
|
||||
finger_pressed=-1;
|
||||
action_id=-1;
|
||||
passby_press=false;
|
||||
visibility=VISIBILITY_ALWAYS;
|
||||
}
|
||||
95
scene/2d/screen_button.h
Normal file
95
scene/2d/screen_button.h
Normal file
@ -0,0 +1,95 @@
|
||||
/*************************************************************************/
|
||||
/* screen_button.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef SCREEN_BUTTON_H
|
||||
#define SCREEN_BUTTON_H
|
||||
|
||||
#include "scene/2d/node_2d.h"
|
||||
#include "scene/resources/texture.h"
|
||||
#include "scene/resources/bit_mask.h"
|
||||
|
||||
class TouchScreenButton : public Node2D {
|
||||
|
||||
OBJ_TYPE(TouchScreenButton,Node2D);
|
||||
public:
|
||||
|
||||
enum VisibilityMode {
|
||||
VISIBILITY_ALWAYS,
|
||||
VISIBILITY_TOUCHSCREEN_ONLY
|
||||
};
|
||||
|
||||
private:
|
||||
Ref<Texture> texture;
|
||||
Ref<Texture> texture_pressed;
|
||||
Ref<BitMap> bitmask;
|
||||
|
||||
StringName action;
|
||||
bool passby_press;
|
||||
int finger_pressed;
|
||||
int action_id;
|
||||
|
||||
VisibilityMode visibility;
|
||||
|
||||
void _input(const InputEvent& p_Event);
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
|
||||
void set_texture(const Ref<Texture>& p_texture);
|
||||
Ref<Texture> get_texture() const;
|
||||
|
||||
void set_texture_pressed(const Ref<Texture>& p_texture_pressed);
|
||||
Ref<Texture> get_texture_pressed() const;
|
||||
|
||||
void set_bitmask(const Ref<BitMap>& p_bitmask);
|
||||
Ref<BitMap> get_bitmask() const;
|
||||
|
||||
void set_action(const String& p_action);
|
||||
String get_action() const;
|
||||
|
||||
void set_passby_press(bool p_enable);
|
||||
bool is_passby_press_enabled() const;
|
||||
|
||||
void set_visibility_mode(VisibilityMode p_mode);
|
||||
VisibilityMode get_visibility_mode() const;
|
||||
|
||||
bool is_pressed() const;
|
||||
|
||||
Rect2 get_item_rect() const;
|
||||
|
||||
|
||||
TouchScreenButton();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(TouchScreenButton::VisibilityMode);
|
||||
|
||||
#endif // SCREEN_BUTTON_H
|
||||
123
scene/2d/sound_player_2d.cpp
Normal file
123
scene/2d/sound_player_2d.cpp
Normal file
@ -0,0 +1,123 @@
|
||||
/*************************************************************************/
|
||||
/* sound_player_2d.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "sound_player_2d.h"
|
||||
|
||||
#include "servers/audio_server.h"
|
||||
|
||||
#include "servers/spatial_sound_2d_server.h"
|
||||
#include "scene/resources/surface_tool.h"
|
||||
|
||||
|
||||
void SoundPlayer2D::_notification(int p_what) {
|
||||
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_ENTER_SCENE: {
|
||||
//find the sound space
|
||||
|
||||
source_rid = SpatialSound2DServer::get_singleton()->source_create(get_world_2d()->get_sound_space());
|
||||
|
||||
for(int i=0;i<PARAM_MAX;i++)
|
||||
set_param(Param(i),params[i]);
|
||||
|
||||
SpatialSound2DServer::get_singleton()->source_set_transform(source_rid,get_global_transform());
|
||||
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
|
||||
SpatialSound2DServer::get_singleton()->source_set_transform(source_rid,get_global_transform());
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_SCENE: {
|
||||
|
||||
if (source_rid.is_valid())
|
||||
SpatialSound2DServer::get_singleton()->free(source_rid);
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void SoundPlayer2D::set_param( Param p_param, float p_value) {
|
||||
|
||||
ERR_FAIL_INDEX(p_param,PARAM_MAX);
|
||||
params[p_param]=p_value;
|
||||
if (source_rid.is_valid())
|
||||
SpatialSound2DServer::get_singleton()->source_set_param(source_rid,(SpatialSound2DServer::SourceParam)p_param,p_value);
|
||||
|
||||
}
|
||||
|
||||
float SoundPlayer2D::get_param( Param p_param) const {
|
||||
|
||||
ERR_FAIL_INDEX_V(p_param,PARAM_MAX,0);
|
||||
return params[p_param];
|
||||
|
||||
}
|
||||
|
||||
|
||||
void SoundPlayer2D::_bind_methods() {
|
||||
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_param","param","value"),&SoundPlayer2D::set_param);
|
||||
ObjectTypeDB::bind_method(_MD("get_param","param"),&SoundPlayer2D::get_param);
|
||||
|
||||
BIND_CONSTANT( PARAM_VOLUME_DB );
|
||||
BIND_CONSTANT( PARAM_PITCH_SCALE );
|
||||
BIND_CONSTANT( PARAM_ATTENUATION_MIN_DISTANCE );
|
||||
BIND_CONSTANT( PARAM_ATTENUATION_MAX_DISTANCE );
|
||||
BIND_CONSTANT( PARAM_ATTENUATION_DISTANCE_EXP );
|
||||
BIND_CONSTANT( PARAM_MAX );
|
||||
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/volume_db",PROPERTY_HINT_RANGE, "-80,24,0.01"),_SCS("set_param"),_SCS("get_param"),PARAM_VOLUME_DB);
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/pitch_scale",PROPERTY_HINT_RANGE, "0.001,32,0.001"),_SCS("set_param"),_SCS("get_param"),PARAM_PITCH_SCALE);
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/attenuation/min_distance",PROPERTY_HINT_EXP_RANGE, "16,16384,1"),_SCS("set_param"),_SCS("get_param"),PARAM_ATTENUATION_MIN_DISTANCE);
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/attenuation/max_distance",PROPERTY_HINT_EXP_RANGE, "16,16384,1"),_SCS("set_param"),_SCS("get_param"),PARAM_ATTENUATION_MAX_DISTANCE);
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/attenuation/distance_exp",PROPERTY_HINT_EXP_EASING, "attenuation"),_SCS("set_param"),_SCS("get_param"),PARAM_ATTENUATION_DISTANCE_EXP);
|
||||
|
||||
}
|
||||
|
||||
|
||||
SoundPlayer2D::SoundPlayer2D() {
|
||||
|
||||
params[PARAM_VOLUME_DB]=0.0;
|
||||
params[PARAM_PITCH_SCALE]=1.0;
|
||||
params[PARAM_ATTENUATION_MIN_DISTANCE]=1;
|
||||
params[PARAM_ATTENUATION_MAX_DISTANCE]=2048;
|
||||
params[PARAM_ATTENUATION_DISTANCE_EXP]=1.0; //linear (and not really good)
|
||||
|
||||
|
||||
}
|
||||
|
||||
SoundPlayer2D::~SoundPlayer2D() {
|
||||
|
||||
|
||||
}
|
||||
82
scene/2d/sound_player_2d.h
Normal file
82
scene/2d/sound_player_2d.h
Normal file
@ -0,0 +1,82 @@
|
||||
/*************************************************************************/
|
||||
/* sound_player_2d.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef SOUND_PLAYER_2D_H
|
||||
#define SOUND_PLAYER_2D_H
|
||||
|
||||
|
||||
#include "scene/2d/node_2d.h"
|
||||
#include "scene/resources/sample_library.h"
|
||||
#include "servers/spatial_sound_2d_server.h"
|
||||
#include "scene/main/viewport.h"
|
||||
|
||||
class SoundPlayer2D : public Node2D {
|
||||
|
||||
OBJ_TYPE(SoundPlayer2D,Node2D);
|
||||
public:
|
||||
|
||||
|
||||
enum Param {
|
||||
|
||||
PARAM_VOLUME_DB=SpatialSound2DServer::SOURCE_PARAM_VOLUME_DB,
|
||||
PARAM_PITCH_SCALE=SpatialSound2DServer::SOURCE_PARAM_PITCH_SCALE,
|
||||
PARAM_ATTENUATION_MIN_DISTANCE=SpatialSound2DServer::SOURCE_PARAM_ATTENUATION_MIN_DISTANCE,
|
||||
PARAM_ATTENUATION_MAX_DISTANCE=SpatialSound2DServer::SOURCE_PARAM_ATTENUATION_MAX_DISTANCE,
|
||||
PARAM_ATTENUATION_DISTANCE_EXP=SpatialSound2DServer::SOURCE_PARAM_ATTENUATION_DISTANCE_EXP,
|
||||
PARAM_MAX=SpatialSound2DServer::SOURCE_PARAM_MAX
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
float params[PARAM_MAX];
|
||||
RID source_rid;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
_FORCE_INLINE_ RID get_source_rid() const { return source_rid; }
|
||||
|
||||
void _notification(int p_what);
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
void set_param( Param p_param, float p_value);
|
||||
float get_param( Param p_param) const;
|
||||
|
||||
|
||||
SoundPlayer2D();
|
||||
~SoundPlayer2D();
|
||||
|
||||
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(SoundPlayer2D::Param );
|
||||
|
||||
#endif // SOUND_PLAYER_2D_H
|
||||
337
scene/2d/sprite.cpp
Normal file
337
scene/2d/sprite.cpp
Normal file
@ -0,0 +1,337 @@
|
||||
/*************************************************************************/
|
||||
/* sprite.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "sprite.h"
|
||||
#include "core/core_string_names.h"
|
||||
#include "scene/scene_string_names.h"
|
||||
void Sprite::edit_set_pivot(const Point2& p_pivot) {
|
||||
|
||||
set_offset(p_pivot);
|
||||
}
|
||||
|
||||
Point2 Sprite::edit_get_pivot() const {
|
||||
|
||||
return get_offset();
|
||||
}
|
||||
bool Sprite::edit_has_pivot() const {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Sprite::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_DRAW: {
|
||||
|
||||
if (texture.is_null())
|
||||
return;
|
||||
|
||||
|
||||
|
||||
|
||||
RID ci = get_canvas_item();
|
||||
|
||||
/*
|
||||
texture->draw(ci,Point2());
|
||||
break;
|
||||
*/
|
||||
|
||||
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=offset;
|
||||
if (centered)
|
||||
ofs-=s/2;
|
||||
|
||||
Rect2i dst_rect(ofs,s);
|
||||
|
||||
if (hflip)
|
||||
dst_rect.size.x=-dst_rect.size.x;
|
||||
if (vflip)
|
||||
dst_rect.size.y=-dst_rect.size.y;
|
||||
|
||||
texture->draw_rect_region(ci,dst_rect,src_rect,modulate);
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void Sprite::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()->update);
|
||||
}
|
||||
texture=p_texture;
|
||||
if (texture.is_valid()) {
|
||||
texture->set_flags(texture->get_flags()&(~Texture::FLAG_REPEAT)); //remove repeat from texture, it looks bad in sprites
|
||||
texture->connect(CoreStringNames::get_singleton()->changed,this,SceneStringNames::get_singleton()->update);
|
||||
}
|
||||
update();
|
||||
item_rect_changed();
|
||||
}
|
||||
|
||||
Ref<Texture> Sprite::get_texture() const {
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
void Sprite::set_centered(bool p_center) {
|
||||
|
||||
centered=p_center;
|
||||
update();
|
||||
item_rect_changed();
|
||||
}
|
||||
|
||||
bool Sprite::is_centered() const {
|
||||
|
||||
return centered;
|
||||
}
|
||||
|
||||
void Sprite::set_offset(const Point2& p_offset) {
|
||||
|
||||
offset=p_offset;
|
||||
update();
|
||||
item_rect_changed();
|
||||
}
|
||||
Point2 Sprite::get_offset() const {
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
void Sprite::set_flip_h(bool p_flip) {
|
||||
|
||||
hflip=p_flip;
|
||||
update();
|
||||
}
|
||||
bool Sprite::is_flipped_h() const {
|
||||
|
||||
return hflip;
|
||||
}
|
||||
|
||||
void Sprite::set_flip_v(bool p_flip) {
|
||||
|
||||
vflip=p_flip;
|
||||
update();
|
||||
}
|
||||
bool Sprite::is_flipped_v() const {
|
||||
|
||||
return vflip;
|
||||
}
|
||||
|
||||
void Sprite::set_region(bool p_region) {
|
||||
|
||||
if (p_region==region)
|
||||
return;
|
||||
|
||||
region=p_region;
|
||||
update();
|
||||
}
|
||||
|
||||
bool Sprite::is_region() const{
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
void Sprite::set_region_rect(const Rect2& p_region_rect) {
|
||||
|
||||
bool changed=region_rect!=p_region_rect;
|
||||
region_rect=p_region_rect;
|
||||
if (region && changed) {
|
||||
update();
|
||||
item_rect_changed();
|
||||
}
|
||||
}
|
||||
|
||||
Rect2 Sprite::get_region_rect() const {
|
||||
|
||||
return region_rect;
|
||||
}
|
||||
|
||||
void Sprite::set_frame(int p_frame) {
|
||||
|
||||
ERR_FAIL_INDEX(p_frame,vframes*hframes);
|
||||
|
||||
if (frame != p_frame)
|
||||
item_rect_changed();
|
||||
|
||||
frame=p_frame;
|
||||
}
|
||||
|
||||
int Sprite::get_frame() const {
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
void Sprite::set_vframes(int p_amount) {
|
||||
|
||||
ERR_FAIL_COND(p_amount<1);
|
||||
vframes=p_amount;
|
||||
update();
|
||||
item_rect_changed();
|
||||
_change_notify("frame");
|
||||
}
|
||||
int Sprite::get_vframes() const {
|
||||
|
||||
return vframes;
|
||||
}
|
||||
|
||||
void Sprite::set_hframes(int p_amount) {
|
||||
|
||||
ERR_FAIL_COND(p_amount<1);
|
||||
hframes=p_amount;
|
||||
update();
|
||||
item_rect_changed();
|
||||
_change_notify("frame");
|
||||
}
|
||||
int Sprite::get_hframes() const {
|
||||
|
||||
return hframes;
|
||||
}
|
||||
|
||||
void Sprite::set_modulate(const Color& p_color) {
|
||||
|
||||
modulate=p_color;
|
||||
update();
|
||||
}
|
||||
|
||||
Color Sprite::get_modulate() const{
|
||||
|
||||
return modulate;
|
||||
}
|
||||
|
||||
|
||||
Rect2 Sprite::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=offset;
|
||||
if (centered)
|
||||
ofs-=s/2;
|
||||
|
||||
if (s==Size2(0,0))
|
||||
s=Size2(1,1);
|
||||
|
||||
return Rect2(ofs,s);
|
||||
}
|
||||
|
||||
|
||||
void Sprite::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_texture","texture:Texture"),&Sprite::set_texture);
|
||||
ObjectTypeDB::bind_method(_MD("get_texture:Texture"),&Sprite::get_texture);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_centered","centered"),&Sprite::set_centered);
|
||||
ObjectTypeDB::bind_method(_MD("is_centered"),&Sprite::is_centered);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_offset","offset"),&Sprite::set_offset);
|
||||
ObjectTypeDB::bind_method(_MD("get_offset"),&Sprite::get_offset);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_flip_h","flip_h"),&Sprite::set_flip_h);
|
||||
ObjectTypeDB::bind_method(_MD("is_flipped_h"),&Sprite::is_flipped_h);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_flip_v","flip_v"),&Sprite::set_flip_v);
|
||||
ObjectTypeDB::bind_method(_MD("is_flipped_v"),&Sprite::is_flipped_v);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_region","enabled"),&Sprite::set_region);
|
||||
ObjectTypeDB::bind_method(_MD("is_region"),&Sprite::is_region);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_region_rect","rect"),&Sprite::set_region_rect);
|
||||
ObjectTypeDB::bind_method(_MD("get_region_rect"),&Sprite::get_region_rect);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_frame","frame"),&Sprite::set_frame);
|
||||
ObjectTypeDB::bind_method(_MD("get_frame"),&Sprite::get_frame);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_vframes","vframes"),&Sprite::set_vframes);
|
||||
ObjectTypeDB::bind_method(_MD("get_vframes"),&Sprite::get_vframes);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_hframes","hframes"),&Sprite::set_hframes);
|
||||
ObjectTypeDB::bind_method(_MD("get_hframes"),&Sprite::get_hframes);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_modulate","modulate"),&Sprite::set_modulate);
|
||||
ObjectTypeDB::bind_method(_MD("get_modulate"),&Sprite::get_modulate);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_texture"),_SCS("get_texture"));
|
||||
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::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::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate"));
|
||||
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"));
|
||||
|
||||
}
|
||||
|
||||
Sprite::Sprite() {
|
||||
|
||||
centered=true;
|
||||
hflip=false;
|
||||
vflip=false;
|
||||
region=false;
|
||||
|
||||
frame=0;
|
||||
|
||||
vframes=1;
|
||||
hframes=1;
|
||||
|
||||
modulate=Color(1,1,1,1);
|
||||
|
||||
|
||||
}
|
||||
108
scene/2d/sprite.h
Normal file
108
scene/2d/sprite.h
Normal file
@ -0,0 +1,108 @@
|
||||
/*************************************************************************/
|
||||
/* sprite.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef SPRITE_H
|
||||
#define SPRITE_H
|
||||
|
||||
#include "scene/2d/node_2d.h"
|
||||
#include "scene/resources/texture.h"
|
||||
|
||||
|
||||
class Sprite : public Node2D {
|
||||
|
||||
OBJ_TYPE( Sprite, Node2D );
|
||||
|
||||
Ref<Texture> texture;
|
||||
|
||||
bool centered;
|
||||
Point2 offset;
|
||||
|
||||
bool hflip;
|
||||
bool vflip;
|
||||
bool region;
|
||||
Rect2 region_rect;
|
||||
|
||||
int frame;
|
||||
|
||||
int vframes;
|
||||
int hframes;
|
||||
|
||||
Color modulate;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
|
||||
static void _bind_methods();;
|
||||
|
||||
public:
|
||||
|
||||
virtual void edit_set_pivot(const Point2& p_pivot);
|
||||
virtual Point2 edit_get_pivot() const;
|
||||
virtual bool edit_has_pivot() const;
|
||||
|
||||
void set_texture(const Ref<Texture>& p_texture);
|
||||
Ref<Texture> get_texture() const;
|
||||
|
||||
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_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;
|
||||
|
||||
void set_modulate(const Color& p_color);
|
||||
Color get_modulate() const;
|
||||
|
||||
virtual Rect2 get_item_rect() const;
|
||||
|
||||
Sprite();
|
||||
};
|
||||
|
||||
#endif // SPRITE_H
|
||||
592
scene/2d/tile_map.cpp
Normal file
592
scene/2d/tile_map.cpp
Normal file
@ -0,0 +1,592 @@
|
||||
/*************************************************************************/
|
||||
/* tile_map.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "tile_map.h"
|
||||
#include "io/marshalls.h"
|
||||
#include "servers/physics_2d_server.h"
|
||||
void TileMap::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_ENTER_SCENE: {
|
||||
|
||||
pending_update=true;
|
||||
_update_dirty_quadrants();
|
||||
RID space = get_world_2d()->get_space();
|
||||
_update_quadrant_transform();
|
||||
_update_quadrant_space(space);
|
||||
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_SCENE: {
|
||||
|
||||
_update_quadrant_space(RID());
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
|
||||
//move stuff
|
||||
_update_quadrant_transform();
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void TileMap::_update_quadrant_space(const RID& p_space) {
|
||||
|
||||
for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) {
|
||||
|
||||
Quadrant &q=E->get();
|
||||
Physics2DServer::get_singleton()->body_set_space(q.static_body,p_space);
|
||||
}
|
||||
}
|
||||
|
||||
void TileMap::_update_quadrant_transform() {
|
||||
|
||||
if (!is_inside_scene())
|
||||
return;
|
||||
|
||||
Matrix32 global_transform = get_global_transform();
|
||||
|
||||
for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) {
|
||||
|
||||
Quadrant &q=E->get();
|
||||
Matrix32 xform;
|
||||
xform.set_origin( q.pos );
|
||||
xform = global_transform * xform;
|
||||
Physics2DServer::get_singleton()->body_set_state(q.static_body,Physics2DServer::BODY_STATE_TRANSFORM,xform);
|
||||
}
|
||||
}
|
||||
|
||||
void TileMap::set_tileset(const Ref<TileSet>& p_tileset) {
|
||||
|
||||
if (tile_set.is_valid())
|
||||
tile_set->disconnect("changed",this,"_recreate_quadrants");
|
||||
|
||||
_clear_quadrants();
|
||||
tile_set=p_tileset;
|
||||
|
||||
if (tile_set.is_valid())
|
||||
tile_set->connect("changed",this,"_recreate_quadrants");
|
||||
else
|
||||
clear();
|
||||
|
||||
_recreate_quadrants();
|
||||
|
||||
}
|
||||
|
||||
Ref<TileSet> TileMap::get_tileset() const {
|
||||
|
||||
return tile_set;
|
||||
}
|
||||
|
||||
void TileMap::set_cell_size(int p_size) {
|
||||
|
||||
ERR_FAIL_COND(p_size<1);
|
||||
|
||||
_clear_quadrants();
|
||||
cell_size=p_size;
|
||||
_recreate_quadrants();
|
||||
|
||||
|
||||
}
|
||||
int TileMap::get_cell_size() const {
|
||||
|
||||
return cell_size;
|
||||
}
|
||||
void TileMap::set_quadrant_size(int p_size) {
|
||||
|
||||
ERR_FAIL_COND(p_size<1);
|
||||
|
||||
_clear_quadrants();
|
||||
quadrant_size=p_size;
|
||||
_recreate_quadrants();
|
||||
|
||||
}
|
||||
int TileMap::get_quadrant_size() const {
|
||||
|
||||
return quadrant_size;
|
||||
}
|
||||
|
||||
void TileMap::set_center_x(bool p_enable) {
|
||||
|
||||
center_x=p_enable;
|
||||
_recreate_quadrants();
|
||||
|
||||
}
|
||||
bool TileMap::get_center_x() const {
|
||||
|
||||
return center_x;
|
||||
}
|
||||
void TileMap::set_center_y(bool p_enable) {
|
||||
|
||||
center_y=p_enable;
|
||||
_recreate_quadrants();
|
||||
|
||||
}
|
||||
bool TileMap::get_center_y() const {
|
||||
|
||||
return center_y;
|
||||
}
|
||||
|
||||
void TileMap::_update_dirty_quadrants() {
|
||||
|
||||
if (!pending_update)
|
||||
return;
|
||||
if (!is_inside_scene())
|
||||
return;
|
||||
if (!tile_set.is_valid())
|
||||
return;
|
||||
|
||||
VisualServer *vs = VisualServer::get_singleton();
|
||||
Physics2DServer *ps = Physics2DServer::get_singleton();
|
||||
|
||||
while (dirty_quadrant_list.first()) {
|
||||
|
||||
Quadrant &q = *dirty_quadrant_list.first()->self();
|
||||
|
||||
vs->canvas_item_clear(q.canvas_item);
|
||||
ps->body_clear_shapes(q.static_body);
|
||||
|
||||
for(int i=0;i<q.cells.size();i++) {
|
||||
|
||||
Map<PosKey,Cell>::Element *E=tile_map.find( q.cells[i] );
|
||||
Cell &c=E->get();
|
||||
//moment of truth
|
||||
if (!tile_set->has_tile(c.id))
|
||||
continue;
|
||||
Ref<Texture> tex = tile_set->tile_get_texture(c.id);
|
||||
Vector2 tile_ofs = tile_set->tile_get_offset(c.id);
|
||||
|
||||
Vector2 offset = Point2( E->key().x, E->key().y )*cell_size - q.pos;
|
||||
|
||||
if (!tex.is_valid())
|
||||
continue;
|
||||
|
||||
|
||||
Rect2 r = tile_set->tile_get_region(c.id);
|
||||
Size2 s = tex->get_size();
|
||||
|
||||
if (r==Rect2())
|
||||
s = tex->get_size();
|
||||
else {
|
||||
s = r.size;
|
||||
r.pos.x+=fp_adjust;
|
||||
r.pos.y+=fp_adjust;
|
||||
r.size.x-=fp_adjust*2.0;
|
||||
r.size.y-=fp_adjust*2.0;
|
||||
}
|
||||
|
||||
Rect2 rect;
|
||||
rect.pos=offset.floor();
|
||||
rect.size=s;
|
||||
|
||||
rect.size.x+=fp_adjust;
|
||||
rect.size.y+=fp_adjust;
|
||||
|
||||
if (c.flip_h)
|
||||
rect.size.x=-rect.size.x;
|
||||
if (c.flip_v)
|
||||
rect.size.y=-rect.size.y;
|
||||
|
||||
|
||||
if (r==Rect2()) {
|
||||
|
||||
tex->draw_rect(q.canvas_item,rect);
|
||||
} else {
|
||||
|
||||
tex->draw_rect_region(q.canvas_item,rect,r);
|
||||
}
|
||||
|
||||
Vector< Ref<Shape2D> > shapes = tile_set->tile_get_shapes(c.id);
|
||||
|
||||
|
||||
for(int i=0;i<shapes.size();i++) {
|
||||
|
||||
Ref<Shape2D> shape = shapes[i];
|
||||
if (shape.is_valid()) {
|
||||
|
||||
Matrix32 xform;
|
||||
xform.set_origin(offset.floor());
|
||||
if (c.flip_h) {
|
||||
xform.elements[0]=-xform.elements[0];
|
||||
xform.elements[2].x+=s.x;
|
||||
}
|
||||
if (c.flip_v) {
|
||||
xform.elements[1]=-xform.elements[1];
|
||||
xform.elements[2].y+=s.y;
|
||||
}
|
||||
|
||||
ps->body_add_shape(q.static_body,shape->get_rid(),xform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dirty_quadrant_list.remove( dirty_quadrant_list.first() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
pending_update=false;
|
||||
|
||||
_recompute_rect_cache();
|
||||
|
||||
}
|
||||
|
||||
void TileMap::_recompute_rect_cache() {
|
||||
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
|
||||
if (!rect_cache_dirty)
|
||||
return;
|
||||
|
||||
Rect2 r_total;
|
||||
for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) {
|
||||
|
||||
|
||||
Rect2 r( Point2(E->key().x, E->key().y)*cell_size*quadrant_size, Size2(1,1)*cell_size*quadrant_size );
|
||||
if (E==quadrant_map.front())
|
||||
r_total=r;
|
||||
else
|
||||
r_total=r_total.merge(r);
|
||||
|
||||
}
|
||||
if (r_total==Rect2()) {
|
||||
rect_cache=Rect2(-10,-10,20,20);
|
||||
} else {
|
||||
rect_cache=r_total;
|
||||
}
|
||||
|
||||
item_rect_changed();
|
||||
|
||||
rect_cache_dirty=false;
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
Map<TileMap::PosKey,TileMap::Quadrant>::Element *TileMap::_create_quadrant(const PosKey& p_qk) {
|
||||
|
||||
Matrix32 xform;
|
||||
xform.set_origin(Point2(p_qk.x,p_qk.y)*quadrant_size*cell_size);
|
||||
Quadrant q;
|
||||
q.canvas_item = VisualServer::get_singleton()->canvas_item_create();
|
||||
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);
|
||||
if (is_inside_scene()) {
|
||||
xform = get_global_transform() * xform;
|
||||
RID space = get_world_2d()->get_space();
|
||||
Physics2DServer::get_singleton()->body_set_space(q.static_body,space);
|
||||
}
|
||||
|
||||
Physics2DServer::get_singleton()->body_set_state(q.static_body,Physics2DServer::BODY_STATE_TRANSFORM,xform);
|
||||
q.pos=Vector2(p_qk.x,p_qk.y)*quadrant_size*cell_size;
|
||||
|
||||
rect_cache_dirty=true;
|
||||
return quadrant_map.insert(p_qk,q);
|
||||
}
|
||||
|
||||
void TileMap::_erase_quadrant(Map<PosKey,Quadrant>::Element *Q) {
|
||||
|
||||
Quadrant &q=Q->get();
|
||||
Physics2DServer::get_singleton()->free(q.static_body);
|
||||
VisualServer::get_singleton()->free(q.canvas_item);
|
||||
if (q.dirty_list.in_list())
|
||||
dirty_quadrant_list.remove(&q.dirty_list);
|
||||
|
||||
quadrant_map.erase(Q);
|
||||
rect_cache_dirty=true;
|
||||
}
|
||||
|
||||
void TileMap::_make_quadrant_dirty(Map<PosKey,Quadrant>::Element *Q) {
|
||||
|
||||
Quadrant &q=Q->get();
|
||||
if (!q.dirty_list.in_list())
|
||||
dirty_quadrant_list.add(&q.dirty_list);
|
||||
|
||||
if (pending_update)
|
||||
return;
|
||||
pending_update=true;
|
||||
if (!is_inside_scene())
|
||||
return;
|
||||
call_deferred("_update_dirty_quadrants");
|
||||
}
|
||||
|
||||
|
||||
void TileMap::set_cell(int p_x,int p_y,int p_tile,bool p_flip_x,bool p_flip_y) {
|
||||
|
||||
PosKey pk(p_x,p_y);
|
||||
|
||||
Map<PosKey,Cell>::Element *E=tile_map.find(pk);
|
||||
if (!E && p_tile==INVALID_CELL)
|
||||
return; //nothing to do
|
||||
|
||||
PosKey qk(p_x/quadrant_size,p_y/quadrant_size);
|
||||
if (p_tile==INVALID_CELL) {
|
||||
//erase existing
|
||||
tile_map.erase(pk);
|
||||
Map<PosKey,Quadrant>::Element *Q = quadrant_map.find(qk);
|
||||
ERR_FAIL_COND(!Q);
|
||||
Quadrant &q=Q->get();
|
||||
q.cells.erase(pk);
|
||||
if (q.cells.size()==0)
|
||||
_erase_quadrant(Q);
|
||||
else
|
||||
_make_quadrant_dirty(Q);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Map<PosKey,Quadrant>::Element *Q = quadrant_map.find(qk);
|
||||
|
||||
if (!E) {
|
||||
E=tile_map.insert(pk,Cell());
|
||||
if (!Q)
|
||||
Q=_create_quadrant(qk);
|
||||
Quadrant &q=Q->get();
|
||||
q.cells.insert(pk);
|
||||
} else {
|
||||
ERR_FAIL_COND(!Q); // quadrant should exist...
|
||||
|
||||
if (E->get().id==p_tile && E->get().flip_h==p_flip_x && E->get().flip_v==p_flip_y)
|
||||
return; //nothing changed
|
||||
|
||||
}
|
||||
|
||||
|
||||
Cell &c = E->get();
|
||||
|
||||
c.id=p_tile;
|
||||
c.flip_h=p_flip_x;
|
||||
c.flip_v=p_flip_y;
|
||||
|
||||
_make_quadrant_dirty(Q);
|
||||
|
||||
}
|
||||
|
||||
int TileMap::get_cell(int p_x,int p_y) const {
|
||||
|
||||
PosKey pk(p_x,p_y);
|
||||
|
||||
const Map<PosKey,Cell>::Element *E=tile_map.find(pk);
|
||||
|
||||
if (!E)
|
||||
return INVALID_CELL;
|
||||
|
||||
return E->get().id;
|
||||
|
||||
}
|
||||
bool TileMap::is_cell_x_flipped(int p_x,int p_y) const {
|
||||
|
||||
PosKey pk(p_x,p_y);
|
||||
|
||||
const Map<PosKey,Cell>::Element *E=tile_map.find(pk);
|
||||
|
||||
if (!E)
|
||||
return false;
|
||||
|
||||
return E->get().flip_h;
|
||||
}
|
||||
bool TileMap::is_cell_y_flipped(int p_x,int p_y) const {
|
||||
|
||||
PosKey pk(p_x,p_y);
|
||||
|
||||
const Map<PosKey,Cell>::Element *E=tile_map.find(pk);
|
||||
|
||||
if (!E)
|
||||
return false;
|
||||
|
||||
return E->get().flip_v;
|
||||
}
|
||||
|
||||
|
||||
void TileMap::_recreate_quadrants() {
|
||||
|
||||
_clear_quadrants();
|
||||
|
||||
for (Map<PosKey,Cell>::Element *E=tile_map.front();E;E=E->next()) {
|
||||
|
||||
PosKey qk(E->key().x/quadrant_size,E->key().y/quadrant_size);
|
||||
|
||||
Map<PosKey,Quadrant>::Element *Q=quadrant_map.find(qk);
|
||||
if (!Q) {
|
||||
Q=_create_quadrant(qk);
|
||||
dirty_quadrant_list.add(&Q->get().dirty_list);
|
||||
}
|
||||
|
||||
Q->get().cells.insert(E->key());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void TileMap::_clear_quadrants() {
|
||||
|
||||
while (quadrant_map.size()) {
|
||||
_erase_quadrant( quadrant_map.front() );
|
||||
}
|
||||
}
|
||||
|
||||
void TileMap::clear() {
|
||||
|
||||
_clear_quadrants();
|
||||
tile_map.clear();
|
||||
}
|
||||
|
||||
void TileMap::_set_tile_data(const DVector<int>& p_data) {
|
||||
|
||||
int c=p_data.size();
|
||||
DVector<int>::Read r = p_data.read();
|
||||
|
||||
|
||||
for(int i=0;i<c;i+=2) {
|
||||
|
||||
const uint8_t *ptr=(const uint8_t*)&r[i];
|
||||
uint8_t local[8];
|
||||
for(int j=0;j<8;j++)
|
||||
local[j]=ptr[j];
|
||||
|
||||
#ifdef BIG_ENDIAN_ENABLED
|
||||
|
||||
|
||||
SWAP(local[0],local[3]);
|
||||
SWAP(local[1],local[2]);
|
||||
SWAP(local[4],local[7]);
|
||||
SWAP(local[5],local[6]);
|
||||
#endif
|
||||
int x = decode_uint16(&local[0]);
|
||||
int y = decode_uint16(&local[2]);
|
||||
uint32_t v = decode_uint32(&local[4]);
|
||||
bool flip_h = v&(1<<29);
|
||||
bool flip_v = v&(1<<30);
|
||||
v&=(1<<29)-1;
|
||||
|
||||
// if (x<-20 || y <-20 || x>4000 || y>4000)
|
||||
// continue;
|
||||
set_cell(x,y,v,flip_h,flip_v);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DVector<int> TileMap::_get_tile_data() const {
|
||||
|
||||
DVector<int> data;
|
||||
data.resize(tile_map.size()*2);
|
||||
DVector<int>::Write w = data.write();
|
||||
|
||||
int idx=0;
|
||||
for(const Map<PosKey,Cell>::Element *E=tile_map.front();E;E=E->next()) {
|
||||
|
||||
uint8_t *ptr = (uint8_t*)&w[idx];
|
||||
encode_uint16(E->key().x,&ptr[0]);
|
||||
encode_uint16(E->key().y,&ptr[2]);
|
||||
uint32_t val = E->get().id;
|
||||
if (E->get().flip_h)
|
||||
val|=(1<<29);
|
||||
if (E->get().flip_v)
|
||||
val|=(1<<30);
|
||||
|
||||
encode_uint32(val,&ptr[4]);
|
||||
idx+=2;
|
||||
}
|
||||
|
||||
|
||||
w = DVector<int>::Write();
|
||||
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
Rect2 TileMap::get_item_rect() const {
|
||||
|
||||
const_cast<TileMap*>(this)->_update_dirty_quadrants();
|
||||
return rect_cache;
|
||||
}
|
||||
|
||||
void TileMap::_bind_methods() {
|
||||
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_tileset","tileset:TileSet"),&TileMap::set_tileset);
|
||||
ObjectTypeDB::bind_method(_MD("get_tileset:TileSet"),&TileMap::get_tileset);
|
||||
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_cell_size","size"),&TileMap::set_cell_size);
|
||||
ObjectTypeDB::bind_method(_MD("get_cell_size"),&TileMap::get_cell_size);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_quadrant_size","size"),&TileMap::set_quadrant_size);
|
||||
ObjectTypeDB::bind_method(_MD("get_quadrant_size"),&TileMap::get_quadrant_size);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_center_x","enable"),&TileMap::set_center_x);
|
||||
ObjectTypeDB::bind_method(_MD("get_center_x"),&TileMap::get_center_x);
|
||||
|
||||
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_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);
|
||||
ObjectTypeDB::bind_method(_MD("is_cell_x_flipped","x","y"),&TileMap::is_cell_x_flipped);
|
||||
ObjectTypeDB::bind_method(_MD("is_cell_y_flipped","x","y"),&TileMap::is_cell_y_flipped);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("clear"),&TileMap::clear);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_clear_quadrants"),&TileMap::_clear_quadrants);
|
||||
ObjectTypeDB::bind_method(_MD("_recreate_quadrants"),&TileMap::_recreate_quadrants);
|
||||
ObjectTypeDB::bind_method(_MD("_update_dirty_quadrants"),&TileMap::_update_dirty_quadrants);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_set_tile_data"),&TileMap::_set_tile_data);
|
||||
ObjectTypeDB::bind_method(_MD("_get_tile_data"),&TileMap::_get_tile_data);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"cell_size",PROPERTY_HINT_RANGE,"1,8192,1"),_SCS("set_cell_size"),_SCS("get_cell_size"));
|
||||
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"));
|
||||
|
||||
BIND_CONSTANT( INVALID_CELL );
|
||||
}
|
||||
|
||||
TileMap::TileMap() {
|
||||
|
||||
|
||||
|
||||
rect_cache_dirty=true;
|
||||
pending_update=false;
|
||||
quadrant_size=16;
|
||||
cell_size=64;
|
||||
center_x=false;
|
||||
center_y=false;
|
||||
|
||||
fp_adjust=0.4;
|
||||
fp_adjust=0.4;
|
||||
}
|
||||
|
||||
TileMap::~TileMap() {
|
||||
|
||||
clear();
|
||||
}
|
||||
154
scene/2d/tile_map.h
Normal file
154
scene/2d/tile_map.h
Normal file
@ -0,0 +1,154 @@
|
||||
/*************************************************************************/
|
||||
/* tile_map.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef TILE_MAP_H
|
||||
#define TILE_MAP_H
|
||||
|
||||
#include "scene/2d/node_2d.h"
|
||||
#include "scene/resources/tile_set.h"
|
||||
#include "self_list.h"
|
||||
#include "vset.h"
|
||||
|
||||
class TileMap : public Node2D {
|
||||
|
||||
OBJ_TYPE( TileMap, Node2D );
|
||||
|
||||
|
||||
Ref<TileSet> tile_set;
|
||||
int cell_size;
|
||||
int quadrant_size;
|
||||
bool center_x,center_y;
|
||||
|
||||
union PosKey {
|
||||
|
||||
struct {
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
};
|
||||
|
||||
uint32_t key;
|
||||
bool operator<(const PosKey& pk) const { return key<pk.key; }
|
||||
|
||||
PosKey(int16_t p_x, int16_t p_y) { x=p_x; y=p_y; }
|
||||
PosKey() { key=0; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
union Cell {
|
||||
|
||||
struct {
|
||||
int32_t id:24;
|
||||
bool flip_h:1;
|
||||
bool flip_v:1;
|
||||
};
|
||||
|
||||
uint32_t _u32t;
|
||||
Cell() { _u32t=0; }
|
||||
};
|
||||
|
||||
|
||||
Map<PosKey,Cell> tile_map;
|
||||
struct Quadrant {
|
||||
|
||||
Vector2 pos;
|
||||
RID canvas_item;
|
||||
RID static_body;
|
||||
|
||||
SelfList<Quadrant> dirty_list;
|
||||
|
||||
VSet<PosKey> cells;
|
||||
|
||||
void operator=(const Quadrant& q) { pos=q.pos; canvas_item=q.canvas_item; static_body=q.static_body; cells=q.cells; }
|
||||
Quadrant(const Quadrant& q) : dirty_list(this) { pos=q.pos; canvas_item=q.canvas_item; static_body=q.static_body; cells=q.cells;}
|
||||
Quadrant() : dirty_list(this) {}
|
||||
};
|
||||
|
||||
Map<PosKey,Quadrant> quadrant_map;
|
||||
|
||||
SelfList<Quadrant>::List dirty_quadrant_list;
|
||||
|
||||
bool pending_update;
|
||||
|
||||
Rect2 rect_cache;
|
||||
bool rect_cache_dirty;
|
||||
float fp_adjust;
|
||||
|
||||
|
||||
Map<PosKey,Quadrant>::Element *_create_quadrant(const PosKey& p_qk);
|
||||
void _erase_quadrant(Map<PosKey,Quadrant>::Element *Q);
|
||||
void _make_quadrant_dirty(Map<PosKey,Quadrant>::Element *Q);
|
||||
void _recreate_quadrants();
|
||||
void _clear_quadrants();
|
||||
void _update_dirty_quadrants();
|
||||
void _update_quadrant_space(const RID& p_space);
|
||||
void _update_quadrant_transform();
|
||||
void _recompute_rect_cache();
|
||||
|
||||
void _set_tile_data(const DVector<int>& p_data);
|
||||
DVector<int> _get_tile_data() const;
|
||||
protected:
|
||||
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
enum {
|
||||
INVALID_CELL=-1
|
||||
};
|
||||
|
||||
void set_tileset(const Ref<TileSet>& p_tileset);
|
||||
Ref<TileSet> get_tileset() const;
|
||||
|
||||
void set_cell_size(int p_size);
|
||||
int get_cell_size() const;
|
||||
|
||||
void set_quadrant_size(int p_size);
|
||||
int get_quadrant_size() const;
|
||||
|
||||
void set_center_x(bool p_enable);
|
||||
bool get_center_x() const;
|
||||
void set_center_y(bool p_enable);
|
||||
bool get_center_y() const;
|
||||
|
||||
void set_cell(int p_x,int p_y,int p_tile,bool p_flip_x=false,bool p_flip_y=false);
|
||||
int get_cell(int p_x,int p_y) const;
|
||||
bool is_cell_x_flipped(int p_x,int p_y) const;
|
||||
bool is_cell_y_flipped(int p_x,int p_y) const;
|
||||
|
||||
Rect2 get_item_rect() const;
|
||||
|
||||
void clear();
|
||||
|
||||
TileMap();
|
||||
~TileMap();
|
||||
};
|
||||
|
||||
#endif // TILE_MAP_H
|
||||
322
scene/2d/visibility_notifier_2d.cpp
Normal file
322
scene/2d/visibility_notifier_2d.cpp
Normal file
@ -0,0 +1,322 @@
|
||||
/*************************************************************************/
|
||||
/* visibility_notifier_2d.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "visibility_notifier_2d.h"
|
||||
|
||||
#include "scene/scene_string_names.h"
|
||||
#include "scene/2d/physics_body_2d.h"
|
||||
#include "scene/animation/animation_player.h"
|
||||
#include "scene/scene_string_names.h"
|
||||
|
||||
void VisibilityNotifier2D::_enter_viewport(Viewport* p_viewport) {
|
||||
|
||||
ERR_FAIL_COND(viewports.has(p_viewport));
|
||||
viewports.insert(p_viewport);
|
||||
if (viewports.size()==1) {
|
||||
emit_signal(SceneStringNames::get_singleton()->enter_screen);
|
||||
_screen_enter();
|
||||
|
||||
|
||||
}
|
||||
emit_signal(SceneStringNames::get_singleton()->enter_viewport,p_viewport);
|
||||
|
||||
}
|
||||
|
||||
void VisibilityNotifier2D::_exit_viewport(Viewport* p_viewport){
|
||||
|
||||
ERR_FAIL_COND(!viewports.has(p_viewport));
|
||||
viewports.erase(p_viewport);
|
||||
|
||||
emit_signal(SceneStringNames::get_singleton()->exit_viewport,p_viewport);
|
||||
if (viewports.size()==0) {
|
||||
emit_signal(SceneStringNames::get_singleton()->exit_screen);
|
||||
|
||||
_screen_exit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void VisibilityNotifier2D::set_rect(const Rect2& p_rect){
|
||||
|
||||
rect=p_rect;
|
||||
if (is_inside_scene())
|
||||
get_world_2d()->_update_notifier(this,get_global_transform().xform(rect));
|
||||
|
||||
_change_notify("rect");
|
||||
}
|
||||
|
||||
Rect2 VisibilityNotifier2D::get_item_rect() const {
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
Rect2 VisibilityNotifier2D::get_rect() const{
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
|
||||
void VisibilityNotifier2D::_notification(int p_what) {
|
||||
|
||||
|
||||
switch(p_what) {
|
||||
case NOTIFICATION_ENTER_SCENE: {
|
||||
|
||||
//get_world_2d()->
|
||||
get_world_2d()->_register_notifier(this,get_global_transform().xform(rect));
|
||||
} break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
|
||||
//get_world_2d()->
|
||||
get_world_2d()->_update_notifier(this,get_global_transform().xform(rect));
|
||||
} break;
|
||||
case NOTIFICATION_DRAW: {
|
||||
|
||||
if (get_scene()->is_editor_hint()) {
|
||||
|
||||
draw_rect(rect,Color(1,0.5,1,0.2));
|
||||
}
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_SCENE: {
|
||||
|
||||
get_world_2d()->_remove_notifier(this);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
bool VisibilityNotifier2D::is_on_screen() const {
|
||||
|
||||
return viewports.size()>0;
|
||||
}
|
||||
|
||||
void VisibilityNotifier2D::_bind_methods(){
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_rect","rect"),&VisibilityNotifier2D::set_rect);
|
||||
ObjectTypeDB::bind_method(_MD("get_rect"),&VisibilityNotifier2D::get_rect);
|
||||
ObjectTypeDB::bind_method(_MD("is_on_screen"),&VisibilityNotifier2D::is_on_screen);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::RECT2,"rect"),_SCS("set_rect"),_SCS("get_rect"));
|
||||
|
||||
ADD_SIGNAL( MethodInfo("enter_viewport",PropertyInfo(Variant::OBJECT,"viewport",PROPERTY_HINT_RESOURCE_TYPE,"Viewport")) );
|
||||
ADD_SIGNAL( MethodInfo("exit_viewport",PropertyInfo(Variant::OBJECT,"viewport",PROPERTY_HINT_RESOURCE_TYPE,"Viewport")) );
|
||||
ADD_SIGNAL( MethodInfo("enter_screen"));
|
||||
ADD_SIGNAL( MethodInfo("exit_screen"));
|
||||
}
|
||||
|
||||
|
||||
VisibilityNotifier2D::VisibilityNotifier2D() {
|
||||
|
||||
rect=Rect2(-10,-10,20,20);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
|
||||
void VisibilityEnabler2D::_screen_enter() {
|
||||
|
||||
|
||||
for(Map<Node*,Variant>::Element *E=nodes.front();E;E=E->next()) {
|
||||
|
||||
_change_node_state(E->key(),true);
|
||||
}
|
||||
|
||||
visible=true;
|
||||
}
|
||||
|
||||
void VisibilityEnabler2D::_screen_exit(){
|
||||
|
||||
for(Map<Node*,Variant>::Element *E=nodes.front();E;E=E->next()) {
|
||||
|
||||
_change_node_state(E->key(),false);
|
||||
}
|
||||
|
||||
visible=false;
|
||||
}
|
||||
|
||||
void VisibilityEnabler2D::_find_nodes(Node* p_node) {
|
||||
|
||||
|
||||
bool add=false;
|
||||
Variant meta;
|
||||
|
||||
if (enabler[ENABLER_FREEZE_BODIES]) {
|
||||
|
||||
RigidBody2D *rb2d = p_node->cast_to<RigidBody2D>();
|
||||
if (rb2d && ((rb2d->get_mode()==RigidBody2D::MODE_CHARACTER || (rb2d->get_mode()==RigidBody2D::MODE_RIGID && !rb2d->is_able_to_sleep())))) {
|
||||
|
||||
|
||||
add=true;
|
||||
meta=rb2d->get_mode();
|
||||
}
|
||||
}
|
||||
|
||||
if (enabler[ENABLER_PAUSE_ANIMATIONS]) {
|
||||
|
||||
AnimationPlayer *ap = p_node->cast_to<AnimationPlayer>();
|
||||
if (ap) {
|
||||
add=true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (add) {
|
||||
|
||||
p_node->connect(SceneStringNames::get_singleton()->exit_scene,this,"_node_removed",varray(p_node),CONNECT_ONESHOT);
|
||||
nodes[p_node]=meta;
|
||||
_change_node_state(p_node,false);
|
||||
}
|
||||
|
||||
for(int i=0;i<p_node->get_child_count();i++) {
|
||||
Node *c = p_node->get_child(i);
|
||||
if (c->get_filename()!=String())
|
||||
continue; //skip, instance
|
||||
|
||||
_find_nodes(c);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void VisibilityEnabler2D::_notification(int p_what){
|
||||
|
||||
if (p_what==NOTIFICATION_ENTER_SCENE) {
|
||||
|
||||
if (get_scene()->is_editor_hint())
|
||||
return;
|
||||
|
||||
|
||||
Node *from = this;
|
||||
//find where current scene starts
|
||||
while(from->get_parent() && from->get_filename()==String())
|
||||
from=from->get_parent();
|
||||
|
||||
_find_nodes(from);
|
||||
|
||||
}
|
||||
|
||||
if (p_what==NOTIFICATION_EXIT_SCENE) {
|
||||
|
||||
if (get_scene()->is_editor_hint())
|
||||
return;
|
||||
|
||||
|
||||
Node *from = this;
|
||||
//find where current scene starts
|
||||
|
||||
for (Map<Node*,Variant>::Element *E=nodes.front();E;E=E->next()) {
|
||||
|
||||
if (!visible)
|
||||
_change_node_state(E->key(),true);
|
||||
E->key()->disconnect(SceneStringNames::get_singleton()->exit_scene,this,"_node_removed");
|
||||
}
|
||||
|
||||
nodes.clear();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void VisibilityEnabler2D::_change_node_state(Node* p_node,bool p_enabled) {
|
||||
|
||||
ERR_FAIL_COND(!nodes.has(p_node));
|
||||
|
||||
{
|
||||
RigidBody2D *rb = p_node->cast_to<RigidBody2D>();
|
||||
if (rb) {
|
||||
|
||||
if (p_enabled) {
|
||||
RigidBody2D::Mode mode = RigidBody2D::Mode(nodes[p_node].operator int());
|
||||
//rb->set_mode(mode);
|
||||
rb->set_active(true);
|
||||
} else {
|
||||
//rb->set_mode(RigidBody2D::MODE_STATIC);
|
||||
rb->set_active(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
AnimationPlayer *ap=p_node->cast_to<AnimationPlayer>();
|
||||
|
||||
if (ap) {
|
||||
|
||||
ap->set_active(p_enabled);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void VisibilityEnabler2D::_node_removed(Node* p_node) {
|
||||
|
||||
if (!visible)
|
||||
_change_node_state(p_node,true);
|
||||
//changed to one shot, not needed
|
||||
//p_node->disconnect(SceneStringNames::get_singleton()->exit_scene,this,"_node_removed");
|
||||
nodes.erase(p_node);
|
||||
|
||||
}
|
||||
|
||||
void VisibilityEnabler2D::_bind_methods(){
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_enabler","enabler","enabled"),&VisibilityEnabler2D::set_enabler);
|
||||
ObjectTypeDB::bind_method(_MD("is_enabler_enabled","enabler"),&VisibilityEnabler2D::is_enabler_enabled);
|
||||
ObjectTypeDB::bind_method(_MD("_node_removed"),&VisibilityEnabler2D::_node_removed);
|
||||
|
||||
ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"enabler/pause_animations"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_PAUSE_ANIMATIONS );
|
||||
ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"enabler/freeze_bodies"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_FREEZE_BODIES);
|
||||
|
||||
BIND_CONSTANT( ENABLER_FREEZE_BODIES );
|
||||
BIND_CONSTANT( ENABLER_PAUSE_ANIMATIONS );
|
||||
BIND_CONSTANT( ENABLER_MAX);
|
||||
}
|
||||
|
||||
void VisibilityEnabler2D::set_enabler(Enabler p_enabler,bool p_enable){
|
||||
|
||||
ERR_FAIL_INDEX(p_enabler,ENABLER_MAX);
|
||||
enabler[p_enabler]=p_enable;
|
||||
|
||||
}
|
||||
bool VisibilityEnabler2D::is_enabler_enabled(Enabler p_enabler) const{
|
||||
|
||||
ERR_FAIL_INDEX_V(p_enabler,ENABLER_MAX,false);
|
||||
return enabler[p_enabler];
|
||||
|
||||
}
|
||||
|
||||
VisibilityEnabler2D::VisibilityEnabler2D() {
|
||||
|
||||
for(int i=0;i<ENABLER_MAX;i++)
|
||||
enabler[i]=true;
|
||||
|
||||
visible=false;
|
||||
|
||||
}
|
||||
|
||||
109
scene/2d/visibility_notifier_2d.h
Normal file
109
scene/2d/visibility_notifier_2d.h
Normal file
@ -0,0 +1,109 @@
|
||||
/*************************************************************************/
|
||||
/* visibility_notifier_2d.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef VISIBILITY_NOTIFIER_2D_H
|
||||
#define VISIBILITY_NOTIFIER_2D_H
|
||||
|
||||
#include "scene/2d/node_2d.h"
|
||||
|
||||
class Viewport;
|
||||
class VisibilityNotifier2D : public Node2D {
|
||||
|
||||
OBJ_TYPE(VisibilityNotifier2D,Node2D);
|
||||
|
||||
Set<Viewport*> viewports;
|
||||
|
||||
Rect2 rect;
|
||||
|
||||
protected:
|
||||
friend class SpatialIndexer2D;
|
||||
|
||||
void _enter_viewport(Viewport* p_viewport);
|
||||
void _exit_viewport(Viewport* p_viewport);
|
||||
|
||||
|
||||
virtual void _screen_enter() {}
|
||||
virtual void _screen_exit() {}
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_rect(const Rect2& p_rect);
|
||||
Rect2 get_rect() const;
|
||||
|
||||
bool is_on_screen() const;
|
||||
|
||||
virtual Rect2 get_item_rect() const;
|
||||
|
||||
VisibilityNotifier2D();
|
||||
};
|
||||
|
||||
|
||||
class VisibilityEnabler2D : public VisibilityNotifier2D {
|
||||
|
||||
OBJ_TYPE(VisibilityEnabler2D,VisibilityNotifier2D);
|
||||
public:
|
||||
|
||||
enum Enabler {
|
||||
ENABLER_PAUSE_ANIMATIONS,
|
||||
ENABLER_FREEZE_BODIES,
|
||||
ENABLER_MAX
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
virtual void _screen_enter();
|
||||
virtual void _screen_exit();
|
||||
|
||||
bool visible;
|
||||
|
||||
void _find_nodes(Node* p_node);
|
||||
|
||||
Map<Node*,Variant> nodes;
|
||||
void _node_removed(Node* p_node);
|
||||
bool enabler[ENABLER_MAX];
|
||||
|
||||
void _change_node_state(Node* p_node,bool p_enabled);
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
void set_enabler(Enabler p_enabler,bool p_enable);
|
||||
bool is_enabler_enabled(Enabler p_enabler) const;
|
||||
|
||||
VisibilityEnabler2D();
|
||||
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(VisibilityEnabler2D::Enabler);
|
||||
|
||||
|
||||
#endif // VISIBILITY_NOTIFIER_2D_H
|
||||
14
scene/3d/SCsub
Normal file
14
scene/3d/SCsub
Normal file
@ -0,0 +1,14 @@
|
||||
Import('env')
|
||||
|
||||
|
||||
print("V: "+env["disable_3d"])
|
||||
if (env["disable_3d"]=="yes"):
|
||||
|
||||
env.scene_sources.append("3d/spatial.cpp")
|
||||
env.scene_sources.append("3d/skeleton.cpp")
|
||||
else:
|
||||
env.add_source_files(env.scene_sources,"*.cpp")
|
||||
|
||||
Export('env')
|
||||
|
||||
|
||||
317
scene/3d/area.cpp
Normal file
317
scene/3d/area.cpp
Normal file
@ -0,0 +1,317 @@
|
||||
/*************************************************************************/
|
||||
/* area.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "area.h"
|
||||
#include "scene/scene_string_names.h"
|
||||
#include "servers/physics_server.h"
|
||||
void Area::set_space_override_mode(SpaceOverride p_mode) {
|
||||
|
||||
space_override=p_mode;
|
||||
PhysicsServer::get_singleton()->area_set_space_override_mode(get_rid(),PhysicsServer::AreaSpaceOverrideMode(p_mode));
|
||||
|
||||
|
||||
}
|
||||
Area::SpaceOverride Area::get_space_override_mode() const{
|
||||
|
||||
return space_override;
|
||||
}
|
||||
|
||||
void Area::set_gravity_is_point(bool p_enabled){
|
||||
|
||||
gravity_is_point=p_enabled;
|
||||
PhysicsServer::get_singleton()->area_set_param(get_rid(),PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT,p_enabled);
|
||||
|
||||
}
|
||||
bool Area::is_gravity_a_point() const{
|
||||
|
||||
return gravity_is_point;
|
||||
}
|
||||
|
||||
void Area::set_gravity_vector(const Vector3& p_vec){
|
||||
|
||||
gravity_vec=p_vec;
|
||||
PhysicsServer::get_singleton()->area_set_param(get_rid(),PhysicsServer::AREA_PARAM_GRAVITY_VECTOR,p_vec);
|
||||
|
||||
}
|
||||
Vector3 Area::get_gravity_vector() const{
|
||||
|
||||
return gravity_vec;
|
||||
}
|
||||
|
||||
void Area::set_gravity(real_t p_gravity){
|
||||
|
||||
gravity=p_gravity;
|
||||
PhysicsServer::get_singleton()->area_set_param(get_rid(),PhysicsServer::AREA_PARAM_GRAVITY,p_gravity);
|
||||
}
|
||||
real_t Area::get_gravity() const{
|
||||
|
||||
return gravity;
|
||||
}
|
||||
|
||||
void Area::set_density(real_t p_density){
|
||||
|
||||
density=p_density;
|
||||
PhysicsServer::get_singleton()->area_set_param(get_rid(),PhysicsServer::AREA_PARAM_DENSITY,p_density);
|
||||
}
|
||||
real_t Area::get_density() const{
|
||||
|
||||
return density;
|
||||
}
|
||||
|
||||
void Area::set_priority(real_t p_priority){
|
||||
|
||||
priority=p_priority;
|
||||
PhysicsServer::get_singleton()->area_set_param(get_rid(),PhysicsServer::AREA_PARAM_PRIORITY,p_priority);
|
||||
}
|
||||
real_t Area::get_priority() const{
|
||||
|
||||
return priority;
|
||||
}
|
||||
|
||||
|
||||
void Area::_body_enter_scene(ObjectID p_id) {
|
||||
|
||||
Object *obj = ObjectDB::get_instance(p_id);
|
||||
Node *node = obj ? obj->cast_to<Node>() : NULL;
|
||||
ERR_FAIL_COND(!node);
|
||||
|
||||
Map<ObjectID,BodyState>::Element *E=body_map.find(p_id);
|
||||
ERR_FAIL_COND(!E);
|
||||
ERR_FAIL_COND(E->get().in_scene);
|
||||
|
||||
E->get().in_scene=true;
|
||||
emit_signal(SceneStringNames::get_singleton()->body_enter,node);
|
||||
for(int i=0;i<E->get().shapes.size();i++) {
|
||||
|
||||
emit_signal(SceneStringNames::get_singleton()->body_enter_shape,p_id,node,E->get().shapes[i].body_shape,E->get().shapes[i].area_shape);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Area::_body_exit_scene(ObjectID p_id) {
|
||||
|
||||
Object *obj = ObjectDB::get_instance(p_id);
|
||||
Node *node = obj ? obj->cast_to<Node>() : NULL;
|
||||
ERR_FAIL_COND(!node);
|
||||
Map<ObjectID,BodyState>::Element *E=body_map.find(p_id);
|
||||
ERR_FAIL_COND(!E);
|
||||
ERR_FAIL_COND(!E->get().in_scene);
|
||||
E->get().in_scene=false;
|
||||
emit_signal(SceneStringNames::get_singleton()->body_exit,node);
|
||||
for(int i=0;i<E->get().shapes.size();i++) {
|
||||
|
||||
emit_signal(SceneStringNames::get_singleton()->body_exit_shape,p_id,node,E->get().shapes[i].body_shape,E->get().shapes[i].area_shape);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Area::_body_inout(int p_status,const RID& p_body, int p_instance, int p_body_shape,int p_area_shape) {
|
||||
|
||||
bool body_in = p_status==PhysicsServer::AREA_BODY_ADDED;
|
||||
ObjectID objid=p_instance;
|
||||
|
||||
Object *obj = ObjectDB::get_instance(objid);
|
||||
Node *node = obj ? obj->cast_to<Node>() : NULL;
|
||||
|
||||
Map<ObjectID,BodyState>::Element *E=body_map.find(objid);
|
||||
|
||||
ERR_FAIL_COND(!body_in && !E);
|
||||
|
||||
if (body_in) {
|
||||
if (!E) {
|
||||
|
||||
E = body_map.insert(objid,BodyState());
|
||||
E->get().rc=0;
|
||||
E->get().in_scene=node && node->is_inside_scene();
|
||||
if (node) {
|
||||
node->connect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene,make_binds(objid));
|
||||
node->connect(SceneStringNames::get_singleton()->exit_scene,this,SceneStringNames::get_singleton()->_body_exit_scene,make_binds(objid));
|
||||
if (E->get().in_scene) {
|
||||
emit_signal(SceneStringNames::get_singleton()->body_enter,node);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
E->get().rc++;
|
||||
if (node)
|
||||
E->get().shapes.insert(ShapePair(p_body_shape,p_area_shape));
|
||||
|
||||
|
||||
if (E->get().in_scene) {
|
||||
emit_signal(SceneStringNames::get_singleton()->body_enter_shape,objid,node,p_body_shape,p_area_shape);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
E->get().rc--;
|
||||
|
||||
if (node)
|
||||
E->get().shapes.erase(ShapePair(p_body_shape,p_area_shape));
|
||||
|
||||
bool eraseit=false;
|
||||
|
||||
if (E->get().rc==0) {
|
||||
|
||||
if (node) {
|
||||
node->disconnect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene);
|
||||
node->disconnect(SceneStringNames::get_singleton()->exit_scene,this,SceneStringNames::get_singleton()->_body_exit_scene);
|
||||
if (E->get().in_scene)
|
||||
emit_signal(SceneStringNames::get_singleton()->body_exit,obj);
|
||||
|
||||
}
|
||||
|
||||
eraseit=true;
|
||||
|
||||
}
|
||||
if (node && E->get().in_scene) {
|
||||
emit_signal(SceneStringNames::get_singleton()->body_exit_shape,objid,obj,p_body_shape,p_area_shape);
|
||||
}
|
||||
|
||||
if (eraseit)
|
||||
body_map.erase(E);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Area::_clear_monitoring() {
|
||||
|
||||
Map<ObjectID,BodyState> bmcopy = body_map;
|
||||
body_map.clear();
|
||||
//disconnect all monitored stuff
|
||||
|
||||
for (Map<ObjectID,BodyState>::Element *E=bmcopy.front();E;E=E->next()) {
|
||||
|
||||
Object *obj = ObjectDB::get_instance(E->key());
|
||||
Node *node = obj ? obj->cast_to<Node>() : NULL;
|
||||
ERR_CONTINUE(!node);
|
||||
if (!E->get().in_scene)
|
||||
continue;
|
||||
|
||||
for(int i=0;i<E->get().shapes.size();i++) {
|
||||
|
||||
emit_signal(SceneStringNames::get_singleton()->body_exit_shape,E->key(),node,E->get().shapes[i].body_shape,E->get().shapes[i].area_shape);
|
||||
}
|
||||
|
||||
emit_signal(SceneStringNames::get_singleton()->body_exit,obj);
|
||||
|
||||
node->disconnect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene);
|
||||
node->disconnect(SceneStringNames::get_singleton()->exit_scene,this,SceneStringNames::get_singleton()->_body_exit_scene);
|
||||
}
|
||||
|
||||
}
|
||||
void Area::_notification(int p_what) {
|
||||
|
||||
if (p_what==NOTIFICATION_EXIT_SCENE) {
|
||||
_clear_monitoring();
|
||||
}
|
||||
}
|
||||
|
||||
void Area::set_enable_monitoring(bool p_enable) {
|
||||
|
||||
if (p_enable==monitoring)
|
||||
return;
|
||||
|
||||
monitoring=p_enable;
|
||||
|
||||
if (monitoring) {
|
||||
|
||||
PhysicsServer::get_singleton()->area_set_monitor_callback(get_rid(),this,"_body_inout");
|
||||
} else {
|
||||
PhysicsServer::get_singleton()->area_set_monitor_callback(get_rid(),NULL,StringName());
|
||||
_clear_monitoring();
|
||||
}
|
||||
}
|
||||
|
||||
bool Area::is_monitoring_enabled() const {
|
||||
|
||||
return monitoring;
|
||||
}
|
||||
|
||||
|
||||
void Area::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_body_enter_scene","id"),&Area::_body_enter_scene);
|
||||
ObjectTypeDB::bind_method(_MD("_body_exit_scene","id"),&Area::_body_exit_scene);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_space_override_mode","enable"),&Area::set_space_override_mode);
|
||||
ObjectTypeDB::bind_method(_MD("get_space_override_mode"),&Area::get_space_override_mode);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_gravity_is_point","enable"),&Area::set_gravity_is_point);
|
||||
ObjectTypeDB::bind_method(_MD("is_gravity_a_point"),&Area::is_gravity_a_point);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_gravity_vector","vector"),&Area::set_gravity_vector);
|
||||
ObjectTypeDB::bind_method(_MD("get_gravity_vector"),&Area::get_gravity_vector);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_gravity","gravity"),&Area::set_gravity);
|
||||
ObjectTypeDB::bind_method(_MD("get_gravity"),&Area::get_gravity);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_density","density"),&Area::set_density);
|
||||
ObjectTypeDB::bind_method(_MD("get_density"),&Area::get_density);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_priority","priority"),&Area::set_priority);
|
||||
ObjectTypeDB::bind_method(_MD("get_priority"),&Area::get_priority);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_enable_monitoring","enable"),&Area::set_enable_monitoring);
|
||||
ObjectTypeDB::bind_method(_MD("is_monitoring_enabled"),&Area::is_monitoring_enabled);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_body_inout"),&Area::_body_inout);
|
||||
|
||||
|
||||
ADD_SIGNAL( MethodInfo("body_enter_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"area_shape")));
|
||||
ADD_SIGNAL( MethodInfo("body_exit_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"area_shape")));
|
||||
ADD_SIGNAL( MethodInfo("body_enter",PropertyInfo(Variant::OBJECT,"body")));
|
||||
ADD_SIGNAL( MethodInfo("body_exit",PropertyInfo(Variant::OBJECT,"body")));
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"space_override",PROPERTY_HINT_ENUM,"Disabled,Combine,Replace"),_SCS("set_space_override_mode"),_SCS("get_space_override_mode"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"gravity_point"),_SCS("set_gravity_is_point"),_SCS("is_gravity_a_point"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"gravity_vec"),_SCS("set_gravity_vector"),_SCS("get_gravity_vector"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity",PROPERTY_HINT_RANGE,"-1024,1024,0.01"),_SCS("set_gravity"),_SCS("get_gravity"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"density",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_density"),_SCS("get_density"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"priority",PROPERTY_HINT_RANGE,"0,128,1"),_SCS("set_priority"),_SCS("get_priority"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"monitoring"),_SCS("set_enable_monitoring"),_SCS("is_monitoring_enabled"));
|
||||
|
||||
}
|
||||
|
||||
Area::Area() : CollisionObject(PhysicsServer::get_singleton()->area_create(),true) {
|
||||
|
||||
space_override=SPACE_OVERRIDE_DISABLED;
|
||||
set_gravity(9.8);;
|
||||
set_gravity_vector(Vector3(0,-1,0));
|
||||
gravity_is_point=false;
|
||||
density=0.1;
|
||||
priority=0;
|
||||
monitoring=false;
|
||||
|
||||
}
|
||||
|
||||
Area::~Area() {
|
||||
|
||||
|
||||
}
|
||||
121
scene/3d/area.h
Normal file
121
scene/3d/area.h
Normal file
@ -0,0 +1,121 @@
|
||||
/*************************************************************************/
|
||||
/* area.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef AREA_H
|
||||
#define AREA_H
|
||||
|
||||
#include "scene/3d/collision_object.h"
|
||||
#include "vset.h"
|
||||
|
||||
class Area : public CollisionObject {
|
||||
|
||||
OBJ_TYPE( Area, CollisionObject );
|
||||
public:
|
||||
|
||||
enum SpaceOverride {
|
||||
SPACE_OVERRIDE_DISABLED,
|
||||
SPACE_OVERRIDE_COMBINE,
|
||||
SPACE_OVERRIDE_REPLACE
|
||||
};
|
||||
private:
|
||||
|
||||
|
||||
SpaceOverride space_override;
|
||||
Vector3 gravity_vec;
|
||||
real_t gravity;
|
||||
bool gravity_is_point;
|
||||
real_t density;
|
||||
int priority;
|
||||
bool monitoring;
|
||||
|
||||
void _body_inout(int p_status,const RID& p_body, int p_instance, int p_body_shape,int p_area_shape);
|
||||
|
||||
void _body_enter_scene(ObjectID p_id);
|
||||
void _body_exit_scene(ObjectID p_id);
|
||||
|
||||
struct ShapePair {
|
||||
|
||||
int body_shape;
|
||||
int area_shape;
|
||||
bool operator<(const ShapePair& p_sp) const {
|
||||
if (body_shape==p_sp.body_shape)
|
||||
return area_shape < p_sp.area_shape;
|
||||
else
|
||||
return body_shape < p_sp.body_shape;
|
||||
}
|
||||
|
||||
ShapePair() {}
|
||||
ShapePair(int p_bs, int p_as) { body_shape=p_bs; area_shape=p_as; }
|
||||
};
|
||||
|
||||
struct BodyState {
|
||||
|
||||
int rc;
|
||||
bool in_scene;
|
||||
VSet<ShapePair> shapes;
|
||||
};
|
||||
|
||||
Map<ObjectID,BodyState> body_map;
|
||||
void _clear_monitoring();
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_space_override_mode(SpaceOverride p_mode);
|
||||
SpaceOverride get_space_override_mode() const;
|
||||
|
||||
void set_gravity_is_point(bool p_enabled);
|
||||
bool is_gravity_a_point() const;
|
||||
|
||||
void set_gravity_vector(const Vector3& p_vec);
|
||||
Vector3 get_gravity_vector() const;
|
||||
|
||||
void set_gravity(real_t p_gravity);
|
||||
real_t get_gravity() const;
|
||||
|
||||
void set_density(real_t p_density);
|
||||
real_t get_density() const;
|
||||
|
||||
void set_priority(real_t p_priority);
|
||||
real_t get_priority() const;
|
||||
|
||||
void set_enable_monitoring(bool p_enable);
|
||||
bool is_monitoring_enabled() const;
|
||||
|
||||
|
||||
Area();
|
||||
~Area();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(Area::SpaceOverride);
|
||||
|
||||
#endif // AREA__H
|
||||
829
scene/3d/body_shape.cpp
Normal file
829
scene/3d/body_shape.cpp
Normal file
@ -0,0 +1,829 @@
|
||||
/*************************************************************************/
|
||||
/* body_shape.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "body_shape.h"
|
||||
#include "servers/visual_server.h"
|
||||
#include "scene/resources/sphere_shape.h"
|
||||
#include "scene/resources/ray_shape.h"
|
||||
#include "scene/resources/box_shape.h"
|
||||
#include "scene/resources/capsule_shape.h"
|
||||
//#include "scene/resources/cylinder_shape.h"
|
||||
#include "scene/resources/convex_polygon_shape.h"
|
||||
#include "scene/resources/concave_polygon_shape.h"
|
||||
#include "scene/resources/height_map_shape.h"
|
||||
#include "scene/resources/plane_shape.h"
|
||||
#include "mesh_instance.h"
|
||||
#include "physics_body.h"
|
||||
#include "quick_hull.h"
|
||||
|
||||
void CollisionShape::_update_body() {
|
||||
|
||||
|
||||
|
||||
if (get_parent() && get_parent()->cast_to<CollisionObject>())
|
||||
get_parent()->cast_to<CollisionObject>()->_update_shapes_from_children();
|
||||
|
||||
}
|
||||
|
||||
void CollisionShape::make_convex_from_brothers() {
|
||||
|
||||
Node *p = get_parent();
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
for(int i=0;i<p->get_child_count();i++) {
|
||||
|
||||
Node *n = p->get_child(i);
|
||||
if (n->cast_to<MeshInstance>()) {
|
||||
|
||||
MeshInstance *mi=n->cast_to<MeshInstance>();
|
||||
Ref<Mesh> m = mi->get_mesh();
|
||||
if (m.is_valid()) {
|
||||
|
||||
Ref<Shape> s = m->create_convex_shape();
|
||||
set_shape(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CollisionShape::_update_indicator() {
|
||||
|
||||
while (VisualServer::get_singleton()->mesh_get_surface_count(indicator))
|
||||
VisualServer::get_singleton()->mesh_remove_surface(indicator,0);
|
||||
|
||||
if (shape.is_null())
|
||||
return;
|
||||
|
||||
DVector<Vector3> points;
|
||||
DVector<Vector3> normals;
|
||||
|
||||
VS::PrimitiveType pt = VS::PRIMITIVE_TRIANGLES;
|
||||
|
||||
if (shape->cast_to<RayShape>()) {
|
||||
|
||||
RayShape *rs = shape->cast_to<RayShape>();
|
||||
points.push_back(Vector3());
|
||||
points.push_back(Vector3(0,0,rs->get_length()));
|
||||
pt = VS::PRIMITIVE_LINES;
|
||||
} else if (shape->cast_to<SphereShape>()) {
|
||||
|
||||
// VisualServer *vs=VisualServer::get_singleton();
|
||||
SphereShape *shapeptr=shape->cast_to<SphereShape>();
|
||||
|
||||
|
||||
Color col(0.4,1.0,1.0,0.5);
|
||||
|
||||
int lats=6;
|
||||
int lons=12;
|
||||
float size=shapeptr->get_radius();
|
||||
|
||||
|
||||
for(int i = 1; i <= lats; i++) {
|
||||
double lat0 = Math_PI * (-0.5 + (double) (i - 1) / lats);
|
||||
double z0 = Math::sin(lat0);
|
||||
double zr0 = Math::cos(lat0);
|
||||
|
||||
double lat1 = Math_PI * (-0.5 + (double) i / lats);
|
||||
double z1 = Math::sin(lat1);
|
||||
double zr1 = Math::cos(lat1);
|
||||
|
||||
for(int j = lons; j >= 1; j--) {
|
||||
|
||||
double lng0 = 2 * Math_PI * (double) (j - 1) / lons;
|
||||
double x0 = Math::cos(lng0);
|
||||
double y0 = Math::sin(lng0);
|
||||
|
||||
double lng1 = 2 * Math_PI * (double) (j) / lons;
|
||||
double x1 = Math::cos(lng1);
|
||||
double y1 = Math::sin(lng1);
|
||||
|
||||
Vector3 v4=Vector3(x0 * zr0, z0, y0 *zr0)*size;
|
||||
Vector3 v3=Vector3(x0 * zr1, z1, y0 *zr1)*size;
|
||||
Vector3 v2=Vector3(x1 * zr1, z1, y1 *zr1)*size;
|
||||
Vector3 v1=Vector3(x1 * zr0, z0, y1 *zr0)*size;
|
||||
|
||||
Vector<Vector3> line;
|
||||
line.push_back(v1);
|
||||
line.push_back(v2);
|
||||
line.push_back(v3);
|
||||
line.push_back(v4);
|
||||
|
||||
|
||||
points.push_back(v1);
|
||||
points.push_back(v2);
|
||||
points.push_back(v3);
|
||||
|
||||
points.push_back(v1);
|
||||
points.push_back(v3);
|
||||
points.push_back(v4);
|
||||
|
||||
normals.push_back(v1.normalized());
|
||||
normals.push_back(v2.normalized());
|
||||
normals.push_back(v3.normalized());
|
||||
|
||||
normals.push_back(v1.normalized());
|
||||
normals.push_back(v3.normalized());
|
||||
normals.push_back(v4.normalized());
|
||||
|
||||
}
|
||||
}
|
||||
} else if (shape->cast_to<BoxShape>()) {
|
||||
|
||||
BoxShape *shapeptr=shape->cast_to<BoxShape>();
|
||||
|
||||
for (int i=0;i<6;i++) {
|
||||
|
||||
|
||||
Vector3 face_points[4];
|
||||
|
||||
|
||||
for (int j=0;j<4;j++) {
|
||||
|
||||
float v[3];
|
||||
v[0]=1.0;
|
||||
v[1]=1-2*((j>>1)&1);
|
||||
v[2]=v[1]*(1-2*(j&1));
|
||||
|
||||
for (int k=0;k<3;k++) {
|
||||
|
||||
if (i<3)
|
||||
face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1);
|
||||
else
|
||||
face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1);
|
||||
}
|
||||
}
|
||||
Vector3 normal;
|
||||
normal[i%3]=(i>=3?-1:1);
|
||||
|
||||
for(int j=0;j<4;j++)
|
||||
face_points[j]*=shapeptr->get_extents();
|
||||
|
||||
points.push_back(face_points[0]);
|
||||
points.push_back(face_points[1]);
|
||||
points.push_back(face_points[2]);
|
||||
|
||||
points.push_back(face_points[0]);
|
||||
points.push_back(face_points[2]);
|
||||
points.push_back(face_points[3]);
|
||||
|
||||
for(int n=0;n<6;n++)
|
||||
normals.push_back(normal);
|
||||
|
||||
}
|
||||
|
||||
} else if (shape->cast_to<ConvexPolygonShape>()) {
|
||||
|
||||
ConvexPolygonShape *shapeptr=shape->cast_to<ConvexPolygonShape>();
|
||||
|
||||
Geometry::MeshData md;
|
||||
QuickHull::build(Variant(shapeptr->get_points()),md);
|
||||
|
||||
for(int i=0;i<md.faces.size();i++) {
|
||||
|
||||
for(int j=2;j<md.faces[i].indices.size();j++) {
|
||||
points.push_back(md.vertices[md.faces[i].indices[0]]);
|
||||
points.push_back(md.vertices[md.faces[i].indices[j-1]]);
|
||||
points.push_back(md.vertices[md.faces[i].indices[j]]);
|
||||
normals.push_back(md.faces[i].plane.normal);
|
||||
normals.push_back(md.faces[i].plane.normal);
|
||||
normals.push_back(md.faces[i].plane.normal);
|
||||
}
|
||||
}
|
||||
} else if (shape->cast_to<ConcavePolygonShape>()) {
|
||||
|
||||
ConcavePolygonShape *shapeptr=shape->cast_to<ConcavePolygonShape>();
|
||||
|
||||
points = shapeptr->get_faces();
|
||||
for(int i=0;i<points.size()/3;i++) {
|
||||
|
||||
Vector3 n = Plane( points[i*3+0],points[i*3+1],points[i*3+2] ).normal;
|
||||
normals.push_back(n);
|
||||
normals.push_back(n);
|
||||
normals.push_back(n);
|
||||
}
|
||||
|
||||
} else if (shape->cast_to<CapsuleShape>()) {
|
||||
|
||||
CapsuleShape *shapeptr=shape->cast_to<CapsuleShape>();
|
||||
|
||||
DVector<Plane> planes = Geometry::build_capsule_planes(shapeptr->get_radius(), shapeptr->get_height()/2.0, 12, Vector3::AXIS_Z);
|
||||
Geometry::MeshData md = Geometry::build_convex_mesh(planes);
|
||||
|
||||
for(int i=0;i<md.faces.size();i++) {
|
||||
|
||||
for(int j=2;j<md.faces[i].indices.size();j++) {
|
||||
points.push_back(md.vertices[md.faces[i].indices[0]]);
|
||||
points.push_back(md.vertices[md.faces[i].indices[j-1]]);
|
||||
points.push_back(md.vertices[md.faces[i].indices[j]]);
|
||||
normals.push_back(md.faces[i].plane.normal);
|
||||
normals.push_back(md.faces[i].plane.normal);
|
||||
normals.push_back(md.faces[i].plane.normal);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} else if (shape->cast_to<PlaneShape>()) {
|
||||
|
||||
PlaneShape *shapeptr=shape->cast_to<PlaneShape>();
|
||||
|
||||
Plane p = shapeptr->get_plane();
|
||||
Vector3 n1 = p.get_any_perpendicular_normal();
|
||||
Vector3 n2 = p.normal.cross(n1).normalized();
|
||||
|
||||
Vector3 pface[4]={
|
||||
p.normal*p.d+n1*100.0+n2*100.0,
|
||||
p.normal*p.d+n1*100.0+n2*-100.0,
|
||||
p.normal*p.d+n1*-100.0+n2*-100.0,
|
||||
p.normal*p.d+n1*-100.0+n2*100.0,
|
||||
};
|
||||
|
||||
points.push_back(pface[0]);
|
||||
points.push_back(pface[1]);
|
||||
points.push_back(pface[2]);
|
||||
|
||||
points.push_back(pface[0]);
|
||||
points.push_back(pface[2]);
|
||||
points.push_back(pface[3]);
|
||||
|
||||
normals.push_back(p.normal);
|
||||
normals.push_back(p.normal);
|
||||
normals.push_back(p.normal);
|
||||
normals.push_back(p.normal);
|
||||
normals.push_back(p.normal);
|
||||
normals.push_back(p.normal);
|
||||
|
||||
}
|
||||
|
||||
if (!points.size())
|
||||
return;
|
||||
RID material = VisualServer::get_singleton()->fixed_material_create();
|
||||
VisualServer::get_singleton()->fixed_material_set_param(material,VS::FIXED_MATERIAL_PARAM_DIFFUSE,Color(0,0.6,0.7,0.3));
|
||||
VisualServer::get_singleton()->fixed_material_set_param(material,VS::FIXED_MATERIAL_PARAM_EMISSION,0.7);
|
||||
if (normals.size()==0)
|
||||
VisualServer::get_singleton()->material_set_flag(material,VS::MATERIAL_FLAG_UNSHADED,true);
|
||||
VisualServer::get_singleton()->material_set_flag(material,VS::MATERIAL_FLAG_DOUBLE_SIDED,true);
|
||||
Array d;
|
||||
d.resize(VS::ARRAY_MAX);
|
||||
d[VS::ARRAY_VERTEX]=points;
|
||||
if (normals.size())
|
||||
d[VS::ARRAY_NORMAL]=normals;
|
||||
VisualServer::get_singleton()->mesh_add_surface(indicator,pt,d);
|
||||
VisualServer::get_singleton()->mesh_surface_set_material(indicator,0,material,true);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CollisionShape::_add_to_collision_object(Object* p_cshape) {
|
||||
|
||||
CollisionObject *co=p_cshape->cast_to<CollisionObject>();
|
||||
ERR_FAIL_COND(!co);
|
||||
|
||||
if (shape.is_valid()) {
|
||||
|
||||
co->add_shape(shape,get_transform());
|
||||
if (trigger)
|
||||
co->set_shape_as_trigger( co->get_shape_count() -1, true );
|
||||
}
|
||||
}
|
||||
|
||||
void CollisionShape::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_ENTER_WORLD: {
|
||||
indicator_instance = VisualServer::get_singleton()->instance_create2(indicator,get_world()->get_scenario());
|
||||
} break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
VisualServer::get_singleton()->instance_set_transform(indicator_instance,get_global_transform());
|
||||
if (updating_body) {
|
||||
_update_body();
|
||||
}
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_WORLD: {
|
||||
if (indicator_instance.is_valid()) {
|
||||
VisualServer::get_singleton()->free(indicator_instance);
|
||||
indicator_instance=RID();
|
||||
}
|
||||
} break;
|
||||
case NOTIFICATION_UNPARENTED: {
|
||||
if (updating_body)
|
||||
_update_body();
|
||||
} break;
|
||||
case NOTIFICATION_PARENTED: {
|
||||
if (updating_body)
|
||||
_update_body();
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CollisionShape::resource_changed(RES res) {
|
||||
|
||||
update_gizmo();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CollisionShape::_bind_methods() {
|
||||
|
||||
//not sure if this should do anything
|
||||
ObjectTypeDB::bind_method(_MD("resource_changed"),&CollisionShape::resource_changed);
|
||||
ObjectTypeDB::bind_method(_MD("set_shape","shape"),&CollisionShape::set_shape);
|
||||
ObjectTypeDB::bind_method(_MD("get_shape"),&CollisionShape::get_shape);
|
||||
ObjectTypeDB::bind_method(_MD("_add_to_collision_object"),&CollisionShape::_add_to_collision_object);
|
||||
ObjectTypeDB::bind_method(_MD("set_trigger","enable"),&CollisionShape::set_trigger);
|
||||
ObjectTypeDB::bind_method(_MD("is_trigger"),&CollisionShape::is_trigger);
|
||||
ObjectTypeDB::bind_method(_MD("make_convex_from_brothers"),&CollisionShape::make_convex_from_brothers);
|
||||
ObjectTypeDB::set_method_flags("CollisionShape","make_convex_from_brothers",METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
|
||||
|
||||
|
||||
ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape"), _SCS("set_shape"), _SCS("get_shape"));
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"trigger"),_SCS("set_trigger"),_SCS("is_trigger"));
|
||||
}
|
||||
|
||||
|
||||
void CollisionShape::set_shape(const Ref<Shape> &p_shape) {
|
||||
|
||||
if (!shape.is_null())
|
||||
shape->unregister_owner(this);
|
||||
shape=p_shape;
|
||||
if (!shape.is_null())
|
||||
shape->register_owner(this);
|
||||
update_gizmo();
|
||||
if (updating_body)
|
||||
_update_body();
|
||||
}
|
||||
|
||||
Ref<Shape> CollisionShape::get_shape() const {
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
|
||||
void CollisionShape::set_updating_body(bool p_update) {
|
||||
updating_body=p_update;
|
||||
}
|
||||
|
||||
bool CollisionShape::is_updating_body() const {
|
||||
|
||||
return updating_body;
|
||||
}
|
||||
|
||||
void CollisionShape::set_trigger(bool p_trigger) {
|
||||
|
||||
trigger=p_trigger;
|
||||
if (updating_body)
|
||||
_update_body();
|
||||
}
|
||||
|
||||
bool CollisionShape::is_trigger() const{
|
||||
|
||||
return trigger;
|
||||
}
|
||||
|
||||
CollisionShape::CollisionShape() {
|
||||
|
||||
indicator = VisualServer::get_singleton()->mesh_create();
|
||||
updating_body=true;
|
||||
trigger=false;
|
||||
}
|
||||
|
||||
CollisionShape::~CollisionShape() {
|
||||
if (!shape.is_null())
|
||||
shape->unregister_owner(this);
|
||||
VisualServer::get_singleton()->free(indicator);
|
||||
}
|
||||
|
||||
#if 0
|
||||
#include "body_volume.h"
|
||||
|
||||
#include "scene/3d/physics_body.h"
|
||||
#include "geometry.h"
|
||||
|
||||
#define ADD_TRIANGLE( m_a, m_b, m_c, m_color)\
|
||||
{\
|
||||
Vector<Vector3> points;\
|
||||
points.resize(3);\
|
||||
points[0]=m_a;\
|
||||
points[1]=m_b;\
|
||||
points[2]=m_c;\
|
||||
Vector<Color> colors;\
|
||||
colors.resize(3);\
|
||||
colors[0]=m_color;\
|
||||
colors[1]=m_color;\
|
||||
colors[2]=m_color;\
|
||||
vs->poly_add_primitive(p_indicator,points,Vector<Vector3>(),colors,Vector<Vector3>());\
|
||||
}
|
||||
|
||||
|
||||
void CollisionShape::_notification(int p_what) {
|
||||
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_SCENE: {
|
||||
|
||||
|
||||
if (get_root_node()->get_editor() && !indicator.is_valid()) {
|
||||
|
||||
indicator=VisualServer::get_singleton()->poly_create();
|
||||
RID mat=VisualServer::get_singleton()->fixed_material_create();
|
||||
VisualServer::get_singleton()->material_set_flag( mat, VisualServer::MATERIAL_FLAG_UNSHADED, true );
|
||||
VisualServer::get_singleton()->material_set_flag( mat, VisualServer::MATERIAL_FLAG_WIREFRAME, true );
|
||||
VisualServer::get_singleton()->material_set_flag( mat, VisualServer::MATERIAL_FLAG_DOUBLE_SIDED, true );
|
||||
VisualServer::get_singleton()->material_set_line_width( mat, 3 );
|
||||
|
||||
VisualServer::get_singleton()->poly_set_material(indicator,mat,true);
|
||||
|
||||
update_indicator(indicator);
|
||||
}
|
||||
|
||||
if (indicator.is_valid()) {
|
||||
|
||||
indicator_instance=VisualServer::get_singleton()->instance_create2(indicator,get_world()->get_scenario());
|
||||
VisualServer::get_singleton()->instance_attach_object_instance_ID(indicator_instance,get_instance_ID());
|
||||
}
|
||||
volume_changed();
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_SCENE: {
|
||||
|
||||
if (indicator_instance.is_valid()) {
|
||||
|
||||
VisualServer::get_singleton()->free(indicator_instance);
|
||||
}
|
||||
volume_changed();
|
||||
} break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
|
||||
if (indicator_instance.is_valid()) {
|
||||
|
||||
VisualServer::get_singleton()->instance_set_transform(indicator_instance,get_global_transform());
|
||||
}
|
||||
volume_changed();
|
||||
} break;
|
||||
default: {}
|
||||
}
|
||||
}
|
||||
|
||||
void CollisionShape::volume_changed() {
|
||||
|
||||
if (indicator.is_valid())
|
||||
update_indicator(indicator);
|
||||
|
||||
Object *parent=get_parent();
|
||||
if (!parent)
|
||||
return;
|
||||
PhysicsBody *physics_body=parent->cast_to<PhysicsBody>();
|
||||
|
||||
ERR_EXPLAIN("CollisionShape parent is not of type PhysicsBody");
|
||||
ERR_FAIL_COND(!physics_body);
|
||||
|
||||
physics_body->recompute_child_volumes();
|
||||
|
||||
}
|
||||
|
||||
RID CollisionShape::_get_visual_instance_rid() const {
|
||||
|
||||
return indicator_instance;
|
||||
|
||||
}
|
||||
|
||||
void CollisionShape::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method("_get_visual_instance_rid",&CollisionShape::_get_visual_instance_rid);
|
||||
}
|
||||
|
||||
CollisionShape::CollisionShape() {
|
||||
|
||||
}
|
||||
|
||||
CollisionShape::~CollisionShape() {
|
||||
|
||||
if (indicator.is_valid()) {
|
||||
|
||||
VisualServer::get_singleton()->free(indicator);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CollisionShapeSphere::_set(const String& p_name, const Variant& p_value) {
|
||||
|
||||
if (p_name=="radius") {
|
||||
radius=p_value;
|
||||
volume_changed();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Variant CollisionShapeSphere::_get(const String& p_name) const {
|
||||
|
||||
if (p_name=="radius") {
|
||||
return radius;
|
||||
}
|
||||
|
||||
return Variant();
|
||||
}
|
||||
|
||||
void CollisionShapeSphere::_get_property_list( List<PropertyInfo> *p_list) const {
|
||||
|
||||
p_list->push_back( PropertyInfo(Variant::REAL,"radius",PROPERTY_HINT_RANGE,"0.01,16384,0.01") );
|
||||
}
|
||||
|
||||
void CollisionShapeSphere::update_indicator(RID p_indicator) {
|
||||
|
||||
VisualServer *vs=VisualServer::get_singleton();
|
||||
|
||||
vs->poly_clear(p_indicator);
|
||||
Color col(0.4,1.0,1.0,0.5);
|
||||
|
||||
int lats=6;
|
||||
int lons=12;
|
||||
float size=radius;
|
||||
|
||||
for(int i = 1; i <= lats; i++) {
|
||||
double lat0 = Math_PI * (-0.5 + (double) (i - 1) / lats);
|
||||
double z0 = Math::sin(lat0);
|
||||
double zr0 = Math::cos(lat0);
|
||||
|
||||
double lat1 = Math_PI * (-0.5 + (double) i / lats);
|
||||
double z1 = Math::sin(lat1);
|
||||
double zr1 = Math::cos(lat1);
|
||||
|
||||
for(int j = lons; j >= 1; j--) {
|
||||
|
||||
double lng0 = 2 * Math_PI * (double) (j - 1) / lons;
|
||||
double x0 = Math::cos(lng0);
|
||||
double y0 = Math::sin(lng0);
|
||||
|
||||
double lng1 = 2 * Math_PI * (double) (j) / lons;
|
||||
double x1 = Math::cos(lng1);
|
||||
double y1 = Math::sin(lng1);
|
||||
|
||||
Vector3 v4=Vector3(x0 * zr0, z0, y0 *zr0)*size;
|
||||
Vector3 v3=Vector3(x0 * zr1, z1, y0 *zr1)*size;
|
||||
Vector3 v2=Vector3(x1 * zr1, z1, y1 *zr1)*size;
|
||||
Vector3 v1=Vector3(x1 * zr0, z0, y1 *zr0)*size;
|
||||
|
||||
Vector<Vector3> line;
|
||||
line.push_back(v1);
|
||||
line.push_back(v2);
|
||||
line.push_back(v3);
|
||||
line.push_back(v4);
|
||||
|
||||
Vector<Color> cols;
|
||||
cols.push_back(col);
|
||||
cols.push_back(col);
|
||||
cols.push_back(col);
|
||||
cols.push_back(col);
|
||||
|
||||
|
||||
VisualServer::get_singleton()->poly_add_primitive(p_indicator,line,Vector<Vector3>(),cols,Vector<Vector3>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CollisionShapeSphere::append_to_volume(Ref<Shape> p_volume) {
|
||||
|
||||
p_volume->add_sphere_shape(radius,get_transform());
|
||||
}
|
||||
|
||||
|
||||
CollisionShapeSphere::CollisionShapeSphere() {
|
||||
|
||||
radius=1.0;
|
||||
}
|
||||
|
||||
/* BOX */
|
||||
|
||||
|
||||
void CollisionShapeBox::_set(const String& p_name, const Variant& p_value) {
|
||||
|
||||
if (p_name=="half_extents") {
|
||||
half_extents=p_value;
|
||||
volume_changed();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Variant CollisionShapeBox::_get(const String& p_name) const {
|
||||
|
||||
if (p_name=="half_extents") {
|
||||
return half_extents;
|
||||
}
|
||||
|
||||
return Variant();
|
||||
}
|
||||
|
||||
void CollisionShapeBox::_get_property_list( List<PropertyInfo> *p_list) const {
|
||||
|
||||
p_list->push_back( PropertyInfo(Variant::VECTOR3,"half_extents" ) );
|
||||
}
|
||||
|
||||
|
||||
void CollisionShapeBox::update_indicator(RID p_indicator) {
|
||||
|
||||
VisualServer *vs=VisualServer::get_singleton();
|
||||
|
||||
vs->poly_clear(p_indicator);
|
||||
Color col(0.4,1.0,1.0,0.5);
|
||||
|
||||
|
||||
for (int i=0;i<6;i++) {
|
||||
|
||||
|
||||
Vector3 face_points[4];
|
||||
|
||||
for (int j=0;j<4;j++) {
|
||||
|
||||
float v[3];
|
||||
v[0]=1.0;
|
||||
v[1]=1-2*((j>>1)&1);
|
||||
v[2]=v[1]*(1-2*(j&1));
|
||||
|
||||
for (int k=0;k<3;k++) {
|
||||
|
||||
if (i<3)
|
||||
face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1);
|
||||
else
|
||||
face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1);
|
||||
}
|
||||
}
|
||||
|
||||
for(int j=0;j<4;j++)
|
||||
face_points[i]*=half_extents;
|
||||
|
||||
ADD_TRIANGLE(face_points[0],face_points[1],face_points[2],col);
|
||||
ADD_TRIANGLE(face_points[2],face_points[3],face_points[0],col);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void CollisionShapeBox::append_to_volume(Ref<Shape> p_volume) {
|
||||
|
||||
p_volume->add_box_shape(half_extents,get_transform());
|
||||
}
|
||||
|
||||
|
||||
CollisionShapeBox::CollisionShapeBox() {
|
||||
|
||||
half_extents=Vector3(1,1,1);
|
||||
}
|
||||
|
||||
/* CYLINDER */
|
||||
|
||||
|
||||
void CollisionShapeCylinder::_set(const String& p_name, const Variant& p_value) {
|
||||
|
||||
if (p_name=="radius") {
|
||||
radius=p_value;
|
||||
volume_changed();
|
||||
}
|
||||
if (p_name=="height") {
|
||||
height=p_value;
|
||||
volume_changed();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Variant CollisionShapeCylinder::_get(const String& p_name) const {
|
||||
|
||||
if (p_name=="radius") {
|
||||
return radius;
|
||||
}
|
||||
if (p_name=="height") {
|
||||
return height;
|
||||
}
|
||||
return Variant();
|
||||
}
|
||||
|
||||
void CollisionShapeCylinder::_get_property_list( List<PropertyInfo> *p_list) const {
|
||||
|
||||
p_list->push_back( PropertyInfo(Variant::REAL,"radius",PROPERTY_HINT_RANGE,"0.01,16384,0.01") );
|
||||
p_list->push_back( PropertyInfo(Variant::REAL,"height",PROPERTY_HINT_RANGE,"0.01,16384,0.01") );
|
||||
}
|
||||
|
||||
|
||||
void CollisionShapeCylinder::update_indicator(RID p_indicator) {
|
||||
|
||||
VisualServer *vs=VisualServer::get_singleton();
|
||||
|
||||
vs->poly_clear(p_indicator);
|
||||
Color col(0.4,1.0,1.0,0.5);
|
||||
|
||||
DVector<Plane> planes = Geometry::build_cylinder_planes(radius, height, 12, Vector3::AXIS_Z);
|
||||
Geometry::MeshData md = Geometry::build_convex_mesh(planes);
|
||||
|
||||
for(int i=0;i<md.faces.size();i++) {
|
||||
|
||||
for(int j=2;j<md.faces[i].indices.size();j++) {
|
||||
ADD_TRIANGLE(md.vertices[md.faces[i].indices[0]],md.vertices[md.faces[i].indices[j-1]],md.vertices[md.faces[i].indices[j]],col);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CollisionShapeCylinder::append_to_volume(Ref<Shape> p_volume) {
|
||||
|
||||
p_volume->add_cylinder_shape(radius,height*2.0,get_transform());
|
||||
}
|
||||
|
||||
|
||||
CollisionShapeCylinder::CollisionShapeCylinder() {
|
||||
|
||||
height=1;
|
||||
radius=1;
|
||||
}
|
||||
|
||||
/* CAPSULE */
|
||||
|
||||
|
||||
void CollisionShapeCapsule::_set(const String& p_name, const Variant& p_value) {
|
||||
|
||||
if (p_name=="radius") {
|
||||
radius=p_value;
|
||||
volume_changed();
|
||||
}
|
||||
|
||||
if (p_name=="height") {
|
||||
height=p_value;
|
||||
volume_changed();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Variant CollisionShapeCapsule::_get(const String& p_name) const {
|
||||
|
||||
if (p_name=="radius") {
|
||||
return radius;
|
||||
}
|
||||
if (p_name=="height") {
|
||||
return height;
|
||||
}
|
||||
return Variant();
|
||||
}
|
||||
|
||||
void CollisionShapeCapsule::_get_property_list( List<PropertyInfo> *p_list) const {
|
||||
|
||||
p_list->push_back( PropertyInfo(Variant::REAL,"radius",PROPERTY_HINT_RANGE,"0.01,16384,0.01") );
|
||||
p_list->push_back( PropertyInfo(Variant::REAL,"height",PROPERTY_HINT_RANGE,"0.01,16384,0.01") );
|
||||
}
|
||||
|
||||
|
||||
void CollisionShapeCapsule::update_indicator(RID p_indicator) {
|
||||
|
||||
VisualServer *vs=VisualServer::get_singleton();
|
||||
|
||||
vs->poly_clear(p_indicator);
|
||||
Color col(0.4,1.0,1.0,0.5);
|
||||
|
||||
DVector<Plane> planes = Geometry::build_capsule_planes(radius, height, 12, 3, Vector3::AXIS_Z);
|
||||
Geometry::MeshData md = Geometry::build_convex_mesh(planes);
|
||||
|
||||
for(int i=0;i<md.faces.size();i++) {
|
||||
|
||||
for(int j=2;j<md.faces[i].indices.size();j++) {
|
||||
ADD_TRIANGLE(md.vertices[md.faces[i].indices[0]],md.vertices[md.faces[i].indices[j-1]],md.vertices[md.faces[i].indices[j]],col);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CollisionShapeCapsule::append_to_volume(Ref<Shape> p_volume) {
|
||||
|
||||
|
||||
p_volume->add_capsule_shape(radius,height,get_transform());
|
||||
}
|
||||
|
||||
|
||||
CollisionShapeCapsule::CollisionShapeCapsule() {
|
||||
|
||||
height=1;
|
||||
radius=1;
|
||||
}
|
||||
#endif
|
||||
80
scene/3d/body_shape.h
Normal file
80
scene/3d/body_shape.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*************************************************************************/
|
||||
/* body_shape.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef COLLISION_SHAPE_H
|
||||
#define COLLISION_SHAPE_H
|
||||
|
||||
#include "scene/3d/spatial.h"
|
||||
#include "scene/resources/shape.h"
|
||||
|
||||
class CollisionShape : public Spatial {
|
||||
|
||||
OBJ_TYPE( CollisionShape, Spatial );
|
||||
OBJ_CATEGORY("3D Physics Nodes");
|
||||
|
||||
RID _get_visual_instance_rid() const;
|
||||
|
||||
Ref<Shape> shape;
|
||||
|
||||
void _update_indicator();
|
||||
|
||||
RID material;
|
||||
RID indicator;
|
||||
RID indicator_instance;
|
||||
|
||||
void resource_changed(RES res);
|
||||
|
||||
bool updating_body;
|
||||
bool trigger;
|
||||
|
||||
void _update_body();
|
||||
void _add_to_collision_object(Object* p_cshape);
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
void make_convex_from_brothers();
|
||||
|
||||
void set_shape(const Ref<Shape> &p_shape);
|
||||
Ref<Shape> get_shape() const;
|
||||
|
||||
void set_updating_body(bool p_update);
|
||||
bool is_updating_body() const;
|
||||
|
||||
void set_trigger(bool p_trigger);
|
||||
bool is_trigger() const;
|
||||
|
||||
CollisionShape();
|
||||
~CollisionShape();
|
||||
};
|
||||
|
||||
#endif // BODY_VOLUME_H
|
||||
|
||||
138
scene/3d/bone_attachment.cpp
Normal file
138
scene/3d/bone_attachment.cpp
Normal file
@ -0,0 +1,138 @@
|
||||
/*************************************************************************/
|
||||
/* bone_attachment.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "bone_attachment.h"
|
||||
|
||||
bool BoneAttachment::_get(const StringName& p_name,Variant &r_ret) const {
|
||||
|
||||
if (String(p_name)=="bone_name") {
|
||||
|
||||
r_ret=get_bone_name();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
bool BoneAttachment::_set(const StringName& p_name, const Variant& p_value){
|
||||
|
||||
if (String(p_name)=="bone_name") {
|
||||
|
||||
set_bone_name(p_value);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
void BoneAttachment::_get_property_list( List<PropertyInfo>* p_list ) const{
|
||||
|
||||
Skeleton *parent=NULL;
|
||||
if(get_parent())
|
||||
parent=get_parent()->cast_to<Skeleton>();
|
||||
|
||||
if (parent) {
|
||||
|
||||
String names;
|
||||
for(int i=0;i<parent->get_bone_count();i++) {
|
||||
if(i>0)
|
||||
names+=",";
|
||||
names+=parent->get_bone_name(i);
|
||||
}
|
||||
|
||||
p_list->push_back(PropertyInfo(Variant::STRING,"bone_name",PROPERTY_HINT_ENUM,names));
|
||||
} else {
|
||||
|
||||
p_list->push_back(PropertyInfo(Variant::STRING,"bone_name"));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void BoneAttachment::_check_bind() {
|
||||
|
||||
if (get_parent() && get_parent()->cast_to<Skeleton>()) {
|
||||
Skeleton *sk = get_parent()->cast_to<Skeleton>();
|
||||
int idx = sk->find_bone(bone_name);
|
||||
if (idx!=-1) {
|
||||
sk->bind_child_node_to_bone(idx,this);;
|
||||
bound=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BoneAttachment::_check_unbind() {
|
||||
|
||||
if (bound) {
|
||||
|
||||
if (get_parent() && get_parent()->cast_to<Skeleton>()) {
|
||||
Skeleton *sk = get_parent()->cast_to<Skeleton>();
|
||||
int idx = sk->find_bone(bone_name);
|
||||
if (idx!=-1) {
|
||||
sk->unbind_child_node_from_bone(idx,this);;
|
||||
}
|
||||
}
|
||||
bound=false;
|
||||
}
|
||||
}
|
||||
|
||||
void BoneAttachment::set_bone_name(const String& p_name) {
|
||||
|
||||
if (is_inside_scene())
|
||||
_check_unbind();
|
||||
|
||||
bone_name=p_name;
|
||||
|
||||
if (is_inside_scene())
|
||||
_check_bind();
|
||||
}
|
||||
|
||||
String BoneAttachment::get_bone_name() const{
|
||||
|
||||
return bone_name;
|
||||
}
|
||||
|
||||
void BoneAttachment::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_ENTER_SCENE: {
|
||||
|
||||
_check_bind();
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_SCENE: {
|
||||
|
||||
_check_unbind();
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
BoneAttachment::BoneAttachment()
|
||||
{
|
||||
bound=false;
|
||||
|
||||
}
|
||||
58
scene/3d/bone_attachment.h
Normal file
58
scene/3d/bone_attachment.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*************************************************************************/
|
||||
/* bone_attachment.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef BONE_ATTACHMENT_H
|
||||
#define BONE_ATTACHMENT_H
|
||||
|
||||
#include "scene/3d/skeleton.h"
|
||||
|
||||
class BoneAttachment : public Spatial {
|
||||
|
||||
OBJ_TYPE(BoneAttachment,Spatial);
|
||||
|
||||
bool bound;
|
||||
String bone_name;
|
||||
|
||||
void _check_bind();
|
||||
void _check_unbind();
|
||||
protected:
|
||||
|
||||
bool _get(const StringName& p_name,Variant &r_ret) const;
|
||||
bool _set(const StringName& p_name, const Variant& p_value);
|
||||
void _get_property_list( List<PropertyInfo>* p_list ) const;
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
|
||||
void set_bone_name(const String& p_name);
|
||||
String get_bone_name() const;
|
||||
|
||||
BoneAttachment();
|
||||
};
|
||||
|
||||
#endif // BONE_ATTACHMENT_H
|
||||
727
scene/3d/camera.cpp
Normal file
727
scene/3d/camera.cpp
Normal file
@ -0,0 +1,727 @@
|
||||
/*************************************************************************/
|
||||
/* camera.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "camera.h"
|
||||
|
||||
#include "camera_matrix.h"
|
||||
#include "scene/resources/material.h"
|
||||
#include "scene/resources/surface_tool.h"
|
||||
|
||||
|
||||
void Camera::_update_audio_listener_state() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Camera::_request_camera_update() {
|
||||
|
||||
_update_camera();
|
||||
}
|
||||
|
||||
void Camera::_update_camera_mode() {
|
||||
|
||||
|
||||
force_change=true;
|
||||
switch(mode) {
|
||||
case PROJECTION_PERSPECTIVE: {
|
||||
|
||||
|
||||
set_perspective(fov,near,far);
|
||||
|
||||
} break;
|
||||
case PROJECTION_ORTHOGONAL: {
|
||||
set_orthogonal(size,near,far);
|
||||
} break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool Camera::_set(const StringName& p_name, const Variant& p_value) {
|
||||
|
||||
bool changed_all=false;
|
||||
if (p_name=="projection") {
|
||||
|
||||
int proj = p_value;
|
||||
if (proj==PROJECTION_PERSPECTIVE)
|
||||
mode=PROJECTION_PERSPECTIVE;
|
||||
if (proj==PROJECTION_ORTHOGONAL)
|
||||
mode=PROJECTION_ORTHOGONAL;
|
||||
|
||||
changed_all=true;
|
||||
} else if (p_name=="fov")
|
||||
fov=p_value;
|
||||
else if (p_name=="size")
|
||||
size=p_value;
|
||||
else if (p_name=="near")
|
||||
near=p_value;
|
||||
else if (p_name=="far")
|
||||
far=p_value;
|
||||
else if (p_name=="vaspect")
|
||||
set_use_vertical_aspect(p_value);
|
||||
else if (p_name=="current") {
|
||||
if (p_value.operator bool()) {
|
||||
make_current();
|
||||
} else {
|
||||
clear_current();
|
||||
}
|
||||
} else if (p_name=="visible_layers") {
|
||||
set_visible_layers(p_value);
|
||||
} else if (p_name=="environment") {
|
||||
set_environment(p_value);
|
||||
} else
|
||||
return false;
|
||||
|
||||
_update_camera_mode();
|
||||
if (changed_all)
|
||||
_change_notify();
|
||||
return true;
|
||||
|
||||
}
|
||||
bool Camera::_get(const StringName& p_name,Variant &r_ret) const {
|
||||
|
||||
if (p_name=="projection") {
|
||||
r_ret= mode;
|
||||
} else if (p_name=="fov")
|
||||
r_ret= fov;
|
||||
else if (p_name=="size")
|
||||
r_ret= size;
|
||||
else if (p_name=="near")
|
||||
r_ret= near;
|
||||
else if (p_name=="far")
|
||||
r_ret= far;
|
||||
else if (p_name=="vaspect")
|
||||
r_ret= vaspect;
|
||||
else if (p_name=="current") {
|
||||
|
||||
if (is_inside_scene() && get_scene()->is_editor_hint()) {
|
||||
r_ret=current;
|
||||
} else {
|
||||
r_ret=is_current();
|
||||
}
|
||||
} else if (p_name=="visible_layers") {
|
||||
r_ret=get_visible_layers();
|
||||
} else if (p_name=="environment") {
|
||||
r_ret=get_environment();
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Camera::_get_property_list( List<PropertyInfo> *p_list) const {
|
||||
|
||||
p_list->push_back( PropertyInfo( Variant::INT, "projection", PROPERTY_HINT_ENUM, "Perspective,Orthogonal") );
|
||||
|
||||
switch(mode) {
|
||||
|
||||
case PROJECTION_PERSPECTIVE: {
|
||||
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "fov" , PROPERTY_HINT_RANGE, "1,89,0.1") );
|
||||
|
||||
} break;
|
||||
case PROJECTION_ORTHOGONAL: {
|
||||
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "size" , PROPERTY_HINT_RANGE, "1,16384,0.01" ) );
|
||||
} break;
|
||||
|
||||
}
|
||||
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "near" , PROPERTY_HINT_EXP_RANGE, "0.01,4096.0,0.01") );
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "far" , PROPERTY_HINT_EXP_RANGE, "0.01,4096.0,0.01") );
|
||||
p_list->push_back( PropertyInfo( Variant::BOOL, "vaspect") );
|
||||
p_list->push_back( PropertyInfo( Variant::BOOL, "current" ) );
|
||||
p_list->push_back( PropertyInfo( Variant::INT, "visible_layers",PROPERTY_HINT_ALL_FLAGS ) );
|
||||
p_list->push_back( PropertyInfo( Variant::OBJECT, "environment",PROPERTY_HINT_RESOURCE_TYPE,"Environment" ) );
|
||||
|
||||
}
|
||||
|
||||
void Camera::_update_camera() {
|
||||
|
||||
Transform tr = get_camera_transform();
|
||||
VisualServer::get_singleton()->camera_set_transform( camera, tr );
|
||||
|
||||
// here goes listener stuff
|
||||
// if (viewport_ptr && is_inside_scene() && is_current())
|
||||
// viewport_ptr->_camera_transform_changed_notify();
|
||||
|
||||
if (is_inside_scene() && is_current()) {
|
||||
if (viewport_ptr) {
|
||||
viewport_ptr->_camera_transform_changed_notify();
|
||||
}
|
||||
}
|
||||
|
||||
if (is_current() && get_world().is_valid()) {
|
||||
get_world()->_update_camera(this);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Camera::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_ENTER_WORLD: {
|
||||
|
||||
viewport_ptr=NULL;
|
||||
|
||||
{ //find viewport stuff
|
||||
Node *parent=get_parent();
|
||||
|
||||
while(parent) {
|
||||
|
||||
Viewport* viewport = parent->cast_to<Viewport>();
|
||||
|
||||
if (viewport) {
|
||||
viewport_ptr=viewport;
|
||||
break;
|
||||
}
|
||||
parent=parent->get_parent();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (viewport_ptr)
|
||||
viewport_ptr->cameras.insert(this);
|
||||
if (current)
|
||||
make_current();
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
|
||||
_request_camera_update();
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_WORLD: {
|
||||
|
||||
if (is_current()) {
|
||||
clear_current();
|
||||
current=true; //keep it true
|
||||
|
||||
} else {
|
||||
current=false;
|
||||
}
|
||||
if (viewport_ptr)
|
||||
viewport_ptr->cameras.erase(this);
|
||||
viewport_ptr=NULL;
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_BECAME_CURRENT: {
|
||||
if (get_world().is_valid()) {
|
||||
get_world()->_register_camera(this);
|
||||
}
|
||||
} break;
|
||||
case NOTIFICATION_LOST_CURRENT: {
|
||||
if (get_world().is_valid()) {
|
||||
get_world()->_remove_camera(this);
|
||||
}
|
||||
} break;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Transform Camera::get_camera_transform() const {
|
||||
|
||||
return get_global_transform();
|
||||
}
|
||||
|
||||
void Camera::set_perspective(float p_fovy_degrees, float p_z_near, float p_z_far) {
|
||||
|
||||
if (!force_change && fov==p_fovy_degrees && p_z_near==near && p_z_far==far && mode==PROJECTION_PERSPECTIVE)
|
||||
return;
|
||||
|
||||
fov=p_fovy_degrees;
|
||||
near=p_z_near;
|
||||
far=p_z_far;
|
||||
mode=PROJECTION_PERSPECTIVE;
|
||||
|
||||
VisualServer::get_singleton()->camera_set_perspective(camera,fov,near,far);
|
||||
update_gizmo();
|
||||
force_change=false;
|
||||
}
|
||||
void Camera::set_orthogonal(float p_size, float p_z_near, float p_z_far) {
|
||||
|
||||
if (!force_change && size==p_size && p_z_near==near && p_z_far==far && mode==PROJECTION_ORTHOGONAL)
|
||||
return;
|
||||
|
||||
size = p_size;
|
||||
|
||||
near=p_z_near;
|
||||
far=p_z_far;
|
||||
mode=PROJECTION_ORTHOGONAL;
|
||||
force_change=false;
|
||||
|
||||
VisualServer::get_singleton()->camera_set_orthogonal(camera,size,near,far);
|
||||
update_gizmo();
|
||||
}
|
||||
|
||||
RID Camera::get_camera() const {
|
||||
|
||||
return camera;
|
||||
};
|
||||
|
||||
void Camera::make_current() {
|
||||
|
||||
current=true;
|
||||
|
||||
if (!is_inside_scene())
|
||||
return;
|
||||
|
||||
if (viewport_ptr) {
|
||||
viewport_ptr->_set_camera(this);
|
||||
}
|
||||
|
||||
//get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,camera_group,"_camera_make_current",this);
|
||||
}
|
||||
|
||||
void Camera::clear_current() {
|
||||
|
||||
current=false;
|
||||
if (!is_inside_scene())
|
||||
return;
|
||||
|
||||
if (viewport_ptr) {
|
||||
if (viewport_ptr->get_camera()==this)
|
||||
viewport_ptr->_set_camera(NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool Camera::is_current() const {
|
||||
|
||||
if (is_inside_scene()) {
|
||||
if (viewport_ptr)
|
||||
return viewport_ptr->get_camera()==this;
|
||||
} else
|
||||
return current;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Camera::_can_gizmo_scale() const {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
RES Camera::_get_gizmo_geometry() const {
|
||||
|
||||
|
||||
Ref<SurfaceTool> surface_tool( memnew( SurfaceTool ));
|
||||
|
||||
Ref<FixedMaterial> mat( memnew( FixedMaterial ));
|
||||
|
||||
mat->set_parameter( FixedMaterial::PARAM_DIFFUSE,Color(1.0,0.5,1.0,0.5) );
|
||||
mat->set_line_width(4);
|
||||
mat->set_flag(Material::FLAG_DOUBLE_SIDED,true);
|
||||
mat->set_flag(Material::FLAG_UNSHADED,true);
|
||||
mat->set_hint(Material::HINT_NO_DEPTH_DRAW,true);
|
||||
|
||||
surface_tool->begin(Mesh::PRIMITIVE_LINES);
|
||||
surface_tool->set_material(mat);
|
||||
|
||||
switch(mode) {
|
||||
|
||||
case PROJECTION_PERSPECTIVE: {
|
||||
|
||||
|
||||
|
||||
Vector3 side=Vector3( Math::sin(Math::deg2rad(fov)), 0, -Math::cos(Math::deg2rad(fov)) );
|
||||
Vector3 nside=side;
|
||||
nside.x=-nside.x;
|
||||
Vector3 up=Vector3(0,side.x,0);
|
||||
|
||||
|
||||
#define ADD_TRIANGLE( m_a, m_b, m_c)\
|
||||
{\
|
||||
surface_tool->add_vertex(m_a);\
|
||||
surface_tool->add_vertex(m_b);\
|
||||
surface_tool->add_vertex(m_b);\
|
||||
surface_tool->add_vertex(m_c);\
|
||||
surface_tool->add_vertex(m_c);\
|
||||
surface_tool->add_vertex(m_a);\
|
||||
}
|
||||
|
||||
ADD_TRIANGLE( Vector3(), side+up, side-up );
|
||||
ADD_TRIANGLE( Vector3(), nside+up, nside-up );
|
||||
ADD_TRIANGLE( Vector3(), side+up, nside+up );
|
||||
ADD_TRIANGLE( Vector3(), side-up, nside-up );
|
||||
|
||||
side.x*=0.25;
|
||||
nside.x*=0.25;
|
||||
Vector3 tup( 0, up.y*3/2,side.z);
|
||||
ADD_TRIANGLE( tup, side+up, nside+up );
|
||||
|
||||
} break;
|
||||
case PROJECTION_ORTHOGONAL: {
|
||||
|
||||
#define ADD_QUAD( m_a, m_b, m_c, m_d)\
|
||||
{\
|
||||
surface_tool->add_vertex(m_a);\
|
||||
surface_tool->add_vertex(m_b);\
|
||||
surface_tool->add_vertex(m_b);\
|
||||
surface_tool->add_vertex(m_c);\
|
||||
surface_tool->add_vertex(m_c);\
|
||||
surface_tool->add_vertex(m_d);\
|
||||
surface_tool->add_vertex(m_d);\
|
||||
surface_tool->add_vertex(m_a);\
|
||||
}
|
||||
|
||||
float hsize=size*0.5;
|
||||
Vector3 right(hsize,0,0);
|
||||
Vector3 up(0,hsize,0);
|
||||
Vector3 back(0,0,-1.0);
|
||||
Vector3 front(0,0,0);
|
||||
|
||||
ADD_QUAD( -up-right,-up+right,up+right,up-right);
|
||||
ADD_QUAD( -up-right+back,-up+right+back,up+right+back,up-right+back);
|
||||
ADD_QUAD( up+right,up+right+back,up-right+back,up-right);
|
||||
ADD_QUAD( -up+right,-up+right+back,-up-right+back,-up-right);
|
||||
|
||||
right.x*=0.25;
|
||||
Vector3 tup( 0, up.y*3/2,back.z );
|
||||
ADD_TRIANGLE( tup, right+up+back, -right+up+back );
|
||||
|
||||
} break;
|
||||
|
||||
}
|
||||
|
||||
return surface_tool->commit();
|
||||
|
||||
}
|
||||
|
||||
Vector3 Camera::project_ray_normal(const Point2& p_pos) const {
|
||||
|
||||
Vector3 ray = project_local_ray_normal(p_pos);
|
||||
return get_camera_transform().basis.xform(ray).normalized();
|
||||
};
|
||||
|
||||
Vector3 Camera::project_local_ray_normal(const Point2& p_pos) const {
|
||||
|
||||
if (!is_inside_scene()) {
|
||||
ERR_EXPLAIN("Camera is not inside scene.");
|
||||
ERR_FAIL_COND_V(!is_inside_scene(),Vector3());
|
||||
}
|
||||
|
||||
Size2 viewport_size = viewport_ptr->get_visible_rect().size;
|
||||
|
||||
Vector3 ray;
|
||||
|
||||
if (mode==PROJECTION_ORTHOGONAL) {
|
||||
|
||||
ray=Vector3(0,0,-1);
|
||||
} else {
|
||||
CameraMatrix cm;
|
||||
cm.set_perspective(fov,viewport_size.get_aspect(),near,far,vaspect);
|
||||
float screen_w,screen_h;
|
||||
cm.get_viewport_size(screen_w,screen_h);
|
||||
ray=Vector3( ((p_pos.x/viewport_size.width)*2.0-1.0)*screen_w, ((1.0-(p_pos.y/viewport_size.height))*2.0-1.0)*screen_h,-near).normalized();
|
||||
}
|
||||
|
||||
|
||||
return ray;
|
||||
};
|
||||
|
||||
|
||||
Vector3 Camera::project_ray_origin(const Point2& p_pos) const {
|
||||
|
||||
if (!is_inside_scene()) {
|
||||
ERR_EXPLAIN("Camera is not inside scene.");
|
||||
ERR_FAIL_COND_V(!is_inside_scene(),Vector3());
|
||||
}
|
||||
|
||||
Size2 viewport_size = viewport_ptr->get_visible_rect().size;
|
||||
|
||||
|
||||
ERR_FAIL_COND_V( viewport_size.y == 0, Vector3() );
|
||||
// float aspect = viewport_size.x / viewport_size.y;
|
||||
|
||||
if (mode == PROJECTION_PERSPECTIVE) {
|
||||
|
||||
return get_camera_transform().origin;
|
||||
} else {
|
||||
|
||||
Vector2 pos = p_pos / viewport_size;
|
||||
float vsize,hsize;
|
||||
if (vaspect) {
|
||||
vsize = size/viewport_size.get_aspect();
|
||||
hsize = size;
|
||||
} else {
|
||||
hsize = size*viewport_size.get_aspect();
|
||||
vsize = size;
|
||||
|
||||
}
|
||||
|
||||
Vector3 ray;
|
||||
ray.x = pos.x * (hsize) - hsize/2;
|
||||
ray.y = (1.0 - pos.y) * (vsize) - vsize/2;
|
||||
ray.z = -near;
|
||||
ray = get_camera_transform().xform(ray);
|
||||
return ray;
|
||||
};
|
||||
};
|
||||
|
||||
Point2 Camera::unproject_position(const Vector3& p_pos) const {
|
||||
|
||||
if (!is_inside_scene()) {
|
||||
ERR_EXPLAIN("Camera is not inside scene.");
|
||||
ERR_FAIL_COND_V(!is_inside_scene(),Vector2());
|
||||
}
|
||||
|
||||
Size2 viewport_size = viewport_ptr->get_visible_rect().size;
|
||||
|
||||
CameraMatrix cm;
|
||||
|
||||
|
||||
if (mode==PROJECTION_ORTHOGONAL)
|
||||
cm.set_orthogonal(size,viewport_size.get_aspect(),near,far,vaspect);
|
||||
else
|
||||
cm.set_perspective(fov,viewport_size.get_aspect(),near,far,vaspect);
|
||||
|
||||
Plane p(get_camera_transform().xform_inv(p_pos),1.0);
|
||||
|
||||
p=cm.xform4(p);
|
||||
p.normal/=p.d;
|
||||
|
||||
|
||||
Point2 res;
|
||||
res.x = (p.normal.x * 0.5 + 0.5) * viewport_size.x;
|
||||
res.y = (-p.normal.y * 0.5 + 0.5) * viewport_size.y;
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
Vector3 Camera::project_position(const Point2& p_point) const {
|
||||
|
||||
if (!is_inside_scene()) {
|
||||
ERR_EXPLAIN("Camera is not inside scene.");
|
||||
ERR_FAIL_COND_V(!is_inside_scene(),Vector3());
|
||||
}
|
||||
|
||||
Size2 viewport_size = viewport_ptr->get_visible_rect().size;
|
||||
|
||||
CameraMatrix cm;
|
||||
|
||||
if (mode==PROJECTION_ORTHOGONAL)
|
||||
cm.set_orthogonal(size,viewport_size.get_aspect(),near,far,vaspect);
|
||||
else
|
||||
cm.set_perspective(fov,viewport_size.get_aspect(),near,far,vaspect);
|
||||
|
||||
Size2 vp_size;
|
||||
cm.get_viewport_size(vp_size.x,vp_size.y);
|
||||
|
||||
Vector2 point;
|
||||
point.x = (p_point.x/viewport_size.x) * 2.0 - 1.0;
|
||||
point.y = (p_point.y/viewport_size.y) * 2.0 - 1.0;
|
||||
point*=vp_size;
|
||||
|
||||
Vector3 p(point.x,point.y,-near);
|
||||
|
||||
|
||||
return get_camera_transform().xform(p);
|
||||
}
|
||||
|
||||
/*
|
||||
void Camera::_camera_make_current(Node *p_camera) {
|
||||
|
||||
|
||||
if (p_camera==this) {
|
||||
VisualServer::get_singleton()->viewport_attach_camera(viewport_id,camera);
|
||||
active=true;
|
||||
} else {
|
||||
if (active && p_camera==NULL) {
|
||||
//detech camera because no one else will claim it
|
||||
VisualServer::get_singleton()->viewport_attach_camera(viewport_id,RID());
|
||||
}
|
||||
active=false;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void Camera::set_environment(const Ref<Environment>& p_environment) {
|
||||
|
||||
environment=p_environment;
|
||||
if (environment.is_valid())
|
||||
VS::get_singleton()->camera_set_environment(camera,environment->get_rid());
|
||||
else
|
||||
VS::get_singleton()->camera_set_environment(camera,RID());
|
||||
}
|
||||
|
||||
Ref<Environment> Camera::get_environment() const {
|
||||
|
||||
return environment;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Camera::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method( _MD("project_ray_normal","screen_point"), &Camera::project_ray_normal);
|
||||
ObjectTypeDB::bind_method( _MD("project_local_ray_normal","screen_point"), &Camera::project_local_ray_normal);
|
||||
ObjectTypeDB::bind_method( _MD("project_ray_origin","screen_point"), &Camera::project_ray_origin);
|
||||
ObjectTypeDB::bind_method( _MD("unproject_position","world_point"), &Camera::unproject_position);
|
||||
ObjectTypeDB::bind_method( _MD("project_position","screen_point"), &Camera::project_position);
|
||||
ObjectTypeDB::bind_method( _MD("set_perspective","fov","z_near","z_far"),&Camera::set_perspective );
|
||||
ObjectTypeDB::bind_method( _MD("set_orthogonal","size","z_near","z_far"),&Camera::set_orthogonal );
|
||||
ObjectTypeDB::bind_method( _MD("make_current"),&Camera::make_current );
|
||||
ObjectTypeDB::bind_method( _MD("clear_current"),&Camera::clear_current );
|
||||
ObjectTypeDB::bind_method( _MD("is_current"),&Camera::is_current );
|
||||
ObjectTypeDB::bind_method( _MD("get_camera_transform"),&Camera::get_camera_transform );
|
||||
ObjectTypeDB::bind_method( _MD("get_fov"),&Camera::get_fov );
|
||||
ObjectTypeDB::bind_method( _MD("get_size"),&Camera::get_size );
|
||||
ObjectTypeDB::bind_method( _MD("get_zfar"),&Camera::get_zfar );
|
||||
ObjectTypeDB::bind_method( _MD("get_znear"),&Camera::get_znear );
|
||||
ObjectTypeDB::bind_method( _MD("get_projection"),&Camera::get_projection );
|
||||
ObjectTypeDB::bind_method( _MD("set_visible_layers","mask"),&Camera::set_visible_layers );
|
||||
ObjectTypeDB::bind_method( _MD("get_visible_layers"),&Camera::get_visible_layers );
|
||||
ObjectTypeDB::bind_method( _MD("look_at","target","up"),&Camera::look_at );
|
||||
ObjectTypeDB::bind_method( _MD("look_at_from_pos","pos","target","up"),&Camera::look_at_from_pos );
|
||||
ObjectTypeDB::bind_method(_MD("set_environment","env:Environment"),&Camera::set_environment);
|
||||
ObjectTypeDB::bind_method(_MD("get_environment:Environment"),&Camera::get_environment);
|
||||
ObjectTypeDB::bind_method(_MD("set_use_vertical_aspect","enable"),&Camera::set_use_vertical_aspect);
|
||||
ObjectTypeDB::bind_method(_MD("is_using_vertical_aspect"),&Camera::is_using_vertical_aspect);
|
||||
//ObjectTypeDB::bind_method( _MD("_camera_make_current"),&Camera::_camera_make_current );
|
||||
|
||||
BIND_CONSTANT( PROJECTION_PERSPECTIVE );
|
||||
BIND_CONSTANT( PROJECTION_ORTHOGONAL );
|
||||
}
|
||||
|
||||
float Camera::get_fov() const {
|
||||
|
||||
return fov;
|
||||
}
|
||||
|
||||
float Camera::get_size() const {
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
float Camera::get_znear() const {
|
||||
|
||||
return near;
|
||||
}
|
||||
|
||||
float Camera::get_zfar() const {
|
||||
|
||||
return far;
|
||||
}
|
||||
|
||||
|
||||
Camera::Projection Camera::get_projection() const {
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
void Camera::set_visible_layers(uint32_t p_layers) {
|
||||
|
||||
layers=p_layers;
|
||||
VisualServer::get_singleton()->camera_set_visible_layers(camera,layers);
|
||||
}
|
||||
|
||||
uint32_t Camera::get_visible_layers() const{
|
||||
|
||||
return layers;
|
||||
}
|
||||
|
||||
|
||||
Vector<Plane> Camera::get_frustum() const {
|
||||
|
||||
ERR_FAIL_COND_V(!is_inside_world(),Vector<Plane>());
|
||||
|
||||
Size2 viewport_size = viewport_ptr->get_visible_rect().size;
|
||||
CameraMatrix cm;
|
||||
if (mode==PROJECTION_PERSPECTIVE)
|
||||
cm.set_perspective(fov,viewport_size.get_aspect(),near,far,vaspect);
|
||||
else
|
||||
cm.set_orthogonal(size,viewport_size.get_aspect(),near,far,vaspect);
|
||||
|
||||
return cm.get_projection_planes(get_global_transform());
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Camera::set_use_vertical_aspect(bool p_enable) {
|
||||
|
||||
vaspect=p_enable;
|
||||
VisualServer::get_singleton()->camera_set_use_vertical_aspect(camera,p_enable);
|
||||
}
|
||||
|
||||
|
||||
bool Camera::is_using_vertical_aspect() const{
|
||||
|
||||
return vaspect;
|
||||
}
|
||||
|
||||
void Camera::look_at(const Vector3& p_target, const Vector3& p_up_normal) {
|
||||
|
||||
Transform lookat;
|
||||
lookat.origin=get_global_transform().origin;
|
||||
lookat=lookat.looking_at(p_target,p_up_normal);
|
||||
set_global_transform(lookat);
|
||||
}
|
||||
|
||||
void Camera::look_at_from_pos(const Vector3& p_pos,const Vector3& p_target, const Vector3& p_up_normal) {
|
||||
|
||||
Transform lookat;
|
||||
lookat.origin=p_pos;
|
||||
lookat=lookat.looking_at(p_target,p_up_normal);
|
||||
set_global_transform(lookat);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Camera::Camera() {
|
||||
|
||||
camera = VisualServer::get_singleton()->camera_create();
|
||||
size=1;
|
||||
fov=0;
|
||||
near=0;
|
||||
far=0;
|
||||
current=false;
|
||||
viewport_ptr=NULL;
|
||||
force_change=false;
|
||||
mode=PROJECTION_PERSPECTIVE;
|
||||
set_perspective(60.0,0.1,100.0);
|
||||
vaspect=false;
|
||||
layers=0xFFFFFFFF;
|
||||
//active=false;
|
||||
}
|
||||
|
||||
|
||||
Camera::~Camera() {
|
||||
|
||||
VisualServer::get_singleton()->free(camera);
|
||||
|
||||
}
|
||||
|
||||
|
||||
144
scene/3d/camera.h
Normal file
144
scene/3d/camera.h
Normal file
@ -0,0 +1,144 @@
|
||||
/*************************************************************************/
|
||||
/* camera.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef CAMERA_H
|
||||
#define CAMERA_H
|
||||
|
||||
|
||||
#include "scene/3d/spatial.h"
|
||||
#include "scene/main/viewport.h"
|
||||
#include "scene/resources/environment.h"
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
class Camera : public Spatial {
|
||||
|
||||
OBJ_TYPE( Camera, Spatial );
|
||||
public:
|
||||
enum Projection {
|
||||
|
||||
PROJECTION_PERSPECTIVE,
|
||||
PROJECTION_ORTHOGONAL
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
bool force_change;
|
||||
bool current;
|
||||
|
||||
Projection mode;
|
||||
|
||||
float fov;
|
||||
float size;
|
||||
float near,far;
|
||||
bool vaspect;
|
||||
|
||||
RID camera;
|
||||
RID scenario_id;
|
||||
|
||||
uint32_t layers;
|
||||
|
||||
Viewport *viewport_ptr;
|
||||
Ref<Environment> environment;
|
||||
|
||||
virtual bool _can_gizmo_scale() const;
|
||||
virtual RES _get_gizmo_geometry() const;
|
||||
|
||||
|
||||
|
||||
//void _camera_make_current(Node *p_camera);
|
||||
friend class Viewport;
|
||||
void _update_audio_listener_state();
|
||||
protected:
|
||||
|
||||
void _update_camera();
|
||||
virtual void _request_camera_update();
|
||||
void _update_camera_mode();
|
||||
|
||||
bool _set(const StringName& p_name, const Variant& p_value);
|
||||
bool _get(const StringName& p_name,Variant &r_ret) const;
|
||||
void _get_property_list( List<PropertyInfo> *p_list) const;
|
||||
void _notification(int p_what);
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
enum {
|
||||
|
||||
NOTIFICATION_BECAME_CURRENT=50,
|
||||
NOTIFICATION_LOST_CURRENT=51
|
||||
};
|
||||
|
||||
void set_perspective(float p_fovy_degrees, float p_z_near, float p_z_far);
|
||||
void set_orthogonal(float p_size, float p_z_near, float p_z_far);
|
||||
|
||||
void make_current();
|
||||
void clear_current();
|
||||
bool is_current() const;
|
||||
|
||||
RID get_camera() const;
|
||||
|
||||
float get_fov() const;
|
||||
float get_size() const;
|
||||
float get_zfar() const;
|
||||
float get_znear() const;
|
||||
Projection get_projection() const;
|
||||
|
||||
virtual Transform get_camera_transform() const;
|
||||
|
||||
Vector3 project_ray_normal(const Point2& p_point) const;
|
||||
Vector3 project_ray_origin(const Point2& p_point) const;
|
||||
Vector3 project_local_ray_normal(const Point2& p_point) const;
|
||||
Point2 unproject_position(const Vector3& p_pos) const;
|
||||
Vector3 project_position(const Point2& p_point) const;
|
||||
|
||||
void set_visible_layers(uint32_t p_layers);
|
||||
uint32_t get_visible_layers() const;
|
||||
|
||||
Vector<Plane> get_frustum() const;
|
||||
|
||||
void set_environment(const Ref<Environment>& p_environment);
|
||||
Ref<Environment> get_environment() const;
|
||||
|
||||
void set_use_vertical_aspect(bool p_enable);
|
||||
bool is_using_vertical_aspect() const;
|
||||
|
||||
void look_at(const Vector3& p_target, const Vector3& p_up_normal);
|
||||
void look_at_from_pos(const Vector3& p_pos,const Vector3& p_target, const Vector3& p_up_normal);
|
||||
|
||||
|
||||
Camera();
|
||||
~Camera();
|
||||
|
||||
};
|
||||
|
||||
|
||||
VARIANT_ENUM_CAST( Camera::Projection );
|
||||
|
||||
#endif
|
||||
741
scene/3d/car_body.cpp
Normal file
741
scene/3d/car_body.cpp
Normal file
@ -0,0 +1,741 @@
|
||||
/*************************************************************************/
|
||||
/* car_body.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "car_body.h"
|
||||
|
||||
#define DEG2RADMUL (Math_PI/180.0)
|
||||
#define RAD2DEGMUL (180.0/Math_PI)
|
||||
|
||||
void CarWheel::_notification(int p_what) {
|
||||
|
||||
|
||||
if (p_what==NOTIFICATION_ENTER_SCENE) {
|
||||
|
||||
if (!get_parent())
|
||||
return;
|
||||
CarBody *cb = get_parent()->cast_to<CarBody>();
|
||||
if (!cb)
|
||||
return;
|
||||
body=cb;
|
||||
local_xform=get_transform();
|
||||
cb->wheels.push_back(this);
|
||||
}
|
||||
if (p_what==NOTIFICATION_EXIT_SCENE) {
|
||||
|
||||
if (!get_parent())
|
||||
return;
|
||||
CarBody *cb = get_parent()->cast_to<CarBody>();
|
||||
if (!cb)
|
||||
return;
|
||||
cb->wheels.erase(this);
|
||||
body=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void CarWheel::set_side_friction(real_t p_friction) {
|
||||
|
||||
side_friction=p_friction;
|
||||
}
|
||||
void CarWheel::set_forward_friction(real_t p_friction) {
|
||||
|
||||
forward_friction=p_friction;
|
||||
}
|
||||
void CarWheel::set_travel(real_t p_travel) {
|
||||
|
||||
travel=p_travel;
|
||||
update_gizmo();
|
||||
|
||||
}
|
||||
void CarWheel::set_radius(real_t p_radius) {
|
||||
|
||||
radius=p_radius;
|
||||
update_gizmo();
|
||||
|
||||
}
|
||||
void CarWheel::set_resting_frac(real_t p_frac) {
|
||||
|
||||
resting_frac=p_frac;
|
||||
}
|
||||
void CarWheel::set_damping_frac(real_t p_frac) {
|
||||
|
||||
damping_frac=p_frac;
|
||||
}
|
||||
void CarWheel::set_num_rays(real_t p_rays) {
|
||||
|
||||
num_rays=p_rays;
|
||||
}
|
||||
|
||||
real_t CarWheel::get_side_friction() const{
|
||||
|
||||
return side_friction;
|
||||
}
|
||||
real_t CarWheel::get_forward_friction() const{
|
||||
|
||||
return forward_friction;
|
||||
}
|
||||
real_t CarWheel::get_travel() const{
|
||||
|
||||
return travel;
|
||||
}
|
||||
real_t CarWheel::get_radius() const{
|
||||
|
||||
return radius;
|
||||
}
|
||||
real_t CarWheel::get_resting_frac() const{
|
||||
|
||||
return resting_frac;
|
||||
}
|
||||
real_t CarWheel::get_damping_frac() const{
|
||||
|
||||
return damping_frac;
|
||||
}
|
||||
|
||||
int CarWheel::get_num_rays() const{
|
||||
|
||||
return num_rays;
|
||||
}
|
||||
|
||||
|
||||
void CarWheel::update(real_t dt) {
|
||||
|
||||
|
||||
if (dt <= 0.0f)
|
||||
return;
|
||||
|
||||
float origAngVel = angVel;
|
||||
|
||||
if (locked)
|
||||
{
|
||||
angVel = 0;
|
||||
torque = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
float wheelMass = 0.03f * body->mass;
|
||||
float inertia = 0.5f * (radius * radius) * wheelMass;
|
||||
|
||||
angVel += torque * dt / inertia;
|
||||
torque = 0;
|
||||
|
||||
// prevent friction from reversing dir - todo do this better
|
||||
// by limiting the torque
|
||||
if (((origAngVel > angVelForGrip) && (angVel < angVelForGrip)) ||
|
||||
((origAngVel < angVelForGrip) && (angVel > angVelForGrip)))
|
||||
angVel = angVelForGrip;
|
||||
|
||||
angVel += driveTorque * dt / inertia;
|
||||
driveTorque = 0;
|
||||
|
||||
float maxAngVel = 200;
|
||||
print_line("angvel: "+rtos(angVel));
|
||||
angVel = CLAMP(angVel, -maxAngVel, maxAngVel);
|
||||
|
||||
axisAngle += Math::rad2deg(dt * angVel);
|
||||
}
|
||||
}
|
||||
|
||||
bool CarWheel::add_forces(PhysicsDirectBodyState *s) {
|
||||
|
||||
|
||||
Vector3 force;
|
||||
|
||||
PhysicsDirectSpaceState *space = s->get_space_state();
|
||||
|
||||
Transform world = s->get_transform() * local_xform;
|
||||
|
||||
// OpenGl has differnet row/column order for matrixes than XNA has ..
|
||||
//Vector3 wheelFwd = world.get_basis().get_axis(Vector3::AXIS_Z);
|
||||
//Vector3 wheelFwd = RotationMatrix(mSteerAngle, worldAxis) * carBody.GetOrientation().GetCol(0);
|
||||
Vector3 wheelUp = world.get_basis().get_axis(Vector3::AXIS_Y);
|
||||
Vector3 wheelFwd = Matrix3(wheelUp,Math::deg2rad(steerAngle)).xform( world.get_basis().get_axis(Vector3::AXIS_Z) );
|
||||
Vector3 wheelLeft = -wheelUp.cross(wheelFwd).normalized();
|
||||
Vector3 worldPos = world.origin;
|
||||
Vector3 worldAxis = wheelUp;
|
||||
|
||||
// start of ray
|
||||
float rayLen = 2.0f * radius + travel;
|
||||
Vector3 wheelRayEnd = worldPos - radius * worldAxis;
|
||||
Vector3 wheelRayBegin = wheelRayEnd + rayLen * worldAxis;
|
||||
//wheelRayEnd = -rayLen * worldAxis;
|
||||
|
||||
//Assert(PhysicsSystem.CurrentPhysicsSystem);
|
||||
|
||||
|
||||
///Assert(collSystem);
|
||||
///
|
||||
const int maxNumRays = 32;
|
||||
|
||||
int numRaysUse = MIN(num_rays, maxNumRays);
|
||||
|
||||
// adjust the start position of the ray - divide the wheel into numRays+2
|
||||
// rays, but don't use the first/last.
|
||||
float deltaFwd = (2.0f * radius) / (numRaysUse + 1);
|
||||
float deltaFwdStart = deltaFwd;
|
||||
|
||||
float fracs[maxNumRays];
|
||||
Vector3 segmentEnds[maxNumRays];
|
||||
Vector3 groundPositions[maxNumRays];
|
||||
Vector3 groundNormals[maxNumRays];
|
||||
|
||||
|
||||
lastOnFloor = false;
|
||||
int bestIRay = 0;
|
||||
int iRay;
|
||||
|
||||
|
||||
for (iRay = 0; iRay < numRaysUse; ++iRay)
|
||||
{
|
||||
fracs[iRay] = 1e20;
|
||||
// work out the offset relative to the middle ray
|
||||
float distFwd = (deltaFwdStart + iRay * deltaFwd) - radius;
|
||||
float zOffset = radius * (1.0f - (float)Math::cos( Math::deg2rad( 90.0f * (distFwd / radius))));
|
||||
|
||||
segmentEnds[iRay] = wheelRayEnd + distFwd * wheelFwd + zOffset * wheelUp;
|
||||
|
||||
|
||||
PhysicsDirectSpaceState::RayResult rr;
|
||||
|
||||
bool collided = space->intersect_ray(wheelRayBegin,segmentEnds[iRay],rr,body->exclude);
|
||||
|
||||
|
||||
if (collided){
|
||||
lastOnFloor = true;
|
||||
groundPositions[iRay]=rr.position;
|
||||
groundNormals[iRay]=rr.normal;
|
||||
fracs[iRay] = ((wheelRayBegin-rr.position).length() / (wheelRayBegin-wheelRayEnd).length());
|
||||
if (fracs[iRay] < fracs[bestIRay])
|
||||
bestIRay = iRay;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!lastOnFloor)
|
||||
return false;
|
||||
|
||||
//Assert(bestIRay < numRays);
|
||||
|
||||
// use the best one
|
||||
Vector3 groundPos = groundPositions[bestIRay];
|
||||
float frac = fracs[bestIRay];
|
||||
|
||||
// const Vector3 groundNormal = (worldPos - segments[bestIRay].GetEnd()).NormaliseSafe();
|
||||
// const Vector3 groundNormal = groundNormals[bestIRay];
|
||||
|
||||
|
||||
Vector3 groundNormal = worldAxis;
|
||||
|
||||
if (numRaysUse > 1)
|
||||
{
|
||||
for (iRay = 0; iRay < numRaysUse; ++iRay)
|
||||
{
|
||||
if (fracs[iRay] <= 1.0f)
|
||||
{
|
||||
groundNormal += (1.0f - fracs[iRay]) * (worldPos - segmentEnds[iRay]);
|
||||
}
|
||||
}
|
||||
|
||||
groundNormal.normalize();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
groundNormal = groundNormals[bestIRay];
|
||||
}
|
||||
|
||||
|
||||
|
||||
float spring = (body->mass/body->wheels.size()) * s->get_total_gravity().length() / (resting_frac * travel);
|
||||
|
||||
float displacement = rayLen * (1.0f - frac);
|
||||
displacement = CLAMP(displacement, 0, travel);
|
||||
|
||||
|
||||
|
||||
float displacementForceMag = displacement * spring;
|
||||
|
||||
// reduce force when suspension is par to ground
|
||||
displacementForceMag *= groundNormals[bestIRay].dot(worldAxis);
|
||||
|
||||
// apply damping
|
||||
float damping = 2.0f * (float)Math::sqrt(spring * body->mass);
|
||||
damping /= body->wheels.size(); // assume wheels act together
|
||||
damping *= damping_frac; // a bit bouncy
|
||||
|
||||
float upSpeed = (displacement - lastDisplacement) / s->get_step();
|
||||
|
||||
float dampingForceMag = upSpeed * damping;
|
||||
|
||||
float totalForceMag = displacementForceMag + dampingForceMag;
|
||||
|
||||
if (totalForceMag < 0.0f) totalForceMag = 0.0f;
|
||||
|
||||
Vector3 extraForce = totalForceMag * worldAxis;
|
||||
|
||||
|
||||
force += extraForce;
|
||||
// side-slip friction and drive force. Work out wheel- and floor-relative coordinate frame
|
||||
Vector3 groundUp = groundNormal;
|
||||
Vector3 groundLeft = groundNormal.cross(wheelFwd).normalized();
|
||||
|
||||
Vector3 groundFwd = groundLeft.cross(groundUp);
|
||||
|
||||
Vector3 wheelPointVel = s->get_linear_velocity() +
|
||||
(s->get_angular_velocity()).cross(s->get_transform().basis.xform(local_xform.origin));// * mPos);
|
||||
|
||||
Vector3 rimVel = -angVel * wheelLeft.cross(groundPos - worldPos);
|
||||
wheelPointVel += rimVel;
|
||||
|
||||
// if sitting on another body then adjust for its velocity.
|
||||
/*if (worldBody != null)
|
||||
{
|
||||
Vector3 worldVel = worldBody.Velocity +
|
||||
Vector3.Cross(worldBody.AngularVelocity, groundPos - worldBody.Position);
|
||||
|
||||
wheelPointVel -= worldVel;
|
||||
}*/
|
||||
|
||||
// sideways forces
|
||||
float noslipVel = 0.2f;
|
||||
float slipVel = 0.4f;
|
||||
float slipFactor = 0.7f;
|
||||
|
||||
float smallVel = 3;
|
||||
float friction = side_friction;
|
||||
|
||||
float sideVel = wheelPointVel.dot(groundLeft);
|
||||
|
||||
if ((sideVel > slipVel) || (sideVel < -slipVel))
|
||||
friction *= slipFactor;
|
||||
else
|
||||
if ((sideVel > noslipVel) || (sideVel < -noslipVel))
|
||||
friction *= 1.0f - (1.0f - slipFactor) * (Math::absf(sideVel) - noslipVel) / (slipVel - noslipVel);
|
||||
|
||||
if (sideVel < 0.0f)
|
||||
friction *= -1.0f;
|
||||
|
||||
if (Math::absf(sideVel) < smallVel)
|
||||
friction *= Math::absf(sideVel) / smallVel;
|
||||
|
||||
float sideForce = -friction * totalForceMag;
|
||||
|
||||
extraForce = sideForce * groundLeft;
|
||||
force += extraForce;
|
||||
// fwd/back forces
|
||||
friction = forward_friction;
|
||||
float fwdVel = wheelPointVel.dot(groundFwd);
|
||||
|
||||
if ((fwdVel > slipVel) || (fwdVel < -slipVel))
|
||||
friction *= slipFactor;
|
||||
else
|
||||
if ((fwdVel > noslipVel) || (fwdVel < -noslipVel))
|
||||
friction *= 1.0f - (1.0f - slipFactor) * (Math::absf(fwdVel) - noslipVel) / (slipVel - noslipVel);
|
||||
|
||||
if (fwdVel < 0.0f)
|
||||
friction *= -1.0f;
|
||||
|
||||
if (Math::absf(fwdVel) < smallVel)
|
||||
friction *= Math::absf(fwdVel) / smallVel;
|
||||
|
||||
float fwdForce = -friction * totalForceMag;
|
||||
|
||||
extraForce = fwdForce * groundFwd;
|
||||
force += extraForce;
|
||||
|
||||
|
||||
//if (!force.IsSensible())
|
||||
//{
|
||||
// TRACE_FILE_IF(ONCE_1)
|
||||
// TRACE("Bad force in car wheel\n");
|
||||
// return true;
|
||||
//}
|
||||
|
||||
// fwd force also spins the wheel
|
||||
Vector3 wheelCentreVel = s->get_linear_velocity() +
|
||||
(s->get_angular_velocity()).cross(s->get_transform().basis.xform(local_xform.origin));
|
||||
|
||||
angVelForGrip = wheelCentreVel.dot(groundFwd) / radius;
|
||||
torque += -fwdForce * radius;
|
||||
|
||||
// add force to car
|
||||
// carBody.AddWorldForce(force, groundPos);
|
||||
|
||||
s->add_force(force,(groundPos-s->get_transform().origin));
|
||||
|
||||
// add force to the world
|
||||
/*
|
||||
if (worldBody != null && !worldBody.Immovable)
|
||||
{
|
||||
// todo get the position in the right place...
|
||||
// also limit the velocity that this force can produce by looking at the
|
||||
// mass/inertia of the other object
|
||||
float maxOtherBodyAcc = 500.0f;
|
||||
float maxOtherBodyForce = maxOtherBodyAcc * worldBody.Mass;
|
||||
|
||||
if (force.LengthSquared() > (maxOtherBodyForce * maxOtherBodyForce))
|
||||
force *= maxOtherBodyForce / force.Length();
|
||||
|
||||
worldBody.AddWorldForce(-force, groundPos);
|
||||
}*/
|
||||
|
||||
Transform wheel_xf = local_xform;
|
||||
wheel_xf.origin += wheelUp * displacement;
|
||||
wheel_xf.basis = wheel_xf.basis * Matrix3(Vector3(0,1,0),Math::deg2rad(steerAngle));
|
||||
//wheel_xf.basis = wheel_xf.basis * Matrix3(wheel_xf.basis[0],-Math::deg2rad(axisAngle));
|
||||
|
||||
set_transform(wheel_xf);
|
||||
lastDisplacement=displacement;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
void CarWheel::set_type_drive(bool p_enable) {
|
||||
|
||||
type_drive=p_enable;
|
||||
}
|
||||
|
||||
bool CarWheel::is_type_drive() const {
|
||||
|
||||
return type_drive;
|
||||
}
|
||||
|
||||
void CarWheel::set_type_steer(bool p_enable) {
|
||||
|
||||
type_steer=p_enable;
|
||||
}
|
||||
|
||||
bool CarWheel::is_type_steer() const {
|
||||
|
||||
return type_steer;
|
||||
}
|
||||
|
||||
|
||||
void CarWheel::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_side_friction","friction"),&CarWheel::set_side_friction);
|
||||
ObjectTypeDB::bind_method(_MD("set_forward_friction","friction"),&CarWheel::set_forward_friction);
|
||||
ObjectTypeDB::bind_method(_MD("set_travel","distance"),&CarWheel::set_travel);
|
||||
ObjectTypeDB::bind_method(_MD("set_radius","radius"),&CarWheel::set_radius);
|
||||
ObjectTypeDB::bind_method(_MD("set_resting_frac","frac"),&CarWheel::set_resting_frac);
|
||||
ObjectTypeDB::bind_method(_MD("set_damping_frac","frac"),&CarWheel::set_damping_frac);
|
||||
ObjectTypeDB::bind_method(_MD("set_num_rays","amount"),&CarWheel::set_num_rays);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("get_side_friction"),&CarWheel::get_side_friction);
|
||||
ObjectTypeDB::bind_method(_MD("get_forward_friction"),&CarWheel::get_forward_friction);
|
||||
ObjectTypeDB::bind_method(_MD("get_travel"),&CarWheel::get_travel);
|
||||
ObjectTypeDB::bind_method(_MD("get_radius"),&CarWheel::get_radius);
|
||||
ObjectTypeDB::bind_method(_MD("get_resting_frac"),&CarWheel::get_resting_frac);
|
||||
ObjectTypeDB::bind_method(_MD("get_damping_frac"),&CarWheel::get_damping_frac);
|
||||
ObjectTypeDB::bind_method(_MD("get_num_rays"),&CarWheel::get_num_rays);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_type_drive","enable"),&CarWheel::set_type_drive);
|
||||
ObjectTypeDB::bind_method(_MD("is_type_drive"),&CarWheel::is_type_drive);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_type_steer","enable"),&CarWheel::set_type_steer);
|
||||
ObjectTypeDB::bind_method(_MD("is_type_steer"),&CarWheel::is_type_steer);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"type/drive"),_SCS("set_type_drive"),_SCS("is_type_drive"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"type/steer"),_SCS("set_type_steer"),_SCS("is_type_steer"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/side_friction",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_side_friction"),_SCS("get_side_friction"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/forward_friction",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_forward_friction"),_SCS("get_forward_friction"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/travel",PROPERTY_HINT_RANGE,"0.01,1024,0.01"),_SCS("set_travel"),_SCS("get_travel"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/radius",PROPERTY_HINT_RANGE,"0.01,1024,0.01"),_SCS("set_radius"),_SCS("get_radius"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/resting_frac",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_resting_frac"),_SCS("get_resting_frac"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/damping_frac",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_damping_frac"),_SCS("get_damping_frac"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/num_rays",PROPERTY_HINT_RANGE,"1,32,1"),_SCS("set_num_rays"),_SCS("get_num_rays"));
|
||||
|
||||
}
|
||||
|
||||
CarWheel::CarWheel() {
|
||||
|
||||
side_friction=4.7;
|
||||
forward_friction=5.0;
|
||||
travel=0.2;
|
||||
radius=0.4;
|
||||
resting_frac=0.45;
|
||||
damping_frac=0.3;
|
||||
num_rays=1;
|
||||
|
||||
angVel = 0.0f;
|
||||
steerAngle = 0.0f;
|
||||
torque = 0.0f;
|
||||
driveTorque = 0.0f;
|
||||
axisAngle = 0.0f;
|
||||
upSpeed = 0.0f;
|
||||
locked = false;
|
||||
lastDisplacement = 0.0f;
|
||||
lastOnFloor = false;
|
||||
angVelForGrip = 0.0f;
|
||||
angVelForGrip=0;
|
||||
|
||||
type_drive=false;
|
||||
type_steer=false;
|
||||
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
|
||||
void CarBody::set_max_steer_angle(real_t p_angle) {
|
||||
|
||||
max_steer_angle=p_angle;
|
||||
}
|
||||
void CarBody::set_steer_rate(real_t p_rate) {
|
||||
|
||||
steer_rate=p_rate;
|
||||
}
|
||||
void CarBody::set_drive_torque(real_t p_torque) {
|
||||
|
||||
drive_torque=p_torque;
|
||||
}
|
||||
|
||||
real_t CarBody::get_max_steer_angle() const{
|
||||
|
||||
return max_steer_angle;
|
||||
}
|
||||
real_t CarBody::get_steer_rate() const{
|
||||
|
||||
return steer_rate;
|
||||
}
|
||||
real_t CarBody::get_drive_torque() const{
|
||||
|
||||
return drive_torque;
|
||||
}
|
||||
|
||||
|
||||
void CarBody::set_target_steering(float p_steering) {
|
||||
|
||||
target_steering=p_steering;
|
||||
}
|
||||
|
||||
void CarBody::set_target_accelerate(float p_accelerate) {
|
||||
target_accelerate=p_accelerate;
|
||||
}
|
||||
|
||||
void CarBody::set_hand_brake(float p_amont) {
|
||||
|
||||
hand_brake=p_amont;
|
||||
}
|
||||
|
||||
real_t CarBody::get_target_steering() const {
|
||||
|
||||
return target_steering;
|
||||
}
|
||||
real_t CarBody::get_target_accelerate() const {
|
||||
|
||||
return target_accelerate;
|
||||
}
|
||||
real_t CarBody::get_hand_brake() const {
|
||||
|
||||
return hand_brake;
|
||||
}
|
||||
|
||||
|
||||
void CarBody::_direct_state_changed(Object *p_state) {
|
||||
|
||||
PhysicsDirectBodyState *state=p_state->cast_to<PhysicsDirectBodyState>();
|
||||
|
||||
float dt = state->get_step();
|
||||
AABB aabb;
|
||||
int drive_total=0;
|
||||
for(int i=0;i<wheels.size();i++) {
|
||||
CarWheel *w=wheels[i];
|
||||
if (i==0) {
|
||||
aabb.pos=w->local_xform.origin;
|
||||
} else {
|
||||
aabb.expand_to(w->local_xform.origin);
|
||||
}
|
||||
if (w->type_drive)
|
||||
drive_total++;
|
||||
|
||||
}
|
||||
// control inputs
|
||||
float deltaAccelerate = dt * 4.0f;
|
||||
|
||||
float dAccelerate = target_accelerate - accelerate;
|
||||
dAccelerate = CLAMP(dAccelerate, -deltaAccelerate, deltaAccelerate);
|
||||
accelerate += dAccelerate;
|
||||
|
||||
float deltaSteering = dt * steer_rate;
|
||||
float dSteering = target_steering - steering;
|
||||
dSteering = CLAMP(dSteering, -deltaSteering, deltaSteering);
|
||||
steering += dSteering;
|
||||
|
||||
// apply these inputs
|
||||
float maxTorque = drive_torque;
|
||||
|
||||
float torque_div = drive_total/2;
|
||||
if (torque_div>0)
|
||||
maxTorque/=torque_div;
|
||||
|
||||
|
||||
float alpha = ABS(max_steer_angle * steering);
|
||||
float angleSgn = steering > 0.0f ? 1.0f : -1.0f;
|
||||
|
||||
int wheels_on_floor=0;
|
||||
|
||||
for(int i=0;i<wheels.size();i++) {
|
||||
|
||||
CarWheel *w=wheels[i];
|
||||
if (w->type_drive)
|
||||
w->driveTorque+=maxTorque * accelerate;
|
||||
w->locked = !w->type_steer && (hand_brake > 0.5f);
|
||||
|
||||
if (w->type_steer) {
|
||||
//steering
|
||||
|
||||
bool inner = (steering > 0 && w->local_xform.origin.x > 0) || (steering < 0 && w->local_xform.origin.x < 0);
|
||||
|
||||
if (inner || alpha==0.0) {
|
||||
|
||||
w->steerAngle = (angleSgn * alpha);
|
||||
} else {
|
||||
float dx = aabb.size.z;
|
||||
float dy = aabb.size.x;
|
||||
|
||||
float beta = Math::atan2(dy, dx + (dy / (float)Math::tan(Math::deg2rad(alpha))));
|
||||
beta = Math::rad2deg(beta);
|
||||
w->steerAngle = (angleSgn * beta);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (w->add_forces(state))
|
||||
wheels_on_floor++;
|
||||
w->update(dt);
|
||||
|
||||
|
||||
}
|
||||
|
||||
print_line("onfloor: "+itos(wheels_on_floor));
|
||||
|
||||
|
||||
set_ignore_transform_notification(true);
|
||||
set_global_transform(state->get_transform());
|
||||
linear_velocity=state->get_linear_velocity();
|
||||
angular_velocity=state->get_angular_velocity();
|
||||
//active=!state->is_sleeping();
|
||||
//if (get_script_instance())
|
||||
// get_script_instance()->call("_integrate_forces",state);
|
||||
set_ignore_transform_notification(false);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CarBody::set_mass(real_t p_mass) {
|
||||
|
||||
mass=p_mass;
|
||||
PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_MASS,mass);
|
||||
}
|
||||
|
||||
real_t CarBody::get_mass() const{
|
||||
|
||||
return mass;
|
||||
}
|
||||
|
||||
|
||||
void CarBody::set_friction(real_t p_friction) {
|
||||
|
||||
friction=p_friction;
|
||||
PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_FRICTION,friction);
|
||||
}
|
||||
|
||||
real_t CarBody::get_friction() const{
|
||||
|
||||
return friction;
|
||||
}
|
||||
|
||||
|
||||
void CarBody::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_max_steer_angle","value"),&CarBody::set_max_steer_angle);
|
||||
ObjectTypeDB::bind_method(_MD("set_steer_rate","rate"),&CarBody::set_steer_rate);
|
||||
ObjectTypeDB::bind_method(_MD("set_drive_torque","value"),&CarBody::set_drive_torque);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("get_max_steer_angle"),&CarBody::get_max_steer_angle);
|
||||
ObjectTypeDB::bind_method(_MD("get_steer_rate"),&CarBody::get_steer_rate);
|
||||
ObjectTypeDB::bind_method(_MD("get_drive_torque"),&CarBody::get_drive_torque);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_target_steering","amount"),&CarBody::set_target_steering);
|
||||
ObjectTypeDB::bind_method(_MD("set_target_accelerate","amount"),&CarBody::set_target_accelerate);
|
||||
ObjectTypeDB::bind_method(_MD("set_hand_brake","amount"),&CarBody::set_hand_brake);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("get_target_steering"),&CarBody::get_target_steering);
|
||||
ObjectTypeDB::bind_method(_MD("get_target_accelerate"),&CarBody::get_target_accelerate);
|
||||
ObjectTypeDB::bind_method(_MD("get_hand_brake"),&CarBody::get_hand_brake);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_mass","mass"),&CarBody::set_mass);
|
||||
ObjectTypeDB::bind_method(_MD("get_mass"),&CarBody::get_mass);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_friction","friction"),&CarBody::set_friction);
|
||||
ObjectTypeDB::bind_method(_MD("get_friction"),&CarBody::get_friction);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_direct_state_changed"),&CarBody::_direct_state_changed);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"body/mass",PROPERTY_HINT_RANGE,"0.01,65536,0.01"),_SCS("set_mass"),_SCS("get_mass"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"body/friction",PROPERTY_HINT_RANGE,"0.01,1,0.01"),_SCS("set_friction"),_SCS("get_friction"));
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/max_steer_angle",PROPERTY_HINT_RANGE,"1,90,1"),_SCS("set_max_steer_angle"),_SCS("get_max_steer_angle"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/drive_torque",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_drive_torque"),_SCS("get_drive_torque"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/steer_rate",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_steer_rate"),_SCS("get_steer_rate"));
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"drive/target_steering",PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_target_steering"),_SCS("get_target_steering"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"drive/target_accelerate",PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_target_accelerate"),_SCS("get_target_accelerate"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"drive/hand_brake",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_hand_brake"),_SCS("get_hand_brake"));
|
||||
|
||||
}
|
||||
|
||||
CarBody::CarBody() : PhysicsBody(PhysicsServer::BODY_MODE_RIGID) {
|
||||
|
||||
forward_drive=true;
|
||||
backward_drive=true;
|
||||
max_steer_angle=30;
|
||||
steer_rate=1;
|
||||
drive_torque=520;
|
||||
|
||||
target_steering=0;
|
||||
target_accelerate=0;
|
||||
hand_brake=0;
|
||||
|
||||
steering=0;
|
||||
accelerate=0;
|
||||
|
||||
mass=1;
|
||||
friction=1;
|
||||
|
||||
ccd=false;
|
||||
// can_sleep=true;
|
||||
|
||||
|
||||
|
||||
|
||||
exclude.insert(get_rid());
|
||||
PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(),this,"_direct_state_changed");
|
||||
|
||||
|
||||
}
|
||||
170
scene/3d/car_body.h
Normal file
170
scene/3d/car_body.h
Normal file
@ -0,0 +1,170 @@
|
||||
/*************************************************************************/
|
||||
/* car_body.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef CAR_BODY_H
|
||||
#define CAR_BODY_H
|
||||
|
||||
#include "scene/3d/physics_body.h"
|
||||
|
||||
|
||||
class CarBody;
|
||||
|
||||
class CarWheel : public Spatial {
|
||||
|
||||
OBJ_TYPE(CarWheel,Spatial);
|
||||
|
||||
friend class CarBody;
|
||||
real_t side_friction;
|
||||
real_t forward_friction;
|
||||
real_t travel;
|
||||
real_t radius;
|
||||
real_t resting_frac;
|
||||
real_t damping_frac;
|
||||
int num_rays;
|
||||
Transform local_xform;
|
||||
|
||||
CarBody *body;
|
||||
|
||||
float angVel;
|
||||
float steerAngle;
|
||||
float torque;
|
||||
float driveTorque;
|
||||
float axisAngle;
|
||||
float upSpeed; // speed relative to the car
|
||||
bool locked;
|
||||
// last frame stuff
|
||||
float lastDisplacement;
|
||||
float angVelForGrip;
|
||||
bool lastOnFloor;
|
||||
|
||||
bool type_drive;
|
||||
bool type_steer;
|
||||
|
||||
|
||||
protected:
|
||||
void update(real_t dt);
|
||||
bool add_forces(PhysicsDirectBodyState *s);
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
void set_side_friction(real_t p_friction);
|
||||
void set_forward_friction(real_t p_friction);
|
||||
void set_travel(real_t p_travel);
|
||||
void set_radius(real_t p_radius);
|
||||
void set_resting_frac(real_t p_frac);
|
||||
void set_damping_frac(real_t p_frac);
|
||||
void set_num_rays(real_t p_rays);
|
||||
|
||||
real_t get_side_friction() const;
|
||||
real_t get_forward_friction() const;
|
||||
real_t get_travel() const;
|
||||
real_t get_radius() const;
|
||||
real_t get_resting_frac() const;
|
||||
real_t get_damping_frac() const;
|
||||
int get_num_rays() const;
|
||||
|
||||
void set_type_drive(bool p_enable);
|
||||
bool is_type_drive() const;
|
||||
|
||||
void set_type_steer(bool p_enable);
|
||||
bool is_type_steer() const;
|
||||
|
||||
CarWheel();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
class CarBody : public PhysicsBody {
|
||||
|
||||
OBJ_TYPE(CarBody,PhysicsBody);
|
||||
|
||||
real_t mass;
|
||||
real_t friction;
|
||||
|
||||
Vector3 linear_velocity;
|
||||
Vector3 angular_velocity;
|
||||
bool ccd;
|
||||
|
||||
real_t max_steer_angle;
|
||||
real_t steer_rate;
|
||||
int wheel_num_rays;
|
||||
real_t drive_torque;
|
||||
|
||||
// control stuff
|
||||
real_t target_steering;
|
||||
real_t target_accelerate;
|
||||
|
||||
bool forward_drive;
|
||||
bool backward_drive;
|
||||
|
||||
real_t steering;
|
||||
real_t accelerate;
|
||||
real_t hand_brake;
|
||||
Set<RID> exclude;
|
||||
|
||||
|
||||
friend class CarWheel;
|
||||
Vector<CarWheel*> wheels;
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
void _direct_state_changed(Object *p_state);
|
||||
public:
|
||||
|
||||
|
||||
void set_mass(real_t p_mass);
|
||||
real_t get_mass() const;
|
||||
|
||||
void set_friction(real_t p_friction);
|
||||
real_t get_friction() const;
|
||||
|
||||
void set_max_steer_angle(real_t p_angle);
|
||||
void set_steer_rate(real_t p_rate);
|
||||
void set_drive_torque(real_t p_torque);
|
||||
|
||||
real_t get_max_steer_angle() const;
|
||||
real_t get_steer_rate() const;
|
||||
real_t get_drive_torque() const;
|
||||
|
||||
|
||||
void set_target_steering(float p_steering);
|
||||
void set_target_accelerate(float p_accelerate);
|
||||
void set_hand_brake(float p_amont);
|
||||
|
||||
real_t get_target_steering() const;
|
||||
real_t get_target_accelerate() const;
|
||||
real_t get_hand_brake() const;
|
||||
|
||||
|
||||
CarBody();
|
||||
};
|
||||
|
||||
#endif // CAR_BODY_H
|
||||
718
scene/3d/character_camera.cpp
Normal file
718
scene/3d/character_camera.cpp
Normal file
@ -0,0 +1,718 @@
|
||||
/*************************************************************************/
|
||||
/* character_camera.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "character_camera.h"
|
||||
|
||||
#include "physics_body.h"
|
||||
#if 0
|
||||
void CharacterCamera::_set(const String& p_name, const Variant& p_value) {
|
||||
|
||||
if (p_name=="type")
|
||||
set_camera_type((CameraType)((int)(p_value)));
|
||||
else if (p_name=="orbit")
|
||||
set_orbit(p_value);
|
||||
else if (p_name=="height")
|
||||
set_height(p_value);
|
||||
else if (p_name=="inclination")
|
||||
set_inclination(p_value);
|
||||
else if (p_name=="max_orbit_x")
|
||||
set_max_orbit_x(p_value);
|
||||
else if (p_name=="min_orbit_x")
|
||||
set_min_orbit_x(p_value);
|
||||
else if (p_name=="max_distance")
|
||||
set_max_distance(p_value);
|
||||
else if (p_name=="min_distance")
|
||||
set_min_distance(p_value);
|
||||
else if (p_name=="distance")
|
||||
set_distance(p_value);
|
||||
else if (p_name=="clip")
|
||||
set_clip(p_value);
|
||||
else if (p_name=="autoturn")
|
||||
set_autoturn(p_value);
|
||||
else if (p_name=="autoturn_tolerance")
|
||||
set_autoturn_tolerance(p_value);
|
||||
else if (p_name=="autoturn_speed")
|
||||
set_autoturn_speed(p_value);
|
||||
|
||||
}
|
||||
Variant CharacterCamera::_get(const String& p_name) const {
|
||||
|
||||
if (p_name=="type")
|
||||
return get_camera_type();
|
||||
else if (p_name=="orbit")
|
||||
return get_orbit();
|
||||
else if (p_name=="height")
|
||||
return get_height();
|
||||
else if (p_name=="inclination")
|
||||
return get_inclination();
|
||||
else if (p_name=="max_orbit_x")
|
||||
return get_max_orbit_x();
|
||||
else if (p_name=="min_orbit_x")
|
||||
return get_min_orbit_x();
|
||||
else if (p_name=="max_distance")
|
||||
return get_max_distance();
|
||||
else if (p_name=="min_distance")
|
||||
return get_min_distance();
|
||||
else if (p_name=="distance")
|
||||
return get_distance();
|
||||
else if (p_name=="clip")
|
||||
return has_clip();
|
||||
else if (p_name=="autoturn")
|
||||
return has_autoturn();
|
||||
else if (p_name=="autoturn_tolerance")
|
||||
return get_autoturn_tolerance();
|
||||
else if (p_name=="autoturn_speed")
|
||||
return get_autoturn_speed();
|
||||
|
||||
return Variant();
|
||||
}
|
||||
|
||||
void CharacterCamera::_get_property_list( List<PropertyInfo> *p_list) const {
|
||||
|
||||
p_list->push_back( PropertyInfo( Variant::INT, "type", PROPERTY_HINT_ENUM, "Fixed,Follow") );
|
||||
p_list->push_back( PropertyInfo( Variant::VECTOR2, "orbit" ) );
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "height", PROPERTY_HINT_RANGE,"-1024,1024,0.01" ) );
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "inclination", PROPERTY_HINT_RANGE,"-90,90,0.01" ) ); ;
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "max_orbit_x", PROPERTY_HINT_RANGE,"-90,90,0.01" ) );
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "min_orbit_x", PROPERTY_HINT_RANGE,"-90,90,0.01" ) );
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "min_distance", PROPERTY_HINT_RANGE,"0,100,0.01" ) );
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "max_distance", PROPERTY_HINT_RANGE,"0,100,0.01" ) );
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "distance", PROPERTY_HINT_RANGE,"0.01,1024,0,01") );
|
||||
p_list->push_back( PropertyInfo( Variant::BOOL, "clip") );
|
||||
p_list->push_back( PropertyInfo( Variant::BOOL, "autoturn") );
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "autoturn_tolerance", PROPERTY_HINT_RANGE,"1,90,0.01") );
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "autoturn_speed", PROPERTY_HINT_RANGE,"1,90,0.01") );
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CharacterCamera::_compute_camera() {
|
||||
|
||||
|
||||
// update the transform with the next proposed transform (camera is 1 logic frame delayed)
|
||||
|
||||
/*
|
||||
float time = get_root_node()->get_frame_time();
|
||||
Vector3 oldp = accepted.get_origin();
|
||||
Vector3 newp = proposed.get_origin();
|
||||
|
||||
float frame_dist = time *
|
||||
if (oldp.distance_to(newp) >
|
||||
*/
|
||||
|
||||
float time = get_root_node()->get_frame_time();
|
||||
|
||||
if (true) {
|
||||
|
||||
if (clip_ray[0].clipped && clip_ray[1].clipped && clip_ray[2].clipped) {
|
||||
//all have been clipped
|
||||
proposed.origin=clip_ray[1].clip_pos;
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
Vector3 rel=proposed.origin-target_pos;
|
||||
|
||||
if (clip_ray[0].clipped && !clip_ray[2].clipped) {
|
||||
|
||||
float distance = target_pos.distance_to(clip_ray[0].clip_pos);
|
||||
real_t amount = 1.0-(distance/clip_len);
|
||||
amount = CLAMP(amount,0,1);
|
||||
|
||||
|
||||
rel=Matrix3(Vector3(0,1,0)),
|
||||
rotate_orbit(Vector2(0,autoturn_speed*time*amount));
|
||||
}
|
||||
if (clip_ray[2].clipped && !clip_ray[0].clipped) {
|
||||
|
||||
float distance = target_pos.distance_to(clip_ray[2].clip_pos);
|
||||
real_t amount = 1.0-(distance/clip_len);
|
||||
amount = CLAMP(amount,0,1);
|
||||
|
||||
rotate_orbit(Vector2(0,-autoturn_speed*time*amount));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Transform final;
|
||||
|
||||
static float pos_ratio = 0.9;
|
||||
static float rot_ratio = 10;
|
||||
|
||||
Vector3 vec1 = accepted.origin;
|
||||
Vector3 vec2 = proposed.origin;
|
||||
final.origin = vec2.linear_interpolate(vec1, pos_ratio * time);;
|
||||
|
||||
Quat q1 = accepted.basis;
|
||||
Quat q2 = proposed.basis;
|
||||
final.basis = q1.slerp(q2, rot_ratio * time);
|
||||
|
||||
accepted=final;
|
||||
|
||||
_update_camera();
|
||||
|
||||
// calculate the next proposed transform
|
||||
|
||||
|
||||
Vector3 new_pos;
|
||||
Vector3 character_pos = get_global_transform().origin;
|
||||
character_pos.y+=height; // height compensate
|
||||
|
||||
if(type==CAMERA_FOLLOW) {
|
||||
|
||||
|
||||
|
||||
/* calculate some variables */
|
||||
|
||||
Vector3 rel = follow_pos - character_pos;
|
||||
|
||||
float l = rel.length();
|
||||
Vector3 rel_n = (l > 0) ? (rel/l) : Vector3();
|
||||
#if 1
|
||||
float ang = Math::acos(rel_n.dot( Vector3(0,1,0) ));
|
||||
|
||||
Vector3 tangent = rel_n;
|
||||
tangent.y=0; // get rid of y
|
||||
if (tangent.length_squared() < CMP_EPSILON2)
|
||||
tangent=Vector3(0,0,1); // use Z as tangent if rel is parallel to y
|
||||
else
|
||||
tangent.normalize();
|
||||
|
||||
/* now start applying the rules */
|
||||
|
||||
//clip distance
|
||||
if (l > max_distance)
|
||||
l=max_distance;
|
||||
if (l < min_distance)
|
||||
l=min_distance;
|
||||
|
||||
//fix angle
|
||||
|
||||
float ang_min = Math_PI * 0.5 + Math::deg2rad(min_orbit_x);
|
||||
float ang_max = Math_PI * 0.5 + Math::deg2rad(max_orbit_x);
|
||||
|
||||
if (ang<ang_min)
|
||||
ang=ang_min;
|
||||
if (ang>ang_max)
|
||||
ang=ang_max;
|
||||
|
||||
/* finally, rebuild the validated camera position */
|
||||
|
||||
new_pos=Vector3(0,Math::cos(ang),0);
|
||||
new_pos+=tangent*Math::sin(ang);
|
||||
new_pos*=l;
|
||||
new_pos+=character_pos;
|
||||
#else
|
||||
if (l > max_distance)
|
||||
l=max_distance;
|
||||
if (l < min_distance)
|
||||
l=min_distance;
|
||||
|
||||
new_pos = character_pos + rel_n * l;
|
||||
|
||||
|
||||
#endif
|
||||
follow_pos=new_pos;
|
||||
|
||||
} else if (type==CAMERA_FIXED) {
|
||||
|
||||
|
||||
if (distance<min_distance)
|
||||
distance=min_distance;
|
||||
if (distance>max_distance)
|
||||
distance=max_distance;
|
||||
|
||||
if (orbit.x<min_orbit_x)
|
||||
orbit.x=min_orbit_x;
|
||||
if (orbit.x>max_orbit_x)
|
||||
orbit.x=max_orbit_x;
|
||||
|
||||
Matrix3 m;
|
||||
m.rotate(Vector3(0,1,0),Math::deg2rad(orbit.y));
|
||||
m.rotate(Vector3(1,0,0),Math::deg2rad(orbit.x));
|
||||
|
||||
new_pos = (m.get_axis(2) * distance) + character_pos;
|
||||
|
||||
if (use_lookat_target) {
|
||||
|
||||
Transform t = get_global_transform();
|
||||
Vector3 y = t.basis.get_axis(1).normalized();
|
||||
Vector3 z = lookat_target - character_pos;
|
||||
z= (z - y * y.dot(z)).normalized();
|
||||
orbit.y = -Math::rad2deg(Math::atan2(z.x,z.z)) + 180;
|
||||
|
||||
/*
|
||||
Transform t = get_global_transform();
|
||||
Vector3 y = t.basis.get_axis(1).normalized();
|
||||
Vector3 z = lookat_target - t.origin;
|
||||
z= (z - y * y.dot(z)).normalized();
|
||||
Vector3 x = z.cross(y).normalized();
|
||||
Transform t2;
|
||||
t2.basis.set_axis(0,x);
|
||||
t2.basis.set_axis(1,y);
|
||||
t2.basis.set_axis(2,z);
|
||||
t2.origin=t.origin;
|
||||
|
||||
Vector3 local = t2.xform_inv(camera_pos);
|
||||
|
||||
float ang = Math::atan2(local.x,local.y);
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Vector3 vec1 = lookat_target - new_pos;
|
||||
vec1.normalize();
|
||||
Vector3 vec2 = character_pos - new_pos;
|
||||
vec2.normalize();
|
||||
|
||||
float dot = vec1.dot(vec2);
|
||||
printf("dot %f\n", dot);
|
||||
if ( dot < 0.5) {
|
||||
|
||||
rotate_orbit(Vector2(0, 90));
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
Vector3 target;
|
||||
if (use_lookat_target) {
|
||||
|
||||
target = lookat_target;
|
||||
} else {
|
||||
target = character_pos;
|
||||
};
|
||||
|
||||
proposed.set_look_at(new_pos,target,Vector3(0,1,0));
|
||||
proposed = proposed * Transform(Matrix3(Vector3(1,0,0),Math::deg2rad(inclination)),Vector3()); //inclination
|
||||
|
||||
|
||||
Vector<RID> exclude;
|
||||
exclude.push_back(target_body);
|
||||
|
||||
|
||||
|
||||
Vector3 rel = new_pos-target;
|
||||
|
||||
for(int i=0;i<3;i++) {
|
||||
|
||||
PhysicsServer::get_singleton()->query_intersection(clip_ray[i].query,get_world().get_space(),exclude);
|
||||
PhysicsServer::get_singleton()->query_intersection_segment(clip_ray[i].query,target,target+Matrix3(Vector3(0,1,0),Math::deg2rad(autoturn_tolerance*(i-1.0))).xform(rel));
|
||||
clip_ray[i].clipped=false;
|
||||
clip_ray[i].clip_pos=Vector3();
|
||||
}
|
||||
target_pos=target;
|
||||
clip_len=rel.length();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CharacterCamera::set_use_lookat_target(bool p_use, const Vector3 &p_lookat) {
|
||||
|
||||
use_lookat_target = p_use;
|
||||
lookat_target = p_lookat;
|
||||
};
|
||||
|
||||
|
||||
void CharacterCamera::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_PROCESS: {
|
||||
|
||||
|
||||
_compute_camera();
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_ENTER_SCENE: {
|
||||
|
||||
if (type==CAMERA_FOLLOW) {
|
||||
|
||||
set_orbit(orbit);
|
||||
set_distance(distance);
|
||||
}
|
||||
|
||||
accepted=get_global_transform();
|
||||
proposed=accepted;
|
||||
|
||||
target_body = RID();
|
||||
|
||||
Node* parent = get_parent();
|
||||
while (parent) {
|
||||
PhysicsBody* p = parent->cast_to<PhysicsBody>();
|
||||
if (p) {
|
||||
target_body = p->get_body();
|
||||
break;
|
||||
};
|
||||
parent = parent->get_parent();
|
||||
};
|
||||
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_SCENE: {
|
||||
|
||||
if (type==CAMERA_FOLLOW) {
|
||||
distance=get_distance();
|
||||
orbit=get_orbit();
|
||||
|
||||
}
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_BECAME_CURRENT: {
|
||||
|
||||
set_process(true);
|
||||
} break;
|
||||
case NOTIFICATION_LOST_CURRENT: {
|
||||
|
||||
set_process(false);
|
||||
} break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CharacterCamera::set_camera_type(CameraType p_camera_type) {
|
||||
|
||||
|
||||
if (p_camera_type==type)
|
||||
return;
|
||||
|
||||
type=p_camera_type;
|
||||
|
||||
// do conversions
|
||||
}
|
||||
|
||||
CharacterCamera::CameraType CharacterCamera::get_camera_type() const {
|
||||
|
||||
return type;
|
||||
|
||||
}
|
||||
|
||||
void CharacterCamera::set_orbit(const Vector2& p_orbit) {
|
||||
|
||||
orbit=p_orbit;
|
||||
|
||||
if(type == CAMERA_FOLLOW && is_inside_scene()) {
|
||||
|
||||
Vector3 char_pos = get_global_transform().origin;
|
||||
char_pos.y+=height;
|
||||
float d = char_pos.distance_to(follow_pos);
|
||||
|
||||
Matrix3 m;
|
||||
m.rotate(Vector3(0,1,0),orbit.y);
|
||||
m.rotate(Vector3(1,0,0),orbit.x);
|
||||
|
||||
follow_pos=char_pos + m.get_axis(2) * d;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
void CharacterCamera::set_orbit_x(float p_x) {
|
||||
|
||||
orbit.x=p_x;
|
||||
if(type == CAMERA_FOLLOW && is_inside_scene())
|
||||
set_orbit(Vector2( p_x, get_orbit().y ));
|
||||
}
|
||||
void CharacterCamera::set_orbit_y(float p_y) {
|
||||
|
||||
|
||||
orbit.y=p_y;
|
||||
if(type == CAMERA_FOLLOW && is_inside_scene())
|
||||
set_orbit(Vector2( get_orbit().x, p_y ));
|
||||
|
||||
}
|
||||
Vector2 CharacterCamera::get_orbit() const {
|
||||
|
||||
|
||||
if (type == CAMERA_FOLLOW && is_inside_scene()) {
|
||||
|
||||
Vector3 char_pos = get_global_transform().origin;
|
||||
char_pos.y+=height;
|
||||
Vector3 rel = (follow_pos - char_pos).normalized();
|
||||
Vector2 ret_orbit;
|
||||
ret_orbit.x = Math::acos( Vector3(0,1,0).dot( rel ) ) - Math_PI * 0.5;
|
||||
ret_orbit.y = Math::atan2(rel.x,rel.z);
|
||||
return ret_orbit;
|
||||
}
|
||||
return orbit;
|
||||
}
|
||||
|
||||
void CharacterCamera::rotate_orbit(const Vector2& p_relative) {
|
||||
|
||||
if (type == CAMERA_FOLLOW && is_inside_scene()) {
|
||||
|
||||
Matrix3 m;
|
||||
m.rotate(Vector3(0,1,0),Math::deg2rad(p_relative.y));
|
||||
m.rotate(Vector3(1,0,0),Math::deg2rad(p_relative.x));
|
||||
|
||||
Vector3 char_pos = get_global_transform().origin;
|
||||
char_pos.y+=height;
|
||||
Vector3 rel = (follow_pos - char_pos);
|
||||
rel = m.xform(rel);
|
||||
follow_pos=char_pos+rel;
|
||||
|
||||
}
|
||||
|
||||
orbit+=p_relative;
|
||||
}
|
||||
|
||||
void CharacterCamera::set_height(float p_height) {
|
||||
|
||||
|
||||
height=p_height;
|
||||
}
|
||||
|
||||
float CharacterCamera::get_height() const {
|
||||
|
||||
return height;
|
||||
|
||||
}
|
||||
|
||||
void CharacterCamera::set_max_orbit_x(float p_max) {
|
||||
|
||||
max_orbit_x=p_max;
|
||||
}
|
||||
|
||||
float CharacterCamera::get_max_orbit_x() const {
|
||||
|
||||
return max_orbit_x;
|
||||
}
|
||||
|
||||
void CharacterCamera::set_min_orbit_x(float p_min) {
|
||||
|
||||
min_orbit_x=p_min;
|
||||
}
|
||||
|
||||
float CharacterCamera::get_min_orbit_x() const {
|
||||
|
||||
return min_orbit_x;
|
||||
}
|
||||
|
||||
float CharacterCamera::get_min_distance() const {
|
||||
|
||||
return min_distance;
|
||||
}
|
||||
float CharacterCamera::get_max_distance() const {
|
||||
|
||||
return max_distance;
|
||||
}
|
||||
|
||||
void CharacterCamera::set_min_distance(float p_min) {
|
||||
|
||||
min_distance=p_min;
|
||||
}
|
||||
|
||||
void CharacterCamera::set_max_distance(float p_max) {
|
||||
|
||||
max_distance = p_max;
|
||||
}
|
||||
|
||||
|
||||
void CharacterCamera::set_distance(float p_distance) {
|
||||
|
||||
if (type == CAMERA_FOLLOW && is_inside_scene()) {
|
||||
|
||||
Vector3 char_pos = get_global_transform().origin;
|
||||
char_pos.y+=height;
|
||||
Vector3 rel = (follow_pos - char_pos).normalized();
|
||||
rel*=p_distance;
|
||||
follow_pos=char_pos+rel;
|
||||
|
||||
}
|
||||
|
||||
distance=p_distance;
|
||||
}
|
||||
|
||||
float CharacterCamera::get_distance() const {
|
||||
|
||||
if (type == CAMERA_FOLLOW && is_inside_scene()) {
|
||||
|
||||
Vector3 char_pos = get_global_transform().origin;
|
||||
char_pos.y+=height;
|
||||
return (follow_pos - char_pos).length();
|
||||
|
||||
}
|
||||
|
||||
return distance;
|
||||
}
|
||||
|
||||
void CharacterCamera::set_clip(bool p_enabled) {
|
||||
|
||||
|
||||
clip=p_enabled;
|
||||
}
|
||||
|
||||
bool CharacterCamera::has_clip() const {
|
||||
|
||||
return clip;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CharacterCamera::set_autoturn(bool p_enabled) {
|
||||
|
||||
|
||||
autoturn=p_enabled;
|
||||
}
|
||||
|
||||
bool CharacterCamera::has_autoturn() const {
|
||||
|
||||
return autoturn;
|
||||
|
||||
}
|
||||
|
||||
void CharacterCamera::set_autoturn_tolerance(float p_degrees) {
|
||||
|
||||
|
||||
autoturn_tolerance=p_degrees;
|
||||
}
|
||||
float CharacterCamera::get_autoturn_tolerance() const {
|
||||
|
||||
|
||||
return autoturn_tolerance;
|
||||
}
|
||||
|
||||
void CharacterCamera::set_inclination(float p_degrees) {
|
||||
|
||||
|
||||
inclination=p_degrees;
|
||||
}
|
||||
float CharacterCamera::get_inclination() const {
|
||||
|
||||
|
||||
return inclination;
|
||||
}
|
||||
|
||||
|
||||
void CharacterCamera::set_autoturn_speed(float p_speed) {
|
||||
|
||||
|
||||
autoturn_speed=p_speed;
|
||||
}
|
||||
float CharacterCamera::get_autoturn_speed() const {
|
||||
|
||||
return autoturn_speed;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void CharacterCamera::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_camera_type","type"),&CharacterCamera::set_camera_type);
|
||||
ObjectTypeDB::bind_method(_MD("get_camera_type"),&CharacterCamera::get_camera_type);
|
||||
ObjectTypeDB::bind_method(_MD("set_orbit","orbit"),&CharacterCamera::set_orbit);
|
||||
ObjectTypeDB::bind_method(_MD("get_orbit"),&CharacterCamera::get_orbit);
|
||||
ObjectTypeDB::bind_method(_MD("set_orbit_x","x"),&CharacterCamera::set_orbit_x);
|
||||
ObjectTypeDB::bind_method(_MD("set_orbit_y","y"),&CharacterCamera::set_orbit_y);
|
||||
ObjectTypeDB::bind_method(_MD("set_min_orbit_x","x"),&CharacterCamera::set_min_orbit_x);
|
||||
ObjectTypeDB::bind_method(_MD("get_min_orbit_x"),&CharacterCamera::get_min_orbit_x);
|
||||
ObjectTypeDB::bind_method(_MD("set_max_orbit_x","x"),&CharacterCamera::set_max_orbit_x);
|
||||
ObjectTypeDB::bind_method(_MD("get_max_orbit_x"),&CharacterCamera::get_max_orbit_x);
|
||||
ObjectTypeDB::bind_method(_MD("rotate_orbit"),&CharacterCamera::rotate_orbit);
|
||||
ObjectTypeDB::bind_method(_MD("set_distance","distance"),&CharacterCamera::set_distance);
|
||||
ObjectTypeDB::bind_method(_MD("get_distance"),&CharacterCamera::get_distance);
|
||||
ObjectTypeDB::bind_method(_MD("set_clip","enable"),&CharacterCamera::set_clip);
|
||||
ObjectTypeDB::bind_method(_MD("has_clip"),&CharacterCamera::has_clip);
|
||||
ObjectTypeDB::bind_method(_MD("set_autoturn","enable"),&CharacterCamera::set_autoturn);
|
||||
ObjectTypeDB::bind_method(_MD("has_autoturn"),&CharacterCamera::has_autoturn);
|
||||
ObjectTypeDB::bind_method(_MD("set_autoturn_tolerance","degrees"),&CharacterCamera::set_autoturn_tolerance);
|
||||
ObjectTypeDB::bind_method(_MD("get_autoturn_tolerance"),&CharacterCamera::get_autoturn_tolerance);
|
||||
ObjectTypeDB::bind_method(_MD("set_autoturn_speed","speed"),&CharacterCamera::set_autoturn_speed);
|
||||
ObjectTypeDB::bind_method(_MD("get_autoturn_speed"),&CharacterCamera::get_autoturn_speed);
|
||||
ObjectTypeDB::bind_method(_MD("set_use_lookat_target","use","lookat"),&CharacterCamera::set_use_lookat_target, DEFVAL(Vector3()));
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_ray_collision"),&CharacterCamera::_ray_collision);
|
||||
|
||||
BIND_CONSTANT( CAMERA_FIXED );
|
||||
BIND_CONSTANT( CAMERA_FOLLOW );
|
||||
}
|
||||
|
||||
void CharacterCamera::_ray_collision(Vector3 p_point, Vector3 p_normal, int p_subindex, ObjectID p_against,int p_idx) {
|
||||
|
||||
|
||||
clip_ray[p_idx].clip_pos=p_point;
|
||||
clip_ray[p_idx].clipped=true;
|
||||
};
|
||||
|
||||
Transform CharacterCamera::get_camera_transform() const {
|
||||
|
||||
return accepted;
|
||||
}
|
||||
|
||||
|
||||
CharacterCamera::CharacterCamera() {
|
||||
|
||||
|
||||
type=CAMERA_FOLLOW;
|
||||
height=1;
|
||||
|
||||
orbit=Vector2(0,0);
|
||||
|
||||
distance=3;
|
||||
min_distance=2;
|
||||
max_distance=5;
|
||||
|
||||
autoturn=false;
|
||||
autoturn_tolerance=15;
|
||||
autoturn_speed=20;
|
||||
|
||||
min_orbit_x=-50;
|
||||
max_orbit_x=70;
|
||||
inclination=0;
|
||||
|
||||
clip=false;
|
||||
use_lookat_target = false;
|
||||
|
||||
for(int i=0;i<3;i++) {
|
||||
clip_ray[i].query=PhysicsServer::get_singleton()->query_create(this, "_ray_collision", i, true);
|
||||
clip_ray[i].clipped=false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
CharacterCamera::~CharacterCamera() {
|
||||
|
||||
for(int i=0;i<3;i++) {
|
||||
PhysicsServer::get_singleton()->free(clip_ray[i].query);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
167
scene/3d/character_camera.h
Normal file
167
scene/3d/character_camera.h
Normal file
@ -0,0 +1,167 @@
|
||||
/*************************************************************************/
|
||||
/* character_camera.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef CHARACTER_CAMERA_H
|
||||
#define CHARACTER_CAMERA_H
|
||||
|
||||
|
||||
#include "scene/3d/camera.h"
|
||||
#if 0
|
||||
class CharacterCamera : public Camera {
|
||||
|
||||
OBJ_TYPE( CharacterCamera, Camera );
|
||||
public:
|
||||
|
||||
enum CameraType {
|
||||
CAMERA_FIXED,
|
||||
CAMERA_FOLLOW
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
|
||||
CameraType type;
|
||||
|
||||
//used for follow
|
||||
Vector3 follow_pos;
|
||||
//used for fixed
|
||||
Vector2 orbit;
|
||||
float distance;
|
||||
|
||||
float height;
|
||||
|
||||
float min_distance;
|
||||
float max_distance;
|
||||
|
||||
float max_orbit_x;
|
||||
float min_orbit_x;
|
||||
|
||||
float inclination;
|
||||
|
||||
bool clip;
|
||||
bool autoturn;
|
||||
float autoturn_tolerance;
|
||||
float autoturn_speed;
|
||||
|
||||
|
||||
|
||||
struct ClipRay {
|
||||
RID query;
|
||||
bool clipped;
|
||||
Vector3 clip_pos;
|
||||
};
|
||||
|
||||
ClipRay clip_ray[3];
|
||||
Vector3 target_pos;
|
||||
float clip_len;
|
||||
|
||||
|
||||
Transform accepted;
|
||||
Vector3 proposed_pos;
|
||||
|
||||
bool use_lookat_target;
|
||||
Vector3 lookat_target;
|
||||
|
||||
void _compute_camera();
|
||||
|
||||
RID ray_query;
|
||||
RID left_turn_query;
|
||||
RID right_turn_query;
|
||||
RID target_body;
|
||||
|
||||
protected:
|
||||
|
||||
virtual void _request_camera_update() {} //ignore
|
||||
|
||||
bool _set(const StringName& p_name, const Variant& p_value);
|
||||
bool _get(const StringName& p_name,Variant &r_ret) const;
|
||||
void _get_property_list( List<PropertyInfo> *p_list) const;
|
||||
void _notification(int p_what);
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
void _ray_collision(Vector3 p_point, Vector3 p_normal, int p_subindex, ObjectID p_against,int p_idx);
|
||||
|
||||
public:
|
||||
|
||||
|
||||
void set_camera_type(CameraType p_camera_type);
|
||||
CameraType get_camera_type() const;
|
||||
|
||||
void set_orbit(const Vector2& p_orbit);
|
||||
void set_orbit_x(float p_x);
|
||||
void set_orbit_y(float p_y);
|
||||
Vector2 get_orbit() const;
|
||||
|
||||
void set_height(float p_height);
|
||||
float get_height() const;
|
||||
|
||||
void set_inclination(float p_degrees);
|
||||
float get_inclination() const;
|
||||
|
||||
void set_max_orbit_x(float p_max);
|
||||
float get_max_orbit_x() const;
|
||||
|
||||
void set_min_orbit_x(float p_min);
|
||||
float get_min_orbit_x() const;
|
||||
|
||||
void rotate_orbit(const Vector2& p_relative);
|
||||
|
||||
void set_distance(float p_distance);
|
||||
float get_distance() const;
|
||||
|
||||
float get_min_distance() const;
|
||||
float get_max_distance() const;
|
||||
void set_min_distance(float p_min);
|
||||
void set_max_distance(float p_max);
|
||||
|
||||
|
||||
void set_clip(bool p_enabled);
|
||||
bool has_clip() const;
|
||||
|
||||
void set_autoturn(bool p_enabled);
|
||||
bool has_autoturn() const;
|
||||
|
||||
void set_autoturn_tolerance(float p_degrees);
|
||||
float get_autoturn_tolerance() const;
|
||||
|
||||
void set_autoturn_speed(float p_speed);
|
||||
float get_autoturn_speed() const;
|
||||
|
||||
void set_use_lookat_target(bool p_use, const Vector3 &p_lookat = Vector3());
|
||||
|
||||
virtual Transform get_camera_transform() const;
|
||||
|
||||
CharacterCamera();
|
||||
~CharacterCamera();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST( CharacterCamera::CameraType );
|
||||
|
||||
#endif
|
||||
#endif // CHARACTER_CAMERA_H
|
||||
284
scene/3d/collision_object.cpp
Normal file
284
scene/3d/collision_object.cpp
Normal file
@ -0,0 +1,284 @@
|
||||
/*************************************************************************/
|
||||
/* collision_object.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "collision_object.h"
|
||||
#include "servers/physics_server.h"
|
||||
|
||||
void CollisionObject::_update_shapes_from_children() {
|
||||
|
||||
shapes.resize(0);
|
||||
for(int i=0;i<get_child_count();i++) {
|
||||
|
||||
Node* n = get_child(i);
|
||||
n->call("_add_to_collision_object",this);
|
||||
}
|
||||
|
||||
// _update_shapes();
|
||||
}
|
||||
|
||||
void CollisionObject::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_ENTER_WORLD: {
|
||||
|
||||
RID space = get_world()->get_space();
|
||||
if (area) {
|
||||
PhysicsServer::get_singleton()->area_set_space(rid,space);
|
||||
} else
|
||||
PhysicsServer::get_singleton()->body_set_space(rid,space);
|
||||
|
||||
//get space
|
||||
}
|
||||
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
|
||||
if (area)
|
||||
PhysicsServer::get_singleton()->area_set_transform(rid,get_global_transform());
|
||||
else
|
||||
PhysicsServer::get_singleton()->body_set_state(rid,PhysicsServer::BODY_STATE_TRANSFORM,get_global_transform());
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_WORLD: {
|
||||
|
||||
if (area) {
|
||||
PhysicsServer::get_singleton()->area_set_space(rid,RID());
|
||||
} else
|
||||
PhysicsServer::get_singleton()->body_set_space(rid,RID());
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void CollisionObject::_update_shapes() {
|
||||
|
||||
if (!rid.is_valid())
|
||||
return;
|
||||
|
||||
if (area)
|
||||
PhysicsServer::get_singleton()->area_clear_shapes(rid);
|
||||
else
|
||||
PhysicsServer::get_singleton()->body_clear_shapes(rid);
|
||||
|
||||
for(int i=0;i<shapes.size();i++) {
|
||||
|
||||
if (shapes[i].shape.is_null())
|
||||
continue;
|
||||
if (area)
|
||||
PhysicsServer::get_singleton()->area_add_shape(rid,shapes[i].shape->get_rid(),shapes[i].xform);
|
||||
else {
|
||||
PhysicsServer::get_singleton()->body_add_shape(rid,shapes[i].shape->get_rid(),shapes[i].xform);
|
||||
if (shapes[i].trigger)
|
||||
PhysicsServer::get_singleton()->body_set_shape_as_trigger(rid,i,shapes[i].trigger);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CollisionObject::_set(const StringName& p_name, const Variant& p_value) {
|
||||
String name=p_name;
|
||||
|
||||
if (name=="shape_count") {
|
||||
|
||||
shapes.resize(p_value);
|
||||
_update_shapes();
|
||||
_change_notify();
|
||||
|
||||
} else if (name.begins_with("shapes/")) {
|
||||
|
||||
int idx=name.get_slice("/",1).to_int();
|
||||
String what=name.get_slice("/",2);
|
||||
if (what=="shape")
|
||||
set_shape(idx,RefPtr(p_value));
|
||||
else if (what=="transform")
|
||||
set_shape_transform(idx,p_value);
|
||||
else if (what=="trigger")
|
||||
set_shape_as_trigger(idx,p_value);
|
||||
|
||||
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool CollisionObject::_get(const StringName& p_name,Variant &r_ret) const {
|
||||
|
||||
String name=p_name;
|
||||
|
||||
if (name=="shape_count") {
|
||||
r_ret= shapes.size();
|
||||
} else if (name.begins_with("shapes/")) {
|
||||
|
||||
int idx=name.get_slice("/",1).to_int();
|
||||
String what=name.get_slice("/",2);
|
||||
if (what=="shape")
|
||||
r_ret= get_shape(idx);
|
||||
else if (what=="transform")
|
||||
r_ret= get_shape_transform(idx);
|
||||
else if (what=="trigger")
|
||||
r_ret= is_shape_set_as_trigger(idx);
|
||||
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CollisionObject::_get_property_list( List<PropertyInfo> *p_list) const {
|
||||
|
||||
p_list->push_back( PropertyInfo(Variant::INT,"shape_count",PROPERTY_HINT_RANGE,"0,256,1",PROPERTY_USAGE_NOEDITOR) );
|
||||
|
||||
for(int i=0;i<shapes.size();i++) {
|
||||
String path="shapes/"+itos(i)+"/";
|
||||
p_list->push_back( PropertyInfo(Variant::OBJECT,path+"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape",PROPERTY_USAGE_NOEDITOR) );
|
||||
p_list->push_back( PropertyInfo(Variant::TRANSFORM,path+"transform",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
|
||||
p_list->push_back( PropertyInfo(Variant::BOOL,path+"trigger",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void CollisionObject::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("add_shape","shape:Shape","transform"),&CollisionObject::add_shape,DEFVAL(Transform()));
|
||||
ObjectTypeDB::bind_method(_MD("get_shape_count"),&CollisionObject::get_shape_count);
|
||||
ObjectTypeDB::bind_method(_MD("set_shape","shape_idx","shape:Shape"),&CollisionObject::set_shape);
|
||||
ObjectTypeDB::bind_method(_MD("set_shape_transform","shape_idx","transform"),&CollisionObject::set_shape_transform);
|
||||
// ObjectTypeDB::bind_method(_MD("set_shape_transform","shape_idx","transform"),&CollisionObject::set_shape_transform);
|
||||
ObjectTypeDB::bind_method(_MD("set_shape_as_trigger","shape_idx","enable"),&CollisionObject::set_shape_as_trigger);
|
||||
ObjectTypeDB::bind_method(_MD("is_shape_set_as_trigger","shape_idx"),&CollisionObject::is_shape_set_as_trigger);
|
||||
ObjectTypeDB::bind_method(_MD("get_shape:Shape","shape_idx"),&CollisionObject::get_shape);
|
||||
ObjectTypeDB::bind_method(_MD("get_shape_transform","shape_idx"),&CollisionObject::get_shape_transform);
|
||||
ObjectTypeDB::bind_method(_MD("remove_shape","shape_idx"),&CollisionObject::remove_shape);
|
||||
ObjectTypeDB::bind_method(_MD("clear_shapes"),&CollisionObject::clear_shapes);
|
||||
ObjectTypeDB::bind_method(_MD("get_rid"),&CollisionObject::get_rid);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CollisionObject::add_shape(const Ref<Shape>& p_shape, const Transform& p_transform) {
|
||||
|
||||
ShapeData sdata;
|
||||
sdata.shape=p_shape;
|
||||
sdata.xform=p_transform;
|
||||
shapes.push_back(sdata);
|
||||
_update_shapes();
|
||||
|
||||
}
|
||||
int CollisionObject::get_shape_count() const {
|
||||
|
||||
return shapes.size();
|
||||
|
||||
}
|
||||
void CollisionObject::set_shape(int p_shape_idx, const Ref<Shape>& p_shape) {
|
||||
|
||||
ERR_FAIL_INDEX(p_shape_idx,shapes.size());
|
||||
shapes[p_shape_idx].shape=p_shape;
|
||||
_update_shapes();
|
||||
}
|
||||
|
||||
void CollisionObject::set_shape_transform(int p_shape_idx, const Transform& p_transform) {
|
||||
|
||||
ERR_FAIL_INDEX(p_shape_idx,shapes.size());
|
||||
shapes[p_shape_idx].xform=p_transform;
|
||||
|
||||
_update_shapes();
|
||||
}
|
||||
|
||||
Ref<Shape> CollisionObject::get_shape(int p_shape_idx) const {
|
||||
|
||||
ERR_FAIL_INDEX_V(p_shape_idx,shapes.size(),Ref<Shape>());
|
||||
return shapes[p_shape_idx].shape;
|
||||
|
||||
}
|
||||
Transform CollisionObject::get_shape_transform(int p_shape_idx) const {
|
||||
|
||||
ERR_FAIL_INDEX_V(p_shape_idx,shapes.size(),Transform());
|
||||
return shapes[p_shape_idx].xform;
|
||||
|
||||
}
|
||||
void CollisionObject::remove_shape(int p_shape_idx) {
|
||||
|
||||
ERR_FAIL_INDEX(p_shape_idx,shapes.size());
|
||||
shapes.remove(p_shape_idx);
|
||||
|
||||
_update_shapes();
|
||||
}
|
||||
|
||||
void CollisionObject::clear_shapes() {
|
||||
|
||||
shapes.clear();
|
||||
|
||||
_update_shapes();
|
||||
}
|
||||
|
||||
void CollisionObject::set_shape_as_trigger(int p_shape_idx, bool p_trigger) {
|
||||
|
||||
ERR_FAIL_INDEX(p_shape_idx,shapes.size());
|
||||
shapes[p_shape_idx].trigger=p_trigger;
|
||||
if (!area && rid.is_valid()) {
|
||||
|
||||
PhysicsServer::get_singleton()->body_set_shape_as_trigger(rid,p_shape_idx,p_trigger);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool CollisionObject::is_shape_set_as_trigger(int p_shape_idx) const {
|
||||
|
||||
ERR_FAIL_INDEX_V(p_shape_idx,shapes.size(),false);
|
||||
return shapes[p_shape_idx].trigger;
|
||||
}
|
||||
|
||||
CollisionObject::CollisionObject(RID p_rid, bool p_area) {
|
||||
|
||||
rid=p_rid;
|
||||
area=p_area;
|
||||
if (p_area) {
|
||||
PhysicsServer::get_singleton()->area_attach_object_instance_ID(rid,get_instance_ID());
|
||||
} else {
|
||||
PhysicsServer::get_singleton()->body_attach_object_instance_ID(rid,get_instance_ID());
|
||||
}
|
||||
// set_transform_notify(true);
|
||||
|
||||
}
|
||||
|
||||
|
||||
CollisionObject::CollisionObject() {
|
||||
|
||||
|
||||
//owner=
|
||||
|
||||
//set_transform_notify(true);
|
||||
}
|
||||
|
||||
CollisionObject::~CollisionObject() {
|
||||
|
||||
PhysicsServer::get_singleton()->free(rid);
|
||||
}
|
||||
90
scene/3d/collision_object.h
Normal file
90
scene/3d/collision_object.h
Normal file
@ -0,0 +1,90 @@
|
||||
/*************************************************************************/
|
||||
/* collision_object.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef COLLISION_OBJECT_H
|
||||
#define COLLISION_OBJECT_H
|
||||
|
||||
#include "scene/3d/spatial.h"
|
||||
#include "scene/resources/shape.h"
|
||||
|
||||
class CollisionObject : public Spatial {
|
||||
|
||||
OBJ_TYPE( CollisionObject, Spatial );
|
||||
|
||||
bool area;
|
||||
RID rid;
|
||||
|
||||
struct ShapeData {
|
||||
Transform xform;
|
||||
Ref<Shape> shape;
|
||||
bool trigger;
|
||||
|
||||
ShapeData() {
|
||||
trigger=false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
Vector<ShapeData> shapes;
|
||||
|
||||
void _update_shapes();
|
||||
|
||||
friend class CollisionShape;
|
||||
friend class CollisionPolygon;
|
||||
void _update_shapes_from_children();
|
||||
protected:
|
||||
|
||||
CollisionObject(RID p_rid, bool p_area);
|
||||
|
||||
void _notification(int p_what);
|
||||
bool _set(const StringName& p_name, const Variant& p_value);
|
||||
bool _get(const StringName& p_name,Variant &r_ret) const;
|
||||
void _get_property_list( List<PropertyInfo> *p_list) const;
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
|
||||
void add_shape(const Ref<Shape>& p_shape, const Transform& p_transform=Transform());
|
||||
int get_shape_count() const;
|
||||
void set_shape(int p_shape_idx, const Ref<Shape>& p_shape);
|
||||
void set_shape_transform(int p_shape_idx, const Transform& p_transform);
|
||||
Ref<Shape> get_shape(int p_shape_idx) const;
|
||||
Transform get_shape_transform(int p_shape_idx) const;
|
||||
void remove_shape(int p_shape_idx);
|
||||
void clear_shapes();
|
||||
void set_shape_as_trigger(int p_shape_idx, bool p_trigger);
|
||||
bool is_shape_set_as_trigger(int p_shape_idx) const;
|
||||
|
||||
_FORCE_INLINE_ RID get_rid() const { return rid; }
|
||||
|
||||
CollisionObject();
|
||||
~CollisionObject();
|
||||
};
|
||||
|
||||
#endif // COLLISION_OBJECT__H
|
||||
85
scene/3d/editable_shape.cpp
Normal file
85
scene/3d/editable_shape.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
/*************************************************************************/
|
||||
/* editable_shape.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "editable_shape.h"
|
||||
|
||||
|
||||
void EditableShape::_notification(int p_what) {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void EditableShape::set_bsp_tree(const BSP_Tree& p_bsp) {
|
||||
|
||||
bsp=p_bsp;
|
||||
}
|
||||
|
||||
void EditableShape::set_shape(const Ref<Shape>& p_shape) {
|
||||
|
||||
shape=p_shape;
|
||||
}
|
||||
|
||||
|
||||
|
||||
EditableShape::EditableShape()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////////
|
||||
|
||||
|
||||
void EditableSphere::set_radius(float p_radius) {
|
||||
|
||||
radius=p_radius;
|
||||
update_gizmo();
|
||||
_change_notify("params/radius");
|
||||
}
|
||||
|
||||
|
||||
float EditableSphere::get_radius() const{
|
||||
|
||||
return radius;
|
||||
}
|
||||
|
||||
|
||||
void EditableSphere::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_radius","radius"),&EditableSphere::set_radius);
|
||||
ObjectTypeDB::bind_method(_MD("get_radius"),&EditableSphere::get_radius);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"params/radius",PROPERTY_HINT_EXP_RANGE,"0.001,16384,0.001"),_SCS("set_radius"),_SCS("get_radius"));
|
||||
}
|
||||
|
||||
EditableSphere::EditableSphere() {
|
||||
|
||||
radius=1.0;
|
||||
}
|
||||
73
scene/3d/editable_shape.h
Normal file
73
scene/3d/editable_shape.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*************************************************************************/
|
||||
/* editable_shape.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef EDITABLE_SHAPE_H
|
||||
#define EDITABLE_SHAPE_H
|
||||
|
||||
#include "scene/3d/spatial.h"
|
||||
#include "scene/resources/shape.h"
|
||||
|
||||
class EditableShape : public Spatial {
|
||||
|
||||
OBJ_TYPE(EditableShape,Spatial);
|
||||
|
||||
//can hold either of those
|
||||
BSP_Tree bsp;
|
||||
Ref<Shape> shape;
|
||||
|
||||
void _update_parent();
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
|
||||
void set_bsp_tree(const BSP_Tree& p_bsp);
|
||||
void set_shape(const Ref<Shape>& p_shape);
|
||||
public:
|
||||
EditableShape();
|
||||
};
|
||||
|
||||
|
||||
class EditableSphere : public EditableShape {
|
||||
|
||||
OBJ_TYPE( EditableSphere, EditableShape );
|
||||
|
||||
|
||||
float radius;
|
||||
protected:
|
||||
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_radius(float p_radius);
|
||||
float get_radius() const;
|
||||
|
||||
EditableSphere();
|
||||
};
|
||||
|
||||
|
||||
#endif // EDITABLE_SHAPE_H
|
||||
778
scene/3d/follow_camera.cpp
Normal file
778
scene/3d/follow_camera.cpp
Normal file
@ -0,0 +1,778 @@
|
||||
/*************************************************************************/
|
||||
/* follow_camera.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "follow_camera.h"
|
||||
|
||||
|
||||
#include "physics_body.h"
|
||||
#include "scene/resources/surface_tool.h"
|
||||
|
||||
void FollowCamera::_set_initial_orbit(const Vector2& p_orbit) {
|
||||
|
||||
initial_orbit=p_orbit;
|
||||
set_orbit(p_orbit);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FollowCamera::_clear_queries() {
|
||||
|
||||
if (!queries_active)
|
||||
return;
|
||||
#if 0
|
||||
for(int i=0;i<3;i++)
|
||||
PhysicsServer::get_singleton()->query_clear(clip_ray[i].query);
|
||||
#endif
|
||||
queries_active=false;
|
||||
|
||||
}
|
||||
|
||||
void FollowCamera::_compute_camera() {
|
||||
|
||||
// update the transform with the next proposed transform (camera is 1 logic frame delayed)
|
||||
|
||||
/*
|
||||
float time = get_root_node()->get_frame_time();
|
||||
Vector3 oldp = accepted.get_origin();
|
||||
Vector3 newp = proposed.get_origin();
|
||||
|
||||
float frame_dist = time *
|
||||
if (oldp.distance_to(newp) >
|
||||
*/
|
||||
|
||||
float time = get_process_delta_time();
|
||||
bool noblend=false;
|
||||
|
||||
if (clip) {
|
||||
|
||||
if ((clip_ray[0].clipped==clip_ray[2].clipped || fullclip) && clip_ray[1].clipped) {
|
||||
//all have been clipped
|
||||
proposed_pos=clip_ray[1].clip_pos-extraclip*(proposed_pos-target_pos).normalized();
|
||||
if (clip_ray[0].clipped)
|
||||
fullclip=true;
|
||||
noblend=true;
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
//Vector3 rel=follow_pos-target_pos;
|
||||
|
||||
if (clip_ray[0].clipped && !clip_ray[2].clipped) {
|
||||
|
||||
float distance = target_pos.distance_to(clip_ray[0].clip_pos);
|
||||
real_t amount = 1.0-(distance/clip_len);
|
||||
amount = CLAMP(amount,0,1)*autoturn_speed*time;
|
||||
if (clip_ray[1].clipped)
|
||||
amount*=2.0;
|
||||
//rotate_rel=Matrix3(Vector3(0,1,0),amount).xform(rel);
|
||||
rotate_orbit(Vector2(0,amount));
|
||||
|
||||
} else if (clip_ray[2].clipped && !clip_ray[0].clipped) {
|
||||
|
||||
float distance = target_pos.distance_to(clip_ray[2].clip_pos);
|
||||
real_t amount = 1.0-(distance/clip_len);
|
||||
amount = CLAMP(amount,0,1)*autoturn_speed*time;
|
||||
if (clip_ray[1].clipped)
|
||||
amount*=2.0;
|
||||
rotate_orbit(Vector2(0,-amount));
|
||||
}
|
||||
|
||||
fullclip=false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vector3 base_pos = get_global_transform().origin;
|
||||
Vector3 pull_from = base_pos;
|
||||
pull_from.y+=height; // height compensate
|
||||
|
||||
|
||||
|
||||
Vector3 camera_target;
|
||||
if (use_lookat_target) {
|
||||
|
||||
camera_target = lookat_target;
|
||||
} else {
|
||||
camera_target = base_pos;
|
||||
};
|
||||
|
||||
Transform proposed;
|
||||
proposed.set_look_at(proposed_pos,camera_target,up_vector);
|
||||
proposed = proposed * Transform(Matrix3(Vector3(1,0,0),Math::deg2rad(inclination)),Vector3()); //inclination
|
||||
|
||||
|
||||
accepted=proposed;
|
||||
if (smooth && !noblend) {
|
||||
|
||||
|
||||
Vector3 vec1 = accepted.origin;
|
||||
Vector3 vec2 = final.origin;
|
||||
final.origin = vec2.linear_interpolate(vec1, MIN(1,smooth_pos_ratio * time));;
|
||||
|
||||
Quat q1 = accepted.basis;
|
||||
Quat q2 = final.basis;
|
||||
final.basis = q2.slerp(q1, MIN(1,smooth_rot_ratio * time));
|
||||
|
||||
} else {
|
||||
final=accepted;
|
||||
}
|
||||
|
||||
_update_camera();
|
||||
|
||||
// calculate the next proposed transform
|
||||
|
||||
|
||||
Vector3 new_pos;
|
||||
|
||||
{ /*follow code*/
|
||||
|
||||
|
||||
|
||||
/* calculate some variables */
|
||||
|
||||
Vector3 rel = follow_pos - pull_from;
|
||||
|
||||
float l = rel.length();
|
||||
Vector3 rel_n = (l > 0) ? (rel/l) : Vector3();
|
||||
float ang = Math::acos(rel_n.dot( Vector3(0,1,0) ));
|
||||
|
||||
Vector3 tangent = rel_n;
|
||||
tangent.y=0; // get rid of y
|
||||
if (tangent.length_squared() < CMP_EPSILON2)
|
||||
tangent=Vector3(0,0,1); // use Z as tangent if rel is parallel to y
|
||||
else
|
||||
tangent.normalize();
|
||||
|
||||
/* now start applying the rules */
|
||||
|
||||
//clip distance
|
||||
if (l > max_distance)
|
||||
l=max_distance;
|
||||
if (l < min_distance)
|
||||
l=min_distance;
|
||||
|
||||
//fix angle
|
||||
|
||||
float ang_min = Math_PI * 0.5 + Math::deg2rad(min_orbit_x);
|
||||
float ang_max = Math_PI * 0.5 + Math::deg2rad(max_orbit_x);
|
||||
|
||||
if (ang<ang_min)
|
||||
ang=ang_min;
|
||||
if (ang>ang_max)
|
||||
ang=ang_max;
|
||||
|
||||
/* finally, rebuild the validated camera position */
|
||||
|
||||
new_pos=Vector3(0,Math::cos(ang),0);
|
||||
new_pos+=tangent*Math::sin(ang);
|
||||
new_pos*=l;
|
||||
new_pos+=pull_from;
|
||||
follow_pos=new_pos;
|
||||
|
||||
}
|
||||
|
||||
proposed_pos=new_pos;
|
||||
|
||||
Vector3 rel = new_pos-camera_target;
|
||||
|
||||
|
||||
if (clip) {
|
||||
|
||||
Vector<RID> exclude;
|
||||
exclude.push_back(target_body);
|
||||
|
||||
for(int i=0;i<3;i++) {
|
||||
|
||||
clip_ray[i].clipped=false;
|
||||
clip_ray[i].clip_pos=Vector3();
|
||||
clip_ray[i].cast_pos=camera_target;
|
||||
|
||||
Vector3 cast_to = camera_target+Matrix3(Vector3(0,1,0),Math::deg2rad(autoturn_tolerance*(i-1.0))).xform(rel);
|
||||
|
||||
|
||||
if (i!=1) {
|
||||
|
||||
Vector3 side = rel.cross(Vector3(0,1,0)).normalized()*(i-1.0);
|
||||
clip_ray[i].cast_pos+side*target_width+rel.normalized()*target_width;
|
||||
|
||||
Vector3 d = -rel;
|
||||
d.rotate(Vector3(0,1,0),Math::deg2rad(get_fov())*(i-1.0));
|
||||
Plane p(new_pos,new_pos+d,new_pos+Vector3(0,1,0)); //fov clipping plane, build a face and use it as plane, facing doesn't matter
|
||||
Vector3 intersect;
|
||||
if (p.intersects_segment(clip_ray[i].cast_pos,cast_to,&intersect))
|
||||
cast_to=intersect;
|
||||
|
||||
} else {
|
||||
|
||||
cast_to+=rel.normalized()*extraclip;
|
||||
}
|
||||
|
||||
// PhysicsServer::get_singleton()->query_intersection(clip_ray[i].query,get_world()->get_space(),exclude);
|
||||
// PhysicsServer::get_singleton()->query_intersection_segment(clip_ray[i].query,clip_ray[i].cast_pos,cast_to);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
queries_active=true;
|
||||
} else {
|
||||
|
||||
_clear_queries();
|
||||
}
|
||||
target_pos=camera_target;
|
||||
clip_len=rel.length();
|
||||
|
||||
}
|
||||
|
||||
void FollowCamera::set_use_lookat_target(bool p_use, const Vector3 &p_lookat) {
|
||||
|
||||
use_lookat_target = p_use;
|
||||
lookat_target = p_lookat;
|
||||
};
|
||||
|
||||
|
||||
void FollowCamera::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_PROCESS: {
|
||||
|
||||
|
||||
_compute_camera();
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_ENTER_WORLD: {
|
||||
|
||||
set_orbit(orbit);
|
||||
set_distance(distance);
|
||||
|
||||
accepted=final=get_global_transform();
|
||||
proposed_pos=accepted.origin;
|
||||
|
||||
target_body = RID();
|
||||
/*
|
||||
Node* parent = get_parent();
|
||||
while (parent) {
|
||||
PhysicsBody* p = parent->cast_to<PhysicsBody>();
|
||||
if (p) {
|
||||
target_body = p->get_body();
|
||||
break;
|
||||
};
|
||||
parent = parent->get_parent();
|
||||
};
|
||||
*/
|
||||
set_process(true);
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_WORLD: {
|
||||
|
||||
distance=get_distance();
|
||||
orbit=get_orbit();
|
||||
_clear_queries();
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_BECAME_CURRENT: {
|
||||
|
||||
set_process(true);
|
||||
} break;
|
||||
case NOTIFICATION_LOST_CURRENT: {
|
||||
|
||||
set_process(false);
|
||||
_clear_queries();
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FollowCamera::set_orbit(const Vector2& p_orbit) {
|
||||
|
||||
orbit=p_orbit;
|
||||
|
||||
if(is_inside_scene()) {
|
||||
|
||||
Vector3 char_pos = get_global_transform().origin;
|
||||
char_pos.y+=height;
|
||||
float d = char_pos.distance_to(follow_pos);
|
||||
|
||||
Matrix3 m;
|
||||
m.rotate(Vector3(0,1,0),orbit.y);
|
||||
m.rotate(Vector3(1,0,0),orbit.x);
|
||||
|
||||
follow_pos=char_pos + m.get_axis(2) * d;
|
||||
|
||||
}
|
||||
|
||||
update_gizmo();
|
||||
|
||||
}
|
||||
void FollowCamera::set_orbit_x(float p_x) {
|
||||
|
||||
orbit.x=p_x;
|
||||
if(is_inside_scene())
|
||||
set_orbit(Vector2( p_x, get_orbit().y ));
|
||||
}
|
||||
void FollowCamera::set_orbit_y(float p_y) {
|
||||
|
||||
|
||||
orbit.y=p_y;
|
||||
if(is_inside_scene())
|
||||
set_orbit(Vector2( get_orbit().x, p_y ));
|
||||
|
||||
}
|
||||
Vector2 FollowCamera::get_orbit() const {
|
||||
|
||||
|
||||
if (is_inside_scene()) {
|
||||
|
||||
Vector3 char_pos = get_global_transform().origin;
|
||||
char_pos.y+=height;
|
||||
Vector3 rel = (follow_pos - char_pos).normalized();
|
||||
Vector2 ret_orbit;
|
||||
ret_orbit.x = Math::acos( Vector3(0,1,0).dot( rel ) ) - Math_PI * 0.5;
|
||||
ret_orbit.y = Math::atan2(rel.x,rel.z);
|
||||
return ret_orbit;
|
||||
}
|
||||
return orbit;
|
||||
}
|
||||
|
||||
void FollowCamera::rotate_orbit(const Vector2& p_relative) {
|
||||
|
||||
if (is_inside_scene()) {
|
||||
|
||||
Matrix3 m;
|
||||
m.rotate(Vector3(0,1,0),Math::deg2rad(p_relative.y));
|
||||
m.rotate(Vector3(1,0,0),Math::deg2rad(p_relative.x));
|
||||
|
||||
Vector3 char_pos = get_global_transform().origin;
|
||||
char_pos.y+=height;
|
||||
Vector3 rel = (follow_pos - char_pos);
|
||||
rel = m.xform(rel);
|
||||
follow_pos=char_pos+rel;
|
||||
|
||||
}
|
||||
|
||||
orbit+=p_relative;
|
||||
update_gizmo();
|
||||
}
|
||||
|
||||
void FollowCamera::set_height(float p_height) {
|
||||
|
||||
|
||||
height=p_height;
|
||||
update_gizmo();
|
||||
}
|
||||
|
||||
float FollowCamera::get_height() const {
|
||||
|
||||
return height;
|
||||
|
||||
}
|
||||
|
||||
void FollowCamera::set_max_orbit_x(float p_max) {
|
||||
|
||||
max_orbit_x=p_max;
|
||||
update_gizmo();
|
||||
}
|
||||
|
||||
float FollowCamera::get_max_orbit_x() const {
|
||||
|
||||
return max_orbit_x;
|
||||
}
|
||||
|
||||
void FollowCamera::set_min_orbit_x(float p_min) {
|
||||
|
||||
min_orbit_x=p_min;
|
||||
update_gizmo();
|
||||
}
|
||||
|
||||
float FollowCamera::get_min_orbit_x() const {
|
||||
|
||||
return min_orbit_x;
|
||||
}
|
||||
|
||||
float FollowCamera::get_min_distance() const {
|
||||
|
||||
return min_distance;
|
||||
}
|
||||
float FollowCamera::get_max_distance() const {
|
||||
|
||||
return max_distance;
|
||||
}
|
||||
|
||||
void FollowCamera::set_min_distance(float p_min) {
|
||||
|
||||
min_distance=p_min;
|
||||
update_gizmo();
|
||||
}
|
||||
|
||||
void FollowCamera::set_max_distance(float p_max) {
|
||||
|
||||
max_distance = p_max;
|
||||
update_gizmo();
|
||||
}
|
||||
|
||||
|
||||
void FollowCamera::set_distance(float p_distance) {
|
||||
|
||||
if (is_inside_scene()) {
|
||||
|
||||
Vector3 char_pos = get_global_transform().origin;
|
||||
char_pos.y+=height;
|
||||
Vector3 rel = (follow_pos - char_pos).normalized();
|
||||
rel*=p_distance;
|
||||
follow_pos=char_pos+rel;
|
||||
|
||||
}
|
||||
|
||||
distance=p_distance;
|
||||
}
|
||||
|
||||
float FollowCamera::get_distance() const {
|
||||
|
||||
if (is_inside_scene()) {
|
||||
|
||||
Vector3 char_pos = get_global_transform().origin;
|
||||
char_pos.y+=height;
|
||||
return (follow_pos - char_pos).length();
|
||||
|
||||
}
|
||||
|
||||
return distance;
|
||||
}
|
||||
|
||||
void FollowCamera::set_clip(bool p_enabled) {
|
||||
|
||||
|
||||
clip=p_enabled;
|
||||
|
||||
if (!p_enabled)
|
||||
_clear_queries();
|
||||
}
|
||||
|
||||
bool FollowCamera::has_clip() const {
|
||||
|
||||
return clip;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void FollowCamera::set_autoturn(bool p_enabled) {
|
||||
|
||||
|
||||
autoturn=p_enabled;
|
||||
}
|
||||
|
||||
bool FollowCamera::has_autoturn() const {
|
||||
|
||||
return autoturn;
|
||||
|
||||
}
|
||||
|
||||
void FollowCamera::set_autoturn_tolerance(float p_degrees) {
|
||||
|
||||
|
||||
autoturn_tolerance=p_degrees;
|
||||
}
|
||||
float FollowCamera::get_autoturn_tolerance() const {
|
||||
|
||||
|
||||
return autoturn_tolerance;
|
||||
}
|
||||
|
||||
void FollowCamera::set_inclination(float p_degrees) {
|
||||
|
||||
|
||||
inclination=p_degrees;
|
||||
}
|
||||
float FollowCamera::get_inclination() const {
|
||||
|
||||
|
||||
return inclination;
|
||||
}
|
||||
|
||||
|
||||
void FollowCamera::set_autoturn_speed(float p_speed) {
|
||||
|
||||
|
||||
autoturn_speed=p_speed;
|
||||
}
|
||||
|
||||
float FollowCamera::get_autoturn_speed() const {
|
||||
|
||||
return autoturn_speed;
|
||||
|
||||
}
|
||||
|
||||
|
||||
RES FollowCamera::_get_gizmo_geometry() const {
|
||||
|
||||
Ref<SurfaceTool> surface_tool( memnew( SurfaceTool ));
|
||||
|
||||
Ref<FixedMaterial> mat( memnew( FixedMaterial ));
|
||||
|
||||
mat->set_parameter( FixedMaterial::PARAM_DIFFUSE,Color(1.0,0.5,1.0,0.3) );
|
||||
mat->set_line_width(4);
|
||||
mat->set_flag(Material::FLAG_DOUBLE_SIDED,true);
|
||||
mat->set_flag(Material::FLAG_UNSHADED,true);
|
||||
mat->set_hint(Material::HINT_NO_DEPTH_DRAW,true);
|
||||
|
||||
surface_tool->begin(Mesh::PRIMITIVE_LINES);
|
||||
surface_tool->set_material(mat);
|
||||
|
||||
|
||||
int steps=16;
|
||||
|
||||
Vector3 base_up = Matrix3(Vector3(1,0,0),Math::deg2rad(max_orbit_x)).get_axis(2);
|
||||
Vector3 base_down = Matrix3(Vector3(1,0,0),Math::deg2rad(min_orbit_x)).get_axis(2);
|
||||
|
||||
Vector3 ofs(0,height,0);
|
||||
|
||||
for(int i=0;i<steps;i++) {
|
||||
|
||||
|
||||
Matrix3 rot(Vector3(0,1,0),Math_PI*2*float(i)/steps);
|
||||
Matrix3 rot2(Vector3(0,1,0),Math_PI*2*float(i+1)/steps);
|
||||
|
||||
Vector3 up = rot.xform(base_up);
|
||||
Vector3 up2 = rot2.xform(base_up);
|
||||
|
||||
Vector3 down = rot.xform(base_down);
|
||||
Vector3 down2 = rot2.xform(base_down);
|
||||
|
||||
surface_tool->add_vertex(ofs+up*min_distance);
|
||||
surface_tool->add_vertex(ofs+up*max_distance);
|
||||
surface_tool->add_vertex(ofs+up*min_distance);
|
||||
surface_tool->add_vertex(ofs+up2*min_distance);
|
||||
surface_tool->add_vertex(ofs+up*max_distance);
|
||||
surface_tool->add_vertex(ofs+up2*max_distance);
|
||||
|
||||
surface_tool->add_vertex(ofs+down*min_distance);
|
||||
surface_tool->add_vertex(ofs+down*max_distance);
|
||||
surface_tool->add_vertex(ofs+down*min_distance);
|
||||
surface_tool->add_vertex(ofs+down2*min_distance);
|
||||
surface_tool->add_vertex(ofs+down*max_distance);
|
||||
surface_tool->add_vertex(ofs+down2*max_distance);
|
||||
|
||||
int substeps = 8;
|
||||
|
||||
for(int j=0;j<substeps;j++) {
|
||||
|
||||
Vector3 a = up.linear_interpolate(down,float(j)/substeps).normalized()*max_distance;
|
||||
Vector3 b = up.linear_interpolate(down,float(j+1)/substeps).normalized()*max_distance;
|
||||
Vector3 am = up.linear_interpolate(down,float(j)/substeps).normalized()*min_distance;
|
||||
Vector3 bm = up.linear_interpolate(down,float(j+1)/substeps).normalized()*min_distance;
|
||||
|
||||
surface_tool->add_vertex(ofs+a);
|
||||
surface_tool->add_vertex(ofs+b);
|
||||
surface_tool->add_vertex(ofs+am);
|
||||
surface_tool->add_vertex(ofs+bm);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return surface_tool->commit();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void FollowCamera::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_set_initial_orbit","orbit"),&FollowCamera::_set_initial_orbit);
|
||||
ObjectTypeDB::bind_method(_MD("set_orbit","orbit"),&FollowCamera::set_orbit);
|
||||
ObjectTypeDB::bind_method(_MD("get_orbit"),&FollowCamera::get_orbit);
|
||||
ObjectTypeDB::bind_method(_MD("set_orbit_x","x"),&FollowCamera::set_orbit_x);
|
||||
ObjectTypeDB::bind_method(_MD("set_orbit_y","y"),&FollowCamera::set_orbit_y);
|
||||
ObjectTypeDB::bind_method(_MD("set_min_orbit_x","x"),&FollowCamera::set_min_orbit_x);
|
||||
ObjectTypeDB::bind_method(_MD("get_min_orbit_x"),&FollowCamera::get_min_orbit_x);
|
||||
ObjectTypeDB::bind_method(_MD("set_max_orbit_x","x"),&FollowCamera::set_max_orbit_x);
|
||||
ObjectTypeDB::bind_method(_MD("get_max_orbit_x"),&FollowCamera::get_max_orbit_x);
|
||||
ObjectTypeDB::bind_method(_MD("set_height","height"),&FollowCamera::set_height);
|
||||
ObjectTypeDB::bind_method(_MD("get_height"),&FollowCamera::get_height);
|
||||
ObjectTypeDB::bind_method(_MD("set_inclination","inclination"),&FollowCamera::set_inclination);
|
||||
ObjectTypeDB::bind_method(_MD("get_inclination"),&FollowCamera::get_inclination);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("rotate_orbit"),&FollowCamera::rotate_orbit);
|
||||
ObjectTypeDB::bind_method(_MD("set_distance","distance"),&FollowCamera::set_distance);
|
||||
ObjectTypeDB::bind_method(_MD("get_distance"),&FollowCamera::get_distance);
|
||||
ObjectTypeDB::bind_method(_MD("set_max_distance","max_distance"),&FollowCamera::set_max_distance);
|
||||
ObjectTypeDB::bind_method(_MD("get_max_distance"),&FollowCamera::get_max_distance);
|
||||
ObjectTypeDB::bind_method(_MD("set_min_distance","min_distance"),&FollowCamera::set_min_distance);
|
||||
ObjectTypeDB::bind_method(_MD("get_min_distance"),&FollowCamera::get_min_distance);
|
||||
ObjectTypeDB::bind_method(_MD("set_clip","enable"),&FollowCamera::set_clip);
|
||||
ObjectTypeDB::bind_method(_MD("has_clip"),&FollowCamera::has_clip);
|
||||
ObjectTypeDB::bind_method(_MD("set_autoturn","enable"),&FollowCamera::set_autoturn);
|
||||
ObjectTypeDB::bind_method(_MD("has_autoturn"),&FollowCamera::has_autoturn);
|
||||
ObjectTypeDB::bind_method(_MD("set_autoturn_tolerance","degrees"),&FollowCamera::set_autoturn_tolerance);
|
||||
ObjectTypeDB::bind_method(_MD("get_autoturn_tolerance"),&FollowCamera::get_autoturn_tolerance);
|
||||
ObjectTypeDB::bind_method(_MD("set_autoturn_speed","speed"),&FollowCamera::set_autoturn_speed);
|
||||
ObjectTypeDB::bind_method(_MD("get_autoturn_speed"),&FollowCamera::get_autoturn_speed);
|
||||
ObjectTypeDB::bind_method(_MD("set_smoothing","enable"),&FollowCamera::set_smoothing);
|
||||
ObjectTypeDB::bind_method(_MD("has_smoothing"),&FollowCamera::has_smoothing);
|
||||
ObjectTypeDB::bind_method(_MD("set_rotation_smoothing","amount"),&FollowCamera::set_rotation_smoothing);
|
||||
ObjectTypeDB::bind_method(_MD("get_rotation_smoothing"),&FollowCamera::get_rotation_smoothing);
|
||||
ObjectTypeDB::bind_method(_MD("set_translation_smoothing","amount"),&FollowCamera::set_translation_smoothing);
|
||||
ObjectTypeDB::bind_method(_MD("get_translation_smoothing"),&FollowCamera::get_translation_smoothing);
|
||||
ObjectTypeDB::bind_method(_MD("set_use_lookat_target","use","lookat"),&FollowCamera::set_use_lookat_target, DEFVAL(Vector3()));
|
||||
ObjectTypeDB::bind_method(_MD("set_up_vector","vector"),&FollowCamera::set_up_vector);
|
||||
ObjectTypeDB::bind_method(_MD("get_up_vector"),&FollowCamera::get_up_vector);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_ray_collision"),&FollowCamera::_ray_collision);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo( Variant::VECTOR2, "orbit" ), _SCS("_set_initial_orbit"),_SCS("get_orbit") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "height", PROPERTY_HINT_RANGE,"-1024,1024,0.01" ), _SCS("set_height"), _SCS("get_height") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "inclination", PROPERTY_HINT_RANGE,"-90,90,0.01" ), _SCS("set_inclination"), _SCS("get_inclination") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "max_orbit_x", PROPERTY_HINT_RANGE,"-90,90,0.01" ), _SCS("set_max_orbit_x"), _SCS("get_max_orbit_x") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "min_orbit_x", PROPERTY_HINT_RANGE,"-90,90,0.01" ), _SCS("set_min_orbit_x"), _SCS("get_min_orbit_x") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "min_distance", PROPERTY_HINT_RANGE,"0,100,0.01" ), _SCS("set_min_distance"), _SCS("get_min_distance") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "max_distance", PROPERTY_HINT_RANGE,"0,100,0.01" ), _SCS("set_max_distance"), _SCS("get_max_distance") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "distance", PROPERTY_HINT_RANGE,"0.01,1024,0,01"), _SCS("set_distance"), _SCS("get_distance") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "clip"), _SCS("set_clip"), _SCS("has_clip") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "autoturn"), _SCS("set_autoturn"), _SCS("has_autoturn") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "autoturn_tolerance", PROPERTY_HINT_RANGE,"1,90,0.01") , _SCS("set_autoturn_tolerance"), _SCS("get_autoturn_tolerance") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "autoturn_speed", PROPERTY_HINT_RANGE,"1,90,0.01"), _SCS("set_autoturn_speed"), _SCS("get_autoturn_speed") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "smoothing"), _SCS("set_smoothing"), _SCS("has_smoothing") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "translation_smooth", PROPERTY_HINT_RANGE,"0.01,128,0.01"), _SCS("set_translation_smoothing"), _SCS("get_translation_smoothing") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "rotation_smooth", PROPERTY_HINT_RANGE,"0.01,128,0.01"), _SCS("set_rotation_smoothing"), _SCS("get_rotation_smoothing") );
|
||||
|
||||
|
||||
}
|
||||
|
||||
void FollowCamera::_ray_collision(Vector3 p_point, Vector3 p_normal, int p_subindex, ObjectID p_against,int p_idx) {
|
||||
|
||||
clip_ray[p_idx].clip_pos=p_point;
|
||||
clip_ray[p_idx].clipped=true;
|
||||
|
||||
};
|
||||
|
||||
Transform FollowCamera::get_camera_transform() const {
|
||||
|
||||
return final;
|
||||
}
|
||||
|
||||
void FollowCamera::set_smoothing(bool p_enable) {
|
||||
|
||||
smooth=p_enable;
|
||||
}
|
||||
|
||||
bool FollowCamera::has_smoothing() const {
|
||||
|
||||
return smooth;
|
||||
}
|
||||
|
||||
void FollowCamera::set_translation_smoothing(float p_amount) {
|
||||
|
||||
smooth_pos_ratio=p_amount;
|
||||
}
|
||||
float FollowCamera::get_translation_smoothing() const {
|
||||
|
||||
return smooth_pos_ratio;
|
||||
}
|
||||
|
||||
void FollowCamera::set_rotation_smoothing(float p_amount) {
|
||||
|
||||
smooth_rot_ratio=p_amount;
|
||||
|
||||
}
|
||||
|
||||
void FollowCamera::set_up_vector(const Vector3& p_up) {
|
||||
|
||||
up_vector=p_up;
|
||||
}
|
||||
|
||||
Vector3 FollowCamera::get_up_vector() const{
|
||||
|
||||
return up_vector;
|
||||
}
|
||||
|
||||
float FollowCamera::get_rotation_smoothing() const {
|
||||
|
||||
return smooth_pos_ratio;
|
||||
|
||||
}
|
||||
|
||||
|
||||
FollowCamera::FollowCamera() {
|
||||
|
||||
|
||||
height=1;
|
||||
|
||||
orbit=Vector2(0,0);
|
||||
up_vector=Vector3(0,1,0);
|
||||
|
||||
distance=3;
|
||||
min_distance=2;
|
||||
max_distance=5;
|
||||
|
||||
autoturn=true;
|
||||
autoturn_tolerance=10;
|
||||
autoturn_speed=80;
|
||||
|
||||
min_orbit_x=-50;
|
||||
max_orbit_x=70;
|
||||
inclination=0;
|
||||
target_width=0.3;
|
||||
|
||||
clip=true;
|
||||
use_lookat_target = false;
|
||||
extraclip=0.3;
|
||||
fullclip=false;
|
||||
|
||||
smooth=true;
|
||||
smooth_rot_ratio=10;
|
||||
smooth_pos_ratio=10;
|
||||
|
||||
|
||||
for(int i=0;i<3;i++) {
|
||||
// clip_ray[i].query=PhysicsServer::get_singleton()->query_create(this, "_ray_collision", i, true);
|
||||
clip_ray[i].clipped=false;
|
||||
}
|
||||
|
||||
queries_active=false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
FollowCamera::~FollowCamera() {
|
||||
|
||||
for(int i=0;i<3;i++) {
|
||||
PhysicsServer::get_singleton()->free(clip_ray[i].query);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
180
scene/3d/follow_camera.h
Normal file
180
scene/3d/follow_camera.h
Normal file
@ -0,0 +1,180 @@
|
||||
/*************************************************************************/
|
||||
/* follow_camera.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef FOLLOW_CAMERA_H
|
||||
#define FOLLOW_CAMERA_H
|
||||
|
||||
#include "scene/3d/camera.h"
|
||||
|
||||
class FollowCamera : public Camera {
|
||||
|
||||
OBJ_TYPE( FollowCamera, Camera );
|
||||
|
||||
private:
|
||||
|
||||
|
||||
//used for follow
|
||||
Vector3 follow_pos;
|
||||
//used for fixed
|
||||
Vector2 initial_orbit;
|
||||
Vector2 orbit;
|
||||
float distance;
|
||||
|
||||
float height;
|
||||
float target_width;
|
||||
|
||||
float min_distance;
|
||||
float max_distance;
|
||||
|
||||
float max_orbit_x;
|
||||
float min_orbit_x;
|
||||
|
||||
float inclination;
|
||||
float extraclip;
|
||||
bool fullclip;
|
||||
|
||||
bool clip;
|
||||
bool autoturn;
|
||||
float autoturn_tolerance;
|
||||
float autoturn_speed;
|
||||
|
||||
bool smooth;
|
||||
float smooth_rot_ratio;
|
||||
float smooth_pos_ratio;
|
||||
|
||||
|
||||
|
||||
struct ClipRay {
|
||||
RID query;
|
||||
bool clipped;
|
||||
Vector3 cast_pos;
|
||||
Vector3 clip_pos;
|
||||
};
|
||||
|
||||
ClipRay clip_ray[3];
|
||||
Vector3 target_pos;
|
||||
float clip_len;
|
||||
|
||||
Vector3 up_vector;
|
||||
|
||||
|
||||
virtual RES _get_gizmo_geometry() const;
|
||||
|
||||
Transform ted;
|
||||
Vector3 proposed_pos;
|
||||
Transform accepted;
|
||||
Transform final;
|
||||
RID target_body;
|
||||
|
||||
bool use_lookat_target;
|
||||
Vector3 lookat_target;
|
||||
|
||||
void _compute_camera();
|
||||
|
||||
bool queries_active;
|
||||
void _clear_queries();
|
||||
|
||||
void _set_initial_orbit(const Vector2& p_orbit);
|
||||
|
||||
protected:
|
||||
|
||||
virtual void _request_camera_update() {} //ignore
|
||||
|
||||
void _notification(int p_what);
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
void _ray_collision(Vector3 p_point, Vector3 p_normal, int p_subindex, ObjectID p_against,int p_idx);
|
||||
|
||||
public:
|
||||
|
||||
|
||||
void set_orbit(const Vector2& p_orbit);
|
||||
void set_orbit_x(float p_x);
|
||||
void set_orbit_y(float p_y);
|
||||
Vector2 get_orbit() const;
|
||||
|
||||
void set_height(float p_height);
|
||||
float get_height() const;
|
||||
|
||||
void set_inclination(float p_degrees);
|
||||
float get_inclination() const;
|
||||
|
||||
void set_max_orbit_x(float p_max);
|
||||
float get_max_orbit_x() const;
|
||||
|
||||
void set_min_orbit_x(float p_min);
|
||||
float get_min_orbit_x() const;
|
||||
|
||||
void rotate_orbit(const Vector2& p_relative);
|
||||
|
||||
void set_distance(float p_distance);
|
||||
float get_distance() const;
|
||||
|
||||
float get_min_distance() const;
|
||||
float get_max_distance() const;
|
||||
void set_min_distance(float p_min);
|
||||
void set_max_distance(float p_max);
|
||||
|
||||
/** FINISH THIS AND CLEAN IT UP */
|
||||
|
||||
void set_clip(bool p_enabled);
|
||||
bool has_clip() const;
|
||||
|
||||
void set_autoturn(bool p_enabled);
|
||||
bool has_autoturn() const;
|
||||
|
||||
void set_autoturn_tolerance(float p_degrees);
|
||||
float get_autoturn_tolerance() const;
|
||||
|
||||
void set_autoturn_speed(float p_speed);
|
||||
float get_autoturn_speed() const;
|
||||
|
||||
void set_smoothing(bool p_enable);
|
||||
bool has_smoothing() const;
|
||||
|
||||
void set_translation_smoothing(float p_amount);
|
||||
float get_translation_smoothing() const;
|
||||
|
||||
void set_rotation_smoothing(float p_amount);
|
||||
float get_rotation_smoothing() const;
|
||||
|
||||
void set_use_lookat_target(bool p_use, const Vector3 &p_lookat = Vector3());
|
||||
|
||||
void set_up_vector(const Vector3& p_up);
|
||||
Vector3 get_up_vector() const;
|
||||
|
||||
virtual Transform get_camera_transform() const;
|
||||
|
||||
FollowCamera();
|
||||
~FollowCamera();
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // FOLLOW_CAMERA_H
|
||||
157
scene/3d/interpolated_camera.cpp
Normal file
157
scene/3d/interpolated_camera.cpp
Normal file
@ -0,0 +1,157 @@
|
||||
/*************************************************************************/
|
||||
/* interpolated_camera.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "interpolated_camera.h"
|
||||
|
||||
|
||||
void InterpolatedCamera::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
case NOTIFICATION_ENTER_SCENE: {
|
||||
|
||||
if (get_scene()->is_editor_hint() && enabled)
|
||||
set_fixed_process(false);
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_PROCESS: {
|
||||
|
||||
if (!enabled)
|
||||
break;
|
||||
if (has_node(target)) {
|
||||
|
||||
Spatial *node = get_node(target)->cast_to<Spatial>();
|
||||
if (!node)
|
||||
break;
|
||||
|
||||
float delta = speed*get_process_delta_time();
|
||||
Transform target_xform = node->get_global_transform();
|
||||
Transform local_transform = get_transform();
|
||||
local_transform = local_transform.interpolate_with(target_xform,delta);
|
||||
set_global_transform(local_transform);
|
||||
|
||||
if (node->cast_to<Camera>()) {
|
||||
Camera *cam = node->cast_to<Camera>();
|
||||
if (cam->get_projection()==get_projection()) {
|
||||
|
||||
float new_near = Math::lerp(get_znear(),cam->get_znear(),delta);
|
||||
float new_far = Math::lerp(get_zfar(),cam->get_zfar(),delta);
|
||||
|
||||
if (cam->get_projection()==PROJECTION_ORTHOGONAL) {
|
||||
|
||||
float size = Math::lerp(get_size(),cam->get_size(),delta);
|
||||
set_orthogonal(size,new_near,new_far);
|
||||
} else {
|
||||
|
||||
float fov = Math::lerp(get_fov(),cam->get_fov(),delta);
|
||||
set_perspective(fov,new_near,new_far);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void InterpolatedCamera::_set_target(const Object *p_target) {
|
||||
|
||||
ERR_FAIL_NULL(p_target);
|
||||
set_target(p_target->cast_to<Spatial>());
|
||||
}
|
||||
|
||||
void InterpolatedCamera::set_target(const Spatial *p_target) {
|
||||
|
||||
ERR_FAIL_NULL(p_target);
|
||||
target=get_path_to(p_target);
|
||||
}
|
||||
|
||||
|
||||
void InterpolatedCamera::set_target_path(const NodePath& p_path){
|
||||
|
||||
target=p_path;
|
||||
}
|
||||
|
||||
NodePath InterpolatedCamera::get_target_path() const{
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
void InterpolatedCamera::set_interpolation_enabled(bool p_enable) {
|
||||
|
||||
if (enabled==p_enable)
|
||||
return;
|
||||
enabled=p_enable;
|
||||
if (p_enable) {
|
||||
if (is_inside_scene() && get_scene()->is_editor_hint())
|
||||
return;
|
||||
set_process(true);
|
||||
} else
|
||||
set_process(false);
|
||||
}
|
||||
|
||||
bool InterpolatedCamera::is_interpolation_enabled() const {
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
void InterpolatedCamera::set_speed(real_t p_speed) {
|
||||
|
||||
speed=p_speed;
|
||||
}
|
||||
|
||||
real_t InterpolatedCamera::get_speed() const {
|
||||
|
||||
return speed;
|
||||
}
|
||||
|
||||
|
||||
void InterpolatedCamera::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_target_path","target_path"),&InterpolatedCamera::set_target_path);
|
||||
ObjectTypeDB::bind_method(_MD("get_target_path"),&InterpolatedCamera::get_target_path);
|
||||
ObjectTypeDB::bind_method(_MD("set_target","target"),&InterpolatedCamera::_set_target);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_speed","speed"),&InterpolatedCamera::set_speed);
|
||||
ObjectTypeDB::bind_method(_MD("get_speed"),&InterpolatedCamera::get_speed);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_interpolation_enabled","target_path"),&InterpolatedCamera::set_interpolation_enabled);
|
||||
ObjectTypeDB::bind_method(_MD("is_interpolation_enabled"),&InterpolatedCamera::is_interpolation_enabled);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::NODE_PATH,"target"), _SCS("set_target_path"), _SCS("get_target_path") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"speed"), _SCS("set_speed"), _SCS("get_speed") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enabled"), _SCS("set_interpolation_enabled"), _SCS("is_interpolation_enabled") );
|
||||
}
|
||||
|
||||
InterpolatedCamera::InterpolatedCamera() {
|
||||
|
||||
enabled=false;
|
||||
speed=1;
|
||||
|
||||
}
|
||||
63
scene/3d/interpolated_camera.h
Normal file
63
scene/3d/interpolated_camera.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*************************************************************************/
|
||||
/* interpolated_camera.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef INTERPOLATED_CAMERA_H
|
||||
#define INTERPOLATED_CAMERA_H
|
||||
|
||||
#include "scene/3d/camera.h"
|
||||
|
||||
class InterpolatedCamera : public Camera {
|
||||
|
||||
OBJ_TYPE(InterpolatedCamera,Camera);
|
||||
|
||||
bool enabled;
|
||||
real_t speed;
|
||||
NodePath target;
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
void _set_target(const Object *p_target);
|
||||
|
||||
public:
|
||||
|
||||
void set_target(const Spatial *p_target);
|
||||
void set_target_path(const NodePath& p_path);
|
||||
NodePath get_target_path() const;
|
||||
|
||||
void set_speed(real_t p_speed);
|
||||
real_t get_speed() const;
|
||||
|
||||
void set_interpolation_enabled(bool p_enable);
|
||||
bool is_interpolation_enabled() const;
|
||||
|
||||
|
||||
InterpolatedCamera();
|
||||
};
|
||||
|
||||
#endif // INTERPOLATED_CAMERA_H
|
||||
585
scene/3d/light.cpp
Normal file
585
scene/3d/light.cpp
Normal file
@ -0,0 +1,585 @@
|
||||
/*************************************************************************/
|
||||
/* light.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "light.h"
|
||||
|
||||
#include "globals.h"
|
||||
#include "scene/resources/surface_tool.h"
|
||||
|
||||
|
||||
static const char* _light_param_names[VS::LIGHT_PARAM_MAX]={
|
||||
"params/spot_attenuation",
|
||||
"params/spot_angle",
|
||||
"params/radius",
|
||||
"params/energy",
|
||||
"params/attenuation",
|
||||
"shadow/darkening",
|
||||
"shadow/z_offset",
|
||||
"shadow/z_slope_scale"
|
||||
};
|
||||
|
||||
void Light::set_parameter(Parameter p_param, float p_value) {
|
||||
|
||||
ERR_FAIL_INDEX(p_param, PARAM_MAX);
|
||||
vars[p_param]=p_value;
|
||||
VisualServer::get_singleton()->light_set_param(light,(VisualServer::LightParam)p_param,p_value);
|
||||
if (p_param==PARAM_RADIUS || p_param==PARAM_SPOT_ANGLE)
|
||||
update_gizmo();
|
||||
_change_notify(_light_param_names[p_param]);
|
||||
// _change_notify(_param_names[p_param]);
|
||||
}
|
||||
|
||||
float Light::get_parameter(Parameter p_param) const {
|
||||
|
||||
ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
|
||||
return vars[p_param];
|
||||
|
||||
}
|
||||
|
||||
void Light::set_color(LightColor p_color, const Color& p_value) {
|
||||
|
||||
ERR_FAIL_INDEX(p_color, 3);
|
||||
colors[p_color]=p_value;
|
||||
VisualServer::get_singleton()->light_set_color(light,(VisualServer::LightColor)p_color,p_value);
|
||||
//_change_notify(_color_names[p_color]);
|
||||
|
||||
}
|
||||
Color Light::get_color(LightColor p_color) const {
|
||||
|
||||
ERR_FAIL_INDEX_V(p_color, 3, Color());
|
||||
return colors[p_color];
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Light::set_project_shadows(bool p_enabled) {
|
||||
|
||||
shadows=p_enabled;
|
||||
VisualServer::get_singleton()->light_set_shadow(light, p_enabled);
|
||||
_change_notify("shadow");
|
||||
}
|
||||
bool Light::has_project_shadows() const {
|
||||
|
||||
return shadows;
|
||||
}
|
||||
|
||||
void Light::set_projector(const Ref<Texture>& p_projector) {
|
||||
|
||||
projector=p_projector;
|
||||
VisualServer::get_singleton()->light_set_projector(light, projector.is_null()?RID():projector->get_rid());
|
||||
}
|
||||
|
||||
Ref<Texture> Light::get_projector() const {
|
||||
|
||||
return projector;
|
||||
}
|
||||
|
||||
|
||||
bool Light::_can_gizmo_scale() const {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static void _make_sphere(int p_lats, int p_lons, float p_radius, Ref<SurfaceTool> p_tool) {
|
||||
|
||||
|
||||
p_tool->begin(Mesh::PRIMITIVE_TRIANGLES);
|
||||
|
||||
for(int i = 1; i <= p_lats; i++) {
|
||||
double lat0 = Math_PI * (-0.5 + (double) (i - 1) / p_lats);
|
||||
double z0 = Math::sin(lat0);
|
||||
double zr0 = Math::cos(lat0);
|
||||
|
||||
double lat1 = Math_PI * (-0.5 + (double) i / p_lats);
|
||||
double z1 = Math::sin(lat1);
|
||||
double zr1 = Math::cos(lat1);
|
||||
|
||||
for(int j = p_lons; j >= 1; j--) {
|
||||
|
||||
double lng0 = 2 * Math_PI * (double) (j - 1) / p_lons;
|
||||
double x0 = Math::cos(lng0);
|
||||
double y0 = Math::sin(lng0);
|
||||
|
||||
double lng1 = 2 * Math_PI * (double) (j) / p_lons;
|
||||
double x1 = Math::cos(lng1);
|
||||
double y1 = Math::sin(lng1);
|
||||
|
||||
|
||||
Vector3 v[4]={
|
||||
Vector3(x1 * zr0, z0, y1 *zr0),
|
||||
Vector3(x1 * zr1, z1, y1 *zr1),
|
||||
Vector3(x0 * zr1, z1, y0 *zr1),
|
||||
Vector3(x0 * zr0, z0, y0 *zr0)
|
||||
};
|
||||
|
||||
#define ADD_POINT(m_idx) \
|
||||
p_tool->add_normal(v[m_idx]);\
|
||||
p_tool->add_vertex(v[m_idx]*p_radius);
|
||||
|
||||
ADD_POINT(0);
|
||||
ADD_POINT(1);
|
||||
ADD_POINT(2);
|
||||
|
||||
ADD_POINT(2);
|
||||
ADD_POINT(3);
|
||||
ADD_POINT(0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RES Light::_get_gizmo_geometry() const {
|
||||
|
||||
|
||||
Ref<FixedMaterial> mat_area( memnew( FixedMaterial ));
|
||||
|
||||
mat_area->set_parameter( FixedMaterial::PARAM_DIFFUSE,Color(0.7,0.6,0.0,0.05) );
|
||||
mat_area->set_parameter( FixedMaterial::PARAM_EMISSION,Color(0.7,0.7,0.7) );
|
||||
mat_area->set_blend_mode( Material::BLEND_MODE_ADD );
|
||||
mat_area->set_flag(Material::FLAG_DOUBLE_SIDED,true);
|
||||
mat_area->set_hint(Material::HINT_NO_DEPTH_DRAW,true);
|
||||
|
||||
Ref<FixedMaterial> mat_light( memnew( FixedMaterial ));
|
||||
|
||||
mat_light->set_parameter( FixedMaterial::PARAM_DIFFUSE, Color(1.0,1.0,0.8,0.9) );
|
||||
mat_light->set_flag(Material::FLAG_UNSHADED,true);
|
||||
|
||||
Ref< Mesh > mesh;
|
||||
|
||||
Ref<SurfaceTool> surftool( memnew( SurfaceTool ));
|
||||
|
||||
switch(type) {
|
||||
|
||||
case VisualServer::LIGHT_DIRECTIONAL: {
|
||||
|
||||
|
||||
mat_area->set_parameter( FixedMaterial::PARAM_DIFFUSE,Color(0.9,0.8,0.1,0.8) );
|
||||
mat_area->set_blend_mode( Material::BLEND_MODE_MIX);
|
||||
mat_area->set_flag(Material::FLAG_DOUBLE_SIDED,false);
|
||||
mat_area->set_flag(Material::FLAG_UNSHADED,true);
|
||||
|
||||
_make_sphere( 5,5,0.6, surftool );
|
||||
surftool->set_material(mat_light);
|
||||
mesh=surftool->commit(mesh);
|
||||
|
||||
// float radius=1;
|
||||
|
||||
surftool->begin(Mesh::PRIMITIVE_TRIANGLES);
|
||||
|
||||
const int arrow_points=5;
|
||||
Vector3 arrow[arrow_points]={
|
||||
Vector3(0,0,2),
|
||||
Vector3(1,1,2),
|
||||
Vector3(1,1,-1),
|
||||
Vector3(2,2,-1),
|
||||
Vector3(0,0,-3)
|
||||
};
|
||||
|
||||
int arrow_sides=4;
|
||||
|
||||
|
||||
for(int i = 0; i < arrow_sides ; i++) {
|
||||
|
||||
|
||||
Matrix3 ma(Vector3(0,0,1),Math_PI*2*float(i)/arrow_sides);
|
||||
Matrix3 mb(Vector3(0,0,1),Math_PI*2*float(i+1)/arrow_sides);
|
||||
|
||||
|
||||
for(int j=0;j<arrow_points-1;j++) {
|
||||
|
||||
Vector3 points[4]={
|
||||
ma.xform(arrow[j]),
|
||||
mb.xform(arrow[j]),
|
||||
mb.xform(arrow[j+1]),
|
||||
ma.xform(arrow[j+1]),
|
||||
};
|
||||
|
||||
Vector3 n = Plane(points[0],points[1],points[2]).normal;
|
||||
|
||||
surftool->add_normal(n);
|
||||
surftool->add_vertex(points[0]);
|
||||
surftool->add_normal(n);
|
||||
surftool->add_vertex(points[1]);
|
||||
surftool->add_normal(n);
|
||||
surftool->add_vertex(points[2]);
|
||||
|
||||
surftool->add_normal(n);
|
||||
surftool->add_vertex(points[0]);
|
||||
surftool->add_normal(n);
|
||||
surftool->add_vertex(points[2]);
|
||||
surftool->add_normal(n);
|
||||
surftool->add_vertex(points[3]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
surftool->set_material(mat_area);
|
||||
mesh=surftool->commit(mesh);
|
||||
|
||||
|
||||
|
||||
} break;
|
||||
case VisualServer::LIGHT_OMNI: {
|
||||
|
||||
|
||||
_make_sphere( 20,20,vars[PARAM_RADIUS], surftool );
|
||||
surftool->set_material(mat_area);
|
||||
mesh=surftool->commit(mesh);
|
||||
_make_sphere(5,5, 0.1, surftool );
|
||||
surftool->set_material(mat_light);
|
||||
mesh=surftool->commit(mesh);
|
||||
} break;
|
||||
|
||||
case VisualServer::LIGHT_SPOT: {
|
||||
|
||||
_make_sphere( 5,5,0.1, surftool );
|
||||
surftool->set_material(mat_light);
|
||||
mesh=surftool->commit(mesh);
|
||||
|
||||
// make cone
|
||||
int points=24;
|
||||
float len=vars[PARAM_RADIUS];
|
||||
float size=Math::tan(Math::deg2rad(vars[PARAM_SPOT_ANGLE]))*len;
|
||||
|
||||
surftool->begin(Mesh::PRIMITIVE_TRIANGLES);
|
||||
|
||||
for(int i = 0; i < points; i++) {
|
||||
|
||||
float x0=Math::sin(i * Math_PI * 2 / points);
|
||||
float y0=Math::cos(i * Math_PI * 2 / points);
|
||||
float x1=Math::sin((i+1) * Math_PI * 2 / points);
|
||||
float y1=Math::cos((i+1) * Math_PI * 2 / points);
|
||||
|
||||
Vector3 v1=Vector3(x0*size,y0*size,-len).normalized()*len;
|
||||
Vector3 v2=Vector3(x1*size,y1*size,-len).normalized()*len;
|
||||
|
||||
Vector3 v3=Vector3(0,0,0);
|
||||
Vector3 v4=Vector3(0,0,v1.z);
|
||||
|
||||
Vector3 n = Plane(v1,v2,v3).normal;
|
||||
|
||||
|
||||
surftool->add_normal(n);
|
||||
surftool->add_vertex(v1);
|
||||
surftool->add_normal(n);
|
||||
surftool->add_vertex(v2);
|
||||
surftool->add_normal(n);
|
||||
surftool->add_vertex(v3);
|
||||
|
||||
n=Vector3(0,0,-1);
|
||||
|
||||
surftool->add_normal(n);
|
||||
surftool->add_vertex(v1);
|
||||
surftool->add_normal(n);
|
||||
surftool->add_vertex(v2);
|
||||
surftool->add_normal(n);
|
||||
surftool->add_vertex(v4);
|
||||
|
||||
|
||||
}
|
||||
|
||||
surftool->set_material(mat_area);
|
||||
mesh=surftool->commit(mesh);
|
||||
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
|
||||
AABB Light::get_aabb() const {
|
||||
|
||||
if (type==VisualServer::LIGHT_DIRECTIONAL) {
|
||||
|
||||
return AABB( Vector3(-1,-1,-1), Vector3(2, 2, 2 ) );
|
||||
|
||||
} else if (type==VisualServer::LIGHT_OMNI) {
|
||||
|
||||
return AABB( Vector3(-1,-1,-1) * vars[PARAM_RADIUS], Vector3(2, 2, 2 ) * vars[PARAM_RADIUS]);
|
||||
|
||||
} else if (type==VisualServer::LIGHT_SPOT) {
|
||||
|
||||
float len=vars[PARAM_RADIUS];
|
||||
float size=Math::tan(Math::deg2rad(vars[PARAM_SPOT_ANGLE]))*len;
|
||||
return AABB( Vector3( -size,-size,-len ), Vector3( size*2, size*2, len ) );
|
||||
}
|
||||
|
||||
return AABB();
|
||||
}
|
||||
|
||||
DVector<Face3> Light::get_faces(uint32_t p_usage_flags) const {
|
||||
|
||||
return DVector<Face3>();
|
||||
}
|
||||
|
||||
|
||||
void Light::set_operator(Operator p_op) {
|
||||
ERR_FAIL_INDEX(p_op,2);
|
||||
op=p_op;
|
||||
VisualServer::get_singleton()->light_set_operator(light,VS::LightOp(op));
|
||||
|
||||
}
|
||||
|
||||
Light::Operator Light::get_operator() const {
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
void Light::approximate_opengl_attenuation(float p_constant, float p_linear, float p_quadratic,float p_radius_treshold) {
|
||||
|
||||
//this is horrible and must never be used
|
||||
|
||||
float a = p_quadratic * p_radius_treshold;
|
||||
float b = p_linear * p_radius_treshold;
|
||||
float c = p_constant * p_radius_treshold -1;
|
||||
|
||||
float radius=10000;
|
||||
|
||||
if(a == 0) { // solve linear
|
||||
float d = Math::abs(-c/b);
|
||||
if(d<radius)
|
||||
radius=d;
|
||||
|
||||
|
||||
} else { // solve quadratic
|
||||
// now ad^2 + bd + c = 0, solve quadratic equation:
|
||||
|
||||
float denominator = 2*a;
|
||||
|
||||
if(denominator != 0) {
|
||||
|
||||
|
||||
float root = b*b - 4*a*c;
|
||||
|
||||
if(root >=0) {
|
||||
|
||||
root = sqrt(root);
|
||||
|
||||
float solution1 = fabs( (-b + root) / denominator);
|
||||
float solution2 = fabs( (-b - root) / denominator);
|
||||
|
||||
if(solution1 > radius)
|
||||
solution1 = radius;
|
||||
|
||||
if(solution2 > radius)
|
||||
solution2 = radius;
|
||||
|
||||
radius = (solution1 > solution2 ? solution1 : solution2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float energy=1.0;
|
||||
|
||||
if (p_constant>0)
|
||||
energy=1.0/p_constant; //energy is this
|
||||
else
|
||||
energy=8.0; // some high number..
|
||||
|
||||
|
||||
if (radius==10000)
|
||||
radius=100; //bug?
|
||||
|
||||
set_parameter(PARAM_RADIUS,radius);
|
||||
set_parameter(PARAM_ENERGY,energy);
|
||||
|
||||
}
|
||||
|
||||
void Light::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_parameter","variable","value"), &Light::set_parameter );
|
||||
ObjectTypeDB::bind_method(_MD("get_parameter"), &Light::get_parameter );
|
||||
ObjectTypeDB::bind_method(_MD("set_color","color","value"), &Light::set_color );
|
||||
ObjectTypeDB::bind_method(_MD("get_color"), &Light::get_color );
|
||||
ObjectTypeDB::bind_method(_MD("set_project_shadows","enable"), &Light::set_project_shadows );
|
||||
ObjectTypeDB::bind_method(_MD("has_project_shadows"), &Light::has_project_shadows );
|
||||
ObjectTypeDB::bind_method(_MD("set_projector","projector:Texture"), &Light::set_projector );
|
||||
ObjectTypeDB::bind_method(_MD("get_projector:Texture"), &Light::get_projector );
|
||||
ObjectTypeDB::bind_method(_MD("set_operator","operator"), &Light::set_operator );
|
||||
ObjectTypeDB::bind_method(_MD("get_operator"), &Light::get_operator );
|
||||
|
||||
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/energy", PROPERTY_HINT_EXP_RANGE, "0,64,0.01"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_ENERGY );
|
||||
/*
|
||||
if (type == VisualServer::LIGHT_OMNI || type == VisualServer::LIGHT_SPOT) {
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "params/radius", PROPERTY_HINT_RANGE, "0.01,4096,0.01"));
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "params/attenuation", PROPERTY_HINT_RANGE, "0,8,0.01"));
|
||||
}
|
||||
|
||||
if (type == VisualServer::LIGHT_SPOT) {
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "params/spot_angle", PROPERTY_HINT_RANGE, "0.01,90.0,0.01"));
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "params/spot_attenuation", PROPERTY_HINT_RANGE, "0,8,0.01"));
|
||||
|
||||
}*/
|
||||
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::COLOR, "colors/ambient"), _SCS("set_color"), _SCS("get_color"),COLOR_AMBIENT);
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::COLOR, "colors/diffuse"), _SCS("set_color"), _SCS("get_color"),COLOR_DIFFUSE);
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::COLOR, "colors/specular"), _SCS("set_color"), _SCS("get_color"),COLOR_SPECULAR);
|
||||
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "shadow/shadow"), _SCS("set_project_shadows"), _SCS("has_project_shadows"));
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/darkening", PROPERTY_HINT_RANGE, "0,64,0.01"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_DARKENING );
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/z_offset", PROPERTY_HINT_RANGE, "0,128,0.001"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_Z_OFFSET);
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/z_slope_scale", PROPERTY_HINT_RANGE, "0,128,0.001"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_Z_SLOPE_SCALE);
|
||||
ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "projector",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_projector"), _SCS("get_projector"));
|
||||
ADD_PROPERTY( PropertyInfo( Variant::INT, "operator",PROPERTY_HINT_ENUM,"Add,Sub"), _SCS("set_operator"), _SCS("get_operator"));
|
||||
|
||||
|
||||
BIND_CONSTANT( PARAM_RADIUS );
|
||||
BIND_CONSTANT( PARAM_ENERGY );
|
||||
BIND_CONSTANT( PARAM_ATTENUATION );
|
||||
BIND_CONSTANT( PARAM_SPOT_ANGLE );
|
||||
BIND_CONSTANT( PARAM_SPOT_ATTENUATION );
|
||||
BIND_CONSTANT( PARAM_SHADOW_DARKENING );
|
||||
BIND_CONSTANT( PARAM_SHADOW_Z_OFFSET );
|
||||
|
||||
BIND_CONSTANT( COLOR_AMBIENT );
|
||||
BIND_CONSTANT( COLOR_DIFFUSE );
|
||||
BIND_CONSTANT( COLOR_SPECULAR );
|
||||
|
||||
}
|
||||
|
||||
|
||||
Light::Light(VisualServer::LightType p_type) {
|
||||
|
||||
type=p_type;
|
||||
light=VisualServer::get_singleton()->light_create(p_type);
|
||||
|
||||
set_parameter(PARAM_SPOT_ATTENUATION,1.0);
|
||||
set_parameter(PARAM_SPOT_ANGLE,30.0);
|
||||
set_parameter(PARAM_RADIUS,2.0);
|
||||
set_parameter(PARAM_ENERGY,1.0);
|
||||
set_parameter(PARAM_ATTENUATION,1.0);
|
||||
set_parameter(PARAM_SHADOW_DARKENING,0.0);
|
||||
set_parameter(PARAM_SHADOW_Z_OFFSET,0.05);
|
||||
set_parameter(PARAM_SHADOW_Z_SLOPE_SCALE,0);
|
||||
|
||||
set_color( COLOR_AMBIENT, Color(0,0,0));
|
||||
set_color( COLOR_DIFFUSE, Color(1,1,1));
|
||||
set_color( COLOR_SPECULAR, Color(1,1,1));
|
||||
|
||||
op=OPERATOR_ADD;
|
||||
set_project_shadows( false );
|
||||
set_base(light);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Light::Light() {
|
||||
|
||||
type=VisualServer::LIGHT_DIRECTIONAL;
|
||||
ERR_PRINT("Light shouldn't be instanced dircetly, use the subtypes.");
|
||||
}
|
||||
|
||||
|
||||
Light::~Light() {
|
||||
|
||||
if (light.is_valid())
|
||||
VisualServer::get_singleton()->free(light);
|
||||
}
|
||||
/////////////////////////////////////////
|
||||
|
||||
|
||||
void DirectionalLight::set_shadow_mode(ShadowMode p_mode) {
|
||||
|
||||
shadow_mode=p_mode;
|
||||
VS::get_singleton()->light_directional_set_shadow_mode(light,(VS::LightDirectionalShadowMode)p_mode);
|
||||
|
||||
}
|
||||
|
||||
DirectionalLight::ShadowMode DirectionalLight::get_shadow_mode() const{
|
||||
|
||||
return shadow_mode;
|
||||
}
|
||||
|
||||
void DirectionalLight::set_shadow_param(ShadowParam p_param, float p_value) {
|
||||
|
||||
ERR_FAIL_INDEX(p_param,3);
|
||||
shadow_param[p_param]=p_value;
|
||||
VS::get_singleton()->light_directional_set_shadow_param(light,VS::LightDirectionalShadowParam(p_param),p_value);
|
||||
}
|
||||
|
||||
float DirectionalLight::get_shadow_param(ShadowParam p_param) const {
|
||||
ERR_FAIL_INDEX_V(p_param,3,0);
|
||||
return shadow_param[p_param];
|
||||
}
|
||||
|
||||
void DirectionalLight::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_shadow_mode","mode"),&DirectionalLight::set_shadow_mode);
|
||||
ObjectTypeDB::bind_method(_MD("get_shadow_mode"),&DirectionalLight::get_shadow_mode);
|
||||
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_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_PARAM_MAX_DISTANCE );
|
||||
BIND_CONSTANT( SHADOW_PARAM_PSSM_SPLIT_WEIGHT );
|
||||
BIND_CONSTANT( SHADOW_PARAM_PSSM_ZOFFSET_SCALE );
|
||||
|
||||
}
|
||||
|
||||
|
||||
DirectionalLight::DirectionalLight() : Light( VisualServer::LIGHT_DIRECTIONAL ) {
|
||||
|
||||
shadow_mode=SHADOW_ORTHOGONAL;
|
||||
shadow_param[SHADOW_PARAM_MAX_DISTANCE]=0;
|
||||
shadow_param[SHADOW_PARAM_PSSM_SPLIT_WEIGHT]=0.5;
|
||||
shadow_param[SHADOW_PARAM_PSSM_ZOFFSET_SCALE]=2.0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void OmniLight::_bind_methods() {
|
||||
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/radius", PROPERTY_HINT_EXP_RANGE, "0.2,4096,0.01"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_RADIUS );
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_ATTENUATION );
|
||||
|
||||
}
|
||||
|
||||
void SpotLight::_bind_methods() {
|
||||
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/radius", PROPERTY_HINT_EXP_RANGE, "0.2,4096,0.01"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_RADIUS );
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_ATTENUATION );
|
||||
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/spot_angle", PROPERTY_HINT_RANGE, "0.01,89.9,0.01"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SPOT_ANGLE );
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/spot_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_ATTENUATION );
|
||||
|
||||
}
|
||||
|
||||
|
||||
195
scene/3d/light.h
Normal file
195
scene/3d/light.h
Normal file
@ -0,0 +1,195 @@
|
||||
/*************************************************************************/
|
||||
/* light.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef LIGHT_H
|
||||
#define LIGHT_H
|
||||
|
||||
|
||||
#include "scene/3d/visual_instance.h"
|
||||
#include "scene/resources/texture.h"
|
||||
#include "servers/visual_server.h"
|
||||
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
class Light : public VisualInstance {
|
||||
|
||||
OBJ_TYPE( Light, VisualInstance );
|
||||
OBJ_CATEGORY("3D Light Nodes");
|
||||
|
||||
public:
|
||||
|
||||
enum Parameter {
|
||||
PARAM_RADIUS=VisualServer::LIGHT_PARAM_RADIUS,
|
||||
PARAM_ENERGY=VisualServer::LIGHT_PARAM_ENERGY,
|
||||
PARAM_ATTENUATION=VisualServer::LIGHT_PARAM_ATTENUATION,
|
||||
PARAM_SPOT_ANGLE=VisualServer::LIGHT_PARAM_SPOT_ANGLE,
|
||||
PARAM_SPOT_ATTENUATION=VisualServer::LIGHT_PARAM_ATTENUATION,
|
||||
PARAM_SHADOW_DARKENING=VisualServer::LIGHT_PARAM_SHADOW_DARKENING,
|
||||
PARAM_SHADOW_Z_OFFSET=VisualServer::LIGHT_PARAM_SHADOW_Z_OFFSET,
|
||||
PARAM_SHADOW_Z_SLOPE_SCALE=VisualServer::LIGHT_PARAM_SHADOW_Z_SLOPE_SCALE,
|
||||
PARAM_MAX=VisualServer::LIGHT_PARAM_MAX
|
||||
};
|
||||
|
||||
|
||||
enum LightColor {
|
||||
|
||||
COLOR_AMBIENT=VisualServer::LIGHT_COLOR_AMBIENT,
|
||||
COLOR_DIFFUSE=VisualServer::LIGHT_COLOR_DIFFUSE,
|
||||
COLOR_SPECULAR=VisualServer::LIGHT_COLOR_SPECULAR
|
||||
};
|
||||
|
||||
|
||||
enum Operator {
|
||||
|
||||
OPERATOR_ADD,
|
||||
OPERATOR_SUB
|
||||
};
|
||||
private:
|
||||
|
||||
|
||||
Ref<Texture> projector;
|
||||
float vars[PARAM_MAX];
|
||||
Color colors[3];
|
||||
|
||||
|
||||
VisualServer::LightType type;
|
||||
bool shadows;
|
||||
Operator op;
|
||||
|
||||
// bind helpers
|
||||
|
||||
protected:
|
||||
|
||||
RID light;
|
||||
|
||||
virtual bool _can_gizmo_scale() const;
|
||||
virtual RES _get_gizmo_geometry() const;
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
|
||||
Light(VisualServer::LightType p_type);
|
||||
public:
|
||||
|
||||
VS::LightType get_light_type() const { return type; }
|
||||
|
||||
void set_parameter(Parameter p_var, float p_value);
|
||||
float get_parameter(Parameter p_var) const;
|
||||
|
||||
void set_color(LightColor p_color,const Color& p_value);
|
||||
Color get_color(LightColor p_color) const;
|
||||
|
||||
void set_project_shadows(bool p_enabled);
|
||||
bool has_project_shadows() const;
|
||||
|
||||
void set_projector(const Ref<Texture>& p_projector);
|
||||
Ref<Texture> get_projector() const;
|
||||
|
||||
void set_operator(Operator p_op);
|
||||
Operator get_operator() const;
|
||||
|
||||
virtual AABB get_aabb() const;
|
||||
virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const;
|
||||
|
||||
void approximate_opengl_attenuation(float p_constant, float p_linear, float p_quadratic, float p_radius_treshold=0.5);
|
||||
|
||||
Light();
|
||||
~Light();
|
||||
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST( Light::Parameter );
|
||||
VARIANT_ENUM_CAST( Light::LightColor );
|
||||
VARIANT_ENUM_CAST( Light::Operator );
|
||||
|
||||
|
||||
class DirectionalLight : public Light {
|
||||
|
||||
OBJ_TYPE( DirectionalLight, Light );
|
||||
|
||||
public:
|
||||
|
||||
enum ShadowMode {
|
||||
SHADOW_ORTHOGONAL,
|
||||
SHADOW_PERSPECTIVE,
|
||||
SHADOW_PARALLEL_SPLIT
|
||||
};
|
||||
enum ShadowParam {
|
||||
SHADOW_PARAM_MAX_DISTANCE,
|
||||
SHADOW_PARAM_PSSM_SPLIT_WEIGHT,
|
||||
SHADOW_PARAM_PSSM_ZOFFSET_SCALE
|
||||
};
|
||||
|
||||
private:
|
||||
ShadowMode shadow_mode;
|
||||
float shadow_param[3];
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_shadow_mode(ShadowMode p_mode);
|
||||
ShadowMode get_shadow_mode() const;
|
||||
|
||||
void set_shadow_max_distance(float p_distance);
|
||||
float get_shadow_max_distance() const;
|
||||
void set_shadow_param(ShadowParam p_param, float p_value);
|
||||
float get_shadow_param(ShadowParam p_param) const;
|
||||
|
||||
DirectionalLight();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST( DirectionalLight::ShadowMode );
|
||||
VARIANT_ENUM_CAST( DirectionalLight::ShadowParam );
|
||||
|
||||
|
||||
class OmniLight : public Light {
|
||||
|
||||
OBJ_TYPE( OmniLight, Light );
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
|
||||
OmniLight() : Light( VisualServer::LIGHT_OMNI ) {}
|
||||
};
|
||||
|
||||
class SpotLight : public Light {
|
||||
|
||||
OBJ_TYPE( SpotLight, Light );
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
|
||||
SpotLight() : Light( VisualServer::LIGHT_SPOT ) {}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
218
scene/3d/mesh_instance.cpp
Normal file
218
scene/3d/mesh_instance.cpp
Normal file
@ -0,0 +1,218 @@
|
||||
/*************************************************************************/
|
||||
/* mesh_instance.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "mesh_instance.h"
|
||||
|
||||
#include "skeleton.h"
|
||||
#include "physics_body.h"
|
||||
|
||||
|
||||
|
||||
bool MeshInstance::_set(const StringName& p_name, const Variant& p_value) {
|
||||
|
||||
//this is not _too_ bad performance wise, really. it only arrives here if the property was not set anywhere else.
|
||||
//add to it that it's probably found on first call to _set anyway.
|
||||
|
||||
if (!get_instance().is_valid())
|
||||
return false;
|
||||
|
||||
|
||||
Map<StringName,MorphTrack>::Element *E = morph_tracks.find(p_name);
|
||||
if (!E)
|
||||
return false;
|
||||
|
||||
E->get().value=p_value;
|
||||
VisualServer::get_singleton()->instance_set_morph_target_weight(get_instance(),E->get().idx,E->get().value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MeshInstance::_get(const StringName& p_name,Variant &r_ret) const {
|
||||
|
||||
|
||||
if (!get_instance().is_valid())
|
||||
return false;
|
||||
|
||||
const Map<StringName,MorphTrack>::Element *E = morph_tracks.find(p_name);
|
||||
if (!E)
|
||||
return false;
|
||||
|
||||
r_ret = E->get().value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MeshInstance::_get_property_list( List<PropertyInfo> *p_list) const {
|
||||
|
||||
List<String> ls;
|
||||
for(const Map<StringName,MorphTrack>::Element *E=morph_tracks.front();E;E=E->next()) {
|
||||
|
||||
ls.push_back(E->key());
|
||||
}
|
||||
|
||||
ls.sort();;
|
||||
|
||||
for(List<String>::Element *E=ls.front();E;E=E->next()) {
|
||||
p_list->push_back( PropertyInfo(Variant::REAL,E->get(),PROPERTY_HINT_RANGE,"0,1,0.01"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void MeshInstance::set_mesh(const Ref<Mesh>& p_mesh) {
|
||||
|
||||
mesh=p_mesh;
|
||||
|
||||
morph_tracks.clear();
|
||||
if (mesh.is_valid()) {
|
||||
|
||||
|
||||
for(int i=0;i<mesh->get_morph_target_count();i++) {
|
||||
|
||||
MorphTrack mt;
|
||||
mt.idx=i;
|
||||
mt.value=0;
|
||||
morph_tracks["morph/"+String(mesh->get_morph_target_name(i))]=mt;
|
||||
}
|
||||
set_base(mesh->get_rid());
|
||||
} else {
|
||||
|
||||
set_base(RID());
|
||||
}
|
||||
|
||||
_change_notify("mesh");
|
||||
}
|
||||
Ref<Mesh> MeshInstance::get_mesh() const {
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
|
||||
AABB MeshInstance::get_aabb() const {
|
||||
|
||||
if (!mesh.is_null())
|
||||
return mesh->get_aabb();
|
||||
|
||||
return AABB();
|
||||
}
|
||||
|
||||
DVector<Face3> MeshInstance::get_faces(uint32_t p_usage_flags) const {
|
||||
|
||||
if (!(p_usage_flags&(FACES_SOLID|FACES_ENCLOSING)))
|
||||
return DVector<Face3>();
|
||||
|
||||
if (mesh.is_null())
|
||||
return DVector<Face3>();
|
||||
|
||||
return mesh->get_faces();
|
||||
}
|
||||
|
||||
|
||||
Node* MeshInstance::create_trimesh_collision_node() {
|
||||
|
||||
if (mesh.is_null())
|
||||
return NULL;
|
||||
|
||||
Ref<Shape> shape = mesh->create_trimesh_shape();
|
||||
if (shape.is_null())
|
||||
return NULL;
|
||||
|
||||
StaticBody * static_body = memnew( StaticBody );
|
||||
static_body->add_shape( shape );
|
||||
return static_body;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MeshInstance::create_trimesh_collision() {
|
||||
|
||||
|
||||
StaticBody* static_body = create_trimesh_collision_node()->cast_to<StaticBody>();
|
||||
ERR_FAIL_COND(!static_body);
|
||||
static_body->set_name( String(get_name()) + "_col" );
|
||||
|
||||
add_child(static_body);
|
||||
if (get_owner())
|
||||
static_body->set_owner( get_owner() );
|
||||
|
||||
}
|
||||
|
||||
Node* MeshInstance::create_convex_collision_node() {
|
||||
|
||||
if (mesh.is_null())
|
||||
return NULL;
|
||||
|
||||
Ref<Shape> shape = mesh->create_convex_shape();
|
||||
if (shape.is_null())
|
||||
return NULL;
|
||||
|
||||
StaticBody * static_body = memnew( StaticBody );
|
||||
static_body->add_shape( shape );
|
||||
return static_body;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MeshInstance::create_convex_collision() {
|
||||
|
||||
|
||||
StaticBody* static_body = create_convex_collision_node()->cast_to<StaticBody>();
|
||||
ERR_FAIL_COND(!static_body);
|
||||
static_body->set_name( String(get_name()) + "_col" );
|
||||
|
||||
add_child(static_body);
|
||||
if (get_owner())
|
||||
static_body->set_owner( get_owner() );
|
||||
|
||||
}
|
||||
|
||||
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("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"));
|
||||
|
||||
|
||||
}
|
||||
|
||||
MeshInstance::MeshInstance()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
MeshInstance::~MeshInstance() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
80
scene/3d/mesh_instance.h
Normal file
80
scene/3d/mesh_instance.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*************************************************************************/
|
||||
/* mesh_instance.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef MESH_INSTANCE_H
|
||||
#define MESH_INSTANCE_H
|
||||
|
||||
#include "scene/3d/visual_instance.h"
|
||||
#include "scene/resources/mesh.h"
|
||||
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
class MeshInstance : public GeometryInstance {
|
||||
|
||||
OBJ_TYPE( MeshInstance, GeometryInstance );
|
||||
|
||||
Ref<Mesh> mesh;
|
||||
|
||||
struct MorphTrack {
|
||||
|
||||
int idx;
|
||||
float value;
|
||||
MorphTrack() { idx=0; value=0; }
|
||||
};
|
||||
|
||||
Map<StringName,MorphTrack> morph_tracks;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
bool _set(const StringName& p_name, const Variant& p_value);
|
||||
bool _get(const StringName& p_name,Variant &r_ret) const;
|
||||
void _get_property_list( List<PropertyInfo> *p_list) const;
|
||||
|
||||
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_mesh(const Ref<Mesh>& p_mesh);
|
||||
Ref<Mesh> get_mesh() const;
|
||||
|
||||
Node* create_trimesh_collision_node();
|
||||
void create_trimesh_collision();
|
||||
|
||||
Node* create_convex_collision_node();
|
||||
void create_convex_collision();
|
||||
|
||||
virtual AABB get_aabb() const;
|
||||
virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const;
|
||||
|
||||
MeshInstance();
|
||||
~MeshInstance();
|
||||
};
|
||||
|
||||
#endif
|
||||
81
scene/3d/multimesh_instance.cpp
Normal file
81
scene/3d/multimesh_instance.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
/*************************************************************************/
|
||||
/* multimesh_instance.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "multimesh_instance.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void MultiMeshInstance::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_multimesh","multimesh"),&MultiMeshInstance::set_multimesh);
|
||||
ObjectTypeDB::bind_method(_MD("get_multimesh"),&MultiMeshInstance::get_multimesh);
|
||||
ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"multimesh",PROPERTY_HINT_RESOURCE_TYPE,"MultiMesh"), _SCS("set_multimesh"), _SCS("get_multimesh"));
|
||||
|
||||
|
||||
}
|
||||
|
||||
void MultiMeshInstance::set_multimesh(const Ref<MultiMesh>& p_multimesh) {
|
||||
|
||||
multimesh=p_multimesh;
|
||||
if (multimesh.is_valid())
|
||||
set_base(multimesh->get_rid());
|
||||
else
|
||||
set_base(RID());
|
||||
|
||||
}
|
||||
|
||||
Ref<MultiMesh> MultiMeshInstance::get_multimesh() const {
|
||||
|
||||
return multimesh;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DVector<Face3> MultiMeshInstance::get_faces(uint32_t p_usage_flags) const {
|
||||
|
||||
return DVector<Face3>();
|
||||
}
|
||||
|
||||
AABB MultiMeshInstance::get_aabb() const {
|
||||
|
||||
if (multimesh.is_null())
|
||||
return AABB();
|
||||
else
|
||||
return multimesh->get_aabb();
|
||||
}
|
||||
|
||||
MultiMeshInstance::MultiMeshInstance() {
|
||||
|
||||
}
|
||||
|
||||
MultiMeshInstance::~MultiMeshInstance() {
|
||||
|
||||
|
||||
}
|
||||
64
scene/3d/multimesh_instance.h
Normal file
64
scene/3d/multimesh_instance.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*************************************************************************/
|
||||
/* multimesh_instance.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef MULTIMESH_INSTANCE_H
|
||||
#define MULTIMESH_INSTANCE_H
|
||||
|
||||
#include "scene/3d/visual_instance.h"
|
||||
#include "scene/resources/multimesh.h"
|
||||
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
|
||||
class MultiMeshInstance : public GeometryInstance {
|
||||
OBJ_TYPE( MultiMeshInstance, GeometryInstance );
|
||||
|
||||
|
||||
Ref<MultiMesh> multimesh;
|
||||
protected:
|
||||
|
||||
|
||||
static void _bind_methods();
|
||||
// bind helpers
|
||||
|
||||
public:
|
||||
|
||||
virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const;
|
||||
|
||||
void set_multimesh(const Ref<MultiMesh>& p_multimesh);
|
||||
Ref<MultiMesh> get_multimesh() const;
|
||||
|
||||
virtual AABB get_aabb() const;
|
||||
|
||||
MultiMeshInstance();
|
||||
~MultiMeshInstance();
|
||||
};
|
||||
|
||||
#endif // MULTIMESH_INSTANCE_H
|
||||
|
||||
33
scene/3d/optimized_spatial_scene.cpp
Normal file
33
scene/3d/optimized_spatial_scene.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
/*************************************************************************/
|
||||
/* optimized_spatial_scene.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "optimized_spatial_scene.h"
|
||||
|
||||
OptimizedSpatialScene::OptimizedSpatialScene()
|
||||
{
|
||||
}
|
||||
41
scene/3d/optimized_spatial_scene.h
Normal file
41
scene/3d/optimized_spatial_scene.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*************************************************************************/
|
||||
/* optimized_spatial_scene.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef OPTIMIZED_SPATIAL_SCENE_H
|
||||
#define OPTIMIZED_SPATIAL_SCENE_H
|
||||
|
||||
#include "scene/3d/spatial.h"
|
||||
|
||||
class OptimizedSpatialScene : public Spatial {
|
||||
|
||||
OBJ_TYPE( OptimizedSpatialScene, Spatial );
|
||||
public:
|
||||
OptimizedSpatialScene();
|
||||
};
|
||||
|
||||
#endif // OPTIMIZED_SPATIAL_SCENE_H
|
||||
559
scene/3d/particles.cpp
Normal file
559
scene/3d/particles.cpp
Normal file
@ -0,0 +1,559 @@
|
||||
/*************************************************************************/
|
||||
/* particles.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "particles.h"
|
||||
#include "servers/visual_server.h"
|
||||
#include "scene/resources/surface_tool.h"
|
||||
|
||||
/*
|
||||
static const char* _var_names[Particles::VAR_MAX]={
|
||||
"vars/lifetime",
|
||||
"vars/spread",
|
||||
"vars/gravity",
|
||||
"vars/linear_vel",
|
||||
"vars/angular_vel",
|
||||
"vars/linear_accel",
|
||||
"vars/radial_accel",
|
||||
"vars/tan_accel",
|
||||
"vars/initial_size",
|
||||
"vars/final_size",
|
||||
"vars/initial_angle",
|
||||
"vars/height",
|
||||
"vars/height_speed_scale",
|
||||
};
|
||||
*/
|
||||
static const char* _rand_names[Particles::VAR_MAX]={
|
||||
"rand/lifetime",
|
||||
"rand/spread",
|
||||
"rand/gravity",
|
||||
"rand/linear_vel",
|
||||
"rand/angular_vel",
|
||||
"rand/linear_accel",
|
||||
"rand/radial_accel",
|
||||
"rand/tan_accel",
|
||||
"rand/damping",
|
||||
"rand/initial_size",
|
||||
"rand/final_size",
|
||||
"rand/initial_angle",
|
||||
"rand/height",
|
||||
"rand/height_speed_scale",
|
||||
};
|
||||
|
||||
static const Particles::Variable _var_indices[Particles::VAR_MAX]={
|
||||
Particles::VAR_LIFETIME,
|
||||
Particles::VAR_SPREAD,
|
||||
Particles::VAR_GRAVITY,
|
||||
Particles::VAR_LINEAR_VELOCITY,
|
||||
Particles::VAR_ANGULAR_VELOCITY,
|
||||
Particles::VAR_LINEAR_ACCELERATION,
|
||||
Particles::VAR_DRAG,
|
||||
Particles::VAR_TANGENTIAL_ACCELERATION,
|
||||
Particles::VAR_DAMPING,
|
||||
Particles::VAR_INITIAL_SIZE,
|
||||
Particles::VAR_FINAL_SIZE,
|
||||
Particles::VAR_INITIAL_ANGLE,
|
||||
Particles::VAR_HEIGHT,
|
||||
Particles::VAR_HEIGHT_SPEED_SCALE,
|
||||
};
|
||||
|
||||
|
||||
|
||||
AABB Particles::get_aabb() const {
|
||||
|
||||
return AABB( Vector3(-1,-1,-1), Vector3(2, 2, 2 ) );
|
||||
}
|
||||
DVector<Face3> Particles::get_faces(uint32_t p_usage_flags) const {
|
||||
|
||||
return DVector<Face3>();
|
||||
}
|
||||
|
||||
|
||||
void Particles::set_amount(int p_amount) {
|
||||
|
||||
ERR_FAIL_INDEX(p_amount,4096);
|
||||
amount=p_amount;
|
||||
VisualServer::get_singleton()->particles_set_amount(particles,p_amount);
|
||||
}
|
||||
int Particles::get_amount() const {
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
void Particles::set_emitting(bool p_emitting) {
|
||||
|
||||
emitting=p_emitting;
|
||||
VisualServer::get_singleton()->particles_set_emitting(particles,p_emitting);
|
||||
|
||||
setup_timer();
|
||||
}
|
||||
bool Particles::is_emitting() const {
|
||||
|
||||
return emitting;
|
||||
}
|
||||
|
||||
void Particles::set_visibility_aabb(const AABB& p_aabb) {
|
||||
|
||||
visibility_aabb=p_aabb;
|
||||
VisualServer::get_singleton()->particles_set_visibility_aabb(particles,p_aabb);
|
||||
update_gizmo();
|
||||
|
||||
}
|
||||
AABB Particles::get_visibility_aabb() const {
|
||||
|
||||
return visibility_aabb;
|
||||
}
|
||||
|
||||
|
||||
void Particles::set_emission_points(const DVector<Vector3>& p_points) {
|
||||
|
||||
using_points = p_points.size();
|
||||
VisualServer::get_singleton()->particles_set_emission_points(particles,p_points);
|
||||
}
|
||||
|
||||
DVector<Vector3> Particles::get_emission_points() const {
|
||||
|
||||
if (!using_points)
|
||||
return DVector<Vector3>();
|
||||
|
||||
return VisualServer::get_singleton()->particles_get_emission_points(particles);
|
||||
|
||||
}
|
||||
|
||||
void Particles::set_emission_half_extents(const Vector3& p_half_extents) {
|
||||
|
||||
emission_half_extents=p_half_extents;
|
||||
VisualServer::get_singleton()->particles_set_emission_half_extents(particles,p_half_extents);
|
||||
|
||||
}
|
||||
|
||||
Vector3 Particles::get_emission_half_extents() const {
|
||||
|
||||
return emission_half_extents;
|
||||
}
|
||||
|
||||
void Particles::set_emission_base_velocity(const Vector3& p_base_velocity) {
|
||||
|
||||
emission_base_velocity=p_base_velocity;
|
||||
VisualServer::get_singleton()->particles_set_emission_base_velocity(particles,p_base_velocity);
|
||||
|
||||
}
|
||||
|
||||
Vector3 Particles::get_emission_base_velocity() const {
|
||||
|
||||
return emission_base_velocity;
|
||||
}
|
||||
|
||||
void Particles::set_gravity_normal(const Vector3& p_normal) {
|
||||
|
||||
gravity_normal=p_normal;
|
||||
VisualServer::get_singleton()->particles_set_gravity_normal(particles,p_normal);
|
||||
}
|
||||
|
||||
Vector3 Particles::get_gravity_normal() const {
|
||||
|
||||
return gravity_normal;
|
||||
|
||||
}
|
||||
|
||||
void Particles::set_variable(Variable p_variable,float p_value) {
|
||||
|
||||
ERR_FAIL_INDEX(p_variable,VAR_MAX);
|
||||
var[p_variable]=p_value;
|
||||
VisualServer::get_singleton()->particles_set_variable(particles,(VS::ParticleVariable)p_variable,p_value);
|
||||
if (p_variable==VAR_SPREAD)
|
||||
update_gizmo();
|
||||
}
|
||||
|
||||
float Particles::get_variable(Variable p_variable) const {
|
||||
|
||||
ERR_FAIL_INDEX_V(p_variable,VAR_MAX,-1);
|
||||
return var[p_variable];
|
||||
|
||||
}
|
||||
|
||||
void Particles::set_randomness(Variable p_variable,float p_randomness) {
|
||||
|
||||
ERR_FAIL_INDEX(p_variable,VAR_MAX);
|
||||
var_random[p_variable]=p_randomness;
|
||||
VisualServer::get_singleton()->particles_set_randomness(particles,(VS::ParticleVariable)p_variable,p_randomness);
|
||||
|
||||
}
|
||||
float Particles::get_randomness(Variable p_variable) const {
|
||||
|
||||
ERR_FAIL_INDEX_V(p_variable,VAR_MAX,-1);
|
||||
return var_random[p_variable];
|
||||
|
||||
}
|
||||
|
||||
void Particles::set_color_phase_pos(int p_phase, float p_pos) {
|
||||
|
||||
ERR_FAIL_INDEX(p_phase,VS::MAX_PARTICLE_COLOR_PHASES);
|
||||
color_phase[p_phase].pos=p_pos;
|
||||
VisualServer::get_singleton()->particles_set_color_phase_pos(particles,p_phase,p_pos);
|
||||
|
||||
}
|
||||
float Particles::get_color_phase_pos(int p_phase) const {
|
||||
|
||||
ERR_FAIL_INDEX_V(p_phase,VS::MAX_PARTICLE_COLOR_PHASES,-1);
|
||||
return color_phase[p_phase].pos;
|
||||
}
|
||||
|
||||
void Particles::set_color_phase_color(int p_phase, const Color& p_color) {
|
||||
|
||||
ERR_FAIL_INDEX(p_phase,VS::MAX_PARTICLE_COLOR_PHASES);
|
||||
color_phase[p_phase].color=p_color;
|
||||
VisualServer::get_singleton()->particles_set_color_phase_color(particles,p_phase,p_color);
|
||||
|
||||
}
|
||||
Color Particles::get_color_phase_color(int p_phase) const {
|
||||
|
||||
ERR_FAIL_INDEX_V(p_phase,VS::MAX_PARTICLE_COLOR_PHASES,Color());
|
||||
return color_phase[p_phase].color;
|
||||
|
||||
}
|
||||
|
||||
void Particles::set_material(const Ref<Material>& p_material) {
|
||||
|
||||
material=p_material;
|
||||
if(material.is_null()) {
|
||||
VisualServer::get_singleton()->particles_set_material(particles,RID());
|
||||
} else {
|
||||
VisualServer::get_singleton()->particles_set_material(particles,material->get_rid());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Particles::setup_timer() {
|
||||
|
||||
if (emitting && emit_timeout > 0) {
|
||||
|
||||
timer->set_wait_time(emit_timeout);
|
||||
timer->start();
|
||||
timer->set_one_shot(true);
|
||||
};
|
||||
};
|
||||
|
||||
void Particles::set_emit_timeout(float p_timeout) {
|
||||
|
||||
emit_timeout = p_timeout;
|
||||
setup_timer();
|
||||
};
|
||||
|
||||
float Particles::get_emit_timeout() const {
|
||||
|
||||
return emit_timeout;
|
||||
};
|
||||
|
||||
|
||||
Ref<Material> Particles::get_material() const {
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
void Particles::set_height_from_velocity(bool p_enable) {
|
||||
|
||||
height_from_velocity=p_enable;
|
||||
VisualServer::get_singleton()->particles_set_height_from_velocity(particles,height_from_velocity);
|
||||
}
|
||||
|
||||
bool Particles::has_height_from_velocity() const {
|
||||
|
||||
return height_from_velocity;
|
||||
}
|
||||
|
||||
void Particles::set_color_phases(int p_phases) {
|
||||
|
||||
color_phase_count=p_phases;
|
||||
VisualServer::get_singleton()->particles_set_color_phases(particles,p_phases);
|
||||
}
|
||||
|
||||
int Particles::get_color_phases() const{
|
||||
|
||||
return color_phase_count;
|
||||
}
|
||||
|
||||
bool Particles::_can_gizmo_scale() const {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Particles::set_use_local_coordinates(bool p_use) {
|
||||
|
||||
local_coordinates=p_use;
|
||||
VisualServer::get_singleton()->particles_set_use_local_coordinates(particles,local_coordinates);
|
||||
}
|
||||
|
||||
bool Particles::is_using_local_coordinates() const{
|
||||
|
||||
return local_coordinates;
|
||||
}
|
||||
|
||||
|
||||
RES Particles::_get_gizmo_geometry() const {
|
||||
|
||||
Ref<SurfaceTool> surface_tool( memnew( SurfaceTool ));
|
||||
|
||||
Ref<FixedMaterial> mat( memnew( FixedMaterial ));
|
||||
|
||||
mat->set_parameter( FixedMaterial::PARAM_DIFFUSE,Color(0.0,0.6,0.7,0.2) );
|
||||
mat->set_parameter( FixedMaterial::PARAM_EMISSION,Color(0.5,0.7,0.8) );
|
||||
mat->set_blend_mode( Material::BLEND_MODE_ADD );
|
||||
mat->set_flag(Material::FLAG_DOUBLE_SIDED,true);
|
||||
mat->set_hint(Material::HINT_NO_DEPTH_DRAW,true);
|
||||
|
||||
|
||||
surface_tool->begin(Mesh::PRIMITIVE_TRIANGLES);
|
||||
surface_tool->set_material(mat);
|
||||
|
||||
int sides=16;
|
||||
int sections=24;
|
||||
|
||||
// float len=1;
|
||||
float deg=Math::deg2rad(var[VAR_SPREAD]*180);
|
||||
if (deg==180)
|
||||
deg=179.5;
|
||||
|
||||
Vector3 to=Vector3(0,0,-1);
|
||||
|
||||
for(int j=0;j<sections;j++) {
|
||||
|
||||
Vector3 p1=Matrix3(Vector3(1,0,0),deg*j/sections).xform(to);
|
||||
Vector3 p2=Matrix3(Vector3(1,0,0),deg*(j+1)/sections).xform(to);
|
||||
|
||||
for(int i=0;i<sides;i++) {
|
||||
|
||||
Vector3 p1r = Matrix3(Vector3(0,0,1),Math_PI*2*float(i)/sides).xform(p1);
|
||||
Vector3 p1s = Matrix3(Vector3(0,0,1),Math_PI*2*float(i+1)/sides).xform(p1);
|
||||
Vector3 p2s = Matrix3(Vector3(0,0,1),Math_PI*2*float(i+1)/sides).xform(p2);
|
||||
Vector3 p2r = Matrix3(Vector3(0,0,1),Math_PI*2*float(i)/sides).xform(p2);
|
||||
|
||||
surface_tool->add_normal(p1r.normalized());
|
||||
surface_tool->add_vertex(p1r);
|
||||
surface_tool->add_normal(p1s.normalized());
|
||||
surface_tool->add_vertex(p1s);
|
||||
surface_tool->add_normal(p2s.normalized());
|
||||
surface_tool->add_vertex(p2s);
|
||||
|
||||
surface_tool->add_normal(p1r.normalized());
|
||||
surface_tool->add_vertex(p1r);
|
||||
surface_tool->add_normal(p2s.normalized());
|
||||
surface_tool->add_vertex(p2s);
|
||||
surface_tool->add_normal(p2r.normalized());
|
||||
surface_tool->add_vertex(p2r);
|
||||
|
||||
if (j==sections-1) {
|
||||
|
||||
surface_tool->add_normal(p2r.normalized());
|
||||
surface_tool->add_vertex(p2r);
|
||||
surface_tool->add_normal(p2s.normalized());
|
||||
surface_tool->add_vertex(p2s);
|
||||
surface_tool->add_normal(Vector3(0,0,1));
|
||||
surface_tool->add_vertex(Vector3());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Ref<Mesh> mesh = surface_tool->commit();
|
||||
|
||||
Ref<FixedMaterial> mat_aabb( memnew( FixedMaterial ));
|
||||
|
||||
mat_aabb->set_parameter( FixedMaterial::PARAM_DIFFUSE,Color(0.8,0.8,0.9,0.7) );
|
||||
mat_aabb->set_line_width(3);
|
||||
mat_aabb->set_flag( Material::FLAG_UNSHADED, true );
|
||||
|
||||
surface_tool->begin(Mesh::PRIMITIVE_LINES);
|
||||
surface_tool->set_material(mat_aabb);
|
||||
|
||||
for(int i=0;i<12;i++) {
|
||||
|
||||
Vector3 f,t;
|
||||
visibility_aabb.get_edge(i,f,t);
|
||||
surface_tool->add_vertex(f);
|
||||
surface_tool->add_vertex(t);
|
||||
}
|
||||
|
||||
return surface_tool->commit(mesh);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Particles::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_amount","amount"),&Particles::set_amount);
|
||||
ObjectTypeDB::bind_method(_MD("get_amount"),&Particles::get_amount);
|
||||
ObjectTypeDB::bind_method(_MD("set_emitting","enabled"),&Particles::set_emitting);
|
||||
ObjectTypeDB::bind_method(_MD("is_emitting"),&Particles::is_emitting);
|
||||
ObjectTypeDB::bind_method(_MD("set_visibility_aabb","aabb"),&Particles::set_visibility_aabb);
|
||||
ObjectTypeDB::bind_method(_MD("get_visibility_aabb"),&Particles::get_visibility_aabb);
|
||||
ObjectTypeDB::bind_method(_MD("set_emission_half_extents","half_extents"),&Particles::set_emission_half_extents);
|
||||
ObjectTypeDB::bind_method(_MD("get_emission_half_extents"),&Particles::get_emission_half_extents);
|
||||
ObjectTypeDB::bind_method(_MD("set_emission_base_velocity","base_velocity"),&Particles::set_emission_base_velocity);
|
||||
ObjectTypeDB::bind_method(_MD("get_emission_base_velocity"),&Particles::get_emission_base_velocity);
|
||||
ObjectTypeDB::bind_method(_MD("set_emission_points","points"),&Particles::set_emission_points);
|
||||
ObjectTypeDB::bind_method(_MD("get_emission_points"),&Particles::get_emission_points);
|
||||
ObjectTypeDB::bind_method(_MD("set_gravity_normal","normal"),&Particles::set_gravity_normal);
|
||||
ObjectTypeDB::bind_method(_MD("get_gravity_normal"),&Particles::get_gravity_normal);
|
||||
ObjectTypeDB::bind_method(_MD("set_variable","variable","value"),&Particles::set_variable);
|
||||
ObjectTypeDB::bind_method(_MD("get_variable","variable"),&Particles::get_variable);
|
||||
ObjectTypeDB::bind_method(_MD("set_randomness","variable","randomness"),&Particles::set_randomness);
|
||||
ObjectTypeDB::bind_method(_MD("get_randomness"),&Particles::get_randomness);
|
||||
ObjectTypeDB::bind_method(_MD("set_color_phase_pos","phase","pos"),&Particles::set_color_phase_pos);
|
||||
ObjectTypeDB::bind_method(_MD("get_color_phase_pos","phase"),&Particles::get_color_phase_pos);
|
||||
ObjectTypeDB::bind_method(_MD("set_color_phase_color","phase","color"),&Particles::set_color_phase_color);
|
||||
ObjectTypeDB::bind_method(_MD("get_color_phase_color","phase"),&Particles::get_color_phase_color);
|
||||
ObjectTypeDB::bind_method(_MD("set_material","material:Material"),&Particles::set_material);
|
||||
ObjectTypeDB::bind_method(_MD("get_material:Material"),&Particles::get_material);
|
||||
ObjectTypeDB::bind_method(_MD("set_emit_timeout"),&Particles::set_emit_timeout);
|
||||
ObjectTypeDB::bind_method(_MD("get_emit_timeout"),&Particles::get_emit_timeout);
|
||||
ObjectTypeDB::bind_method(_MD("set_height_from_velocity","enable"),&Particles::set_height_from_velocity);
|
||||
ObjectTypeDB::bind_method(_MD("has_height_from_velocity"),&Particles::has_height_from_velocity);
|
||||
ObjectTypeDB::bind_method(_MD("set_use_local_coordinates","enable"),&Particles::set_use_local_coordinates);
|
||||
ObjectTypeDB::bind_method(_MD("is_using_local_coordinates"),&Particles::is_using_local_coordinates);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_color_phases","count"),&Particles::set_color_phases);
|
||||
ObjectTypeDB::bind_method(_MD("get_color_phases"),&Particles::get_color_phases);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "Material" ), _SCS("set_material"), _SCS("get_material") );
|
||||
|
||||
ADD_PROPERTY( PropertyInfo( Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,4096,1" ), _SCS("set_amount"), _SCS("get_amount") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "emitting" ), _SCS("set_emitting"), _SCS("is_emitting") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::_AABB, "visibility" ), _SCS("set_visibility_aabb"), _SCS("get_visibility_aabb") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::VECTOR3, "emission_extents" ), _SCS("set_emission_half_extents"), _SCS("get_emission_half_extents") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::VECTOR3, "emission_base_velocity" ), _SCS("set_emission_base_velocity"), _SCS("get_emission_base_velocity") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::VECTOR3_ARRAY, "emission_points" ), _SCS("set_emission_points"), _SCS("get_emission_points") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::VECTOR3, "gravity_normal" ), _SCS("set_gravity_normal"), _SCS("get_gravity_normal") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "local_coords" ), _SCS("set_use_local_coordinates"), _SCS("is_using_local_coordinates") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "emit_timeout",PROPERTY_HINT_RANGE,"0,256,0.01"), _SCS("set_emit_timeout"), _SCS("get_emit_timeout") );
|
||||
|
||||
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/lifetime", PROPERTY_HINT_RANGE,"0.1,60,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_LIFETIME );
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/spread", PROPERTY_HINT_RANGE,"0,1,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_SPREAD );
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/gravity", PROPERTY_HINT_RANGE,"-48,48,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_GRAVITY );
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/linear_vel", PROPERTY_HINT_RANGE,"-100,100,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_LINEAR_VELOCITY );
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/angular_vel", PROPERTY_HINT_RANGE,"-100,100,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_ANGULAR_VELOCITY );
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/linear_accel", PROPERTY_HINT_RANGE,"-100,100,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_LINEAR_ACCELERATION );
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/radial_accel", PROPERTY_HINT_RANGE,"-100,100,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_DRAG );
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/tan_accel", PROPERTY_HINT_RANGE,"-100,100,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_TANGENTIAL_ACCELERATION );
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/damping", PROPERTY_HINT_RANGE,"0,128,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_DAMPING );
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/initial_size", PROPERTY_HINT_RANGE,"0,100,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_INITIAL_SIZE );
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/final_size", PROPERTY_HINT_RANGE,"0,100,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_FINAL_SIZE );
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/initial_angle",PROPERTY_HINT_RANGE,"0,1,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_INITIAL_ANGLE );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "vars/height_from_velocity"), _SCS("set_height_from_velocity"), _SCS("has_height_from_velocity") );
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/height",PROPERTY_HINT_RANGE,"0,4096,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_HEIGHT);
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/height_speed_scale",PROPERTY_HINT_RANGE,"0,4096,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_HEIGHT_SPEED_SCALE );
|
||||
|
||||
for(int i=0;i<VAR_MAX;i++)
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, _rand_names[i], PROPERTY_HINT_RANGE,"-16.0,16.0,0.01"),_SCS("set_randomness"), _SCS("get_randomness"),_var_indices[i] );
|
||||
|
||||
|
||||
ADD_PROPERTY( PropertyInfo( Variant::INT, "color_phases/count",PROPERTY_HINT_RANGE,"0,4,1"), _SCS("set_color_phases"), _SCS("get_color_phases"));
|
||||
|
||||
for(int i=0;i<VS::MAX_PARTICLE_COLOR_PHASES;i++) {
|
||||
String phase="phase_"+itos(i)+"/";
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, phase+"pos", PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_color_phase_pos"),_SCS("get_color_phase_pos"),i );
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::COLOR, phase+"color"),_SCS("set_color_phase_color"),_SCS("get_color_phase_color"),i );
|
||||
}
|
||||
|
||||
BIND_CONSTANT( VAR_LIFETIME );
|
||||
BIND_CONSTANT( VAR_SPREAD );
|
||||
BIND_CONSTANT( VAR_GRAVITY );
|
||||
BIND_CONSTANT( VAR_LINEAR_VELOCITY );
|
||||
BIND_CONSTANT( VAR_ANGULAR_VELOCITY );
|
||||
BIND_CONSTANT( VAR_LINEAR_ACCELERATION );
|
||||
BIND_CONSTANT( VAR_DRAG );
|
||||
BIND_CONSTANT( VAR_TANGENTIAL_ACCELERATION );
|
||||
BIND_CONSTANT( VAR_INITIAL_SIZE );
|
||||
BIND_CONSTANT( VAR_FINAL_SIZE );
|
||||
BIND_CONSTANT( VAR_INITIAL_ANGLE );
|
||||
BIND_CONSTANT( VAR_HEIGHT );
|
||||
BIND_CONSTANT( VAR_HEIGHT_SPEED_SCALE );
|
||||
BIND_CONSTANT( VAR_MAX );
|
||||
|
||||
}
|
||||
|
||||
Particles::Particles() {
|
||||
|
||||
particles = VisualServer::get_singleton()->particles_create();
|
||||
timer = memnew(Timer);
|
||||
add_child(timer);
|
||||
emit_timeout = 0;
|
||||
|
||||
set_amount(64);
|
||||
set_emitting(true);
|
||||
set_visibility_aabb(AABB( Vector3(-4,-4,-4), Vector3(8,8,8) ) );
|
||||
|
||||
for (int i=0;i<VAR_MAX;i++) {
|
||||
set_randomness((Variable)i,0.0);
|
||||
}
|
||||
|
||||
set_variable( VAR_LIFETIME, 5.0);
|
||||
set_variable( VAR_SPREAD, 0.2);
|
||||
set_variable( VAR_GRAVITY, 9.8);
|
||||
set_variable( VAR_LINEAR_VELOCITY, 0.2);
|
||||
set_variable( VAR_ANGULAR_VELOCITY, 0.0);
|
||||
set_variable( VAR_LINEAR_ACCELERATION, 0.0);
|
||||
set_variable( VAR_DRAG, 0.0);
|
||||
set_variable( VAR_TANGENTIAL_ACCELERATION, 0.0);
|
||||
set_variable( VAR_DAMPING, 0.0);
|
||||
set_variable( VAR_INITIAL_SIZE, 1.0);
|
||||
set_variable( VAR_FINAL_SIZE, 1.0);
|
||||
set_variable( VAR_INITIAL_ANGLE, 0.0);
|
||||
set_variable( VAR_HEIGHT, 1.0);
|
||||
set_variable( VAR_HEIGHT_SPEED_SCALE, 0.0);
|
||||
|
||||
color_phase_count=0;
|
||||
|
||||
set_color_phase_pos(0,0.0);
|
||||
set_color_phase_pos(1,1.0);
|
||||
set_color_phase_pos(2,1.0);
|
||||
set_color_phase_pos(3,1.0);
|
||||
|
||||
set_color_phase_color(0,Color(1,1,1));
|
||||
set_color_phase_color(1,Color(0,0,0));
|
||||
set_color_phase_color(2,Color(0,0,0));
|
||||
set_color_phase_color(3,Color(0,0,0));
|
||||
|
||||
set_gravity_normal(Vector3(0,-1.0,0));
|
||||
set_emission_half_extents(Vector3(0.1,0.1,0.1));
|
||||
|
||||
height_from_velocity=false;
|
||||
|
||||
Vector<Variant> pars;
|
||||
pars.push_back(false);
|
||||
timer->connect("timeout", this, "set_emitting", pars);
|
||||
set_base(particles);
|
||||
local_coordinates=false;
|
||||
}
|
||||
|
||||
|
||||
Particles::~Particles() {
|
||||
|
||||
VisualServer::get_singleton()->free(particles);
|
||||
}
|
||||
|
||||
165
scene/3d/particles.h
Normal file
165
scene/3d/particles.h
Normal file
@ -0,0 +1,165 @@
|
||||
/*************************************************************************/
|
||||
/* particles.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef VISUALINSTANCEPARTICLES_H
|
||||
#define VISUALINSTANCEPARTICLES_H
|
||||
|
||||
#include "scene/3d/visual_instance.h"
|
||||
#include "scene/resources/material.h"
|
||||
#include "scene/main/timer.h"
|
||||
#include "rid.h"
|
||||
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
|
||||
class Particles : public GeometryInstance {
|
||||
public:
|
||||
|
||||
enum Variable {
|
||||
VAR_LIFETIME=VS::PARTICLE_LIFETIME,
|
||||
VAR_SPREAD=VS::PARTICLE_SPREAD,
|
||||
VAR_GRAVITY=VS::PARTICLE_GRAVITY,
|
||||
VAR_LINEAR_VELOCITY=VS::PARTICLE_LINEAR_VELOCITY,
|
||||
VAR_ANGULAR_VELOCITY=VS::PARTICLE_ANGULAR_VELOCITY,
|
||||
VAR_LINEAR_ACCELERATION=VS::PARTICLE_LINEAR_ACCELERATION,
|
||||
VAR_DRAG=VS::PARTICLE_RADIAL_ACCELERATION,
|
||||
VAR_TANGENTIAL_ACCELERATION=VS::PARTICLE_TANGENTIAL_ACCELERATION,
|
||||
VAR_DAMPING=VS::PARTICLE_DAMPING,
|
||||
VAR_INITIAL_SIZE=VS::PARTICLE_INITIAL_SIZE,
|
||||
VAR_FINAL_SIZE=VS::PARTICLE_FINAL_SIZE,
|
||||
VAR_INITIAL_ANGLE=VS::PARTICLE_INITIAL_ANGLE,
|
||||
VAR_HEIGHT=VS::PARTICLE_HEIGHT,
|
||||
VAR_HEIGHT_SPEED_SCALE=VS::PARTICLE_HEIGHT_SPEED_SCALE,
|
||||
VAR_MAX=VS::PARTICLE_VAR_MAX
|
||||
};
|
||||
|
||||
private:
|
||||
OBJ_TYPE( Particles, GeometryInstance );
|
||||
|
||||
RID particles;
|
||||
|
||||
int amount;
|
||||
bool emitting;
|
||||
float emit_timeout;
|
||||
AABB visibility_aabb;
|
||||
Vector3 gravity_normal;
|
||||
Vector3 emission_half_extents;
|
||||
bool using_points;
|
||||
float var[VAR_MAX];
|
||||
float var_random[VAR_MAX];
|
||||
bool height_from_velocity;
|
||||
Vector3 emission_base_velocity;
|
||||
bool local_coordinates;
|
||||
|
||||
struct ColorPhase {
|
||||
|
||||
Color color;
|
||||
float pos;
|
||||
};
|
||||
|
||||
virtual bool _can_gizmo_scale() const;
|
||||
virtual RES _get_gizmo_geometry() const;
|
||||
|
||||
int color_phase_count;
|
||||
|
||||
ColorPhase color_phase[4];
|
||||
|
||||
Ref<Material> material;
|
||||
|
||||
Timer* timer;
|
||||
void setup_timer();
|
||||
|
||||
protected:
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
|
||||
AABB get_aabb() const;
|
||||
DVector<Face3> get_faces(uint32_t p_usage_flags) const;
|
||||
|
||||
void set_amount(int p_amount);
|
||||
int get_amount() const;
|
||||
|
||||
void set_emitting(bool p_emitting);
|
||||
bool is_emitting() const;
|
||||
|
||||
void set_visibility_aabb(const AABB& p_aabb);
|
||||
AABB get_visibility_aabb() const;
|
||||
|
||||
void set_emission_half_extents(const Vector3& p_half_extents);
|
||||
Vector3 get_emission_half_extents() const;
|
||||
|
||||
void set_emission_base_velocity(const Vector3& p_base_velocity);
|
||||
Vector3 get_emission_base_velocity() const;
|
||||
|
||||
void set_emission_points(const DVector<Vector3>& p_points);
|
||||
DVector<Vector3> get_emission_points() const;
|
||||
|
||||
void set_gravity_normal(const Vector3& p_normal);
|
||||
Vector3 get_gravity_normal() const;
|
||||
|
||||
void set_variable(Variable p_variable,float p_value);
|
||||
float get_variable(Variable p_variable) const;
|
||||
|
||||
void set_randomness(Variable p_variable,float p_randomness);
|
||||
float get_randomness(Variable p_variable) const;
|
||||
|
||||
void set_color_phases(int p_phases);
|
||||
int get_color_phases() const;
|
||||
|
||||
void set_color_phase_pos(int p_phase, float p_pos);
|
||||
float get_color_phase_pos(int p_phase) const;
|
||||
|
||||
void set_color_phase_color(int p_phase, const Color& p_color);
|
||||
Color get_color_phase_color(int p_phase) const;
|
||||
|
||||
void set_height_from_velocity(bool p_enable);
|
||||
bool has_height_from_velocity() const;
|
||||
|
||||
void set_material(const Ref<Material>& p_material);
|
||||
Ref<Material> get_material() const;
|
||||
|
||||
void set_emit_timeout(float p_timeout);
|
||||
float get_emit_timeout() const;
|
||||
|
||||
void set_use_local_coordinates(bool p_use);
|
||||
bool is_using_local_coordinates() const;
|
||||
|
||||
void start_emitting(float p_time);
|
||||
|
||||
|
||||
Particles();
|
||||
~Particles();
|
||||
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST( Particles::Variable );
|
||||
#endif
|
||||
388
scene/3d/path.cpp
Normal file
388
scene/3d/path.cpp
Normal file
@ -0,0 +1,388 @@
|
||||
/*************************************************************************/
|
||||
/* path.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "path.h"
|
||||
#include "scene/scene_string_names.h"
|
||||
|
||||
void Path::_notification(int p_what) {
|
||||
#if 0
|
||||
if (p_what==NOTIFICATION_DRAW && curve.is_valid() && is_inside_scene() && get_scene()->is_editor_hint()) {
|
||||
//draw the curve!!
|
||||
|
||||
for(int i=0;i<curve->get_point_count();i++) {
|
||||
|
||||
Vector2 prev_p=curve->get_point_pos(i);
|
||||
|
||||
for(int j=1;j<=8;j++) {
|
||||
|
||||
real_t frac = j/8.0;
|
||||
Vector2 p = curve->interpolate(i,frac);
|
||||
draw_line(prev_p,p,Color(0.5,0.6,1.0,0.7),2);
|
||||
prev_p=p;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Path::_curve_changed() {
|
||||
|
||||
|
||||
if (is_inside_scene() && get_scene()->is_editor_hint())
|
||||
update_gizmo();
|
||||
}
|
||||
|
||||
|
||||
void Path::set_curve(const Ref<Curve3D>& p_curve) {
|
||||
|
||||
if (curve.is_valid()) {
|
||||
curve->disconnect("changed",this,"_curve_changed");
|
||||
}
|
||||
|
||||
curve=p_curve;
|
||||
|
||||
if (curve.is_valid()) {
|
||||
curve->connect("changed",this,"_curve_changed");
|
||||
}
|
||||
_curve_changed();
|
||||
|
||||
}
|
||||
|
||||
Ref<Curve3D> Path::get_curve() const{
|
||||
|
||||
return curve;
|
||||
}
|
||||
|
||||
void Path::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_curve","curve:Curve3D"),&Path::set_curve);
|
||||
ObjectTypeDB::bind_method(_MD("get_curve:Curve3D","curve"),&Path::get_curve);
|
||||
ObjectTypeDB::bind_method(_MD("_curve_changed"),&Path::_curve_changed);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve3D"), _SCS("set_curve"),_SCS("get_curve"));
|
||||
}
|
||||
|
||||
Path::Path() {
|
||||
|
||||
set_curve(Ref<Curve3D>( memnew( Curve3D ))); //create one by default
|
||||
}
|
||||
|
||||
|
||||
//////////////
|
||||
|
||||
|
||||
void PathFollow::_update_transform() {
|
||||
|
||||
|
||||
if (!path)
|
||||
return;
|
||||
|
||||
Ref<Curve3D> c =path->get_curve();
|
||||
if (!c.is_valid())
|
||||
return;
|
||||
|
||||
|
||||
float o = offset;
|
||||
if (loop)
|
||||
o=Math::fposmod(o,c->get_baked_length());
|
||||
|
||||
Vector3 pos = c->interpolate_baked(o,cubic);
|
||||
Transform t=get_transform();
|
||||
|
||||
|
||||
if (rotation_mode!=ROTATION_NONE) {
|
||||
|
||||
Vector3 n = (c->interpolate_baked(o+lookahead,cubic)-pos).normalized();
|
||||
|
||||
if (rotation_mode==ROTATION_Y) {
|
||||
|
||||
n.y=0;
|
||||
n.normalize();
|
||||
}
|
||||
|
||||
if (n.length()<CMP_EPSILON) {//nothing, use previous
|
||||
n=-t.get_basis().get_axis(2).normalized();
|
||||
}
|
||||
|
||||
|
||||
Vector3 up = Vector3(0,1,0);
|
||||
|
||||
if (rotation_mode==ROTATION_XYZ) {
|
||||
|
||||
float tilt = c->interpolate_baked_tilt(o);
|
||||
if (tilt!=0) {
|
||||
|
||||
Matrix3 rot(-n,tilt); //remember.. lookat will be znegative.. znegative!! we abide by opengl clan.
|
||||
up=rot.xform(up);
|
||||
}
|
||||
}
|
||||
|
||||
t.set_look_at(pos,pos+n,up);
|
||||
|
||||
} else {
|
||||
|
||||
t.origin=pos;
|
||||
}
|
||||
|
||||
t.origin+=t.basis.get_axis(0)*h_offset + t.basis.get_axis(1)*v_offset;
|
||||
set_transform(t);
|
||||
|
||||
}
|
||||
|
||||
void PathFollow::_notification(int p_what) {
|
||||
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_ENTER_SCENE: {
|
||||
|
||||
Node *parent=get_parent();
|
||||
if (parent) {
|
||||
|
||||
path=parent->cast_to<Path>();
|
||||
if (path) {
|
||||
_update_transform();
|
||||
}
|
||||
}
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_SCENE: {
|
||||
|
||||
|
||||
path=NULL;
|
||||
} break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void PathFollow::set_cubic_interpolation(bool p_enable) {
|
||||
|
||||
cubic=p_enable;
|
||||
}
|
||||
|
||||
bool PathFollow::get_cubic_interpolation() const {
|
||||
|
||||
return cubic;
|
||||
}
|
||||
|
||||
|
||||
bool PathFollow::_set(const StringName& p_name, const Variant& p_value) {
|
||||
|
||||
if (p_name==SceneStringNames::get_singleton()->offset) {
|
||||
set_offset(p_value);
|
||||
} else if (p_name==SceneStringNames::get_singleton()->unit_offset) {
|
||||
set_unit_offset(p_value);
|
||||
} else if (p_name==SceneStringNames::get_singleton()->rotation_mode) {
|
||||
set_rotation_mode(RotationMode(p_value.operator int()));
|
||||
} else if (p_name==SceneStringNames::get_singleton()->v_offset) {
|
||||
set_v_offset(p_value);
|
||||
} else if (p_name==SceneStringNames::get_singleton()->h_offset) {
|
||||
set_h_offset(p_value);
|
||||
} else if (String(p_name)=="cubic_interp") {
|
||||
set_cubic_interpolation(p_value);
|
||||
} else if (String(p_name)=="loop") {
|
||||
set_loop(p_value);
|
||||
} else if (String(p_name)=="lookahead") {
|
||||
set_lookahead(p_value);
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PathFollow::_get(const StringName& p_name,Variant &r_ret) const{
|
||||
|
||||
if (p_name==SceneStringNames::get_singleton()->offset) {
|
||||
r_ret=get_offset();
|
||||
} else if (p_name==SceneStringNames::get_singleton()->unit_offset) {
|
||||
r_ret=get_unit_offset();
|
||||
} else if (p_name==SceneStringNames::get_singleton()->rotation_mode) {
|
||||
r_ret=get_rotation_mode();
|
||||
} else if (p_name==SceneStringNames::get_singleton()->v_offset) {
|
||||
r_ret=get_v_offset();
|
||||
} else if (p_name==SceneStringNames::get_singleton()->h_offset) {
|
||||
r_ret=get_h_offset();
|
||||
} else if (String(p_name)=="cubic_interp") {
|
||||
r_ret=cubic;
|
||||
} else if (String(p_name)=="loop") {
|
||||
r_ret=loop;
|
||||
} else if (String(p_name)=="lookahead") {
|
||||
r_ret=lookahead;
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
void PathFollow::_get_property_list( List<PropertyInfo> *p_list) const{
|
||||
|
||||
float max=10000;
|
||||
if (path && path->get_curve().is_valid())
|
||||
max=path->get_curve()->get_baked_length();
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "offset", PROPERTY_HINT_RANGE,"0,"+rtos(max)+",0.01"));
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "unit_offset", PROPERTY_HINT_RANGE,"0,1,0.0001",PROPERTY_USAGE_EDITOR));
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "h_offset") );
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "v_offset") );
|
||||
p_list->push_back( PropertyInfo( Variant::INT, "rotation_mode", PROPERTY_HINT_ENUM,"None,Y,XY,XYZ"));
|
||||
p_list->push_back( PropertyInfo( Variant::BOOL, "cubic_interp"));
|
||||
p_list->push_back( PropertyInfo( Variant::BOOL, "loop"));
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "lookahead",PROPERTY_HINT_RANGE,"0.001,1024.0,0.001"));
|
||||
}
|
||||
|
||||
|
||||
void PathFollow::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_offset","offset"),&PathFollow::set_offset);
|
||||
ObjectTypeDB::bind_method(_MD("get_offset"),&PathFollow::get_offset);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_h_offset","h_offset"),&PathFollow::set_h_offset);
|
||||
ObjectTypeDB::bind_method(_MD("get_h_offset"),&PathFollow::get_h_offset);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_v_offset","v_offset"),&PathFollow::set_v_offset);
|
||||
ObjectTypeDB::bind_method(_MD("get_v_offset"),&PathFollow::get_v_offset);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_unit_offset","unit_offset"),&PathFollow::set_unit_offset);
|
||||
ObjectTypeDB::bind_method(_MD("get_unit_offset"),&PathFollow::get_unit_offset);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_rotation_mode","rotation_mode"),&PathFollow::set_rotation_mode);
|
||||
ObjectTypeDB::bind_method(_MD("get_rotation_mode"),&PathFollow::get_rotation_mode);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_cubic_interpolation","enable"),&PathFollow::set_cubic_interpolation);
|
||||
ObjectTypeDB::bind_method(_MD("get_cubic_interpolation"),&PathFollow::get_cubic_interpolation);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_loop","loop"),&PathFollow::set_loop);
|
||||
ObjectTypeDB::bind_method(_MD("has_loop"),&PathFollow::has_loop);
|
||||
|
||||
BIND_CONSTANT( ROTATION_NONE );
|
||||
BIND_CONSTANT( ROTATION_Y );
|
||||
BIND_CONSTANT( ROTATION_XY );
|
||||
BIND_CONSTANT( ROTATION_XYZ );
|
||||
|
||||
}
|
||||
|
||||
void PathFollow::set_offset(float p_offset) {
|
||||
|
||||
offset=p_offset;
|
||||
if (path)
|
||||
_update_transform();
|
||||
_change_notify("offset");
|
||||
_change_notify("unit_offset");
|
||||
|
||||
}
|
||||
|
||||
void PathFollow::set_h_offset(float p_h_offset) {
|
||||
|
||||
h_offset=p_h_offset;
|
||||
if (path)
|
||||
_update_transform();
|
||||
|
||||
}
|
||||
|
||||
float PathFollow::get_h_offset() const {
|
||||
|
||||
return h_offset;
|
||||
}
|
||||
|
||||
void PathFollow::set_v_offset(float p_v_offset) {
|
||||
|
||||
v_offset=p_v_offset;
|
||||
if (path)
|
||||
_update_transform();
|
||||
|
||||
}
|
||||
|
||||
float PathFollow::get_v_offset() const {
|
||||
|
||||
return v_offset;
|
||||
}
|
||||
|
||||
|
||||
float PathFollow::get_offset() const{
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
void PathFollow::set_unit_offset(float p_unit_offset) {
|
||||
|
||||
if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length())
|
||||
set_offset(p_unit_offset*path->get_curve()->get_baked_length());
|
||||
|
||||
}
|
||||
|
||||
float PathFollow::get_unit_offset() const{
|
||||
|
||||
if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length())
|
||||
return get_offset()/path->get_curve()->get_baked_length();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PathFollow::set_lookahead(float p_lookahead) {
|
||||
|
||||
lookahead=p_lookahead;
|
||||
|
||||
}
|
||||
|
||||
float PathFollow::get_lookahead() const{
|
||||
|
||||
return lookahead;
|
||||
}
|
||||
|
||||
void PathFollow::set_rotation_mode(RotationMode p_rotation_mode) {
|
||||
|
||||
rotation_mode=p_rotation_mode;
|
||||
_update_transform();
|
||||
}
|
||||
|
||||
PathFollow::RotationMode PathFollow::get_rotation_mode() const {
|
||||
|
||||
return rotation_mode;
|
||||
}
|
||||
|
||||
void PathFollow::set_loop(bool p_loop) {
|
||||
|
||||
loop=p_loop;
|
||||
}
|
||||
|
||||
bool PathFollow::has_loop() const{
|
||||
|
||||
return loop;
|
||||
}
|
||||
|
||||
|
||||
PathFollow::PathFollow() {
|
||||
|
||||
offset=0;
|
||||
h_offset=0;
|
||||
v_offset=0;
|
||||
path=NULL;
|
||||
rotation_mode=ROTATION_XYZ;
|
||||
cubic=true;
|
||||
loop=true;
|
||||
lookahead=0.1;
|
||||
}
|
||||
122
scene/3d/path.h
Normal file
122
scene/3d/path.h
Normal file
@ -0,0 +1,122 @@
|
||||
/*************************************************************************/
|
||||
/* path.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef PATH_H
|
||||
#define PATH_H
|
||||
|
||||
#include "scene/resources/curve.h"
|
||||
#include "scene/3d/spatial.h"
|
||||
|
||||
class Path : public Spatial {
|
||||
|
||||
OBJ_TYPE( Path, Spatial );
|
||||
|
||||
Ref<Curve3D> curve;
|
||||
|
||||
void _curve_changed();
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_curve(const Ref<Curve3D>& p_curve);
|
||||
Ref<Curve3D> get_curve() const;
|
||||
|
||||
|
||||
Path();
|
||||
};
|
||||
|
||||
class PathFollow : public Spatial {
|
||||
|
||||
OBJ_TYPE(PathFollow,Spatial);
|
||||
public:
|
||||
|
||||
enum RotationMode {
|
||||
|
||||
ROTATION_NONE,
|
||||
ROTATION_Y,
|
||||
ROTATION_XY,
|
||||
ROTATION_XYZ
|
||||
};
|
||||
|
||||
private:
|
||||
Path *path;
|
||||
real_t offset;
|
||||
real_t h_offset;
|
||||
real_t v_offset;
|
||||
real_t lookahead;
|
||||
bool cubic;
|
||||
bool loop;
|
||||
RotationMode rotation_mode;
|
||||
|
||||
void _update_transform();
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
bool _set(const StringName& p_name, const Variant& p_value);
|
||||
bool _get(const StringName& p_name,Variant &r_ret) const;
|
||||
void _get_property_list( List<PropertyInfo> *p_list) const;
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_offset(float p_offset);
|
||||
float get_offset() const;
|
||||
|
||||
void set_h_offset(float p_h_offset);
|
||||
float get_h_offset() const;
|
||||
|
||||
void set_v_offset(float p_v_offset);
|
||||
float get_v_offset() const;
|
||||
|
||||
void set_unit_offset(float p_unit_offset);
|
||||
float get_unit_offset() const;
|
||||
|
||||
void set_lookahead(float p_lookahead);
|
||||
float get_lookahead() const;
|
||||
|
||||
void set_loop(bool p_loop);
|
||||
bool has_loop() const;
|
||||
|
||||
void set_rotation_mode(RotationMode p_rotation_mode);
|
||||
RotationMode get_rotation_mode() const;
|
||||
|
||||
void set_cubic_interpolation(bool p_enable);
|
||||
bool get_cubic_interpolation() const;
|
||||
|
||||
PathFollow();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(PathFollow::RotationMode);
|
||||
|
||||
#endif // PATH_H
|
||||
741
scene/3d/physics_body.cpp
Normal file
741
scene/3d/physics_body.cpp
Normal file
@ -0,0 +1,741 @@
|
||||
/*************************************************************************/
|
||||
/* physics_body.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "physics_body.h"
|
||||
#include "scene/scene_string_names.h"
|
||||
|
||||
void PhysicsBody::_notification(int p_what) {
|
||||
|
||||
/*
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
|
||||
PhysicsServer::get_singleton()->body_set_state(get_rid(),PhysicsServer::BODY_STATE_TRANSFORM,get_global_transform());
|
||||
|
||||
} break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
PhysicsBody::PhysicsBody(PhysicsServer::BodyMode p_mode) : CollisionObject( PhysicsServer::get_singleton()->body_create(p_mode), false) {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void StaticBody::set_constant_linear_velocity(const Vector3& p_vel) {
|
||||
|
||||
constant_linear_velocity=p_vel;
|
||||
PhysicsServer::get_singleton()->body_set_state(get_rid(),PhysicsServer::BODY_STATE_LINEAR_VELOCITY,constant_linear_velocity);
|
||||
|
||||
}
|
||||
|
||||
void StaticBody::set_constant_angular_velocity(const Vector3& p_vel) {
|
||||
|
||||
constant_angular_velocity=p_vel;
|
||||
PhysicsServer::get_singleton()->body_set_state(get_rid(),PhysicsServer::BODY_STATE_ANGULAR_VELOCITY,constant_angular_velocity);
|
||||
}
|
||||
|
||||
Vector3 StaticBody::get_constant_linear_velocity() const {
|
||||
|
||||
return constant_linear_velocity;
|
||||
}
|
||||
Vector3 StaticBody::get_constant_angular_velocity() const {
|
||||
|
||||
return constant_angular_velocity;
|
||||
}
|
||||
|
||||
|
||||
void StaticBody::_state_notify(Object *p_object) {
|
||||
|
||||
if (!pre_xform)
|
||||
return;
|
||||
|
||||
PhysicsDirectBodyState *p2d = (PhysicsDirectBodyState*)p_object;
|
||||
setting=true;
|
||||
|
||||
Transform new_xform = p2d->get_transform();
|
||||
*pre_xform=new_xform;
|
||||
set_ignore_transform_notification(true);
|
||||
set_global_transform(new_xform);
|
||||
set_ignore_transform_notification(false);
|
||||
|
||||
setting=false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void StaticBody::_update_xform() {
|
||||
|
||||
if (!pre_xform || !pending)
|
||||
return;
|
||||
|
||||
setting=true;
|
||||
|
||||
|
||||
Transform new_xform = get_global_transform(); //obtain the new one
|
||||
|
||||
//set_block_transform_notify(true);
|
||||
set_ignore_transform_notification(true);
|
||||
PhysicsServer::get_singleton()->body_set_state(get_rid(),PhysicsServer::BODY_STATE_TRANSFORM,*pre_xform); //then simulate motion!
|
||||
set_global_transform(*pre_xform); //but restore state to previous one in both visual and physics
|
||||
set_ignore_transform_notification(false);
|
||||
|
||||
PhysicsServer::get_singleton()->body_static_simulate_motion(get_rid(),new_xform); //then simulate motion!
|
||||
|
||||
setting=false;
|
||||
pending=false;
|
||||
|
||||
}
|
||||
|
||||
void StaticBody::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_ENTER_SCENE: {
|
||||
|
||||
if (pre_xform)
|
||||
*pre_xform = get_global_transform();
|
||||
pending=false;
|
||||
} break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
|
||||
if (simulating_motion && !pending && is_inside_scene() && !setting && !get_scene()->is_editor_hint()) {
|
||||
|
||||
call_deferred(SceneStringNames::get_singleton()->_update_xform);
|
||||
pending=true;
|
||||
}
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void StaticBody::set_simulate_motion(bool p_enable) {
|
||||
|
||||
if (p_enable==simulating_motion)
|
||||
return;
|
||||
simulating_motion=p_enable;
|
||||
|
||||
if (p_enable) {
|
||||
pre_xform = memnew( Transform );
|
||||
if (is_inside_scene())
|
||||
*pre_xform=get_transform();
|
||||
// query = PhysicsServer::get_singleton()->query_create(this,"_state_notify",Variant());
|
||||
// PhysicsServer::get_singleton()->query_body_direct_state(query,get_rid());
|
||||
PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(),this,"_state_notify");
|
||||
|
||||
} else {
|
||||
memdelete( pre_xform );
|
||||
pre_xform=NULL;
|
||||
PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(),NULL,StringName());
|
||||
pending=false;
|
||||
}
|
||||
}
|
||||
|
||||
bool StaticBody::is_simulating_motion() const {
|
||||
|
||||
return simulating_motion;
|
||||
}
|
||||
|
||||
void StaticBody::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_simulate_motion","enabled"),&StaticBody::set_simulate_motion);
|
||||
ObjectTypeDB::bind_method(_MD("is_simulating_motion"),&StaticBody::is_simulating_motion);
|
||||
ObjectTypeDB::bind_method(_MD("_update_xform"),&StaticBody::_update_xform);
|
||||
ObjectTypeDB::bind_method(_MD("_state_notify"),&StaticBody::_state_notify);
|
||||
ObjectTypeDB::bind_method(_MD("set_constant_linear_velocity","vel"),&StaticBody::set_constant_linear_velocity);
|
||||
ObjectTypeDB::bind_method(_MD("set_constant_angular_velocity","vel"),&StaticBody::set_constant_angular_velocity);
|
||||
ObjectTypeDB::bind_method(_MD("get_constant_linear_velocity"),&StaticBody::get_constant_linear_velocity);
|
||||
ObjectTypeDB::bind_method(_MD("get_constant_angular_velocity"),&StaticBody::get_constant_angular_velocity);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"simulate_motion"),_SCS("set_simulate_motion"),_SCS("is_simulating_motion"));
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3,"constant_linear_velocity"),_SCS("set_constant_linear_velocity"),_SCS("get_constant_linear_velocity"));
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3,"constant_angular_velocity"),_SCS("set_constant_angular_velocity"),_SCS("get_constant_angular_velocity"));
|
||||
}
|
||||
|
||||
StaticBody::StaticBody() : PhysicsBody(PhysicsServer::BODY_MODE_STATIC) {
|
||||
|
||||
simulating_motion=false;
|
||||
pre_xform=NULL;
|
||||
setting=false;
|
||||
pending=false;
|
||||
//constant_angular_velocity=0;
|
||||
|
||||
}
|
||||
|
||||
StaticBody::~StaticBody() {
|
||||
|
||||
if (pre_xform)
|
||||
memdelete(pre_xform);
|
||||
//if (query.is_valid())
|
||||
// PhysicsServer::get_singleton()->free(query);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void RigidBody::_body_enter_scene(ObjectID p_id) {
|
||||
|
||||
Object *obj = ObjectDB::get_instance(p_id);
|
||||
Node *node = obj ? obj->cast_to<Node>() : NULL;
|
||||
ERR_FAIL_COND(!node);
|
||||
|
||||
Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.find(p_id);
|
||||
ERR_FAIL_COND(!E);
|
||||
ERR_FAIL_COND(E->get().in_scene);
|
||||
|
||||
E->get().in_scene=true;
|
||||
emit_signal(SceneStringNames::get_singleton()->body_enter,node);
|
||||
|
||||
for(int i=0;i<E->get().shapes.size();i++) {
|
||||
|
||||
emit_signal(SceneStringNames::get_singleton()->body_enter_shape,p_id,node,E->get().shapes[i].body_shape,E->get().shapes[i].local_shape);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RigidBody::_body_exit_scene(ObjectID p_id) {
|
||||
|
||||
Object *obj = ObjectDB::get_instance(p_id);
|
||||
Node *node = obj ? obj->cast_to<Node>() : NULL;
|
||||
ERR_FAIL_COND(!node);
|
||||
Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.find(p_id);
|
||||
ERR_FAIL_COND(!E);
|
||||
ERR_FAIL_COND(!E->get().in_scene);
|
||||
E->get().in_scene=false;
|
||||
emit_signal(SceneStringNames::get_singleton()->body_exit,node);
|
||||
for(int i=0;i<E->get().shapes.size();i++) {
|
||||
|
||||
emit_signal(SceneStringNames::get_singleton()->body_exit_shape,p_id,node,E->get().shapes[i].body_shape,E->get().shapes[i].local_shape);
|
||||
}
|
||||
}
|
||||
|
||||
void RigidBody::_body_inout(int p_status, ObjectID p_instance, int p_body_shape,int p_local_shape) {
|
||||
|
||||
bool body_in = p_status==1;
|
||||
ObjectID objid=p_instance;
|
||||
|
||||
Object *obj = ObjectDB::get_instance(objid);
|
||||
Node *node = obj ? obj->cast_to<Node>() : NULL;
|
||||
|
||||
Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.find(objid);
|
||||
|
||||
ERR_FAIL_COND(!body_in && !E);
|
||||
|
||||
if (body_in) {
|
||||
if (!E) {
|
||||
|
||||
E = contact_monitor->body_map.insert(objid,BodyState());
|
||||
E->get().rc=0;
|
||||
E->get().in_scene=node && node->is_inside_scene();
|
||||
if (node) {
|
||||
node->connect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene,make_binds(objid));
|
||||
node->connect(SceneStringNames::get_singleton()->exit_scene,this,SceneStringNames::get_singleton()->_body_exit_scene,make_binds(objid));
|
||||
if (E->get().in_scene) {
|
||||
emit_signal(SceneStringNames::get_singleton()->body_enter,node);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
E->get().rc++;
|
||||
if (node)
|
||||
E->get().shapes.insert(ShapePair(p_body_shape,p_local_shape));
|
||||
|
||||
|
||||
if (E->get().in_scene) {
|
||||
emit_signal(SceneStringNames::get_singleton()->body_enter_shape,objid,node,p_body_shape,p_local_shape);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
E->get().rc--;
|
||||
|
||||
if (node)
|
||||
E->get().shapes.erase(ShapePair(p_body_shape,p_local_shape));
|
||||
|
||||
if (E->get().rc==0) {
|
||||
|
||||
if (node) {
|
||||
node->disconnect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene);
|
||||
node->disconnect(SceneStringNames::get_singleton()->exit_scene,this,SceneStringNames::get_singleton()->_body_exit_scene);
|
||||
if (E->get().in_scene)
|
||||
emit_signal(SceneStringNames::get_singleton()->body_exit,obj);
|
||||
|
||||
}
|
||||
|
||||
contact_monitor->body_map.erase(E);
|
||||
}
|
||||
if (node && E->get().in_scene) {
|
||||
emit_signal(SceneStringNames::get_singleton()->body_exit_shape,objid,obj,p_body_shape,p_local_shape);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
struct _RigidBodyInOut {
|
||||
|
||||
ObjectID id;
|
||||
int shape;
|
||||
int local_shape;
|
||||
};
|
||||
|
||||
void RigidBody::_direct_state_changed(Object *p_state) {
|
||||
|
||||
//eh.. fuck
|
||||
#ifdef DEBUG_ENABLED
|
||||
|
||||
state=p_state->cast_to<PhysicsDirectBodyState>();
|
||||
#else
|
||||
state=(PhysicsDirectBodyState*)p_state; //trust it
|
||||
#endif
|
||||
|
||||
if (contact_monitor) {
|
||||
|
||||
//untag all
|
||||
int rc=0;
|
||||
for( Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.front();E;E=E->next()) {
|
||||
|
||||
for(int i=0;i<E->get().shapes.size();i++) {
|
||||
|
||||
E->get().shapes[i].tagged=false;
|
||||
rc++;
|
||||
}
|
||||
}
|
||||
|
||||
_RigidBodyInOut *toadd=(_RigidBodyInOut*)alloca(state->get_contact_count()*sizeof(_RigidBodyInOut));
|
||||
int toadd_count=0;//state->get_contact_count();
|
||||
RigidBody_RemoveAction *toremove=(RigidBody_RemoveAction*)alloca(rc*sizeof(RigidBody_RemoveAction));
|
||||
int toremove_count=0;
|
||||
|
||||
//put the ones to add
|
||||
|
||||
for(int i=0;i<state->get_contact_count();i++) {
|
||||
|
||||
ObjectID obj = state->get_contact_collider_id(i);
|
||||
int local_shape = state->get_contact_local_shape(i);
|
||||
int shape = state->get_contact_collider_shape(i);
|
||||
toadd[i].local_shape=local_shape;
|
||||
toadd[i].id=obj;
|
||||
toadd[i].shape=shape;
|
||||
|
||||
bool found=false;
|
||||
|
||||
Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.find(obj);
|
||||
if (!E) {
|
||||
toadd_count++;
|
||||
continue;
|
||||
}
|
||||
|
||||
ShapePair sp( shape,local_shape );
|
||||
int idx = E->get().shapes.find(sp);
|
||||
if (idx==-1) {
|
||||
|
||||
toadd_count++;
|
||||
continue;
|
||||
}
|
||||
|
||||
E->get().shapes[idx].tagged=true;
|
||||
}
|
||||
|
||||
//put the ones to remove
|
||||
|
||||
for( Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.front();E;E=E->next()) {
|
||||
|
||||
for(int i=0;i<E->get().shapes.size();i++) {
|
||||
|
||||
if (!E->get().shapes[i].tagged) {
|
||||
|
||||
toremove[toremove_count].body_id=E->key();
|
||||
toremove[toremove_count].pair=E->get().shapes[i];
|
||||
toremove_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//process remotions
|
||||
|
||||
for(int i=0;i<toremove_count;i++) {
|
||||
|
||||
_body_inout(0,toremove[i].body_id,toremove[i].pair.body_shape,toremove[i].pair.local_shape);
|
||||
}
|
||||
|
||||
//process aditions
|
||||
|
||||
for(int i=0;i<toadd_count;i++) {
|
||||
|
||||
_body_inout(1,toadd[i].id,toadd[i].shape,toadd[i].local_shape);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
set_ignore_transform_notification(true);
|
||||
set_global_transform(state->get_transform());
|
||||
linear_velocity=state->get_linear_velocity();
|
||||
angular_velocity=state->get_angular_velocity();
|
||||
active=!state->is_sleeping();
|
||||
if (get_script_instance())
|
||||
get_script_instance()->call("_integrate_forces",state);
|
||||
set_ignore_transform_notification(false);
|
||||
|
||||
state=NULL;
|
||||
}
|
||||
|
||||
void RigidBody::_notification(int p_what) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
void RigidBody::set_mode(Mode p_mode) {
|
||||
|
||||
mode=p_mode;
|
||||
switch(p_mode) {
|
||||
|
||||
case MODE_RIGID: {
|
||||
|
||||
PhysicsServer::get_singleton()->body_set_mode(get_rid(),PhysicsServer::BODY_MODE_RIGID);
|
||||
} break;
|
||||
case MODE_STATIC: {
|
||||
|
||||
PhysicsServer::get_singleton()->body_set_mode(get_rid(),PhysicsServer::BODY_MODE_STATIC);
|
||||
|
||||
} break;
|
||||
case MODE_CHARACTER: {
|
||||
PhysicsServer::get_singleton()->body_set_mode(get_rid(),PhysicsServer::BODY_MODE_CHARACTER);
|
||||
|
||||
} break;
|
||||
case MODE_STATIC_ACTIVE: {
|
||||
|
||||
PhysicsServer::get_singleton()->body_set_mode(get_rid(),PhysicsServer::BODY_MODE_STATIC_ACTIVE);
|
||||
} break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
RigidBody::Mode RigidBody::get_mode() const{
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
void RigidBody::set_mass(real_t p_mass){
|
||||
|
||||
ERR_FAIL_COND(p_mass<=0);
|
||||
mass=p_mass;
|
||||
_change_notify("mass");
|
||||
_change_notify("weight");
|
||||
PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_MASS,mass);
|
||||
|
||||
}
|
||||
real_t RigidBody::get_mass() const{
|
||||
|
||||
return mass;
|
||||
}
|
||||
|
||||
void RigidBody::set_weight(real_t p_weight){
|
||||
|
||||
set_mass(p_weight/9.8);
|
||||
}
|
||||
real_t RigidBody::get_weight() const{
|
||||
|
||||
return mass*9.8;
|
||||
}
|
||||
|
||||
|
||||
void RigidBody::set_friction(real_t p_friction){
|
||||
|
||||
ERR_FAIL_COND(p_friction<0 || p_friction>1);
|
||||
|
||||
friction=p_friction;
|
||||
PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_FRICTION,friction);
|
||||
|
||||
}
|
||||
real_t RigidBody::get_friction() const{
|
||||
|
||||
return friction;
|
||||
}
|
||||
|
||||
void RigidBody::set_bounce(real_t p_bounce){
|
||||
|
||||
ERR_FAIL_COND(p_bounce<0 || p_bounce>1);
|
||||
|
||||
bounce=p_bounce;
|
||||
PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_BOUNCE,bounce);
|
||||
|
||||
}
|
||||
real_t RigidBody::get_bounce() const{
|
||||
|
||||
return bounce;
|
||||
}
|
||||
|
||||
void RigidBody::set_axis_velocity(const Vector3& p_axis) {
|
||||
|
||||
Vector3 v = state? state->get_linear_velocity() : linear_velocity;
|
||||
Vector3 axis = p_axis.normalized();
|
||||
v-=axis*axis.dot(v);
|
||||
v+=p_axis;
|
||||
if (state) {
|
||||
set_linear_velocity(v);
|
||||
} else {
|
||||
PhysicsServer::get_singleton()->body_set_axis_velocity(get_rid(),p_axis);
|
||||
linear_velocity=v;
|
||||
}
|
||||
}
|
||||
|
||||
void RigidBody::set_linear_velocity(const Vector3& p_velocity){
|
||||
|
||||
linear_velocity=p_velocity;
|
||||
if (state)
|
||||
state->set_linear_velocity(linear_velocity);
|
||||
else
|
||||
PhysicsServer::get_singleton()->body_set_state(get_rid(),PhysicsServer::BODY_STATE_LINEAR_VELOCITY,linear_velocity);
|
||||
|
||||
}
|
||||
|
||||
Vector3 RigidBody::get_linear_velocity() const{
|
||||
|
||||
return linear_velocity;
|
||||
}
|
||||
|
||||
void RigidBody::set_angular_velocity(const Vector3& p_velocity){
|
||||
|
||||
angular_velocity=p_velocity;
|
||||
if (state)
|
||||
state->set_angular_velocity(angular_velocity);
|
||||
else
|
||||
PhysicsServer::get_singleton()->body_set_state(get_rid(),PhysicsServer::BODY_STATE_ANGULAR_VELOCITY,angular_velocity);
|
||||
}
|
||||
Vector3 RigidBody::get_angular_velocity() const{
|
||||
|
||||
return angular_velocity;
|
||||
}
|
||||
|
||||
void RigidBody::set_use_custom_integrator(bool p_enable){
|
||||
|
||||
if (custom_integrator==p_enable)
|
||||
return;
|
||||
|
||||
custom_integrator=p_enable;
|
||||
PhysicsServer::get_singleton()->body_set_omit_force_integration(get_rid(),p_enable);
|
||||
|
||||
|
||||
}
|
||||
bool RigidBody::is_using_custom_integrator(){
|
||||
|
||||
return custom_integrator;
|
||||
}
|
||||
|
||||
void RigidBody::set_active(bool p_active) {
|
||||
|
||||
active=p_active;
|
||||
PhysicsServer::get_singleton()->body_set_state(get_rid(),PhysicsServer::BODY_STATE_SLEEPING,!active);
|
||||
|
||||
}
|
||||
|
||||
void RigidBody::set_can_sleep(bool p_active) {
|
||||
|
||||
can_sleep=p_active;
|
||||
PhysicsServer::get_singleton()->body_set_state(get_rid(),PhysicsServer::BODY_STATE_CAN_SLEEP,p_active);
|
||||
}
|
||||
|
||||
bool RigidBody::is_able_to_sleep() const {
|
||||
|
||||
return can_sleep;
|
||||
}
|
||||
|
||||
bool RigidBody::is_active() const {
|
||||
|
||||
return active;
|
||||
}
|
||||
|
||||
void RigidBody::set_max_contacts_reported(int p_amount) {
|
||||
|
||||
max_contacts_reported=p_amount;
|
||||
PhysicsServer::get_singleton()->body_set_max_contacts_reported(get_rid(),p_amount);
|
||||
}
|
||||
|
||||
int RigidBody::get_max_contacts_reported() const{
|
||||
|
||||
return max_contacts_reported;
|
||||
}
|
||||
|
||||
void RigidBody::apply_impulse(const Vector3& p_pos, const Vector3& p_impulse) {
|
||||
|
||||
PhysicsServer::get_singleton()->body_apply_impulse(get_rid(),p_pos,p_impulse);
|
||||
}
|
||||
|
||||
void RigidBody::set_use_continuous_collision_detection(bool p_enable) {
|
||||
|
||||
ccd=p_enable;
|
||||
PhysicsServer::get_singleton()->body_set_enable_continuous_collision_detection(get_rid(),p_enable);
|
||||
}
|
||||
|
||||
bool RigidBody::is_using_continuous_collision_detection() const {
|
||||
|
||||
|
||||
return ccd;
|
||||
}
|
||||
|
||||
|
||||
void RigidBody::set_contact_monitor(bool p_enabled) {
|
||||
|
||||
if (p_enabled==is_contact_monitor_enabled())
|
||||
return;
|
||||
|
||||
if (!p_enabled) {
|
||||
|
||||
for(Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.front();E;E=E->next()) {
|
||||
|
||||
//clean up mess
|
||||
}
|
||||
|
||||
memdelete( contact_monitor );
|
||||
contact_monitor=NULL;
|
||||
} else {
|
||||
|
||||
contact_monitor = memnew( ContactMonitor );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool RigidBody::is_contact_monitor_enabled() const {
|
||||
|
||||
return contact_monitor!=NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void RigidBody::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_mode","mode"),&RigidBody::set_mode);
|
||||
ObjectTypeDB::bind_method(_MD("get_mode"),&RigidBody::get_mode);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_mass","mass"),&RigidBody::set_mass);
|
||||
ObjectTypeDB::bind_method(_MD("get_mass"),&RigidBody::get_mass);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_weight","weight"),&RigidBody::set_weight);
|
||||
ObjectTypeDB::bind_method(_MD("get_weight"),&RigidBody::get_weight);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_friction","friction"),&RigidBody::set_friction);
|
||||
ObjectTypeDB::bind_method(_MD("get_friction"),&RigidBody::get_friction);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_bounce","bounce"),&RigidBody::set_bounce);
|
||||
ObjectTypeDB::bind_method(_MD("get_bounce"),&RigidBody::get_bounce);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_linear_velocity","linear_velocity"),&RigidBody::set_linear_velocity);
|
||||
ObjectTypeDB::bind_method(_MD("get_linear_velocity"),&RigidBody::get_linear_velocity);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_angular_velocity","angular_velocity"),&RigidBody::set_angular_velocity);
|
||||
ObjectTypeDB::bind_method(_MD("get_angular_velocity"),&RigidBody::get_angular_velocity);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_max_contacts_reported","amount"),&RigidBody::set_max_contacts_reported);
|
||||
ObjectTypeDB::bind_method(_MD("get_max_contacts_reported"),&RigidBody::get_max_contacts_reported);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_use_custom_integrator","enable"),&RigidBody::set_use_custom_integrator);
|
||||
ObjectTypeDB::bind_method(_MD("is_using_custom_integrator"),&RigidBody::is_using_custom_integrator);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_contact_monitor","enabled"),&RigidBody::set_contact_monitor);
|
||||
ObjectTypeDB::bind_method(_MD("is_contact_monitor_enabled"),&RigidBody::is_contact_monitor_enabled);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_use_continuous_collision_detection","enable"),&RigidBody::set_use_continuous_collision_detection);
|
||||
ObjectTypeDB::bind_method(_MD("is_using_continuous_collision_detection"),&RigidBody::is_using_continuous_collision_detection);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_axis_velocity","axis_velocity"),&RigidBody::set_axis_velocity);
|
||||
ObjectTypeDB::bind_method(_MD("apply_impulse","pos","impulse"),&RigidBody::apply_impulse);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_active","active"),&RigidBody::set_active);
|
||||
ObjectTypeDB::bind_method(_MD("is_active"),&RigidBody::is_active);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_can_sleep","able_to_sleep"),&RigidBody::set_can_sleep);
|
||||
ObjectTypeDB::bind_method(_MD("is_able_to_sleep"),&RigidBody::is_able_to_sleep);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_direct_state_changed"),&RigidBody::_direct_state_changed);
|
||||
ObjectTypeDB::bind_method(_MD("_body_enter_scene"),&RigidBody::_body_enter_scene);
|
||||
ObjectTypeDB::bind_method(_MD("_body_exit_scene"),&RigidBody::_body_exit_scene);
|
||||
|
||||
BIND_VMETHOD(MethodInfo("_integrate_forces",PropertyInfo(Variant::OBJECT,"state:PhysicsDirectBodyState")));
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Rigid,Static,Character,Static Active"),_SCS("set_mode"),_SCS("get_mode"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"mass",PROPERTY_HINT_EXP_RANGE,"0.01,65535,0.01"),_SCS("set_mass"),_SCS("get_mass"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"weight",PROPERTY_HINT_EXP_RANGE,"0.01,65535,0.01",PROPERTY_USAGE_EDITOR),_SCS("set_weight"),_SCS("get_weight"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_friction"),_SCS("get_friction"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_bounce"),_SCS("get_bounce"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"custom_integrator"),_SCS("set_use_custom_integrator"),_SCS("is_using_custom_integrator"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"continuous_cd"),_SCS("set_use_continuous_collision_detection"),_SCS("is_using_continuous_collision_detection"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"contacts_reported"),_SCS("set_max_contacts_reported"),_SCS("get_max_contacts_reported"));
|
||||
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::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"));
|
||||
|
||||
ADD_SIGNAL( MethodInfo("body_enter_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"local_shape")));
|
||||
ADD_SIGNAL( MethodInfo("body_exit_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"local_shape")));
|
||||
ADD_SIGNAL( MethodInfo("body_enter",PropertyInfo(Variant::OBJECT,"body")));
|
||||
ADD_SIGNAL( MethodInfo("body_exit",PropertyInfo(Variant::OBJECT,"body")));
|
||||
|
||||
BIND_CONSTANT( MODE_STATIC );
|
||||
BIND_CONSTANT( MODE_STATIC_ACTIVE );
|
||||
BIND_CONSTANT( MODE_RIGID );
|
||||
BIND_CONSTANT( MODE_CHARACTER );
|
||||
}
|
||||
|
||||
RigidBody::RigidBody() : PhysicsBody(PhysicsServer::BODY_MODE_RIGID) {
|
||||
|
||||
mode=MODE_RIGID;
|
||||
|
||||
bounce=0;
|
||||
mass=1;
|
||||
friction=1;
|
||||
max_contacts_reported=0;
|
||||
state=NULL;
|
||||
|
||||
//angular_velocity=0;
|
||||
active=true;
|
||||
ccd=false;
|
||||
|
||||
custom_integrator=false;
|
||||
contact_monitor=NULL;
|
||||
can_sleep=true;
|
||||
|
||||
PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(),this,"_direct_state_changed");
|
||||
}
|
||||
|
||||
RigidBody::~RigidBody() {
|
||||
|
||||
if (contact_monitor)
|
||||
memdelete( contact_monitor );
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
219
scene/3d/physics_body.h
Normal file
219
scene/3d/physics_body.h
Normal file
@ -0,0 +1,219 @@
|
||||
/*************************************************************************/
|
||||
/* physics_body.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef PHYSICS_BODY__H
|
||||
#define PHYSICS_BODY__H
|
||||
|
||||
#include "scene/3d/collision_object.h"
|
||||
#include "servers/physics_server.h"
|
||||
#include "vset.h"
|
||||
|
||||
|
||||
class PhysicsBody : public CollisionObject {
|
||||
|
||||
OBJ_TYPE(PhysicsBody,CollisionObject);
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
PhysicsBody(PhysicsServer::BodyMode p_mode);
|
||||
public:
|
||||
|
||||
PhysicsBody();
|
||||
|
||||
};
|
||||
|
||||
class StaticBody : public PhysicsBody {
|
||||
|
||||
OBJ_TYPE(StaticBody,PhysicsBody);
|
||||
|
||||
Transform *pre_xform;
|
||||
//RID query;
|
||||
bool setting;
|
||||
bool pending;
|
||||
bool simulating_motion;
|
||||
Vector3 constant_linear_velocity;
|
||||
Vector3 constant_angular_velocity;
|
||||
void _update_xform();
|
||||
void _state_notify(Object *p_object);
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
void set_simulate_motion(bool p_enable);
|
||||
bool is_simulating_motion() const;
|
||||
|
||||
void set_constant_linear_velocity(const Vector3& p_vel);
|
||||
void set_constant_angular_velocity(const Vector3& p_vel);
|
||||
|
||||
Vector3 get_constant_linear_velocity() const;
|
||||
Vector3 get_constant_angular_velocity() const;
|
||||
|
||||
StaticBody();
|
||||
~StaticBody();
|
||||
|
||||
};
|
||||
|
||||
class RigidBody : public PhysicsBody {
|
||||
|
||||
OBJ_TYPE(RigidBody,PhysicsBody);
|
||||
public:
|
||||
|
||||
enum Mode {
|
||||
MODE_RIGID,
|
||||
MODE_STATIC,
|
||||
MODE_CHARACTER,
|
||||
MODE_STATIC_ACTIVE,
|
||||
};
|
||||
private:
|
||||
|
||||
bool can_sleep;
|
||||
PhysicsDirectBodyState *state;
|
||||
Mode mode;
|
||||
|
||||
real_t bounce;
|
||||
real_t mass;
|
||||
real_t friction;
|
||||
|
||||
Vector3 linear_velocity;
|
||||
Vector3 angular_velocity;
|
||||
bool active;
|
||||
bool ccd;
|
||||
|
||||
|
||||
int max_contacts_reported;
|
||||
|
||||
bool custom_integrator;
|
||||
|
||||
|
||||
struct ShapePair {
|
||||
|
||||
int body_shape;
|
||||
int local_shape;
|
||||
bool tagged;
|
||||
bool operator<(const ShapePair& p_sp) const {
|
||||
if (body_shape==p_sp.body_shape)
|
||||
return local_shape < p_sp.local_shape;
|
||||
else
|
||||
return body_shape < p_sp.body_shape;
|
||||
}
|
||||
|
||||
ShapePair() {}
|
||||
ShapePair(int p_bs, int p_ls) { body_shape=p_bs; local_shape=p_ls; }
|
||||
};
|
||||
struct RigidBody_RemoveAction {
|
||||
|
||||
|
||||
ObjectID body_id;
|
||||
ShapePair pair;
|
||||
|
||||
};
|
||||
struct BodyState {
|
||||
|
||||
int rc;
|
||||
bool in_scene;
|
||||
VSet<ShapePair> shapes;
|
||||
};
|
||||
|
||||
struct ContactMonitor {
|
||||
|
||||
|
||||
Map<ObjectID,BodyState> body_map;
|
||||
|
||||
};
|
||||
|
||||
|
||||
ContactMonitor *contact_monitor;
|
||||
void _body_enter_scene(ObjectID p_id);
|
||||
void _body_exit_scene(ObjectID p_id);
|
||||
|
||||
|
||||
void _body_inout(int p_status, ObjectID p_instance, int p_body_shape,int p_local_shape);
|
||||
void _direct_state_changed(Object *p_state);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_mode(Mode p_mode);
|
||||
Mode get_mode() const;
|
||||
|
||||
void set_mass(real_t p_mass);
|
||||
real_t get_mass() const;
|
||||
|
||||
void set_weight(real_t p_weight);
|
||||
real_t get_weight() const;
|
||||
|
||||
void set_friction(real_t p_friction);
|
||||
real_t get_friction() const;
|
||||
|
||||
void set_bounce(real_t p_bounce);
|
||||
real_t get_bounce() const;
|
||||
|
||||
void set_linear_velocity(const Vector3& p_velocity);
|
||||
Vector3 get_linear_velocity() const;
|
||||
|
||||
void set_axis_velocity(const Vector3& p_axis);
|
||||
|
||||
void set_angular_velocity(const Vector3&p_velocity);
|
||||
Vector3 get_angular_velocity() const;
|
||||
|
||||
void set_use_custom_integrator(bool p_enable);
|
||||
bool is_using_custom_integrator();
|
||||
|
||||
void set_active(bool p_active);
|
||||
bool is_active() const;
|
||||
|
||||
void set_can_sleep(bool p_active);
|
||||
bool is_able_to_sleep() const;
|
||||
|
||||
void set_contact_monitor(bool p_enabled);
|
||||
bool is_contact_monitor_enabled() const;
|
||||
|
||||
void set_max_contacts_reported(int p_amount);
|
||||
int get_max_contacts_reported() const;
|
||||
|
||||
void set_use_continuous_collision_detection(bool p_enable);
|
||||
bool is_using_continuous_collision_detection() const;
|
||||
|
||||
void apply_impulse(const Vector3& p_pos, const Vector3& p_impulse);
|
||||
|
||||
RigidBody();
|
||||
~RigidBody();
|
||||
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(RigidBody::Mode);
|
||||
#endif // PHYSICS_BODY__H
|
||||
327
scene/3d/physics_joint.cpp
Normal file
327
scene/3d/physics_joint.cpp
Normal file
@ -0,0 +1,327 @@
|
||||
/*************************************************************************/
|
||||
/* physics_joint.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "physics_joint.h"
|
||||
|
||||
#if 0
|
||||
|
||||
void PhysicsJoint::_set(const String& p_name, const Variant& p_value) {
|
||||
|
||||
if (p_name=="body_A")
|
||||
set_body_A(p_value);
|
||||
else if (p_name=="body_B")
|
||||
set_body_B(p_value);
|
||||
else if (p_name=="active")
|
||||
set_active(p_value);
|
||||
else if (p_name=="no_collision")
|
||||
set_disable_collision(p_value);
|
||||
}
|
||||
Variant PhysicsJoint::_get(const String& p_name) const {
|
||||
|
||||
if (p_name=="body_A")
|
||||
return get_body_A();
|
||||
else if (p_name=="body_B")
|
||||
return get_body_B();
|
||||
else if (p_name=="active")
|
||||
return is_active();
|
||||
else if (p_name=="no_collision")
|
||||
return has_disable_collision();
|
||||
|
||||
return Variant();
|
||||
}
|
||||
void PhysicsJoint::_get_property_list( List<PropertyInfo> *p_list) const {
|
||||
|
||||
|
||||
p_list->push_back( PropertyInfo( Variant::NODE_PATH, "body_A" ) );
|
||||
p_list->push_back( PropertyInfo( Variant::NODE_PATH, "body_B" ) );
|
||||
p_list->push_back( PropertyInfo( Variant::BOOL, "active" ) );
|
||||
p_list->push_back( PropertyInfo( Variant::BOOL, "no_collision" ) );
|
||||
}
|
||||
void PhysicsJoint::_notification(int p_what) {
|
||||
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_PARENT_CONFIGURED: {
|
||||
|
||||
_connect();
|
||||
if (get_root_node()->get_editor() && !indicator.is_valid()) {
|
||||
|
||||
indicator=VisualServer::get_singleton()->poly_create();
|
||||
RID mat=VisualServer::get_singleton()->fixed_material_create();
|
||||
VisualServer::get_singleton()->material_set_flag( mat, VisualServer::MATERIAL_FLAG_UNSHADED, true );
|
||||
VisualServer::get_singleton()->material_set_flag( mat, VisualServer::MATERIAL_FLAG_ONTOP, true );
|
||||
VisualServer::get_singleton()->material_set_flag( mat, VisualServer::MATERIAL_FLAG_WIREFRAME, true );
|
||||
VisualServer::get_singleton()->material_set_flag( mat, VisualServer::MATERIAL_FLAG_DOUBLE_SIDED, true );
|
||||
VisualServer::get_singleton()->material_set_line_width( mat, 3 );
|
||||
|
||||
VisualServer::get_singleton()->poly_set_material(indicator,mat,true);
|
||||
_update_indicator();
|
||||
|
||||
}
|
||||
|
||||
if (indicator.is_valid()) {
|
||||
|
||||
indicator_instance=VisualServer::get_singleton()->instance_create(indicator,get_world()->get_scenario());
|
||||
VisualServer::get_singleton()->instance_attach_object_instance_ID( indicator_instance,get_instance_ID() );
|
||||
}
|
||||
} break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
|
||||
if (indicator_instance.is_valid()) {
|
||||
|
||||
VisualServer::get_singleton()->instance_set_transform(indicator_instance,get_global_transform());
|
||||
}
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_SCENE: {
|
||||
|
||||
if (indicator_instance.is_valid()) {
|
||||
|
||||
VisualServer::get_singleton()->free(indicator_instance);
|
||||
}
|
||||
_disconnect();
|
||||
|
||||
} break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RID PhysicsJoint::_get_visual_instance_rid() const {
|
||||
|
||||
return indicator_instance;
|
||||
|
||||
}
|
||||
|
||||
void PhysicsJoint::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_get_visual_instance_rid"),&PhysicsJoint::_get_visual_instance_rid);
|
||||
ObjectTypeDB::bind_method(_MD("set_body_A","path"),&PhysicsJoint::set_body_A);
|
||||
ObjectTypeDB::bind_method(_MD("set_body_B"),&PhysicsJoint::set_body_B);
|
||||
ObjectTypeDB::bind_method(_MD("get_body_A","path"),&PhysicsJoint::get_body_A);
|
||||
ObjectTypeDB::bind_method(_MD("get_body_B"),&PhysicsJoint::get_body_B);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_active","active"),&PhysicsJoint::set_active);
|
||||
ObjectTypeDB::bind_method(_MD("is_active"),&PhysicsJoint::is_active);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_disable_collision","disable"),&PhysicsJoint::set_disable_collision);
|
||||
ObjectTypeDB::bind_method(_MD("has_disable_collision"),&PhysicsJoint::has_disable_collision);
|
||||
|
||||
|
||||
ObjectTypeDB::bind_method("reconnect",&PhysicsJoint::reconnect);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("get_rid"),&PhysicsJoint::get_rid);
|
||||
|
||||
}
|
||||
|
||||
void PhysicsJoint::set_body_A(const NodePath& p_path) {
|
||||
|
||||
_disconnect();
|
||||
body_A=p_path;
|
||||
_connect();
|
||||
_change_notify("body_A");
|
||||
}
|
||||
void PhysicsJoint::set_body_B(const NodePath& p_path) {
|
||||
|
||||
_disconnect();
|
||||
body_B=p_path;
|
||||
_connect();
|
||||
_change_notify("body_B");
|
||||
|
||||
}
|
||||
NodePath PhysicsJoint::get_body_A() const {
|
||||
|
||||
return body_A;
|
||||
}
|
||||
NodePath PhysicsJoint::get_body_B() const {
|
||||
|
||||
return body_B;
|
||||
}
|
||||
|
||||
void PhysicsJoint::set_active(bool p_active) {
|
||||
|
||||
active=p_active;
|
||||
if (is_inside_scene()) {
|
||||
PhysicsServer::get_singleton()->joint_set_active(joint,active);
|
||||
}
|
||||
_change_notify("active");
|
||||
}
|
||||
|
||||
void PhysicsJoint::set_disable_collision(bool p_active) {
|
||||
|
||||
if (no_collision==p_active)
|
||||
return;
|
||||
_disconnect();
|
||||
no_collision=p_active;
|
||||
_connect();
|
||||
|
||||
_change_notify("no_collision");
|
||||
}
|
||||
bool PhysicsJoint::has_disable_collision() const {
|
||||
|
||||
return no_collision;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool PhysicsJoint::is_active() const {
|
||||
|
||||
return active;
|
||||
}
|
||||
|
||||
void PhysicsJoint::_disconnect() {
|
||||
|
||||
if (!is_inside_scene())
|
||||
return;
|
||||
|
||||
if (joint.is_valid())
|
||||
PhysicsServer::get_singleton()->free(joint);
|
||||
|
||||
joint=RID();
|
||||
|
||||
Node *nA = get_node(body_A);
|
||||
Node *nB = get_node(body_B);
|
||||
|
||||
PhysicsBody *A = nA?nA->cast_to<PhysicsBody>():NULL;
|
||||
PhysicsBody *B = nA?nB->cast_to<PhysicsBody>():NULL;
|
||||
|
||||
if (!A ||!B)
|
||||
return;
|
||||
|
||||
if (no_collision)
|
||||
PhysicsServer::get_singleton()->body_remove_collision_exception(A->get_body(),B->get_body());
|
||||
|
||||
}
|
||||
void PhysicsJoint::_connect() {
|
||||
|
||||
if (!is_inside_scene())
|
||||
return;
|
||||
|
||||
ERR_FAIL_COND(joint.is_valid());
|
||||
|
||||
Node *nA = get_node(body_A);
|
||||
Node *nB = get_node(body_B);
|
||||
|
||||
PhysicsBody *A = nA?nA->cast_to<PhysicsBody>():NULL;
|
||||
PhysicsBody *B = nA?nB->cast_to<PhysicsBody>():NULL;
|
||||
|
||||
if (!A && !B)
|
||||
return;
|
||||
|
||||
if (B && !A)
|
||||
SWAP(B,A);
|
||||
|
||||
joint = create(A,B);
|
||||
|
||||
if (A<B)
|
||||
SWAP(A,B);
|
||||
|
||||
if (no_collision)
|
||||
PhysicsServer::get_singleton()->body_add_collision_exception(A->get_body(),B->get_body());
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void PhysicsJoint::reconnect() {
|
||||
|
||||
_disconnect();
|
||||
_connect();
|
||||
|
||||
}
|
||||
|
||||
|
||||
RID PhysicsJoint::get_rid() {
|
||||
|
||||
return joint;
|
||||
}
|
||||
|
||||
|
||||
PhysicsJoint::PhysicsJoint() {
|
||||
|
||||
active=true;
|
||||
no_collision=true;
|
||||
}
|
||||
|
||||
|
||||
PhysicsJoint::~PhysicsJoint() {
|
||||
|
||||
if (indicator.is_valid()) {
|
||||
|
||||
VisualServer::get_singleton()->free(indicator);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* PIN */
|
||||
|
||||
void PhysicsJointPin::_update_indicator() {
|
||||
|
||||
|
||||
VisualServer::get_singleton()->poly_clear(indicator);
|
||||
|
||||
Vector<Color> colors;
|
||||
colors.push_back( Color(0.3,0.9,0.2,0.7) );
|
||||
colors.push_back( Color(0.3,0.9,0.2,0.7) );
|
||||
|
||||
Vector<Vector3> points;
|
||||
points.resize(2);
|
||||
points[0]=Vector3(Vector3(-0.2,0,0));
|
||||
points[1]=Vector3(Vector3(0.2,0,0));
|
||||
VisualServer::get_singleton()->poly_add_primitive(indicator,points,Vector<Vector3>(),colors,Vector<Vector3>());
|
||||
|
||||
points[0]=Vector3(Vector3(0,-0.2,0));
|
||||
points[1]=Vector3(Vector3(0,0.2,0));
|
||||
VisualServer::get_singleton()->poly_add_primitive(indicator,points,Vector<Vector3>(),colors,Vector<Vector3>());
|
||||
|
||||
points[0]=Vector3(Vector3(0,0,-0.2));
|
||||
points[1]=Vector3(Vector3(0,0,0.2));
|
||||
VisualServer::get_singleton()->poly_add_primitive(indicator,points,Vector<Vector3>(),colors,Vector<Vector3>());
|
||||
|
||||
}
|
||||
|
||||
RID PhysicsJointPin::create(PhysicsBody*A,PhysicsBody*B) {
|
||||
|
||||
RID body_A = A->get_body();
|
||||
RID body_B = B?B->get_body():RID();
|
||||
|
||||
ERR_FAIL_COND_V( !body_A.is_valid(), RID() );
|
||||
|
||||
Vector3 pin_pos = get_global_transform().origin;
|
||||
|
||||
if (body_B.is_valid())
|
||||
return PhysicsServer::get_singleton()->joint_create_double_pin_global(body_A,pin_pos,body_B,pin_pos);
|
||||
else
|
||||
return PhysicsServer::get_singleton()->joint_create_pin(body_A,A->get_global_transform().xform_inv(pin_pos),pin_pos);
|
||||
}
|
||||
|
||||
PhysicsJointPin::PhysicsJointPin() {
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
104
scene/3d/physics_joint.h
Normal file
104
scene/3d/physics_joint.h
Normal file
@ -0,0 +1,104 @@
|
||||
/*************************************************************************/
|
||||
/* physics_joint.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef PHYSICS_JOINT_H
|
||||
#define PHYSICS_JOINT_H
|
||||
|
||||
#include "scene/3d/spatial.h"
|
||||
#include "scene/3d/physics_body.h"
|
||||
|
||||
#if 0
|
||||
class PhysicsJoint : public Spatial {
|
||||
|
||||
OBJ_TYPE(PhysicsJoint,Spatial);
|
||||
OBJ_CATEGORY("3D Physics Nodes");
|
||||
|
||||
NodePath body_A;
|
||||
NodePath body_B;
|
||||
bool active;
|
||||
bool no_collision;
|
||||
|
||||
|
||||
RID indicator_instance;
|
||||
|
||||
RID _get_visual_instance_rid() const;
|
||||
protected:
|
||||
|
||||
RID joint;
|
||||
RID indicator;
|
||||
|
||||
bool _set(const StringName& p_name, const Variant& p_value);
|
||||
bool _get(const StringName& p_name,Variant &r_ret) const;
|
||||
void _get_property_list( List<PropertyInfo> *p_list) const;
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
virtual RID create(PhysicsBody*A,PhysicsBody*B)=0;
|
||||
virtual void _update_indicator()=0;
|
||||
|
||||
void _disconnect();
|
||||
void _connect();
|
||||
public:
|
||||
|
||||
void set_body_A(const NodePath& p_path);
|
||||
void set_body_B(const NodePath& p_path);
|
||||
NodePath get_body_A() const;
|
||||
NodePath get_body_B() const;
|
||||
|
||||
void set_active(bool p_active);
|
||||
bool is_active() const;
|
||||
|
||||
void set_disable_collision(bool p_active);
|
||||
bool has_disable_collision() const;
|
||||
|
||||
void reconnect();
|
||||
|
||||
RID get_rid();
|
||||
|
||||
PhysicsJoint();
|
||||
~PhysicsJoint();
|
||||
};
|
||||
|
||||
|
||||
|
||||
class PhysicsJointPin : public PhysicsJoint {
|
||||
|
||||
OBJ_TYPE( PhysicsJointPin, PhysicsJoint );
|
||||
|
||||
protected:
|
||||
|
||||
virtual void _update_indicator();
|
||||
virtual RID create(PhysicsBody*A,PhysicsBody*B);
|
||||
public:
|
||||
|
||||
|
||||
PhysicsJointPin();
|
||||
};
|
||||
|
||||
#endif // PHYSICS_JOINT_H
|
||||
#endif
|
||||
281
scene/3d/portal.cpp
Normal file
281
scene/3d/portal.cpp
Normal file
@ -0,0 +1,281 @@
|
||||
/*************************************************************************/
|
||||
/* portal.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "portal.h"
|
||||
#include "servers/visual_server.h"
|
||||
#include "scene/resources/surface_tool.h"
|
||||
#include "globals.h"
|
||||
|
||||
bool Portal::_set(const StringName& p_name, const Variant& p_value) {
|
||||
|
||||
if (p_name=="shape") {
|
||||
DVector<float> src_coords=p_value;
|
||||
Vector<Point2> points;
|
||||
int src_coords_size = src_coords.size();
|
||||
ERR_FAIL_COND_V(src_coords_size%2,false);
|
||||
points.resize(src_coords_size/2);
|
||||
for (int i=0;i<points.size();i++) {
|
||||
|
||||
points[i].x=src_coords[i*2+0];
|
||||
points[i].y=src_coords[i*2+1];
|
||||
set_shape(points);
|
||||
}
|
||||
} else if (p_name=="enabled") {
|
||||
set_enabled(p_value);
|
||||
} else if (p_name=="disable_distance") {
|
||||
set_disable_distance(p_value);
|
||||
} else if (p_name=="disabled_color") {
|
||||
set_disabled_color(p_value);
|
||||
} else if (p_name=="connect_range") {
|
||||
set_connect_range(p_value);
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Portal::_get(const StringName& p_name,Variant &r_ret) const {
|
||||
|
||||
if (p_name=="shape") {
|
||||
Vector<Point2> points=get_shape();
|
||||
DVector<float> dst_coords;
|
||||
dst_coords.resize(points.size()*2);
|
||||
|
||||
for (int i=0;i<points.size();i++) {
|
||||
|
||||
dst_coords.set(i*2+0,points[i].x);
|
||||
dst_coords.set(i*2+1,points[i].y);
|
||||
}
|
||||
|
||||
r_ret= dst_coords;
|
||||
} else if (p_name=="enabled") {
|
||||
r_ret= is_enabled();
|
||||
} else if (p_name=="disable_distance") {
|
||||
r_ret= get_disable_distance();
|
||||
} else if (p_name=="disabled_color") {
|
||||
r_ret= get_disabled_color();
|
||||
} else if (p_name=="connect_range") {
|
||||
r_ret= get_connect_range();
|
||||
} else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Portal::_get_property_list( List<PropertyInfo> *p_list) const {
|
||||
|
||||
p_list->push_back( PropertyInfo( Variant::REAL_ARRAY, "shape" ) );
|
||||
p_list->push_back( PropertyInfo( Variant::BOOL, "enabled" ) );
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "disable_distance",PROPERTY_HINT_RANGE,"0,4096,0.01" ) );
|
||||
p_list->push_back( PropertyInfo( Variant::COLOR, "disabled_color") );
|
||||
p_list->push_back( PropertyInfo( Variant::REAL, "connect_range",PROPERTY_HINT_RANGE,"0.1,4096,0.01" ) );
|
||||
}
|
||||
|
||||
|
||||
RES Portal::_get_gizmo_geometry() const {
|
||||
|
||||
Ref<SurfaceTool> surface_tool( memnew( SurfaceTool ));
|
||||
|
||||
Ref<FixedMaterial> mat( memnew( FixedMaterial ));
|
||||
|
||||
mat->set_parameter( FixedMaterial::PARAM_DIFFUSE,Color(1.0,0.8,0.8,0.7) );
|
||||
mat->set_line_width(4);
|
||||
mat->set_flag(Material::FLAG_DOUBLE_SIDED,true);
|
||||
mat->set_flag(Material::FLAG_UNSHADED,true);
|
||||
mat->set_hint(Material::HINT_NO_DEPTH_DRAW,true);
|
||||
|
||||
surface_tool->begin(Mesh::PRIMITIVE_LINES);
|
||||
surface_tool->set_material(mat);
|
||||
|
||||
Vector<Point2> shape = get_shape();
|
||||
|
||||
Vector2 center;
|
||||
for (int i=0;i<shape.size();i++) {
|
||||
|
||||
int n=(i+1)%shape.size();
|
||||
Vector<Vector3> points;
|
||||
surface_tool->add_vertex( Vector3( shape[i].x, shape[i].y,0 ));
|
||||
surface_tool->add_vertex( Vector3( shape[n].x, shape[n].y,0 ));
|
||||
center+=shape[i];
|
||||
|
||||
}
|
||||
|
||||
if (shape.size()>0) {
|
||||
|
||||
center/=shape.size();
|
||||
Vector<Vector3> points;
|
||||
surface_tool->add_vertex( Vector3( center.x, center.y,0 ));
|
||||
surface_tool->add_vertex( Vector3( center.x, center.y,1.0 ));
|
||||
}
|
||||
|
||||
return surface_tool->commit();
|
||||
}
|
||||
|
||||
|
||||
|
||||
AABB Portal::get_aabb() const {
|
||||
|
||||
return aabb;
|
||||
}
|
||||
DVector<Face3> Portal::get_faces(uint32_t p_usage_flags) const {
|
||||
|
||||
if (!(p_usage_flags&FACES_ENCLOSING))
|
||||
return DVector<Face3>();
|
||||
|
||||
Vector<Point2> shape = get_shape();
|
||||
if (shape.size()==0)
|
||||
return DVector<Face3>();
|
||||
|
||||
Vector2 center;
|
||||
for (int i=0;i<shape.size();i++) {
|
||||
|
||||
center+=shape[i];
|
||||
|
||||
}
|
||||
|
||||
DVector<Face3> ret;
|
||||
center/=shape.size();
|
||||
|
||||
for (int i=0;i<shape.size();i++) {
|
||||
|
||||
int n=(i+1)%shape.size();
|
||||
|
||||
Face3 f;
|
||||
f.vertex[0]=Vector3( center.x, center.y, 0 );
|
||||
f.vertex[1]=Vector3( shape[i].x, shape[i].y, 0 );
|
||||
f.vertex[2]=Vector3( shape[n].x, shape[n].y, 0 );
|
||||
ret.push_back(f);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Portal::set_shape(const Vector<Point2>& p_shape) {
|
||||
|
||||
|
||||
VisualServer::get_singleton()->portal_set_shape(portal, p_shape);
|
||||
update_gizmo();
|
||||
}
|
||||
|
||||
Vector<Point2> Portal::get_shape() const {
|
||||
|
||||
return VisualServer::get_singleton()->portal_get_shape(portal);
|
||||
}
|
||||
|
||||
void Portal::set_connect_range(float p_range) {
|
||||
|
||||
connect_range=p_range;
|
||||
VisualServer::get_singleton()->portal_set_connect_range(portal,p_range);
|
||||
}
|
||||
|
||||
float Portal::get_connect_range() const {
|
||||
|
||||
return connect_range;
|
||||
}
|
||||
|
||||
|
||||
void Portal::set_enabled(bool p_enabled) {
|
||||
|
||||
enabled=p_enabled;
|
||||
VisualServer::get_singleton()->portal_set_enabled(portal,enabled);
|
||||
}
|
||||
|
||||
bool Portal::is_enabled() const {
|
||||
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
void Portal::set_disable_distance(float p_distance) {
|
||||
|
||||
disable_distance=p_distance;
|
||||
VisualServer::get_singleton()->portal_set_disable_distance(portal,disable_distance);
|
||||
|
||||
}
|
||||
float Portal::get_disable_distance() const {
|
||||
|
||||
|
||||
return disable_distance;
|
||||
}
|
||||
|
||||
void Portal::set_disabled_color(const Color& p_disabled_color) {
|
||||
|
||||
disabled_color=p_disabled_color;
|
||||
VisualServer::get_singleton()->portal_set_disabled_color(portal,disabled_color);
|
||||
}
|
||||
|
||||
Color Portal::get_disabled_color() const {
|
||||
|
||||
return disabled_color;
|
||||
}
|
||||
|
||||
void Portal::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_shape","points"),&Portal::set_shape);
|
||||
ObjectTypeDB::bind_method(_MD("get_shape"),&Portal::get_shape);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_enabled","enable"),&Portal::set_enabled);
|
||||
ObjectTypeDB::bind_method(_MD("is_enabled"),&Portal::is_enabled);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_disable_distance","distance"),&Portal::set_disable_distance);
|
||||
ObjectTypeDB::bind_method(_MD("get_disable_distance"),&Portal::get_disable_distance);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_disabled_color","color"),&Portal::set_disabled_color);
|
||||
ObjectTypeDB::bind_method(_MD("get_disabled_color"),&Portal::get_disabled_color);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_connect_range","range"),&Portal::set_connect_range);
|
||||
ObjectTypeDB::bind_method(_MD("get_connect_range"),&Portal::get_connect_range);
|
||||
|
||||
}
|
||||
|
||||
Portal::Portal() {
|
||||
|
||||
portal = VisualServer::get_singleton()->portal_create();
|
||||
Vector< Point2 > points;
|
||||
points.push_back( Point2( -1, 1 ) );
|
||||
points.push_back( Point2( 1, 1 ) );
|
||||
points.push_back( Point2( 1, -1 ) );
|
||||
points.push_back( Point2( -1, -1 ) );
|
||||
set_shape(points); // default shape
|
||||
|
||||
|
||||
set_connect_range(0.8);
|
||||
set_disable_distance(50);
|
||||
set_enabled(true);
|
||||
|
||||
set_base(portal);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
Portal::~Portal() {
|
||||
|
||||
VisualServer::get_singleton()->free(portal);
|
||||
}
|
||||
|
||||
|
||||
93
scene/3d/portal.h
Normal file
93
scene/3d/portal.h
Normal file
@ -0,0 +1,93 @@
|
||||
/*************************************************************************/
|
||||
/* portal.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef PORTAL_H
|
||||
#define PORTAL_H
|
||||
|
||||
#include "scene/3d/visual_instance.h"
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
/* Portal Logic:
|
||||
If a portal is placed next (very close to) a similar, opposing portal, they automatically connect,
|
||||
otherwise, a portal connects to the parent room
|
||||
*/
|
||||
|
||||
|
||||
|
||||
class Portal : public VisualInstance {
|
||||
|
||||
OBJ_TYPE(Portal, VisualInstance);
|
||||
|
||||
RID portal;
|
||||
|
||||
bool enabled;
|
||||
float disable_distance;
|
||||
Color disabled_color;
|
||||
float connect_range;
|
||||
|
||||
AABB aabb;
|
||||
|
||||
virtual RES _get_gizmo_geometry() const;
|
||||
|
||||
protected:
|
||||
|
||||
bool _set(const StringName& p_name, const Variant& p_value);
|
||||
bool _get(const StringName& p_name,Variant &r_ret) const;
|
||||
void _get_property_list( List<PropertyInfo> *p_list) const;
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
virtual AABB get_aabb() const;
|
||||
virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const;
|
||||
|
||||
void set_enabled(bool p_enabled);
|
||||
bool is_enabled() const;
|
||||
|
||||
void set_disable_distance(float p_distance);
|
||||
float get_disable_distance() const;
|
||||
|
||||
void set_disabled_color(const Color& p_disabled_color);
|
||||
Color get_disabled_color() const;
|
||||
|
||||
void set_shape(const Vector<Point2>& p_shape);
|
||||
Vector<Point2> get_shape() const;
|
||||
|
||||
void set_connect_range(float p_range);
|
||||
float get_connect_range() const;
|
||||
|
||||
Portal();
|
||||
~Portal();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
66
scene/3d/position_3d.cpp
Normal file
66
scene/3d/position_3d.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
/*************************************************************************/
|
||||
/* position_3d.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "position_3d.h"
|
||||
#include "scene/resources/mesh.h"
|
||||
|
||||
RES Position3D::_get_gizmo_geometry() const {
|
||||
|
||||
|
||||
Ref<Mesh> mesh = memnew( Mesh );
|
||||
|
||||
DVector<Vector3> cursor_points;
|
||||
DVector<Color> cursor_colors;
|
||||
float cs = 0.25;
|
||||
cursor_points.push_back(Vector3(+cs,0,0));
|
||||
cursor_points.push_back(Vector3(-cs,0,0));
|
||||
cursor_points.push_back(Vector3(0,+cs,0));
|
||||
cursor_points.push_back(Vector3(0,-cs,0));
|
||||
cursor_points.push_back(Vector3(0,0,+cs));
|
||||
cursor_points.push_back(Vector3(0,0,-cs));
|
||||
cursor_colors.push_back(Color(1,0.5,0.5,1));
|
||||
cursor_colors.push_back(Color(1,0.5,0.5,1));
|
||||
cursor_colors.push_back(Color(0.5,1,0.5,1));
|
||||
cursor_colors.push_back(Color(0.5,1,0.5,1));
|
||||
cursor_colors.push_back(Color(0.5,0.5,1,1));
|
||||
cursor_colors.push_back(Color(0.5,0.5,1,1));
|
||||
|
||||
Ref<FixedMaterial> mat = memnew( FixedMaterial );
|
||||
mat->set_flag(Material::FLAG_UNSHADED,true);
|
||||
mat->set_line_width(3);
|
||||
Array d;
|
||||
d[Mesh::ARRAY_VERTEX]=cursor_points;
|
||||
d[Mesh::ARRAY_COLOR]=cursor_colors;
|
||||
mesh->add_surface(Mesh::PRIMITIVE_LINES,d);
|
||||
mesh->surface_set_material(0,mat);
|
||||
return mesh;
|
||||
}
|
||||
|
||||
Position3D::Position3D()
|
||||
{
|
||||
}
|
||||
45
scene/3d/position_3d.h
Normal file
45
scene/3d/position_3d.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*************************************************************************/
|
||||
/* position_3d.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef POSITION_3D_H
|
||||
#define POSITION_3D_H
|
||||
|
||||
#include "scene/3d/spatial.h"
|
||||
|
||||
class Position3D : public Spatial {
|
||||
|
||||
OBJ_TYPE(Position3D,Spatial);
|
||||
|
||||
virtual RES _get_gizmo_geometry() const;
|
||||
|
||||
public:
|
||||
|
||||
Position3D();
|
||||
};
|
||||
|
||||
#endif // POSITION_3D_H
|
||||
198
scene/3d/proximity_group.cpp
Normal file
198
scene/3d/proximity_group.cpp
Normal file
@ -0,0 +1,198 @@
|
||||
/*************************************************************************/
|
||||
/* proximity_group.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "proximity_group.h"
|
||||
|
||||
#include "math_funcs.h"
|
||||
|
||||
void ProximityGroup::clear_groups() {
|
||||
|
||||
Map<StringName, uint32_t>::Element *E;
|
||||
|
||||
{
|
||||
const int size = 16;
|
||||
StringName remove_list[size];
|
||||
E = groups.front();
|
||||
int num = 0;
|
||||
while (E && num < size) {
|
||||
|
||||
if (E->get() != group_version) {
|
||||
remove_list[num++] = E->key();
|
||||
};
|
||||
|
||||
E = E->next();
|
||||
};
|
||||
for (int i=0; i<num; i++) {
|
||||
|
||||
groups.erase(remove_list[i]);
|
||||
};
|
||||
};
|
||||
|
||||
if (E) {
|
||||
clear_groups(); // call until we go through the whole list
|
||||
};
|
||||
};
|
||||
|
||||
void ProximityGroup::update_groups() {
|
||||
|
||||
if (grid_radius == Vector3(0, 0, 0))
|
||||
return;
|
||||
|
||||
++group_version;
|
||||
|
||||
Vector3 pos = get_global_transform().get_origin();
|
||||
Vector3 vcell = pos / cell_size;
|
||||
int cell[3] = { Math::fast_ftoi(vcell.x), Math::fast_ftoi(vcell.y), Math::fast_ftoi(vcell.z) };
|
||||
|
||||
add_groups(cell, group_name, 0);
|
||||
|
||||
clear_groups();
|
||||
};
|
||||
|
||||
void ProximityGroup::add_groups(int* p_cell, String p_base, int p_depth) {
|
||||
|
||||
p_base = p_base + "|";
|
||||
if (grid_radius[p_depth] == 0) {
|
||||
|
||||
if (p_depth == 2) {
|
||||
_new_group(p_base);
|
||||
} else {
|
||||
add_groups(p_cell, p_base, p_depth + 1);
|
||||
};
|
||||
};
|
||||
|
||||
int start = p_cell[p_depth] - grid_radius[p_depth];
|
||||
int end = p_cell[p_depth] + grid_radius[p_depth];
|
||||
|
||||
for (int i=start; i<=end; i++) {
|
||||
|
||||
String gname = p_base + itos(i);
|
||||
if (p_depth == 2) {
|
||||
_new_group(gname);
|
||||
} else {
|
||||
add_groups(p_cell, gname, p_depth + 1);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
void ProximityGroup::_new_group(StringName p_name) {
|
||||
|
||||
const Map<StringName, uint32_t>::Element* E = groups.find(p_name);
|
||||
if (!E) {
|
||||
add_to_group(p_name);
|
||||
};
|
||||
|
||||
groups[p_name] = group_version;
|
||||
};
|
||||
|
||||
void ProximityGroup::set_group_name(String p_group_name) {
|
||||
|
||||
group_name = p_group_name;
|
||||
};
|
||||
|
||||
void ProximityGroup::_notification(int what) {
|
||||
|
||||
switch (what) {
|
||||
|
||||
case NOTIFICATION_EXIT_SCENE:
|
||||
++group_version;
|
||||
clear_groups();
|
||||
break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED:
|
||||
update_groups();
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
void ProximityGroup::broadcast(String p_name, Variant p_params) {
|
||||
|
||||
Map<StringName, uint32_t>::Element *E;
|
||||
E = groups.front();
|
||||
while (E) {
|
||||
|
||||
get_scene()->call_group(SceneMainLoop::GROUP_CALL_DEFAULT, E->key(), "_proximity_group_broadcast", p_name, p_params);
|
||||
E = E->next();
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
void ProximityGroup::_proximity_group_broadcast(String p_name, Variant p_params) {
|
||||
|
||||
if (dispatch_mode == MODE_PROXY) {
|
||||
|
||||
get_parent()->call(p_name, p_params);
|
||||
} else {
|
||||
|
||||
emit_signal("broadcast", p_name, p_params);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
void ProximityGroup::set_dispatch_mode(int p_mode) {
|
||||
|
||||
dispatch_mode = (DispatchMode)p_mode;
|
||||
};
|
||||
|
||||
void ProximityGroup::set_grid_radius(const Vector3& p_radius) {
|
||||
|
||||
grid_radius = p_radius;
|
||||
};
|
||||
|
||||
Vector3 ProximityGroup::get_grid_radius() const {
|
||||
|
||||
return grid_radius;
|
||||
};
|
||||
|
||||
|
||||
void ProximityGroup::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_group_name","name"), &ProximityGroup::set_group_name);
|
||||
ObjectTypeDB::bind_method(_MD("broadcast","name", "parameters"), &ProximityGroup::broadcast);
|
||||
ObjectTypeDB::bind_method(_MD("set_dispatch_mode","mode"), &ProximityGroup::set_dispatch_mode);
|
||||
ObjectTypeDB::bind_method(_MD("_proximity_group_broadcast","name","params"), &ProximityGroup::_proximity_group_broadcast);
|
||||
ObjectTypeDB::bind_method(_MD("set_grid_radius","radius"), &ProximityGroup::set_grid_radius);
|
||||
ObjectTypeDB::bind_method(_MD("get_grid_radius"), &ProximityGroup::get_grid_radius);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo( Variant::VECTOR3, "grid_radius"), _SCS("set_grid_radius"), _SCS("get_grid_radius"));
|
||||
|
||||
ADD_SIGNAL( MethodInfo("broadcast", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::ARRAY, "parameters")) );
|
||||
};
|
||||
|
||||
|
||||
ProximityGroup::ProximityGroup() {
|
||||
|
||||
group_version = 0;
|
||||
dispatch_mode = MODE_PROXY;
|
||||
|
||||
grid_radius = Vector3(1, 1, 1);
|
||||
|
||||
};
|
||||
|
||||
ProximityGroup::~ProximityGroup() {
|
||||
|
||||
};
|
||||
81
scene/3d/proximity_group.h
Normal file
81
scene/3d/proximity_group.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*************************************************************************/
|
||||
/* proximity_group.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef PROXIMITY_GROUP_H
|
||||
#define PROXIMITY_GROUP_H
|
||||
|
||||
#include "spatial.h"
|
||||
|
||||
class ProximityGroup : public Spatial {
|
||||
|
||||
OBJ_TYPE( ProximityGroup, Spatial );
|
||||
OBJ_CATEGORY("3D");
|
||||
|
||||
public:
|
||||
enum DispatchMode {
|
||||
MODE_PROXY,
|
||||
MODE_SIGNAL,
|
||||
};
|
||||
|
||||
public:
|
||||
void clear_groups();
|
||||
void update_groups();
|
||||
|
||||
void _notification(int p_what);
|
||||
|
||||
DispatchMode dispatch_mode;
|
||||
|
||||
Map<StringName, uint32_t> groups;
|
||||
String group_name;
|
||||
|
||||
float cell_size;
|
||||
Vector3 grid_radius;
|
||||
uint32_t group_version;
|
||||
|
||||
void add_groups(int* p_cell, String p_base, int p_depth);
|
||||
void _new_group(StringName p_name);
|
||||
|
||||
void _proximity_group_broadcast(String p_name, Variant p_params);
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
void set_group_name(String p_group_name);
|
||||
void broadcast(String p_name, Variant p_params);
|
||||
void set_dispatch_mode(int p_mode);
|
||||
|
||||
void set_grid_radius(const Vector3& p_radius);
|
||||
Vector3 get_grid_radius() const;
|
||||
|
||||
ProximityGroup();
|
||||
~ProximityGroup();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
232
scene/3d/quad.cpp
Normal file
232
scene/3d/quad.cpp
Normal file
@ -0,0 +1,232 @@
|
||||
/*************************************************************************/
|
||||
/* quad.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "quad.h"
|
||||
#include "servers/visual_server.h"
|
||||
|
||||
void Quad::_update() {
|
||||
|
||||
if (!is_inside_scene())
|
||||
return;
|
||||
|
||||
Vector3 normal;
|
||||
normal[axis]=1.0;
|
||||
|
||||
const int axis_order_1[3]={1,2,0};
|
||||
const int axis_order_2[3]={2,0,1};
|
||||
const int a1=axis_order_1[axis];
|
||||
const int a2=axis_order_2[axis];
|
||||
|
||||
|
||||
|
||||
DVector<Vector3> points;
|
||||
points.resize(4);
|
||||
DVector<Vector3>::Write pointsw = points.write();
|
||||
|
||||
Vector2 s2 = size*0.5;
|
||||
Vector2 o = offset;
|
||||
if (!centered)
|
||||
o+=s2;
|
||||
|
||||
pointsw[0][a1]=-s2.x+offset.x;
|
||||
pointsw[0][a2]=s2.y+offset.y;
|
||||
|
||||
pointsw[1][a1]=s2.x+offset.x;
|
||||
pointsw[1][a2]=s2.y+offset.y;
|
||||
|
||||
pointsw[2][a1]=s2.x+offset.x;
|
||||
pointsw[2][a2]=-s2.y+offset.y;
|
||||
|
||||
pointsw[3][a1]=-s2.x+offset.x;
|
||||
pointsw[3][a2]=-s2.y+offset.y;
|
||||
|
||||
|
||||
aabb=AABB(pointsw[0],Vector3());
|
||||
for(int i=1;i<4;i++)
|
||||
aabb.expand_to(pointsw[i]);
|
||||
|
||||
pointsw = DVector<Vector3>::Write();
|
||||
|
||||
DVector<Vector3> normals;
|
||||
normals.resize(4);
|
||||
DVector<Vector3>::Write normalsw = normals.write();
|
||||
|
||||
for(int i=0;i<4;i++)
|
||||
normalsw[i]=normal;
|
||||
|
||||
normalsw=DVector<Vector3>::Write();
|
||||
|
||||
|
||||
|
||||
DVector<Vector2> uvs;
|
||||
uvs.resize(4);
|
||||
DVector<Vector2>::Write uvsw = uvs.write();
|
||||
|
||||
uvsw[0]=Vector2(0,0);
|
||||
uvsw[1]=Vector2(1,0);
|
||||
uvsw[2]=Vector2(1,1);
|
||||
uvsw[3]=Vector2(0,1);
|
||||
|
||||
uvsw = DVector<Vector2>::Write();
|
||||
|
||||
DVector<int> indices;
|
||||
indices.resize(6);
|
||||
|
||||
DVector<int>::Write indicesw = indices.write();
|
||||
indicesw[0]=0;
|
||||
indicesw[1]=1;
|
||||
indicesw[2]=2;
|
||||
indicesw[3]=2;
|
||||
indicesw[4]=3;
|
||||
indicesw[5]=0;
|
||||
|
||||
indicesw=DVector<int>::Write();
|
||||
|
||||
Array arr;
|
||||
arr.resize(VS::ARRAY_MAX);
|
||||
arr[VS::ARRAY_VERTEX]=points;
|
||||
arr[VS::ARRAY_NORMAL]=normals;
|
||||
arr[VS::ARRAY_TEX_UV]=uvs;
|
||||
arr[VS::ARRAY_INDEX]=indices;
|
||||
|
||||
|
||||
if (configured) {
|
||||
VS::get_singleton()->mesh_remove_surface(mesh,0);
|
||||
} else {
|
||||
configured=true;
|
||||
}
|
||||
VS::get_singleton()->mesh_add_surface(mesh,VS::PRIMITIVE_TRIANGLES,arr);
|
||||
|
||||
pending_update=false;
|
||||
}
|
||||
|
||||
|
||||
void Quad::set_axis(Vector3::Axis p_axis) {
|
||||
|
||||
axis=p_axis;
|
||||
_update();
|
||||
}
|
||||
|
||||
Vector3::Axis Quad::get_axis() const{
|
||||
|
||||
return axis;
|
||||
}
|
||||
|
||||
void Quad::set_size(const Vector2& p_size){
|
||||
|
||||
size=p_size;
|
||||
_update();
|
||||
}
|
||||
Vector2 Quad::get_size() const{
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void Quad::set_offset(const Vector2& p_offset){
|
||||
|
||||
offset=p_offset;
|
||||
_update();
|
||||
}
|
||||
Vector2 Quad::get_offset() const{
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
void Quad::set_centered(bool p_enabled){
|
||||
|
||||
centered=p_enabled;
|
||||
_update();
|
||||
}
|
||||
bool Quad::is_centered() const{
|
||||
|
||||
return centered;
|
||||
}
|
||||
|
||||
void Quad::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_ENTER_SCENE: {
|
||||
|
||||
if (pending_update)
|
||||
_update();
|
||||
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_SCENE: {
|
||||
|
||||
pending_update=true;
|
||||
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
DVector<Face3> Quad::get_faces(uint32_t p_usage_flags) const {
|
||||
|
||||
return DVector<Face3>();
|
||||
}
|
||||
|
||||
AABB Quad::get_aabb() const {
|
||||
|
||||
return aabb;
|
||||
}
|
||||
|
||||
void Quad::_bind_methods(){
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_axis","axis"),&Quad::set_axis);
|
||||
ObjectTypeDB::bind_method(_MD("get_axis"),&Quad::get_axis);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_size","size"),&Quad::set_size);
|
||||
ObjectTypeDB::bind_method(_MD("get_size"),&Quad::get_size);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_centered","centered"),&Quad::set_centered);
|
||||
ObjectTypeDB::bind_method(_MD("is_centered"),&Quad::is_centered);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_offset","offset"),&Quad::set_offset);
|
||||
ObjectTypeDB::bind_method(_MD("get_offset"),&Quad::get_offset);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo( Variant::INT, "quad/axis", PROPERTY_HINT_ENUM,"X,Y,Z" ), _SCS("set_axis"), _SCS("get_axis"));
|
||||
ADD_PROPERTY( PropertyInfo( Variant::VECTOR2, "quad/size" ), _SCS("set_size"), _SCS("get_size"));
|
||||
ADD_PROPERTY( PropertyInfo( Variant::VECTOR2, "quad/offset" ), _SCS("set_offset"), _SCS("get_offset"));
|
||||
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "quad/centered" ), _SCS("set_centered"), _SCS("is_centered"));
|
||||
|
||||
}
|
||||
|
||||
Quad::Quad() {
|
||||
|
||||
pending_update=true;
|
||||
centered=true;
|
||||
//offset=0;
|
||||
size=Vector2(1,1);
|
||||
axis=Vector3::AXIS_Z;
|
||||
mesh=VisualServer::get_singleton()->mesh_create();
|
||||
set_base(mesh);
|
||||
configured=false;
|
||||
|
||||
}
|
||||
76
scene/3d/quad.h
Normal file
76
scene/3d/quad.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*************************************************************************/
|
||||
/* quad.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef QUAD_H
|
||||
#define QUAD_H
|
||||
|
||||
|
||||
#include "scene/3d/visual_instance.h"
|
||||
#include "rid.h"
|
||||
|
||||
class Quad : public GeometryInstance {
|
||||
|
||||
OBJ_TYPE(Quad,GeometryInstance);
|
||||
|
||||
Vector3::Axis axis;
|
||||
bool centered;
|
||||
Vector2 offset;
|
||||
Vector2 size;
|
||||
|
||||
AABB aabb;
|
||||
bool configured;
|
||||
bool pending_update;
|
||||
RID mesh;
|
||||
|
||||
void _update();
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_axis(Vector3::Axis p_axis);
|
||||
Vector3::Axis get_axis() const;
|
||||
|
||||
void set_size(const Vector2& p_sizze);
|
||||
Vector2 get_size() const;
|
||||
|
||||
void set_offset(const Vector2& p_offset);
|
||||
Vector2 get_offset() const;
|
||||
|
||||
void set_centered(bool p_enabled);
|
||||
bool is_centered() const;
|
||||
|
||||
virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const;
|
||||
virtual AABB get_aabb() const;
|
||||
|
||||
Quad();
|
||||
};
|
||||
|
||||
#endif // QUAD_H
|
||||
190
scene/3d/ray_cast.cpp
Normal file
190
scene/3d/ray_cast.cpp
Normal file
@ -0,0 +1,190 @@
|
||||
/*************************************************************************/
|
||||
/* ray_cast.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "ray_cast.h"
|
||||
|
||||
#include "servers/physics_server.h"
|
||||
#include "collision_object.h"
|
||||
void RayCast::set_cast_to(const Vector3& p_point) {
|
||||
|
||||
cast_to=p_point;
|
||||
if (is_inside_scene() && get_scene()->is_editor_hint())
|
||||
update_gizmo();
|
||||
|
||||
}
|
||||
|
||||
Vector3 RayCast::get_cast_to() const{
|
||||
|
||||
return cast_to;
|
||||
}
|
||||
|
||||
bool RayCast::is_colliding() const{
|
||||
|
||||
return collided;
|
||||
}
|
||||
Object *RayCast::get_collider() const{
|
||||
|
||||
if (against==0)
|
||||
return NULL;
|
||||
|
||||
return ObjectDB::get_instance(against);
|
||||
}
|
||||
|
||||
int RayCast::get_collider_shape() const {
|
||||
|
||||
return against_shape;
|
||||
}
|
||||
Vector3 RayCast::get_collision_point() const{
|
||||
|
||||
return collision_point;
|
||||
}
|
||||
Vector3 RayCast::get_collision_normal() const{
|
||||
|
||||
return collision_normal;
|
||||
}
|
||||
|
||||
|
||||
void RayCast::set_enabled(bool p_enabled) {
|
||||
|
||||
enabled=p_enabled;
|
||||
if (is_inside_scene() && !get_scene()->is_editor_hint())
|
||||
set_fixed_process(p_enabled);
|
||||
if (!p_enabled)
|
||||
collided=false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool RayCast::is_enabled() const {
|
||||
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
|
||||
void RayCast::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_ENTER_SCENE: {
|
||||
|
||||
if (enabled && !get_scene()->is_editor_hint()) {
|
||||
set_fixed_process(true);
|
||||
Node *p = get_parent();
|
||||
while( p && p->cast_to<Spatial>() ) {
|
||||
|
||||
CollisionObject *co = p->cast_to<CollisionObject>();
|
||||
if (co) {
|
||||
|
||||
exception=co->get_rid();
|
||||
exceptions.insert(exception);
|
||||
}
|
||||
|
||||
p=p->get_parent();
|
||||
}
|
||||
} else
|
||||
set_fixed_process(false);
|
||||
|
||||
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_SCENE: {
|
||||
|
||||
if (enabled) {
|
||||
set_fixed_process(false);
|
||||
}
|
||||
|
||||
exceptions.erase(exception);
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_FIXED_PROCESS: {
|
||||
|
||||
if (!enabled)
|
||||
break;
|
||||
|
||||
|
||||
|
||||
Ref<World> w3d = get_world();
|
||||
ERR_BREAK( w3d.is_null() );
|
||||
|
||||
PhysicsDirectSpaceState *dss = PhysicsServer::get_singleton()->space_get_direct_state(w3d->get_space());
|
||||
ERR_BREAK( !dss );
|
||||
|
||||
Transform gt = get_global_transform();
|
||||
|
||||
Vector3 to = cast_to;
|
||||
if (to==Vector3())
|
||||
to=Vector3(0,0.01,0);
|
||||
|
||||
PhysicsDirectSpaceState::RayResult rr;
|
||||
|
||||
if (dss->intersect_ray(gt.get_origin(),gt.xform(to),rr,exceptions)) {
|
||||
|
||||
collided=true;
|
||||
against=rr.collider_id;
|
||||
collision_point=rr.position;
|
||||
collision_normal=rr.normal;
|
||||
against_shape=rr.shape;
|
||||
} else {
|
||||
collided=false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void RayCast::_bind_methods() {
|
||||
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_enabled","enabled"),&RayCast::set_enabled);
|
||||
ObjectTypeDB::bind_method(_MD("is_enabled"),&RayCast::is_enabled);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_cast_to","local_point"),&RayCast::set_cast_to);
|
||||
ObjectTypeDB::bind_method(_MD("get_cast_to"),&RayCast::get_cast_to);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("is_colliding"),&RayCast::is_colliding);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("get_collider"),&RayCast::get_collider);
|
||||
ObjectTypeDB::bind_method(_MD("get_collider_shape"),&RayCast::get_collider_shape);
|
||||
ObjectTypeDB::bind_method(_MD("get_collision_point"),&RayCast::get_collision_point);
|
||||
ObjectTypeDB::bind_method(_MD("get_collision_normal"),&RayCast::get_collision_normal);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled"));
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3,"cast_to"),_SCS("set_cast_to"),_SCS("get_cast_to"));
|
||||
}
|
||||
|
||||
RayCast::RayCast() {
|
||||
|
||||
enabled=false;
|
||||
against=0;
|
||||
collided=false;
|
||||
against_shape=0;
|
||||
cast_to=Vector3(0,-1,0);
|
||||
}
|
||||
72
scene/3d/ray_cast.h
Normal file
72
scene/3d/ray_cast.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*************************************************************************/
|
||||
/* ray_cast.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef RAY_CAST_H
|
||||
#define RAY_CAST_H
|
||||
|
||||
#include "scene/3d/spatial.h"
|
||||
|
||||
class RayCast : public Spatial {
|
||||
|
||||
OBJ_TYPE(RayCast,Spatial);
|
||||
|
||||
|
||||
bool enabled;
|
||||
bool collided;
|
||||
ObjectID against;
|
||||
int against_shape;
|
||||
Vector3 collision_point;
|
||||
Vector3 collision_normal;
|
||||
|
||||
Vector3 cast_to;
|
||||
|
||||
RID exception;
|
||||
Set<RID> exceptions;
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_enabled(bool p_enabled);
|
||||
bool is_enabled() const;
|
||||
|
||||
void set_cast_to(const Vector3& p_point);
|
||||
Vector3 get_cast_to() const;
|
||||
|
||||
bool is_colliding() const;
|
||||
Object *get_collider() const;
|
||||
int get_collider_shape() const;
|
||||
Vector3 get_collision_point() const;
|
||||
Vector3 get_collision_normal() const;
|
||||
|
||||
RayCast();
|
||||
};
|
||||
|
||||
#endif // RAY_CAST_H
|
||||
299
scene/3d/room_instance.cpp
Normal file
299
scene/3d/room_instance.cpp
Normal file
@ -0,0 +1,299 @@
|
||||
/*************************************************************************/
|
||||
/* room_instance.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "room_instance.h"
|
||||
|
||||
#include "servers/visual_server.h"
|
||||
|
||||
#include "geometry.h"
|
||||
#include "globals.h"
|
||||
#include "scene/resources/surface_tool.h"
|
||||
|
||||
|
||||
void Room::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
case NOTIFICATION_ENTER_WORLD: {
|
||||
// go find parent level
|
||||
Node *parent_room=get_parent();
|
||||
level=0;
|
||||
|
||||
while(parent_room) {
|
||||
|
||||
Room *r = parent_room->cast_to<Room>();
|
||||
if (r) {
|
||||
|
||||
level=r->level+1;
|
||||
break;
|
||||
}
|
||||
|
||||
parent_room=parent_room->get_parent();
|
||||
}
|
||||
|
||||
|
||||
if (sound_enabled)
|
||||
SpatialSoundServer::get_singleton()->room_set_space(sound_room,get_world()->get_sound_space());
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
SpatialSoundServer::get_singleton()->room_set_transform(sound_room,get_global_transform());
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_WORLD: {
|
||||
|
||||
if (sound_enabled)
|
||||
SpatialSoundServer::get_singleton()->room_set_space(sound_room,RID());
|
||||
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
RES Room::_get_gizmo_geometry() const {
|
||||
|
||||
DVector<Face3> faces;
|
||||
if (!room.is_null())
|
||||
faces=room->get_geometry_hint();
|
||||
|
||||
int count=faces.size();
|
||||
if (count==0)
|
||||
return RES();
|
||||
|
||||
DVector<Face3>::Read facesr=faces.read();
|
||||
|
||||
const Face3* facesptr=facesr.ptr();
|
||||
|
||||
DVector<Vector3> points;
|
||||
|
||||
Ref<SurfaceTool> surface_tool( memnew( SurfaceTool ));
|
||||
|
||||
Ref<FixedMaterial> mat( memnew( FixedMaterial ));
|
||||
|
||||
mat->set_parameter( FixedMaterial::PARAM_DIFFUSE,Color(0.2,0.8,0.9,0.3) );
|
||||
mat->set_line_width(4);
|
||||
mat->set_flag(Material::FLAG_DOUBLE_SIDED,true);
|
||||
mat->set_flag(Material::FLAG_UNSHADED,true);
|
||||
mat->set_hint(Material::HINT_NO_DEPTH_DRAW,true);
|
||||
|
||||
surface_tool->begin(Mesh::PRIMITIVE_LINES);
|
||||
surface_tool->set_material(mat);
|
||||
|
||||
for (int i=0;i<count;i++) {
|
||||
|
||||
surface_tool->add_vertex(facesptr[i].vertex[0]);
|
||||
surface_tool->add_vertex(facesptr[i].vertex[1]);
|
||||
|
||||
surface_tool->add_vertex(facesptr[i].vertex[1]);
|
||||
surface_tool->add_vertex(facesptr[i].vertex[2]);
|
||||
|
||||
surface_tool->add_vertex(facesptr[i].vertex[2]);
|
||||
surface_tool->add_vertex(facesptr[i].vertex[0]);
|
||||
|
||||
}
|
||||
|
||||
return surface_tool->commit();
|
||||
}
|
||||
|
||||
|
||||
|
||||
AABB Room::get_aabb() const {
|
||||
|
||||
if (room.is_null())
|
||||
return AABB();
|
||||
|
||||
return room->get_bounds().get_aabb();
|
||||
}
|
||||
DVector<Face3> Room::get_faces(uint32_t p_usage_flags) const {
|
||||
|
||||
return DVector<Face3>();
|
||||
|
||||
}
|
||||
|
||||
void Room::set_room( const Ref<RoomBounds>& p_room ) {
|
||||
|
||||
room=p_room;
|
||||
update_gizmo();
|
||||
|
||||
if (room.is_valid()) {
|
||||
|
||||
set_base(room->get_rid());
|
||||
} else {
|
||||
set_base(RID());
|
||||
}
|
||||
|
||||
if (!is_inside_scene())
|
||||
return;
|
||||
|
||||
|
||||
propagate_notification(NOTIFICATION_AREA_CHANGED);
|
||||
update_gizmo();
|
||||
|
||||
if (room.is_valid())
|
||||
SpatialSoundServer::get_singleton()->room_set_bounds(sound_room,room->get_bounds());
|
||||
|
||||
|
||||
}
|
||||
|
||||
Ref<RoomBounds> Room::get_room() const {
|
||||
|
||||
return room;
|
||||
}
|
||||
|
||||
void Room::_parse_node_faces(DVector<Face3> &all_faces,const Node *p_node) const {
|
||||
|
||||
const VisualInstance *vi=p_node->cast_to<VisualInstance>();
|
||||
|
||||
if (vi) {
|
||||
DVector<Face3> faces=vi->get_faces(FACES_ENCLOSING);
|
||||
|
||||
if (faces.size()) {
|
||||
int old_len=all_faces.size();
|
||||
all_faces.resize( all_faces.size() + faces.size() );
|
||||
int new_len=all_faces.size();
|
||||
DVector<Face3>::Write all_facesw=all_faces.write();
|
||||
Face3 * all_facesptr=all_facesw.ptr();
|
||||
|
||||
DVector<Face3>::Read facesr=faces.read();
|
||||
const Face3 * facesptr=facesr.ptr();
|
||||
|
||||
Transform tr=vi->get_relative_transform(this);
|
||||
|
||||
for(int i=old_len;i<new_len;i++) {
|
||||
|
||||
Face3 f=facesptr[i-old_len];
|
||||
for (int j=0;j<3;j++)
|
||||
f.vertex[j]=tr.xform(f.vertex[j]);
|
||||
all_facesptr[i]=f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int i=0;i<p_node->get_child_count();i++) {
|
||||
|
||||
_parse_node_faces(all_faces,p_node->get_child(i));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Room::compute_room_from_subtree() {
|
||||
|
||||
|
||||
DVector<Face3> all_faces;
|
||||
_parse_node_faces(all_faces,this);
|
||||
|
||||
|
||||
if (all_faces.size()==0)
|
||||
return;
|
||||
float error;
|
||||
DVector<Face3> wrapped_faces = Geometry::wrap_geometry(all_faces,&error);
|
||||
|
||||
|
||||
if (wrapped_faces.size()==0)
|
||||
return;
|
||||
|
||||
BSP_Tree tree(wrapped_faces,error);
|
||||
|
||||
Ref<RoomBounds> room( memnew( RoomBounds ) );
|
||||
room->set_bounds(tree);
|
||||
room->set_geometry_hint(wrapped_faces);
|
||||
|
||||
set_room(room);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Room::set_simulate_acoustics(bool p_enable) {
|
||||
|
||||
if (sound_enabled==p_enable)
|
||||
return;
|
||||
|
||||
sound_enabled=p_enable;
|
||||
if (!is_inside_world())
|
||||
return; //nothing to do
|
||||
|
||||
if (sound_enabled)
|
||||
SpatialSoundServer::get_singleton()->room_set_space(sound_room,get_world()->get_sound_space());
|
||||
else
|
||||
SpatialSoundServer::get_singleton()->room_set_space(sound_room,RID());
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Room::_bounds_changed() {
|
||||
|
||||
update_gizmo();
|
||||
}
|
||||
|
||||
bool Room::is_simulating_acoustics() const {
|
||||
|
||||
return sound_enabled;
|
||||
}
|
||||
|
||||
|
||||
|
||||
RID Room::get_sound_room() const {
|
||||
|
||||
return RID();
|
||||
}
|
||||
|
||||
void Room::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_room","room:Room"),&Room::set_room );
|
||||
ObjectTypeDB::bind_method(_MD("get_room:Room"),&Room::get_room );
|
||||
ObjectTypeDB::bind_method(_MD("compute_room_from_subtree"),&Room::compute_room_from_subtree);
|
||||
|
||||
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_simulate_acoustics","enable"),&Room::set_simulate_acoustics );
|
||||
ObjectTypeDB::bind_method(_MD("is_simulating_acoustics"),&Room::is_simulating_acoustics );
|
||||
|
||||
|
||||
|
||||
ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "room/room", PROPERTY_HINT_RESOURCE_TYPE, "Area" ), _SCS("set_room"), _SCS("get_room") );
|
||||
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "room/simulate_acoustics"), _SCS("set_simulate_acoustics"), _SCS("is_simulating_acoustics") );
|
||||
}
|
||||
|
||||
|
||||
Room::Room() {
|
||||
|
||||
sound_enabled=false;
|
||||
sound_room=SpatialSoundServer::get_singleton()->room_create();
|
||||
|
||||
level=0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
Room::~Room() {
|
||||
|
||||
SpatialSoundServer::get_singleton()->free(sound_room);
|
||||
}
|
||||
|
||||
102
scene/3d/room_instance.h
Normal file
102
scene/3d/room_instance.h
Normal file
@ -0,0 +1,102 @@
|
||||
/*************************************************************************/
|
||||
/* room_instance.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef ROOM_INSTANCE_H
|
||||
#define ROOM_INSTANCE_H
|
||||
|
||||
#include "scene/3d/visual_instance.h"
|
||||
#include "scene/resources/room.h"
|
||||
#include "servers/spatial_sound_server.h"
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
/* RoomInstance Logic:
|
||||
a) Instances that belong to the room are drawn only if the room is visible (seen through portal, or player inside)
|
||||
b) Instances that don't belong to any room are considered to belong to the root room (RID empty)
|
||||
c) "dynamic" Instances are assigned to the rooms their AABB touch
|
||||
|
||||
*/
|
||||
|
||||
|
||||
class Room : public VisualInstance {
|
||||
|
||||
OBJ_TYPE( Room, VisualInstance );
|
||||
public:
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
Ref<RoomBounds> room;
|
||||
|
||||
RID sound_room;
|
||||
|
||||
bool sound_enabled;
|
||||
|
||||
int level;
|
||||
void _parse_node_faces(DVector<Face3> &all_faces,const Node *p_node) const;
|
||||
|
||||
|
||||
void _bounds_changed();
|
||||
virtual RES _get_gizmo_geometry() const;
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
enum {
|
||||
// used to notify portals that the room in which they are has changed.
|
||||
NOTIFICATION_AREA_CHANGED=60
|
||||
};
|
||||
|
||||
virtual AABB get_aabb() const;
|
||||
virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const;
|
||||
|
||||
void set_room( const Ref<RoomBounds>& p_room );
|
||||
Ref<RoomBounds> get_room() const;
|
||||
|
||||
void set_simulate_acoustics(bool p_enable);
|
||||
bool is_simulating_acoustics() const;
|
||||
|
||||
void compute_room_from_subtree();
|
||||
|
||||
RID get_sound_room() const;
|
||||
|
||||
Room();
|
||||
~Room();
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // ROOM_INSTANCE_H
|
||||
74
scene/3d/scenario_fx.cpp
Normal file
74
scene/3d/scenario_fx.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
/*************************************************************************/
|
||||
/* scenario_fx.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "scenario_fx.h"
|
||||
|
||||
|
||||
|
||||
void WorldEnvironment::_notification(int p_what) {
|
||||
|
||||
|
||||
if (p_what==NOTIFICATION_ENTER_WORLD) {
|
||||
|
||||
get_world()->set_environment(environment);
|
||||
} else if (p_what==NOTIFICATION_EXIT_WORLD) {
|
||||
|
||||
get_world()->set_environment(Ref<Environment>());
|
||||
}
|
||||
}
|
||||
|
||||
void WorldEnvironment::set_environment(const Ref<Environment>& p_environment) {
|
||||
|
||||
environment=p_environment;
|
||||
if (is_inside_world()) {
|
||||
get_world()->set_environment(environment);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Ref<Environment> WorldEnvironment::get_environment() const {
|
||||
|
||||
return environment;
|
||||
}
|
||||
|
||||
|
||||
void WorldEnvironment::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_environment","env:Environment"),&WorldEnvironment::set_environment);
|
||||
ObjectTypeDB::bind_method(_MD("get_environment:Environment"),&WorldEnvironment::get_environment);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"environment",PROPERTY_HINT_RESOURCE_TYPE,"Environment"),_SCS("set_environment"),_SCS("get_environment"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
WorldEnvironment::WorldEnvironment() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
58
scene/3d/scenario_fx.h
Normal file
58
scene/3d/scenario_fx.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*************************************************************************/
|
||||
/* scenario_fx.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef SCENARIO_FX_H
|
||||
#define SCENARIO_FX_H
|
||||
|
||||
#include "scene/3d/spatial.h"
|
||||
|
||||
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
class WorldEnvironment : public Spatial {
|
||||
|
||||
OBJ_TYPE(WorldEnvironment,Spatial );
|
||||
|
||||
Ref<Environment> environment;
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
void set_environment(const Ref<Environment>& p_environment);
|
||||
Ref<Environment> get_environment() const;
|
||||
|
||||
WorldEnvironment();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user