onejs-react 0.1.11 → 0.1.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -258,6 +258,27 @@ type MeshGenerationContext = CS.UnityEngine.UIElements.MeshGenerationContext
258
258
  type GenerateVisualContentCallback = (context: MeshGenerationContext) => void
259
259
  ```
260
260
 
261
+ ## C# Interop Utilities
262
+
263
+ ### `toArray<T>(collection): T[]`
264
+
265
+ Converts C# collections (`List<T>`, arrays) to JavaScript arrays. C# collections exposed through the OneJS proxy have `.Count`/`.Length` and indexers but lack `.map()`, `.filter()`, and other array methods.
266
+
267
+ ```tsx
268
+ import { toArray } from "onejs-react"
269
+
270
+ // Convert a C# List for use in JSX
271
+ {toArray<Item>(inventory.Items).map(item => <ItemView key={item.Id} item={item} />)}
272
+
273
+ // Convert a C# array
274
+ const resolutions = toArray<Resolution>(Screen.resolutions)
275
+
276
+ // Safe with null — returns []
277
+ const npcs = toArray(currentPlace?.NPCs)
278
+ ```
279
+
280
+ Supports objects with `.Count` (List, IList) or `.Length` (C# arrays). Returns `[]` for null/undefined.
281
+
261
282
  ## Dependencies
262
283
 
263
284
  - `react-reconciler@0.31.x` (React 19 compatible)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "onejs-react",
3
- "version": "0.1.11",
3
+ "version": "0.1.14",
4
4
  "description": "React 19 renderer for OneJS (Unity UI Toolkit)",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -327,6 +327,7 @@ export function createMockCS() {
327
327
  GPU: {
328
328
  GPUBridge: {
329
329
  SetElementBackgroundImage: () => {},
330
+ SetElementBackgroundFromObject: () => {},
330
331
  ClearElementBackgroundImage: () => {},
331
332
  },
332
333
  },
@@ -27,8 +27,8 @@ declare function useExtensions(typeRef: any): void
27
27
  // Register ImageConversion extension methods so tex.LoadImage(bytes) works
28
28
  useExtensions(CS.UnityEngine.ImageConversion)
29
29
 
30
- // Module-level texture cache shared across all Image instances
31
- const _textureCache = new Map<string, any>()
30
+ // Module-level image cache shared across all Image instances
31
+ const _imageCache = new Map<string, any>()
32
32
 
33
33
  function _resolveAssetPath(src: string): string {
34
34
  const Path = CS.System.IO.Path
@@ -41,8 +41,8 @@ function _resolveAssetPath(src: string): string {
41
41
  return Path.Combine(CS.UnityEngine.Application.streamingAssetsPath, "onejs", "assets", src)
42
42
  }
43
43
 
44
- function _loadTexture(src: string): any | null {
45
- const cached = _textureCache.get(src)
44
+ function _loadImageAsset(src: string): any | null {
45
+ const cached = _imageCache.get(src)
46
46
  if (cached) return cached
47
47
 
48
48
  const fullPath = _resolveAssetPath(src)
@@ -51,20 +51,28 @@ function _loadTexture(src: string): any | null {
51
51
  return null
52
52
  }
53
53
 
54
- const bytes = CS.System.IO.File.ReadAllBytes(fullPath)
55
- const tex = new CS.UnityEngine.Texture2D(2, 2)
56
- tex.LoadImage(bytes)
57
- tex.filterMode = CS.UnityEngine.FilterMode.Bilinear
58
- _textureCache.set(src, tex)
59
- return tex
54
+ let result: any
55
+ if (src.toLowerCase().endsWith(".svg")) {
56
+ const svgText = CS.System.IO.File.ReadAllText(fullPath)
57
+ result = CS.OneJS.SVGUtils.LoadFromString(svgText)
58
+ } else {
59
+ const bytes = CS.System.IO.File.ReadAllBytes(fullPath)
60
+ const tex = new CS.UnityEngine.Texture2D(2, 2)
61
+ tex.LoadImage(bytes)
62
+ tex.filterMode = CS.UnityEngine.FilterMode.Bilinear
63
+ result = tex
64
+ }
65
+
66
+ _imageCache.set(src, result)
67
+ return result
60
68
  }
61
69
 
62
70
  /**
63
- * Clear the Image component's texture cache.
71
+ * Clear the Image component's image cache.
64
72
  * Call this if you need to force-reload images (e.g., after replacing files on disk).
65
73
  */
66
74
  export function clearImageCache(): void {
67
- _textureCache.clear()
75
+ _imageCache.clear()
68
76
  }
69
77
 
70
78
  // Props with ref support for intrinsic elements
@@ -152,11 +160,11 @@ export const ScrollView = forwardRef<ScrollViewElement, ScrollViewProps>((props,
152
160
  ScrollView.displayName = 'ScrollView';
153
161
 
154
162
  export const Image = forwardRef<ImageElement, ImageProps>(({ src, image, ...rest }, ref) => {
155
- const resolvedImage = useMemo(() => {
156
- if (src) return _loadTexture(src)
163
+ const resolved = useMemo(() => {
164
+ if (src) return _loadImageAsset(src)
157
165
  return image
158
166
  }, [src, image])
159
- return <ojs-image ref={ref} image={resolvedImage} {...rest} />;
167
+ return <ojs-image ref={ref} image={resolved} {...rest} />;
160
168
  });
161
169
  Image.displayName = 'Image';
162
170
 
@@ -65,6 +65,7 @@ declare const CS: {
65
65
  GPU: {
66
66
  GPUBridge: {
67
67
  SetElementBackgroundImage: (element: CSObject, rtHandle: number) => void;
68
+ SetElementBackgroundFromObject: (element: CSObject, obj: CSObject) => void;
68
69
  ClearElementBackgroundImage: (element: CSObject) => void;
69
70
  };
70
71
  };
@@ -350,12 +351,18 @@ function applyStyle(element: CSObject, style: ViewStyle | undefined): Set<string
350
351
  s[prop] = parsed;
351
352
  appliedKeys.add(prop);
352
353
  }
353
- } else if (key === "backgroundImage" && isRenderTextureHandle(value)) {
354
- // Special handling for RenderTexture background images
355
- // Supports both direct RenderTexture objects and marker objects
356
- const handle = getRenderTextureHandle(value);
357
- if (handle >= 0) {
358
- CS.OneJS.GPU.GPUBridge.SetElementBackgroundImage(element, handle);
354
+ } else if (key === "backgroundImage") {
355
+ if (value == null) {
356
+ CS.OneJS.GPU.GPUBridge.ClearElementBackgroundImage(element);
357
+ } else if (isRenderTextureHandle(value)) {
358
+ // GPU compute RenderTexture handles (via rt.getUnityObject())
359
+ const handle = getRenderTextureHandle(value);
360
+ if (handle >= 0) {
361
+ CS.OneJS.GPU.GPUBridge.SetElementBackgroundImage(element, handle);
362
+ }
363
+ } else if (typeof value === "object" && "__csHandle" in value) {
364
+ // C# objects: Texture2D, Sprite, VectorImage, RenderTexture
365
+ CS.OneJS.GPU.GPUBridge.SetElementBackgroundFromObject(element, value);
359
366
  }
360
367
  appliedKeys.add(key);
361
368
  } else {
@@ -642,7 +649,16 @@ function applyToggleProps(element: CSObject, props: Record<string, unknown>) {
642
649
  // Apply Image-specific properties
643
650
  function applyImageProps(element: CSObject, props: Record<string, unknown>) {
644
651
  const el = element as any;
645
- if (props.image !== undefined) el.image = props.image;
652
+ if (props.image !== undefined) {
653
+ const img = props.image;
654
+ if (img != null && (img as any).GetType?.().Name === "VectorImage") {
655
+ el.image = null;
656
+ el.vectorImage = img;
657
+ } else {
658
+ el.vectorImage = null;
659
+ el.image = img;
660
+ }
661
+ }
646
662
  if (props.sprite !== undefined) el.sprite = props.sprite;
647
663
  if (props.vectorImage !== undefined) el.vectorImage = props.vectorImage;
648
664
  if (props.scaleMode !== undefined) {
package/src/types.ts CHANGED
@@ -82,10 +82,19 @@ export interface ViewStyle {
82
82
  /** Background color. Examples: "#3498db", "rgba(0,0,0,0.5)", "red" */
83
83
  backgroundColor?: StyleColor;
84
84
  /**
85
- * Background image - accepts a Texture2D, RenderTexture, or RenderTexture object from GPU compute.
85
+ * Background image - accepts Texture2D, Sprite, VectorImage, RenderTexture,
86
+ * or a GPU compute RenderTexture handle.
86
87
  *
87
- * For GPU compute RenderTextures, you can pass the RenderTexture object directly:
88
88
  * @example
89
+ * // Texture2D
90
+ * const tex = loadImage("images/card-bg.png")
91
+ * <View style={{ backgroundImage: tex }} />
92
+ *
93
+ * // Sprite from C#
94
+ * const sprite = getSpriteFromCSharp()
95
+ * <View style={{ backgroundImage: sprite }} />
96
+ *
97
+ * // GPU compute RenderTexture
89
98
  * const rt = compute.renderTexture({ width: 100, height: 100 })
90
99
  * <View style={{ backgroundImage: rt }} />
91
100
  */
@@ -528,14 +537,12 @@ export interface ScrollViewProps extends BaseProps {
528
537
  }
529
538
 
530
539
  export interface ImageProps extends BaseProps {
531
- /** Path to image asset relative to the assets/ folder (convenience prop) */
540
+ /** Path to image asset relative to the assets/ folder. Supports PNG, JPG, and SVG files. */
532
541
  src?: string;
533
- /** Pre-loaded Texture2D object (use when you loaded the texture yourself) */
542
+ /** Pre-loaded Texture2D or VectorImage object. Type is auto-detected at runtime. */
534
543
  image?: object;
535
544
  /** Sprite to display (alternative to image) */
536
545
  sprite?: object;
537
- /** Vector image to display */
538
- vectorImage?: object;
539
546
  /** How the image scales to fit the element */
540
547
  scaleMode?: 'StretchToFill' | 'ScaleAndCrop' | 'ScaleToFit';
541
548
  /** Tint color applied to the image */