void Update() { if (!_sim) { _sim = GameObject.FindObjectOfType <SimulationControl>(); } if (!_sim) { return; } if (!_srend) { CreateSpriteObj(); } if (_srend) { if (!_cbody) { _cbody = GetComponent <CelestialBody>(); } float maxrange = Mathf.Min(_sim.MaxAttractionRange, _cbody != null ? _cbody.MaxAttractionRange : _sim.MaxAttractionRange); if (maxrange > 100000f) { _srend.gameObject.SetActive(false); return; } else { _srend.gameObject.SetActive(true); } float radius = _srend.sprite.pixelsPerUnit / _srend.sprite.texture.width * maxrange * 2f; _srend.transform.localScale = new Vector3(radius / transform.localScale.x, radius / transform.localScale.y, 1 / transform.localScale.z); } }
void Update() { if ( !_sim){ _sim = GameObject.FindObjectOfType<SimulationControl>(); } if (!_sim){ return; } if ( !_srend ) { CreateSpriteObj(); } if ( _srend ) { if (!_cbody){ _cbody = GetComponent<CelestialBody>(); } float maxrange = Mathf.Min(_sim.MaxAttractionRange, _cbody != null ? _cbody.MaxAttractionRange : _sim.MaxAttractionRange); if ( maxrange > 100000f){ _srend.gameObject.SetActive(false); return; }else{ _srend.gameObject.SetActive(true); } float radius = _srend.sprite.pixelsPerUnit / _srend.sprite.texture.width * maxrange * 2f; _srend.transform.localScale = new Vector3( radius / transform.localScale.x, radius / transform.localScale.y, 1 / transform.localScale.z ); } }
void Start() { if (!SimControl) { SimControl = GameObject.FindObjectOfType <SimulationControl>(); } if (!slider) { slider = GetComponentInChildren <Slider>(); } if (slider) { slider.minValue = minValue; slider.maxValue = maxValue; if (SimControl) { slider.value = SimControl.TimeScale; } slider.onValueChanged.AddListener(( float f ) => { if (SimControl) { SimControl.TimeScale = f; } }); } }
protected override void Start() { base.Start(); var transforms = GetComponentsInChildren <RectTransform>(); if (Application.isPlaying) { leftFillArea = transforms.FirstOrDefault(t => t.name == "LeftFillArea"); if (leftFillArea != null) { leftFillArea.anchorMin = new Vector2(leftFillArea.anchorMax.x, 0); leftFillArea.pivot = new Vector2(1f, 0.5f); } rightFillArea = transforms.FirstOrDefault(t => t.name == "RightFillArea"); if (rightFillArea != null) { rightFillArea.anchorMax = new Vector2(rightFillArea.anchorMin.x, 1); rightFillArea.pivot = new Vector2(0f, 0.5f); } RefreshFillAreas(); if (simControl == null) { simControl = GameObject.FindObjectOfType <SimulationControl>(); } if (simControl != null) { simControl.timeScale = value; } } }
/// <summary> /// Editor update delegate. /// Subscribe OnSceneGUI delegate if _simControl is not null. If SimulationControl is not exists on scene, continuously retry untill it's not created /// </summary> void StartupUpdate() { if (_waitTime > EditorApplication.timeSinceStartup) { return; ///Wait for check time } if (_simControl == null) { if (SimulationControl.instance != null) { _simControl = SimulationControl.instance; } else { var simControl = GameObject.FindObjectOfType <SimulationControl>(); if (simControl != null) { SimulationControl.instance = simControl; _simControl = simControl; } else { _waitTime = EditorApplication.timeSinceStartup + _waitDuration; return; ///If simulation control is not created, exit and wait for next check time } } } _arrowsBtnImage = Resources.Load("Textures/arrowsBtn") as Texture2D; _orbitsBtnImage = Resources.Load("Textures/orbitsBtn") as Texture2D; // subscribe our OnSceneGUI for updates callbacks SceneView.onSceneGUIDelegate += this.OnSceneGUI; //Instance = this; SceneView.RepaintAll(); EditorApplication.update -= StartupUpdate; //Don't call this function any more. }
void Start() { if ( !SimControl ) { SimControl = GameObject.FindObjectOfType<SimulationControl>(); } if ( !slider ) { slider = GetComponentInChildren<Slider>(); } if ( slider ) { slider.minValue = minValue; slider.maxValue = maxValue; if ( SimControl ) { slider.value = SimControl.TimeScale; } slider.onValueChanged.AddListener( ( float f ) => { if ( SimControl ) { SimControl.TimeScale = f; } } ); } }
///<summary>Computes time step to advance hydraulic simulation.</summary> private long TimeStep() { long tstep = net.HStep; long n = (Htime + net.PStart) / net.PStep + 1; long t = n * net.PStep - Htime; if (t > 0 && t < tstep) { tstep = t; } // Revise time step based on smallest time to fill or drain a tank t = Rtime - Htime; if (t > 0 && t < tstep) { tstep = t; } tstep = SimulationTank.MinimumTimeStep(_tanks, tstep); tstep = SimulationControl.MinimumTimeStep(net, _controls, Htime, tstep); if (_rules.Length > 0) { long step, htime; SimulationRule.MinimumTimeStep( net, _logger, _rules, _tanks, Htime, tstep, _dsystem, out step, out htime); tstep = step; Htime = htime; } else { SimulationTank.StepWaterLevels(_tanks, net.FieldsMap, tstep); } return(tstep); }
void FindReferences() { if (simControl == null) { simControl = GameObject.FindObjectOfType <SimulationControl>(); } if (cam == null) { cam = Camera.main ?? GameObject.FindObjectOfType <Camera>(); } if (pool == null) { pool = GetComponent <BodiesPool>() ?? GameObject.FindObjectOfType <BodiesPool>(); } if (predictionSystem == null) { predictionSystem = GameObject.FindObjectOfType <PredictionSystem>(); } }
private void ProcessPacket(byte[] packet) { using (MemoryStream stream = new MemoryStream(packet)) { using (BinaryReader reader = new BinaryReader(stream)) { var type = reader.ReadSarlString(); switch (type) { case SimulationControl.SIMULATION_CONTROL: { var simulationControl = new SimulationControl(); simulationControl.Parse(reader.BaseStream); SimulationControlReceived(simulationControl); Debug.Log("Simulation Control received"); } break; case Influence.PHYSICAL_INFLUENCE: { var influence = new PhysicalInfluence(); influence.Parse(reader.BaseStream); PhysicalInfluenceReceived(influence); Debug.Log("Physical Influence received"); } break; case Influence.ACTION_INFLUENCE: { var influence = new ActionInfluence(); influence.Parse(reader.BaseStream); ActionInfluenceReceived(influence); Debug.Log("Action Influence received"); } break; } } } }
///<summary>Solve the linear equation system to compute the links flows and nodes heads.</summary> /// <returns>Solver steps and relative error.</returns> protected void NetSolve(out int iter, out double relerr) { iter = 0; relerr = 0.0; int nextCheck = net.CheckFreq; if (net.StatFlag == StatFlag.FULL) { LogRelErr(iter, relerr); } int maxTrials = net.MaxIter; if (net.ExtraIter > 0) { maxTrials += net.ExtraIter; } double relaxFactor = 1.0; int errcode = 0; iter = 1; while (iter <= maxTrials) { //Compute coefficient matrices A & F and solve A*H = F // where H = heads, A = Jacobian coeffs. derived from // head loss gradients, & F = flow correction terms. NewCoeffs(); //dumpMatrixCoeffs(new File("dumpMatrix.txt"),true); // Solution for H is returned in F from call to linsolve(). errcode = _smat.LinSolve( _junctions.Count, _lsv.AiiVector, _lsv.AijVector, _lsv.RhsCoeffs); // Ill-conditioning problem if (errcode > 0) { // If control valve causing problem, fix its status & continue, // otherwise end the iterations with no solution. if (SimulationValve.CheckBadValve( net, _logger, _valves, Htime, _smat.GetOrder(errcode))) { continue; } break; } // Update current solution. // (Row[i] = row of solution matrix corresponding to node i). foreach (SimulationNode node in _junctions) { node.SimHead = _lsv.GetRhsCoeff(_smat.GetRow(node.Index)); // Update heads } // Update flows relerr = NewFlows(relaxFactor); // Write convergence error to status report if called for if (net.StatFlag == StatFlag.FULL) { LogRelErr(iter, relerr); } relaxFactor = 1.0; bool valveChange = false; // Apply solution damping & check for change in valve status if (net.DampLimit > 0.0) { if (relerr <= net.DampLimit) { relaxFactor = 0.6; valveChange = SimulationValve.ValveStatus(net, _logger, _valves); } } else { valveChange = SimulationValve.ValveStatus(net, _logger, _valves); } // Check for convergence if (relerr <= net.HAcc) { // We have convergence. Quit if we are into extra iterations. if (iter > net.MaxIter) { break; } // Quit if no status changes occur. bool statChange = valveChange; if (SimulationLink.LinkStatus(net, _logger, _links)) { statChange = true; } if (SimulationControl.PSwitch(_logger, net, _controls)) { statChange = true; } if (!statChange) { break; } // We have a status change so continue the iterations nextCheck = iter + net.CheckFreq; } else if (iter <= net.MaxCheck && iter == nextCheck) { // No convergence yet. See if its time for a periodic status // check on pumps, CV's, and pipes connected to tanks. SimulationLink.LinkStatus(net, _logger, _links); nextCheck += net.CheckFreq; } iter++; } foreach (SimulationNode node in _junctions) { node.SimDemand = node.SimDemand + node.SimEmitter; } if (errcode > 0) { LogHydErr(_smat.GetOrder(errcode)); errcode = 110; return; } if (errcode != 0) { throw new ENException((ErrorCode)errcode); } }
/// <summary> /// Editor update delegate. /// Subscribe OnSceneGUI delegate if _simControl is not null. If SimulationControl is not exists on scene, continuously retry untill it's not created /// </summary> void StartupUpdate() { if (_waitTime > EditorApplication.timeSinceStartup) { return; ///Wait for check time } if (_simControl == null) { if (SimulationControl.instance != null) { _simControl = SimulationControl.instance; } else { var simControl = GameObject.FindObjectOfType<SimulationControl>(); if (simControl != null) { SimulationControl.instance = simControl; _simControl = simControl; } else { _waitTime = EditorApplication.timeSinceStartup + _waitDuration; return; ///If simulation control is not created, exit and wait for next check time } } } _arrowsBtnImage = Resources.Load("Textures/arrowsBtn") as Texture2D; _orbitsBtnImage = Resources.Load("Textures/orbitsBtn") as Texture2D; // subscribe our OnSceneGUI for updates callbacks SceneView.onSceneGUIDelegate += this.OnSceneGUI; //Instance = this; SceneView.RepaintAll(); EditorApplication.update -= StartupUpdate; //Don't call this function any more. }
/// <summary> /// simControl may be null /// </summary> public SceneViewDisplayManager(SimulationControl simControl) { _simControl = simControl; _bodies = new List<CelestialBody>(); EditorApplication.update += StartupUpdate; }
/// <summary> /// General window onGUI /// </summary> void OnGUI() { if (!_simControl || _simControlSerialized == null) { _simControl = FindOrCreateSimulationControlGameObject(); if (!_simControl) {//check if creation process failed Debug.LogWarning("SpaceGravity2D.Editor: no Simulation Control found or created"); this.Close(); return; } InitializeProperties(); } if (SimulationControl.instance == null) { SimulationControl.instance = _simControl; } _simControlSerialized.Update(); EditorGUILayout.LabelField("Tools:", EditorStyles.boldLabel); if (GUILayout.Button("Inverse velocity for all selected celestial bodies")) { InverseVelocityFor(Selection.gameObjects); //Undo functionality is supported } if (GUILayout.Button(new GUIContent("Place all selected bodies randomly around attractor", "Convinient to create asteroids belts. \nusage: all selected bodies must have same attracor. before making selection and pressing this button, place one body at preffered minimal distance and one body - at preffered max distance. placement distances bounds will be calculated from bodies start positions."))) { PlaceBodiesRandomly(Selection.gameObjects); } try { EditorGUILayout.LabelField("Global Parameters:", EditorStyles.boldLabel); EditorGUILayout.PropertyField(calcTypeProp, new GUIContent("N-Body algorithm", "Euler - fastest, \nVerlet - fast and more stable, \nRungeKutta - more precise")); EditorGUILayout.PropertyField(gravConstProp); var gravConst = EditorGUILayout.FloatField(new GUIContent("Grav.Const. Proportional", "Change gravitational constant AND keep all orbits unaffected"), gravConstProp.floatValue); if (gravConst != gravConstProp.floatValue) { if (Mathf.Abs(gravConst) < 1e-8f) { gravConst = 1e-4f; } _simControl.GravitationalConstantProportional = gravConst; } EditorGUILayout.PropertyField(inflRangeProp); EditorGUILayout.PropertyField(inflRangeMinProp); EditorGUILayout.PropertyField(timeScaleProp); EditorGUILayout.PropertyField(minMassProp); EditorGUILayout.PropertyField(drawArrowsProp); EditorGUILayout.PropertyField(drawEditorOrbsProp); EditorGUILayout.PropertyField(drawDisabledOrbsProp, new GUIContent("Draw disabled orbits in editor", "Use if you want to see all orbits, even if celestial body has disabled orbit display")); EditorGUILayout.PropertyField(drawPlayOrbsProp); EditorGUILayout.LabelField("Orbit Line Renderer:", EditorStyles.boldLabel); EditorGUILayout.PropertyField(lineRendMatProp); EditorGUILayout.PropertyField(orbitWidthProp); EditorGUILayout.PropertyField(orbitPointsProp); EditorGUILayout.LabelField("Editor Parameters:", EditorStyles.boldLabel); EditorGUILayout.PropertyField(drawDebugPointsProp); EditorGUILayout.PropertyField(arrowsSizeProp); EditorGUILayout.PropertyField(arrowsGlobalProp, new GUIContent("Global velocity vectors", "Toggle global/local space for velocity arrows")); _simControl.selectWhenDraggingArrow = EditorGUILayout.Toggle("Select object with arrow", _simControl.selectWhenDraggingArrow); } catch (Exception ex) { Debug.LogError("SpaceGravity2D.Editor: " + ex.Message); Close(); } if (GUI.changed) { _simControlSerialized.ApplyModifiedProperties(); SceneView.RepaintAll(); } }
///<summary>Implements simple controls based on time or tank levels.</summary> private void ComputeControls() { SimulationControl.StepActions(_logger, net, _controls, Htime); }
void Start() { simulationControl = GetComponent <SimulationControl>(); }
/// <summary> /// simControl may be null /// </summary> public SceneViewDisplayManager(SimulationControl simControl) { _simControl = simControl; _bodies = new List <CelestialBody>(); EditorApplication.update += StartupUpdate; }
/// <summary> /// General window onGUI /// </summary> void OnGUI() { if (!_simControl || _simControlSerialized == null) { _simControl = FindOrCreateSimulationControlGameObject(); if (!_simControl) //check if creation process failed { Debug.LogWarning("SpaceGravity2D.Editor: no Simulation Control found or created"); this.Close(); return; } InitializeProperties(); } if (SimulationControl.instance == null) { SimulationControl.instance = _simControl; } _simControlSerialized.Update(); EditorGUILayout.LabelField("Tools:", EditorStyles.boldLabel); if (GUILayout.Button("Inverse velocity for all selected celestial bodies")) { InverseVelocityFor(Selection.gameObjects); //Undo functionality is supported } if (GUILayout.Button(new GUIContent("Place all selected bodies randomly around attractor", "Convinient to create asteroids belts. \nusage: all selected bodies must have same attracor. before making selection and pressing this button, place one body at preffered minimal distance and one body - at preffered max distance. placement distances bounds will be calculated from bodies start positions."))) { PlaceBodiesRandomly(Selection.gameObjects); } try { EditorGUILayout.LabelField("Global Parameters:", EditorStyles.boldLabel); EditorGUILayout.PropertyField(calcTypeProp, new GUIContent("N-Body algorithm", "Euler - fastest, \nVerlet - fast and more stable, \nRungeKutta - more precise")); EditorGUILayout.PropertyField(gravConstProp); var gravConst = EditorGUILayout.FloatField(new GUIContent("Grav.Const. Proportional", "Change gravitational constant AND keep all orbits unaffected"), gravConstProp.floatValue); if (gravConst != gravConstProp.floatValue) { if (Mathf.Abs(gravConst) < 1e-8f) { gravConst = 1e-4f; } _simControl.GravitationalConstantProportional = gravConst; } EditorGUILayout.PropertyField(inflRangeProp); EditorGUILayout.PropertyField(inflRangeMinProp); EditorGUILayout.PropertyField(timeScaleProp); EditorGUILayout.PropertyField(minMassProp); EditorGUILayout.PropertyField(drawArrowsProp); EditorGUILayout.PropertyField(drawEditorOrbsProp); EditorGUILayout.PropertyField(drawDisabledOrbsProp, new GUIContent("Draw disabled orbits in editor", "Use if you want to see all orbits, even if celestial body has disabled orbit display")); EditorGUILayout.PropertyField(drawPlayOrbsProp); EditorGUILayout.LabelField("Orbit Line Renderer:", EditorStyles.boldLabel); EditorGUILayout.PropertyField(lineRendMatProp); EditorGUILayout.PropertyField(orbitWidthProp); EditorGUILayout.PropertyField(orbitPointsProp); EditorGUILayout.LabelField("Editor Parameters:", EditorStyles.boldLabel); EditorGUILayout.PropertyField(drawDebugPointsProp); EditorGUILayout.PropertyField(arrowsSizeProp); EditorGUILayout.PropertyField(arrowsGlobalProp, new GUIContent("Global velocity vectors", "Toggle global/local space for velocity arrows")); _simControl.selectWhenDraggingArrow = EditorGUILayout.Toggle("Select object with arrow", _simControl.selectWhenDraggingArrow); } catch (Exception ex) { Debug.LogError("SpaceGravity2D.Editor: " + ex.Message); Close(); } if (GUI.changed) { _simControlSerialized.ApplyModifiedProperties(); SceneView.RepaintAll(); } }
/// <summary> /// Editor window onGUI. /// </summary> private void OnGUI() { if (!_simControl || _simControlSerialized == null) { _simControl = FindSimulationControlGameObject(); if (!_simControl) { EditorGUILayout.LabelField("SimulationControl instance not found on scene."); return; } InitializeProperties(); } if (SimulationControl.Instance == null) { SimulationControl.Instance = _simControl; } _simControlSerialized.Update(); _scrollPos = GUILayout.BeginScrollView(_scrollPos, false, true, GUILayout.MinHeight(200), GUILayout.MaxHeight(1000), GUILayout.ExpandHeight(true)); EditorGUILayout.LabelField("Global Parameters:", EditorStyles.boldLabel); EditorGUILayout.PropertyField(calcTypeProp, new GUIContent("N-Body algorithm(?)", "Euler - fastest performance, \nVerlet - fast and more stable, \nRungeKutta - more precise.")); var gravConst = EditorGUILayout.DoubleField(new GUIContent("Gravitational Constant(?)", "Main constant. The real value 6.67384 * 10E-11 may not be very useful for gaming purposes."), _simControl.GravitationalConstant); if (gravConst != _simControl.GravitationalConstant) { Undo.RecordObject(_simControl, "Grav.Const change"); _simControl.GravitationalConstant = gravConst; } EditorGUILayout.Space(); EditorGUILayout.BeginVertical("box"); { EditorGUILayout.LabelField("Change Grav. Const. with proportional adjusting of all velocities on scene:"); gravConst = EditorGUILayout.DoubleField(new GUIContent("Grav.Const.Proportional(?)", "Change gravitational constant AND keep all orbits unaffected."), _simControl.GravitationalConstant); if (gravConst != _simControl.GravitationalConstant) { Undo.RecordObject(_simControl, "Grav.Const change"); _simControl.GravitationalConstantProportional = gravConst; } } EditorGUILayout.EndVertical(); EditorGUILayout.Space(); EditorGUILayout.PropertyField(inflRangeProp, new GUIContent("Max influence range(?)", "Global max range of n-body attraction.")); EditorGUILayout.PropertyField(inflRangeMinProp, new GUIContent("Min influence range(?)", "Global min range of n-body attraction.")); EditorGUILayout.PropertyField(timeScaleProp, new GUIContent("Time Scale(?)", "Time multiplier. Note: high value will decrease n-body calculations precision.")); EditorGUILayout.PropertyField(minMassProp, new GUIContent("Min attractor mass(?)", "Mass threshold for body to became attractor.")); EditorGUILayout.Space(); EditorGUILayout.Space(); EditorGUILayout.LabelField("Keep ALL bodies on ecliptic plane:"); var keep2d = EditorGUILayout.Toggle(new GUIContent("2d mode(?)", "Force all bodies to project positions and velocities onto ecliptic plane."), _simControl.KeepBodiesOnEclipticPlane); if (keep2d != _simControl.KeepBodiesOnEclipticPlane) { Undo.RecordObject(_simControl, "2d mode toggle"); _simControl.KeepBodiesOnEclipticPlane = keep2d; if (keep2d) { _simControl.ProjectAllBodiesOnEcliptic(); } } EditorGUILayout.LabelField("Is affected by global timescale:"); var scaledTime = EditorGUILayout.Toggle(new GUIContent("Global timescale(?)", "Toggle ignoring of Time.timeScale."), _simControl.AffectedByGlobalTimescale); if (scaledTime != _simControl.AffectedByGlobalTimescale) { Undo.RecordObject(_simControl, "affected by timescale toggle"); _simControl.AffectedByGlobalTimescale = scaledTime; } EditorGUILayout.Space(); EditorGUILayout.PropertyField(eclipticNormalProp, new GUIContent("Ecliptic Normal Vector(?)", "Perpendicular to ecliptic plane.")); EditorGUILayout.PropertyField(eclipticUpProp, new GUIContent("Ecliptic Up Vector(?)", "Up vector on ecliptic plane. Always perpendicular to ecliptic normal. Used for rotation tool.")); EditorGUILayout.Space(); EditorGUILayout.LabelField("Set ecliptic normal along axis:", EditorStyles.boldLabel); GUILayout.BeginHorizontal(); if (GUILayout.Button("X")) { SetEclipticNormal(new Vector3d(1, 0, 0), new Vector3d(0, 0, 1)); } GUILayout.Space(6); if (GUILayout.Button("-X")) { SetEclipticNormal(new Vector3d(-1, 0, 0), new Vector3d(0, 0, -1)); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); if (GUILayout.Button("Y")) { SetEclipticNormal(new Vector3d(0, 1, 0), new Vector3d(0, 0, 1)); } GUILayout.Space(6); if (GUILayout.Button("-Y")) { SetEclipticNormal(new Vector3d(0, -1, 0), new Vector3d(0, 0, -1)); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); if (GUILayout.Button("Z")) { SetEclipticNormal(new Vector3d(0, 0, 1), new Vector3d(1, 0, 0)); } GUILayout.Space(6); if (GUILayout.Button("-Z")) { SetEclipticNormal(new Vector3d(0, 0, -1), new Vector3d(-1, 0, 0)); } GUILayout.EndHorizontal(); EditorGUILayout.LabelField("Ecliptic plane is used to calculate ascending/descending nodes,"); EditorGUILayout.LabelField("orbit inclination and for 2D-restricted simulation (if this option is active)."); bool eclipticRotateTool = GUILayout.Toggle(_displayManager.IsEclipticRotating, "Rotate Ecliptic Plane", "Button"); if (eclipticRotateTool != _displayManager.IsEclipticRotating) { _displayManager.IsEclipticRotating = eclipticRotateTool; } bool orbitRotateTool = GUILayout.Toggle(_displayManager.IsOrbitRotating, "Rotate Orbit Of Selected Obj.", "Button"); if (orbitRotateTool != _displayManager.IsOrbitRotating) { _displayManager.IsOrbitRotating = orbitRotateTool; } EditorGUIUtility.labelWidth = 250f; EditorGUILayout.BeginVertical("box"); { EditorGUILayout.PropertyField(sceneViewDisplayParametersProp, true); } EditorGUILayout.EndVertical(); GUILayout.Space(15); GUILayout.EndScrollView(); if (GUI.changed) { _simControlSerialized.ApplyModifiedProperties(); SceneView.RepaintAll(); } }