Преглед на файлове

new space shooter demo

ortho camera sort fix, closes #2063
Juan Linietsky преди 10 години
родител
ревизия
9e479065f5
променени са 44 файла, в които са добавени 468 реда и са изтрити 44 реда
  1. 49 0
      demos/2d/space_shooter/asteroid.gd
  2. BIN
      demos/2d/space_shooter/asteroid.scn
  3. BIN
      demos/2d/space_shooter/bg_gradient.png
  4. BIN
      demos/2d/space_shooter/big_star.png
  5. 37 0
      demos/2d/space_shooter/enemy1.gd
  6. BIN
      demos/2d/space_shooter/enemy1.png
  7. BIN
      demos/2d/space_shooter/enemy1.scn
  8. 56 0
      demos/2d/space_shooter/enemy2.gd
  9. BIN
      demos/2d/space_shooter/enemy2.png
  10. BIN
      demos/2d/space_shooter/enemy2.scn
  11. 32 0
      demos/2d/space_shooter/enemy_shot.gd
  12. BIN
      demos/2d/space_shooter/enemy_shot.png
  13. BIN
      demos/2d/space_shooter/enemy_shot.scn
  14. 21 0
      demos/2d/space_shooter/engine.cfg
  15. BIN
      demos/2d/space_shooter/explosion.scn
  16. BIN
      demos/2d/space_shooter/fire.png
  17. 24 0
      demos/2d/space_shooter/game_state.gd
  18. BIN
      demos/2d/space_shooter/level.scn
  19. BIN
      demos/2d/space_shooter/level_tiles.res
  20. BIN
      demos/2d/space_shooter/level_tiles.scn
  21. 20 0
      demos/2d/space_shooter/main_menu.gd
  22. BIN
      demos/2d/space_shooter/main_menu.scn
  23. BIN
      demos/2d/space_shooter/meteorite.png
  24. BIN
      demos/2d/space_shooter/parallax.scn
  25. 26 0
      demos/2d/space_shooter/rail.gd
  26. 88 0
      demos/2d/space_shooter/ship.gd
  27. BIN
      demos/2d/space_shooter/ship.png
  28. BIN
      demos/2d/space_shooter/ship.scn
  29. BIN
      demos/2d/space_shooter/shoot.png
  30. 47 0
      demos/2d/space_shooter/shot.gd
  31. BIN
      demos/2d/space_shooter/shot.scn
  32. BIN
      demos/2d/space_shooter/small_star.png
  33. BIN
      demos/2d/space_shooter/sound_explode.wav
  34. BIN
      demos/2d/space_shooter/sound_shoot.wav
  35. BIN
      demos/2d/space_shooter/tile.png
  36. 8 3
      drivers/gles2/rasterizer_gles2.cpp
  37. 2 1
      drivers/gles2/rasterizer_gles2.h
  38. 1 0
      makerel.bat
  39. 37 31
      scene/2d/camera_2d.cpp
  40. 11 3
      scene/2d/camera_2d.h
  41. 1 1
      servers/visual/rasterizer.h
  42. 1 1
      servers/visual/rasterizer_dummy.cpp
  43. 1 1
      servers/visual/rasterizer_dummy.h
  44. 6 3
      servers/visual/visual_server_raster.cpp

+ 49 - 0
demos/2d/space_shooter/asteroid.gd

@@ -0,0 +1,49 @@
+
+extends Area2D
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+const SPEED=-200
+const Y_RANDOM=10
+
+var points=1
+
+
+var speed_y=0.0
+
+func _process(delta):
+
+	translate( Vector2(SPEED,speed_y) * delta )
+
+func _ready():
+	# Initialization here	
+	speed_y=rand_range(-Y_RANDOM,Y_RANDOM)
+	pass
+
+var destroyed=false
+
+func destroy():
+	if (destroyed):
+		return	
+	destroyed=true
+	get_node("anim").play("explode")
+	set_process(false)
+	get_node("sfx").play("sound_explode")
+	#accum points
+	get_node("/root/game_state").points+=1
+	
+func is_enemy():
+	return not destroyed	
+	
+
+func _on_visibility_enter_screen():
+	set_process(true)
+	#make it spin!
+	get_node("anim").play("spin")
+	
+
+func _on_visibility_exit_screen():
+	queue_free()
+	pass # replace with function body

BIN
demos/2d/space_shooter/asteroid.scn


BIN
demos/2d/space_shooter/bg_gradient.png


BIN
demos/2d/space_shooter/big_star.png


+ 37 - 0
demos/2d/space_shooter/enemy1.gd

@@ -0,0 +1,37 @@
+
+extends Area2D
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+const SPEED=-200
+
+func _process(delta):
+	get_parent().translate(Vector2(SPEED*delta,0))
+
+	
+var destroyed=false
+
+func is_enemy():
+	return not destroyed
+
+
+func destroy():
+	if (destroyed):
+		return	
+	destroyed=true
+	get_node("anim").play("explode")
+	set_process(false)	
+	get_node("sfx").play("sound_explode")
+	#accum points
+	get_node("/root/game_state").points+=5
+
+func _on_visibility_enter_screen():
+	set_process(true)
+	get_node("anim").play("zigzag")	
+	get_node("anim").seek(randf()*2.0) #make it start from any pos
+
+func _on_visibility_exit_screen():
+	queue_free()
+	

BIN
demos/2d/space_shooter/enemy1.png


BIN
demos/2d/space_shooter/enemy1.scn


+ 56 - 0
demos/2d/space_shooter/enemy2.gd

@@ -0,0 +1,56 @@
+
+extends Area2D
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+const SPEED=-220
+const SHOOT_INTERVAL=1
+var shoot_timeout=0
+
+func _process(delta):
+	translate( Vector2(SPEED*delta,0) )
+	shoot_timeout-=delta
+	
+	if (shoot_timeout<0):
+	
+		shoot_timeout=SHOOT_INTERVAL
+		
+		#instance a shot
+		var shot = preload("res://enemy_shot.scn").instance()
+		#set pos as "shoot_from" Position2D node
+		shot.set_pos( get_node("shoot_from").get_global_pos() )
+		#add it to parent, so it has world coordinates
+		get_parent().add_child(shot)
+		
+var destroyed=false
+
+func is_enemy():
+	return not destroyed
+
+func destroy():
+	if (destroyed):
+		return	
+	destroyed=true
+	get_node("anim").play("explode")
+	set_process(false)	
+	get_node("sfx").play("sound_explode")
+	#accum points
+	get_node("/root/game_state").points+=10
+
+func _ready():
+	set_fixed_process(true)
+	# Initialization here
+	pass
+
+
+
+
+func _on_visibility_enter_screen():
+	set_process(true)
+	pass # replace with function body
+
+
+func _on_visibility_exit_screen():
+	queue_free()
+	pass # replace with function body

BIN
demos/2d/space_shooter/enemy2.png


BIN
demos/2d/space_shooter/enemy2.scn


+ 32 - 0
demos/2d/space_shooter/enemy_shot.gd

@@ -0,0 +1,32 @@
+
+extends Area2D
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+const SPEED = -800
+
+func _process(delta):
+	translate(Vector2(delta*SPEED,0))
+
+func _ready():
+	# Initialization here
+	set_process(true)
+
+
+var hit=false
+
+func is_enemy():
+	return true
+
+func _hit_something():
+	if (hit):
+		return
+	hit=true
+	set_process(false)
+	get_node("anim").play("splash")
+
+func _on_visibility_exit_screen():
+	queue_free()
+	

BIN
demos/2d/space_shooter/enemy_shot.png


BIN
demos/2d/space_shooter/enemy_shot.scn


+ 21 - 0
demos/2d/space_shooter/engine.cfg

@@ -0,0 +1,21 @@
+[application]
+
+name="Simple Shooter"
+main_scene="res://main_menu.scn"
+
+[autoload]
+
+game_state="res://game_state.gd"
+
+[display]
+
+width=1024
+height=600
+
+[input]
+
+move_up=[key(Up)]
+move_down=[key(Down)]
+move_left=[key(Left)]
+move_right=[key(Right)]
+shoot=[key(Space)]

BIN
demos/2d/space_shooter/explosion.scn


BIN
demos/2d/space_shooter/fire.png


+ 24 - 0
demos/2d/space_shooter/game_state.gd

@@ -0,0 +1,24 @@
+extends Node
+
+
+var points = 0
+var max_points = 0
+
+
+func _ready():
+	var f = File.new()
+	#load high score
+	if (f.open("user://highscore",File.READ)==OK):
+		
+		max_points=f.get_var()
+
+
+
+func game_over():
+	if (points>max_points):
+		max_points=points
+		#save high score
+		var f = File.new()
+		f.open("user://highscore",File.WRITE)
+		f.store_var(max_points)
+		

BIN
demos/2d/space_shooter/level.scn


BIN
demos/2d/space_shooter/level_tiles.res


BIN
demos/2d/space_shooter/level_tiles.scn


+ 20 - 0
demos/2d/space_shooter/main_menu.gd

@@ -0,0 +1,20 @@
+
+extends Control
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+func _ready():
+
+	get_node("score").set_text( "HIGH SCORE: "+str( get_node("/root/game_state").max_points ) )
+	# Initialization here
+	pass
+
+
+
+
+func _on_play_pressed():
+	get_node("/root/game_state").points=0
+	get_tree().change_scene("res://level.scn")
+	pass # replace with function body

BIN
demos/2d/space_shooter/main_menu.scn


BIN
demos/2d/space_shooter/meteorite.png


BIN
demos/2d/space_shooter/parallax.scn


+ 26 - 0
demos/2d/space_shooter/rail.gd

@@ -0,0 +1,26 @@
+
+extends Node2D
+
+
+const SPEED=200
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+func stop():
+	set_process(false)
+
+var offset=0
+
+
+func _process(delta):
+	
+	offset+=delta*SPEED
+	set_pos(Vector2(offset,0))
+
+func _ready():
+	set_process(true)
+	# Initialization here
+	
+
+

+ 88 - 0
demos/2d/space_shooter/ship.gd

@@ -0,0 +1,88 @@
+
+extends Area2D
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+const SPEED = 200
+
+var screen_size
+
+var prev_shooting=false
+
+func _process(delta):
+
+	var motion = Vector2()
+	if Input.is_action_pressed("move_up"):
+		motion+=Vector2(0,-1)
+	if Input.is_action_pressed("move_down"):
+		motion+=Vector2(0,1)
+	if Input.is_action_pressed("move_left"):
+		motion+=Vector2(-1,0)
+	if Input.is_action_pressed("move_right"):
+		motion+=Vector2(1,0)
+	var shooting = Input.is_action_pressed("shoot")
+		
+	var pos = get_pos()
+	
+	pos+=motion*delta*SPEED
+	if (pos.x<0):
+		pos.x=0
+	if (pos.x>screen_size.x):
+		pos.x=screen_size.x
+	if (pos.y<0):
+		pos.y=0
+	if (pos.y>screen_size.y):
+		pos.y=screen_size.y
+
+	set_pos(pos)
+	
+	if (shooting and not prev_shooting):
+		# just pressed
+		var shot = preload("res://shot.scn").instance()
+		#use the position3d as reference
+		shot.set_pos( get_node("shootfrom").get_global_pos() )
+		#put it two parents above, so it is not moved by us
+		get_node("../..").add_child(shot)
+		#play sound
+		get_node("sfx").play("shoot")
+		
+	
+	prev_shooting = shooting
+
+	#update points counter
+	get_node("../hud/score_points").set_text( str(get_node("/root/game_state").points) )
+
+func _ready():
+	# Initialization here
+	screen_size = get_viewport().get_rect().size
+	set_process(true)
+	pass
+
+var killed=false
+
+func _hit_something():
+	if (killed):
+		return
+	killed=true
+	get_node("anim").play("explode")
+	get_node("sfx").play("sound_explode")
+	get_node("../hud/game_over").show()
+	get_node("/root/game_state").game_over()
+	get_parent().stop()
+	set_process(false)
+
+
+func _on_ship_body_enter( body ):
+	_hit_something()
+
+
+func _on_ship_area_enter( area ):
+	if (area.has_method("is_enemy") and area.is_enemy()):
+		_hit_something()
+
+
+func _on_back_to_menu_pressed():
+	get_tree().change_scene("res://main_menu.scn")
+	pass # replace with function body

BIN
demos/2d/space_shooter/ship.png


BIN
demos/2d/space_shooter/ship.scn


BIN
demos/2d/space_shooter/shoot.png


+ 47 - 0
demos/2d/space_shooter/shot.gd

@@ -0,0 +1,47 @@
+
+extends Area2D
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+const SPEED = 800
+
+func _process(delta):
+	translate(Vector2(delta*SPEED,0))
+
+func _ready():
+	# Initialization here
+	set_process(true)
+	pass
+
+var hit=false
+
+func _hit_something():
+	if (hit):
+		return
+	hit=true
+	set_process(false)
+	get_node("anim").play("splash")
+
+func _on_visibility_exit_screen():
+	queue_free()
+	pass # replace with function body
+
+
+
+func _on_shot_area_enter( area ):
+	#hit an enemy or asteroid
+	if (area.has_method("destroy")):
+		#duck typing at it's best
+		area.destroy()
+		_hit_something()
+	
+	
+	pass 
+
+
+func _on_shot_body_enter( body ):
+	#hit the tilemap
+	_hit_something()
+	pass # replace with function body

BIN
demos/2d/space_shooter/shot.scn


BIN
demos/2d/space_shooter/small_star.png


BIN
demos/2d/space_shooter/sound_explode.wav


BIN
demos/2d/space_shooter/sound_shoot.wav


BIN
demos/2d/space_shooter/tile.png


+ 8 - 3
drivers/gles2/rasterizer_gles2.cpp

@@ -4394,7 +4394,7 @@ void RasterizerGLES2::begin_shadow_map( RID p_light_instance, int p_shadow_pass
 
 }
 
-void RasterizerGLES2::set_camera(const Transform& p_world,const CameraMatrix& p_projection) {
+void RasterizerGLES2::set_camera(const Transform& p_world,const CameraMatrix& p_projection,bool p_ortho_hint) {
 
 	camera_transform=p_world;
 	if (current_rt && current_rt_vflip) {
@@ -4406,6 +4406,7 @@ void RasterizerGLES2::set_camera(const Transform& p_world,const CameraMatrix& p_
 	camera_z_near=camera_projection.get_z_near();
 	camera_z_far=camera_projection.get_z_far();
 	camera_projection.get_viewport_size(camera_vp_size.x,camera_vp_size.y);
+	camera_ortho=p_ortho_hint;
 }
 
 void RasterizerGLES2::add_light( RID p_light_instance ) {
@@ -4768,8 +4769,11 @@ void RasterizerGLES2::_add_geometry( const Geometry* p_geometry, const InstanceD
 	e->geometry_cmp=p_geometry_cmp;
 	e->material=m;
 	e->instance=p_instance;
-	//e->depth=camera_plane.distance_to(p_world->origin);
-	e->depth=camera_transform.origin.distance_to(p_instance->transform.origin);
+	if (camera_ortho) {
+		e->depth=camera_plane.distance_to(p_instance->transform.origin);
+	} else {
+		e->depth=camera_transform.origin.distance_to(p_instance->transform.origin);
+	}
 	e->owner=p_owner;
 	e->light_type=0;
 	e->additive=false;
@@ -10796,6 +10800,7 @@ void RasterizerGLES2::init() {
 	current_rt=NULL;
 	current_vd=NULL;
 	current_debug=VS::SCENARIO_DEBUG_DISABLED;
+	camera_ortho=false;
 
 	glGenBuffers(1,&gui_quad_buffer);
 	glBindBuffer(GL_ARRAY_BUFFER,gui_quad_buffer);

+ 2 - 1
drivers/gles2/rasterizer_gles2.h

@@ -1052,6 +1052,7 @@ class RasterizerGLES2 : public Rasterizer {
 	float camera_z_near;
 	float camera_z_far;
 	Size2 camera_vp_size;
+	bool camera_ortho;
 	Set<String> extensions;
 	bool texscreen_copied;
 	bool texscreen_used;
@@ -1589,7 +1590,7 @@ public:
 
 	virtual void begin_shadow_map( RID p_light_instance, int p_shadow_pass );
 
-	virtual void set_camera(const Transform& p_world,const CameraMatrix& p_projection);
+	virtual void set_camera(const Transform& p_world,const CameraMatrix& p_projection,bool p_ortho_hint);
 
 	virtual void add_light( RID p_light_instance ); ///< all "add_light" calls happen before add_geometry calls
 

+ 1 - 0
makerel.bat

@@ -0,0 +1 @@
+"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" && c:\python27\scons p=windows target=debug_release tools=no

+ 37 - 31
scene/2d/camera_2d.cpp

@@ -81,43 +81,47 @@ Matrix32 Camera2D::get_camera_transform()  {
 	if (!first) {
 
 
-		if (centered) {
+		if (anchor_mode==ANCHOR_MODE_DRAG_CENTER) {
 
-            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_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 (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) {
 
-            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]));
 
-                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 {
 
-            } 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 (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;
-                }
-            }
+		} else if (anchor_mode==ANCHOR_MODE_FIXED_TOP_LEFT){
 
+			camera_pos=new_camera_pos;
 		}
 
 
+
 		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;
+			//			camera_pos=camera_pos*(1.0-smoothing)+new_camera_pos*smoothing;
 		} else {
 
 			ret_camera_pos=smoothed_camera_pos=camera_pos;
@@ -132,7 +136,7 @@ Matrix32 Camera2D::get_camera_transform()  {
 	}
 
 
-	Point2 screen_offset = (centered ? (screen_size * 0.5 * zoom) : Point2());
+	Point2 screen_offset = (anchor_mode==ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5 * zoom) : Point2());
 
 	float angle = get_global_transform().get_rotation();
 	if(rotating){
@@ -267,15 +271,15 @@ Vector2 Camera2D::get_offset() const{
 	return offset;
 }
 
-void Camera2D::set_centered(bool p_centered){
+void Camera2D::set_anchor_mode(AnchorMode p_anchor_mode){
 
-	centered=p_centered;
+	anchor_mode=p_anchor_mode;
 	_update_scroll();
 }
 
-bool Camera2D::is_centered() const {
+Camera2D::AnchorMode Camera2D::get_anchor_mode() const {
 
-	return centered;
+	return anchor_mode;
 }
 
 void Camera2D::set_rotating(bool p_rotating){
@@ -439,8 +443,8 @@ 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("set_anchor_mode","anchor_mode"),&Camera2D::set_anchor_mode);
+	ObjectTypeDB::bind_method(_MD("get_anchor_mode"),&Camera2D::get_anchor_mode);
 
 	ObjectTypeDB::bind_method(_MD("set_rotating","rotating"),&Camera2D::set_rotating);
 	ObjectTypeDB::bind_method(_MD("is_rotating"),&Camera2D::is_rotating);
@@ -487,7 +491,7 @@ void Camera2D::_bind_methods() {
 
 
 	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::INT,"anchor_mode",PROPERTY_HINT_ENUM,"Fixed TopLeft,Drag Center"),_SCS("set_anchor_mode"),_SCS("get_anchor_mode"));
 	ADD_PROPERTY( PropertyInfo(Variant::BOOL,"rotating"),_SCS("set_rotating"),_SCS("is_rotating"));
 	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") );
@@ -507,6 +511,8 @@ void Camera2D::_bind_methods() {
 	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);
 
 
+	BIND_CONSTANT( ANCHOR_MODE_DRAG_CENTER );
+	BIND_CONSTANT( ANCHOR_MODE_FIXED_TOP_LEFT );
 
 }
 
@@ -514,7 +520,7 @@ Camera2D::Camera2D() {
 
 
 
-	centered=true;
+	anchor_mode=ANCHOR_MODE_DRAG_CENTER;
 	rotating=false;
 	current=false;
 	limit[MARGIN_LEFT]=-10000000;

+ 11 - 3
scene/2d/camera_2d.h

@@ -36,6 +36,12 @@
 class Camera2D : public Node2D {
 
 	OBJ_TYPE( Camera2D, Node2D );
+public:
+
+	enum AnchorMode {
+		ANCHOR_MODE_FIXED_TOP_LEFT,
+		ANCHOR_MODE_DRAG_CENTER
+	};
 
 protected:
 	Point2 camera_pos;
@@ -49,7 +55,7 @@ protected:
 	RID canvas;
 	Vector2 offset;
 	Vector2 zoom;
-	bool centered;
+	AnchorMode anchor_mode;
 	bool rotating;
 	bool current;
 	float smoothing;
@@ -77,8 +83,8 @@ public:
 	void set_offset(const Vector2& p_offset);
 	Vector2 get_offset() const;
 
-	void set_centered(bool p_centered);
-	bool is_centered() const;
+	void set_anchor_mode(AnchorMode p_anchor_mode);
+	AnchorMode get_anchor_mode() const;
 
 	void set_rotating(bool p_rotating);
 	bool is_rotating() const;
@@ -120,4 +126,6 @@ public:
 	Camera2D();
 };
 
+VARIANT_ENUM_CAST(Camera2D::AnchorMode);
+
 #endif // CAMERA_2D_H

+ 1 - 1
servers/visual/rasterizer.h

@@ -502,7 +502,7 @@ public:
 	virtual void begin_scene(RID p_viewport_data,RID p_env,VS::ScenarioDebugMode p_debug)=0;
 	virtual void begin_shadow_map( RID p_light_instance, int p_shadow_pass )=0;
 
-	virtual void set_camera(const Transform& p_world,const CameraMatrix& p_projection)=0;
+	virtual void set_camera(const Transform& p_world,const CameraMatrix& p_projection,bool p_ortho_hint)=0;
 	
 	virtual void add_light( RID p_light_instance )=0; ///< all "add_light" calls happen before add_geometry calls
 	

+ 1 - 1
servers/visual/rasterizer_dummy.cpp

@@ -1497,7 +1497,7 @@ void RasterizerDummy::begin_shadow_map( RID p_light_instance, int p_shadow_pass
 
 }
 
-void RasterizerDummy::set_camera(const Transform& p_world,const CameraMatrix& p_projection) {
+void RasterizerDummy::set_camera(const Transform& p_world, const CameraMatrix& p_projection, bool p_ortho_hint) {
 
 
 }

+ 1 - 1
servers/visual/rasterizer_dummy.h

@@ -679,7 +679,7 @@ public:
 	virtual void begin_scene(RID p_viewport_data,RID p_env,VS::ScenarioDebugMode p_debug);
 	virtual void begin_shadow_map( RID p_light_instance, int p_shadow_pass );
 
-	virtual void set_camera(const Transform& p_world,const CameraMatrix& p_projection);
+	virtual void set_camera(const Transform& p_world,const CameraMatrix& p_projection,bool p_ortho_hint);
 
 	virtual void add_light( RID p_light_instance ); ///< all "add_light" calls happen before add_geometry calls
 

+ 6 - 3
servers/visual/visual_server_raster.cpp

@@ -6302,7 +6302,7 @@ void VisualServerRaster::_render_no_camera(Viewport *p_viewport,Camera *p_camera
 	else
 		environment=p_scenario->fallback_environment;
 
-	rasterizer->set_camera(Transform(),CameraMatrix());
+	rasterizer->set_camera(Transform(),CameraMatrix(),false);
 	rasterizer->begin_scene(p_viewport->viewport_data,environment,p_scenario->debug);
 	rasterizer->set_viewport(viewport_rect);
 	rasterizer->end_scene();
@@ -6318,7 +6318,8 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S
 
 	/* STEP 1 - SETUP CAMERA */
 	CameraMatrix camera_matrix;
-	
+	bool ortho=false;
+
 	switch(p_camera->type) {
 		case Camera::ORTHOGONAL: {
 		
@@ -6330,6 +6331,7 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S
 				p_camera->vaspect
 
 			);
+			ortho=true;
 		} break;
 		case Camera::PERSPECTIVE: {
 
@@ -6341,12 +6343,13 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S
 				p_camera->vaspect
 
 			);
+			ortho=false;
 				
 		} break;		
 	}
 
 
-	rasterizer->set_camera(p_camera->transform, camera_matrix);
+	rasterizer->set_camera(p_camera->transform, camera_matrix,ortho);
 	
 	Vector<Plane> planes = camera_matrix.get_projection_planes(p_camera->transform);