-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Proper view model with versioning of changes on C# side - jQuery based test Web app works reliably to show blocks and their properties - Modification of block properties work (test Web app is unusable with frequently updated blocks, like active rotors) - Missing: interacted block ID, grids, named groups - Slows down as the browser is open, collects some threads/garbage, needs to be profiled
- Loading branch information
1 parent
3773f66
commit ed72884
Showing
23 changed files
with
953 additions
and
446 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,164 +1,209 @@ | ||
var blockStates = null; | ||
let displayedVersion = 0; | ||
let rendering = false; | ||
|
||
// Invoked from C# | ||
// Invoked from C# whenever a new game state version is available | ||
// noinspection JSUnusedGlobalSymbols | ||
async function stateUpdated() { | ||
const blockViews = $('#blocks'); | ||
blockViews.empty(); | ||
|
||
blockStates = await state.GetBlockStates(); | ||
for (const entityId in blockStates) { | ||
renderBlock(blockViews, blockStates[entityId]); | ||
async function OnGameStateChange(version) { | ||
// Is the model accessible? | ||
if (TerminalViewModel === undefined) | ||
return; | ||
|
||
// Eliminate any any duplicate or redundant calls | ||
if (rendering || version <= displayedVersion) | ||
return; | ||
|
||
rendering = true; | ||
try { | ||
let blockIds = await TerminalViewModel.GetModifiedBlockIds(displayedVersion); | ||
let blocks = $('#blocks'); | ||
for (const i in blockIds) { | ||
let blockId = blockIds[i]; | ||
let blockState = await TerminalViewModel.GetBlockState(blockId); | ||
renderBlock(blocks, blockState); | ||
} | ||
} finally { | ||
displayedVersion = version; | ||
rendering = false; | ||
} | ||
} | ||
|
||
function renderBlock(parent, blockState) { | ||
let blockView = $('<div />'); | ||
blockView.addClass('block'); | ||
blockView.attr('id', 'block-' + blockState.EntityId); | ||
renderBlockInner(blockView, blockState); | ||
parent.append(blockView); | ||
if (blockState == null) | ||
return; | ||
|
||
let blockViewId = 'block-' + blockState.Id; | ||
let oldBlockDiv = $('#' + blockViewId); | ||
|
||
let blockDiv = $('<div />'); | ||
blockDiv.addClass('block'); | ||
blockDiv.attr('id', blockViewId); | ||
renderBlockInner(blockDiv, blockState); | ||
|
||
if (oldBlockDiv.length === 0) | ||
parent.append(blockDiv); | ||
else | ||
oldBlockDiv.replaceWith(blockDiv); | ||
} | ||
|
||
function renderBlockInner(blockView, blockState) { | ||
let id = $('<div />'); | ||
id.addClass('entityId'); | ||
id.text(blockState.EntityId); | ||
blockView.append(id); | ||
|
||
let type = $('<div />'); | ||
type.addClass('type'); | ||
type.text(blockState.ClassName + ' | ' + blockState.TypeId + ' | ' + blockState.SubtypeName); | ||
blockView.append(type); | ||
|
||
let name = $('<div />'); | ||
name.addClass('name'); | ||
name.text(blockState.Name); | ||
blockView.append(name); | ||
|
||
let properties = $('<div />') | ||
properties.addClass('properties'); | ||
for (const propertyId in blockState.PropertyStates) { | ||
renderBlockProperty(properties, blockState.PropertyStates[propertyId]) | ||
let blockId = blockState.Id; | ||
|
||
let idDiv = $('<div />'); | ||
idDiv.addClass('id'); | ||
idDiv.text('Block #' + blockId); | ||
blockView.append(idDiv); | ||
|
||
let typeDiv = $('<div />'); | ||
typeDiv.addClass('type'); | ||
typeDiv.text(blockState.ClassName + ' | ' + blockState.TypeId + ' | ' + blockState.SubtypeName); | ||
blockView.append(typeDiv); | ||
|
||
let nameDiv = $('<div />'); | ||
nameDiv.addClass('name'); | ||
nameDiv.text(blockState.Name); | ||
blockView.append(nameDiv); | ||
|
||
let propertiesDiv = $('<div />') | ||
propertiesDiv.addClass('properties'); | ||
for (const propertyId in blockState.Properties) { | ||
renderBlockProperty(propertiesDiv, blockState.Id, blockState.Properties[propertyId]) | ||
} | ||
blockView.append(properties) | ||
blockView.append(propertiesDiv) | ||
|
||
blockView.append($('<hr />')) | ||
} | ||
|
||
function renderBlockProperty(parent, propertyState) { | ||
let propertyView= $('<div />'); | ||
propertyView.addClass('property'); | ||
function renderBlockProperty(parent, blockId, propertyState) { | ||
let propertyId = propertyState.Id; | ||
let propertyValue = propertyState.Value; | ||
|
||
let cb, label; | ||
let propertyDiv= $('<div />'); | ||
let propertyDivId = 'block-' + blockId + '-property-' + propertyId; | ||
propertyDiv.attr('id', propertyDivId) | ||
propertyDiv.addClass('property'); | ||
|
||
let propertyInputId = 'block-' + blockId + '-property-' + propertyId + '-input' | ||
|
||
let input, label; | ||
let value = $('<div />'); | ||
value.addClass('value'); | ||
switch(propertyState.TypeName) { | ||
case "Boolean": | ||
cb = $('<input />') | ||
cb.attr('id', propertyState.Id); | ||
cb.attr('type', 'checkbox'); | ||
if (propertyState.Value) { | ||
cb.attr('checked', 'checked'); | ||
input = $('<input />') | ||
input.attr('id', propertyInputId); | ||
input.attr('type', 'checkbox'); | ||
if (propertyValue) { | ||
input.attr('checked', 'checked'); | ||
} | ||
value.append(cb); | ||
value.append(input); | ||
|
||
label = $('<label />'); | ||
label.attr('for', propertyState.Id); | ||
label.text(propertyState.Id); | ||
label.attr('for', propertyInputId); | ||
label.text(propertyId); | ||
value.append(label); | ||
|
||
value.bind('change', async function (e) { | ||
await TerminalViewModel.SetBlockProperty(blockId, propertyId, input.is(':checked')); | ||
}); | ||
|
||
break; | ||
|
||
case "Int64": | ||
label = $('<label />'); | ||
label.attr('for', propertyState.Id); | ||
label.text(propertyState.Id); | ||
label.attr('for', propertyInputId); | ||
label.text(propertyId); | ||
value.append(label); | ||
|
||
cb = $('<input />') | ||
cb.attr('id', propertyState.Id); | ||
cb.attr('type', 'number'); | ||
cb.attr('value', propertyState.Value == null ? '0' : propertyState.Value.toString()); | ||
cb.attr('maxlength', '20'); | ||
cb.attr('size', '20'); | ||
value.append(cb); | ||
input = $('<input />') | ||
input.attr('id', propertyInputId); | ||
input.attr('type', 'number'); | ||
input.attr('value', propertyValue == null ? '0' : propertyValue.toString()); | ||
input.attr('maxlength', '20'); | ||
input.attr('size', '20'); | ||
value.append(input); | ||
|
||
value.bind('change', async function (e) { | ||
await TerminalViewModel.SetBlockProperty(blockId, propertyId, parseInt(input.value())); | ||
}); | ||
|
||
break; | ||
|
||
case "Single": | ||
label = $('<label />'); | ||
label.attr('for', propertyState.Id); | ||
label.text(propertyState.Id); | ||
label.attr('for', propertyInputId); | ||
label.text(propertyId); | ||
value.append(label); | ||
|
||
cb = $('<input />') | ||
cb.attr('id', propertyState.Id); | ||
cb.attr('type', 'number'); | ||
cb.attr('value', propertyState.Value == null ? '0.0' : propertyState.Value.toString()); | ||
cb.attr('maxlength', '20'); | ||
cb.attr('size', '20'); | ||
value.append(cb); | ||
input = $('<input />') | ||
input.attr('id', propertyInputId); | ||
input.attr('type', 'number'); | ||
input.attr('value', propertyValue == null ? '0.0' : propertyValue.toString()); | ||
input.attr('maxlength', '20'); | ||
input.attr('size', '20'); | ||
value.append(input); | ||
|
||
value.bind('change', async function (e) { | ||
await TerminalViewModel.SetBlockProperty(blockId, propertyId, parseFloat(input.value())); | ||
}); | ||
|
||
break; | ||
|
||
case "StringBuilder": | ||
label = $('<label />'); | ||
label.attr('for', propertyState.Id); | ||
label.text(propertyState.Id); | ||
label.attr('for', propertyInputId); | ||
label.text(propertyId); | ||
value.append(label); | ||
|
||
cb = $('<input />') | ||
cb.attr('id', propertyState.Id); | ||
cb.attr('value', propertyState.Value == null ? '' : propertyState.Value.toString()); | ||
cb.attr('maxlength', '65535'); | ||
cb.attr('size', '100'); | ||
value.append(cb); | ||
input = $('<input />') | ||
input.attr('id', propertyInputId); | ||
input.attr('value', propertyValue == null ? '' : propertyValue.toString()); | ||
input.attr('maxlength', '65535'); | ||
input.attr('size', '100'); | ||
value.append(input); | ||
|
||
value.bind('change', async function (e) { | ||
await TerminalViewModel.SetBlockProperty(blockId, propertyId, input.value()); | ||
}); | ||
|
||
break; | ||
|
||
case "Color": | ||
// FIXME: Add a color picker on click event! | ||
// See https://bitbucket.org/chromiumembedded/cef/issues/899 | ||
|
||
label = $('<label />'); | ||
label.attr('for', propertyState.Id); | ||
label.text(propertyState.Id); | ||
label.attr('for', propertyInputId); | ||
label.text(propertyId); | ||
value.append(label); | ||
|
||
cb = $('<input />') | ||
cb.attr('id', propertyState.Id); | ||
cb.attr('type', 'color'); | ||
cb.attr('value', propertyState.Value == null ? '#ffffff' : propertyState.Value.toString()); | ||
value.append(cb); | ||
input = $('<input />') | ||
input.attr('id', propertyInputId); | ||
input.attr('type', 'color'); | ||
input.attr('value', propertyValue == null ? '#ffffff' : propertyValue.toString()); | ||
value.append(input); | ||
|
||
value.bind('change', async function (e) { | ||
await TerminalViewModel.SetBlockProperty(blockId, propertyId, input.value()); | ||
}); | ||
|
||
break; | ||
|
||
default: | ||
label = $('<label />'); | ||
label.attr('for', propertyState.Id); | ||
label.text(propertyState.Id + '[' + propertyState.TypeName + '] '); | ||
label.attr('for', propertyInputId); | ||
label.text(propertyId + '[' + propertyState.TypeName + '] '); | ||
value.append(label); | ||
|
||
cb = $('<input />') | ||
cb.attr('readonly', 'readonly'); | ||
cb.attr('id', propertyState.Id); | ||
cb.attr('value', propertyState.Value == null ? '' : propertyState.Value.toString()); | ||
value.append(cb); | ||
input = $('<input />') | ||
input.attr('readonly', 'readonly'); | ||
input.attr('id', propertyInputId); | ||
input.attr('value', propertyValue == null ? '' : propertyValue.toString()); | ||
value.append(input); | ||
|
||
break; | ||
} | ||
|
||
propertyView.append(value); | ||
propertyDiv.append(value); | ||
|
||
parent.append(propertyView); | ||
} | ||
|
||
// Invoked from C# | ||
// noinspection JSUnusedGlobalSymbols | ||
async function blockStateUpdated(entityId) { | ||
// let blockState = await state.GetBlockState(entityId); | ||
// let blockView = $('#block-' + entityId); | ||
// if (blockView.length > 0) { | ||
// renderBlockInner(blockView, blockState); | ||
// } | ||
parent.append(propertyDiv); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,3 @@ | ||
$(document).ready(async function () { | ||
// For debugging only | ||
// $("#window-size").text(`${window.innerWidth}x${window.innerHeight}`); | ||
|
||
await CefSharp.BindObjectAsync("state"); | ||
state.NotifyBound(); | ||
await CefSharp.BindObjectAsync("TerminalViewModel"); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.