public Translate(float startTick, float endTick, string actorName, Vector3?possibleOrigin, Vector3Nullable destination) : base(startTick, endTick) { this.actorName = actorName; this.possibleOrigin = possibleOrigin; this.destination = destination; }
private static void enqueueRotateActions(IStoryAction <UintT> storyAction, CM.DomainAction domainAction, CM.Animation effectingAnimation, FireBoltActionList aaq, string parentActionId, bool implicitActorInstantiation) { foreach (CM.RotateAction ra in domainAction.RotateActions) { float startTick = 0; float endTick = 0; string actorName = null; float? targetDegrees = null; Vector2?targetPoint = null; foreach (CM.DomainActionParameter domainActionParameter in domainAction.Params) { if (domainActionParameter.Name == ra.ActorNameParamName) { if (!getActionParameterValue(storyAction, domainActionParameter, out actorName) || (implicitActorInstantiation && !actorWillBeInstantiated(actorName))) { break; } } else if (domainActionParameter.Name == ra.DestinationParamName) { IActionProperty targetOrientation; if (storyAction.TryGetProperty(domainActionParameter.Name, out targetOrientation)) { if (targetOrientation.Value.Value is float) { targetDegrees = (float)targetOrientation.Value.Value; if (targetOrientation.Range.Name == "x+degrees") { targetDegrees = targetDegrees.Value.convertSourceEngineToUnityRotation(); } } else if (targetOrientation.Value.Value is Coordinate2D) { targetPoint = new Vector2((float)((Coordinate2D)targetOrientation.Value.Value).X, (float)((Coordinate2D)targetOrientation.Value.Value).Y); } } else { Debug.LogError("orientation not set for stepId[" + storyAction.Name + "]"); } } } startTick = getStartTick(storyAction, ra, effectingAnimation); endTick = getEndTick(storyAction, ra, effectingAnimation, startTick); var targetRotation = new Vector3Nullable(null, targetDegrees, null); if (Rotate.ValidForConstruction(actorName, targetRotation, targetPoint)) { aaq.Add(new Rotate(startTick, endTick, actorName, targetRotation, targetPoint) { ParentActionId = parentActionId }); } } }
public static bool ValidForConstruction(string actorName, Vector3Nullable targetRotation, Vector2?targetPoint) { if (string.IsNullOrEmpty(actorName)) { return(false); } if ((targetRotation.X.HasValue || targetRotation.Y.HasValue || targetRotation.Z.HasValue) && //can't define an angle and a point targetPoint.HasValue) { return(false); } return(true); }
/// <summary> /// /// </summary> /// <param name="startTick"></param> /// <param name="endTick"></param> /// <param name="actorName"></param> /// <param name="targetRotation"></param> /// <param name="targetPoint">x,z</param> public Rotate(float startTick, float endTick, string actorName, Vector3Nullable targetRotation, Vector2?targetPoint) : base(startTick, endTick) { this.actorName = actorName; //TODO this smells. but generality in all dimensions will take too long to figure out //if the targetPoint is specified, prefer to use it over a bare rotation value if (targetPoint.HasValue) { this.targetOrientation = new Vector3Nullable(null, Mathf.Atan2(targetPoint.Value.x, targetPoint.Value.y) * Mathf.Rad2Deg, null); } else { this.targetOrientation = targetRotation; } }
public override bool Init() { if (initialized) { return(true); } Profiler.BeginSample("init shot frag"); Extensions.RenderColliders(); //don't throw null refs in the debug statement if framing isn't there. it's not required string framingDescriptor = string.Empty; if (existsFraming()) { framingDescriptor = framings[0].ToString(); } Extensions.Log("init shot fragment start[{0}] end[{1}] anchor[{2}] height[{3}] lens[{4}] fStop[{5}] framing[{6}] direction[{7}] angle[{8}] focus[{9}] d:s[{10}:{11}]", startTick, endTick, anchor, height, lensName, fStopName, framingDescriptor, direction, cameraAngle, focusTarget, ElPresidente.Instance.CurrentDiscourseTime, ElPresidente.Instance.CurrentStoryTime); if (!findCamera()) { return(false); } savePreviousCameraState(); //ground parameters tempCameraPosition = new Vector3Nullable(null, null, null); tempCameraOrientation = new Vector3Nullable(null, null, null); //anchor if specified Vector2 anchorPosition; if (calculateAnchor(anchor, out anchorPosition)) { Extensions.Log("setting camera anchor[{0}]", anchorPosition); tempCameraPosition.X = anchorPosition.x; tempCameraPosition.Z = anchorPosition.y; } //subject position if something is framed GameObject framingTarget = null; if (existsFraming()) { if (getActorByName(framings[0].FramingTarget, out framingTarget)) { targetLookAtPoint = findTargetLookAtPoint(framingTarget); } else { Debug.LogError(string.Format("could not find actor [{0}]", framings[0].FramingTarget).AppendTimestamps()); } } //height if (existsFraming()) //default to even height with point of interest on framed target { tempCameraPosition.Y = targetLookAtPoint.y; } else if (height.HasValue) { tempCameraPosition.Y = height; } else { tempCameraPosition.Y = 1; //in the absence of all information just put the camera not at 0 height } //lens ushort tempLens; if (!string.IsNullOrEmpty(lensName) && CameraActionFactory.lenses.TryGetValue(lensName, out tempLens)) { tempLensIndex = tempLens; } //F Stop ushort tempFStop; if (!string.IsNullOrEmpty(fStopName) && CameraActionFactory.fStops.TryGetValue(fStopName, out tempFStop)) { tempFStopIndex = tempFStop; } //framing if (existsFraming() && framingTarget) { Bounds targetBounds = framingTarget.GetComponent <BoxCollider>().bounds; targetBounds.BuildDebugBox(5, Color.cyan); Extensions.Log("framing target[{0}] bounds[{1},{2}]", framingTarget.name, targetBounds.min.y, targetBounds.max.y); FramingParameters framingParameters = FramingParameters.FramingTable[framings[0].FramingType]; //default our aperture to one appropriate to the framing if it's not set if (!tempFStopIndex.HasValue && CameraActionFactory.fStops.TryGetValue(framingParameters.DefaultFStop, out tempFStop)) { tempFStopIndex = tempFStop; } if (tempLensIndex.HasValue && tempCameraPosition.X.HasValue && tempCameraPosition.Z.HasValue) { //case is here for completeness. rotation needs to be done for all combinations of lens and anchor specification, so it goes after all the conditionals } else if (!tempLensIndex.HasValue && tempCameraPosition.X.HasValue && tempCameraPosition.Z.HasValue)//direction still doesn't matter since we can't move in the x,z plane { //naively guessing and checking Quaternion savedCameraRotation = cameraBody.NodalCamera.transform.rotation; //point the camera at the thing cameraBody.NodalCamera.transform.rotation = Quaternion.LookRotation(targetBounds.center - cameraBody.NodalCamera.transform.position); float targetFov = 0; //need to keep from stepping up and down over some boundary bool incremented = false; bool decremented = false; while (!(incremented && decremented)) //if we haven't set a value and we haven't stepped both up and down. { //find where on the screen the extents are. using viewport space so this will be in %. z is world units away from camera Vector3 bMax = cameraBody.NodalCamera.WorldToViewportPoint(targetBounds.max); Vector3 bMin = cameraBody.NodalCamera.WorldToViewportPoint(targetBounds.min); float FovStepSize = 2.5f;//consider making step size a function of current size to increase granularity at low fov. 2.5 is big enough to jump 100-180 oddly if (bMax.y - bMin.y > framingParameters.MaxPercent && bMax.y - bMin.y < framingParameters.MinPercent) { break;//we found our answer in cameraBody.NodalCamera.fov } else if (bMax.y - bMin.y < framingParameters.MinPercent) { cameraBody.NodalCamera.fieldOfView -= FovStepSize; decremented = true; } else //(bMax.y - bMin.y >= fp.MaxPercent) { cameraBody.NodalCamera.fieldOfView += FovStepSize; incremented = true; } //force matrix recalculations on the camera after adjusting fov cameraBody.NodalCamera.ResetProjectionMatrix(); cameraBody.NodalCamera.ResetWorldToCameraMatrix(); } //reset camera position...we should only be moving the rig targetFov = cameraBody.NodalCamera.fieldOfView; cameraBody.NodalCamera.transform.rotation = savedCameraRotation; tempLensIndex = (ushort)ElPresidente.Instance.GetLensIndex(targetFov); } else if (tempLensIndex.HasValue && //direction matters here. (!tempCameraPosition.X.HasValue || !tempCameraPosition.Z.HasValue)) //also assuming we get x,z in a pair. if only one is provided, it is invalid and will be ignored { //allow full exploration of circle about target since we can't move in or out and keep the same framing if (!findCameraPositionByRadius(framingTarget, targetBounds, framingParameters, 1.0f)) { Extensions.Log("failed to find satisfactory position for camera to frame [{0}] [{1}] with lens [{2}]. view will be obstructed", framings[0].FramingTarget, framings[0].FramingType.ToString(), ElPresidente.Instance.lensFovData[tempLensIndex.Value]._focalLength); } } else //we are calculating everything by framing and direction. { //x,z does not have value //pick a typical lens for this type of shot tempLensIndex = CameraActionFactory.lenses[framingParameters.DefaultFocalLength]; //see if we can find a camera location for this lens //allow less than some % of a circle variance from ideal viewing. if we don't find an answer, change the lens bool sign = true; short iterations = 0; ushort maxLensChangeIterations = 6; while (!findCameraPositionByRadius(framingTarget, targetBounds, framingParameters, 0.35f)) { iterations++; if (iterations > maxLensChangeIterations) { Extensions.Log("exceeded max lens change iterations[{0}] solving framing[{1}] on target[{2}]", maxLensChangeIterations, framingParameters.Type, framingTarget); break; //framing is just not working out. we will return a shot that's not so good and get on with things } int offset = sign ? iterations : -iterations; if (tempLensIndex + offset < 0) { //should never get here since the smallest we specify is 27mm and we will cap at +-3 lenses } else if (tempLensIndex + offset > CameraActionFactory.lenses.Values.Max <ushort>()) { //explore on the other side of our start lens until we hit our max iterations iterations++; offset = sign ? -iterations : iterations; } tempLensIndex = (ushort)(tempLensIndex + offset); } } tempCameraOrientation.Y = Quaternion.LookRotation(framingTarget.transform.position - tempCameraPosition.Merge(previousCameraPosition)).eulerAngles.y; } else if (pan.HasValue) //no framing, we can pay attention to a direct rotate command { tempCameraOrientation.Y = pan.Value.BindToSemiCircle(); } //this destroys the ability to angle with respect to anything but the framing target if specified //this does not seem terribly harmful. subject is attached to angle mostly because we wanted to not have //to specify a framing (if we used an absolute anchor for camera positioning) tiltCameraAtSubject(cameraAngle, framingTarget); //focus has to go after all possible x,y,z settings to get the correct distance to subject Vector3 focusPosition; if (calculateFocusPosition(focusTarget, out focusPosition)) { tempFocusDistance = Vector3.Distance(tempCameraPosition.Merge(previousCameraPosition), focusPosition); } else if (framingTarget != null)//we didn't specify what to focus on, but we framed something. let's focus on that by default { tempFocusDistance = Vector3.Distance(tempCameraPosition.Merge(previousCameraPosition), targetLookAtPoint); } //sort out what wins where and assign to final camera properties //start with previous camera properties in case nothing fills them in newCameraPosition = tempCameraPosition.Merge(previousCameraPosition); newCameraOrientation = Quaternion.Euler(tempCameraOrientation.Merge(previousCameraOrientation.eulerAngles)); newLensIndex = tempLensIndex.HasValue ? tempLensIndex.Value : previousLensIndex; newFStopIndex = tempFStopIndex.HasValue ? tempFStopIndex.Value : previousFStopIndex; newfocusDistance = tempFocusDistance.HasValue ? tempFocusDistance.Value : previousFocusDistance; Skip(); initialized = true; Profiler.EndSample(); return(initialized); }
/// <summary> /// applies the specified values in this Vector3Nullable, newValues, over those in overridden. /// for all unspecified values in newValues, overridden controls. /// </summary> /// <param name="newValues"></param> /// <param name="overridden"></param> /// <returns></returns> public static Vector3 Merge(this Vector3Nullable newValues, Vector3 overridden) { return(new Vector3(newValues.X.HasValue ? newValues.X.Value : overridden.x, newValues.Y.HasValue ? newValues.Y.Value : overridden.y, newValues.Z.HasValue ? newValues.Z.Value : overridden.z)); }
private static void enqueuetranslateActions(IStoryAction <UintT> storyAction, CM.DomainAction domainAction, CM.Animation effectingAnimation, FireBoltActionList aaq, string parentActionId, bool implicitActorInstantiation) { foreach (CM.TranslateAction ta in domainAction.TranslateActions) { float startTick = 0; float endTick = 0; string actorName = null; Vector3Nullable destination = new Vector3Nullable(null, null, null); Vector3 origin = Vector3.zero; foreach (CM.DomainActionParameter domainActionParameter in domainAction.Params) { if (domainActionParameter.Name == ta.OriginParamName) { IActionProperty coord; if (storyAction.TryGetProperty(domainActionParameter.Name, out coord)) { if (coord.Value.Value is Coordinate2D) { origin = ((Coordinate2D)coord.Value.Value).ToVector3(cm.DomainDistancePerEngineDistanceX, cm.DomainDistancePerEngineDistanceY, cm.DomainDistancePerEngineDistanceZ); } else if (coord.Value.Value is Coordinate3D) { origin = ((Coordinate3D)coord.Value.Value).ToVector3(cm.DomainDistancePerEngineDistanceX, cm.DomainDistancePerEngineDistanceY, cm.DomainDistancePerEngineDistanceZ); } } else { Debug.LogError("origin not set for stepId[" + storyAction.Name + "]"); } } else if (domainActionParameter.Name == ta.DestinationParamName) { IActionProperty coord; if (storyAction.TryGetProperty(domainActionParameter.Name, out coord)) { if (coord.Value.Value is Coordinate2D) { destination = ((Coordinate2D)coord.Value.Value).ToVector3Nullable(cm.DomainDistancePerEngineDistanceX, cm.DomainDistancePerEngineDistanceY, cm.DomainDistancePerEngineDistanceZ); } else if (coord.Value.Value is Coordinate3D) { destination = ((Coordinate3D)coord.Value.Value).ToVector3Nullable(cm.DomainDistancePerEngineDistanceX, cm.DomainDistancePerEngineDistanceY, cm.DomainDistancePerEngineDistanceZ); } } else { Debug.LogError("destination not set for stepId[" + storyAction.Name + "]"); } } else if (domainActionParameter.Name == ta.ActorNameParamName) { if (!getActionParameterValue(storyAction, domainActionParameter, out actorName) || (implicitActorInstantiation && !actorWillBeInstantiated(actorName))) { break; } } } startTick = getStartTick(storyAction, ta, effectingAnimation); endTick = getEndTick(storyAction, ta, effectingAnimation, startTick); if (Translate.ValidForConstruction(actorName)) { aaq.Add(new Translate(startTick, endTick, actorName, origin, destination) { ParentActionId = parentActionId }); } } }