From 875669f0e87338e13d55db97b3a0a85a4cc45729 Mon Sep 17 00:00:00 2001 From: Jacob Frank Date: Sun, 17 Jan 2016 02:44:39 -0800 Subject: [PATCH] WIP #12: internal ship nodes! Also: - Fix null check when client not loaded into console - WIP picking (not yet functional) - New wireframe transparency - And much, much more! --- .../RealEngineeringConsoleManager.java | 17 +-- .../artemis/engconsole/ui/damcon/Damcon.java | 67 ++++++++-- .../engconsole/ui/damcon/InternalNode.java | 126 ++++++++++++++++++ .../artemis/protocol/RobustProxyListener.java | 6 +- 4 files changed, 194 insertions(+), 22 deletions(-) create mode 100644 src/com/brindyblitz/artemis/engconsole/ui/damcon/InternalNode.java diff --git a/src/com/brindyblitz/artemis/engconsole/RealEngineeringConsoleManager.java b/src/com/brindyblitz/artemis/engconsole/RealEngineeringConsoleManager.java index 2f13175..e081d9a 100644 --- a/src/com/brindyblitz/artemis/engconsole/RealEngineeringConsoleManager.java +++ b/src/com/brindyblitz/artemis/engconsole/RealEngineeringConsoleManager.java @@ -32,7 +32,7 @@ public void onChange() { @Override public int getSystemEnergyAllocated(ShipSystem system) { - if (this.worldAwareRobustProxyListener.getServer() == null) { + if (this.worldAwareRobustProxyListener.getSystemManager().getPlayerShip(0) == null) { return 100; } return (int)(this.worldAwareRobustProxyListener.getSystemManager().getPlayerShip(0).getSystemEnergy(system) * 300); @@ -40,7 +40,7 @@ public int getSystemEnergyAllocated(ShipSystem system) { @Override public int getSystemCoolantAllocated(ShipSystem system) { - if (this.worldAwareRobustProxyListener.getServer() == null) { + if (this.worldAwareRobustProxyListener.getSystemManager().getPlayerShip(0) == null) { return 0; } return this.worldAwareRobustProxyListener.getSystemManager().getPlayerShip(0).getSystemCoolant(system); @@ -48,15 +48,16 @@ public int getSystemCoolantAllocated(ShipSystem system) { @Override public int getSystemHeat(ShipSystem system) { - if (this.worldAwareRobustProxyListener.getServer() == null) { + if (this.worldAwareRobustProxyListener.getSystemManager().getPlayerShip(0) == null) { return 0; } + return (int) (this.worldAwareRobustProxyListener.getSystemManager().getPlayerShip(0).getSystemHeat(system) * 100); } @Override public int getSystemHealth(ShipSystem system) { - if (this.worldAwareRobustProxyListener.getServer() == null) { + if (this.worldAwareRobustProxyListener.getSystemManager().getPlayerShip(0) == null) { return 0; } return (int) (this.worldAwareRobustProxyListener.getSystemManager().getHealthOfSystem(system) * 100); @@ -64,7 +65,7 @@ public int getSystemHealth(ShipSystem system) { @Override public int getTotalCoolantRemaining() { - if (this.worldAwareRobustProxyListener.getServer() == null) { + if (this.worldAwareRobustProxyListener.getSystemManager().getPlayerShip(0) == null) { return Artemis.DEFAULT_COOLANT; } final int totalCoolantUsed = Arrays.stream(ShipSystem.values()).mapToInt(system -> this.getSystemCoolantAllocated(system)).sum(); @@ -73,7 +74,7 @@ public int getTotalCoolantRemaining() { @Override public int getTotalShipCoolant() { - if (this.worldAwareRobustProxyListener.getServer() == null) { + if (this.worldAwareRobustProxyListener.getSystemManager().getPlayerShip(0) == null) { return 0; } return this.worldAwareRobustProxyListener.getSystemManager().getPlayerShip(0).getAvailableCoolant(); @@ -90,7 +91,7 @@ public Map getGridHealth() { @Override public void incrementSystemEnergyAllocated(ShipSystem system, int amount) { - if (this.worldAwareRobustProxyListener.getServer() == null) { + if (this.worldAwareRobustProxyListener.getSystemManager().getPlayerShip(0) == null) { return; } super.incrementSystemEnergyAllocated(system, amount); @@ -98,7 +99,7 @@ public void incrementSystemEnergyAllocated(ShipSystem system, int amount) { @Override public void incrementSystemCoolantAllocated(ShipSystem system, int amount) { - if (this.worldAwareRobustProxyListener.getServer() == null) { + if (this.worldAwareRobustProxyListener.getSystemManager().getPlayerShip(0) == null) { return; } super.incrementSystemCoolantAllocated(system, amount); diff --git a/src/com/brindyblitz/artemis/engconsole/ui/damcon/Damcon.java b/src/com/brindyblitz/artemis/engconsole/ui/damcon/Damcon.java index 4b3a26c..e251159 100644 --- a/src/com/brindyblitz/artemis/engconsole/ui/damcon/Damcon.java +++ b/src/com/brindyblitz/artemis/engconsole/ui/damcon/Damcon.java @@ -1,13 +1,20 @@ package com.brindyblitz.artemis.engconsole.ui.damcon; import com.brindyblitz.artemis.engconsole.EngineeringConsoleManager; + +// See: http://download.java.net/media/java3d/javadoc/1.5.1/ import com.sun.j3d.loaders.IncorrectFormatException; import com.sun.j3d.loaders.ParsingErrorException; import com.sun.j3d.loaders.Scene; import com.sun.j3d.loaders.objectfile.ObjectFile; +import com.sun.j3d.utils.pickfast.PickCanvas; +import com.sun.j3d.utils.picking.PickResult; +import com.sun.j3d.utils.picking.PickTool; import com.sun.j3d.utils.universe.SimpleUniverse; import com.sun.j3d.utils.universe.Viewer; import com.sun.j3d.utils.universe.ViewingPlatform; +import net.dhleong.acl.util.GridCoord; +import net.dhleong.acl.vesseldata.VesselNode; import javax.media.j3d.*; import javax.swing.*; @@ -16,14 +23,12 @@ import java.awt.event.*; import java.io.File; import java.io.FileNotFoundException; -import java.util.Enumeration; -import java.util.Random; -import java.util.TimerTask; +import java.util.*; public class Damcon implements MouseListener, MouseMotionListener, MouseWheelListener { private static final int WIDTH = 400, HEIGHT = 300; - private static final Color WIREFRAME_COLOR = Color.GREEN; + private static final Color WIREFRAME_COLOR = Color.GREEN; // TODO: vary this color with total ship health if available? private static final Transform3D DEFAULT_CAMERA_VIEW = new Transform3D(new double[] { 0.6954015757171349d, 0.4658852009660681d, -0.5471449789689495d, -2.0244364221851137d, @@ -33,6 +38,7 @@ public class Damcon implements MouseListener, MouseMotionListener, MouseWheelLis private EngineeringConsoleManager engineeringConsoleManager; private Canvas3D canvas; + private PickCanvas pickCanvas; private SimpleUniverse universe; private Scene scene = null; private static final boolean WINDOW_HACK = true; @@ -52,6 +58,8 @@ public class Damcon implements MouseListener, MouseMotionListener, MouseWheelLis new int[] { LineAttributes.PATTERN_DASH, LineAttributes.PATTERN_DASH_DOT, LineAttributes.PATTERN_DOT, LineAttributes.PATTERN_SOLID }; private static final Random random = new Random(); + private Map internalNodes = new HashMap<>(); + public Damcon(EngineeringConsoleManager engineeringConsoleManager) { this.engineeringConsoleManager = engineeringConsoleManager; @@ -69,6 +77,8 @@ public Damcon(EngineeringConsoleManager engineeringConsoleManager) { createUniverseAndScene(); } + loadInternalNodes(); + addMouseListeners(); setCameraPresets(); @@ -95,6 +105,33 @@ private void loadAndWireframeifyModel() { } } + private void loadInternalNodes() { + BranchGroup node_branchgroup = new BranchGroup(); + + for (VesselNode vn : this.engineeringConsoleManager.getGrid()) { + InternalNode in = new InternalNode(vn); + internalNodes.put(vn.getGridCoord(), in); + node_branchgroup.addChild(in.getBranchGroup()); + } + + this.universe.addBranchGraph(node_branchgroup); + + pickCanvas = new PickCanvas(this.canvas, node_branchgroup); + pickCanvas.setMode(PickInfo.PICK_GEOMETRY); + pickCanvas.setFlags(PickInfo.NODE | PickInfo.CLOSEST_INTERSECTION_POINT); + pickCanvas.setTolerance(0.5f); + + this.engineeringConsoleManager.addChangeListener(new EngineeringConsoleManager.EngineeringConsoleChangeListener() { + @Override + public void onChange() { + for (Map.Entry entry : engineeringConsoleManager.getGridHealth().entrySet()) { + InternalNode node = internalNodes.get(entry.getKey()); + node.updateHealth(entry.getValue()); + } + } + }); + } + private void createUniverseAndScene() { // This is an attempt to give the Viewer a canvas so it doesn't create its own window (it doesn't render properly) GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration(); @@ -147,9 +184,11 @@ private static void wireframeifyScene(Scene scene, int line_attribute_pattern) { s3d.setAppearance(wireframe); try { s3d.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE); + // TODO: try scene.setCapability above with BranchGroup.ALLOW_CHILDREN_WRITE etc. and see if this exception is no longer thrown + // See http://www.java-tips.org/other-api-tips-100035/119-java3d/1527-how-to-use-the-capability.html + // I got it working for the internal node spheres so I probably just need to figure out which node(s) to set it on, or set it on creation } catch(RestrictedAccessException e) { - // TODO: look into missing capabilities for this: - // Exception in thread "AWT-EventQueue-0" javax.media.j3d.RestrictedAccessException: Cannot modify capability bits on a live or compiled object + // e=Exception in thread "AWT-EventQueue-0" javax.media.j3d.RestrictedAccessException: Cannot modify capability bits on a live or compiled object } } } @@ -159,7 +198,7 @@ private static Appearance getWireframeAppearance(int line_attributes_pattern) { Appearance appearance = new Appearance(); // Set transparency - TransparencyAttributes transparency = new TransparencyAttributes(TransparencyAttributes.NICEST, .75f); + TransparencyAttributes transparency = new TransparencyAttributes(TransparencyAttributes.NICEST, .9f); appearance.setTransparencyAttributes(transparency); // Enable automatic anti-aliasing @@ -191,7 +230,13 @@ private static Appearance getWireframeAppearance(int line_attributes_pattern) { public void mouseClicked(MouseEvent e) { if (e.getButton() == 1) { // TODO: damcon selection and orders issuing - System.out.println("Left click"); + // pickCanvas.setShapeLocation(e); + // PickInfo[] pickInfos = pickCanvas.pickAll(); + + System.out.println("Left click:\n"); + /*for (PickInfo pi : pickInfos) { + System.out.println(pi); + }*/ } } @@ -340,9 +385,9 @@ public void mouseWheelMoved(MouseWheelEvent e) { camera.setTransform(xform); } - ////////// - // Misc // - ////////// + ////////////////// + // Damage Shake // + ////////////////// public void toggleDamageShake() { dotified = !dotified; diff --git a/src/com/brindyblitz/artemis/engconsole/ui/damcon/InternalNode.java b/src/com/brindyblitz/artemis/engconsole/ui/damcon/InternalNode.java new file mode 100644 index 0000000..5aed540 --- /dev/null +++ b/src/com/brindyblitz/artemis/engconsole/ui/damcon/InternalNode.java @@ -0,0 +1,126 @@ +package com.brindyblitz.artemis.engconsole.ui.damcon; + +import com.sun.j3d.utils.geometry.ColorCube; +import com.sun.j3d.utils.geometry.Sphere; +import net.dhleong.acl.vesseldata.VesselNode; +import sun.reflect.generics.reflectiveObjects.NotImplementedException; + +import javax.media.j3d.*; +import javax.vecmath.*; +import java.awt.*; + +public class InternalNode { + private static final float RADIUS = 0.05f, SCALE = 0.0034f; + + private BranchGroup branchGroup; + private VesselNode vesselNode; + private Sphere sphere; + + public InternalNode(VesselNode vessel_node) { + this.vesselNode = vessel_node; + + this.branchGroup = new BranchGroup(); + + if (this.vesselNode.getSystem() != null) { + Vector3f pos = new Vector3f(-vessel_node.getX(), vessel_node.getY(), vessel_node.getZ()); + pos.scale(SCALE); + + sphere = new Sphere(RADIUS, appearanceFromHealthPercentage(1f)); + // sphere = new Sphere(RADIUS, Shape3D.ALLOW_APPEARANCE_WRITE | Shape3D.ALLOW_APPEARANCE_OVERRIDE_WRITE, appearanceFromHealthPercentage(1f)); + /*sphere.setCapability(Shape3D.ALLOW_APPEARANCE_READ); + sphere.setCapability(Shape3D.ALLOW_APPEARANCE_OVERRIDE_READ); + sphere.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE); + sphere.setCapability(Shape3D.ALLOW_APPEARANCE_OVERRIDE_WRITE);*/ + sphere.getShape(Sphere.BODY).setCapability(Shape3D.ALLOW_APPEARANCE_WRITE); + + sphere.setCapability(Shape3D.ENABLE_PICK_REPORTING); + sphere.setPickable(true); + + Transform3D transform = new Transform3D(); + transform.setTranslation(pos); + + TransformGroup tg = new TransformGroup(); + tg.setTransform(transform); + tg.addChild(sphere); + + this.branchGroup.addChild(tg); + } + } + + public void updateHealth(float pct) { + sphere.setAppearance(appearanceFromHealthPercentage(pct)); + } + + private static Appearance appearanceFromHealthPercentage(float pct) { + Color color = Color.getHSBColor(getEmptyHue() - (getEmptyHue() - getFullHue()) * pct, 1, 1); + + // TODO: cleanup! + + Color3f ambientColour = new Color3f(0f, 0f, 0f); + Color3f emissiveColour = new Color3f(color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f); + Color3f specularColour = new Color3f(0f, 0f, 0f); + Color3f diffuseColour = new Color3f(0f, 0f, 0f); + float shininess = 0.0f; + Appearance app = new Appearance(); + app.setCapability(Appearance.ALLOW_COLORING_ATTRIBUTES_READ); + app.setCapability(Appearance.ALLOW_COLORING_ATTRIBUTES_WRITE); + app.setMaterial(new Material(ambientColour, emissiveColour, diffuseColour, specularColour, shininess)); + TransparencyAttributes transparency = new TransparencyAttributes(TransparencyAttributes.NICEST, .5f); // TODO: when hovering, make opaque + app.setTransparencyAttributes(transparency); + return app; + } + + private static float getFullHue() { + return 120f / 360f; + } + + private static float getEmptyHue() { + return 0f; + } + // TODO: this color stuff is duplicated in SystemHealthSlider.java, fix it! + + private InternalNode(Vector3d position, int IDONTWORKYET) { + if (true) { + throw new NotImplementedException(); + } + + ///// + + ColorCube color_cube = new ColorCube(0.05d); + branchGroup = new BranchGroup(); + branchGroup.addChild(color_cube); + + ////// + + Transform3D xform = new Transform3D(); + xform.set(position); + + TransformGroup xformGroup = new TransformGroup(); + xformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); + xformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); + xformGroup.setTransform(xform); + + ColorCube rightCube = new ColorCube(); + xformGroup.addChild(rightCube); + + /*Appearance app = new Appearance(); + Color3f ambientColour = new Color3f(1.0f, 1.0f, 0.0f); + Color3f emissiveColour = new Color3f(0.0f, 0.0f, 0.0f); + Color3f specularColour = new Color3f(1.0f, 1.0f, 1.0f); + Color3f diffuseColour = new Color3f(1.0f, 1.0f, 0.0f); + float shininess = 20.0f; + app.setMaterial(new Material(ambientColour, emissiveColour, + diffuseColour, specularColour, shininess)); + Box leftCube = new Box(1.0f, 1.0f, 1.0f, app); + xformGroup.addChild(leftCube);*/ + + Billboard billboard = new Billboard(xformGroup, Billboard.ROTATE_ABOUT_AXIS, new Vector3f(0f, 1f, 0f)); + + branchGroup = new BranchGroup(); + branchGroup.addChild(billboard); + } + + public BranchGroup getBranchGroup() { + return branchGroup; + } +} \ No newline at end of file diff --git a/src/com/brindyblitz/artemis/protocol/RobustProxyListener.java b/src/com/brindyblitz/artemis/protocol/RobustProxyListener.java index 2766bd4..ad67867 100644 --- a/src/com/brindyblitz/artemis/protocol/RobustProxyListener.java +++ b/src/com/brindyblitz/artemis/protocol/RobustProxyListener.java @@ -41,10 +41,10 @@ public void run() { System.out.println("Listening for connections on port " + this.proxyPort + "..."); Socket skt = listener.accept(); - System.out.println("Received connection from " + skt.getRemoteSocketAddress()); + System.out.println("Received connection from " + skt.getRemoteSocketAddress().toString().substring(1) + "."); this.client = new ThreadedArtemisNetworkInterface(skt, ConnectionType.CLIENT); - System.out.println("Connecting to server at " + serverAddr + ":" + serverPort + "..."); + System.out.print("Connecting to server at " + serverAddr + ":" + serverPort + "..."); this.server = new ThreadedArtemisNetworkInterface(serverAddr, serverPort); @@ -57,7 +57,7 @@ public void run() { this.server.start(); this.client.start(); - System.out.println("Connection established."); + System.out.println("connection established."); } catch (IOException ex) { ex.printStackTrace(); } finally {