Răsfoiți Sursa

camera 2d working

Nicolas Cannasse 5 ani în urmă
părinte
comite
cdaf5ca799
3 a modificat fișierele cu 225 adăugiri și 8 ștergeri
  1. 190 0
      hide/comp/CameraController2D.hx
  2. 32 7
      hide/comp/SceneEditor.hx
  3. 3 1
      hide/view/Prefab.hx

+ 190 - 0
hide/comp/CameraController2D.hx

@@ -0,0 +1,190 @@
+package hide.comp;
+
+class CameraController2D extends h2d.Object {
+
+	public var friction = 0.4;
+	public var zoomAmount = 1.15;
+	public var panSpeed = 1.;
+	public var smooth = 0.6;
+
+	var scene : h2d.Scene;
+	var pushing = -1;
+	var pushX = 0.;
+	var pushY = 0.;
+	var pushStartX = 0.;
+	var pushStartY = 0.;
+	var moveX = 0.;
+	var moveY = 0.;
+	var pushTime : Float;
+	var curPos = new h3d.col.Point();
+	var targetPos = new h3d.col.Point();
+
+	public function new(?parent) {
+		super(parent);
+		name = "CameraController";
+	}
+
+	/**
+		Set the controller parameters.
+		Distance is ray distance from target.
+		Theta and Phi are the two spherical angles
+		Target is the target position
+	**/
+	public function set( x : Float, y : Float, ?zoom : Float ) {
+		targetPos.x = x;
+		targetPos.y = y;
+		if( zoom != null ) targetPos.z = zoom;
+	}
+
+	/**
+		Load current position from current camera position and target.
+		Call if you want to modify manually the camera.
+	**/
+	public function loadFromScene( animate = false ) {
+		var scene = if( scene == null ) getScene() else scene;
+		if( scene == null ) throw "Not in scene";
+		targetPos.set( (scene.width*0.5-parent.x) / parent.scaleX, (scene.height*0.5-parent.y) / parent.scaleX, parent.scaleX);
+		if( !animate )
+			toTarget();
+		else
+			syncCamera(); // reset camera to current
+	}
+
+	/**
+		Initialize to look at the whole scene, based on reported scene bounds.
+	**/
+	public function initFromScene() {
+		var scene = getScene();
+		if( scene == null ) throw "Not in scene";
+		var bounds = parent.getBounds(parent);
+		var center = bounds.getCenter();
+
+		var scale = Math.min(1, Math.min(scene.width / bounds.width, scene.height / bounds.height));
+		parent.setScale(scale);
+		parent.x = scene.width * 0.5 - center.x;
+		parent.y = scene.height * 0.5 - center.y;
+		loadFromScene();
+	}
+
+	/**
+		Stop animation by directly moving to end position.
+		Call after set() if you don't want to animate the change
+	**/
+	public function toTarget() {
+		curPos.load(targetPos);
+		syncCamera();
+	}
+
+	override function onAdd() {
+		super.onAdd();
+		scene = getScene();
+		scene.addEventListener(onEvent);
+		targetPos.load(curPos);
+	}
+
+	override function onRemove() {
+		super.onRemove();
+		scene.removeEventListener(onEvent);
+		scene = null;
+	}
+
+	public dynamic function onClick( e : hxd.Event ) {
+	}
+
+	function onEvent( e : hxd.Event ) {
+
+		var p : h2d.Object = this;
+		while( p != null ) {
+			if( !p.visible ) {
+				e.propagate = true;
+				return;
+			}
+			p = p.parent;
+		}
+
+		switch( e.kind ) {
+		case EWheel:
+			zoom(e.wheelDelta);
+		case EPush:
+			@:privateAccess scene.events.startDrag(onEvent, function() pushing = -1, e);
+			pushing = e.button;
+			pushTime = haxe.Timer.stamp();
+			pushStartX = pushX = e.relX;
+			pushStartY = pushY = e.relY;
+		case ERelease, EReleaseOutside:
+			if( pushing == e.button ) {
+				pushing = -1;
+				@:privateAccess scene.events.stopDrag();
+				if( e.kind == ERelease && haxe.Timer.stamp() - pushTime < 0.2 && hxd.Math.distance(e.relX - pushStartX,e.relY - pushStartY) < 5 )
+					onClick(e);
+			}
+		case EMove:
+			switch( pushing ) {
+			case 1:
+				pan((e.relX - pushX) * panSpeed, (e.relY - pushY) * panSpeed);
+				pushX = e.relX;
+				pushY = e.relY;
+			default:
+			}
+		default:
+		}
+	}
+
+	function zoom(delta:Float) {
+		targetPos.z *= Math.pow(zoomAmount, -delta);
+	}
+
+	function rot(dx, dy) {
+		moveX += dx;
+		moveY += dy;
+	}
+
+	function pan(dx:Float, dy:Float) {
+		targetPos.x -= dx / parent.scaleX;
+		targetPos.y -= dy / parent.scaleY;
+	}
+
+	function syncCamera() {
+		var scene = getScene();
+		//if( scene == null ) return;
+		parent.setScale(curPos.z);
+		parent.x = scene.width * 0.5 - curPos.x * parent.scaleX;
+		parent.y = scene.height * 0.5 - curPos.y * parent.scaleY;
+	}
+
+	override function sync(ctx:h2d.RenderContext) {
+
+		var p : h2d.Object = this;
+		while( p != null ) {
+			if( !p.visible ) {
+				super.sync(ctx);
+				return;
+			}
+			p = p.parent;
+		}
+
+		/*
+		if( moveX != 0 ) {
+			targetPos.y += moveX * 0.003 * rotateSpeed;
+			moveX *= 1 - friction;
+			if( Math.abs(moveX) < 1 ) moveX = 0;
+		}
+
+		if( moveY != 0 ) {
+			targetPos.z -= moveY * 0.003 * rotateSpeed;
+			var E = 2e-5;
+			var bound = Math.PI - E;
+			if( targetPos.z < E ) targetPos.z = E;
+			if( targetPos.z > bound ) targetPos.z = bound;
+			moveY *= 1 - friction;
+			if( Math.abs(moveY) < 1 ) moveY = 0;
+		}*/
+
+		var dt = hxd.Math.min(1, 1 - Math.pow(smooth, ctx.elapsedTime * 60));
+		curPos.lerp(curPos, targetPos, dt );
+		syncCamera();
+
+		super.sync(ctx);
+	}
+
+}

+ 32 - 7
hide/comp/SceneEditor.hx

@@ -120,6 +120,7 @@ class SceneEditor {
 	public var snapToGround = false;
 	public var localTransform = true;
 	public var cameraController : h3d.scene.CameraController;
+	public var cameraController2D : CameraController2D;
 	public var editorDisplay(default,set) : Bool;
 	public var camera2D(default,set) : Bool = false;
 
@@ -166,8 +167,7 @@ class SceneEditor {
 		scene.editor = this;
 		scene.onReady = onSceneReady;
 		scene.onResize = function() {
-			context.shared.root2d.x = scene.width >> 1;
-			context.shared.root2d.y = scene.height >> 1;
+			cameraController2D.toTarget();
 			onResize();
 		};
 
@@ -247,7 +247,8 @@ class SceneEditor {
 	}
 
 	function set_camera2D(b) {
-		cameraController.visible = !b;
+		if( cameraController != null ) cameraController.visible = !b;
+		if( cameraController2D != null ) cameraController2D.visible = b;
 		return camera2D = b;
 	}
 
@@ -306,6 +307,10 @@ class SceneEditor {
 		return c;
 	}
 
+	function makeCamController2D() {
+		return new CameraController2D(context.shared.root2d);
+	}
+
 	function focusSelection() {
 		if(curEdit.rootObjects.length > 0) {
 			var bnds = new h3d.col.Bounds();
@@ -394,12 +399,26 @@ class SceneEditor {
 		};
 		resetCamera();
 
+
 		var cam = @:privateAccess view.getDisplayState("Camera");
 		if( cam != null ) {
 			scene.s3d.camera.pos.set(cam.x, cam.y, cam.z);
 			scene.s3d.camera.target.set(cam.tx, cam.ty, cam.tz);
 		}
 		cameraController.loadFromCamera();
+
+		scene.s2d.defaultSmooth = true;
+		context.shared.root2d.x = scene.s2d.width >> 1;
+		context.shared.root2d.y = scene.s2d.height >> 1;
+		cameraController2D = makeCamController2D();
+		var cam2d = @:privateAccess view.getDisplayState("Camera2D");
+		if( cam2d != null ) {
+			context.shared.root2d.x = scene.s2d.width*0.5 + cam2d.x;
+			context.shared.root2d.y = scene.s2d.height*0.5 + cam2d.y;
+			context.shared.root2d.setScale(cam2d.z);
+		}
+		cameraController2D.loadFromScene();
+
 		scene.onUpdate = update;
 
 		// BUILD scene tree
@@ -589,6 +608,7 @@ class SceneEditor {
 		sh.currentPath = view.state.path;
 		scene.s3d.addChild(sh.root3d);
 		scene.s2d.addChild(sh.root2d);
+		sh.root2d.addChild(cameraController2D);
 		scene.setCurrent();
 		scene.onResize();
 		context.init();
@@ -1215,10 +1235,14 @@ class SceneEditor {
 	}
 
 	public function resetCamera() {
-		scene.s3d.camera.zNear = scene.s3d.camera.zFar = 0;
-		scene.resetCamera(1.5);
-		cameraController.lockZPlanes = scene.s3d.camera.zNear != 0;
-		cameraController.loadFromCamera();
+		if( camera2D ) {
+			cameraController2D.initFromScene();
+		} else {
+			scene.s3d.camera.zNear = scene.s3d.camera.zFar = 0;
+			scene.resetCamera(1.5);
+			cameraController.lockZPlanes = scene.s3d.camera.zNear != 0;
+			cameraController.loadFromCamera();
+		}
 	}
 
 	public function getPickTransform(parent: PrefabElement) {
@@ -1817,6 +1841,7 @@ class SceneEditor {
 	function update(dt:Float) {
 		var cam = scene.s3d.camera;
 		@:privateAccess view.saveDisplayState("Camera", { x : cam.pos.x, y : cam.pos.y, z : cam.pos.z, tx : cam.target.x, ty : cam.target.y, tz : cam.target.z });
+		@:privateAccess view.saveDisplayState("Camera2D", { x : context.shared.root2d.x - scene.s2d.width*0.5, y : context.shared.root2d.y - scene.s2d.height*0.5, z : context.shared.root2d.scaleX });
 		if(gizmo != null) {
 			if(!gizmo.moving) {
 				moveGizmoToSelection();

+ 3 - 1
hide/view/Prefab.hx

@@ -96,7 +96,9 @@ class Prefab extends FileView {
 			light = null;
 
 		tools.saveDisplayKey = "Prefab/tools";
-		tools.addButton("video-camera", "Perspective camera", () -> sceneEditor.resetCamera());
+
+		tools.addToggle("arrows", "2D Camera", (b) -> sceneEditor.camera2D = b);
+		tools.addButton("video-camera", "Default camera", () -> sceneEditor.resetCamera());
 
 		tools.addColor("Background color", function(v) {
 			scene.engine.backgroundColor = v;