Skip to content

Commit

Permalink
Several UI tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
sachamorgese committed Jul 1, 2024
1 parent 3ce054b commit 099563b
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 51 deletions.
101 changes: 99 additions & 2 deletions example/multi-user-3d-web-experience/client/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,105 @@ const app = new Networked3dWebExperienceClient(holder, {
mmlDocuments: [{ url: `${protocol}//${host}/mml-documents/example-mml.html` }],
environmentConfiguration: {},
avatarConfig: {
allowCustomAvatars: true,
},
availableAvatars: [
{
thumbnailUrl:"https://e7.pngegg.com/pngimages/799/987/png-clipart-computer-icons-avatar-icon-design-avatar-heroes-computer-wallpaper-thumbnail.png",
mmlCharacterUrl: "https://mmlstorage.com/eYIAFx/1706889930376.html",
name: "Avatar 1ahlishdflkjhaskjdfhlakj;shdfijlkhakjsdhfghjkabhsdyhuifbglakjhsdbfkjhabnsdkjfhnbsakjdhnbfjkws",
isDefaultAvatar: false,
},
{
thumbnailUrl: "https://models.readyplayer.me/65a8dba831b23abb4f401bae.png",
meshFileUrl: "https://models.readyplayer.me/65a8dba831b23abb4f401bae.glb",
name: "Avatar 2",
isDefaultAvatar: true,
},
{
thumbnailUrl: "https://static.vecteezy.com/system/resources/previews/019/896/008/original/male-user-avatar-icon-in-flat-design-style-person-signs-illustration-png.png",
mmlCharacterString: "<m-character src=\"https://mmlstorage.com/fca2e81688f8c26b1671b701e399f0a5c9756307607d78c11739293d2e530e78\">\n" +
"</m-character>",
name: "Avatar 3",
isDefaultAvatar: false,
},
{
thumbnailUrl:"https://e7.pngegg.com/pngimages/799/987/png-clipart-computer-icons-avatar-icon-design-avatar-heroes-computer-wallpaper-thumbnail.png",
mmlCharacterUrl: "https://mmlstorage.com/eYIAFx/1706889930376.html",
name: "Avatar 1",
isDefaultAvatar: false,
},
{
thumbnailUrl: "https://models.readyplayer.me/65a8dba831b23abb4f401bae.png",
meshFileUrl: "https://models.readyplayer.me/65a8dba831b23abb4f401bae.glb",
name: "Avatar 2",
isDefaultAvatar: true,
},
{
thumbnailUrl: "https://static.vecteezy.com/system/resources/previews/019/896/008/original/male-user-avatar-icon-in-flat-design-style-person-signs-illustration-png.png",
mmlCharacterString: "<m-character src=\"https://mmlstorage.com/fca2e81688f8c26b1671b701e399f0a5c9756307607d78c11739293d2e530e78\">\n" +
"</m-character>",
name: "Avatar 3",
isDefaultAvatar: false,
},
{
thumbnailUrl:"https://e7.pngegg.com/pngimages/799/987/png-clipart-computer-icons-avatar-icon-design-avatar-heroes-computer-wallpaper-thumbnail.png",
mmlCharacterUrl: "https://mmlstorage.com/eYIAFx/1706889930376.html",
name: "Avatar 1",
isDefaultAvatar: false,
},
{
thumbnailUrl: "https://models.readyplayer.me/65a8dba831b23abb4f401bae.png",
meshFileUrl: "https://models.readyplayer.me/65a8dba831b23abb4f401bae.glb",
name: "Avatar 2",
isDefaultAvatar: true,
},
{
thumbnailUrl: "https://static.vecteezy.com/system/resources/previews/019/896/008/original/male-user-avatar-icon-in-flat-design-style-person-signs-illustration-png.png",
mmlCharacterString: "<m-character src=\"https://mmlstorage.com/fca2e81688f8c26b1671b701e399f0a5c9756307607d78c11739293d2e530e78\">\n" +
"</m-character>",
name: "Avatar 3",
isDefaultAvatar: false,
},
{
thumbnailUrl:"https://e7.pngegg.com/pngimages/799/987/png-clipart-computer-icons-avatar-icon-design-avatar-heroes-computer-wallpaper-thumbnail.png",
mmlCharacterUrl: "https://mmlstorage.com/eYIAFx/1706889930376.html",
name: "Avatar 1",
isDefaultAvatar: false,
},
{
thumbnailUrl: "https://models.readyplayer.me/65a8dba831b23abb4f401bae.png",
meshFileUrl: "https://models.readyplayer.me/65a8dba831b23abb4f401bae.glb",
name: "Avatar 2",
isDefaultAvatar: true,
},
{
thumbnailUrl: "https://static.vecteezy.com/system/resources/previews/019/896/008/original/male-user-avatar-icon-in-flat-design-style-person-signs-illustration-png.png",
mmlCharacterString: "<m-character src=\"https://mmlstorage.com/fca2e81688f8c26b1671b701e399f0a5c9756307607d78c11739293d2e530e78\">\n" +
"</m-character>",
name: "Avatar 3",
isDefaultAvatar: false,
},
{
thumbnailUrl:"https://e7.pngegg.com/pngimages/799/987/png-clipart-computer-icons-avatar-icon-design-avatar-heroes-computer-wallpaper-thumbnail.png",
mmlCharacterUrl: "https://mmlstorage.com/eYIAFx/1706889930376.html",
name: "Avatar 1",
isDefaultAvatar: false,
},
{
thumbnailUrl: "https://models.readyplayer.me/65a8dba831b23abb4f401bae.png",
meshFileUrl: "https://models.readyplayer.me/65a8dba831b23abb4f401bae.glb",
name: "Avatar 2",
isDefaultAvatar: true,
},
{
thumbnailUrl: "https://static.vecteezy.com/system/resources/previews/019/896/008/original/male-user-avatar-icon-in-flat-design-style-person-signs-illustration-png.png",
mmlCharacterString: "<m-character src=\"https://mmlstorage.com/fca2e81688f8c26b1671b701e399f0a5c9756307607d78c11739293d2e530e78\">\n" +
"</m-character>",
name: "Avatar 3",
isDefaultAvatar: false,
},
],
// allowCustomAvatars: true,
}
});

app.update();
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React, {
useRef,
useState,
ForwardRefRenderFunction,
MouseEvent,
MouseEvent, useEffect,
} from "react";

import { CustomAvatar } from "../../AvatarSelectionUI";
Expand All @@ -25,6 +25,10 @@ enum CustomAvatarType {
mml,
}

function SelectedPill() {
return <span className={styles.selectedPill}>Selected</span>;
}

export const AvatarSelectionUIComponent: ForwardRefRenderFunction<any, AvatarSelectionUIProps> = (
props: AvatarSelectionUIProps,
) => {
Expand Down Expand Up @@ -96,43 +100,46 @@ export const AvatarSelectionUIComponent: ForwardRefRenderFunction<any, AvatarSel
</div>
{isVisible && (
<div className={`${styles.avatarSelectionContainer}`}>
<div className={styles.avatarSelectionUi}>
<div className={styles.avatarSelectionUiHeader}>
<h2>Choose your avatar</h2>
<button className={styles.closeButton} onClick={(e) => setIsVisible(false)}>
X
</button>
</div>
<div className={styles.avatarSelectionUiContent}>
{props.availableAvatars.map((avatar, index) => {
const isSelected =
!selectedAvatar?.isCustomAvatar &&
((selectedAvatar?.meshFileUrl &&
selectedAvatar?.meshFileUrl === avatar.meshFileUrl) ||
(selectedAvatar?.mmlCharacterUrl &&
selectedAvatar?.mmlCharacterUrl === avatar.mmlCharacterUrl) ||
(selectedAvatar?.mmlCharacterString &&
selectedAvatar?.mmlCharacterString === avatar.mmlCharacterString));

return (
<div
key={index}
className={styles.avatarSelectionUiAvatar}
onClick={() => selectAvatar(avatar)}
>
<img
className={isSelected ? styles.selectedAvatar : ""}
src={avatar.thumbnailUrl}
alt={avatar.name}
/>
<h2>{avatar.name}</h2>
</div>
);
})}
{!!props.availableAvatars.length && (
<div className={styles.avatarSelectionUi}>
<div className={styles.avatarSelectionUiHeader}>
<h2>Choose your avatar</h2>
<button className={styles.closeButton} onClick={(e) => setIsVisible(false)}>
X
</button>
</div>
<div className={styles.avatarSelectionUiContent}>
{props.availableAvatars.map((avatar, index) => {
const isSelected =
!selectedAvatar?.isCustomAvatar &&
((selectedAvatar?.meshFileUrl &&
selectedAvatar?.meshFileUrl === avatar.meshFileUrl) ||
(selectedAvatar?.mmlCharacterUrl &&
selectedAvatar?.mmlCharacterUrl === avatar.mmlCharacterUrl) ||
(selectedAvatar?.mmlCharacterString &&
selectedAvatar?.mmlCharacterString === avatar.mmlCharacterString));

return (
<div
key={index}
className={styles.avatarSelectionUiAvatar}
onClick={() => selectAvatar(avatar)}
>
<div className={styles.avatarSelectionUiAvatarImgContainer}>
{isSelected && <SelectedPill />}
<img src={avatar.thumbnailUrl} alt={avatar.name} />
</div>
<p>{avatar.name}</p>
<span className={styles.tooltipText}>{avatar.name}</span>
</div>
);
})}
</div>
</div>
</div>
)}
{props.enableCustomAvatar && (
<div className={styles.customAvatarSection}>
{!!props.availableAvatars.length && <hr />}
<h2>Custom Avatar Section</h2>
<input
type="radio"
Expand Down Expand Up @@ -161,6 +168,7 @@ export const AvatarSelectionUIComponent: ForwardRefRenderFunction<any, AvatarSel
checked={customAvatarType === CustomAvatarType.glb}
/>
<label htmlFor="glb">Mesh URL</label>
{selectedAvatar?.isCustomAvatar && <SelectedPill />}
<div className={styles.customAvatarInputSection}>
{customAvatarType === CustomAvatarType.mml ? (
<textarea
Expand All @@ -186,11 +194,6 @@ export const AvatarSelectionUIComponent: ForwardRefRenderFunction<any, AvatarSel
Set
</button>
</div>
{selectedAvatar?.isCustomAvatar && (
<div>
<h2 className={styles.selectedAvatar}>Custom Avatar Selected</h2>
</div>
)}
</div>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
.avatarSelectionUi {
padding-right: 4px;
overflow-y: scroll;
overflow-x: hidden;
max-height: 630px;
}

Expand Down Expand Up @@ -93,6 +94,10 @@
position: relative;
}

.avatarSelectionUiHeader h2 {
font-size: 20px;
}

.avatarSelectionUiCloseButton {
position: absolute;
right: 20px;
Expand All @@ -105,25 +110,67 @@
display: flex;
gap: 4%;
flex-wrap: wrap;
text-overflow: ellipsis;
}

.avatarSelectionUiAvatar {
flex: 0 0 22%;
aspect-ratio: 1;
position: relative;
color: #ffffff;
text-align: center;
cursor: pointer;
max-width: 22%;
}

.avatarSelectionUiAvatarImgContainer {
position: relative;
}

.avatarSelectionUiAvatar p {
margin-top: 5px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
position: relative;
}

.tooltipText {
position: absolute;
transform: translate(-50%, -25%);
z-index: 2;
color: white;
font-size: 12px;
background-color: #192733;
border-radius: 10px;
padding: 10px 15px 10px 15px;
opacity: 0;
transition: opacity 0.2s;
visibility: hidden;
}

.avatarSelectionUiAvatar p:hover + .tooltipText {
opacity: 1;
visibility: visible;
transition-delay: 1s;
}

.avatarSelectionUiAvatar img {
aspect-ratio: 1;
width: 100%;
}

.selectedAvatar {
border: 2px solid #00ff00;
box-sizing: border-box;
.selectedPill {
background-color: #00ff00;
border-radius: 8px;
height: 20px;
color: black;
padding: 2px 6px;
}

.avatarSelectionUiAvatarImgContainer .selectedPill {
position: absolute;
z-index: 2;
bottom: 8px;
right: 2px;
}

.avatarSelectionUiAvatar img:hover {
Expand All @@ -134,19 +181,21 @@
justify-content: center;
margin-top: 20px;
color: white;
position: relative;
}

.customAvatarSection h2 {
text-align: center;
font-size: 20px;
}

.customAvatarSection label {
font-size: 20px;
font-size: 16px;
margin-right: 8px;
}

.customAvatarSection input[type="radio"] {
transform: scale(1.5);
transform: scale(1.3);
margin-right: 4px;
}

Expand All @@ -156,7 +205,8 @@
}

.customAvatarInput {
font-family: 'Helvetica', 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif;
font-family: "Helvetica", "Lucida Sans", "Lucida Sans Regular", "Lucida Grande",
"Lucida Sans Unicode", Geneva, Verdana, sans-serif;
font-size: 15px;
flex: 1;
padding: 10px;
Expand All @@ -183,4 +233,17 @@

.customAvatarInputSection button[disabled] {
background-color: #ffffff50;
}

.sectionHeading {
font-size: 19px;
}

.customAvatarSection .selectedPill {
position: relative;
top: -2px;
}

.customAvatarSection hr {
width: 80%;
}
2 changes: 1 addition & 1 deletion packages/3d-web-experience-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
"lint-fix": "eslint \"./{src,test}/**/*.{js,jsx,ts,tsx}\" --fix"
},
"dependencies": {
"@mml-io/3d-web-avatar-selection-ui": "^0.17.0",
"@mml-io/3d-web-client-core": "^0.17.0",
"@mml-io/3d-web-text-chat": "^0.17.0",
"@mml-io/3d-web-user-networking": "^0.17.0",
"@mml-io/3d-web-voice-chat": "^0.17.0",
"@mml-io/3d-web-avatar-selection-ui": "^0.17.0",
"mml-web": "^0.16.0",
"three": "0.163.0"
},
Expand Down

0 comments on commit 099563b

Please sign in to comment.