public override void OnInspectorGUI() { GUI.changed = false; BinaryPair bPair = (BinaryPair)target; Vector3 velocity = Vector3.zero; GravityScaler.Units units = GravityEngine.Instance().units; string prompt = string.Format("Velocity ({0})", GravityScaler.VelocityUnits(units)); velocity = EditorGUILayout.Vector3Field(new GUIContent(prompt, "velocity of binary center of mass"), bPair.velocity); if (GUI.changed) { Undo.RecordObject(bPair, "EllipseBase Change"); bPair.velocity = velocity; EditorUtility.SetDirty(bPair); } base.OnInspectorGUI(); if (axisUpdated) { bPair.ApplyScale(GravityEngine.Instance().GetLengthScale()); } }
public override void OnInspectorGUI() { GUI.changed = false; GravityParticles nbp = (GravityParticles)target; Vector3 initialV = nbp.initialVelocity; bool addNBodyVelocity = nbp.addNBodyVelocity; IGravityParticlesInit particlesInit = nbp.GetComponent <IGravityParticlesInit>(); GravityScaler.Units units = GravityEngine.Instance().units; string prompt = string.Format("Initial Vel. ({0})", GravityScaler.VelocityUnits(units)); if (particlesInit == null) { EditorGUILayout.LabelField("No init script", EditorStyles.boldLabel); bool hasNBody = false; if (nbp.GetComponent <NBody>() != null) { hasNBody = true; } else if (nbp.transform.parent != null && nbp.transform.parent.gameObject.GetComponent <NBody>() != null) { hasNBody = true; } if (hasNBody) { addNBodyVelocity = EditorGUILayout.Toggle(new GUIContent("Use velocity from NBody", velTip), nbp.addNBodyVelocity); if (addNBodyVelocity) { EditorGUILayout.LabelField("Initial Velocity: (from NBody)", EditorStyles.boldLabel); } else { initialV = EditorGUILayout.Vector3Field(new GUIContent(prompt, iTip), nbp.initialVelocity); } } else { initialV = EditorGUILayout.Vector3Field(new GUIContent(prompt, iTip), nbp.initialVelocity); } } else { EditorGUILayout.LabelField("Initalize with: " + particlesInit.GetType().ToString(), EditorStyles.boldLabel); } if (GUI.changed) { Undo.RecordObject(nbp, "GravityParticles Change"); nbp.initialVelocity = initialV; nbp.addNBodyVelocity = addNBodyVelocity; EditorUtility.SetDirty(nbp); } }
public override void OnInspectorGUI() { GUI.changed = false; NBodyCollision nbc = (NBodyCollision)target; GameObject explodePF = nbc.explosionPrefab; int precedence = nbc.collisionPrecedence; float explodeOrBounceVelocity = nbc.explodeOrBounceVelocity; float bounceFactor = 1f; string layer = null; float oldWidth = EditorGUIUtility.labelWidth; EditorGUIUtility.labelWidth = 200; NBodyCollision.CollisionType type = NBodyCollision.CollisionType.ABSORB_IMMEDIATE; type = (NBodyCollision.CollisionType)EditorGUILayout.EnumPopup(new GUIContent("Collision Type", collTip), nbc.collisionType); precedence = EditorGUILayout.IntField(new GUIContent("Collision Precedence", cTip), nbc.collisionPrecedence); layer = EditorGUILayout.TextField(new GUIContent("Collision Layer (Optional)", layerTip), nbc.collisionLayer); if (type == NBodyCollision.CollisionType.EXPLODE) { explodePF = (GameObject)EditorGUILayout.ObjectField( new GUIContent("Explosion Prefab", "Particle System with NBodyParticles"), explodePF, typeof(GameObject), true); } else if (type == NBodyCollision.CollisionType.BOUNCE) { EditorGUIUtility.labelWidth = oldWidth; bounceFactor = EditorGUILayout.Slider(new GUIContent("Bounce", bTip), nbc.bounceFactor, 0f, 1f); } else if (type == NBodyCollision.CollisionType.EXPLODE_OR_BOUNCE) { explodePF = (GameObject)EditorGUILayout.ObjectField( new GUIContent("Explosion Prefab", "Particle System with NBodyParticles"), explodePF, typeof(GameObject), true); bounceFactor = EditorGUILayout.Slider(new GUIContent("Bounce", bTip), nbc.bounceFactor, 0f, 1f); GravityScaler.Units units = GravityEngine.Instance().units; EditorGUIUtility.labelWidth = oldWidth; string prompt = string.Format("Relative Velocity to Explode ({0})", GravityScaler.VelocityUnits(units)); explodeOrBounceVelocity = EditorGUILayout.FloatField(new GUIContent(prompt, dTip), nbc.explodeOrBounceVelocity); } if (GUI.changed) { Undo.RecordObject(nbc, "NBodyCollision Change"); nbc.explosionPrefab = explodePF; nbc.collisionType = type; nbc.bounceFactor = bounceFactor; nbc.explodeOrBounceVelocity = explodeOrBounceVelocity; nbc.collisionPrecedence = precedence; nbc.collisionLayer = layer; EditorUtility.SetDirty(nbc); } }
// Update is called once per frame void Update() { if (Input.GetKey(KeyCode.A)) { fromPhase += PHASE_PER_KEY; } else if (Input.GetKey(KeyCode.S)) { fromPhase -= PHASE_PER_KEY; } else if (Input.GetKey(KeyCode.Q)) { toPhase += PHASE_PER_KEY; } else if (Input.GetKey(KeyCode.W)) { toPhase -= PHASE_PER_KEY; } fromPhase = NUtils.DegreesMod360(fromPhase); toPhase = NUtils.DegreesMod360(toPhase); SetMarkers(); shipOrbitData.SetOrbitForVelocity(spaceshipNBody, shipOrbit.centerNbody); // Determine TOF Vector3d from = new Vector3d(shipOrbitData.GetPhysicsPositionforEllipse(fromPhase)); Vector3d to = new Vector3d(shipOrbitData.GetPhysicsPositionforEllipse(toPhase)); Vector3d shipPos = GravityEngine.instance.GetPositionDoubleV3(spaceshipNBody); double tPeri = shipOrbit.TimeOfFlight(shipPos, new Vector3d(shipOrbitData.GetPhysicsPositionforEllipse(0f))); double tApo = shipOrbit.TimeOfFlight(shipPos, new Vector3d(shipOrbitData.GetPhysicsPositionforEllipse(180f))); double tof = shipOrbit.TimeOfFlight(from, to); // Scale to game time //tApo = GravityScaler.ScaleToGameSeconds((float) tApo); //tPeri = GravityScaler.ScaleToGameSeconds((float)tPeri); //tof = GravityScaler.ScaleToGameSeconds((float)tof); //tofText.text = string.Format("Time of Flight = {0:#.#}\nTime to Apoapsis = {1:#.#}\nTime to Periapsis = {2:#.#}\ntau = {3}", // tof, tApo, tPeri, shipOrbitData.tau); GravityScaler.Units units = GravityEngine.instance.units; tofText.text = string.Format("Time of Flight = {0}\nTime to Apoapsis = {1}\nTime to Periapsis = {2}\ntau = {3}", GravityScaler.GetWorldTimeFormatted(tof, units), GravityScaler.GetWorldTimeFormatted(tApo, units), GravityScaler.GetWorldTimeFormatted(tPeri, units), GravityScaler.GetWorldTimeFormatted(shipOrbitData.tau, units)); }
public override void OnInspectorGUI() { GUI.changed = false; GravityEngine gravityEngine = (GravityEngine)target; float massScale = gravityEngine.massScale; float timeScale = gravityEngine.timeScale; float lengthScale = gravityEngine.lengthScale; float physToWorldFactor = gravityEngine.physToWorldFactor; bool optimizeMassless = gravityEngine.optimizeMassless; bool detectNbodies = gravityEngine.detectNbodies; bool evolveAtStart = gravityEngine.evolveAtStart; bool scaling = gravityEngine.editorShowScale; bool showAdvanced = gravityEngine.editorShowAdvanced; bool showTrajectory = gravityEngine.editorShowTrajectory; bool cmFoldout = gravityEngine.editorCMfoldout; bool mapToScene = gravityEngine.mapToScene; bool trajectoryPrediction = gravityEngine.trajectoryPrediction; float trajectoryTime = gravityEngine.trajectoryTime; GameObject trajCanvas = gravityEngine.trajectoryCanvas; GameObject markerParent = gravityEngine.markerParent; float computeFactor = gravityEngine.trajectoryComputeFactor; int stepsPerFrame = gravityEngine.stepsPerFrame; int particleStepsPerFrame = gravityEngine.particleStepsPerFrame; GravityEngine.Algorithm algorithm = GravityEngine.Algorithm.LEAPFROG; ForceChooser.Forces force = ForceChooser.Forces.Gravity; GravityScaler.Units units = GravityScaler.Units.DIMENSIONLESS; EditorGUIUtility.labelWidth = 200; mapToScene = EditorGUILayout.Toggle(new GUIContent("Use Transform to Reposition", mapTip), mapToScene); EditorGUIUtility.labelWidth = 150; // SCALING scaling = EditorGUILayout.Foldout(scaling, "Scaling"); if (scaling) { units = (GravityScaler.Units)EditorGUILayout.EnumPopup(new GUIContent("Units", unitsTip), gravityEngine.units); EditorGUILayout.LabelField("Scaling values change when <ENTER> ispressed."); switch (units) { case GravityScaler.Units.DIMENSIONLESS: // only have mass scale in DL case EditorGUILayout.LabelField("Use mass scale to control scene speed."); EditorGUILayout.LabelField("(More massive = faster)"); massScale = EditorGUILayout.DelayedFloatField(new GUIContent("Mass Scale", mTip), gravityEngine.massScale); break; case GravityScaler.Units.SI: // no mass scale is controlled by time exclusivly EditorGUILayout.LabelField("m/kg/sec."); // meters per Unity unit in the case of meters lengthScale = EditorGUILayout.DelayedFloatField(new GUIContent("Unity unit per m", timeTip), gravityEngine.lengthScale); timeScale = EditorGUILayout.DelayedFloatField(new GUIContent("Game sec. per sec.", timeTip), gravityEngine.timeScale); break; case GravityScaler.Units.ORBITAL: EditorGUILayout.LabelField("km/1E24 kg/hr"); // Express in km per Unity unit km/U lengthScale = EditorGUILayout.DelayedFloatField(new GUIContent("Unity unit per km", timeTip), gravityEngine.lengthScale); timeScale = EditorGUILayout.DelayedFloatField(new GUIContent("Game sec. per hour", timeTip), gravityEngine.timeScale); break; case GravityScaler.Units.SOLAR: EditorGUILayout.LabelField("AU/1E24 kg/year"); lengthScale = EditorGUILayout.DelayedFloatField(new GUIContent("Unity unit per AU", timeTip), gravityEngine.lengthScale); timeScale = EditorGUILayout.DelayedFloatField(new GUIContent("Game Sec per year", timeTip), gravityEngine.timeScale); break; } } // TRAJECTORY PREDICTION showTrajectory = EditorGUILayout.Foldout(showTrajectory, "Trajectory Prediction"); if (showTrajectory) { trajectoryPrediction = EditorGUILayout.Toggle(new GUIContent("Trajectory Prediction", trajTip), trajectoryPrediction); trajectoryTime = EditorGUILayout.FloatField(new GUIContent("Trajectory Time", trajTimeTip), trajectoryTime); computeFactor = EditorGUILayout.FloatField(new GUIContent("Re-computes per frame)", trajResetTip), computeFactor); trajCanvas = (GameObject)EditorGUILayout.ObjectField(new GUIContent("Canvas for Text (optional)", trajCanvasTip), trajCanvas, typeof(GameObject), true); markerParent = (GameObject)EditorGUILayout.ObjectField(new GUIContent("Time Marker Parent (optional)", markerTip), markerParent, typeof(GameObject), true); } // ADVANCED showAdvanced = EditorGUILayout.Foldout(showAdvanced, "Advanced"); if (showAdvanced) { algorithm = (GravityEngine.Algorithm)EditorGUILayout.EnumPopup(new GUIContent("Algorithm", algoTip), gravityEngine.algorithm); // Force selection is tangled with choice of integrator and scale - so needs to be here force = (ForceChooser.Forces)EditorGUILayout.EnumPopup(new GUIContent("Force", forceTip), gravityEngine.force); if (force == ForceChooser.Forces.Custom) { IForceDelegate force_delegate = gravityEngine.GetComponent <IForceDelegate>(); if (force_delegate == null) { EditorGUILayout.LabelField(" Attach a Force Delegate to this object.", EditorStyles.boldLabel); } else { EditorGUILayout.LabelField(" Force delegate: " + force_delegate.GetType()); } } if (force != ForceChooser.Forces.Gravity) { EditorGUILayout.LabelField(" Note: Orbit predictors assume Newtonian gravity"); EditorGUILayout.LabelField(" They are not accurate for other forces."); } optimizeMassless = EditorGUILayout.Toggle(new GUIContent("Optimize Massless Bodies", mlessTip), gravityEngine.optimizeMassless); detectNbodies = EditorGUILayout.Toggle(new GUIContent("Automatically Add NBody objects", autoAddTip), gravityEngine.detectNbodies); evolveAtStart = EditorGUILayout.Toggle(new GUIContent("Evolve at Start", autoStartTip), gravityEngine.evolveAtStart); physToWorldFactor = EditorGUILayout.FloatField(new GUIContent("Physics to World Scale", phyWTip), gravityEngine.physToWorldFactor); EditorGUILayout.LabelField("Steps per frame:"); stepsPerFrame = EditorGUILayout.IntField(new GUIContent(" Massive Bodies", stepTip), stepsPerFrame); particleStepsPerFrame = EditorGUILayout.IntField(new GUIContent(" Particles", pstepTip), particleStepsPerFrame); } // Switch bodies list on/off based on option if (!gravityEngine.detectNbodies) { // use native Inspector look & feel for bodies object EditorGUILayout.LabelField("Control Nbody in following gameObjects (and children)", EditorStyles.boldLabel); SerializedProperty bodiesProp = serializedObject.FindProperty("bodies"); EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(bodiesProp, true); if (EditorGUI.EndChangeCheck()) { serializedObject.ApplyModifiedProperties(); } } else { EditorGUILayout.LabelField("NBody objects will be detected automatically", EditorStyles.boldLabel); } // Show the CM and the velocity of the CM cmFoldout = EditorGUILayout.Foldout(cmFoldout, "Center of Mass Info"); if (cmFoldout) { EditorGUILayout.LabelField("Center of Mass:" + gravityEngine.GetWorldCenterOfMass()); EditorGUILayout.LabelField("CM Velocity:" + gravityEngine.GetWorldCenterOfMassVelocity()); } // Checking the Event type lets us update after Undo and Redo commands. // A redo updates _lengthScale but does not run the setter if (Event.current.type == EventType.ExecuteCommand && Event.current.commandName == "UndoRedoPerformed") { // explicitly re-set so setter code will run. gravityEngine.lengthScale = lengthScale; } if (GUI.changed) { Undo.RecordObject(gravityEngine, "GE Change"); gravityEngine.mapToScene = mapToScene; gravityEngine.timeScale = timeScale; gravityEngine.massScale = massScale; // This runs a setter in GE that will do a rescale of the scene if necessary gravityEngine.lengthScale = lengthScale; gravityEngine.units = units; gravityEngine.physToWorldFactor = physToWorldFactor; gravityEngine.optimizeMassless = optimizeMassless; gravityEngine.detectNbodies = detectNbodies; gravityEngine.editorShowTrajectory = showTrajectory; gravityEngine.trajectoryPrediction = trajectoryPrediction; gravityEngine.trajectoryTime = trajectoryTime; gravityEngine.trajectoryCanvas = trajCanvas; gravityEngine.markerParent = markerParent; gravityEngine.trajectoryComputeFactor = computeFactor; gravityEngine.algorithm = algorithm; gravityEngine.force = force; gravityEngine.evolveAtStart = evolveAtStart; gravityEngine.editorShowScale = scaling; gravityEngine.editorShowAdvanced = showAdvanced; gravityEngine.editorCMfoldout = cmFoldout; gravityEngine.stepsPerFrame = stepsPerFrame; gravityEngine.particleStepsPerFrame = particleStepsPerFrame; EditorUtility.SetDirty(gravityEngine); } }
public override void OnInspectorGUI() { GUI.changed = false; NBody nbody = (NBody)target; float mass = 0f; float size = 0.1f; bool autoSize = true; Vector3 velocity = Vector3.zero; Vector3 initialPos = Vector3.zero; bool rotateFrame = false; if (GravityEngine.Instance() == null) { EditorGUILayout.LabelField("Require a GravityEngine in the scene to", EditorStyles.boldLabel); EditorGUILayout.LabelField("display NBody component.", EditorStyles.boldLabel); } GravityScaler.Units units = GravityEngine.Instance().units; string mass_prompt = string.Format("Mass ({0})", GravityScaler.MassUnits(units)); mass = EditorGUILayout.DelayedFloatField(new GUIContent(mass_prompt, mTip), (float)nbody.mass); // If the velocity is controlled by an EllipseBase, or this NBody is the direct child of // BinaryPair or ThreeeBodySolution then don't allowit to be controlled. string controlledBy = null; if (nbody.transform.gameObject.GetComponent <OrbitEllipse>() != null) { controlledBy = "Initial position/Velocity is set by ellipse parameters."; } else if (nbody.transform.gameObject.GetComponent <OrbitHyper>() != null) { controlledBy = "Initial position/Velocity is set by hyperbola parameters."; } else if (nbody.transform.parent != null) { if (nbody.transform.parent.gameObject.GetComponent <BinaryPair>() != null) { controlledBy = "Initial position/Velocity is set by BinaryPair parent."; } else if (nbody.transform.parent.gameObject.GetComponent <ThreeBodySolution>() != null) { controlledBy = "Initial position/Velocity is set by ThreeBodySolution parent."; } } if (controlledBy == null) { switch (units) { case GravityScaler.Units.DIMENSIONLESS: EditorGUILayout.LabelField("Initial position set via transform"); velocity = EditorGUILayout.Vector3Field(new GUIContent("Velocity", velTip), nbody.vel); initialPos = nbody.transform.position; break; default: string prompt = string.Format("Initial Pos ({0})", GravityScaler.LengthUnits(units)); initialPos = EditorGUILayout.Vector3Field(new GUIContent(prompt, iposTip), nbody.initialPos); prompt = string.Format("Velocity ({0})", GravityScaler.VelocityUnits(units)); velocity = EditorGUILayout.Vector3Field(new GUIContent(prompt, velTip), nbody.vel); break; } } else { EditorGUILayout.LabelField(controlledBy, EditorStyles.boldLabel); //EditorGUILayout.LabelField(string.Format("vel= {0:F2} {1:F2} {2:F2}", nbody.vel.x, nbody.vel.y, nbody.vel.z)); } // particle capture size EditorGUIUtility.labelWidth = 200f; EditorGUIUtility.fieldWidth = 20f; rotateFrame = EditorGUILayout.Toggle(new GUIContent("Rotate frame in orbit", rotateTip), nbody.rotateFrame); autoSize = EditorGUILayout.Toggle(new GUIContent("Automatic particle capture size", autoTip), nbody.automaticParticleCapture); EditorGUIUtility.labelWidth = 0; EditorGUIUtility.fieldWidth = 0; if (!autoSize) { EditorGUIUtility.labelWidth = 200f; EditorGUIUtility.fieldWidth = 40f; size = EditorGUILayout.FloatField(new GUIContent("Particle capture radius", sizeTip), (float)nbody.size); EditorGUIUtility.labelWidth = 0; EditorGUIUtility.fieldWidth = 0; } else { float detectedSize = nbody.CalculateSize(); if (detectedSize < 0) { EditorGUILayout.LabelField("Did not detect a child with a MeshFilter.", EditorStyles.boldLabel); EditorGUILayout.LabelField("Using size=" + size); } else { EditorGUILayout.LabelField("Particle Capture radius=" + detectedSize); size = detectedSize; } } if (mass < 0) { mass = 0; } if (nbody.transform.hasChanged) { // User has dragged the object and the transform has changed, need // to change the initial Pos to correspond to this position in the correct units if (units != GravityScaler.Units.DIMENSIONLESS) { initialPos = nbody.transform.position / GravityEngine.Instance().GetLengthScale(); } nbody.initialPos = initialPos; nbody.transform.hasChanged = false; } if (GUI.changed) { Undo.RecordObject(nbody, "NBody Change"); nbody.mass = FixNaN.FixIfNaN(mass); nbody.vel = FixNaN.FixIfNaN(velocity); nbody.size = size; nbody.rotateFrame = rotateFrame; nbody.automaticParticleCapture = autoSize; nbody.initialPos = initialPos; Debug.Log("new v=" + velocity); // must be after initialPos is updated nbody.ApplyScale(GravityEngine.Instance().GetLengthScale(), GravityEngine.Instance().GetVelocityScale()); EditorUtility.SetDirty(nbody); } }
public override void OnInspectorGUI() { GUI.changed = false; EllipseBase ellipseBase = (EllipseBase)target; // fields in class GameObject centerObject = null; EllipseBase.ParamBy paramBy = EllipseBase.ParamBy.AXIS_A; float ecc = 0; float a = 0; float p = 0; float omega_uc = 0; float omega_lc = 0; float inclination = 0; float phase = 0; if (!(target is BinaryPair)) { centerObject = (GameObject)EditorGUILayout.ObjectField( new GUIContent("CenterObject", centerTip), ellipseBase.centerObject, typeof(GameObject), true); } EditorGUILayout.Space(); EditorGUILayout.LabelField("Ellipse Parameters", EditorStyles.boldLabel); // If there is a SolarBody, it is the one place data can be changed. The EB holds the // orbit scaled per SolarSystem scale. SolarBody sbody = ellipseBase.GetComponent <SolarBody>(); if (sbody != null) { EditorGUILayout.LabelField("\tEllipse parameters controlled by SolarBody settings."); EditorGUILayout.LabelField(string.Format(" {0,-25}\t ({1,1})\t {2}", "Semi-Major Axis", "a", ellipseBase.a), EditorStyles.wordWrappedLabel); EditorGUILayout.LabelField(string.Format(" {0,-25}\t ({1,1})\t {2}", "Eccentricity", "e", ellipseBase.ecc), EditorStyles.wordWrappedLabel); EditorGUILayout.LabelField(string.Format(" {0,-25}\t ({1,1})\t {2}", "Incliniation", "i", ellipseBase.inclination), EditorStyles.wordWrappedLabel); EditorGUILayout.LabelField(string.Format(" {0,-25}\t ({1,1})\t {2}", "Arg. of pericenter", "\u03c9", ellipseBase.omega_lc), EditorStyles.wordWrappedLabel); EditorGUILayout.LabelField(string.Format(" {0,-25}\t ({1,1})\t {2}", "Longitude of node", "\u03a9", ellipseBase.omega_uc), EditorStyles.wordWrappedLabel); EditorGUILayout.LabelField(string.Format(" {0,-25}\t ({1,1})\t {2}", "Phase", "M", ellipseBase.phase), EditorStyles.wordWrappedLabel); return; } paramBy = (EllipseBase.ParamBy)EditorGUILayout.EnumPopup(new GUIContent("Parameter Choice", paramTip), ellipseBase.paramBy); ecc = EditorGUILayout.Slider(new GUIContent("Eccentricity", eTip), ellipseBase.ecc, 0f, 0.99f); axisUpdated = false; // backwards compatibility when loading scenes before unit scaling: if (ellipseBase.a_scaled < 0) { axisUpdated = true; } GravityScaler.Units units = GravityEngine.Instance().units; if (ellipseBase.paramBy == EllipseBase.ParamBy.AXIS_A) { float oldLabelWidth = EditorGUIUtility.labelWidth; EditorGUIUtility.labelWidth = oldLabelWidth + 30f; string prompt = string.Format("Semi-Major Axis (a) [{0}]", GravityScaler.LengthUnits(units)); a = EditorGUILayout.DelayedFloatField(new GUIContent(prompt, aTip), ellipseBase.a); if (a != ellipseBase.a) { axisUpdated = true; } EditorGUILayout.LabelField("Scaled a (Unity units): " + ellipseBase.a_scaled); EditorGUIUtility.labelWidth = oldLabelWidth; p = a * (1 - ecc); } else { string prompt = string.Format("Pericenter [{0}]", GravityScaler.LengthUnits(units)); p = EditorGUILayout.DelayedFloatField(new GUIContent(prompt, pTip), ellipseBase.p); if (p != ellipseBase.p) { axisUpdated = true; } EditorGUILayout.LabelField("Scaled p (Unity units) " + ellipseBase.p_scaled); a = p / (1 - ecc); } // implementation uses AngleAxis, so degrees are more natural omega_uc = EditorGUILayout.Slider(new GUIContent("\u03a9 (Longitude of AN)", omega_ucTip), ellipseBase.omega_uc, 0, 360f); omega_lc = EditorGUILayout.Slider(new GUIContent("\u03c9 (AN to Pericenter)", omega_lcTip), ellipseBase.omega_lc, 0, 360f); inclination = EditorGUILayout.Slider(new GUIContent("Inclination", inclinationTip), ellipseBase.inclination, 0f, 180f); // physics uses radians - but ask user for degrees to be consistent phase = EditorGUILayout.Slider(new GUIContent("Starting Phase", phaseTip), ellipseBase.phase, 0, 360f); // Checking the Event type lets us update after Undo and Redo commands. // A redo updates _lengthScale but does not run the setter // if (Event.current.type == EventType.ExecuteCommand && // Event.current.commandName == "UndoRedoPerformed") { // ellipseBase.ApplyScale(GravityEngine.Instance().GetLengthScale()); // } if (GUI.changed) { Undo.RecordObject(ellipseBase, "EllipseBase Change"); ellipseBase.a = a; ellipseBase.p = p; ellipseBase.ecc = ecc; ellipseBase.centerObject = centerObject; ellipseBase.omega_lc = omega_lc; ellipseBase.omega_uc = omega_uc; ellipseBase.inclination = inclination; ellipseBase.phase = phase; ellipseBase.paramBy = paramBy; EditorUtility.SetDirty(ellipseBase); } }
public override void OnInspectorGUI() { GUI.changed = false; OrbitUniversal orbitU = (OrbitUniversal)target; bool displayAndExit = false; // check there is an NBody, if not likely a synthesized Orbit as part of a predictor if (orbitU.GetComponent <NBody>() == null) { EditorGUILayout.LabelField("Ellipse parameters determined from position/velocity."); EditorGUILayout.LabelField("(Orbit Predictor)."); displayAndExit = true; } // If there is a SolarBody, it is the one place data can be changed. The EB holds the // orbit scaled per SolarSystem scale. SolarBody sbody = orbitU.GetComponent <SolarBody>(); if (sbody != null) { EditorGUILayout.LabelField("Ellipse parameters controlled by SolarBody settings."); displayAndExit = true; } if (displayAndExit) { EditorGUILayout.LabelField(string.Format(" {0,-25} ({1,1})\t {2}", "Semi-Major Axis", "a", orbitU.GetMajorAxisInspector()), EditorStyles.wordWrappedLabel); EditorGUILayout.LabelField(string.Format(" {0,-25} ({1,1})\t {2}", "Eccentricity", "e", orbitU.eccentricity), EditorStyles.wordWrappedLabel); EditorGUILayout.LabelField(string.Format(" {0,-25} ({1,1})\t {2}", "Incliniation", "i", orbitU.inclination), EditorStyles.wordWrappedLabel); EditorGUILayout.LabelField(string.Format(" {0,-25} ({1,1})\t {2}", "Arg. of pericenter", "\u03c9", orbitU.omega_lc), EditorStyles.wordWrappedLabel); EditorGUILayout.LabelField(string.Format(" {0,-25} ({1,1})\t {2}", "Longitude of node", "\u03a9", orbitU.omega_uc), EditorStyles.wordWrappedLabel); EditorGUILayout.LabelField(string.Format(" {0,-25} ({1,1})\t {2}", "Phase", "M", orbitU.phase), EditorStyles.wordWrappedLabel); return; } // fields in class NBody centerNBody = null; OrbitUniversal.InputMode inputMode = orbitU.inputMode; double ecc = orbitU.eccentricity; double p_inspector = orbitU.p_inspector; double omega_uc = 0; double omega_lc = 0; double inclination = 0; double phase = 0; bool sizeUpdate = false; WarnAboutKeplerSeq(orbitU); centerNBody = (NBody)EditorGUILayout.ObjectField( new GUIContent("Center NBody", centerTip), orbitU.centerNbody, typeof(NBody), true); OrbitUniversal.EvolveMode evolveMode = orbitU.evolveMode; evolveMode = (OrbitUniversal.EvolveMode)EditorGUILayout.EnumPopup(new GUIContent("Evolve Mode", modeTip), evolveMode); EditorGUILayout.Space(); EditorGUILayout.LabelField("Shape Parameters", EditorStyles.boldLabel); inputMode = (OrbitUniversal.InputMode) EditorGUILayout.EnumPopup(new GUIContent("Parameter Choice", paramTip), orbitU.inputMode); sizeUpdate = false; GravityScaler.Units units = GravityEngine.Instance().units; string promptp = string.Format("Semi-parameter (p) [{0}]", GravityScaler.LengthUnits(units)); // The values for orbit size and shape can be entered in several ways. OrbitUniversal supports // these values as doubles (which is probably overkill in most case). Provide an explicit double mode // but also allow sliders (which reduce the value to a float). // The editor script changes p_inspector. (p in OU is scaled for GE internal units) switch (inputMode) { case OrbitUniversal.InputMode.ELLIPSE_MAJOR_AXIS_A: EditorGUILayout.LabelField("Ellipse with float/sliders using semi-major axis."); ecc = EditorGUILayout.Slider(new GUIContent("Eccentricity", eTip), (float)orbitU.eccentricity, 0f, 0.99f); GetMajorAxis(orbitU, ref p_inspector, ref sizeUpdate, units); break; case OrbitUniversal.InputMode.ELLIPSE_APOGEE_PERIGEE: EditorGUILayout.LabelField("Ellipse with float/sliders using agogee/perigee."); EditorGUILayout.LabelField("MUST use <Return> after updating values!"); double apogee_old = orbitU.GetApogeeInspector(); double apogee = EditorGUILayout.DelayedDoubleField(new GUIContent("Apogee", eTip), apogee_old); double perigee_old = orbitU.GetPerigeeInspector(); double perigee = EditorGUILayout.DelayedDoubleField(new GUIContent("Perigee", eTip), perigee_old); // enforce apogee > perigee if (apogee < perigee) { apogee = perigee; } if (!EditorApplication.isPlaying && (apogee != apogee_old) || (perigee != perigee_old)) { orbitU.SetSizeWithApogeePerigee(apogee, perigee); sizeUpdate = true; // Need to update ecc and p with new values p_inspector = orbitU.p_inspector; ecc = orbitU.eccentricity; } EditorGUILayout.LabelField(string.Format("Require Apogee > Perigee", ecc, p_inspector)); EditorGUILayout.LabelField(string.Format("Apogee/Perigee result in: eccentricty={0:0.00}, p={1:0.00}", ecc, p_inspector)); break; case OrbitUniversal.InputMode.ECC_PERIGEE: EditorGUILayout.LabelField("Orbit with double using eccentricity/perigee."); EditorGUILayout.LabelField("MUST use <Return> after updating values!"); double old_ecc = orbitU.eccentricity; ecc = EditorGUILayout.DelayedDoubleField(new GUIContent("Eccentricity", eTip), orbitU.eccentricity); double hperigee_old = orbitU.GetPerigeeInspector(); double hperigee = EditorGUILayout.DelayedDoubleField(new GUIContent("Perigee", eTip), hperigee_old); if (!EditorApplication.isPlaying && ((hperigee != hperigee_old) || (old_ecc != ecc))) { orbitU.SetSizeWithEccPerigee(ecc, hperigee); sizeUpdate = true; // Need to update ecc and p with new values p_inspector = orbitU.p_inspector; ecc = orbitU.eccentricity; } EditorGUILayout.LabelField(string.Format("Apogee/Perigee result in: eccentricty={0:0.00}, p={1:0.00}", ecc, p_inspector)); break; case OrbitUniversal.InputMode.DOUBLE: EditorGUILayout.LabelField("Specify values with double precision using semi-parameter"); EditorGUILayout.LabelField("MUST use <Return> after updating values!"); // no sliders (they do float) ecc = EditorGUILayout.DelayedDoubleField(new GUIContent("Eccentricity", eTip), orbitU.eccentricity); double old_p = orbitU.p_inspector; p_inspector = EditorGUILayout.DelayedDoubleField(new GUIContent(promptp, pTip), orbitU.p_inspector); if (old_p != p_inspector) { sizeUpdate = true; } break; case OrbitUniversal.InputMode.DOUBLE_ELLIPSE: EditorGUILayout.LabelField("Specify values with double precision using semi-parameter"); EditorGUILayout.LabelField("MUST use <Return> after updating values!"); // no sliders (they do float) ecc = EditorGUILayout.DelayedDoubleField(new GUIContent("Eccentricity", eTip), orbitU.eccentricity); GetMajorAxis(orbitU, ref p_inspector, ref sizeUpdate, units); break; default: Debug.LogWarning("Unknown input mode - internal error"); break; } if (!EditorApplication.isPlaying && (p_inspector != orbitU.p)) { sizeUpdate = true; } EditorGUILayout.LabelField("Scaled p (Unity units): " + orbitU.p); EditorGUILayout.Space(); EditorGUILayout.LabelField("Orientation Parameters", EditorStyles.boldLabel); if ((inputMode != OrbitUniversal.InputMode.DOUBLE) && (inputMode != OrbitUniversal.InputMode.DOUBLE_ELLIPSE)) { // implementation uses AngleAxis, so degrees are more natural omega_uc = EditorGUILayout.Slider(new GUIContent("\u03a9 (Longitude of AN)", omega_ucTip), (float)orbitU.omega_uc, 0, 360f); omega_lc = EditorGUILayout.Slider(new GUIContent("\u03c9 (AN to Pericenter)", omega_lcTip), (float)orbitU.omega_lc, 0, 360f); inclination = EditorGUILayout.Slider(new GUIContent("Inclination", inclinationTip), (float)orbitU.inclination, 0f, 180f); // physics uses radians - but ask user for degrees to be consistent phase = EditorGUILayout.Slider(new GUIContent("Starting Phase", phaseTip), (float)orbitU.phase, 0, 360f); } else { // DOUBLE, so no sliders omega_uc = EditorGUILayout.DoubleField(new GUIContent("\u03a9 (Longitude of AN)", omega_ucTip), orbitU.omega_uc); omega_lc = EditorGUILayout.DoubleField(new GUIContent("\u03c9 (AN to Pericenter)", omega_lcTip), orbitU.omega_lc); inclination = EditorGUILayout.DoubleField(new GUIContent("Inclination", inclinationTip), orbitU.inclination); phase = EditorGUILayout.DoubleField(new GUIContent("Starting Phase", phaseTip), orbitU.phase); } if (GUI.changed) { Undo.RecordObject(orbitU, "EllipseBase Change"); orbitU.p_inspector = p_inspector; orbitU.eccentricity = ecc; orbitU.centerNbody = centerNBody; orbitU.omega_lc = omega_lc; orbitU.omega_uc = omega_uc; orbitU.inclination = inclination; orbitU.phase = phase; orbitU.inputMode = inputMode; orbitU.evolveMode = evolveMode; EditorUtility.SetDirty(orbitU); } if (sizeUpdate) { orbitU.ApplyScale(GravityEngine.Instance().GetLengthScale()); } }
private static void GetMajorAxis(OrbitUniversal orbitU, ref double p_inspector, ref bool sizeUpdate, GravityScaler.Units units) { float oldLabelWidth = EditorGUIUtility.labelWidth; EditorGUIUtility.labelWidth = oldLabelWidth + 50f; string prompt = string.Format("Semi-Major Axis (a) [{0}]", GravityScaler.LengthUnits(units)); double old_a = orbitU.GetMajorAxisInspector(); double a = EditorGUILayout.DelayedDoubleField(new GUIContent(prompt, aTip), old_a); if (!EditorApplication.isPlaying && (a != old_a)) { orbitU.SetMajorAxisInspector(a); sizeUpdate = true; // Need to update ecc and p with new values p_inspector = orbitU.p_inspector; } EditorGUILayout.LabelField(string.Format("Axis result in: p={0:0.00}", p_inspector)); EditorGUIUtility.labelWidth = oldLabelWidth; }