Skip to content

Zero-click presenter with texture selection dropdown#22

Merged
mark-beiline merged 14 commits into
devfrom
mark/present-to-screen-v3
Mar 31, 2023
Merged

Zero-click presenter with texture selection dropdown#22
mark-beiline merged 14 commits into
devfrom
mark/present-to-screen-v3

Conversation

@mark-beiline
Copy link
Copy Markdown
Collaborator

@mark-beiline mark-beiline commented Mar 24, 2023

Project-wide setting enabled by default:
image

Adds remote parameter group to schema:
image

Options are None + channels + live textures:
image

A number of resize strategies:
image

@mark-beiline mark-beiline mentioned this pull request Mar 24, 2023
@mark-beiline mark-beiline marked this pull request as ready for review March 27, 2023 15:24
@mark-beiline
Copy link
Copy Markdown
Collaborator Author

Supporting changes:

  • DisguiseRenderStream.cs: Callbacks and access to live textures.
  • BlitStrategy.cs: Added Clamp strategy
  • CameraCapturePresenter.cs: It was assumed that the CameraCapture component lived on the same GameObject. This was limiting in the case of the DisguisePresenter prefab, so now it supports both ways (auto-assign if null).
  • Presenter.cs: Moved away from Graphics.* API for clearing the screen (which blocks the main thread). Automatically clears the screen after being disabled to prevent a "frozen" frame.

…Unity into mark/present-to-screen-v3

# Conflicts:
#	DisguiseUnityRenderStream/Editor/DisguiseRenderStreamBuild.cs
// overshadows a parent member (ex TextMeshPro.renderer). Since we traverse the hierarchy top to bottom,
// the top-level member will be resolved.

// * BindingFlags.IgnoreCase: For secondary lookup (ex "Position" after "m_Position" failed we want to match both "Position" and "position").
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The root of these edge cases is that we're trying to match UnityEditor.SerializedProperty.propertyPath to a System.Reflection.MemberInfo.

This could be fixed in another PR where we wouldn't use SerializedProperty anymore, by enumerating fields/properties using System.Serialization directly.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible you are missing the .meta for that prefab and DisguisePresenter.cs? I have a null reference exception while building and I think this is the cause.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would be because the .gitignore has *.meta, do we want to keep that?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the .meta files. They're all "default" meta files, except for NativeRenderingPlugin.dll.meta which is configured for Windows x64. Which makes me think maybe the bug could be unrelated to meta files because your default meta files should work like mine.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Build exception is fixed. Probably the prefab uses some uuid from the .meta. So although it is the default one, my computer did not generate the same uuid than yours.


namespace Disguise.RenderStream
{
/// <summary>
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brainstorm: This is brilliant to understand when we have a problem I tried and love it! However does that have any other usage than debug? Will it be used in production? If no then:

  1. Should we give a name making it more obvious that this is for debugging? UnityDebugPresenter? (Unity vs Disguise because the debug is displayed in the unity window on the rendering computer)
  2. Do we want this debug to be present by default (should probably ask Kylo?)? I'm asking because generally debugging in software are off by default.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Good point. Any preference between UnityDebugPresenter and UnityWindowPresenter? I like "window" because it removes ambiguity around "local display" or "local screen".
  2. The default texture selection is "None" so it's opt-in even when it's included in the schema. So the user wouldn't have to make a new build when they want to enable it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Personally I like to have Debug in there so it is obvious that it is for debugging. What about UnityDebugWindowPresenter? The best of both world?
  2. Is there potential draw back of selecting something? I think it has a small performance impact? What about user activate it, forget about it and then has worst performance than before and can't find why?

}

private const string k_PrefabPath = "DisguisePresenter";
private const string k_NoneTextureLabel = "None";
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor from Rider: Inconsistent modifiers style: redundant 'private' modifier

/// The choices for the texture selection dropdown are scene-specific and correspond to a concatenated list of:
/// None + Channels (output) + Live textures (input).
/// </remarks>
public static List<ManagedRemoteParameter> GetManagedRemoteParameters(ManagedSchema schema, ManagedRemoteParameters sceneSchema)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curiosity: Why do we have this special mechanism for those remote parameters? Can't they be simply picked-up as normal remote parameters?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to add the presenter to all scenes automatically. One method would be to add it to each scene in a build postprocessor but I'm not a fan of modifying scene files under the hood.

This other method is to add it to each scene at runtime after it's loaded. We only need to make sure it's in the schema by retrieving the presenter parameters from GetManagedRemoteParameters.

It also does some processing on the parameters, most importantly we need to collect the texture names for the dropdown (channels are global, but live textures are per-scene). So GetManagedRemoteParameters needs to be called after a first version of the schema has been generated.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improvement idea: Instead of keeping those settings in some ScriptableObject hidden somewhere in the assets, should we add it to the project settings? Using [SettingsProvider] like Wen did in ClusterDisplay?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, I would expect to see them in Project Settings. I found the files you mentioned, I can do it in a follow-up PR.

/// The generated schema will include remote parameters to select the texture to display and how to resize it to fit the screen.
/// </summary>
[SerializeField]
public bool exposePresenter = true;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: If we keep the default UI for those those two fields (which on first sight are sufficient), maybe we should add tooltips with parts of the summary for those two parameters?

Copy link
Copy Markdown
Owner

@wenzhang-unity wenzhang-unity left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome. I left some comments for you to consider.

/// <para>
/// 2. Presenting a texture to the screen according to <see cref="Selected"/> and <see cref="ResizeStrategy"/>.
/// </para>
/// </summary>
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor (style): The longer detailed description can go into <remarks>

/// <remarks>
/// <paramref name="outputIdx"/> and <paramref name="inputIdx"/> are -1 when invalid.
/// </remarks>
void VirtualIndexToRealIndex(int virtualIdx, out int outputIdx, out int inputIdx)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A (very) inconsequential case here, but in general, instead of using magic numbers, prefer an alternative such as returning a bool or using nullables. This basically forces the user to deal with the "invalid" case (instead of accidentally passing -1 into an array). e.g.

(int? outputIdx, int? inputIdx) ToRealIndices(int virtualIdx)

Also, it might be more readable if this was split into 2 methods, since the 2 indices are calculated independently as far as I can tell.

{
if (DisguiseRenderStreamSettings.GetOrCreateSettings().exposePresenter)
{
GameObject.Instantiate(DisguisePresenter.LoadPrefab());
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious: Why do we need a prefab? Why not create the components and set their fields via scripting? I can't really review a .prefab.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes the prefab is equivalent to

var root = new GameObject("Disguise Presenter");
var disguisePresenter = root.AddComponent<DisguisePresenter>();

var outputPresenterGO = new GameObject("Output Presenter");
outputPresenterGO.transform.parent = root.transform;
var outputPresenter = outputPresenterGO.AddComponent<CameraCapturePresenter>();

var inputPresenterGO = new GameObject("Input Presenter");
inputPresenterGO.transform.parent = root.transform;
var inputPresenter = inputPresenterGO.AddComponent<Presenter>();

disguisePresenter.OutputPresenter = outputPresenter;
disguisePresenter.InputPresenter = inputPresenter;

But I can't add the remote parameters through code. They look like this in the prefab:
image

get
{
if (LatestFrameData.scene > m_SceneFields.Length)
return null;
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's less burdensome on the client if you return Enumerable.Empty<RenderTexture>() here instead of null, which will require special handling.

Comment thread DisguiseUnityRenderStream/Runtime/PipelineAbstraction/Presenter.cs
@mark-beiline mark-beiline merged commit 59fd78a into dev Mar 31, 2023
@mark-beiline mark-beiline deleted the mark/present-to-screen-v3 branch March 31, 2023 16:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants