mirror of
https://github.com/ApfelTeeSaft/LiveSplitOne.git
synced 2026-08-26 19:23:40 +00:00
Add initial Column Support
This commit is contained in:
+3
-4
@@ -10,10 +10,6 @@ spawnSync(
|
||||
},
|
||||
);
|
||||
|
||||
fs
|
||||
.createReadStream("livesplit-core/capi/bindings/wasm/livesplit_core.ts")
|
||||
.pipe(fs.createWriteStream("src/livesplit.ts"));
|
||||
|
||||
spawnSync(
|
||||
"cargo",
|
||||
[
|
||||
@@ -31,3 +27,6 @@ spawnSync(
|
||||
fs
|
||||
.createReadStream("livesplit-core/target/wasm32-unknown-unknown/release/livesplit_core.wasm")
|
||||
.pipe(fs.createWriteStream("src/livesplit_core.wasm"));
|
||||
fs
|
||||
.createReadStream("livesplit-core/capi/bindings/wasm/livesplit_core.ts")
|
||||
.pipe(fs.createWriteStream("src/livesplit.ts"));
|
||||
|
||||
+1
-1
Submodule livesplit-core updated: 0b97edf3a1...789e2d007f
+16
-15
@@ -50,6 +50,7 @@ export default class Split extends React.Component<Props> {
|
||||
style={outerStyle}
|
||||
>
|
||||
<div
|
||||
key="split-icon"
|
||||
className={hasIcon ? "split-icon-container" : "split-icon-container-empty"}
|
||||
style={innerStyle}
|
||||
>
|
||||
@@ -59,26 +60,26 @@ export default class Split extends React.Component<Props> {
|
||||
}
|
||||
</div>
|
||||
<div
|
||||
key="split-name"
|
||||
className="split-name"
|
||||
style={innerStyle}
|
||||
>
|
||||
{this.props.split.name}
|
||||
</div>
|
||||
<div
|
||||
className="split-delta time"
|
||||
style={{
|
||||
...innerStyle,
|
||||
color: colorToCss(this.props.split.visual_color),
|
||||
}}
|
||||
>
|
||||
{this.props.split.delta}
|
||||
</div>
|
||||
<div
|
||||
className="split-time time"
|
||||
style={innerStyle}
|
||||
>
|
||||
{this.props.split.time}
|
||||
</div>
|
||||
{
|
||||
this.props.split.columns.map((column, i) =>
|
||||
<div
|
||||
key={i}
|
||||
className="split-time time"
|
||||
style={{
|
||||
...innerStyle,
|
||||
color: colorToCss(column.visual_color),
|
||||
}}
|
||||
>
|
||||
{column.value}
|
||||
</div>,
|
||||
).reverse()
|
||||
}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ export default class Splits extends React.Component<Props> {
|
||||
return (
|
||||
<div className="splits" style={style}>
|
||||
{
|
||||
this.props.state.splits.map((s: LiveSplit.SplitStateJson, i: number) =>
|
||||
this.props.state.splits.map((s, i) =>
|
||||
<Split
|
||||
evenOdd={evenOdd}
|
||||
split={s}
|
||||
|
||||
+26
-4
@@ -1,6 +1,7 @@
|
||||
import * as React from "react";
|
||||
import * as LiveSplit from "../livesplit";
|
||||
import { gradientToCss } from "../util/ColorUtil";
|
||||
import { gradientToCss, colorToCss } from "../util/ColorUtil";
|
||||
import { map } from "../util/OptionUtil";
|
||||
|
||||
export interface Props { state: LiveSplit.TextComponentStateJson }
|
||||
|
||||
@@ -14,12 +15,33 @@ export default class Text extends React.Component<Props> {
|
||||
|
||||
const rendered = "Center" in text ? (
|
||||
<tr>
|
||||
<td className="text-component-text center-text">{text.Center}</td>
|
||||
<td
|
||||
className="text-component-text center-text"
|
||||
style={{
|
||||
color: map(this.props.state.left_center_color, colorToCss),
|
||||
}}
|
||||
>
|
||||
{text.Center}
|
||||
</td>
|
||||
</tr>
|
||||
) : (
|
||||
<tr>
|
||||
<td className="text-component-text">{text.Split[0]}</td>
|
||||
<td className="text-component-text">{text.Split[1]}</td>
|
||||
<td
|
||||
className="text-component-text"
|
||||
style={{
|
||||
color: map(this.props.state.left_center_color, colorToCss),
|
||||
}}
|
||||
>
|
||||
{text.Split[0]}
|
||||
</td>
|
||||
<td
|
||||
className="text-component-text"
|
||||
style={{
|
||||
color: map(this.props.state.right_color, colorToCss),
|
||||
}}
|
||||
>
|
||||
{text.Split[1]}
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
|
||||
|
||||
+168
-28
@@ -400,6 +400,12 @@ export interface TitleComponentStateJson {
|
||||
export interface SplitsComponentStateJson {
|
||||
/** The background shown behind the splits. */
|
||||
background: ListGradient,
|
||||
/**
|
||||
* The column labels to visualize about the list of splits. If this is
|
||||
* `null`, no labels are supposed to be visualized. The list is specified
|
||||
* from right to left.
|
||||
*/
|
||||
column_labels: string[] | null,
|
||||
/** The list of all the segments to visualize. */
|
||||
splits: SplitStateJson[],
|
||||
/**
|
||||
@@ -456,14 +462,11 @@ export interface SplitsComponentIconChangeJson {
|
||||
export interface SplitStateJson {
|
||||
/** The name of the segment. */
|
||||
name: string,
|
||||
/** The delta to show for this segment. */
|
||||
delta: string,
|
||||
/** The split time to show for this segment. */
|
||||
time: string,
|
||||
/** The semantic coloring information the delta time carries. */
|
||||
semantic_color: SemanticColor,
|
||||
/** The visual color of the delta time. */
|
||||
visual_color: Color,
|
||||
/**
|
||||
* The state of each column from right to left. The amount of columns is
|
||||
* not guaranteed to be the same across different splits.
|
||||
*/
|
||||
columns: SplitColumnState[],
|
||||
/**
|
||||
* Describes if this segment is the segment the active attempt is currently
|
||||
* on.
|
||||
@@ -473,11 +476,21 @@ export interface SplitStateJson {
|
||||
* The index of the segment based on all the segments of the run. This may
|
||||
* differ from the index of this `SplitStateJson` in the
|
||||
* `SplitsComponentStateJson` object, as there can be a scrolling window,
|
||||
* showing only a subset of segments.
|
||||
* showing only a subset of segments. Each index is guaranteed to be unique.
|
||||
*/
|
||||
index: number,
|
||||
}
|
||||
|
||||
/** Describes the state of a single segment's column to visualize. */
|
||||
export interface SplitColumnState {
|
||||
/** The value shown in the column. */
|
||||
value: string,
|
||||
/** The semantic coloring information the value carries. */
|
||||
semantic_color: SemanticColor,
|
||||
/** The visual color of the value. */
|
||||
visual_color: Color,
|
||||
}
|
||||
|
||||
/** The state object describes the information to visualize for this component. */
|
||||
export interface PreviousSegmentComponentStateJson {
|
||||
/** The background shown behind the component. */
|
||||
@@ -632,6 +645,23 @@ export interface GraphComponentStatePointJson {
|
||||
export interface TextComponentStateJson {
|
||||
/** The background shown behind the component. */
|
||||
background: Gradient,
|
||||
/**
|
||||
* Specifies whether to display the left and right text is supposed to be
|
||||
* displayed as two rows.
|
||||
*/
|
||||
display_two_rows: boolean,
|
||||
/**
|
||||
* The color of the left part of the split up text or the whole text if
|
||||
* it's not split up. If `None` is specified, the color is taken from the
|
||||
* layout.
|
||||
*/
|
||||
left_center_color: Color,
|
||||
/**
|
||||
* The color of the right part of the split up text. This can be ignored if
|
||||
* the text is not split up. If `None` is specified, the color is taken
|
||||
* from the layout.
|
||||
*/
|
||||
right_color: Color,
|
||||
/** The text to show for the component. */
|
||||
text: TextComponentStateText,
|
||||
}
|
||||
@@ -859,6 +889,9 @@ export type SettingsDescriptionValueJson =
|
||||
{ Gradient: Gradient } |
|
||||
{ ListGradient: ListGradient } |
|
||||
{ Alignment: Alignment } |
|
||||
{ ColumnStartWith: ColumnStartWith } |
|
||||
{ ColumnUpdateWith: ColumnUpdateWith } |
|
||||
{ ColumnUpdateTrigger: ColumnUpdateTrigger } |
|
||||
{ CustomCombobox: CustomCombobox };
|
||||
|
||||
/**
|
||||
@@ -871,6 +904,22 @@ export interface CustomCombobox {
|
||||
mandatory: boolean,
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the value a segment starts out with before it gets replaced
|
||||
* with the current attempt's information when splitting.
|
||||
*/
|
||||
export type ColumnStartWith = "Empty" | "ComparisonTime" | "ComparisonSegmentTime";
|
||||
|
||||
/**
|
||||
* Once a certain condition is met, which is usually being on the split or
|
||||
* already having completed the split, the time gets updated with the value
|
||||
* specified here.
|
||||
*/
|
||||
export type ColumnUpdateWith = "DontUpdate" | "SplitTime" | "Delta" | "SegmentTime" | "SegmentDelta";
|
||||
|
||||
/** Specifies when a column's value gets updated. */
|
||||
export type ColumnUpdateTrigger = "OnStartingSegment" | "Contextual" | "OnEndingSegment";
|
||||
|
||||
/**
|
||||
* The Accuracy describes how many digits to show for the fractional part of a
|
||||
* time.
|
||||
@@ -5592,6 +5641,45 @@ export class SettingValue extends SettingValueRefMut {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Creates a new setting value from the column start with name provided. If it
|
||||
* doesn't match a known column start with, null is returned.
|
||||
*/
|
||||
static fromColumnStartWith(value: string): SettingValue | null {
|
||||
const value_allocated = allocString(value);
|
||||
const result = new SettingValue(instance().exports.SettingValue_from_column_start_with(value_allocated.ptr));
|
||||
dealloc(value_allocated);
|
||||
if (result.ptr == 0) {
|
||||
return null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Creates a new setting value from the column update with name provided. If it
|
||||
* doesn't match a known column update with, null is returned.
|
||||
*/
|
||||
static fromColumnUpdateWith(value: string): SettingValue | null {
|
||||
const value_allocated = allocString(value);
|
||||
const result = new SettingValue(instance().exports.SettingValue_from_column_update_with(value_allocated.ptr));
|
||||
dealloc(value_allocated);
|
||||
if (result.ptr == 0) {
|
||||
return null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Creates a new setting value from the column update trigger. If it doesn't
|
||||
* match a known column update trigger, null is returned.
|
||||
*/
|
||||
static fromColumnUpdateTrigger(value: string): SettingValue | null {
|
||||
const value_allocated = allocString(value);
|
||||
const result = new SettingValue(instance().exports.SettingValue_from_column_update_trigger(value_allocated.ptr));
|
||||
dealloc(value_allocated);
|
||||
if (result.ptr == 0) {
|
||||
return null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5707,6 +5795,67 @@ export class SharedTimer extends SharedTimerRefMut {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The state object that describes a single segment's information to visualize.
|
||||
*/
|
||||
export class SplitComponentStateRef {
|
||||
ptr: number;
|
||||
/**
|
||||
* The amount of columns to visualize for the segment with the specified index.
|
||||
* The columns are specified from right to left. You may not provide an out of
|
||||
* bounds index. The amount of columns to visualize may differ from segment to
|
||||
* segment.
|
||||
*/
|
||||
columnsLen(index: number): number {
|
||||
if (this.ptr == 0) {
|
||||
throw "this is disposed";
|
||||
}
|
||||
const result = instance().exports.SplitComponentState_columns_len(this.ptr, index);
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* This constructor is an implementation detail. Do not use this.
|
||||
*/
|
||||
constructor(ptr: number) {
|
||||
this.ptr = ptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The state object that describes a single segment's information to visualize.
|
||||
*/
|
||||
export class SplitComponentStateRefMut extends SplitComponentStateRef {
|
||||
}
|
||||
|
||||
/**
|
||||
* The state object that describes a single segment's information to visualize.
|
||||
*/
|
||||
export class SplitComponentState extends SplitComponentStateRefMut {
|
||||
/**
|
||||
* Allows for scoped usage of the object. The object is guaranteed to get
|
||||
* disposed once this function returns. You are free to dispose the object
|
||||
* early yourself anywhere within the scope. The scope's return value gets
|
||||
* carried to the outside of this function.
|
||||
*/
|
||||
with<T>(closure: (obj: SplitComponentState) => T): T {
|
||||
try {
|
||||
return closure(this);
|
||||
} finally {
|
||||
this.dispose();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Disposes the object, allowing it to clean up all of its memory. You need
|
||||
* to call this for every object that you don't use anymore and hasn't
|
||||
* already been disposed.
|
||||
*/
|
||||
dispose() {
|
||||
if (this.ptr != 0) {
|
||||
this.ptr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Splits Component is the main component for visualizing all the split
|
||||
* times. Each segment is shown in a tabular fashion showing the segment icon,
|
||||
@@ -5962,36 +6111,27 @@ export class SplitsComponentStateRef {
|
||||
return decodeString(result);
|
||||
}
|
||||
/**
|
||||
* The delta to show for the segment with the specified index. You may not
|
||||
* provide an out of bounds index.
|
||||
* The column's value to show for the split and column with the specified
|
||||
* index. The columns are specified from right to left. You may not provide an
|
||||
* out of bounds index.
|
||||
*/
|
||||
delta(index: number): string {
|
||||
columnValue(index: number, columnIndex: number): string {
|
||||
if (this.ptr == 0) {
|
||||
throw "this is disposed";
|
||||
}
|
||||
const result = instance().exports.SplitsComponentState_delta(this.ptr, index);
|
||||
const result = instance().exports.SplitsComponentState_column_value(this.ptr, index, columnIndex);
|
||||
return decodeString(result);
|
||||
}
|
||||
/**
|
||||
* The split time to show for the segment with the specified index. You may not
|
||||
* provide an out of bounds index.
|
||||
* The semantic coloring information the column's value carries of the segment
|
||||
* and column with the specified index. The columns are specified from right to
|
||||
* left. You may not provide an out of bounds index.
|
||||
*/
|
||||
time(index: number): string {
|
||||
columnSemanticColor(index: number, columnIndex: number): string {
|
||||
if (this.ptr == 0) {
|
||||
throw "this is disposed";
|
||||
}
|
||||
const result = instance().exports.SplitsComponentState_time(this.ptr, index);
|
||||
return decodeString(result);
|
||||
}
|
||||
/**
|
||||
* The semantic coloring information the delta time carries of the segment with
|
||||
* the specified index. You may not provide an out of bounds index.
|
||||
*/
|
||||
semanticColor(index: number): string {
|
||||
if (this.ptr == 0) {
|
||||
throw "this is disposed";
|
||||
}
|
||||
const result = instance().exports.SplitsComponentState_semantic_color(this.ptr, index);
|
||||
const result = instance().exports.SplitsComponentState_column_semantic_color(this.ptr, index, columnIndex);
|
||||
return decodeString(result);
|
||||
}
|
||||
/**
|
||||
|
||||
@@ -38,6 +38,9 @@ export interface SettingValueFactory<T> {
|
||||
r2: number, g2: number, b2: number, a2: number,
|
||||
): T;
|
||||
fromAlignment(value: string): T | null;
|
||||
fromColumnStartWith(value: string): T | null;
|
||||
fromColumnUpdateWith(value: string): T | null;
|
||||
fromColumnUpdateTrigger(value: string): T | null;
|
||||
}
|
||||
|
||||
export class JsonSettingValueFactory {
|
||||
@@ -98,6 +101,15 @@ export class JsonSettingValueFactory {
|
||||
public fromAlignment(_: string): SettingsDescriptionValueJson | null {
|
||||
throw new Error("Not implemented");
|
||||
}
|
||||
public fromColumnStartWith(_: string): SettingsDescriptionValueJson | null {
|
||||
throw new Error("Not implemented");
|
||||
}
|
||||
public fromColumnUpdateWith(_: string): SettingsDescriptionValueJson | null {
|
||||
throw new Error("Not implemented");
|
||||
}
|
||||
public fromColumnUpdateTrigger(_: string): SettingsDescriptionValueJson | null {
|
||||
throw new Error("Not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
export class SettingsComponent<T> extends React.Component<Props<T>> {
|
||||
@@ -621,6 +633,59 @@ export class SettingsComponent<T> extends React.Component<Props<T>> {
|
||||
<option value="Left">Left</option>
|
||||
<option value="Center">Center</option>
|
||||
</select>;
|
||||
} else if ("ColumnStartWith" in value) {
|
||||
component = <select
|
||||
value={value.ColumnStartWith}
|
||||
onChange={(e) => {
|
||||
this.props.setValue(
|
||||
valueIndex,
|
||||
expect(
|
||||
factory.fromColumnStartWith(e.target.value),
|
||||
"Unexpected Column Start With value",
|
||||
),
|
||||
);
|
||||
}}
|
||||
>
|
||||
<option value="Empty">Empty</option>
|
||||
<option value="ComparisonTime">Comparison Time</option>
|
||||
<option value="ComparisonSegmentTime">Comparison Segment Time</option>
|
||||
</select>;
|
||||
} else if ("ColumnUpdateWith" in value) {
|
||||
component = <select
|
||||
value={value.ColumnUpdateWith}
|
||||
onChange={(e) => {
|
||||
this.props.setValue(
|
||||
valueIndex,
|
||||
expect(
|
||||
factory.fromColumnUpdateWith(e.target.value),
|
||||
"Unexpected Column Update With value",
|
||||
),
|
||||
);
|
||||
}}
|
||||
>
|
||||
<option value="DontUpdate">Dont Update</option>
|
||||
<option value="SplitTime">Split Time</option>
|
||||
<option value="Delta">Delta</option>
|
||||
<option value="SegmentTime">Segment Time</option>
|
||||
<option value="SegmentDelta">Segment Delta</option>
|
||||
</select>;
|
||||
} else if ("ColumnUpdateTrigger" in value) {
|
||||
component = <select
|
||||
value={value.ColumnUpdateTrigger}
|
||||
onChange={(e) => {
|
||||
this.props.setValue(
|
||||
valueIndex,
|
||||
expect(
|
||||
factory.fromColumnUpdateTrigger(e.target.value),
|
||||
"Unexpected Column Update Trigger value",
|
||||
),
|
||||
);
|
||||
}}
|
||||
>
|
||||
<option value="OnStartingSegment">On Starting Segment</option>
|
||||
<option value="Contextual">Contextual</option>
|
||||
<option value="OnEndingSegment">On Ending Segment</option>
|
||||
</select>;
|
||||
} else if ("CustomCombobox" in value) {
|
||||
const isError = value.CustomCombobox.mandatory
|
||||
&& value.CustomCombobox.value.length === 0;
|
||||
|
||||
Reference in New Issue
Block a user