Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
HFT-informatics-weekend
AR - Urban Planner
Commits
d2a0c033
Commit
d2a0c033
authored
Oct 12, 2025
by
Stoll
Browse files
Fix: Button for screenshot is positioned correctly
parent
c986c42e
Changes
3
Hide whitespace changes
Inline
Side-by-side
webxr-cube/src/components/ARBottomBar.tsx
View file @
d2a0c033
import
React
from
"
react
"
;
interface
ARBottomBarProps
{
objectOptions
:
{
name
:
string
;
emoji
:
string
}[];
onSelect
:
(
name
:
string
)
=>
void
;
objectOptions
:
{
name
:
string
;
emoji
:
string
}[];
onSelect
:
(
name
:
string
)
=>
void
;
}
export
const
ARBottomBar
:
React
.
FC
<
ARBottomBarProps
>
=
({
objectOptions
,
onSelect
})
=>
{
return
(
<
div
style
=
{
{
position
:
"
absolute
"
,
bottom
:
0
,
width
:
"
100%
"
,
height
:
"
90px
"
,
background
:
"
rgba(0, 0, 0, 0.6)
"
,
display
:
"
flex
"
,
alignItems
:
"
center
"
,
justifyContent
:
"
space-around
"
,
color
:
"
white
"
,
zIndex
:
10
,
pointerEvents
:
"
auto
"
,
backdropFilter
:
"
blur(10px)
"
,
}
}
>
{
objectOptions
.
map
((
obj
)
=>
(
<
button
key
=
{
obj
.
name
}
style
=
{
{
background
:
"
#333
"
,
color
:
"
white
"
,
border
:
"
none
"
,
borderRadius
:
"
10px
"
,
padding
:
"
10px 20px
"
,
fontSize
:
"
16px
"
,
}
}
onClick
=
{
()
=>
onSelect
(
obj
.
name
)
}
export
const
ARBottomBar
:
React
.
FC
<
ARBottomBarProps
>
=
({
objectOptions
,
onSelect
,
})
=>
{
return
(
<
div
style
=
{
{
position
:
"
absolute
"
,
bottom
:
0
,
width
:
"
100%
"
,
height
:
"
100px
"
,
background
:
"
rgba(0, 0, 0, 0.6)
"
,
display
:
"
flex
"
,
alignItems
:
"
center
"
,
justifyContent
:
"
flex-start
"
,
color
:
"
white
"
,
zIndex
:
10
,
pointerEvents
:
"
auto
"
,
backdropFilter
:
"
blur(10px)
"
,
overflowX
:
"
auto
"
,
whiteSpace
:
"
nowrap
"
,
padding
:
"
0 10px
"
,
scrollbarWidth
:
"
none
"
,
// hides scrollbar in Firefox
msOverflowStyle
:
"
none
"
,
// hides scrollbar in IE
}
}
>
{
obj
.
emoji
}
{
obj
.
name
}
</
button
>
))
}
</
div
>
);
{
/* hide scrollbar for WebKit browsers */
}
<
style
>
{
`
div::-webkit-scrollbar {
display: none;
}
`
}
</
style
>
{
objectOptions
.
map
((
obj
)
=>
(
<
button
key
=
{
obj
.
name
}
style
=
{
{
background
:
"
#333
"
,
color
:
"
white
"
,
border
:
"
none
"
,
borderRadius
:
"
10px
"
,
padding
:
"
10px 20px
"
,
fontSize
:
"
16px
"
,
marginRight
:
"
10px
"
,
flex
:
"
0 0 auto
"
,
}
}
onClick
=
{
()
=>
onSelect
(
obj
.
name
)
}
>
{
obj
.
emoji
}
{
obj
.
name
}
</
button
>
))
}
</
div
>
);
};
webxr-cube/src/components/XRRenderer.tsx
View file @
d2a0c033
// Import necessary tools and libraries
import
React
,
{
useEffect
,
useRef
,
useState
}
from
"
react
"
;
import
React
,
{
useEffect
,
useRef
,
useState
}
from
"
react
"
;
import
type
{
WebGLRenderer
}
from
"
three
"
;
import
*
as
THREE
from
"
three
"
;
import
{
XRButton
}
from
"
three/examples/jsm/webxr/XRButton
"
;
import
{
BlockManager
}
from
"
./BlockManager
"
;
// manages placed 3D objects in the scene
import
{
Cube
}
from
"
../model/Cube
"
;
// custom class for a simple cube
import
{
GLTFModel
}
from
"
../model/GLTFModel
"
;
// custom loader for .glb 3D models
import
{
ARBottomBar
}
from
"
./ARBottomBar
"
;
import
{
XRButton
}
from
"
three/examples/jsm/webxr/XRButton
"
;
import
{
BlockManager
}
from
"
./BlockManager
"
;
// manages placed 3D objects in the scene
import
{
Cube
}
from
"
../model/Cube
"
;
// custom class for a simple cube
import
{
GLTFModel
}
from
"
../model/GLTFModel
"
;
// custom loader for .glb 3D models
import
{
ARBottomBar
}
from
"
./ARBottomBar
"
;
import
{
RoomEnvironment
}
from
"
three/examples/jsm/environments/RoomEnvironment
"
;
import
{
addLightToScene
,
createCamera
,
createPlacementRing
,
createRenderer
,
setSceneBackground
}
from
"
./Setup.ts
"
;
import
type
{
WebGLRenderer
}
from
"
three
"
;
// bottom UI for selecting objects
import
{
ModelType
}
from
"
../model/ModelType.ts
"
;
// bottom UI for selecting objects
function
createARButton
(
renderer
:
WebGLRenderer
,
overlayRef
:
React
.
RefObject
<
HTMLDivElement
>
)
{
...
...
@@ -134,16 +136,21 @@ export const XRRenderer: React.FC = () => {
let
objectToAdd
;
// Choose what object to add based on selection
if
(
name
===
"
Cube
"
)
{
if
(
name
===
ModelType
.
CUBE
)
{
objectToAdd
=
new
Cube
(
position
);
}
else
if
(
name
===
"
Watermill
"
)
{
objectToAdd
=
new
GLTFModel
(
"
/watermill.glb
"
,
position
,
"
/Textures/colormap.png
"
);
}
else
if
(
name
===
"
Tree
"
)
{
objectToAdd
=
new
GLTFModel
(
"
/tree.glb
"
,
position
,
"
/Textures/colormap.png
"
);
}
else
if
(
name
===
ModelType
.
WATERMILL
)
{
objectToAdd
=
new
GLTFModel
(
"
/fantasy/watermill.glb
"
,
position
,
"
/fantasy/colormap.png
"
);
}
else
if
(
name
===
ModelType
.
TREE
)
{
objectToAdd
=
new
GLTFModel
(
"
/fantasy/tree.glb
"
,
position
,
"
/fantasy/colormap.png
"
);
}
else
if
(
name
===
ModelType
.
CROISSANT
)
{
objectToAdd
=
new
GLTFModel
(
"
/food/croissant.glb
"
,
position
,
"
/food/colormap.png
"
);
}
else
{
objectToAdd
=
new
Cube
(
position
);
// fallback
}
const
audio
=
new
Audio
(
'
/sounds/cash.mp3
'
);
audio
.
play
();
// Add the object to the scene (via manager)
blockManager
.
addObject
(
objectToAdd
);
};
...
...
@@ -228,8 +235,8 @@ export const XRRenderer: React.FC = () => {
aria-label
=
"Save snapshot"
style
=
{
{
position
:
"
absolute
"
,
top
:
12
,
right
:
12
,
top
:
"
4rem
"
,
right
:
"
1.5rem
"
,
zIndex
:
1000
,
padding
:
"
10px 12px
"
,
borderRadius
:
12
,
...
...
@@ -247,9 +254,10 @@ export const XRRenderer: React.FC = () => {
{
isSessionActive
&&
(
<
ARBottomBar
objectOptions
=
{
[
{
name
:
"
Cube
"
,
emoji
:
"
🧊
"
},
{
name
:
"
Watermill
"
,
emoji
:
"
🌊
"
},
{
name
:
"
Tree
"
,
emoji
:
"
🌳
"
},
{
name
:
ModelType
.
CUBE
,
emoji
:
"
🧊
"
},
{
name
:
ModelType
.
WATERMILL
,
emoji
:
"
🌊
"
},
{
name
:
ModelType
.
TREE
,
emoji
:
"
🌳
"
},
{
name
:
ModelType
.
CROISSANT
,
emoji
:
"
🥐
"
},
]
}
onSelect
=
{
handleSelect
}
/>
...
...
webxr-cube/src/model/ModelType.ts
0 → 100644
View file @
d2a0c033
export
enum
ModelType
{
CUBE
=
'
Cube
'
,
FOUNTAIN
=
"
Fountain
"
,
TREE
=
"
Tree
"
,
WATERMILL
=
"
Watermill
"
,
WHEEL
=
"
Wheel
"
,
WINDMILL
=
"
Windmill
"
,
BREAD
=
"
Bread
"
,
BURGER
=
"
Burger
"
,
CROISSANT
=
"
Croissant
"
,
PIZZA_BOX
=
"
Pizza Box
"
,
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment