You can now put a full size reference picture on the examine panel (#3339)

## About The Pull Request

I also centered the tab titles so it looks a little straighter


![o4s526oYFJ](https://github.com/user-attachments/assets/a8cbb5ce-c3c8-4155-bb3a-45d273b93e11)


![image](https://github.com/user-attachments/assets/65995b71-b3af-4644-b2ca-7a27973e25f5)

## Why It's Good For The Game

Cause I want to throw art on the examine panel. 

It'll be a little slow switching back due to ByondUI. Sadly

## Proof Of Testing

See above

## Changelog
🆑
qol: Adds the ability to put a reference picture on the examine panel.
/🆑
This commit is contained in:
The Sharkening
2025-03-19 21:45:55 -06:00
committed by GitHub
parent 8ab61efdc1
commit 4306e952fc
4 changed files with 293 additions and 152 deletions
@@ -57,7 +57,8 @@
var/obscurity_examine_pref = preferences?.read_preference(/datum/preference/toggle/obscurity_examine)
var/ooc_notes = ""
var/headshot = ""
var/art_ref = ""
var/art_ref_nsfw = preferences?.read_preference(/datum/preference/toggle/art_ref_nsfw)
// Handle OOC notes first
if(preferences)
if(preferences.read_preference(/datum/preference/toggle/master_erp_preferences))
@@ -100,6 +101,7 @@
else
headshot = holder_human.dna.features["headshot"]
flavor_text = holder_human.dna.features["flavor_text"]
art_ref = holder_human.dna.features["art_ref"]
name = holder.name
//Custom species handling. Reports the normal custom species if there is not one set.
if(holder_human.dna.species.lore_protected || holder_human.dna.features["custom_species"] == "")
@@ -124,4 +126,6 @@
data["custom_species"] = custom_species
data["custom_species_lore"] = custom_species_lore
data["headshot"] = headshot
data["art_ref"] = art_ref
data["art_ref_nsfw"] = art_ref_nsfw
return data
@@ -9,6 +9,7 @@
var/headshot_nsfw = ""
var/headshot_silicon = ""
var/headshot_silicon_nsfw = ""
var/art_ref = ""
/datum/preference/text/flavor_text_nsfw
category = PREFERENCE_CATEGORY_NON_CONTEXTUAL
@@ -88,6 +89,30 @@
stored_link[usr?.ckey] = value
usr?.client?.prefs.headshot_silicon_nsfw = value
/datum/preference/text/headshot/art_ref
savefile_key = "art_ref"
/datum/preference/text/headshot/art_ref
/datum/preference/text/headshot/art_ref/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/preferences)
target.dna.features["art_ref"] = value
/datum/preference/text/headshot/art_ref/apply_headshot(value)
if(stored_link[usr.ckey] != value)
log_game("[usr] has set their art reference image to '[value]'.")
stored_link[usr?.ckey] = value
usr?.client?.prefs.art_ref = value
/datum/preference/toggle/art_ref_nsfw
category = PREFERENCE_CATEGORY_NON_CONTEXTUAL
savefile_identifier = PREFERENCE_CHARACTER
savefile_key = "art_ref_nsfw"
default_value = FALSE
/datum/preference/toggle/art_ref_nsfw/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/preferences)
return FALSE
//OOC notes for Silicons. Overwrites regular OOC notes when you are playing a Silicon character.
//TODO: Make this your regular OOC notes if you don't have Silicon ones. Every time I've tried, for some reason regular OOC notes haven't shown.
/datum/preference/text/ooc_notes/silicon
+246 -151
View File
@@ -1,6 +1,13 @@
// THIS IS A SKYRAT UI FILE
import { useState } from 'react';
import { ByondUi, Section, Stack, Tabs } from 'tgui-core/components';
import {
Box,
Button,
ByondUi,
Section,
Stack,
Tabs,
} from 'tgui-core/components';
import { resolveAsset } from '../assets';
import { useBackend } from '../backend';
@@ -34,9 +41,10 @@ const formatURLs = (text) => {
return <div>{parts}</div>;
};
export const ExaminePanel = (props) => {
export const ExaminePanel = () => {
const [tabIndex, setTabIndex] = useState(1);
const [lowerTabIndex, setLowerTabIndex] = useState(1);
const [page, setPage] = useState('main');
const { act, data } = useBackend();
const {
character_name,
@@ -50,7 +58,14 @@ export const ExaminePanel = (props) => {
character_ad,
headshot,
headshot_nsfw,
art_ref,
art_ref_nsfw,
} = data;
const handlePageChange = (page, newPage) => {
setPage(newPage);
};
return (
<Window
title={character_name + "'s Examine Panel"}
@@ -58,157 +73,237 @@ export const ExaminePanel = (props) => {
height={670}
>
<Window.Content>
<Stack fill>
<Stack.Item width="30%">
{!headshot ? (
<Section fill title="Character Preview">
<ByondUi
height="100%"
width="100%"
className="ExaminePanel__map"
params={{
id: assigned_map,
type: 'map',
{page === 'main' ? (
<>
{art_ref && (
<Button>
color={data.art_ref_nsfw ? 'pink' : 'green'}
tooltip=
{data.art_ref_nsfw ? 'NSFW Reference Image' : 'Reference Image'}
icon="image" style=
{{
position: 'absolute',
bottom: '10px',
right: '10px',
zIndex: 1,
}}
onClick={() => handlePageChange(setPage, 'image')}
</Button>
)}
<Stack>
<Stack.Item style={{ width: '30%' }}>
{!headshot ? (
<Section
fill
style={{ textAlign: 'center' }}
title="Character Preview"
>
<ByondUi
height="100%"
width="100%"
className="ExaminePanel__map"
params={{
id: assigned_map,
type: 'map',
}}
/>
</Section>
) : (
<>
<Section
maxheight="310px"
title="Character Preview"
style={{ textAlign: 'center' }}
>
<ByondUi
height="260px"
width="100%"
className="ExaminePanel__map"
params={{
id: assigned_map,
type: 'map',
}}
/>
</Section>
<Section
maxheight="310px"
title="Headshot"
style={{ textAlign: 'center' }}
>
<img
src={
tabIndex === 2
? resolveAsset(headshot_nsfw)
: resolveAsset(headshot)
}
height="250px"
width="250px"
/>
</Section>
</>
)}
</Stack.Item>
<Stack.Item style={{ width: '70%' }}>
<Box height="610px">
<Tabs fluid>
<Tabs.Tab
selected={tabIndex === 1}
onClick={() => setTabIndex(1)}
>
<Section
fitted
title={'Flavor Text'}
style={{ textAlign: 'center' }}
/>
</Tabs.Tab>
<Tabs.Tab
selected={tabIndex === 2}
onClick={() => setTabIndex(2)}
>
<Section
fitted
title={'NSFW (Warning)'}
style={{ textAlign: 'center' }}
/>
</Tabs.Tab>
<Tabs.Tab
selected={tabIndex === 3}
onClick={() => setTabIndex(3)}
>
<Section
fitted
title={
custom_species ? custom_species : 'Unnamed Species'
}
style={{ textAlign: 'center' }}
/>
</Tabs.Tab>
</Tabs>
{tabIndex === 1 && (
<Section
style={{ 'overflow-y': 'scroll' }}
fitted
preserveWhitespace
minHeight="50%"
maxHeight="50%"
fontSize="14px"
lineHeight="1.7"
textIndent="3em"
>
{formatURLs(flavor_text)}
</Section>
)}
{tabIndex === 2 && (
<Section
style={{ 'overflow-y': 'scroll' }}
fitted
preserveWhitespace
minHeight="50%"
maxHeight="50%"
fontSize="14px"
lineHeight="1.7"
textIndent="3em"
>
{formatURLs(flavor_text_nsfw)}
</Section>
)}
{tabIndex === 3 && (
<Section
style={{ 'overflow-y': 'scroll' }}
fitted
preserveWhitespace
minHeight="50%"
maxHeight="50%"
fontSize="14px"
lineHeight="1.7"
textIndent="3em"
>
{custom_species
? formatURLs(custom_species_lore)
: 'Just a normal space dweller.'}
</Section>
)}
<Tabs fluid>
<Tabs.Tab
selected={lowerTabIndex === 1}
onClick={() => setLowerTabIndex(1)}
>
<Section
fitted
title={'OOC Notes'}
style={{ textAlign: 'center' }}
/>
</Tabs.Tab>
<Tabs.Tab
selected={lowerTabIndex === 2}
onClick={() => setLowerTabIndex(2)}
>
<Section
fitted
title={'Character Advert'}
style={{ textAlign: 'center' }}
/>
</Tabs.Tab>
</Tabs>
{lowerTabIndex === 1 && (
<Section
style={{ 'overflow-y': 'scroll' }}
preserveWhitespace
fitted
minHeight="35%"
maxHeight="35%"
fontSize="14px"
lineHeight="1.5"
>
<Stack.Item>{formatURLs(ooc_notes)}</Stack.Item>
</Section>
)}
{lowerTabIndex === 2 && (
<Section
style={{ 'overflow-y': 'scroll' }}
preserveWhitespace
fitted
minHeight="35%"
maxHeight="35%"
fontSize="14px"
lineHeight="1.5"
>
<Stack.Item>{formatURLs(character_ad)}</Stack.Item>
</Section>
)}
</Box>
</Stack.Item>
</Stack>
</>
) : (
<div>
<Button
content="Back"
icon="arrow-left"
style={{
position: 'absolute',
bottom: '10px',
right: '10px',
zIndex: 1,
}}
onClick={() => handlePageChange(setPage, 'main')}
/>
<Section>
<Box>
<img
src={data.art_ref}
style={{
height: 'auto',
maxHeight: '600px',
width: '100%',
objectFit: 'contain',
}}
/>
</Section>
) : (
<>
<Section height="310px" title="Character Preview">
<ByondUi
height="260px"
width="100%"
className="ExaminePanel__map"
params={{
id: assigned_map,
type: 'map',
}}
/>
</Section>
<Section height="310px" title="Headshot">
<img
src={
tabIndex === 2
? resolveAsset(headshot_nsfw)
: resolveAsset(headshot)
}
height="250px"
width="250px"
/>
</Section>
</>
)}
</Stack.Item>
<Stack.Item grow>
<Tabs fluid>
<Tabs.Tab
selected={tabIndex === 1}
onClick={() => setTabIndex(1)}
>
<Section fitted title={'Flavor Text'} />
</Tabs.Tab>
<Tabs.Tab
selected={tabIndex === 2}
onClick={() => setTabIndex(2)}
>
<Section fitted title={'NSFW (Warning)'} />
</Tabs.Tab>
<Tabs.Tab
selected={tabIndex === 3}
onClick={() => setTabIndex(3)}
>
<Section
fitted
title={custom_species ? custom_species : 'Unnamed Species'}
/>
</Tabs.Tab>
</Tabs>
{tabIndex === 1 && (
<Section
style={{ 'overflow-y': 'scroll' }}
fitted
preserveWhitespace
minHeight="50%"
maxHeight="50%"
fontSize="14px"
lineHeight="1.7"
textIndent="3em"
>
{formatURLs(flavor_text)}
</Section>
)}
{tabIndex === 2 && (
<Section
style={{ 'overflow-y': 'scroll' }}
fitted
preserveWhitespace
minHeight="50%"
maxHeight="50%"
fontSize="14px"
lineHeight="1.7"
textIndent="3em"
>
{formatURLs(flavor_text_nsfw)}
</Section>
)}
{tabIndex === 3 && (
<Section
style={{ 'overflow-y': 'scroll' }}
fitted
preserveWhitespace
minHeight="50%"
maxHeight="50%"
fontSize="14px"
lineHeight="1.7"
textIndent="3em"
>
{custom_species
? formatURLs(custom_species_lore)
: 'Just a normal space dweller.'}
</Section>
)}
<Tabs fluid>
<Tabs.Tab
selected={lowerTabIndex === 1}
onClick={() => setLowerTabIndex(1)}
>
<Section fitted title={'OOC Notes'} />
</Tabs.Tab>
<Tabs.Tab
selected={lowerTabIndex === 2}
onClick={() => setLowerTabIndex(2)}
>
<Section fitted title={'Character Advert'} />
</Tabs.Tab>
</Tabs>
{lowerTabIndex === 1 && (
<Section
style={{ 'overflow-y': 'scroll' }}
preserveWhitespace
fitted
minHeight="35%"
maxHeight="35%"
fontSize="14px"
lineHeight="1.5"
>
<Stack.Item>{formatURLs(ooc_notes)}</Stack.Item>
</Section>
)}
{lowerTabIndex === 2 && (
<Section
style={{ 'overflow-y': 'scroll' }}
preserveWhitespace
fitted
minHeight="35%"
maxHeight="35%"
fontSize="14px"
lineHeight="1.5"
>
<Stack.Item>{formatURLs(character_ad)}</Stack.Item>
</Section>
)}
</Stack.Item>
</Stack>
</Box>
</Section>
</div>
)}
</Window.Content>
</Window>
);
@@ -1,8 +1,10 @@
import {
CheckboxInput,
Feature,
FeatureChoiced,
FeatureShortTextInput,
FeatureTextInput,
FeatureToggle,
} from '../../base';
import { FeatureDropdownInput } from '../../dropdowns';
@@ -151,3 +153,18 @@ export const custom_species_lore_silicon: Feature<string> = {
'Lore for your silicon, typically its company, make, model, and details regarding its creation.',
component: FeatureTextInput,
};
export const art_ref: Feature<string> = {
name: 'Art Reference',
description:
'Art Reference that others can see for your character \
Requires a link ending with .png, .jpeg, or .jpg, starting with \
https://, and hosted on Catbox, Imgbox, Gyazo, Lensdump, or F-List.',
component: FeatureShortTextInput,
};
export const art_ref_nsfw: FeatureToggle = {
name: 'Art Reference NSFW',
description: 'Is your reference picture NSFW?',
component: CheckboxInput,
};