diff --git a/src/CameraController.hx b/src/CameraController.hx index 9042adec..cd182d41 100644 --- a/src/CameraController.hx +++ b/src/CameraController.hx @@ -2,8 +2,10 @@ package src; import src.Util; import h3d.Quat; +#if hl import sdl.Cursor; import sdl.Sdl; +#end import hxd.Window; import hxd.Event; import src.MarbleWorld; @@ -67,10 +69,14 @@ class CameraController extends Object { Window.getInstance().addEventTarget(onEvent); // level.scene.addEventListener(onEvent); // Sdl.setRelativeMouseMode(true); + #if hl this.screenHeight = Sdl.getScreenHeight(); this.screenWidth = Sdl.getScreenWidth(); + #end level.scene.camera.fovY = 60; + #if hl Cursor.show(false); + #end } function onEvent(e:Event) { @@ -85,7 +91,9 @@ class CameraController extends Object { } public function lockCursor() { + #if hl Sdl.warpMouseGlobal(cast this.screenWidth / 2, cast this.screenHeight / 2); + #end } function orbit(mouseX:Float, mouseY:Float) { diff --git a/src/Marble.hx b/src/Marble.hx index b7912c6b..76f9c3c0 100644 --- a/src/Marble.hx +++ b/src/Marble.hx @@ -9,7 +9,6 @@ import src.ParticleSystem.ParticleEmitter; import src.ParticleSystem.ParticleData; import src.ParticleSystem.ParticleEmitterOptions; import src.DtsObject; -import sdl.Cursor; import hxd.Cursor; import shapes.PowerUp; import src.GameObject; diff --git a/src/MarbleWorld.hx b/src/MarbleWorld.hx index ac98978f..01060137 100644 --- a/src/MarbleWorld.hx +++ b/src/MarbleWorld.hx @@ -4,7 +4,9 @@ import gui.LoadingGui; import gui.PlayMissionGui; import src.MarbleGame; import gui.EndGameGui; +#if hl import sdl.Cursor; +#end import src.ForceObject; import shaders.DirLight; import h3d.col.Bounds; @@ -899,9 +901,13 @@ class MarbleWorld extends Scheduler { this.cursorLock = enabled; if (enabled) { this.marble.camera.lockCursor(); + #if hl Cursor.show(false); + #end } else { + #if hl Cursor.show(true); + #end } } diff --git a/src/ResourceLoader.hx b/src/ResourceLoader.hx index ea5e58a2..c030af95 100644 --- a/src/ResourceLoader.hx +++ b/src/ResourceLoader.hx @@ -1,7 +1,5 @@ package src; -import sys.thread.Lock; -import sys.thread.FixedThreadPool; import hxd.res.Image; import h3d.mat.Texture; import h3d.scene.Object; diff --git a/src/Settings.hx b/src/Settings.hx index 7c4c5846..bd855c0e 100644 --- a/src/Settings.hx +++ b/src/Settings.hx @@ -1,5 +1,6 @@ package src; +import hxd.Key; import src.MarbleGame; import hxd.Window; import haxe.DynamicAccess; @@ -23,6 +24,20 @@ typedef OptionsSettings = { var soundVolume:Float; } +typedef ControlsSettings = { + var forward:Int; + var backward:Int; + var left:Int; + var right:Int; + var camForward:Int; + var camBackward:Int; + var camLeft:Int; + var camRight:Int; + var jump:Int; + var powerup:Int; + var freelook:Int; +} + class Settings { public static var highScores:Map> = []; @@ -37,6 +52,20 @@ class Settings { soundVolume: 0 }; + public static var controlsSettings:ControlsSettings = { + forward: Key.W, + backward: Key.S, + left: Key.A, + right: Key.D, + camForward: Key.UP, + camBackward: Key.DOWN, + camLeft: Key.LEFT, + camRight: Key.RIGHT, + jump: Key.SPACE, + powerup: Key.MOUSE_LEFT, + freelook: Key.MOUSE_RIGHT + }; + public static function applySettings() { Window.getInstance().resize(optionsSettings.screenWidth, optionsSettings.screenHeight); Window.getInstance().displayMode = optionsSettings.isFullScreen ? FullscreenResize : Windowed; diff --git a/src/dts/Sequence.hx b/src/dts/Sequence.hx index e3afff5c..8e81be70 100644 --- a/src/dts/Sequence.hx +++ b/src/dts/Sequence.hx @@ -1,7 +1,6 @@ package dts; import dif.io.BytesReader; -import hl.I64; @:publicFields class Sequence { diff --git a/src/gui/Canvas.hx b/src/gui/Canvas.hx index 62f5504a..0c6a13d8 100644 --- a/src/gui/Canvas.hx +++ b/src/gui/Canvas.hx @@ -44,6 +44,9 @@ class Canvas extends GuiControl { } public override function update(dt:Float, mouseState:MouseState) { - super.update(dt, mouseState); + // Update ONLY the last one + if (children.length > 0) { + children[children.length - 1].update(dt, mouseState); + } } } diff --git a/src/gui/GuiControl.hx b/src/gui/GuiControl.hx index 45ac1fbd..86bd58fa 100644 --- a/src/gui/GuiControl.hx +++ b/src/gui/GuiControl.hx @@ -1,5 +1,6 @@ package gui; +import h2d.Graphics; import hxd.Key; import h2d.Scene; import h2d.col.Bounds; @@ -48,8 +49,8 @@ class GuiControl { } public function update(dt:Float, mouseState:MouseState) { - var renderRect = getRenderRectangle(); - if (renderRect.inRect(mouseState.position)) { + var hitTestRect = getHitTestRect(); + if (hitTestRect.inRect(mouseState.position)) { if (Key.isPressed(Key.MOUSE_LEFT)) { mouseState.button = Key.MOUSE_LEFT; this.onMousePress(mouseState); @@ -133,6 +134,15 @@ class GuiControl { return rect; } + public function getHitTestRect() { + var thisRect = this.getRenderRectangle(); + if (this.parent == null) + return thisRect; + else { + return thisRect.intersect(this.parent.getRenderRectangle()); + } + } + public function addChild(ctrl:GuiControl) { this.children.push(ctrl); ctrl.parent = this; diff --git a/src/gui/MessageBoxYesNoDlg.hx b/src/gui/MessageBoxYesNoDlg.hx new file mode 100644 index 00000000..3c385767 --- /dev/null +++ b/src/gui/MessageBoxYesNoDlg.hx @@ -0,0 +1,70 @@ +package gui; + +import src.MarbleGame; +import hxd.res.BitmapFont; +import h3d.Vector; +import src.ResourceLoader; + +class MessageBoxYesNoDlg extends GuiControl { + public function new(text:String, yesFunc:Void->Void, noFunc:Void->Void) { + super(); + this.horizSizing = Width; + this.vertSizing = Height; + this.position = new Vector(); + this.extent = new Vector(640, 480); + + var domcasual24fontdata = ResourceLoader.loader.load("data/font/DomCasual24px.fnt"); + var domcasual24 = new BitmapFont(domcasual24fontdata.entry); + @:privateAccess domcasual24.loader = ResourceLoader.loader; + + function loadButtonImages(path:String) { + var normal = ResourceLoader.getImage('${path}_n.png').toTile(); + var hover = ResourceLoader.getImage('${path}_h.png').toTile(); + var pressed = ResourceLoader.getImage('${path}_d.png').toTile(); + return [normal, hover, pressed]; + } + + var yesNoFrame = new GuiImage(ResourceLoader.getImage("data/ui/common/dialog.png").toTile()); + yesNoFrame.horizSizing = Center; + yesNoFrame.vertSizing = Center; + yesNoFrame.position = new Vector(187, 156); + yesNoFrame.extent = new Vector(265, 167); + this.addChild(yesNoFrame); + + var yesNoText = new GuiMLText(domcasual24, null); + yesNoText.position = new Vector(33, 46); + yesNoText.horizSizing = Center; + yesNoText.extent = new Vector(198, 23); + yesNoText.text.text = text; + yesNoText.text.textColor = 0; + yesNoText.text.maxWidth = 198; + yesNoFrame.addChild(yesNoText); + + var yesButton = new GuiButton(loadButtonImages("data/ui/common/yes")); + yesButton.position = new Vector(44, 94); + yesButton.extent = new Vector(82, 47); + yesButton.vertSizing = Top; + yesButton.pressedAction = (sender) -> { + MarbleGame.canvas.popDialog(this); + yesFunc(); + } + yesNoFrame.addChild(yesButton); + + var noButton = new GuiButton(loadButtonImages("data/ui/common/no")); + noButton.position = new Vector(151, 94); + noButton.extent = new Vector(75, 47); + noButton.vertSizing = Top; + noButton.pressedAction = (sender) -> { + MarbleGame.canvas.popDialog(this); + noFunc(); + } + yesNoFrame.addChild(noButton); + + if (yesNoText.text.getBounds().yMax > yesNoText.extent.y) { + var diff = yesNoText.text.getBounds().yMax - yesNoText.extent.y; + yesNoFrame.extent.y += diff; + yesButton.position.y += diff; + noButton.position.y += diff; + } + } +} diff --git a/src/gui/OptionsDlg.hx b/src/gui/OptionsDlg.hx index 85813f0b..8f254cd7 100644 --- a/src/gui/OptionsDlg.hx +++ b/src/gui/OptionsDlg.hx @@ -1,5 +1,6 @@ package gui; +import hxd.Key; import src.Settings; import src.Marble; import h2d.Tile; @@ -204,7 +205,7 @@ class OptionsDlg extends GuiImage { } graphicsPane.addChild(gfxd3d); - var applyFunc:Void->Void; + var applyFunc:Void->Void = null; var applyButton = new GuiButton(loadButtonImages("data/ui/options/grafapply")); applyButton.position = new Vector(188, 239); @@ -349,40 +350,106 @@ Extensions: EAX 2.0, EAX 3.0, EAX Unified, and EAX-AC3"; var cameraControlsPane:GuiImage = null; var mouseControlsPane:GuiImage = null; + function getConflictingBinding(bindingName:String, key:Int) { + if (Settings.controlsSettings.forward == key && bindingName != "Move Forward") + return "Move Forward"; + if (Settings.controlsSettings.backward == key && bindingName != "Move Backward") + return "Move Backward"; + if (Settings.controlsSettings.left == key && bindingName != "Move Left") + return "Move Left"; + if (Settings.controlsSettings.right == key && bindingName != "Move Right") + return "Move Right"; + if (Settings.controlsSettings.camForward == key && bindingName != "Rotate Camera Up") + return "Rotate Camera Up"; + if (Settings.controlsSettings.camBackward == key && bindingName != "Rotate Camera Down") + return "Rotate Camera Down"; + if (Settings.controlsSettings.camLeft == key && bindingName != "Rotate Camera Left") + return "Rotate Camera Left"; + if (Settings.controlsSettings.camRight == key && bindingName != "Rotate Camera Right") + return "Rotate Camera Right"; + if (Settings.controlsSettings.jump == key && bindingName != "Jump") + return "Jump"; + if (Settings.controlsSettings.powerup == key && bindingName != "Use PowerUp") + return "Use PowerUp"; + if (Settings.controlsSettings.freelook == key && bindingName != "Free Look") + return "Free Look"; + + return null; + } + + function remapFunc(bindingName:String, bindingFunc:Int->Void, ctrl:GuiButtonText) { + var remapDlg = new RemapDlg(bindingName); + MarbleGame.canvas.pushDialog(remapDlg); + remapDlg.remapCallback = (key) -> { + MarbleGame.canvas.popDialog(remapDlg); + + var conflicting = getConflictingBinding(bindingName, key); + if (conflicting == null) { + ctrl.txtCtrl.text.text = Key.getKeyName(key); + bindingFunc(key); + } else { + var yesNoDlg = new MessageBoxYesNoDlg('

"${Key.getKeyName(key)}" is already bound to "${conflicting}"!
Do you want to undo this mapping?

', + () -> { + ctrl.txtCtrl.text.text = Key.getKeyName(key); + bindingFunc(key); + }, () -> {}); + MarbleGame.canvas.pushDialog(yesNoDlg); + } + } + } + var moveForward = new GuiButtonText(loadButtonImages("data/ui/options/cntr_mrb_fw"), arial14); moveForward.position = new Vector(82, 104); moveForward.setExtent(new Vector(117, 51)); - moveForward.txtCtrl.text.text = "W"; + moveForward.txtCtrl.text.text = Key.getKeyName(Settings.controlsSettings.forward); + moveForward.pressedAction = (sender) -> { + remapFunc("Move Forward", (key) -> Settings.controlsSettings.forward = key, moveForward); + } marbleControlsPane.addChild(moveForward); var moveRight = new GuiButtonText(loadButtonImages("data/ui/options/cntr_mrb_rt"), arial14); moveRight.position = new Vector(230, 167); moveRight.setExtent(new Vector(112, 45)); - moveRight.txtCtrl.text.text = "D"; + moveRight.txtCtrl.text.text = Key.getKeyName(Settings.controlsSettings.right); + moveRight.pressedAction = (sender) -> { + remapFunc("Move Right", (key) -> Settings.controlsSettings.right = key, moveRight); + } marbleControlsPane.addChild(moveRight); var mouseFire = new GuiButtonText(loadButtonImages("data/ui/options/cntr_mrb_pwr"), arial14); mouseFire.position = new Vector(310, 84); mouseFire.setExtent(new Vector(120, 51)); - mouseFire.txtCtrl.text.text = "Left Mouse"; + mouseFire.txtCtrl.text.text = Key.getKeyName(Settings.controlsSettings.powerup); + mouseFire.pressedAction = (sender) -> { + remapFunc("Use PowerUp", (key) -> Settings.controlsSettings.powerup = key, mouseFire); + } marbleControlsPane.addChild(mouseFire); var moveBackward = new GuiButtonText(loadButtonImages("data/ui/options/cntr_mrb_bak"), arial14); moveBackward.position = new Vector(135, 235); moveBackward.setExtent(new Vector(118, 48)); - moveBackward.txtCtrl.text.text = "S"; + moveBackward.txtCtrl.text.text = Key.getKeyName(Settings.controlsSettings.backward); + moveBackward.pressedAction = (sender) -> { + remapFunc("Move Backward", (key) -> Settings.controlsSettings.backward = key, moveBackward); + } marbleControlsPane.addChild(moveBackward); var moveLeft = new GuiButtonText(loadButtonImages("data/ui/options/cntr_mrb_lft"), arial14); moveLeft.position = new Vector(19, 189); moveLeft.setExtent(new Vector(108, 45)); - moveLeft.txtCtrl.text.text = "A"; + moveLeft.txtCtrl.text.text = Key.getKeyName(Settings.controlsSettings.left); + moveLeft.pressedAction = (sender) -> { + remapFunc("Move Left", (key) -> Settings.controlsSettings.left = key, moveLeft); + } marbleControlsPane.addChild(moveLeft); var moveJmp = new GuiButtonText(loadButtonImages("data/ui/options/cntr_mrb_jmp"), arial14); moveJmp.position = new Vector(299, 231); moveJmp.setExtent(new Vector(120, 47)); - moveJmp.txtCtrl.text.text = "Space Bar"; + moveJmp.txtCtrl.text.text = Key.getKeyName(Settings.controlsSettings.jump); + moveJmp.pressedAction = (sender) -> { + remapFunc("Jump", (key) -> Settings.controlsSettings.jump = key, moveJmp); + } marbleControlsPane.addChild(moveJmp); var transparentbmp = new hxd.BitmapData(1, 1); @@ -417,25 +484,37 @@ Extensions: EAX 2.0, EAX 3.0, EAX Unified, and EAX-AC3"; var panUp = new GuiButtonText(loadButtonImages("data/ui/options/cntr_cam_up"), arial14); panUp.position = new Vector(29, 133); panUp.setExtent(new Vector(108, 42)); - panUp.txtCtrl.text.text = "Up"; + panUp.txtCtrl.text.text = Key.getKeyName(Settings.controlsSettings.camForward); + panUp.pressedAction = (sender) -> { + remapFunc("Rotate Camera Up", (key) -> Settings.controlsSettings.camForward = key, panUp); + } cameraControlsPane.addChild(panUp); var turnRight = new GuiButtonText(loadButtonImages("data/ui/options/cntr_cam_rt"), arial14); turnRight.position = new Vector(312, 99); turnRight.setExtent(new Vector(103, 36)); - turnRight.txtCtrl.text.text = "Right"; + turnRight.txtCtrl.text.text = Key.getKeyName(Settings.controlsSettings.camRight); + turnRight.pressedAction = (sender) -> { + remapFunc("Rotate Camera Right", (key) -> Settings.controlsSettings.camRight = key, turnRight); + } cameraControlsPane.addChild(turnRight); var panDown = new GuiButtonText(loadButtonImages("data/ui/options/cntr_cam_dwn"), arial14); panDown.position = new Vector(42, 213); panDown.setExtent(new Vector(109, 39)); - panDown.txtCtrl.text.text = "Down"; + panDown.txtCtrl.text.text = Key.getKeyName(Settings.controlsSettings.camBackward); + panDown.pressedAction = (sender) -> { + remapFunc("Rotate Camera Down", (key) -> Settings.controlsSettings.camBackward = key, panDown); + } cameraControlsPane.addChild(panDown); var turnLeft = new GuiButtonText(loadButtonImages("data/ui/options/cntr_cam_lft"), arial14); turnLeft.position = new Vector(319, 210); turnLeft.setExtent(new Vector(99, 36)); - turnLeft.txtCtrl.text.text = "Left"; + turnLeft.txtCtrl.text.text = Key.getKeyName(Settings.controlsSettings.camLeft); + turnLeft.pressedAction = (sender) -> { + remapFunc("Rotate Camera Left", (key) -> Settings.controlsSettings.camLeft = key, turnLeft); + } cameraControlsPane.addChild(turnLeft); var cameraToMarbleButton = new GuiButton([transparentTile, transparentTile, transparentTile]); @@ -467,7 +546,11 @@ Extensions: EAX 2.0, EAX 3.0, EAX Unified, and EAX-AC3"; var freelook = new GuiButtonText(loadButtonImages("data/ui/options/cntrl_mous_bttn"), arial14); freelook.position = new Vector(219, 225); freelook.setExtent(new Vector(105, 45)); - freelook.txtCtrl.text.text = "Right Mouse"; + freelook.txtCtrl.text.text = Key.getKeyName(Settings.controlsSettings.freelook); + freelook.pressedAction = (sender) -> { + remapFunc("Free Look", (key) -> Settings.controlsSettings.freelook = key, freelook); + } + mouseControlsPane.addChild(freelook); var mouseToMarbleButton = new GuiButton([transparentTile, transparentTile, transparentTile]); diff --git a/src/gui/Rect.hx b/src/gui/Rect.hx index d67bfcff..5ed559e0 100644 --- a/src/gui/Rect.hx +++ b/src/gui/Rect.hx @@ -16,4 +16,18 @@ class Rect { return (position.x <= point.x && (position.x + extent.x) >= point.x) && (position.y <= point.y && (position.y + extent.y) >= point.y); } + + public function intersect(other:Rect) { + var rectangle = new h2d.col.Bounds(); + rectangle.addPoint(new h2d.col.Point(position.x, position.y)); + rectangle.addPoint(new h2d.col.Point(position.x + extent.x, position.y + extent.y)); + + var otherrectangle = new h2d.col.Bounds(); + otherrectangle.addPoint(new h2d.col.Point(other.position.x, other.position.y)); + otherrectangle.addPoint(new h2d.col.Point(other.position.x + other.extent.x, other.position.y + other.extent.y)); + + var isec = rectangle.intersection(otherrectangle); + + return new Rect(new Vector(isec.xMin, isec.yMin), new Vector(isec.xMax - isec.xMin, isec.yMax - isec.yMin)); + } } diff --git a/src/gui/RemapDlg.hx b/src/gui/RemapDlg.hx new file mode 100644 index 00000000..f056dad4 --- /dev/null +++ b/src/gui/RemapDlg.hx @@ -0,0 +1,50 @@ +package gui; + +import hxd.Key; +import gui.GuiControl.MouseState; +import hxd.res.BitmapFont; +import h3d.Vector; +import src.ResourceLoader; + +class RemapDlg extends GuiControl { + var remapCallback:Int->Void; + + public function new(bindingName:String) { + super(); + this.horizSizing = Width; + this.vertSizing = Height; + this.position = new Vector(); + this.extent = new Vector(640, 480); + + var remapDlg = new GuiImage(ResourceLoader.getImage("data/ui/common/dialog.png").toTile()); + remapDlg.horizSizing = Center; + remapDlg.vertSizing = Center; + remapDlg.position = new Vector(170, 159); + remapDlg.extent = new Vector(300, 161); + this.addChild(remapDlg); + + var domcasual24fontdata = ResourceLoader.loader.load("data/font/DomCasual24px.fnt"); + var domcasual24 = new BitmapFont(domcasual24fontdata.entry); + @:privateAccess domcasual24.loader = ResourceLoader.loader; + + var remapText = new GuiMLText(domcasual24, null); + remapText.horizSizing = Center; + remapText.vertSizing = Bottom; + remapText.position = new Vector(46, 60); + remapText.extent = new Vector(213, 23); + remapText.text.textColor = 0; + remapText.text.text = '

Press a new key or button for
"${bindingName}"

'; + remapDlg.addChild(remapText); + } + + public override function update(dt:Float, mouseState:MouseState) { + super.update(dt, mouseState); + for (i in 0...1024) { + if (i == 5) + continue; + if (Key.isDown(i)) { + remapCallback(i); + } + } + } +}