Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 56 additions & 5 deletions SeeSharp.Blazor/FlipViewer.razor
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,28 @@
(
int X,
int Y,
bool CtrlKey

string key,
bool isPressed,

int mouseButton,
bool isButton,

int deltaY,
int selectedIndex,
string registryKey
)
{
}

[Parameter]
public EventCallback<OnClickEventArgs> OnClick { get; set; }
[Parameter]
public EventCallback<OnClickEventArgs> OnWheel { get; set; }
[Parameter]
public EventCallback<OnClickEventArgs> OnMouseOver { get; set; }
[Parameter]
public EventCallback<OnClickEventArgs> OnKey { get; set; }

protected override async Task OnParametersSetAsync()
{
Expand Down Expand Up @@ -54,21 +69,57 @@

public struct _OnFlipClickArgs
{
[JsonInclude] public bool ctrlKey;
[JsonInclude] public string key;
[JsonInclude] public bool isPressed;
[JsonInclude] public int mouseButtom;
[JsonInclude] public bool isButtom;
[JsonInclude] public int deltaY;
[JsonInclude] public int selectedIndex;
[JsonInclude] public string registryKey;
}

[JSInvokable]
public void _OnFlipClick(int buttom)
{
OnClick.InvokeAsync(new(X: -1, Y: -1, key: "", isPressed: false, mouseButton: buttom, isButton: false, deltaY: 0, selectedIndex: -1, registryKey: "")).Wait();
}

// IMPORTANT: There is a bool for altKey, but on the React side a wheel event only is fired when alt is pressed, so altKey is more or less redundant
[JSInvokable]
public void _OnFlipWheel(int deltaY)
Copy link
Owner

Choose a reason for hiding this comment

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

Not sure if fwd-ing the wheel is a good idea from a usability perspective. What's the usage scenario?

{
OnWheel.InvokeAsync(new(X: -1, Y: -1, key: "", isPressed: false, mouseButton: -1, isButton: false, deltaY: deltaY, selectedIndex: -1, registryKey: "")).Wait();
}

[JSInvokable]
public void _OnFlipMouseOver(int x, int y)
{
OnMouseOver.InvokeAsync(new(X: x, Y: y, key: "", isPressed: false, mouseButton: -1, isButton: false, deltaY: 0, selectedIndex: -1, registryKey: "")).Wait();
}

[JSInvokable]
public void _OnFlipClick(int x, int y, _OnFlipClickArgs eventArgs)
public void _OnFlipKey(int selectedIdx, string keyStr, string keyPressed, bool isPressed)
{
OnClick.InvokeAsync(new(x, y, eventArgs.ctrlKey)).Wait();
OnKey.InvokeAsync(new(X: -1, Y: -1, key: keyPressed, isPressed: isPressed, mouseButton: -1, isButton: false, deltaY: 0, selectedIndex: selectedIdx, registryKey: keyStr)).Wait();
}

protected override async Task OnAfterRenderAsync(bool firstRender)
{
// Need to wait with invoking the JS code until the HTML got added to the DOM on the client side
if (flipJson != null)
{
await JSRuntime.InvokeVoidAsync("makeFlipBook", flipJson, DotNetObjectReference.Create(this), nameof(_OnFlipClick));
await JSRuntime.InvokeVoidAsync(
"makeFlipBook",
flipJson,
DotNetObjectReference.Create(this),
nameof(_OnFlipClick),
DotNetObjectReference.Create(this),
nameof(_OnFlipWheel),
DotNetObjectReference.Create(this),
nameof(_OnFlipMouseOver),
DotNetObjectReference.Create(this),
nameof(_OnFlipKey)
);
flipJson = null;
}
}
Expand Down
46 changes: 37 additions & 9 deletions SeeSharp.Blazor/Scripts.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
using Microsoft.AspNetCore.StaticAssets;
using Microsoft.JSInterop;
using System.Net.Http.Headers;
using System.Reflection;

namespace SeeSharp.Blazor;

public static class Scripts
{
static string ReadResourceText(string filename)
{
public static class Scripts {
static string ReadResourceText(string filename) {
var assembly = typeof(Scripts).GetTypeInfo().Assembly;
var stream = assembly.GetManifestResourceStream("SeeSharp.Blazor." + filename)
?? throw new FileNotFoundException("resource file not found", filename);
Expand All @@ -20,14 +20,32 @@ static string ReadResourceText(string filename)
$$"""
<script>
{{SimpleImageIO.FlipBook.HeaderScript}}
function makeFlipBook(jsonArgs, onClickObj, onClickMethodName) {
function makeFlipBook(jsonArgs, onClickObj, onClickMethodName, onWheelObj, onWheelMethodName, onMouseOverObj, onMouseOverMethodName, onKeyObj, onKeyMethodName) {
let onClick = null;
if (onClickObj && onClickMethodName) {
onClick = (col, row, evt) =>
onClickObj.invokeMethodAsync(onClickMethodName, col, row, { ctrlKey: evt.ctrlKey })
onClick = (buttom) =>
onClickObj.invokeMethodAsync(onClickMethodName, buttom)
}

window['flipbook']['MakeFlipBook'](jsonArgs, onClick);
let onWheel = null
if (onWheelObj && onWheelMethodName) {
onWheel = (deltaY) =>
onWheelObj.invokeMethodAsync(onWheelMethodName, deltaY)
}

let onMouseOver = null
if (onMouseOverObj && onMouseOverMethodName) {
onMouseOver = (col, row) =>
onMouseOverObj.invokeMethodAsync(onMouseOverMethodName, col, row)
}

let onKey = null
if (onKeyObj && onKeyMethodName) {
onKey = (selectedIdx, keyStr, keyPressed, isPressed) =>
onKeyObj.invokeMethodAsync(onKeyMethodName, selectedIdx, keyStr, keyPressed, isPressed)
}

window['flipbook']['MakeFlipBook'](jsonArgs, onClick, onWheel, onMouseOver, onKey);
}
</script>
""";
Expand Down Expand Up @@ -59,7 +77,17 @@ function makeFlipBook(jsonArgs, onClickObj, onClickMethodName) {
</script>
""";

public static readonly string AllScripts = FlipBookScript + DownloadScript + WidgetScripts;
public static readonly string UpdateImageScript =
$$"""
<script>
function updateImage(jsonArgs) {
window['flipbook']['UpdateImage'](jsonArgs);
return;
}
</script>
""";

public static readonly string AllScripts = FlipBookScript + DownloadScript + WidgetScripts + UpdateImageScript;

/// <summary>
/// Downloads a stream to the client with the given file name. Requires that <see cref="DownloadScript" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using SeeSharp.Blazor;

namespace SeeSharp.Blazor.Template.Pages;

public struct ListenerState {
public ListenerState() { }

/// <summary>
/// The index of the selected image of the current selected flipbook (selected by clicking on it)
/// </summary>
public int selectedIndex = 0;

/// <summary>
/// Number between 0 and NumSamples. Can be used if data is stored from different iterations
/// </summary>
public int currIteration = 0;

// Add here all action keys for your functionalities
// Attention: any key press disables the default html scrolling!
public string actionKey1 = "a";
public string actionKey2 = "d";
public bool actionKey1Pressed = false;
public bool actionKey2Pressed = false;

public int currX = 0;
public int currY = 0;

/// <summary>
/// The key of the current flipbook
/// </summary>
public string currFlipKey = "";
}

/// <summary>
/// Differences between event type so update methods for flipbooks can ignore events
/// </summary>
public enum FiredType {
Click = 0,
Move = 1,
Wheel = 2,
KeyDown = 4,
KeyUp = 8,
}

public partial class BaseExperiment : ComponentBase {
protected const int Width = 1280;
protected const int Height = 720;
protected const int FlipWidth = 660;
protected const int FlipHeight = 580;
protected const int MaxDepth = 10;
public int NumSamples = 2;

/// <summary>
/// Registers all Flipbooks
/// Key will be the stringified key of a Flipbook which is set by Flipbook.SetKey
/// A Flipbook key is an array of ints
/// </summary>
protected Dictionary<string, FlipBook> registry = new Dictionary<string, FlipBook>();
protected ListenerState state = new ListenerState();
public static string Reverse(string s) {
char[] charArray = s.ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}

// SurfacePoint? selected;
// void OnFlipClick(FlipViewer.OnClickEventArgs args) {
// if (args.CtrlKey) {
// selected = scene.RayCast(new(args.X, args.Y));
// }
// }

/// <summary>
/// Is fired when clicked on an image in the flipbook
/// </summary>
/// <param name="args">ListenerState from HMTL side</param>
public virtual void OnFlipClick(FlipViewer.OnClickEventArgs args) {
updateFlipbook(FiredType.Click);
}

/// <summary>
/// Is fired when the mouse wheel state changes over an image.
/// This gets only called when the alt key is pressed (from HTML side)
/// </summary>
/// <param name="args">ListenerState from HMTL side.</param>
public virtual void OnFlipWheel(FlipViewer.OnClickEventArgs args) {
if (state.actionKey1Pressed) {
// scrolled up
if (args.deltaY < 0) {
if (state.currIteration < NumSamples - 1) {
state.currIteration++;
updateFlipbook(FiredType.Wheel);
}
}
// scrolled down
if (args.deltaY >= 0) {
if (state.currIteration > 0) {
state.currIteration--;
updateFlipbook(FiredType.Wheel);
}
}
}
}

/// <summary>
/// Is fired when mouse position changes over the selected flipbook
/// </summary>
/// <param name="args">ListenerState from HMTL side.</param>
public virtual void OnFlipMouseOver(FlipViewer.OnClickEventArgs args) {
if (state.currX == args.X && state.currY == args.Y)
return;

if (args.X >= 0 && args.X <= Width - 1)
state.currX = args.X;
if (args.Y >= 0 && args.Y <= Height - 1)
state.currY = args.Y;

updateFlipbook(FiredType.Move);
}

/// <summary>
/// Is fired when key is pressed or released
/// </summary>
/// <param name="args">ListenerState from HMTL side.</param>
public virtual void OnFlipKey(FlipViewer.OnClickEventArgs args) {
if (args.key == state.actionKey1)
state.actionKey1Pressed = args.isPressed;

if (args.key == state.actionKey2)
state.actionKey2Pressed = args.isPressed;

state.currFlipKey = args.registryKey;
state.selectedIndex = args.selectedIndex;

if (args.key == state.actionKey1 && !args.isPressed)
state.currIteration = 0;

if (args.isPressed)
updateFlipbook(FiredType.KeyDown);
else
updateFlipbook(FiredType.KeyUp);
}

/// <summary>
/// Catches fired events and forward events to selected flipbooks
/// </summary>
/// <param name="fired">Fired type</param>
public virtual void updateFlipbook(FiredType fired) {
if (String.IsNullOrEmpty(state.currFlipKey))
return;
}

/// <summary>
/// Runs the experiment when "..." is pressed on the HTML
/// </summary>
public virtual void RunExperiment() {
}

/// <summary>
/// Is executed when Download button is pressed on the HTML
/// </summary>
/// <returns></returns>
public virtual async Task OnDownloadClick() {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

@inject IJSRuntime JS

@inherits SeeSharp.Blazor.Template.Pages.BaseExperiment

@page "/Experiment"

<h1>Example experiment</h1>
Expand Down Expand Up @@ -33,16 +35,16 @@
<div class="experiment-results">
<FlipViewer Flip="@flip" OnClick="@OnFlipClick"></FlipViewer>

@if (selected.HasValue && selected.Value)
@* @if (selected.HasValue && selected.Value)
{
<table>
<tr><th>Mesh</th><td>@(selected.Value.Mesh.Name)</td></tr>
<tr><th>Material</th><td>@(selected.Value.Mesh.Material.Name) (roughness: @(selected.Value.Mesh.Material.GetRoughness(selected.Value)), transmissive: @(selected.Value.Mesh.Material.IsTransmissive(selected.Value)))</td></tr>
<tr><th>Distance</th><td>@(selected.Value.Distance)</td></tr>
<tr><th>Position</th><td>@(selected.Value.Position)</td></tr>
</table>
}
<button @onclick="OnDownloadClick">Download results</button>
} *@
@* <button @onclick="OnDownloadClick">Download results</button> *@
</div>
}
}
Expand All @@ -63,12 +65,12 @@
bool resultsAvailable = false;
ElementReference runButton;

SimpleImageIO.FlipBook flip;

async Task OnSceneLoaded(SceneFromFile sceneFromFile)
{
await Task.Run(() => scene = sceneFromFile.MakeScene());

flip = null;

resultsAvailable = false;
readyToRun = true;
sceneJustLoaded = true;
Expand Down
Loading