Skip to content

Commit 64a0fef

Browse files
authored
Merge pull request #7 from ke456-png/update-model-license
モデルデータの利用条件表記ガイドラインに合わせて利用条件表記を更新
2 parents 1da725b + 7319d04 commit 64a0fef

File tree

15 files changed

+416
-227
lines changed

15 files changed

+416
-227
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import type { CharacterModelLicenseSerializer } from '@/types/Response';
2+
import { LicenseItem } from './LicenseItem';
3+
import { getHubVrm0LicenseValue, getHubVrm0LicenseVariant } from './licenseUtils';
4+
5+
/**
6+
* VRoid Hubで設定できるVRM0.0向けのライセンス要約コンポーネント
7+
* モデルデータの利用条件表記ガイドラインに基づく
8+
* https://developer.vroid.com/guidelines/conditions_of_use.html
9+
*/
10+
export const VRM0License = ({ license, version }: { license: CharacterModelLicenseSerializer; version: string }) => {
11+
return (
12+
<div>
13+
<LicenseItem label="フォーマット" value={`VRM${version}`} variant="default" />
14+
<LicenseItem
15+
label="アバター利用"
16+
value={getHubVrm0LicenseValue(license, 'characterization_allowed_user')}
17+
variant={getHubVrm0LicenseVariant(license, 'characterization_allowed_user')}
18+
/>
19+
<LicenseItem
20+
label="暴力表現での利用"
21+
value={getHubVrm0LicenseValue(license, 'violent_expression')}
22+
variant={getHubVrm0LicenseVariant(license, 'violent_expression')}
23+
/>
24+
<LicenseItem
25+
label="性的表現での利用"
26+
value={getHubVrm0LicenseValue(license, 'sexual_expression')}
27+
variant={getHubVrm0LicenseVariant(license, 'sexual_expression')}
28+
/>
29+
<LicenseItem
30+
label="法人利用"
31+
value={getHubVrm0LicenseValue(license, 'corporate_commercial_use')}
32+
variant={getHubVrm0LicenseVariant(license, 'corporate_commercial_use')}
33+
/>
34+
<LicenseItem
35+
label="個人の商用利用"
36+
value={getHubVrm0LicenseValue(license, 'personal_commercial_use')}
37+
variant={getHubVrm0LicenseVariant(license, 'personal_commercial_use')}
38+
/>
39+
<LicenseItem
40+
label="再配布"
41+
value={getHubVrm0LicenseValue(license, 'redistribution')}
42+
variant={getHubVrm0LicenseVariant(license, 'redistribution')}
43+
/>
44+
<LicenseItem
45+
label="改変"
46+
value={getHubVrm0LicenseValue(license, 'modification')}
47+
variant={getHubVrm0LicenseVariant(license, 'modification')}
48+
/>
49+
<LicenseItem
50+
label="クレジット表記"
51+
value={getHubVrm0LicenseValue(license, 'credit')}
52+
variant={getHubVrm0LicenseVariant(license, 'credit')}
53+
/>
54+
</div>
55+
);
56+
};
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import styled from 'styled-components';
2+
3+
interface LicenseItemProps {
4+
label: string;
5+
value: string;
6+
variant: 'default' | 'allow' | 'bold';
7+
}
8+
9+
export const LicenseItem = (props: LicenseItemProps) => {
10+
const { label, value, variant } = props;
11+
12+
return (
13+
<StyledLicenseItem>
14+
<span>{label}</span>
15+
<span> : </span>
16+
<StyledLicenseValue variant={variant}>{value}</StyledLicenseValue>
17+
</StyledLicenseItem>
18+
);
19+
};
20+
21+
const StyledLicenseItem = styled.div`
22+
color: ${(props) => props.theme.color.text2};
23+
margin: ${(props) => props.theme.spacing[8]}px;
24+
`;
25+
26+
const StyledLicenseValue = styled.span<{ variant: 'default' | 'allow' | 'bold' }>`
27+
color: ${(props) => props.theme.color.text3};
28+
font-weight: bold;
29+
${(props) =>
30+
props.variant === 'allow' &&
31+
`
32+
color: ${props.theme.color.success};
33+
`}
34+
${(props) =>
35+
props.variant === 'bold' &&
36+
`
37+
color: ${props.theme.color.text2};
38+
font-weight: bold;
39+
`}
40+
`;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import type { CharacterModelSerializer } from '@/types/Response';
2+
import { VRM1License } from './Vrm1License';
3+
import { VRM0License } from './HubVrm0License';
4+
import styled from 'styled-components';
5+
6+
export const ModelLicense = ({ model }: { model: CharacterModelSerializer }) => {
7+
const version = model.latest_character_model_version?.spec_version ?? '0.0';
8+
if (version === '1.0') {
9+
return (
10+
<LicenseContainer>
11+
<VRM1License meta={model.latest_character_model_version.vrm_meta} version={version} />
12+
</LicenseContainer>
13+
);
14+
}
15+
16+
return (
17+
<LicenseContainer>
18+
<VRM0License license={model.license} version={version} />
19+
</LicenseContainer>
20+
);
21+
};
22+
23+
const LicenseContainer = styled.div`
24+
border-top: solid thin ${(props) => props.theme.color.surface10};
25+
border-bottom: solid thin ${(props) => props.theme.color.surface10};
26+
padding: ${(props) => props.theme.spacing[16]}px;
27+
`;
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import type { VRM1Meta } from '@pixiv/three-vrm';
2+
import { LicenseItem } from './LicenseItem';
3+
import { getVrm1LicenseValue, getVrm1LicenseVariant } from './licenseUtils';
4+
5+
/**
6+
* VRM1.0向けのライセンス要約コンポーネント
7+
* モデルデータの利用条件表記ガイドラインに基づく
8+
* https://developer.vroid.com/guidelines/conditions_of_use.html
9+
*/
10+
export const VRM1License = ({ meta, version }: { meta: VRM1Meta; version: string }) => {
11+
return (
12+
<div>
13+
<LicenseItem label="フォーマット" value={`VRM${version}`} variant="default" />
14+
<LicenseItem
15+
label="アバター利用"
16+
value={getVrm1LicenseValue(meta, 'avatarPermission')}
17+
variant={getVrm1LicenseVariant(meta, 'avatarPermission')}
18+
/>
19+
<LicenseItem
20+
label="暴力表現での利用"
21+
value={getVrm1LicenseValue(meta, 'allowExcessivelyViolentUsage')}
22+
variant={getVrm1LicenseVariant(meta, 'allowExcessivelyViolentUsage')}
23+
/>
24+
<LicenseItem
25+
label="性的表現での利用"
26+
value={getVrm1LicenseValue(meta, 'allowExcessivelySexualUsage')}
27+
variant={getVrm1LicenseVariant(meta, 'allowExcessivelySexualUsage')}
28+
/>
29+
<LicenseItem
30+
label="宗教・政治目的での利用"
31+
value={getVrm1LicenseValue(meta, 'allowPoliticalOrReligiousUsage')}
32+
variant={getVrm1LicenseVariant(meta, 'allowPoliticalOrReligiousUsage')}
33+
/>
34+
<LicenseItem
35+
label="反社会的・憎悪表現での利用"
36+
value={getVrm1LicenseValue(meta, 'allowAntisocialOrHateUsage')}
37+
variant={getVrm1LicenseVariant(meta, 'allowAntisocialOrHateUsage')}
38+
/>
39+
<LicenseItem
40+
label="法人利用"
41+
value={getVrm1LicenseValue(meta, 'commercialUsage')}
42+
variant={getVrm1LicenseVariant(meta, 'commercialUsage')}
43+
/>
44+
<LicenseItem
45+
label="個人の商用利用"
46+
value={getVrm1LicenseValue(meta, 'personalCommercialUse')}
47+
variant={getVrm1LicenseVariant(meta, 'personalCommercialUse')}
48+
/>
49+
<LicenseItem
50+
label="再配布"
51+
value={getVrm1LicenseValue(meta, 'allowRedistribution')}
52+
variant={getVrm1LicenseVariant(meta, 'allowRedistribution')}
53+
/>
54+
<LicenseItem
55+
label="改変"
56+
value={getVrm1LicenseValue(meta, 'modification')}
57+
variant={getVrm1LicenseVariant(meta, 'modification')}
58+
/>
59+
<LicenseItem
60+
label="改変物の再配布"
61+
value={getVrm1LicenseValue(meta, 'modificationRedistribution')}
62+
variant={getVrm1LicenseVariant(meta, 'modificationRedistribution')}
63+
/>
64+
<LicenseItem
65+
label="クレジット表記"
66+
value={getVrm1LicenseValue(meta, 'creditNotation')}
67+
variant={getVrm1LicenseVariant(meta, 'creditNotation')}
68+
/>
69+
</div>
70+
);
71+
};

components/ModelLicense/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { ModelLicense } from './ModelLicense';
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
import type { CharacterModelLicenseSerializer } from '@/types/Response';
2+
import type { VRM1Meta } from '@pixiv/three-vrm';
3+
4+
type LicenseProperty = keyof CharacterModelLicenseSerializer;
5+
6+
/**
7+
* VRoid Hubで設定出来るVRM0のライセンスから表示テキストを返す
8+
* @param license
9+
* @param property
10+
* @returns
11+
*/
12+
export const getHubVrm0LicenseValue = (license: CharacterModelLicenseSerializer, property: LicenseProperty): string => {
13+
const status = license[property];
14+
15+
if (status === 'default') return '未設定';
16+
17+
switch (property) {
18+
case 'characterization_allowed_user':
19+
return status === 'everyone' ? 'OK' : 'NG';
20+
case 'personal_commercial_use':
21+
if (status === 'profit') return 'OK';
22+
if (status === 'nonprofit') return '非営利のみ';
23+
return 'NG';
24+
case 'credit':
25+
return status === 'necessary' ? '必要' : '不要';
26+
case 'modification':
27+
return status === 'allow' ? 'OK' : 'NG';
28+
case 'redistribution':
29+
return status === 'allow' ? 'OK' : 'NG';
30+
case 'sexual_expression':
31+
return status === 'allow' ? 'OK' : 'NG';
32+
case 'violent_expression':
33+
return status === 'allow' ? 'OK' : 'NG';
34+
case 'corporate_commercial_use':
35+
return status === 'allow' ? 'OK' : 'NG';
36+
default:
37+
return '未設定';
38+
}
39+
};
40+
41+
/**
42+
* VRoid Hubで設定出来るVRM0のライセンスからテキストの表示色の種類を返す
43+
* @param license
44+
* @param property
45+
* @returns
46+
*/
47+
export const getHubVrm0LicenseVariant = (
48+
license: CharacterModelLicenseSerializer,
49+
property: LicenseProperty,
50+
): 'default' | 'allow' | 'bold' => {
51+
const status = license[property];
52+
53+
switch (property) {
54+
case 'characterization_allowed_user':
55+
return status === 'everyone' ? 'allow' : 'default';
56+
case 'personal_commercial_use':
57+
return status === 'profit' || status === 'nonprofit' ? 'allow' : 'default';
58+
case 'credit':
59+
return status === 'necessary' ? 'bold' : 'default';
60+
case 'modification':
61+
return status === 'allow' ? 'allow' : 'default';
62+
case 'redistribution':
63+
return status === 'allow' ? 'allow' : 'default';
64+
case 'sexual_expression':
65+
return status === 'allow' ? 'allow' : 'default';
66+
case 'violent_expression':
67+
return status === 'allow' ? 'allow' : 'default';
68+
case 'corporate_commercial_use':
69+
return status === 'allow' ? 'allow' : 'default';
70+
default:
71+
return 'default';
72+
}
73+
};
74+
75+
type vrm1MetaProperty = keyof VRM1Meta | 'personalCommercialUse' | 'modificationRedistribution';
76+
77+
/**
78+
* VRM1.0のライセンスから表示テキストを返す
79+
* @param vrm1Meta
80+
* @param property
81+
* @returns
82+
*/
83+
export const getVrm1LicenseValue = (vrm1Meta: VRM1Meta, property: vrm1MetaProperty) => {
84+
//「 個人の商用利用」は法人利用とプロパティが共用のため、commercialUsageの値を参照し判定する
85+
if (property === 'personalCommercialUse') {
86+
const status = vrm1Meta.commercialUsage;
87+
if (status == null) return '未設定';
88+
89+
return status === 'corporation' || status === 'personalProfit' ? 'OK' : 'NG';
90+
}
91+
92+
// 「改変物の再配布」は改変とプロパティが共用のため、modificationの値を参照し判定する
93+
if (property === 'modificationRedistribution') {
94+
const status = vrm1Meta.modification;
95+
if (status == null) return '未設定';
96+
97+
return status === 'allowModificationRedistribution' ? 'OK' : 'NG';
98+
}
99+
100+
const status = vrm1Meta[property];
101+
if (status == null) return '未設定';
102+
103+
switch (property) {
104+
case 'avatarPermission':
105+
return status === 'everyone' ? 'OK' : 'NG';
106+
case 'allowExcessivelyViolentUsage':
107+
return status === true ? 'OK' : 'NG';
108+
case 'allowExcessivelySexualUsage':
109+
return status === true ? 'OK' : 'NG';
110+
case 'allowPoliticalOrReligiousUsage':
111+
return status === true ? 'OK' : 'NG';
112+
case 'allowAntisocialOrHateUsage':
113+
return status === true ? 'OK' : 'NG';
114+
case 'commercialUsage':
115+
return status === 'corporation' ? 'OK' : 'NG';
116+
case 'allowRedistribution':
117+
return status === true ? 'OK' : 'NG';
118+
case 'modification':
119+
return status === 'allowModification' || status === 'allowModificationRedistribution' ? 'OK' : 'NG';
120+
case 'creditNotation':
121+
return status === 'required' ? '必要' : '不要';
122+
default:
123+
return '未設定';
124+
}
125+
};
126+
127+
/**
128+
* VRM1.0のライセンスからテキストの表示色の種類を返す
129+
* @param vrm1Meta
130+
* @param property
131+
* @returns
132+
*/
133+
export const getVrm1LicenseVariant = (vrm1Meta: VRM1Meta, property: vrm1MetaProperty): 'default' | 'allow' | 'bold' => {
134+
//「 個人の商用利用」は法人利用とプロパティが共用のため、commercialUsageの値を参照し判定する
135+
if (property === 'personalCommercialUse') {
136+
const status = vrm1Meta.commercialUsage;
137+
if (status == null) return 'default';
138+
139+
return status === 'corporation' || status === 'personalProfit' ? 'allow' : 'default';
140+
}
141+
142+
// 「改変物の再配布」は改変とプロパティが共用のため、modificationの値を参照し判定する
143+
if (property === 'modificationRedistribution') {
144+
const status = vrm1Meta.modification;
145+
if (status == null) return 'default';
146+
147+
return status === 'allowModificationRedistribution' ? 'allow' : 'default';
148+
}
149+
150+
const status = vrm1Meta[property];
151+
if (status == null) return 'default';
152+
153+
switch (property) {
154+
case 'avatarPermission':
155+
return status === 'everyone' ? 'allow' : 'default';
156+
case 'allowExcessivelyViolentUsage':
157+
return status === true ? 'allow' : 'default';
158+
case 'allowExcessivelySexualUsage':
159+
return status === true ? 'allow' : 'default';
160+
case 'allowPoliticalOrReligiousUsage':
161+
return status === true ? 'allow' : 'default';
162+
case 'allowAntisocialOrHateUsage':
163+
return status === true ? 'allow' : 'default';
164+
case 'commercialUsage':
165+
return status === 'corporation' ? 'allow' : 'default';
166+
case 'allowRedistribution':
167+
return status === true ? 'allow' : 'default';
168+
case 'modification':
169+
return status === 'allowModification' || status === 'allowModificationRedistribution' ? 'allow' : 'default';
170+
case 'creditNotation':
171+
return status === 'required' ? 'bold' : 'default';
172+
default:
173+
return 'default';
174+
}
175+
};

0 commit comments

Comments
 (0)