studio/src/editor/TerrainPanel.module.css
МИН 31adbf151b Initial public release: Студия Рублокса v1.0
Open-source веб-студия для создания игр Рублокса, двойная лицензия
AGPL-3.0 + Коммерческая.

Главное:
- Vite 5 + React 18 + Babylon 7.54.3 + Monaco Editor + Colyseus 0.16
- Самодостаточный движок ~28к строк (66 файлов): BlockManager,
  TerrainVoxelBuilder, ModelManager, DecoManager, PlayerController,
  ScriptSandboxWorker, MultiplayerSync, 30+ GD-гейммодов
- Главный редактор KubikonEditor (~37к строк) + панели, ScriptEditor (Monaco)
- Витрина игр (KubikonFeed, KubikonStudio, KubikonDocs, KubikonLearn)
- Geometry Dash sub-app (GdMenu, GdShop, GdRules, GdCoverArt)
- 10 admin-preview каталогов для дизайнеров (скины, музыка, порталы и т.д.)
- Конфигурируемый бэкенд через VITE_API_BASE — работает со staging
  (dev-api.rublox.pro) без настройки
- Standalone-режим (VITE_STANDALONE=true) — открыть пустой редактор без бэка
- Полная документация (на русском): README, ARCHITECTURE, CONTRIBUTING,
  SECURITY, CHANGELOG
- ESLint + Prettier + EditorConfig
- Legal: LICENSE (AGPL-3.0), LICENSE-COMMERCIAL.md, CLA.md, COPYRIGHT.md
- Issue templates: bug_report, feature_request, security_disclosure

Перед публикацией:
- Все импорты из minecraftia заменены на локальные
- Все хардкоды URL (minecraftia-school.ru) и внутренних IP убраны → env
- Admin-эндпоинты Kubikon3DService вырезаны (остаются в приватном репо)
- AdminKubikonModeration не публикуется (модерация — в team.rublox.pro)
- 93 МБ ассетов public/kubikon-assets вынесены в .gitignore
  (раздаются через release artifact)
2026-05-27 23:41:10 +03:00

302 lines
7.1 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* TerrainPanel.module.css
* Стили левой панели редактора ландшафта. Подгоняется под светлую тему
* Кубикона (тот же набор --bg-dark / --border / --accent / --text что у
* остальных панелей в KubikonEditor.module.css).
*
* Дизайн — копия Roblox Studio Terrain Editor (сетка 4 кнопки в ряд,
* иконка + подпись, активная кнопка подсвечивается accent-цветом).
*/
.panel {
flex: 1;
display: flex;
flex-direction: column;
min-height: 0;
overflow-y: auto;
overflow-x: hidden;
background: var(--bg-dark);
color: var(--text);
font-size: 12px;
}
/* === Заголовок === */
.header {
padding: 12px 14px 10px;
border-bottom: 1px solid var(--border);
background: linear-gradient(180deg, var(--bg-dark) 0%, var(--bg-darkest) 100%);
}
.headerTitle {
font-size: 14px;
font-weight: 700;
color: var(--text);
margin-bottom: 2px;
}
.headerHint {
font-size: 11px;
color: var(--text-dim);
}
/* === Сетка инструментов — 4 в ряд === */
.toolsGrid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 6px;
padding: 12px;
}
/* Одна кнопка-инструмент. Вертикальная: иконка сверху, подпись снизу. */
.toolBtn {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
gap: 4px;
padding: 8px 4px 6px;
background: transparent;
border: 1px solid transparent;
border-radius: 6px;
color: var(--text);
cursor: pointer;
transition: background 0.12s, border-color 0.12s, color 0.12s;
user-select: none;
-webkit-user-select: none;
}
.toolBtn:hover {
background: var(--bg-darkest);
border-color: var(--border);
}
.toolBtnActive {
background: rgba(51, 87, 255, 0.10); /* accent с альфой */
border-color: var(--accent);
color: var(--accent);
}
.toolBtnActive:hover {
background: rgba(51, 87, 255, 0.14);
}
.toolIcon {
width: 28px;
height: 28px;
display: flex;
align-items: center;
justify-content: center;
color: inherit;
}
.toolLabel {
font-size: 10.5px;
text-align: center;
line-height: 1.1;
color: inherit;
word-break: break-word;
white-space: normal;
}
/* === Разделитель между секциями === */
.divider {
height: 1px;
margin: 4px 12px;
background: var(--border);
}
/* === Общая секция === */
.section {
padding: 10px 12px 12px;
}
.sectionTitle {
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--text-dim);
margin-bottom: 8px;
}
/* === Палитра материалов (цветные плашки) === */
.materialsGrid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 4px;
}
.matBtn {
position: relative;
aspect-ratio: 1 / 1;
border: 2px solid transparent;
border-radius: 5px;
cursor: pointer;
overflow: hidden;
transition: transform 0.1s, border-color 0.1s, box-shadow 0.1s;
padding: 0;
}
.matBtn:hover {
transform: translateY(-1px);
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
}
.matBtnActive {
border-color: var(--accent);
box-shadow: 0 0 0 2px rgba(51, 87, 255, 0.20);
}
/* Превью текстуры — заполняет плашку. Pixel-art (image-rendering: pixelated)
* для sharp-стиля Kenney-pack, без bilinear-размытия при увеличении 32→размер. */
.matPreview {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
image-rendering: pixelated;
image-rendering: -moz-crisp-edges;
-ms-interpolation-mode: nearest-neighbor;
pointer-events: none;
}
/* Подпись материала — поверх плашки, по нижнему краю, читаемый текст */
.matLabel {
position: absolute;
left: 0;
right: 0;
bottom: 0;
font-size: 9.5px;
text-align: center;
color: #ffffff;
padding: 2px 0;
background: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.55));
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
line-height: 1.1;
}
/* === Ряды slider'ов (Размер / Сила) === */
.row {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 8px;
}
.row:last-child {
margin-bottom: 0;
}
.rowLabel {
flex: 0 0 50px;
font-size: 11px;
color: var(--text-dim);
}
.slider {
flex: 1;
height: 4px;
cursor: pointer;
}
.rowValue {
flex: 0 0 28px;
text-align: right;
font-size: 11px;
font-variant-numeric: tabular-nums;
color: var(--text);
}
/* === Переключатель формы кисти === */
.shapeBtns {
display: flex;
gap: 4px;
}
.shapeBtn {
width: 28px;
height: 26px;
background: var(--bg-darkest);
border: 1px solid var(--border);
border-radius: 5px;
color: var(--text);
cursor: pointer;
font-size: 14px;
line-height: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 0;
transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.shapeBtn:hover {
border-color: var(--accent);
}
.shapeBtnActive {
background: rgba(51, 87, 255, 0.10);
border-color: var(--accent);
color: var(--accent);
}
/* === Чекбоксы опций === */
.checkRow {
display: flex;
align-items: center;
gap: 8px;
padding: 4px 0;
font-size: 12px;
color: var(--text);
cursor: pointer;
user-select: none;
-webkit-user-select: none;
}
.checkRow input[type="checkbox"] {
margin: 0;
cursor: pointer;
accent-color: var(--accent);
}
/* === Действия (Undo/Redo/Очистить) === */
.actionsRow {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 6px;
margin-bottom: 6px;
}
.actionBtn {
padding: 7px 10px;
background: var(--bg-darkest);
border: 1px solid var(--border);
border-radius: 6px;
color: var(--text);
cursor: pointer;
font-size: 12px;
font-weight: 600;
transition: background 0.12s, border-color 0.12s, color 0.12s;
user-select: none;
-webkit-user-select: none;
text-align: center;
}
.actionBtn:hover {
background: var(--bg-dark);
border-color: var(--accent);
color: var(--accent);
}
.actionBtn:active {
transform: translateY(1px);
}
.actionBtnDanger {
width: 100%;
color: #ff6b6b;
border-color: rgba(239, 68, 68, 0.3);
}
.actionBtnDanger:hover {
background: rgba(239, 68, 68, 0.16);
color: #ff6b6b;
border-color: #ef4444;
}
/* === Подсказка по hotkey'ам === */
.hotkeysHint {
padding: 10px 12px 14px;
font-size: 10.5px;
color: var(--text-dim);
line-height: 1.7;
border-top: 1px dashed var(--border);
margin-top: 4px;
}
.hotkeysHint b {
color: var(--text);
font-weight: 700;
padding: 1px 5px;
background: var(--bg-darkest);
border: 1px solid var(--border);
border-radius: 3px;
font-size: 10px;
margin-right: 4px;
}