-
-
Notifications
You must be signed in to change notification settings - Fork 4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
1,051 additions
and
0 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 |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# Spatial UI widgets for A-Frame | ||
|
||
Explore spatial design as described in Apple guidelines presented at WWDC 2023. | ||
|
||
For quick prototyping and experimentation of Spatial Applications in your browser: desktop or any headset. | ||
|
||
## | ||
|
||
## TO DO | ||
|
||
- Buttons drop shadows. | ||
- Polish hover effect. | ||
- Reflection / border of windows. | ||
- Implement disolve effect when modal shows / hides. | ||
- Replace MeshPhysicalMaterial with custom glass shader for window. It will allow for finer control of look (reflections, alpha blending to animate opacity...) [Meet SwiftUI for spatial computing | ||
8:19](https://developer.apple.com/videos/play/wwdc2023/10109/) | ||
- Vibrancy | ||
- Lazy follow | ||
- Display icons | ||
- Scale and reposition windows. | ||
- Embed models in the view. [WWDC 2023 Get started with building apps for spatial computing 23:00](https://developer.apple.com/videos/play/wwdc2023/10260/) | ||
- Gestures (Zoom, Rotate): [WWDC 2023 Design For Spatial Design 13:01](https://link-url-here.org) | ||
https://developer.apple.com/videos/play/wwdc2023/10073/) | ||
- Direct input: (Zoom, Rotate): [WWDC 2023 Design For Spatial Design 17:00](https://link-url-here.org) | ||
https://developer.apple.com/videos/play/wwdc2023/10073/) | ||
- Tab Views and ornaments. [Meet SwiftUI for spatial computing | ||
7:50](https://developer.apple.com/videos/play/wwdc2023/10109/) | ||
- Text rendering / rasterization [Explore rendering for spatial computing | ||
14:00](https://developer.apple.com/videos/play/wwdc2023/10095/) | ||
- Passthrough tinting for videos [Enhance your spatial computing app with RealityKit 10:05](https://developer.apple.com/videos/play/wwdc2023/10081/] | ||
|
||
dynamic scale | ||
tab, toolbox, ornaments | ||
|
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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 |
---|---|---|
@@ -0,0 +1,144 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>Spatial UI</title> | ||
<meta name="description" content="Spatial UI • A-Frame"> | ||
<script src="https://cdn.jsdelivr.net/gh/aframevr/aframe@309a1b73786ad79bfe64065f1decac741151524d/dist/aframe-master.min.js"></script> | ||
|
||
<script src="ui-controller.js"></script> | ||
<script src="spatial-utils.js"></script> | ||
<script src="spatial-window.js"></script> | ||
<script src="spatial-modal.js"></script> | ||
<script src="spatial-modal-image.js"></script> | ||
<script src="spatial-button.js"></script> | ||
<script src="spatial-close-button.js"></script> | ||
<script src="spatial-hero-image.js"></script> | ||
<script src="tile.js"></script> | ||
</head> | ||
<body> | ||
<a-scene cursor="rayOrigin: mouse;" raycaster="objects: .tile, .start-button, .close-button" ui-controller> | ||
<a-assets> | ||
<a-mixin | ||
id="tile" tile="width: 0.400; height: 0.285" | ||
animation__scale="property: scale; to: 1.02 1.02 1.02; dur: 100; startEvents: mouseenter" | ||
animation__scale_reverse="property: scale; to: 1 1 1; dur: 100; startEvents: mouseleave"> | ||
</a-mixin> | ||
<a-mixin | ||
id="focus-animation" | ||
animation__scale="property: object3D.position.z; to: -0.05; dur: 100; startEvents: unfocused" | ||
animation__scale_reverse="property: object3D.position.z; to: 0; dur: 100; startEvents: focused"> | ||
</a-mixin> | ||
<img id="leaving-room" src="https://cdn.aframe.io/examples/spatial-input/leaving-room.jpg" crossorigin="anonymous"> | ||
<img id="hero-image" src="https://cdn.aframe.io/examples/spatial-input/hero-image.jpg" crossorigin="anonymous"> | ||
</a-assets> | ||
<a-sky src="#leaving-room" rotation="0 -90 0"></a-sky> | ||
|
||
<a-entity position="0 1.7 -1"> | ||
<a-entity spatial-modal="width: 1.2; height: 0.72" visible="false"> | ||
<a-entity spatial-modal-image="width: 0.6; height: 0.72" position="-0.3 0 0.001"></a-entity> | ||
<a-entity spatial-close-button="" position="0.55 0.31 0.001" class="close-button"></a-entity> | ||
<a-text font="kelsonsans" class="movie-title" value="Hayao Miyazaki" align="left" width="0.75"position="0.03 0.2 0.001"></a-text> | ||
<a-text font="kelsonsans" height="1" class="movie-synopsis" value="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." align="left" width="0.5" position="0.03 0.08 0.001"></a-text> | ||
</a-entity> | ||
|
||
<a-entity mixin="focus-animation" spatial-window="width: 1.775; height: 1"> | ||
<a-entity spatial-hero-image="src: #hero-image; width: 1.775; height: 1" position="0 0 0.001"> | ||
<a-text font="kelsonsans" value="Hayao Miyazaki" align="center" width="3" position="0 0.29 0.001"></a-text> | ||
<a-entity spatial-button position="0 0.06 0.001" class="start-button"></a-entity> | ||
</a-entity> | ||
|
||
<a-entity id="image-grid" visible="false"> | ||
<!-- row --> | ||
<a-entity | ||
mixin="tile" | ||
title="The Secret World of Arrietty (2010)" | ||
synopsis="Arrietty, a tiny teenager, lives with her parents in the recesses of a suburban home, unbeknown to the homeowner and housekeeper. Like others of her kind, Arrietty remains hidden from her human hosts." | ||
tile="src: https://cdn.aframe.io/examples/ui/karigurashi.jpg" | ||
position="-0.6435 0.318 0.01" opacity="0.5"></a-entity> | ||
<a-entity | ||
mixin="tile" | ||
title="Ponyo (2008)" | ||
synopsis="During a forbidden excursion to see the surface world, a goldfish princess encounters a human boy named Sosuke, who gives her the name Ponyo. Ponyo longs to become human, and as her friendship with Sosuke grows, she becomes more humanlike." | ||
tile="src: https://cdn.aframe.io/examples/ui/ponyo.jpg" | ||
position="-0.2150 0.320 0.01"></a-entity> | ||
<a-entity | ||
mixin="tile" | ||
title="The Wind Rises (2013)" | ||
synopsis="A lifelong love of flight inspires Japanese aviation engineer Jiro Horikoshi (Hideaki Anno), whose storied career includes the creation of the A6M World War II fighter plane." | ||
tile="src: https://cdn.aframe.io/examples/ui/wind-raises1.jpg" | ||
position="0.2135 0.320 0.01"></a-entity> | ||
<a-entity | ||
mixin="tile" | ||
title="The Wind Rises (2013)" | ||
synopsis="A lifelong love of flight inspires Japanese aviation engineer Jiro Horikoshi (Hideaki Anno), whose storied career includes the creation of the A6M World War II fighter plane." | ||
tile="src: https://cdn.aframe.io/examples/ui/wind-raises2.jpg" | ||
position="0.6420 0.320 0.01"></a-entity> | ||
<!-- row --> | ||
<a-entity | ||
mixin="tile" | ||
title="The Wind Rises (2013)" | ||
synopsis="A lifelong love of flight inspires Japanese aviation engineer Jiro Horikoshi (Hideaki Anno), whose storied career includes the creation of the A6M World War II fighter plane." | ||
tile="src: https://cdn.aframe.io/examples/ui/kazetachinu.jpg" | ||
position="-0.6435 0 0.01"></a-entity> | ||
<a-entity | ||
mixin="tile" | ||
title="Spirited Away (2001)" | ||
synopsis="Miyazaki, 10-year-old Chihiro (Rumi Hiiragi) and her parents (Takashi Naitô, Yasuko Sawaguchi) stumble upon a seemingly abandoned amusement park. After her mother and father are turned into giant pigs, Chihiro meets the mysterious Haku." | ||
tile="src: https://cdn.aframe.io/examples/ui/spirited-away1.jpg" | ||
position="-0.2150 0 0.01"></a-entity> | ||
<a-entity | ||
mixin="tile" | ||
title="Spirited Away (2001)" | ||
synopsis="Miyazaki, 10-year-old Chihiro (Rumi Hiiragi) and her parents (Takashi Naitô, Yasuko Sawaguchi) stumble upon a seemingly abandoned amusement park. After her mother and father are turned into giant pigs, Chihiro meets the mysterious Haku." | ||
tile="src: https://cdn.aframe.io/examples/ui/spirited-away2.jpg" | ||
position="0.2135 0 0.01"></a-entity> | ||
<a-entity | ||
mixin="tile" | ||
title="Spirited Away (2001)" | ||
synopsis="Miyazaki, 10-year-old Chihiro (Rumi Hiiragi) and her parents (Takashi Naitô, Yasuko Sawaguchi) stumble upon a seemingly abandoned amusement park. After her mother and father are turned into giant pigs, Chihiro meets the mysterious Haku." | ||
tile="src: https://cdn.aframe.io/examples/ui/spirited-away3.jpg" | ||
position="0.6420 0 0.01"></a-entity> | ||
|
||
<!-- row --> | ||
<a-entity | ||
mixin="tile" | ||
title="Tales from Earthsea (2006)" | ||
synopsis="Something bizarre has come over the land. The kingdom is deteriorating. People are beginning to act strange... What's even more strange is that people are beginning to see dragons, which shouldn't enter the world of humans." | ||
tile="src: https://cdn.aframe.io/examples/ui/earth-sea1.jpg" | ||
position="-0.6435 -0.320 0.01"></a-entity> | ||
<a-entity | ||
mixin="tile" | ||
title="Tales from Earthsea (2006)" | ||
synopsis="Something bizarre has come over the land. The kingdom is deteriorating. People are beginning to act strange... What's even more strange is that people are beginning to see dragons, which shouldn't enter the world of humans." | ||
tile="src: https://cdn.aframe.io/examples/ui/earth-sea2.jpg" | ||
position="-0.2150 -0.320 0.01"></a-entity> | ||
<a-entity | ||
mixin="tile" | ||
title="Tales from Earthsea (2006)" | ||
synopsis="Something bizarre has come over the land. The kingdom is deteriorating. People are beginning to act strange... What's even more strange is that people are beginning to see dragons, which shouldn't enter the world of humans." | ||
tile="src: https://cdn.aframe.io/examples/ui/earth-sea3.jpg" | ||
position="0.2135 -0.320 0.01"></a-entity> | ||
<a-entity | ||
mixin="tile" | ||
title="From Up on Poppy Hill (2011)" | ||
synopsis="It's 1963 and Japan is in the midst of swift modernisation, leaving behind the Second World War's painful memories and focusing on a brighter future, symbolised by the coming year's Tokyo Olympics." | ||
tile="src: https://cdn.aframe.io/examples/ui/poppy-hill1.jpg" | ||
position="0.6420 -0.320 0.01"></a-entity> | ||
</a-entity> | ||
</a-entity> | ||
</a-entity> | ||
|
||
<a-entity position="0 1.6 0" look-controls camera> | ||
<a-entity class="camera-cursor" | ||
raycaster="objects: .tile, .start-button, .close-button" | ||
cursor | ||
geometry="primitive: circle; radius: 0.005" | ||
material="color: #283644; shader: flat" | ||
position="0 0 -0.75"></a-entity> | ||
</a-entity> | ||
<a-entity hand-tracking-controls="hand: left"></a-entity> | ||
<a-entity hand-tracking-controls="hand: right"></a-entity> | ||
</a-scene> | ||
</body> | ||
</html> |
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 |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/* global AFRAME, THREE, SPATIAL */ | ||
|
||
if (typeof AFRAME === 'undefined') { | ||
throw new Error('Component attempted to register before AFRAME was available.'); | ||
} | ||
|
||
/** | ||
* Spatial Window component for A-Frame. | ||
*/ | ||
AFRAME.registerComponent('spatial-button', { | ||
schema: { | ||
color: {type: 'color', default: '#60ff7e'}, | ||
width: {default: 0.35, min: 0}, | ||
height: {default: 0.08, min: 0}, | ||
focused: {default: true}, | ||
text: {default: 'start'} | ||
}, | ||
|
||
init: function () { | ||
var data = this.data; | ||
var geometry = this.geometry = SPATIAL.utils.generatePlaneGeometryIndexed(data.width, data.height, 0.035, 22); | ||
var material = this.material = new THREE.MeshPhysicalMaterial({ | ||
roughness: 0.6, | ||
transmission: 1, | ||
color: new THREE.Color(data.color) | ||
}); | ||
|
||
var textEl = this.textEl = document.createElement('a-entity'); | ||
textEl.setAttribute('text', { | ||
value: this.data.text, | ||
width: 0.75, | ||
align: 'center', | ||
font: 'kelsonsans' | ||
}); | ||
textEl.setAttribute('position', '0 0 0.005'); | ||
|
||
this.el.appendChild(textEl); | ||
this.plane = new THREE.Mesh(geometry, material); | ||
this.el.setObject3D('mesh', this.plane); | ||
|
||
this.el.addEventListener('mouseenter', function () { material.roughness = 0.9; }); | ||
this.el.addEventListener('mouseleave', function () { material.roughness = 0.8; }); | ||
} | ||
}); |
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 |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/* global AFRAME, THREE */ | ||
|
||
if (typeof AFRAME === 'undefined') { | ||
throw new Error('Component attempted to register before AFRAME was available.'); | ||
} | ||
|
||
/** | ||
* Spatial Window component for A-Frame. | ||
*/ | ||
AFRAME.registerComponent('spatial-close-button', { | ||
schema: { | ||
color: {type: 'color', default: '#ffffff'}, | ||
width: {default: 1, min: 0}, | ||
height: {default: 1, min: 0}, | ||
focused: {default: true} | ||
}, | ||
|
||
init: function () { | ||
var data = this.data; | ||
var geometry = this.geometry = new THREE.CircleGeometry(0.025, 32); | ||
|
||
var material = this.material = new THREE.MeshPhysicalMaterial({ | ||
roughness: 0.8, | ||
transmission: 1, | ||
color: new THREE.Color(data.color) | ||
}); | ||
|
||
var planeGeometry = this.planeGeometry = new THREE.PlaneGeometry(0.05, 0.05); | ||
var planeMaterial = this.planeMaterial = new THREE.MeshBasicMaterial({ | ||
color: new THREE.Color(data.color), | ||
transparent: true | ||
}); | ||
|
||
var texture = new THREE.TextureLoader().load('./close-button.png', function () { | ||
// material.needsUpdate = true; | ||
}); | ||
planeMaterial.map = texture; | ||
texture.colorSpace = THREE.SRGBColorSpace; | ||
|
||
this.circle = new THREE.Mesh(geometry, material); | ||
this.el.setObject3D('mesh', this.circle); | ||
|
||
this.plane = new THREE.Mesh(planeGeometry, planeMaterial); | ||
this.plane.position.set(0, 0, 0.001); | ||
this.el.setObject3D('plane', this.plane); | ||
|
||
var targetPlaneEl = this.targetPlaneEl = document.createElement('a-entity'); | ||
targetPlaneEl.setAttribute('geometry', {primitive: 'plane', width: 0.1, height: 0.1}); | ||
targetPlaneEl.setAttribute('position', '0 0 0.002'); | ||
targetPlaneEl.setAttribute('visible', false); | ||
targetPlaneEl.classList.add('close-button'); | ||
|
||
this.el.appendChild(targetPlaneEl); | ||
|
||
targetPlaneEl.addEventListener('mouseenter', function () { material.roughness = 0.9; }); | ||
targetPlaneEl.addEventListener('mouseleave', function () { material.roughness = 0.8; }); | ||
}, | ||
|
||
update: function () { | ||
} | ||
}); |
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 |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* global AFRAME, THREE, SPATIAL */ | ||
|
||
if (typeof AFRAME === 'undefined') { | ||
throw new Error('Component attempted to register before AFRAME was available.'); | ||
} | ||
|
||
/** | ||
* Spatial Window component for A-Frame. | ||
*/ | ||
AFRAME.registerComponent('spatial-hero-image', { | ||
schema: { | ||
color: {type: 'color', default: '#fff'}, | ||
width: {default: 1, min: 0}, | ||
height: {default: 1, min: 0}, | ||
focused: {default: true}, | ||
src: {type: 'map'} | ||
}, | ||
|
||
init: function () { | ||
var data = this.data; | ||
var geometry = this.geometry = SPATIAL.utils.generatePlaneGeometryIndexed(data.width, data.height, 0.05, 22); | ||
var material = this.material = new THREE.MeshBasicMaterial({color: new THREE.Color(data.color)}); | ||
this.el.sceneEl.systems.material.loadTexture(data.src, {src: data.src}, function textureLoaded (texture) { | ||
material.map = texture; | ||
texture.colorSpace = THREE.SRGBColorSpace; | ||
}); | ||
this.plane = new THREE.Mesh(geometry, material); | ||
this.el.setObject3D('mesh', this.plane); | ||
} | ||
}); |
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 |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/* global AFRAME, THREE, SPATIAL */ | ||
|
||
if (typeof AFRAME === 'undefined') { | ||
throw new Error('Component attempted to register before AFRAME was available.'); | ||
} | ||
|
||
/** | ||
* Spatial Window component for A-Frame. | ||
*/ | ||
AFRAME.registerComponent('spatial-modal-image', { | ||
schema: { | ||
color: {type: 'color', default: '#fff'}, | ||
width: {default: 1, min: 0}, | ||
height: {default: 1, min: 0}, | ||
src: {type: 'map', default: 'https://cdn.aframe.io/examples/ui/kazetachinu.jpg'} | ||
}, | ||
|
||
init: function () { | ||
var data = this.data; | ||
var geometry = this.geometry = SPATIAL.utils.generatePlaneGeometryTwoCorners(data.width, data.height, 0.05, 22); | ||
var material = this.material = new THREE.MeshBasicMaterial({ color: new THREE.Color(data.color) }); | ||
|
||
this.plane = new THREE.Mesh(geometry, material); | ||
this.el.setObject3D('mesh', this.plane); | ||
}, | ||
|
||
update: function (oldData) { | ||
var data = this.data; | ||
var material = this.material; | ||
|
||
if (data.src !== oldData.src) { | ||
var texture = new THREE.TextureLoader().load(data.src, function () { | ||
// material.needsUpdate = true; | ||
}); | ||
material.map = texture; | ||
material.needsUpdate = true; | ||
texture.colorSpace = THREE.SRGBColorSpace; | ||
} | ||
} | ||
}); |
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 |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* global AFRAME, THREE, SPATIAL */ | ||
|
||
if (typeof AFRAME === 'undefined') { | ||
throw new Error('Component attempted to register before AFRAME was available.'); | ||
} | ||
|
||
/** | ||
* Spatial Window component for A-Frame. | ||
*/ | ||
AFRAME.registerComponent('spatial-modal', { | ||
schema: { | ||
color: {type: 'color', default: '#fff'}, | ||
width: {default: 1, min: 0}, | ||
height: {default: 1, min: 0}, | ||
src: {type: 'map'} | ||
}, | ||
|
||
init: function () { | ||
var data = this.data; | ||
var geometry = this.geometry = SPATIAL.utils.generatePlaneGeometryIndexed(data.width, data.height, 0.05, 22); | ||
var material = this.material = new THREE.MeshPhysicalMaterial({ | ||
roughness: 0.6, | ||
transmission: 1, | ||
transparent: true, | ||
color: new THREE.Color(data.color) | ||
}); | ||
|
||
this.plane = new THREE.Mesh(geometry, material); | ||
this.el.setObject3D('mesh', this.plane); | ||
} | ||
}); |
Oops, something went wrong.