diff --git a/src/DemEntities.tsx b/src/DemEntities.tsx
index 3d9dc76..6308690 100644
--- a/src/DemEntities.tsx
+++ b/src/DemEntities.tsx
@@ -1,4 +1,3 @@
-import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
import { useVirtualizer } from "@tanstack/react-virtual";
import { useAtom } from "jotai";
import { CheckIcon, CogIcon, Link2Icon, Link2OffIcon } from "lucide-react";
@@ -9,12 +8,19 @@ import {
demParserAtom,
demSelectedEntityIndexAtom,
demTickAtom,
+ demViewAtom,
} from "./atoms";
import { Button } from "./lib/Button";
import { ScrollArea } from "./lib/ScrollArea";
import { Tooltip } from "./lib/Tooltip";
-import { type EntityLi, handleToIndex, isHandleValid } from "./lib/haste";
+import {
+ type EntityLi,
+ handleToIndex,
+ isHandleValid,
+ EntityFieldLi,
+} from "./lib/haste";
import { cn } from "./lib/style";
+import * as DropdownMenu from "./lib/DropdownMenu";
const LI_HEIGHT = 26;
@@ -24,30 +30,6 @@ const DEFAULT_SHOW_FIELD_ENCODED_TYPE = true;
const DEFAULT_SHOW_FIELD_DECODED_TYPE = false;
const DEFAULT_SHOW_FIELD_PATH = false;
-type DropdownMenuCheckboxItemProps = Pick<
- DropdownMenuPrimitive.DropdownMenuCheckboxItemProps,
- "checked" | "onCheckedChange"
-> & {
- label: React.ReactNode;
-};
-
-function DropdownMenuCheckboxItem(props: DropdownMenuCheckboxItemProps) {
- const { checked, onCheckedChange, label } = props;
-
- return (
-
-
-
-
- {label}
-
- );
-}
-
type EntityListPreferencesProps = {
showEntityIndex: boolean;
setShowEntityIndex: (value: boolean) => void;
@@ -55,53 +37,56 @@ type EntityListPreferencesProps = {
// NOTE: keep this in sync with EntityFieldListPreferences
function EntityListPreferences(props: EntityListPreferencesProps) {
- const {
- showEntityIndex,
- setShowEntityIndex,
- } = props;
+ const { showEntityIndex, setShowEntityIndex } = props;
const [open, setOpen] = useState(false);
- const active = open;
-
return (
-
-
+
+
-
-
-
-
+
+
-
-
-
-
+ >
+ entity index
+
+
+
+
);
}
function EntityList() {
const [demParser] = useAtom(demParserAtom);
+ const [demView] = useAtom(demViewAtom);
const [demTick] = useAtom(demTickAtom);
const entityList = useMemo(() => {
demTick; // trick eslint
- return demParser?.listEntities();
- }, [demParser, demTick]);
+
+ let entityList: EntityLi[] | undefined;
+ if (demView === "entities") {
+ entityList = demParser?.listEntities();
+ } else if (demView === "baselineEntities") {
+ entityList = demParser?.listBaselineEntities();
+ }
+
+ return entityList;
+ }, [demParser, demView, demTick]);
const [, startTransition] = useTransition();
const [filteredEntityList, setFinalEntityList] = useState(entityList);
@@ -142,7 +127,9 @@ function EntityList() {
[setDemSelectedEntityIndex],
);
- const [showEntityIndex, setShowEntityIndex] = useState(DEFAULT_SHOW_ENTITY_INDEX);
+ const [showEntityIndex, setShowEntityIndex] = useState(
+ DEFAULT_SHOW_ENTITY_INDEX,
+ );
return (
@@ -231,8 +218,8 @@ function EntityFieldListPreferences(props: EntityFieldListPreferencesProps) {
const active = open;
return (
-
-
+
+
@@ -242,39 +229,43 @@ function EntityFieldListPreferences(props: EntityFieldListPreferencesProps) {
-
-
-
+
+
-
-
+ field path
+
+
-
+ encoded type
+
+
-
-
-
+ >
+ decoded type
+
+
+
+
);
}
function EntityFieldList() {
const [demParser] = useAtom(demParserAtom);
- const [demTick] = useAtom(demTickAtom);
+ const [demView] = useAtom(demViewAtom);
const [demSelectedEntityIndex] = useAtom(demSelectedEntityIndexAtom);
+ const [demTick] = useAtom(demTickAtom);
const { entityFieldList, joinedPathMaxLen } = useMemo(() => {
demTick; // trick eslint
@@ -283,21 +274,28 @@ function EntityFieldList() {
return {};
}
+ let tmpEntityFieldList: EntityFieldLi[] | undefined;
+ if (demView === "entities") {
+ tmpEntityFieldList = demParser?.listEntityFields(demSelectedEntityIndex);
+ } else if (demView === "baselineEntities") {
+ tmpEntityFieldList = demParser?.listBaselineEntityFields(
+ demSelectedEntityIndex,
+ );
+ }
+
let joinedPathMaxLen = 0;
- const entityFieldList = demParser
- ?.listEntityFields(demSelectedEntityIndex)
- ?.map((entityField) => {
- const joinedPath = Array.from(entityField.path)
- .map((part) => part.toString().padStart(4, " "))
- .join("");
- joinedPathMaxLen = Math.max(joinedPathMaxLen, joinedPath.length);
- return {
- inner: entityField,
- joinedPath,
- joinedNamedPath: entityField.namedPath.join("."),
- };
- });
+ const entityFieldList = tmpEntityFieldList?.map((entityField) => {
+ const joinedPath = Array.from(entityField.path)
+ .map((part) => part.toString().padStart(4, " "))
+ .join("");
+ joinedPathMaxLen = Math.max(joinedPathMaxLen, joinedPath.length);
+ return {
+ inner: entityField,
+ joinedPath,
+ joinedNamedPath: entityField.namedPath.join("."),
+ };
+ });
entityFieldList?.sort((a, b) => {
// compare path arrays element by element
@@ -316,7 +314,7 @@ function EntityFieldList() {
});
return { entityFieldList, joinedPathMaxLen };
- }, [demSelectedEntityIndex, demParser, demTick]);
+ }, [demParser, demView, demSelectedEntityIndex, demTick]);
type WrappedEntityFieldLi = NonNullable
[0];
diff --git a/src/atoms.ts b/src/atoms.ts
index 52c6af1..9dd51a0 100644
--- a/src/atoms.ts
+++ b/src/atoms.ts
@@ -26,3 +26,4 @@ export const demFileAtom = atom(undefined);
export const demParserAtom = atom(undefined);
export const demTickAtom = atom(0);
export const demSelectedEntityIndexAtom = atom(undefined);
+export const demViewAtom = atom<"entities" | "baselineEntities">("entities");
diff --git a/src/lib/DropdownMenu.tsx b/src/lib/DropdownMenu.tsx
new file mode 100644
index 0000000..c25fca1
--- /dev/null
+++ b/src/lib/DropdownMenu.tsx
@@ -0,0 +1,30 @@
+import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
+import React from "react";
+import { cn } from "./style";
+import { CheckIcon } from "lucide-react";
+
+export * from "@radix-ui/react-dropdown-menu";
+
+export const CheckboxItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>((props, ref) => {
+ const { className, checked, children, ...restProps } = props;
+
+ return (
+
+
+
+
+ {children}
+
+ );
+});
diff --git a/src/lib/haste/haste.d.ts b/src/lib/haste/haste.d.ts
index 8553391..b99efe8 100644
--- a/src/lib/haste/haste.d.ts
+++ b/src/lib/haste/haste.d.ts
@@ -66,10 +66,19 @@ export class WrappedParser {
*/
listEntities(): (EntityLi)[] | undefined;
/**
+* @returns {(EntityLi)[] | undefined}
+*/
+ listBaselineEntities(): (EntityLi)[] | undefined;
+/**
* @param {number} entity_index
* @returns {(EntityFieldLi)[] | undefined}
*/
listEntityFields(entity_index: number): (EntityFieldLi)[] | undefined;
+/**
+* @param {number} entity_index
+* @returns {(EntityFieldLi)[] | undefined}
+*/
+ listBaselineEntityFields(entity_index: number): (EntityFieldLi)[] | undefined;
}
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
@@ -97,7 +106,9 @@ export interface InitOutput {
readonly wrappedparser_totalTicks: (a: number, b: number) => void;
readonly wrappedparser_runToTick: (a: number, b: number, c: number) => void;
readonly wrappedparser_listEntities: (a: number, b: number) => void;
+ readonly wrappedparser_listBaselineEntities: (a: number, b: number) => void;
readonly wrappedparser_listEntityFields: (a: number, b: number, c: number) => void;
+ readonly wrappedparser_listBaselineEntityFields: (a: number, b: number, c: number) => void;
readonly isHandleValid: (a: number) => number;
readonly handleToIndex: (a: number) => number;
readonly __wbg_set_entityli_name: (a: number, b: number, c: number) => void;
diff --git a/src/lib/haste/haste.js b/src/lib/haste/haste.js
index 51b97eb..1f1b956 100644
--- a/src/lib/haste/haste.js
+++ b/src/lib/haste/haste.js
@@ -491,6 +491,25 @@ export class WrappedParser {
}
}
/**
+ * @returns {(EntityLi)[] | undefined}
+ */
+ listBaselineEntities() {
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ wasm.wrappedparser_listBaselineEntities(retptr, this.__wbg_ptr);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ let v1;
+ if (r0 !== 0) {
+ v1 = getArrayJsValueFromWasm0(r0, r1).slice();
+ wasm.__wbindgen_free(r0, r1 * 4, 4);
+ }
+ return v1;
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ }
+ }
+ /**
* @param {number} entity_index
* @returns {(EntityFieldLi)[] | undefined}
*/
@@ -510,6 +529,26 @@ export class WrappedParser {
wasm.__wbindgen_add_to_stack_pointer(16);
}
}
+ /**
+ * @param {number} entity_index
+ * @returns {(EntityFieldLi)[] | undefined}
+ */
+ listBaselineEntityFields(entity_index) {
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ wasm.wrappedparser_listBaselineEntityFields(retptr, this.__wbg_ptr, entity_index);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ let v1;
+ if (r0 !== 0) {
+ v1 = getArrayJsValueFromWasm0(r0, r1).slice();
+ wasm.__wbindgen_free(r0, r1 * 4, 4);
+ }
+ return v1;
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ }
+ }
}
async function __wbg_load(module, imports) {
@@ -550,14 +589,14 @@ function __wbg_get_imports() {
const ret = new Error(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
};
- imports.wbg.__wbg_entityli_new = function(arg0) {
- const ret = EntityLi.__wrap(arg0);
- return addHeapObject(ret);
- };
imports.wbg.__wbg_entityfieldli_new = function(arg0) {
const ret = EntityFieldLi.__wrap(arg0);
return addHeapObject(ret);
};
+ imports.wbg.__wbg_entityli_new = function(arg0) {
+ const ret = EntityLi.__wrap(arg0);
+ return addHeapObject(ret);
+ };
imports.wbg.__wbindgen_string_new = function(arg0, arg1) {
const ret = getStringFromWasm0(arg0, arg1);
return addHeapObject(ret);
diff --git a/src/lib/haste/haste.rs b/src/lib/haste/haste.rs
index 2a57875..0eb898f 100644
--- a/src/lib/haste/haste.rs
+++ b/src/lib/haste/haste.rs
@@ -6,7 +6,7 @@
// - https://stackoverflow.com/questions/65332927/is-it-possible-to-wasm-bindgen-public-structs-and-functions-defined-in-anothe
use haste::{
- entities,
+ entities::{self, Entity},
fieldpath::FieldPath,
fieldvalue::FieldValue,
flattenedserializers::FlattenedSerializer,
@@ -66,44 +66,69 @@ impl WrappedParser {
.map_err(|err| JsError::new(&err.to_string()))
}
+ fn collect_entity_list<'a>(
+ entities: impl Iterator- ,
+ ) -> Vec {
+ entities
+ .map(|(index, entity)| EntityLi {
+ index: *index,
+ name: entity.serializer().serializer_name.str.to_string(),
+ })
+ .collect()
+ }
+
#[wasm_bindgen(js_name = "listEntities")]
pub fn list_entities(&self) -> Option> {
- self.parser.entities().map(|entities| {
- entities
- .iter()
- .map(|(index, entity)| EntityLi {
- index: *index,
- name: entity.serializer().serializer_name.str.to_string(),
- })
- .collect()
- })
+ self.parser
+ .entities()
+ .map(|entities| Self::collect_entity_list(entities.iter()))
+ }
+
+ #[wasm_bindgen(js_name = "listBaselineEntities")]
+ pub fn list_baseline_entities(&self) -> Option> {
+ self.parser
+ .entities()
+ .map(|entities| Self::collect_entity_list(entities.iter_baselines()))
+ }
+
+ fn collect_entity_field_list(entity: &Entity) -> Vec {
+ entity
+ .iter()
+ .map(|(key, field_value)| {
+ let fp = entity
+ .get_path(key)
+ // NOTE: this should never throw because if entity
+ // was returned it means that it exists thus path
+ // exists
+ .unwrap_throw();
+ let (named_path, var_type) = get_value_info(entity.serializer(), fp);
+
+ EntityFieldLi {
+ path: fp.iter().cloned().collect(),
+ named_path,
+ value: field_value.to_string(),
+ encoded_as: var_type,
+ decoded_as: get_field_value_discriminant_name(field_value).to_string(),
+ }
+ })
+ .collect()
}
#[wasm_bindgen(js_name = "listEntityFields")]
pub fn list_entity_fields(&self, entity_index: i32) -> Option> {
self.parser.entities().and_then(|entities| {
- entities.get(&entity_index).map(|entity| {
- entity
- .iter()
- .map(|(key, field_value)| {
- let fp = entity
- .get_path(key)
- // NOTE: this should never throw because if entity
- // was returned it means that it exists thus path
- // exists
- .unwrap_throw();
- let (named_path, var_type) = get_value_info(entity.serializer(), fp);
-
- EntityFieldLi {
- path: fp.iter().cloned().collect(),
- named_path,
- value: field_value.to_string(),
- encoded_as: var_type,
- decoded_as: get_field_value_discriminant_name(field_value).to_string(),
- }
- })
- .collect()
- })
+ entities
+ .get(&entity_index)
+ .map(Self::collect_entity_field_list)
+ })
+ }
+
+ #[wasm_bindgen(js_name = "listBaselineEntityFields")]
+ pub fn list_baseline_entity_fields(&self, entity_index: i32) -> Option> {
+ self.parser.entities().and_then(|entities| {
+ entities
+ .get_baseline(&entity_index)
+ .map(Self::collect_entity_field_list)
})
}
}
diff --git a/src/lib/haste/haste_bg.wasm b/src/lib/haste/haste_bg.wasm
index 2ba3c5b..79da4fd 100644
Binary files a/src/lib/haste/haste_bg.wasm and b/src/lib/haste/haste_bg.wasm differ
diff --git a/src/lib/haste/haste_bg.wasm.d.ts b/src/lib/haste/haste_bg.wasm.d.ts
index 642b840..9fd3f90 100644
--- a/src/lib/haste/haste_bg.wasm.d.ts
+++ b/src/lib/haste/haste_bg.wasm.d.ts
@@ -22,7 +22,9 @@ export function wrappedparser_tick(a: number): number;
export function wrappedparser_totalTicks(a: number, b: number): void;
export function wrappedparser_runToTick(a: number, b: number, c: number): void;
export function wrappedparser_listEntities(a: number, b: number): void;
+export function wrappedparser_listBaselineEntities(a: number, b: number): void;
export function wrappedparser_listEntityFields(a: number, b: number, c: number): void;
+export function wrappedparser_listBaselineEntityFields(a: number, b: number, c: number): void;
export function isHandleValid(a: number): number;
export function handleToIndex(a: number): number;
export function __wbg_set_entityli_name(a: number, b: number, c: number): void;
diff --git a/tailwind.config.js b/tailwind.config.js
index 49a09bb..fa889b8 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -9,7 +9,7 @@ export default {
fg: "rgb(var(--fg) / )",
"bg-subtle": "rgb(var(--bg-subtle) / )",
"fg-subtle": "rgb(var(--fg-subtle) / )",
- divider: "#404040", // dark neutral-700
+ divider: "#525252", // dark neutral-600
},
},
},