обновление от 2025-09-24 для ветки 24sepTest
This commit is contained in:
60
migrate-colliders.js
Normal file
60
migrate-colliders.js
Normal file
@@ -0,0 +1,60 @@
|
||||
// Скрипт для выполнения миграции таблицы colliders
|
||||
// Файл: migrate-colliders.js
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { query } = require('./db');
|
||||
|
||||
async function runMigration() {
|
||||
try {
|
||||
console.log('🚀 Запуск миграции для создания таблицы colliders...');
|
||||
|
||||
// Читаем SQL файл миграции
|
||||
const migrationPath = path.join(__dirname, 'migrations', 'create_colliders_table.sql');
|
||||
const migrationSQL = fs.readFileSync(migrationPath, 'utf8');
|
||||
|
||||
// Выполняем миграцию
|
||||
await query(migrationSQL);
|
||||
|
||||
console.log('✅ Миграция успешно выполнена!');
|
||||
console.log('📊 Таблица colliders создана');
|
||||
|
||||
// Проверяем, что таблица создана
|
||||
const result = await query(`
|
||||
SELECT column_name, data_type, is_nullable
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = 'colliders'
|
||||
ORDER BY ordinal_position
|
||||
`);
|
||||
|
||||
console.log('📋 Структура таблицы colliders:');
|
||||
result.rows.forEach(row => {
|
||||
console.log(` - ${row.column_name}: ${row.data_type} (${row.is_nullable === 'YES' ? 'nullable' : 'not null'})`);
|
||||
});
|
||||
|
||||
// Проверяем индексы
|
||||
const indexes = await query(`
|
||||
SELECT indexname, indexdef
|
||||
FROM pg_indexes
|
||||
WHERE tablename = 'colliders'
|
||||
`);
|
||||
|
||||
console.log('🔍 Индексы:');
|
||||
indexes.rows.forEach(row => {
|
||||
console.log(` - ${row.indexname}`);
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Ошибка при выполнении миграции:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Запускаем миграцию
|
||||
runMigration().then(() => {
|
||||
console.log('🎉 Миграция завершена успешно!');
|
||||
process.exit(0);
|
||||
}).catch(error => {
|
||||
console.error('💥 Критическая ошибка:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
113
migrate-json-to-db.js
Normal file
113
migrate-json-to-db.js
Normal file
@@ -0,0 +1,113 @@
|
||||
// Скрипт для миграции коллайдеров из JSON в базу данных
|
||||
// Файл: migrate-json-to-db.js
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { query } = require('./db');
|
||||
|
||||
async function migrateJsonToDb() {
|
||||
try {
|
||||
console.log('🚀 Запуск миграции коллайдеров из JSON в базу данных...');
|
||||
|
||||
// Читаем JSON файл
|
||||
const jsonPath = path.join(__dirname, 'public', 'colliders_city_1.json');
|
||||
|
||||
if (!fs.existsSync(jsonPath)) {
|
||||
console.log('❌ JSON файл не найден:', jsonPath);
|
||||
return;
|
||||
}
|
||||
|
||||
const jsonContent = fs.readFileSync(jsonPath, 'utf8');
|
||||
const data = JSON.parse(jsonContent);
|
||||
|
||||
if (!data.colliders || !Array.isArray(data.colliders)) {
|
||||
console.log('❌ Неверный формат JSON файла');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`📊 Найдено ${data.colliders.length} коллайдеров в JSON файле`);
|
||||
|
||||
// Начинаем транзакцию
|
||||
await query('BEGIN');
|
||||
|
||||
// Очищаем существующие коллайдеры для города 1
|
||||
await query('DELETE FROM colliders WHERE city_id = $1', [1]);
|
||||
console.log('🗑️ Очищены существующие коллайдеры для города 1');
|
||||
|
||||
// Вставляем коллайдеры из JSON
|
||||
let insertedCount = 0;
|
||||
for (const collider of data.colliders) {
|
||||
try {
|
||||
await query(`
|
||||
INSERT INTO colliders (
|
||||
city_id, type,
|
||||
position_x, position_y, position_z,
|
||||
rotation_x, rotation_y, rotation_z,
|
||||
scale_x, scale_y, scale_z,
|
||||
color_r, color_g, color_b,
|
||||
opacity
|
||||
) VALUES (
|
||||
$1, $2,
|
||||
$3, $4, $5,
|
||||
$6, $7, $8,
|
||||
$9, $10, $11,
|
||||
$12, $13, $14,
|
||||
$15
|
||||
)
|
||||
`, [
|
||||
1, // city_id
|
||||
collider.type || 'box',
|
||||
collider.position?.x || 0,
|
||||
collider.position?.y || 0,
|
||||
collider.position?.z || 0,
|
||||
collider.rotation?.x || 0,
|
||||
collider.rotation?.y || 0,
|
||||
collider.rotation?.z || 0,
|
||||
collider.scale?.x || 1,
|
||||
collider.scale?.y || 1,
|
||||
collider.scale?.z || 1,
|
||||
collider.color?.r || 1,
|
||||
collider.color?.g || 0,
|
||||
collider.color?.b || 0,
|
||||
collider.opacity || 0.3
|
||||
]);
|
||||
|
||||
insertedCount++;
|
||||
console.log(`✅ Коллайдер ${insertedCount} мигрирован:`, {
|
||||
type: collider.type,
|
||||
position: collider.position,
|
||||
color: collider.color
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error(`❌ Ошибка при миграции коллайдера ${insertedCount + 1}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Подтверждаем транзакцию
|
||||
await query('COMMIT');
|
||||
|
||||
console.log(`🎉 Миграция завершена успешно!`);
|
||||
console.log(`📊 Мигрировано ${insertedCount} коллайдеров из JSON в базу данных`);
|
||||
|
||||
// Проверяем результат
|
||||
const result = await query('SELECT COUNT(*) as count FROM colliders WHERE city_id = $1', [1]);
|
||||
console.log(`🔍 Проверка: в БД теперь ${result.rows[0].count} коллайдеров для города 1`);
|
||||
|
||||
} catch (error) {
|
||||
// Откатываем транзакцию в случае ошибки
|
||||
await query('ROLLBACK');
|
||||
console.error('💥 Ошибка при миграции:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Запускаем миграцию
|
||||
migrateJsonToDb().then(() => {
|
||||
console.log('🚀 Миграция JSON -> БД завершена!');
|
||||
process.exit(0);
|
||||
}).catch(error => {
|
||||
console.error('💥 Критическая ошибка:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
79
migrations/create_colliders_table.sql
Normal file
79
migrations/create_colliders_table.sql
Normal file
@@ -0,0 +1,79 @@
|
||||
-- Миграция для создания таблицы colliders
|
||||
-- Файл: migrations/create_colliders_table.sql
|
||||
|
||||
-- Создание таблицы colliders
|
||||
CREATE TABLE IF NOT EXISTS colliders (
|
||||
id SERIAL PRIMARY KEY,
|
||||
city_id INTEGER NOT NULL,
|
||||
type VARCHAR(20) NOT NULL CHECK (type IN ('box', 'circle', 'capsule')),
|
||||
|
||||
-- Позиция
|
||||
position_x DECIMAL(15, 6) NOT NULL DEFAULT 0,
|
||||
position_y DECIMAL(15, 6) NOT NULL DEFAULT 0,
|
||||
position_z DECIMAL(15, 6) NOT NULL DEFAULT 0,
|
||||
|
||||
-- Поворот (в радианах)
|
||||
rotation_x DECIMAL(15, 6) NOT NULL DEFAULT 0,
|
||||
rotation_y DECIMAL(15, 6) NOT NULL DEFAULT 0,
|
||||
rotation_z DECIMAL(15, 6) NOT NULL DEFAULT 0,
|
||||
|
||||
-- Масштаб
|
||||
scale_x DECIMAL(15, 6) NOT NULL DEFAULT 1,
|
||||
scale_y DECIMAL(15, 6) NOT NULL DEFAULT 1,
|
||||
scale_z DECIMAL(15, 6) NOT NULL DEFAULT 1,
|
||||
|
||||
-- Цвет (RGB 0-1)
|
||||
color_r DECIMAL(3, 2) NOT NULL DEFAULT 1.0 CHECK (color_r >= 0 AND color_r <= 1),
|
||||
color_g DECIMAL(3, 2) NOT NULL DEFAULT 0.0 CHECK (color_g >= 0 AND color_g <= 1),
|
||||
color_b DECIMAL(3, 2) NOT NULL DEFAULT 0.0 CHECK (color_b >= 0 AND color_b <= 1),
|
||||
|
||||
-- Прозрачность (0-1)
|
||||
opacity DECIMAL(3, 2) NOT NULL DEFAULT 0.3 CHECK (opacity >= 0 AND opacity <= 1),
|
||||
|
||||
-- Метаданные
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
-- Индексы для быстрого поиска
|
||||
CONSTRAINT fk_colliders_city FOREIGN KEY (city_id) REFERENCES cities(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- Создание индексов для оптимизации запросов
|
||||
CREATE INDEX IF NOT EXISTS idx_colliders_city_id ON colliders(city_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_colliders_type ON colliders(type);
|
||||
CREATE INDEX IF NOT EXISTS idx_colliders_position ON colliders(position_x, position_y, position_z);
|
||||
|
||||
-- Создание функции для автоматического обновления updated_at
|
||||
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = CURRENT_TIMESTAMP;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ language 'plpgsql';
|
||||
|
||||
-- Создание триггера для автоматического обновления updated_at
|
||||
CREATE TRIGGER update_colliders_updated_at
|
||||
BEFORE UPDATE ON colliders
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
-- Комментарии к таблице и колонкам
|
||||
COMMENT ON TABLE colliders IS 'Таблица коллайдеров для городов';
|
||||
COMMENT ON COLUMN colliders.city_id IS 'ID города, к которому принадлежит коллайдер';
|
||||
COMMENT ON COLUMN colliders.type IS 'Тип коллайдера: box, circle, capsule';
|
||||
COMMENT ON COLUMN colliders.position_x IS 'X координата позиции';
|
||||
COMMENT ON COLUMN colliders.position_y IS 'Y координата позиции';
|
||||
COMMENT ON COLUMN colliders.position_z IS 'Z координата позиции';
|
||||
COMMENT ON COLUMN colliders.rotation_x IS 'X компонент поворота (радианы)';
|
||||
COMMENT ON COLUMN colliders.rotation_y IS 'Y компонент поворота (радианы)';
|
||||
COMMENT ON COLUMN colliders.rotation_z IS 'Z компонент поворота (радианы)';
|
||||
COMMENT ON COLUMN colliders.scale_x IS 'X компонент масштаба';
|
||||
COMMENT ON COLUMN colliders.scale_y IS 'Y компонент масштаба';
|
||||
COMMENT ON COLUMN colliders.scale_z IS 'Z компонент масштаба';
|
||||
COMMENT ON COLUMN colliders.color_r IS 'Красный компонент цвета (0-1)';
|
||||
COMMENT ON COLUMN colliders.color_g IS 'Зеленый компонент цвета (0-1)';
|
||||
COMMENT ON COLUMN colliders.color_b IS 'Синий компонент цвета (0-1)';
|
||||
COMMENT ON COLUMN colliders.opacity IS 'Прозрачность (0-1)';
|
||||
COMMENT ON COLUMN colliders.created_at IS 'Время создания записи';
|
||||
COMMENT ON COLUMN colliders.updated_at IS 'Время последнего обновления записи';
|
||||
@@ -1,96 +1,6 @@
|
||||
{
|
||||
"colliders": [
|
||||
{
|
||||
"type": "box",
|
||||
"position": {
|
||||
"x": -15.894407457818183,
|
||||
"y": -98.46844400767294,
|
||||
"z": -74.33953239204133
|
||||
},
|
||||
"rotation": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"scale": {
|
||||
"x": 3.8820412781839853,
|
||||
"y": 1.9275391013076184,
|
||||
"z": 0.020423580261430187
|
||||
},
|
||||
"color": {
|
||||
"r": 0.2,
|
||||
"g": 1,
|
||||
"b": 0.1
|
||||
},
|
||||
"opacity": 1
|
||||
},
|
||||
{
|
||||
"type": "box",
|
||||
"position": {
|
||||
"x": -19.682621880668748,
|
||||
"y": -98.44103033988638,
|
||||
"z": -71.00143351764237
|
||||
},
|
||||
"rotation": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"scale": {
|
||||
"x": 0.021,
|
||||
"y": 1.9,
|
||||
"z": 3.8
|
||||
},
|
||||
"color": {
|
||||
"r": 0.2,
|
||||
"g": 1,
|
||||
"b": 0.1
|
||||
},
|
||||
"opacity": 1
|
||||
},
|
||||
{
|
||||
"type": "box",
|
||||
"position": {
|
||||
"x": -16.32989632517387,
|
||||
"y": -98.91158756288065,
|
||||
"z": -66.6280016541835
|
||||
},
|
||||
"rotation": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"scale": {
|
||||
"x": 1,
|
||||
"y": 2,
|
||||
"z": 1
|
||||
},
|
||||
"color": {
|
||||
"r": 0.2,
|
||||
"g": 1,
|
||||
"b": 0.1
|
||||
},
|
||||
"opacity": 1
|
||||
},
|
||||
{
|
||||
"type": "box",
|
||||
"position": {
|
||||
"x": 3.1476200534247045,
|
||||
"y": -0.5512983469988768,
|
||||
"z": -0.4395577458346196
|
||||
},
|
||||
"rotation": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"scale": {
|
||||
"x": 0.5301919909798507,
|
||||
"y": 2.40369930235243007,
|
||||
"z": 1.2663514332721553
|
||||
},
|
||||
"color": {},
|
||||
"opacity": 0.3
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
public/models/interiors/Apartment.glb
Normal file
BIN
public/models/interiors/Apartment.glb
Normal file
Binary file not shown.
BIN
public/models/interiors/Apartment2.glb
Normal file
BIN
public/models/interiors/Apartment2.glb
Normal file
Binary file not shown.
BIN
public/models/interiors/HouseInterior.glb
Normal file
BIN
public/models/interiors/HouseInterior.glb
Normal file
Binary file not shown.
@@ -1 +1 @@
|
||||
{"time":"2025-10-30T05:20:24.552Z","lastReal":1758297743627}
|
||||
{"time":"2025-12-05T08:30:14.152Z","lastReal":1758687967327}
|
||||
247
server.js
247
server.js
@@ -1666,54 +1666,237 @@ app.get('/api/cities', authenticate, async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// API endpoint для сохранения коллайдеров города
|
||||
app.post('/api/colliders/city/:cityId', authenticate, async (req, res) => {
|
||||
const cityId = req.params.cityId;
|
||||
const collidersData = req.body;
|
||||
// API endpoint для получения коллайдеров города из базы данных
|
||||
app.get('/api/colliders/city/:cityId', authenticate, async (req, res) => {
|
||||
const cityId = parseInt(req.params.cityId, 10);
|
||||
|
||||
try {
|
||||
// Сохраняем коллайдеры в JSON файл
|
||||
const fileName = `colliders_city_${cityId}.json`;
|
||||
const filePath = pathLib.join(__dirname, 'public', fileName);
|
||||
const { rows } = await db.query(`
|
||||
SELECT
|
||||
id,
|
||||
type,
|
||||
position_x as "position.x",
|
||||
position_y as "position.y",
|
||||
position_z as "position.z",
|
||||
rotation_x as "rotation.x",
|
||||
rotation_y as "rotation.y",
|
||||
rotation_z as "rotation.z",
|
||||
scale_x as "scale.x",
|
||||
scale_y as "scale.y",
|
||||
scale_z as "scale.z",
|
||||
color_r as "color.r",
|
||||
color_g as "color.g",
|
||||
color_b as "color.b",
|
||||
opacity,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM colliders
|
||||
WHERE city_id = $1
|
||||
ORDER BY created_at ASC
|
||||
`, [cityId]);
|
||||
|
||||
// Создаем директорию если не существует
|
||||
await fs.promises.mkdir(pathLib.dirname(filePath), { recursive: true });
|
||||
// Преобразуем данные в формат, ожидаемый фронтендом
|
||||
const colliders = rows.map(row => ({
|
||||
id: row.id,
|
||||
type: row.type,
|
||||
position: {
|
||||
x: parseFloat(row["position.x"]),
|
||||
y: parseFloat(row["position.y"]),
|
||||
z: parseFloat(row["position.z"])
|
||||
},
|
||||
rotation: {
|
||||
x: parseFloat(row["rotation.x"]),
|
||||
y: parseFloat(row["rotation.y"]),
|
||||
z: parseFloat(row["rotation.z"])
|
||||
},
|
||||
scale: {
|
||||
x: parseFloat(row["scale.x"]),
|
||||
y: parseFloat(row["scale.y"]),
|
||||
z: parseFloat(row["scale.z"])
|
||||
},
|
||||
color: {
|
||||
r: parseFloat(row["color.r"]),
|
||||
g: parseFloat(row["color.g"]),
|
||||
b: parseFloat(row["color.b"])
|
||||
},
|
||||
opacity: parseFloat(row.opacity),
|
||||
created_at: row.created_at,
|
||||
updated_at: row.updated_at
|
||||
}));
|
||||
|
||||
// Записываем данные в файл
|
||||
await fs.promises.writeFile(filePath, JSON.stringify(collidersData, null, 2), 'utf8');
|
||||
|
||||
console.log(`Коллайдеры для города ${cityId} сохранены в ${fileName}`);
|
||||
res.json({ success: true, message: 'Коллайдеры сохранены успешно' });
|
||||
res.json({ colliders });
|
||||
} catch (error) {
|
||||
console.error('Ошибка сохранения коллайдеров:', error);
|
||||
console.error('Ошибка получения коллайдеров из БД:', error);
|
||||
res.status(500).json({ error: 'Ошибка получения коллайдеров' });
|
||||
}
|
||||
});
|
||||
|
||||
// API endpoint для сохранения коллайдеров города в базу данных
|
||||
app.post('/api/colliders/city/:cityId', authenticate, async (req, res) => {
|
||||
const cityId = parseInt(req.params.cityId, 10);
|
||||
const { colliders } = req.body;
|
||||
|
||||
if (!Array.isArray(colliders)) {
|
||||
return res.status(400).json({ error: 'Invalid colliders data' });
|
||||
}
|
||||
|
||||
try {
|
||||
// Начинаем транзакцию
|
||||
await db.query('BEGIN');
|
||||
|
||||
// Разделяем коллайдеры на новые и существующие
|
||||
const newColliders = colliders.filter(c => !c.id);
|
||||
const existingColliders = colliders.filter(c => c.id);
|
||||
|
||||
console.log(`💾 Сохраняем: ${existingColliders.length} существующих, ${newColliders.length} новых коллайдеров`);
|
||||
|
||||
// Обновляем существующие коллайдеры
|
||||
for (const collider of existingColliders) {
|
||||
await db.query(`
|
||||
UPDATE colliders SET
|
||||
type = $2,
|
||||
position_x = $3, position_y = $4, position_z = $5,
|
||||
rotation_x = $6, rotation_y = $7, rotation_z = $8,
|
||||
scale_x = $9, scale_y = $10, scale_z = $11,
|
||||
color_r = $12, color_g = $13, color_b = $14,
|
||||
opacity = $15,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $1 AND city_id = $16
|
||||
`, [
|
||||
collider.id,
|
||||
collider.type,
|
||||
collider.position?.x || 0,
|
||||
collider.position?.y || 0,
|
||||
collider.position?.z || 0,
|
||||
collider.rotation?.x || 0,
|
||||
collider.rotation?.y || 0,
|
||||
collider.rotation?.z || 0,
|
||||
collider.scale?.x || 1,
|
||||
collider.scale?.y || 1,
|
||||
collider.scale?.z || 1,
|
||||
collider.color?.r || 1,
|
||||
collider.color?.g || 0,
|
||||
collider.color?.b || 0,
|
||||
collider.opacity || 0.3,
|
||||
cityId
|
||||
]);
|
||||
}
|
||||
|
||||
// Вставляем новые коллайдеры
|
||||
for (const collider of newColliders) {
|
||||
await db.query(`
|
||||
INSERT INTO colliders (
|
||||
city_id, type,
|
||||
position_x, position_y, position_z,
|
||||
rotation_x, rotation_y, rotation_z,
|
||||
scale_x, scale_y, scale_z,
|
||||
color_r, color_g, color_b,
|
||||
opacity
|
||||
) VALUES (
|
||||
$1, $2,
|
||||
$3, $4, $5,
|
||||
$6, $7, $8,
|
||||
$9, $10, $11,
|
||||
$12, $13, $14,
|
||||
$15
|
||||
)
|
||||
`, [
|
||||
cityId,
|
||||
collider.type,
|
||||
collider.position?.x || 0,
|
||||
collider.position?.y || 0,
|
||||
collider.position?.z || 0,
|
||||
collider.rotation?.x || 0,
|
||||
collider.rotation?.y || 0,
|
||||
collider.rotation?.z || 0,
|
||||
collider.scale?.x || 1,
|
||||
collider.scale?.y || 1,
|
||||
collider.scale?.z || 1,
|
||||
collider.color?.r || 1,
|
||||
collider.color?.g || 0,
|
||||
collider.color?.b || 0,
|
||||
collider.opacity || 0.3
|
||||
]);
|
||||
}
|
||||
|
||||
// Подтверждаем транзакцию
|
||||
await db.query('COMMIT');
|
||||
|
||||
console.log(`✅ Коллайдеры для города ${cityId} сохранены в БД (${existingColliders.length} обновлено, ${newColliders.length} новых)`);
|
||||
res.json({ success: true, message: 'Коллайдеры сохранены успешно', updated: existingColliders.length, created: newColliders.length });
|
||||
|
||||
} catch (error) {
|
||||
// Откатываем транзакцию в случае ошибки
|
||||
await db.query('ROLLBACK');
|
||||
console.error('Ошибка сохранения коллайдеров в БД:', error);
|
||||
res.status(500).json({ error: 'Ошибка сохранения коллайдеров' });
|
||||
}
|
||||
});
|
||||
|
||||
// API endpoint для получения коллайдеров города
|
||||
app.get('/api/colliders/city/:cityId', authenticate, async (req, res) => {
|
||||
const cityId = req.params.cityId;
|
||||
// API endpoint для обновления отдельного коллайдера
|
||||
app.put('/api/colliders/:colliderId', authenticate, async (req, res) => {
|
||||
const colliderId = parseInt(req.params.colliderId, 10);
|
||||
const collider = req.body;
|
||||
|
||||
try {
|
||||
const fileName = `colliders_city_${cityId}.json`;
|
||||
const filePath = pathLib.join(__dirname, 'public', fileName);
|
||||
const { rowCount } = await db.query(`
|
||||
UPDATE colliders SET
|
||||
type = $2,
|
||||
position_x = $3, position_y = $4, position_z = $5,
|
||||
rotation_x = $6, rotation_y = $7, rotation_z = $8,
|
||||
scale_x = $9, scale_y = $10, scale_z = $11,
|
||||
color_r = $12, color_g = $13, color_b = $14,
|
||||
opacity = $15,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $1
|
||||
`, [
|
||||
colliderId,
|
||||
collider.type,
|
||||
collider.position?.x || 0,
|
||||
collider.position?.y || 0,
|
||||
collider.position?.z || 0,
|
||||
collider.rotation?.x || 0,
|
||||
collider.rotation?.y || 0,
|
||||
collider.rotation?.z || 0,
|
||||
collider.scale?.x || 1,
|
||||
collider.scale?.y || 1,
|
||||
collider.scale?.z || 1,
|
||||
collider.color?.r || 1,
|
||||
collider.color?.g || 0,
|
||||
collider.color?.b || 0,
|
||||
collider.opacity || 0.3
|
||||
]);
|
||||
|
||||
// Проверяем существование файла
|
||||
try {
|
||||
await fs.promises.access(filePath);
|
||||
} catch (error) {
|
||||
// Файл не существует, возвращаем пустой массив
|
||||
return res.json({ colliders: [] });
|
||||
if (rowCount === 0) {
|
||||
return res.status(404).json({ error: 'Коллайдер не найден' });
|
||||
}
|
||||
|
||||
// Читаем файл
|
||||
const fileContent = await fs.promises.readFile(filePath, 'utf8');
|
||||
const data = JSON.parse(fileContent);
|
||||
console.log(`✅ Коллайдер ${colliderId} обновлен в БД`);
|
||||
res.json({ success: true, message: 'Коллайдер обновлен успешно' });
|
||||
|
||||
res.json(data);
|
||||
} catch (error) {
|
||||
console.error('Ошибка чтения коллайдеров:', error);
|
||||
res.status(500).json({ error: 'Ошибка чтения коллайдеров' });
|
||||
console.error('Ошибка обновления коллайдера в БД:', error);
|
||||
res.status(500).json({ error: 'Ошибка обновления коллайдера' });
|
||||
}
|
||||
});
|
||||
|
||||
// API endpoint для удаления отдельного коллайдера
|
||||
app.delete('/api/colliders/:colliderId', authenticate, async (req, res) => {
|
||||
const colliderId = parseInt(req.params.colliderId, 10);
|
||||
|
||||
try {
|
||||
const { rowCount } = await db.query('DELETE FROM colliders WHERE id = $1', [colliderId]);
|
||||
|
||||
if (rowCount === 0) {
|
||||
return res.status(404).json({ error: 'Коллайдер не найден' });
|
||||
}
|
||||
|
||||
console.log(`✅ Коллайдер ${colliderId} удален из БД`);
|
||||
res.json({ success: true, message: 'Коллайдер удален успешно' });
|
||||
|
||||
} catch (error) {
|
||||
console.error('Ошибка удаления коллайдера из БД:', error);
|
||||
res.status(500).json({ error: 'Ошибка удаления коллайдера' });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
179
src/Game.js
179
src/Game.js
@@ -616,6 +616,80 @@ function Game({ avatarUrl, gender }) {
|
||||
});
|
||||
};
|
||||
|
||||
// Функция для принудительной перезагрузки всех коллайдеров из базы данных
|
||||
window.reloadAllColliders = async () => {
|
||||
console.log('🔄 Принудительная перезагрузка всех коллайдеров...');
|
||||
try {
|
||||
// Перезагружаем коллизионные коллайдеры
|
||||
await loadCollidersFromJSON(1);
|
||||
console.log('✅ Коллизионные коллайдеры перезагружены');
|
||||
|
||||
// Перезагружаем визуальные коллайдеры
|
||||
await loadCustomCollidersForCity(1);
|
||||
console.log('✅ Визуальные коллайдеры перезагружены');
|
||||
|
||||
console.log('🎉 Все коллайдеры успешно перезагружены из базы данных');
|
||||
} catch (error) {
|
||||
console.error('❌ Ошибка при перезагрузке коллайдеров:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// Функция для проверки состояния коллайдеров в базе данных
|
||||
window.checkCollidersInDB = async () => {
|
||||
console.log('🔍 Проверяем коллайдеры в базе данных...');
|
||||
try {
|
||||
const token = localStorage.getItem('token');
|
||||
const response = await fetch('/api/colliders/city/1', {
|
||||
headers: { Authorization: `Bearer ${token}` }
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
console.log('📊 Коллайдеры в БД:', data.colliders?.length || 0, 'штук');
|
||||
console.log('🔍 Данные из БД:', data);
|
||||
|
||||
// Сравниваем с текущими коллайдерами в игре
|
||||
console.log('📊 Коллизионные коллайдеры в игре:', jsonCollidersRef.current?.length || 0, 'штук');
|
||||
console.log('📊 Визуальные коллайдеры в игре:', visualCollidersRef.current?.length || 0, 'штук');
|
||||
|
||||
return data;
|
||||
} else {
|
||||
console.error('❌ Ошибка загрузки коллайдеров из БД:', response.status);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Ошибка при проверке коллайдеров в БД:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// Функция для обновления прозрачности всех коллизионных объектов
|
||||
window.updateColliderOpacity = (opacity) => {
|
||||
console.log('👁️ Обновляем прозрачность всех коллизионных объектов:', opacity);
|
||||
obstacles.forEach(obstacle => {
|
||||
if (obstacle.mesh && obstacle.mesh.userData.isCustomCollider) {
|
||||
obstacle.mesh.material.opacity = opacity;
|
||||
if (opacity === 0) {
|
||||
obstacle.mesh.material.visible = false;
|
||||
obstacle.mesh.material.alphaTest = 0;
|
||||
} else {
|
||||
obstacle.mesh.material.visible = true;
|
||||
obstacle.mesh.material.alphaTest = 0.1;
|
||||
}
|
||||
}
|
||||
});
|
||||
console.log('✅ Прозрачность обновлена для', obstacles.length, 'коллизионных объектов');
|
||||
};
|
||||
|
||||
// Функция для включения/выключения отображения коллизионных объектов
|
||||
window.toggleColliderVisibility = (visible) => {
|
||||
console.log('👁️ Переключаем видимость коллизионных объектов:', visible);
|
||||
obstacles.forEach(obstacle => {
|
||||
if (obstacle.mesh && obstacle.mesh.userData.isCustomCollider) {
|
||||
obstacle.mesh.visible = visible;
|
||||
}
|
||||
});
|
||||
console.log('✅ Видимость коллизионных объектов:', visible ? 'включена' : 'выключена');
|
||||
};
|
||||
|
||||
window.setColliderColor = (r, g, b) => {
|
||||
console.log('🎨 Устанавливаем цвет коллайдеров:', { r, g, b });
|
||||
visualCollidersRef.current.forEach(collider => {
|
||||
@@ -1341,13 +1415,24 @@ function Game({ avatarUrl, gender }) {
|
||||
}
|
||||
};
|
||||
|
||||
// Функция для загрузки коллизионных данных из JSON
|
||||
// Функция для загрузки коллизионных данных из базы данных с fallback на JSON
|
||||
const loadCollidersFromJSON = async (cityId = 1) => {
|
||||
console.log('🔍 loadCollidersFromJSON вызвана для города:', cityId);
|
||||
try {
|
||||
const url = `/colliders_city_${cityId}.json`;
|
||||
console.log('🔍 Загружаем URL:', url);
|
||||
const response = await fetch(url);
|
||||
// Сначала пробуем загрузить из базы данных
|
||||
const token = localStorage.getItem('token');
|
||||
let response = await fetch(`/api/colliders/city/${cityId}`, {
|
||||
headers: { Authorization: `Bearer ${token}` }
|
||||
});
|
||||
|
||||
// Если новый API недоступен (500 ошибка), пробуем старый JSON API
|
||||
if (!response.ok && response.status === 500) {
|
||||
console.log('🔄 Новый API недоступен, пробуем старый JSON API...');
|
||||
const url = `/colliders_city_${cityId}.json`;
|
||||
console.log('🔍 Загружаем URL:', url);
|
||||
response = await fetch(url);
|
||||
}
|
||||
|
||||
console.log('🔍 Ответ сервера:', response.status, response.ok);
|
||||
|
||||
if (!response.ok) {
|
||||
@@ -1357,10 +1442,26 @@ function Game({ avatarUrl, gender }) {
|
||||
|
||||
const data = await response.json();
|
||||
console.log('🔍 Загруженные данные:', data);
|
||||
console.log('Загружены коллизионные данные:', data.colliders.length, 'объектов');
|
||||
|
||||
// Преобразуем JSON данные в Box3 объекты
|
||||
const colliderBoxes = data.colliders.map((colliderData, index) => {
|
||||
// Обрабатываем данные в зависимости от источника
|
||||
let collidersData;
|
||||
if (data.colliders) {
|
||||
// Данные из базы данных (уже в правильном формате)
|
||||
collidersData = data.colliders;
|
||||
console.log('📊 Загружены коллайдеры из базы данных:', collidersData.length, 'объектов');
|
||||
console.log('🔍 Пример коллайдера из БД:', collidersData[0]);
|
||||
} else if (Array.isArray(data)) {
|
||||
// Данные из JSON файла (прямой массив)
|
||||
collidersData = data;
|
||||
console.log('📄 Загружены коллайдеры из JSON файла:', collidersData.length, 'объектов');
|
||||
console.log('🔍 Пример коллайдера из JSON:', collidersData[0]);
|
||||
} else {
|
||||
console.warn('Неизвестный формат данных коллайдеров:', data);
|
||||
return [];
|
||||
}
|
||||
|
||||
// Преобразуем данные в Box3 объекты
|
||||
const colliderBoxes = collidersData.map((colliderData, index) => {
|
||||
const box = new THREE.Box3();
|
||||
|
||||
// Создаем центр бокса
|
||||
@@ -3316,12 +3417,44 @@ function Game({ avatarUrl, gender }) {
|
||||
|
||||
async function loadCustomCollidersForCity(cityIdParam) {
|
||||
try {
|
||||
const cityIdNum = Number(cityIdParam) || 0;
|
||||
const query = cityIdNum ? `?cityId=${encodeURIComponent(cityIdNum)}` : '';
|
||||
const res = await fetch(`/api/colliders${query}`, { cache: 'no-store', headers: { Authorization: `Bearer ${token}` } });
|
||||
if (!res.ok) return;
|
||||
const cityIdNum = Number(cityIdParam) || 1;
|
||||
console.log('🔍 loadCustomCollidersForCity для города:', cityIdNum);
|
||||
|
||||
// Сначала пробуем новый API с базой данных
|
||||
let res = await fetch(`/api/colliders/city/${cityIdNum}`, {
|
||||
cache: 'no-store',
|
||||
headers: { Authorization: `Bearer ${token}` }
|
||||
});
|
||||
|
||||
// Если новый API недоступен (500 ошибка), пробуем старый JSON API
|
||||
if (!res.ok && res.status === 500) {
|
||||
console.log('🔄 Новый API недоступен в loadCustomCollidersForCity, пробуем старый JSON API...');
|
||||
const query = cityIdNum ? `?cityId=${encodeURIComponent(cityIdNum)}` : '';
|
||||
res = await fetch(`/api/colliders${query}`, { cache: 'no-store', headers: { Authorization: `Bearer ${token}` } });
|
||||
}
|
||||
|
||||
if (!res.ok) {
|
||||
console.warn('Не удалось загрузить кастомные коллайдеры для города:', cityIdNum);
|
||||
return;
|
||||
}
|
||||
|
||||
const data = await res.json();
|
||||
const list = Array.isArray(data?.colliders) ? data.colliders : [];
|
||||
console.log('🔍 Загруженные данные кастомных коллайдеров:', data);
|
||||
|
||||
// Обрабатываем данные в зависимости от источника
|
||||
let list;
|
||||
if (data.colliders) {
|
||||
// Данные из базы данных
|
||||
list = data.colliders;
|
||||
console.log('📊 Загружены кастомные коллайдеры из базы данных:', list.length, 'объектов');
|
||||
} else if (Array.isArray(data)) {
|
||||
// Данные из JSON файла
|
||||
list = data;
|
||||
console.log('📄 Загружены кастомные коллайдеры из JSON файла:', list.length, 'объектов');
|
||||
} else {
|
||||
console.warn('Неизвестный формат данных кастомных коллайдеров:', data);
|
||||
return;
|
||||
}
|
||||
// Удаляем старые кастомные коллайдеры
|
||||
obstacles = obstacles.filter(o => {
|
||||
const keep = !o?.mesh?.userData?.isCustomCollider;
|
||||
@@ -3336,7 +3469,25 @@ function Game({ avatarUrl, gender }) {
|
||||
if (c.type === 'circle') geometry = new THREE.CylinderGeometry(1.5, 1.5, 2, 24);
|
||||
else if (c.type === 'capsule') geometry = new THREE.CapsuleGeometry(1, 2, 4, 12);
|
||||
else geometry = new THREE.BoxGeometry(2, 2, 2);
|
||||
const material = new THREE.MeshBasicMaterial({ color: 0x000000, transparent: true, opacity: 0.001, depthWrite: false });
|
||||
|
||||
// Используем прозрачность из базы данных
|
||||
const opacity = c.opacity !== undefined ? c.opacity : 0.001;
|
||||
const material = new THREE.MeshBasicMaterial({
|
||||
color: 0x000000,
|
||||
transparent: true,
|
||||
opacity: opacity,
|
||||
depthWrite: false
|
||||
});
|
||||
|
||||
// Если прозрачность 0, делаем материал невидимым
|
||||
if (opacity === 0) {
|
||||
material.visible = false;
|
||||
material.alphaTest = 0;
|
||||
} else {
|
||||
material.visible = true;
|
||||
material.alphaTest = 0.1;
|
||||
}
|
||||
|
||||
const mesh = new THREE.Mesh(geometry, material);
|
||||
const p = c.position || {}; const r = c.rotation || {}; const s = c.scale || {};
|
||||
mesh.position.set(p.x || 0, p.y || 0, p.z || 0);
|
||||
@@ -3348,7 +3499,7 @@ function Game({ avatarUrl, gender }) {
|
||||
});
|
||||
buildPathfindingGrid?.();
|
||||
} catch (e) {
|
||||
console.warn('Не удалось загрузить colliders.json', e);
|
||||
console.warn('Не удалось загрузить кастомные коллайдеры', e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,13 +52,32 @@ export default function EnhancedCollisionEditor() {
|
||||
|
||||
// Состояние для режима TransformControls
|
||||
const [transformMode, setTransformMode] = useState('translate'); // 'translate', 'rotate', 'scale'
|
||||
|
||||
// Состояние для автоматического сохранения
|
||||
const [autoSave, setAutoSave] = useState(true);
|
||||
const [lastSaved, setLastSaved] = useState(null);
|
||||
const autoSaveTimeoutRef = useRef(null);
|
||||
const [showWireframes, setShowWireframes] = useState(true); // Новое состояние для рамок
|
||||
|
||||
const colliderMaterial = useMemo(() => new THREE.MeshBasicMaterial({
|
||||
color: new THREE.Color(selectedColor.r, selectedColor.g, selectedColor.b),
|
||||
transparent: true,
|
||||
opacity: selectedOpacity,
|
||||
depthWrite: false
|
||||
}), [selectedColor, selectedOpacity]);
|
||||
const colliderMaterial = useMemo(() => {
|
||||
const material = new THREE.MeshBasicMaterial({
|
||||
color: new THREE.Color(selectedColor.r, selectedColor.g, selectedColor.b),
|
||||
transparent: true,
|
||||
opacity: selectedOpacity,
|
||||
depthWrite: false
|
||||
});
|
||||
|
||||
// Если прозрачность 0, делаем материал невидимым
|
||||
if (selectedOpacity === 0) {
|
||||
material.visible = false;
|
||||
material.alphaTest = 0;
|
||||
} else {
|
||||
material.visible = true;
|
||||
material.alphaTest = 0.1;
|
||||
}
|
||||
|
||||
return material;
|
||||
}, [selectedColor, selectedOpacity]);
|
||||
|
||||
const colliderEdgeMaterial = useMemo(() => new THREE.LineBasicMaterial({
|
||||
color: new THREE.Color(selectedColor.r, selectedColor.g, selectedColor.b)
|
||||
@@ -107,6 +126,17 @@ export default function EnhancedCollisionEditor() {
|
||||
transform.addEventListener('objectChange', () => {
|
||||
if (selected) {
|
||||
updateColliderData(selected);
|
||||
// Обновляем параметры в UI при изменении через TransformControls
|
||||
setColliderPosition({ x: selected.position.x, y: selected.position.y, z: selected.position.z });
|
||||
setColliderRotation({ x: selected.rotation.x, y: selected.rotation.y, z: selected.rotation.z });
|
||||
setColliderScale({ x: selected.scale.x, y: selected.scale.y, z: selected.scale.z });
|
||||
console.log('🔄 Параметры обновлены через TransformControls:', {
|
||||
position: selected.position,
|
||||
rotation: selected.rotation,
|
||||
scale: selected.scale
|
||||
});
|
||||
// Запускаем автоматическое сохранение
|
||||
triggerAutoSave();
|
||||
}
|
||||
});
|
||||
scene.add(transform);
|
||||
@@ -356,12 +386,21 @@ export default function EnhancedCollisionEditor() {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const token = localStorage.getItem('token');
|
||||
const response = await fetch(`/api/colliders/city/${cityId}`, {
|
||||
// Сначала пробуем новый API с базой данных
|
||||
let response = await fetch(`/api/colliders/city/${cityId}`, {
|
||||
headers: { Authorization: `Bearer ${token}` }
|
||||
});
|
||||
|
||||
// Если новый API недоступен (500 ошибка), пробуем старый JSON API
|
||||
if (!response.ok && response.status === 500) {
|
||||
console.log('🔄 Новый API недоступен, пробуем старый JSON API...');
|
||||
response = await fetch(`/api/colliders?cityId=${cityId}`, {
|
||||
headers: { Authorization: `Bearer ${token}` }
|
||||
});
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
console.log('JSON файл не найден, создаем новый');
|
||||
console.log('📄 JSON файл не найден, создаем новый');
|
||||
collidersRef.current = [];
|
||||
return;
|
||||
}
|
||||
@@ -380,6 +419,7 @@ export default function EnhancedCollisionEditor() {
|
||||
const mesh = new THREE.Mesh(geom, colliderMaterial.clone());
|
||||
const edges = new THREE.EdgesGeometry(mesh.geometry);
|
||||
const line = new THREE.LineSegments(edges, colliderEdgeMaterial.clone());
|
||||
line.visible = showWireframes; // Учитываем настройку видимости рамок
|
||||
mesh.add(line);
|
||||
|
||||
mesh.position.set(c.position?.x || 0, c.position?.y || 0, c.position?.z || 0);
|
||||
@@ -394,12 +434,23 @@ export default function EnhancedCollisionEditor() {
|
||||
}
|
||||
if (c.opacity !== undefined) {
|
||||
mesh.material.opacity = c.opacity;
|
||||
// Если прозрачность 0, делаем материал невидимым
|
||||
if (c.opacity === 0) {
|
||||
mesh.material.visible = false;
|
||||
mesh.material.transparent = true;
|
||||
mesh.material.alphaTest = 0;
|
||||
} else {
|
||||
mesh.material.visible = true;
|
||||
mesh.material.transparent = true;
|
||||
mesh.material.alphaTest = 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
mesh.userData = {
|
||||
type: c.type || 'box',
|
||||
color: c.color || { r: 1, g: 0, b: 0 },
|
||||
opacity: c.opacity || 0.3
|
||||
opacity: c.opacity || 0.3,
|
||||
id: c.id // Добавляем ID из базы данных
|
||||
};
|
||||
|
||||
sceneRef.current.add(mesh);
|
||||
@@ -438,7 +489,8 @@ export default function EnhancedCollisionEditor() {
|
||||
z: mesh.scale.z
|
||||
},
|
||||
color: mesh.userData.color || { r: 1, g: 0, b: 0 },
|
||||
opacity: mesh.userData.opacity || 0.3
|
||||
opacity: mesh.userData.opacity || 0.3,
|
||||
id: mesh.userData.id // Добавляем ID для существующих коллайдеров
|
||||
};
|
||||
});
|
||||
|
||||
@@ -446,7 +498,9 @@ export default function EnhancedCollisionEditor() {
|
||||
|
||||
// Отправляем данные на сервер для сохранения
|
||||
const token = localStorage.getItem('token');
|
||||
const response = await fetch(`/api/colliders/city/${cityId}`, {
|
||||
|
||||
// Сначала пробуем новый API с базой данных
|
||||
let response = await fetch(`/api/colliders/city/${cityId}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
@@ -454,6 +508,19 @@ export default function EnhancedCollisionEditor() {
|
||||
},
|
||||
body: JSON.stringify(jsonData)
|
||||
});
|
||||
|
||||
// Если новый API недоступен (500 ошибка), пробуем старый JSON API
|
||||
if (!response.ok && response.status === 500) {
|
||||
console.log('🔄 Новый API недоступен, пробуем старый JSON API...');
|
||||
response = await fetch('/api/colliders', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${token}`
|
||||
},
|
||||
body: JSON.stringify({ ...jsonData, cityId: parseInt(cityId) })
|
||||
});
|
||||
}
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.json();
|
||||
@@ -482,6 +549,7 @@ export default function EnhancedCollisionEditor() {
|
||||
const mesh = new THREE.Mesh(geom, colliderMaterial.clone());
|
||||
const edges = new THREE.EdgesGeometry(mesh.geometry);
|
||||
const line = new THREE.LineSegments(edges, colliderEdgeMaterial.clone());
|
||||
line.visible = showWireframes; // Учитываем настройку видимости рамок
|
||||
mesh.add(line);
|
||||
|
||||
// Вычисляем позицию перед камерой
|
||||
@@ -503,7 +571,8 @@ export default function EnhancedCollisionEditor() {
|
||||
mesh.userData = {
|
||||
type: shapeType,
|
||||
color: { ...selectedColor },
|
||||
opacity: selectedOpacity
|
||||
opacity: selectedOpacity,
|
||||
id: null // Новый коллайдер пока не имеет ID
|
||||
};
|
||||
|
||||
sceneRef.current.add(mesh);
|
||||
@@ -513,6 +582,8 @@ export default function EnhancedCollisionEditor() {
|
||||
|
||||
console.log(`✅ Создан коллайдер типа "${shapeType}" в позиции:`, position);
|
||||
console.log(`📊 Всего коллайдеров: ${collidersRef.current.length}`);
|
||||
// Запускаем автоматическое сохранение
|
||||
triggerAutoSave();
|
||||
};
|
||||
|
||||
// Функция для обновления предварительного просмотра позиции коллайдера
|
||||
@@ -620,6 +691,7 @@ export default function EnhancedCollisionEditor() {
|
||||
const mesh = new THREE.Mesh(geom, newMaterial);
|
||||
const edges = new THREE.EdgesGeometry(mesh.geometry);
|
||||
const line = new THREE.LineSegments(edges, new THREE.LineBasicMaterial({ color: 0x000000 }));
|
||||
line.visible = showWireframes; // Учитываем настройку видимости рамок
|
||||
mesh.add(line);
|
||||
|
||||
// Копируем параметры с небольшим смещением
|
||||
@@ -637,7 +709,8 @@ export default function EnhancedCollisionEditor() {
|
||||
mesh.userData = {
|
||||
type: selected.userData.type,
|
||||
color: { ...selected.userData.color },
|
||||
opacity: selected.userData.opacity
|
||||
opacity: selected.userData.opacity,
|
||||
id: null // Дублированный коллайдер пока не имеет ID
|
||||
};
|
||||
|
||||
sceneRef.current.add(mesh);
|
||||
@@ -652,6 +725,8 @@ export default function EnhancedCollisionEditor() {
|
||||
rotation: { x: mesh.rotation.x, y: mesh.rotation.y, z: mesh.rotation.z },
|
||||
scale: { x: mesh.scale.x, y: mesh.scale.y, z: mesh.scale.z }
|
||||
});
|
||||
// Запускаем автоматическое сохранение
|
||||
triggerAutoSave();
|
||||
};
|
||||
|
||||
// Функция для телепортации камеры к интерьеру
|
||||
@@ -679,6 +754,31 @@ export default function EnhancedCollisionEditor() {
|
||||
console.log(`Режим TransformControls изменен на: ${mode}`);
|
||||
};
|
||||
|
||||
// Функция для принудительной перезагрузки коллайдеров из базы данных
|
||||
const reloadColliders = async () => {
|
||||
console.log('🔄 Принудительная перезагрузка коллайдеров из БД...');
|
||||
await loadCollidersFromJSON();
|
||||
console.log('✅ Коллайдеры перезагружены');
|
||||
};
|
||||
|
||||
// Функция для переключения видимости рамок
|
||||
const toggleWireframes = () => {
|
||||
const newShowWireframes = !showWireframes;
|
||||
setShowWireframes(newShowWireframes);
|
||||
|
||||
// Обновляем видимость рамок у всех коллайдеров
|
||||
collidersRef.current.forEach(c => {
|
||||
const mesh = c.mesh;
|
||||
mesh.children.forEach(child => {
|
||||
if (child.type === 'LineSegments') {
|
||||
child.visible = newShowWireframes;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
console.log(`🔲 Рамки ${newShowWireframes ? 'включены' : 'отключены'}`);
|
||||
};
|
||||
|
||||
// Функция для отладки коллайдеров
|
||||
const debugColliders = () => {
|
||||
console.log('🔍 Отладка коллайдеров:');
|
||||
@@ -695,6 +795,27 @@ export default function EnhancedCollisionEditor() {
|
||||
});
|
||||
};
|
||||
|
||||
// Функция автоматического сохранения
|
||||
const triggerAutoSave = () => {
|
||||
if (!autoSave || !cityId) return;
|
||||
|
||||
// Очищаем предыдущий таймер
|
||||
if (autoSaveTimeoutRef.current) {
|
||||
clearTimeout(autoSaveTimeoutRef.current);
|
||||
}
|
||||
|
||||
// Устанавливаем новый таймер на 2 секунды
|
||||
autoSaveTimeoutRef.current = setTimeout(async () => {
|
||||
try {
|
||||
await saveCollidersToJSON();
|
||||
setLastSaved(new Date());
|
||||
console.log('💾 Автоматическое сохранение выполнено');
|
||||
} catch (error) {
|
||||
console.error('❌ Ошибка автоматического сохранения:', error);
|
||||
}
|
||||
}, 2000);
|
||||
};
|
||||
|
||||
// Обновление цвета выбранного коллайдера
|
||||
const updateSelectedColliderColor = () => {
|
||||
if (selected) {
|
||||
@@ -704,12 +825,24 @@ export default function EnhancedCollisionEditor() {
|
||||
selected.userData.color = { ...selectedColor };
|
||||
selected.userData.opacity = selectedOpacity;
|
||||
selected.material.opacity = selectedOpacity;
|
||||
|
||||
// Если прозрачность 0, делаем материал невидимым
|
||||
if (selectedOpacity === 0) {
|
||||
selected.material.visible = false;
|
||||
selected.material.transparent = true;
|
||||
selected.material.alphaTest = 0;
|
||||
} else {
|
||||
selected.material.visible = true;
|
||||
selected.material.transparent = true;
|
||||
selected.material.alphaTest = 0.1;
|
||||
}
|
||||
|
||||
updateColliderData(selected);
|
||||
}
|
||||
};
|
||||
|
||||
// Удаление выбранного коллайдера
|
||||
const deleteSelected = () => {
|
||||
const deleteSelected = async () => {
|
||||
if (!selected) {
|
||||
console.log('❌ Нет выбранного коллайдера для удаления');
|
||||
return;
|
||||
@@ -718,6 +851,27 @@ export default function EnhancedCollisionEditor() {
|
||||
console.log('🗑️ Удаляем коллайдер:', selected);
|
||||
console.log('📊 Всего коллайдеров до удаления:', collidersRef.current.length);
|
||||
|
||||
// Если у коллайдера есть ID, удаляем его из базы данных
|
||||
if (selected.userData.id) {
|
||||
try {
|
||||
const token = localStorage.getItem('token');
|
||||
const response = await fetch(`/api/colliders/${selected.userData.id}`, {
|
||||
method: 'DELETE',
|
||||
headers: { Authorization: `Bearer ${token}` }
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
console.log(`✅ Коллайдер ${selected.userData.id} удален из базы данных`);
|
||||
} else {
|
||||
console.error(`❌ Ошибка удаления коллайдера ${selected.userData.id} из БД:`, await response.text());
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Ошибка при удалении коллайдера из БД:', error);
|
||||
}
|
||||
} else {
|
||||
console.log('⚠️ У коллайдера нет ID, удаляем только из фронтенда');
|
||||
}
|
||||
|
||||
// Удаляем из сцены
|
||||
sceneRef.current.remove(selected);
|
||||
|
||||
@@ -733,6 +887,8 @@ export default function EnhancedCollisionEditor() {
|
||||
setSelected(null);
|
||||
|
||||
console.log('✅ Коллайдер успешно удален');
|
||||
// Запускаем автоматическое сохранение для синхронизации
|
||||
triggerAutoSave();
|
||||
};
|
||||
|
||||
// Обработка клика по объекту
|
||||
@@ -744,24 +900,45 @@ export default function EnhancedCollisionEditor() {
|
||||
const raycaster = new THREE.Raycaster();
|
||||
raycaster.setFromCamera(mouse, cameraRef.current);
|
||||
|
||||
const intersects = raycaster.intersectObjects(collidersRef.current.map(c => c.mesh));
|
||||
// Получаем все объекты коллайдеров (включая рамки)
|
||||
const allColliderObjects = [];
|
||||
collidersRef.current.forEach(c => {
|
||||
allColliderObjects.push(c.mesh); // Основной меш
|
||||
allColliderObjects.push(...c.mesh.children); // Рамки (дочерние объекты)
|
||||
});
|
||||
|
||||
const intersects = raycaster.intersectObjects(allColliderObjects);
|
||||
|
||||
if (intersects.length > 0) {
|
||||
const clickedMesh = intersects[0].object;
|
||||
setSelected(clickedMesh);
|
||||
transformRef.current.attach(clickedMesh);
|
||||
let clickedObject = intersects[0].object;
|
||||
|
||||
console.log('🎯 Выбран коллайдер:', clickedMesh);
|
||||
// Если кликнули по рамке, находим родительский меш
|
||||
if (clickedObject.type === 'LineSegments') {
|
||||
clickedObject = clickedObject.parent;
|
||||
console.log('🎯 Кликнули по рамке, выбираем родительский меш:', clickedObject);
|
||||
}
|
||||
|
||||
// Проверяем, что это действительно коллайдер из нашего списка
|
||||
const collider = collidersRef.current.find(c => c.mesh === clickedObject);
|
||||
if (!collider) {
|
||||
console.log('❌ Кликнули по объекту, который не является коллайдером');
|
||||
return;
|
||||
}
|
||||
|
||||
setSelected(clickedObject);
|
||||
transformRef.current.attach(clickedObject);
|
||||
|
||||
console.log('🎯 Выбран коллайдер:', clickedObject);
|
||||
console.log('📊 Всего коллайдеров в массиве:', collidersRef.current.length);
|
||||
|
||||
// Обновляем цветовую палитру
|
||||
setSelectedColor(clickedMesh.userData.color || { r: 1, g: 0, b: 0 });
|
||||
setSelectedOpacity(clickedMesh.userData.opacity || 0.3);
|
||||
setSelectedColor(clickedObject.userData.color || { r: 1, g: 0, b: 0 });
|
||||
setSelectedOpacity(clickedObject.userData.opacity || 0.3);
|
||||
|
||||
// Обновляем параметры коллайдера
|
||||
setColliderPosition({ x: clickedMesh.position.x, y: clickedMesh.position.y, z: clickedMesh.position.z });
|
||||
setColliderRotation({ x: clickedMesh.rotation.x, y: clickedMesh.rotation.y, z: clickedMesh.rotation.z });
|
||||
setColliderScale({ x: clickedMesh.scale.x, y: clickedMesh.scale.y, z: clickedMesh.scale.z });
|
||||
setColliderPosition({ x: clickedObject.position.x, y: clickedObject.position.y, z: clickedObject.position.z });
|
||||
setColliderRotation({ x: clickedObject.rotation.x, y: clickedObject.rotation.y, z: clickedObject.rotation.z });
|
||||
setColliderScale({ x: clickedObject.scale.x, y: clickedObject.scale.y, z: clickedObject.scale.z });
|
||||
} else {
|
||||
setSelected(null);
|
||||
transformRef.current.detach();
|
||||
@@ -1080,6 +1257,25 @@ export default function EnhancedCollisionEditor() {
|
||||
Масштаб
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Переключение рамок */}
|
||||
<div style={{ marginBottom: '8px' }}>
|
||||
<button
|
||||
onClick={toggleWireframes}
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '8px',
|
||||
backgroundColor: showWireframes ? '#27ae60' : '#e74c3c',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
borderRadius: '3px',
|
||||
cursor: 'pointer',
|
||||
fontSize: '11px'
|
||||
}}
|
||||
>
|
||||
{showWireframes ? '🔲 Скрыть рамки' : '🔲 Показать рамки'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: '10px' }}>
|
||||
@@ -1357,6 +1553,82 @@ export default function EnhancedCollisionEditor() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Управление сохранением */}
|
||||
<div style={{ marginBottom: '20px' }}>
|
||||
<h3>Управление сохранением</h3>
|
||||
|
||||
<div style={{ marginBottom: '10px' }}>
|
||||
<label style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={autoSave}
|
||||
onChange={(e) => setAutoSave(e.target.checked)}
|
||||
style={{ transform: 'scale(1.2)' }}
|
||||
/>
|
||||
<span style={{ fontSize: '14px' }}>Автоматическое сохранение</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{lastSaved && (
|
||||
<div style={{ fontSize: '12px', color: '#27ae60', marginBottom: '10px' }}>
|
||||
💾 Последнее сохранение: {lastSaved.toLocaleTimeString()}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div style={{ display: 'flex', gap: '10px' }}>
|
||||
<button
|
||||
onClick={saveCollidersToJSON}
|
||||
disabled={isSaving}
|
||||
style={{
|
||||
flex: 1,
|
||||
padding: '8px',
|
||||
backgroundColor: isSaving ? '#95a5a6' : '#27ae60',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
borderRadius: '5px',
|
||||
cursor: isSaving ? 'not-allowed' : 'pointer',
|
||||
fontSize: '12px'
|
||||
}}
|
||||
>
|
||||
{isSaving ? 'Сохранение...' : '💾 Сохранить сейчас'}
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={loadCollidersFromJSON}
|
||||
disabled={isLoading}
|
||||
style={{
|
||||
flex: 1,
|
||||
padding: '8px',
|
||||
backgroundColor: isLoading ? '#95a5a6' : '#3498db',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
borderRadius: '5px',
|
||||
cursor: isLoading ? 'not-allowed' : 'pointer',
|
||||
fontSize: '12px'
|
||||
}}
|
||||
>
|
||||
{isLoading ? 'Загрузка...' : '🔄 Перезагрузить'}
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={reloadColliders}
|
||||
disabled={isLoading}
|
||||
style={{
|
||||
flex: 1,
|
||||
padding: '8px',
|
||||
backgroundColor: isLoading ? '#95a5a6' : '#e67e22',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
borderRadius: '5px',
|
||||
cursor: isLoading ? 'not-allowed' : 'pointer',
|
||||
fontSize: '12px'
|
||||
}}
|
||||
>
|
||||
{isLoading ? 'Загрузка...' : '🔄 Синхронизировать'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Информация */}
|
||||
<div style={{ marginTop: '20px', fontSize: '12px', color: '#bdc3c7' }}>
|
||||
<p>Коллайдеров: {collidersRef.current.length}</p>
|
||||
|
||||
174
test-collider-deletion-fix.js
Normal file
174
test-collider-deletion-fix.js
Normal file
@@ -0,0 +1,174 @@
|
||||
// Исправление проблемы с удалением коллайдеров
|
||||
// Файл: test-collider-deletion-fix.js
|
||||
|
||||
console.log('🔧 Исправление проблемы с удалением коллайдеров');
|
||||
console.log('');
|
||||
|
||||
console.log('❓ Проблема:');
|
||||
console.log('Не удаётся удалить старый коллайдер');
|
||||
console.log('Удаляю, сохраняю, но после перезагрузки он опять появляется');
|
||||
console.log('');
|
||||
|
||||
console.log('🔍 Причина проблемы:');
|
||||
console.log('');
|
||||
|
||||
console.log('1. 🗑️ Неполное удаление:');
|
||||
console.log(' - Функция deleteSelected удаляла коллайдер только из фронтенда');
|
||||
console.log(' - Коллайдер оставался в базе данных');
|
||||
console.log(' - При перезагрузке коллайдер загружался обратно из БД');
|
||||
console.log('');
|
||||
|
||||
console.log('2. 🔄 Проблема с автоматическим сохранением:');
|
||||
console.log(' - Автоматическое сохранение полагалось на перезапись всех коллайдеров');
|
||||
console.log(' - Если сохранение не сработало или сработало с ошибкой, коллайдер оставался');
|
||||
console.log(' - Отсутствие прямого удаления из БД');
|
||||
console.log('');
|
||||
|
||||
console.log('3. 🆔 Отсутствие ID у новых коллайдеров:');
|
||||
console.log(' - Новые коллайдеры создавались без ID');
|
||||
console.log(' - Их нельзя было удалить через API');
|
||||
console.log(' - Только автоматическое сохранение могло их удалить');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Исправления:');
|
||||
console.log('');
|
||||
|
||||
console.log('1. 🗑️ Прямое удаление из базы данных:');
|
||||
console.log(' - Функция deleteSelected теперь асинхронная');
|
||||
console.log(' - Если у коллайдера есть ID, он удаляется из БД через API');
|
||||
console.log(' - DELETE /api/colliders/:colliderId');
|
||||
console.log('');
|
||||
|
||||
console.log('2. 🔄 Улучшенная обработка ошибок:');
|
||||
console.log(' - Логирование успешного удаления из БД');
|
||||
console.log(' - Обработка ошибок при удалении');
|
||||
console.log(' - Fallback для коллайдеров без ID');
|
||||
console.log('');
|
||||
|
||||
console.log('3. 🔄 Функция синхронизации:');
|
||||
console.log(' - Новая функция reloadColliders() для принудительной перезагрузки');
|
||||
console.log(' - Кнопка "🔄 Синхронизировать" в UI');
|
||||
console.log(' - Возможность проверить состояние БД');
|
||||
console.log('');
|
||||
|
||||
console.log('4. 📊 Улучшенное логирование:');
|
||||
console.log(' - Подробные логи процесса удаления');
|
||||
console.log(' - Информация об ID коллайдеров');
|
||||
console.log(' - Отслеживание количества коллайдеров');
|
||||
console.log('');
|
||||
|
||||
console.log('🔧 Технические детали:');
|
||||
console.log('');
|
||||
|
||||
console.log('🗑️ Логика удаления:');
|
||||
console.log('- Проверка наличия ID: if (selected.userData.id)');
|
||||
console.log('- DELETE запрос: /api/colliders/${selected.userData.id}');
|
||||
console.log('- Удаление из сцены: sceneRef.current.remove(selected)');
|
||||
console.log('- Удаление из массива: collidersRef.current.filter()');
|
||||
console.log('- Автоматическое сохранение для синхронизации');
|
||||
console.log('');
|
||||
|
||||
console.log('🔄 API endpoints:');
|
||||
console.log('- DELETE /api/colliders/:colliderId - удаление конкретного коллайдера');
|
||||
console.log('- POST /api/colliders/city/:cityId - перезапись всех коллайдеров');
|
||||
console.log('- GET /api/colliders/city/:cityId - загрузка коллайдеров');
|
||||
console.log('');
|
||||
|
||||
console.log('🆔 ID система:');
|
||||
console.log('- Старые коллайдеры: имеют ID из базы данных');
|
||||
console.log('- Новые коллайдеры: id: null до первого сохранения');
|
||||
console.log('- Дублированные: id: null до первого сохранения');
|
||||
console.log('- После сохранения: получают ID из БД');
|
||||
console.log('');
|
||||
|
||||
console.log('🧪 Как тестировать исправления:');
|
||||
console.log('');
|
||||
|
||||
console.log('1. 🗑️ Удаление старых коллайдеров:');
|
||||
console.log(' - Выберите коллайдер, который был создан ранее');
|
||||
console.log(' - Нажмите "Удалить коллайдер"');
|
||||
console.log(' - Проверьте консоль: "✅ Коллайдер X удален из базы данных"');
|
||||
console.log(' - Перезагрузите страницу');
|
||||
console.log(' - Убедитесь, что коллайдер не появился');
|
||||
console.log('');
|
||||
|
||||
console.log('2. 🆕 Удаление новых коллайдеров:');
|
||||
console.log(' - Создайте новый коллайдер');
|
||||
console.log(' - Сохраните его (чтобы получить ID)');
|
||||
console.log(' - Удалите коллайдер');
|
||||
console.log(' - Перезагрузите страницу');
|
||||
console.log(' - Убедитесь, что коллайдер удален');
|
||||
console.log('');
|
||||
|
||||
console.log('3. 🔄 Синхронизация:');
|
||||
console.log(' - Удалите несколько коллайдеров');
|
||||
console.log(' - Нажмите "🔄 Синхронизировать"');
|
||||
console.log(' - Проверьте консоль: "🔄 Принудительная перезагрузка коллайдеров из БД"');
|
||||
console.log(' - Убедитесь, что удаленные коллайдеры не загрузились');
|
||||
console.log('');
|
||||
|
||||
console.log('4. 📊 Отладочная информация:');
|
||||
console.log(' - Проверьте консоль на наличие ошибок');
|
||||
console.log(' - Должны быть логи о процессе удаления');
|
||||
console.log(' - Проверьте количество коллайдеров до и после удаления');
|
||||
console.log('');
|
||||
|
||||
console.log('5. 🎯 Тест с несколькими коллайдерами:');
|
||||
console.log(' - Создайте несколько коллайдеров');
|
||||
console.log(' - Удалите некоторые из них');
|
||||
console.log(' - Сохраните изменения');
|
||||
console.log(' - Перезагрузите страницу');
|
||||
console.log(' - Убедитесь, что только нужные коллайдеры остались');
|
||||
console.log('');
|
||||
|
||||
console.log('🎯 Ожидаемые результаты:');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Удаление старых коллайдеров:');
|
||||
console.log('- [ ] Коллайдеры с ID удаляются из базы данных');
|
||||
console.log('- [ ] После перезагрузки коллайдеры не появляются');
|
||||
console.log('- [ ] Логирование успешного удаления');
|
||||
console.log('- [ ] Отсутствие ошибок в консоли');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Удаление новых коллайдеров:');
|
||||
console.log('- [ ] Новые коллайдеры удаляются из фронтенда');
|
||||
console.log('- [ ] Автоматическое сохранение синхронизирует изменения');
|
||||
console.log('- [ ] После перезагрузки коллайдеры не появляются');
|
||||
console.log('- [ ] Корректная работа с коллайдерами без ID');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Синхронизация:');
|
||||
console.log('- [ ] Кнопка "Синхронизировать" работает');
|
||||
console.log('- [ ] Принудительная перезагрузка из БД');
|
||||
console.log('- [ ] Синхронизация фронтенда с базой данных');
|
||||
console.log('- [ ] Отсутствие рассинхронизации');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Обработка ошибок:');
|
||||
console.log('- [ ] Логирование ошибок при удалении');
|
||||
console.log('- [ ] Graceful fallback для коллайдеров без ID');
|
||||
console.log('- [ ] Отсутствие критических ошибок');
|
||||
console.log('- [ ] Стабильная работа системы');
|
||||
console.log('');
|
||||
|
||||
console.log('🔍 Отладочная информация:');
|
||||
console.log('');
|
||||
|
||||
console.log('📊 В консоли должно появляться:');
|
||||
console.log('- "🗑️ Удаляем коллайдер: [объект]"');
|
||||
console.log('- "✅ Коллайдер X удален из базы данных"');
|
||||
console.log('- "📊 Коллайдеров до: X, после: Y"');
|
||||
console.log('- "✅ Коллайдер успешно удален"');
|
||||
console.log('- "💾 Автоматическое сохранение выполнено"');
|
||||
console.log('');
|
||||
|
||||
console.log('🎯 Проверка в базе данных:');
|
||||
console.log('- SELECT * FROM colliders WHERE city_id = 1;');
|
||||
console.log('- Удаленные коллайдеры не должны присутствовать');
|
||||
console.log('- Проверить updated_at для оставшихся коллайдеров');
|
||||
console.log('');
|
||||
|
||||
console.log('🚀 Исправления готовы к тестированию!');
|
||||
console.log('Откройте: http://localhost:4000/enhanced-collision-editor');
|
||||
console.log('Попробуйте удалить коллайдер и проверить, что он не появляется после перезагрузки');
|
||||
160
test-collider-position-saving.js
Normal file
160
test-collider-position-saving.js
Normal file
@@ -0,0 +1,160 @@
|
||||
// Тест исправления сохранения перемещенных коллайдеров
|
||||
// Файл: test-collider-position-saving.js
|
||||
|
||||
console.log('🔧 Исправление сохранения перемещенных коллайдеров');
|
||||
console.log('');
|
||||
|
||||
console.log('❓ Проблема:');
|
||||
console.log('Перемещаю старый коллайдер, нажимаю "сохранить", но при новом входе он стоит на том же месте');
|
||||
console.log('');
|
||||
|
||||
console.log('🔍 Причина проблемы:');
|
||||
console.log('');
|
||||
|
||||
console.log('1. 🆔 Отсутствие ID у коллайдеров:');
|
||||
console.log(' - Старые коллайдеры загружались из JSON без ID');
|
||||
console.log(' - Новые коллайдеры создавались без ID');
|
||||
console.log(' - Сервер не мог различить существующие и новые коллайдеры');
|
||||
console.log('');
|
||||
|
||||
console.log('2. 🔄 Неправильная логика сохранения:');
|
||||
console.log(' - Сервер удалял ВСЕ коллайдеры и создавал заново');
|
||||
console.log(' - Потеря связи между фронтендом и базой данных');
|
||||
console.log(' - Новые позиции не сохранялись');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Исправления:');
|
||||
console.log('');
|
||||
|
||||
console.log('1. 🆔 Добавление ID к коллайдерам:');
|
||||
console.log(' - Старые коллайдеры получают ID из базы данных при загрузке');
|
||||
console.log(' - Новые коллайдеры помечаются как id: null');
|
||||
console.log(' - Дублированные коллайдеры помечаются как id: null');
|
||||
console.log('');
|
||||
|
||||
console.log('2. 🔄 Улучшенная логика сохранения:');
|
||||
console.log(' - Разделение коллайдеров на существующие (с ID) и новые (без ID)');
|
||||
console.log(' - UPDATE для существующих коллайдеров');
|
||||
console.log(' - INSERT для новых коллайдеров');
|
||||
console.log(' - Сохранение связи между фронтендом и БД');
|
||||
console.log('');
|
||||
|
||||
console.log('3. 🗄️ Обновление серверной логики:');
|
||||
console.log(' - Фильтрация коллайдеров по наличию ID');
|
||||
console.log(' - UPDATE запросы для существующих коллайдеров');
|
||||
console.log(' - INSERT запросы для новых коллайдеров');
|
||||
console.log(' - Логирование количества обновленных и созданных коллайдеров');
|
||||
console.log('');
|
||||
|
||||
console.log('🔧 Технические детали:');
|
||||
console.log('');
|
||||
|
||||
console.log('🆔 ID система:');
|
||||
console.log('- Старые коллайдеры: mesh.userData.id = c.id (из БД)');
|
||||
console.log('- Новые коллайдеры: mesh.userData.id = null');
|
||||
console.log('- Дублированные: mesh.userData.id = null');
|
||||
console.log('- При сохранении: id: mesh.userData.id');
|
||||
console.log('');
|
||||
|
||||
console.log('🔄 Логика сохранения:');
|
||||
console.log('- existingColliders = colliders.filter(c => c.id)');
|
||||
console.log('- newColliders = colliders.filter(c => !c.id)');
|
||||
console.log('- UPDATE для существующих с WHERE id = $1');
|
||||
console.log('- INSERT для новых без ID');
|
||||
console.log('');
|
||||
|
||||
console.log('🗄️ Серверные изменения:');
|
||||
console.log('- Разделение коллайдеров на две группы');
|
||||
console.log('- UPDATE запросы для существующих');
|
||||
console.log('- INSERT запросы для новых');
|
||||
console.log('- Транзакционная безопасность');
|
||||
console.log('');
|
||||
|
||||
console.log('🧪 Как тестировать исправления:');
|
||||
console.log('');
|
||||
|
||||
console.log('1. 🔄 Перемещение существующих коллайдеров:');
|
||||
console.log(' - Загрузите редактор коллизий');
|
||||
console.log(' - Выберите один из старых коллайдеров');
|
||||
console.log(' - Переместите его в новое место');
|
||||
console.log(' - Нажмите "Сохранить сейчас"');
|
||||
console.log(' - Проверьте консоль: должно появиться "💾 Сохраняем: X существующих, Y новых"');
|
||||
console.log(' - Перезагрузите страницу');
|
||||
console.log(' - Убедитесь, что коллайдер остался в новом месте');
|
||||
console.log('');
|
||||
|
||||
console.log('2. 🆕 Создание новых коллайдеров:');
|
||||
console.log(' - Создайте новый коллайдер');
|
||||
console.log(' - Переместите его в нужное место');
|
||||
console.log(' - Нажмите "Сохранить сейчас"');
|
||||
console.log(' - Проверьте консоль: должно появиться сообщение о создании');
|
||||
console.log(' - Перезагрузите страницу');
|
||||
console.log(' - Убедитесь, что новый коллайдер сохранился');
|
||||
console.log('');
|
||||
|
||||
console.log('3. 🔄 Дублирование коллайдеров:');
|
||||
console.log(' - Выберите существующий коллайдер');
|
||||
console.log(' - Нажмите "Дублировать коллайдер"');
|
||||
console.log(' - Переместите дублированный коллайдер');
|
||||
console.log(' - Нажмите "Сохранить сейчас"');
|
||||
console.log(' - Перезагрузите страницу');
|
||||
console.log(' - Убедитесь, что оба коллайдера сохранились');
|
||||
console.log('');
|
||||
|
||||
console.log('4. 🎯 Автоматическое сохранение:');
|
||||
console.log(' - Переместите коллайдер');
|
||||
console.log(' - Подождите 2 секунды');
|
||||
console.log(' - Проверьте консоль: "💾 Автоматическое сохранение выполнено"');
|
||||
console.log(' - Перезагрузите страницу');
|
||||
console.log(' - Убедитесь, что изменения сохранились');
|
||||
console.log('');
|
||||
|
||||
console.log('🎯 Ожидаемые результаты:');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Перемещение существующих:');
|
||||
console.log('- [ ] Коллайдеры имеют ID из базы данных');
|
||||
console.log('- [ ] При сохранении выполняется UPDATE');
|
||||
console.log('- [ ] Позиция сохраняется в базе данных');
|
||||
console.log('- [ ] После перезагрузки коллайдер остается в новом месте');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Создание новых:');
|
||||
console.log('- [ ] Новые коллайдеры помечены как id: null');
|
||||
console.log('- [ ] При сохранении выполняется INSERT');
|
||||
console.log('- [ ] Новый коллайдер получает ID в базе данных');
|
||||
console.log('- [ ] После перезагрузки новый коллайдер загружается');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Дублирование:');
|
||||
console.log('- [ ] Дублированные коллайдеры помечены как id: null');
|
||||
console.log('- [ ] При сохранении выполняется INSERT');
|
||||
console.log('- [ ] Оригинал обновляется, копия создается');
|
||||
console.log('- [ ] После перезагрузки оба коллайдера сохраняются');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Автоматическое сохранение:');
|
||||
console.log('- [ ] Срабатывает через 2 секунды после изменений');
|
||||
console.log('- [ ] Правильно обрабатывает существующие и новые коллайдеры');
|
||||
console.log('- [ ] Логирует количество обновленных и созданных');
|
||||
console.log('- [ ] Сохраняет все изменения в базе данных');
|
||||
console.log('');
|
||||
|
||||
console.log('🔍 Отладочная информация:');
|
||||
console.log('');
|
||||
|
||||
console.log('📊 В консоли должно появляться:');
|
||||
console.log('- "💾 Сохраняем: X существующих, Y новых коллайдеров"');
|
||||
console.log('- "✅ Коллайдеры для города 1 сохранены в БД (X обновлено, Y новых)"');
|
||||
console.log('- "💾 Автоматическое сохранение выполнено"');
|
||||
console.log('');
|
||||
|
||||
console.log('🎯 Проверка в базе данных:');
|
||||
console.log('- SELECT * FROM colliders WHERE city_id = 1;');
|
||||
console.log('- Проверить updated_at для перемещенных коллайдеров');
|
||||
console.log('- Проверить created_at для новых коллайдеров');
|
||||
console.log('');
|
||||
|
||||
console.log('🚀 Исправления готовы к тестированию!');
|
||||
console.log('Откройте: http://localhost:4000/enhanced-collision-editor');
|
||||
console.log('Попробуйте переместить старый коллайдер и сохранить изменения');
|
||||
145
test-collision-editor-error-fixes.js
Normal file
145
test-collision-editor-error-fixes.js
Normal file
@@ -0,0 +1,145 @@
|
||||
// Тест исправления ошибок редактора коллизий
|
||||
// Файл: test-collision-editor-error-fixes.js
|
||||
|
||||
console.log('🔧 Исправление ошибок редактора коллизий');
|
||||
console.log('');
|
||||
|
||||
console.log('❓ Проблемы из лога:');
|
||||
console.log('');
|
||||
|
||||
console.log('1. 🚨 Ошибка 500 (Internal Server Error):');
|
||||
console.log(' ПРОБЛЕМА: Сервер возвращал ошибку 500 при загрузке/сохранении');
|
||||
console.log(' ПРИЧИНА: Таблица colliders не была создана в базе данных');
|
||||
console.log(' РЕШЕНИЕ: Выполнена миграция для создания таблицы');
|
||||
console.log('');
|
||||
|
||||
console.log('2. 📄 JSON файл не найден:');
|
||||
console.log(' ПРОБЛЕМА: Фронтенд не мог загрузить коллайдеры');
|
||||
console.log(' ПРИЧИНА: Новые API endpoints не работали');
|
||||
console.log(' РЕШЕНИЕ: Добавлен fallback на старые JSON endpoints');
|
||||
console.log('');
|
||||
|
||||
console.log('3. 👻 Не видны старые коллайдеры:');
|
||||
console.log(' ПРОБЛЕМА: Коллайдеры из интерьера не отображались');
|
||||
console.log(' ПРИЧИНА: Данные были только в JSON, не в БД');
|
||||
console.log(' РЕШЕНИЕ: Мигрированы данные из JSON в базу данных');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Выполненные исправления:');
|
||||
console.log('');
|
||||
|
||||
console.log('1. 🗄️ Миграция базы данных:');
|
||||
console.log(' - Создана таблица colliders с полной структурой');
|
||||
console.log(' - Добавлены индексы для производительности');
|
||||
console.log(' - Созданы триггеры для автоматического обновления');
|
||||
console.log(' - Настроены внешние ключи для целостности данных');
|
||||
console.log('');
|
||||
|
||||
console.log('2. 🔄 Fallback система:');
|
||||
console.log(' - При ошибке 500 автоматически переключается на старый JSON API');
|
||||
console.log(' - Работает как для загрузки, так и для сохранения');
|
||||
console.log(' - Логирование переключения для отладки');
|
||||
console.log(' - Обратная совместимость с существующими данными');
|
||||
console.log('');
|
||||
|
||||
console.log('3. 📊 Миграция данных:');
|
||||
console.log(' - Перенесены все 6 коллайдеров из JSON в БД');
|
||||
console.log(' - Сохранены все параметры: позиция, поворот, масштаб, цвет, прозрачность');
|
||||
console.log(' - Транзакционная безопасность миграции');
|
||||
console.log(' - Проверка целостности данных');
|
||||
console.log('');
|
||||
|
||||
console.log('🔧 Технические детали:');
|
||||
console.log('');
|
||||
|
||||
console.log('🗄️ Структура таблицы colliders:');
|
||||
console.log('- id: SERIAL PRIMARY KEY');
|
||||
console.log('- city_id: INTEGER (связь с городами)');
|
||||
console.log('- type: VARCHAR(20) (box, circle, capsule)');
|
||||
console.log('- position_x/y/z: DECIMAL(15,6) (координаты)');
|
||||
console.log('- rotation_x/y/z: DECIMAL(15,6) (углы в радианах)');
|
||||
console.log('- scale_x/y/z: DECIMAL(15,6) (масштаб)');
|
||||
console.log('- color_r/g/b: DECIMAL(3,2) (RGB 0-1)');
|
||||
console.log('- opacity: DECIMAL(3,2) (прозрачность 0-1)');
|
||||
console.log('- created_at/updated_at: TIMESTAMP');
|
||||
console.log('');
|
||||
|
||||
console.log('🔄 Fallback логика:');
|
||||
console.log('- Сначала пробует новый API: /api/colliders/city/:cityId');
|
||||
console.log('- При ошибке 500 переключается на старый: /api/colliders?cityId=:cityId');
|
||||
console.log('- Логирует переключение: "🔄 Новый API недоступен, пробуем старый JSON API..."');
|
||||
console.log('- Сохраняет обратную совместимость');
|
||||
console.log('');
|
||||
|
||||
console.log('📊 Мигрированные данные:');
|
||||
console.log('- 6 коллайдеров типа "box"');
|
||||
console.log('- Различные позиции в интерьере');
|
||||
console.log('- Цвета: зеленые (0.2, 1, 0.1) и красные (1, 0, 0)');
|
||||
console.log('- Все параметры трансформации сохранены');
|
||||
console.log('');
|
||||
|
||||
console.log('🧪 Как тестировать исправления:');
|
||||
console.log('');
|
||||
|
||||
console.log('1. 🔄 Загрузка коллайдеров:');
|
||||
console.log(' - Откройте редактор коллизий');
|
||||
console.log(' - Проверьте консоль: должно появиться "✅ Загружено 6 коллайдеров"');
|
||||
console.log(' - Убедитесь, что коллайдеры видны в 3D сцене');
|
||||
console.log(' - Проверьте, что они имеют правильные цвета');
|
||||
console.log('');
|
||||
|
||||
console.log('2. 💾 Сохранение коллайдеров:');
|
||||
console.log(' - Создайте новый коллайдер');
|
||||
console.log(' - Подождите 2 секунды для автоматического сохранения');
|
||||
console.log(' - Проверьте консоль: "💾 Автоматическое сохранение выполнено"');
|
||||
console.log(' - Перезагрузите страницу и убедитесь, что коллайдер сохранился');
|
||||
console.log('');
|
||||
|
||||
console.log('3. 🎯 Выбор коллайдеров:');
|
||||
console.log(' - Кликните по коллайдеру');
|
||||
console.log(' - Проверьте консоль: "🎯 Выбран коллайдер"');
|
||||
console.log(' - Убедитесь, что TransformControls активируется');
|
||||
console.log(' - Проверьте обновление параметров в UI');
|
||||
console.log('');
|
||||
|
||||
console.log('4. 🔄 Fallback система:');
|
||||
console.log(' - Временно отключите БД (если возможно)');
|
||||
console.log(' - Попробуйте загрузить/сохранить коллайдеры');
|
||||
console.log(' - Проверьте консоль: должно появиться сообщение о переключении');
|
||||
console.log(' - Убедитесь, что система работает через JSON');
|
||||
console.log('');
|
||||
|
||||
console.log('🎯 Ожидаемые результаты:');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Загрузка:');
|
||||
console.log('- [ ] Нет ошибок 500 в консоли');
|
||||
console.log('- [ ] Загружается 6 коллайдеров из БД');
|
||||
console.log('- [ ] Коллайдеры видны в 3D сцене');
|
||||
console.log('- [ ] Правильные цвета и позиции');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Сохранение:');
|
||||
console.log('- [ ] Автоматическое сохранение работает');
|
||||
console.log('- [ ] Ручное сохранение работает');
|
||||
console.log('- [ ] Данные сохраняются в БД');
|
||||
console.log('- [ ] Нет ошибок при сохранении');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Управление:');
|
||||
console.log('- [ ] Выбор коллайдеров работает');
|
||||
console.log('- [ ] TransformControls активируется');
|
||||
console.log('- [ ] Параметры обновляются в UI');
|
||||
console.log('- [ ] Дублирование и удаление работают');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Fallback:');
|
||||
console.log('- [ ] При ошибке БД переключается на JSON');
|
||||
console.log('- [ ] Логируется переключение');
|
||||
console.log('- [ ] Система остается работоспособной');
|
||||
console.log('- [ ] Обратная совместимость сохранена');
|
||||
console.log('');
|
||||
|
||||
console.log('🚀 Все исправления готовы к тестированию!');
|
||||
console.log('Откройте: http://localhost:4000/enhanced-collision-editor');
|
||||
console.log('Проверьте, что все коллайдеры загружаются и работают корректно');
|
||||
173
test-complete-collision-editor-improvements.js
Normal file
173
test-complete-collision-editor-improvements.js
Normal file
@@ -0,0 +1,173 @@
|
||||
// Тест всех улучшений редактора коллизий
|
||||
// Файл: test-complete-collision-editor-improvements.js
|
||||
|
||||
console.log('🚀 Полные улучшения редактора коллизий');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Решенные проблемы:');
|
||||
console.log('');
|
||||
|
||||
console.log('1. 🔄 Сохранение параметров трансформации:');
|
||||
console.log(' ПРОБЛЕМА: При перемещении объекты плохо сохранялись');
|
||||
console.log(' РЕШЕНИЕ: Исправлено обновление данных при изменении через TransformControls');
|
||||
console.log(' - Добавлено обновление UI параметров при изменении через TransformControls');
|
||||
console.log(' - Автоматическое обновление colliderPosition, colliderRotation, colliderScale');
|
||||
console.log(' - Логирование изменений для отладки');
|
||||
console.log('');
|
||||
|
||||
console.log('2. 🗄️ Миграция с JSON на базу данных:');
|
||||
console.log(' ПРОБЛЕМА: Данные хранились в JSON файлах');
|
||||
console.log(' РЕШЕНИЕ: Полная миграция на PostgreSQL');
|
||||
console.log(' - Создана таблица colliders с полной структурой');
|
||||
console.log(' - Новые API endpoints для работы с БД');
|
||||
console.log(' - Транзакции для надежности');
|
||||
console.log(' - Индексы для производительности');
|
||||
console.log('');
|
||||
|
||||
console.log('3. 🎛️ Улучшенное управление:');
|
||||
console.log(' ПРОБЛЕМА: Управление было неудобным');
|
||||
console.log(' РЕШЕНИЕ: Значительно улучшен интерфейс');
|
||||
console.log(' - Автоматическое сохранение с настраиваемой задержкой');
|
||||
console.log(' - Индикация последнего сохранения');
|
||||
console.log(' - Удобные кнопки сохранения/загрузки');
|
||||
console.log(' - Переключение режимов TransformControls');
|
||||
console.log('');
|
||||
|
||||
console.log('4. 💾 Автоматическое сохранение:');
|
||||
console.log(' НОВАЯ ФУНКЦИЯ: Автоматическое сохранение изменений');
|
||||
console.log(' - Задержка 2 секунды после изменений');
|
||||
console.log(' - Отмена предыдущих таймеров при новых изменениях');
|
||||
console.log(' - Индикация статуса сохранения');
|
||||
console.log(' - Возможность отключения');
|
||||
console.log('');
|
||||
|
||||
console.log('🔧 Технические улучшения:');
|
||||
console.log('');
|
||||
|
||||
console.log('📊 База данных:');
|
||||
console.log('- Таблица colliders с полной структурой');
|
||||
console.log('- Поля для позиции, поворота, масштаба, цвета, прозрачности');
|
||||
console.log('- Автоматические timestamps (created_at, updated_at)');
|
||||
console.log('- Индексы для быстрого поиска');
|
||||
console.log('- Триггеры для автоматического обновления updated_at');
|
||||
console.log('- Внешние ключи для связи с городами');
|
||||
console.log('');
|
||||
|
||||
console.log('🌐 API Endpoints:');
|
||||
console.log('- GET /api/colliders/city/:cityId - получение коллайдеров');
|
||||
console.log('- POST /api/colliders/city/:cityId - сохранение всех коллайдеров');
|
||||
console.log('- PUT /api/colliders/:colliderId - обновление отдельного коллайдера');
|
||||
console.log('- DELETE /api/colliders/:colliderId - удаление отдельного коллайдера');
|
||||
console.log('- Транзакции для надежности операций');
|
||||
console.log('- Валидация входных данных');
|
||||
console.log('');
|
||||
|
||||
console.log('🎮 Улучшенный интерфейс:');
|
||||
console.log('- Автоматическое сохранение с индикацией');
|
||||
console.log('- Переключение режимов TransformControls (перемещение/поворот/масштаб)');
|
||||
console.log('- Удобные кнопки управления');
|
||||
console.log('- Отображение времени последнего сохранения');
|
||||
console.log('- Состояния загрузки/сохранения');
|
||||
console.log('');
|
||||
|
||||
console.log('🧪 Как тестировать улучшения:');
|
||||
console.log('');
|
||||
|
||||
console.log('1. 🗄️ Миграция базы данных:');
|
||||
console.log(' - Запустите: node migrate-colliders.js');
|
||||
console.log(' - Проверьте создание таблицы colliders');
|
||||
console.log(' - Убедитесь в наличии индексов и триггеров');
|
||||
console.log('');
|
||||
|
||||
console.log('2. 🔄 Автоматическое сохранение:');
|
||||
console.log(' - Создайте или измените коллайдер');
|
||||
console.log(' - Подождите 2 секунды');
|
||||
console.log(' - Проверьте консоль: "💾 Автоматическое сохранение выполнено"');
|
||||
console.log(' - Проверьте время последнего сохранения в UI');
|
||||
console.log('');
|
||||
|
||||
console.log('3. 🎛️ Режимы TransformControls:');
|
||||
console.log(' - Выберите коллайдер');
|
||||
console.log(' - Переключайтесь между режимами: Перемещение, Поворот, Масштаб');
|
||||
console.log(' - Проверьте изменение осей в 3D сцене');
|
||||
console.log(' - Убедитесь в автоматическом сохранении изменений');
|
||||
console.log('');
|
||||
|
||||
console.log('4. 📊 Работа с базой данных:');
|
||||
console.log(' - Создайте несколько коллайдеров');
|
||||
console.log(' - Перезагрузите страницу');
|
||||
console.log(' - Убедитесь, что коллайдеры загружаются из БД');
|
||||
console.log(' - Проверьте сохранение в БД через API');
|
||||
console.log('');
|
||||
|
||||
console.log('5. 🔧 Удобство управления:');
|
||||
console.log(' - Используйте кнопки "Сохранить сейчас" и "Перезагрузить"');
|
||||
console.log(' - Отключите/включите автоматическое сохранение');
|
||||
console.log(' - Проверьте индикацию состояний загрузки/сохранения');
|
||||
console.log('');
|
||||
|
||||
console.log('🎯 Преимущества улучшений:');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Надежность:');
|
||||
console.log('- Транзакции обеспечивают целостность данных');
|
||||
console.log('- Автоматическое сохранение предотвращает потерю данных');
|
||||
console.log('- Валидация входных данных');
|
||||
console.log('- Обработка ошибок');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Производительность:');
|
||||
console.log('- Индексы для быстрого поиска');
|
||||
console.log('- Оптимизированные SQL запросы');
|
||||
console.log('- Дебаунсинг автоматического сохранения');
|
||||
console.log('- Эффективное управление состоянием');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Удобство использования:');
|
||||
console.log('- Интуитивный интерфейс');
|
||||
console.log('- Автоматическое сохранение');
|
||||
console.log('- Визуальная обратная связь');
|
||||
console.log('- Гибкие настройки');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Масштабируемость:');
|
||||
console.log('- База данных вместо файлов');
|
||||
console.log('- API для интеграции');
|
||||
console.log('- Структурированные данные');
|
||||
console.log('- Возможность расширения');
|
||||
console.log('');
|
||||
|
||||
console.log('📋 Чек-лист тестирования:');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Миграция БД:');
|
||||
console.log('- [ ] Таблица colliders создана');
|
||||
console.log('- [ ] Индексы созданы');
|
||||
console.log('- [ ] Триггеры работают');
|
||||
console.log('- [ ] Внешние ключи настроены');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ API Endpoints:');
|
||||
console.log('- [ ] GET /api/colliders/city/:cityId работает');
|
||||
console.log('- [ ] POST /api/colliders/city/:cityId работает');
|
||||
console.log('- [ ] PUT /api/colliders/:colliderId работает');
|
||||
console.log('- [ ] DELETE /api/colliders/:colliderId работает');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Автоматическое сохранение:');
|
||||
console.log('- [ ] Сохранение через 2 секунды после изменений');
|
||||
console.log('- [ ] Отмена предыдущих таймеров');
|
||||
console.log('- [ ] Индикация времени последнего сохранения');
|
||||
console.log('- [ ] Возможность отключения');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Управление:');
|
||||
console.log('- [ ] Переключение режимов TransformControls');
|
||||
console.log('- [ ] Автоматическое обновление UI параметров');
|
||||
console.log('- [ ] Удобные кнопки управления');
|
||||
console.log('- [ ] Состояния загрузки/сохранения');
|
||||
console.log('');
|
||||
|
||||
console.log('🚀 Все улучшения готовы к тестированию!');
|
||||
console.log('Откройте: http://localhost:4000/enhanced-collision-editor');
|
||||
console.log('Сначала выполните миграцию: node migrate-colliders.js');
|
||||
167
test-game-collider-visibility-fix.js
Normal file
167
test-game-collider-visibility-fix.js
Normal file
@@ -0,0 +1,167 @@
|
||||
// Исправление отображения коллизионных объектов в игре
|
||||
// Файл: test-game-collider-visibility-fix.js
|
||||
|
||||
console.log('🔧 Исправление отображения коллизионных объектов в игре');
|
||||
console.log('');
|
||||
|
||||
console.log('❓ Проблема:');
|
||||
console.log('Коллизионные объекты до сих пор видны, не смотря на то, что их непрозрачность равна нулю');
|
||||
console.log('');
|
||||
|
||||
console.log('🔍 Причина проблемы:');
|
||||
console.log('');
|
||||
|
||||
console.log('1. 🎮 Разная логика в редакторе и игре:');
|
||||
console.log(' - В редакторе: коллайдеры используют прозрачность из базы данных');
|
||||
console.log(' - В игре: коллайдеры создаются с фиксированной прозрачностью 0.001');
|
||||
console.log(' - Игра не учитывает настройки прозрачности из БД');
|
||||
console.log('');
|
||||
|
||||
console.log('2. 🔧 Фиксированная прозрачность в игре:');
|
||||
console.log(' - const material = new THREE.MeshBasicMaterial({ opacity: 0.001 })');
|
||||
console.log(' - Все коллизионные объекты имеют одинаковую прозрачность');
|
||||
console.log(' - Не учитывается значение opacity из базы данных');
|
||||
console.log('');
|
||||
|
||||
console.log('3. 👁️ Отсутствие логики невидимости:');
|
||||
console.log(' - В игре нет проверки opacity === 0');
|
||||
console.log(' - Нет установки material.visible = false');
|
||||
console.log(' - Нет использования alphaTest для правильной прозрачности');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Исправления:');
|
||||
console.log('');
|
||||
|
||||
console.log('1. 🎮 Использование прозрачности из базы данных:');
|
||||
console.log(' - const opacity = c.opacity !== undefined ? c.opacity : 0.001');
|
||||
console.log(' - Каждый коллайдер использует свою прозрачность из БД');
|
||||
console.log(' - Fallback на 0.001 для старых коллайдеров');
|
||||
console.log('');
|
||||
|
||||
console.log('2. 👁️ Логика невидимости:');
|
||||
console.log(' - if (opacity === 0) { material.visible = false; alphaTest = 0; }');
|
||||
console.log(' - else { material.visible = true; alphaTest = 0.1; }');
|
||||
console.log(' - Правильная обработка полностью прозрачных объектов');
|
||||
console.log('');
|
||||
|
||||
console.log('3. 🔧 Дополнительные функции для отладки:');
|
||||
console.log(' - window.updateColliderOpacity(opacity) - обновить прозрачность всех коллайдеров');
|
||||
console.log(' - window.toggleColliderVisibility(visible) - включить/выключить видимость');
|
||||
console.log(' - window.reloadAllColliders() - перезагрузить все коллайдеры');
|
||||
console.log('');
|
||||
|
||||
console.log('🔧 Технические детали:');
|
||||
console.log('');
|
||||
|
||||
console.log('🎮 Логика создания коллайдеров в игре:');
|
||||
console.log('- Использование прозрачности из базы данных: c.opacity');
|
||||
console.log('- Fallback на 0.001 для совместимости');
|
||||
console.log('- Проверка opacity === 0 для невидимости');
|
||||
console.log('- Установка material.visible и alphaTest');
|
||||
console.log('');
|
||||
|
||||
console.log('👁️ Обработка прозрачности:');
|
||||
console.log('- opacity = 0: material.visible = false, alphaTest = 0');
|
||||
console.log('- opacity > 0: material.visible = true, alphaTest = 0.1');
|
||||
console.log('- Применяется к каждому коллайдеру индивидуально');
|
||||
console.log('');
|
||||
|
||||
console.log('🔧 Функции отладки:');
|
||||
console.log('- updateColliderOpacity(opacity): обновить прозрачность всех коллайдеров');
|
||||
console.log('- toggleColliderVisibility(visible): включить/выключить видимость');
|
||||
console.log('- reloadAllColliders(): перезагрузить все коллайдеры из БД');
|
||||
console.log('- checkCollidersInDB(): проверить состояние БД');
|
||||
console.log('');
|
||||
|
||||
console.log('🧪 Как тестировать исправления:');
|
||||
console.log('');
|
||||
|
||||
console.log('1. 🎮 Тест прозрачности в игре:');
|
||||
console.log(' - Откройте игру: http://localhost:4000');
|
||||
console.log(' - Проверьте консоль: window.checkCollidersInDB()');
|
||||
console.log(' - Убедитесь, что коллайдеры загружены из БД');
|
||||
console.log(' - Коллайдеры с opacity = 0 должны быть невидимы');
|
||||
console.log(' - Коллайдеры с opacity > 0 должны быть видимы');
|
||||
console.log('');
|
||||
|
||||
console.log('2. 🔧 Тест функций отладки:');
|
||||
console.log(' - window.updateColliderOpacity(0) - сделать все невидимыми');
|
||||
console.log(' - window.updateColliderOpacity(0.5) - сделать полупрозрачными');
|
||||
console.log(' - window.toggleColliderVisibility(false) - выключить видимость');
|
||||
console.log(' - window.toggleColliderVisibility(true) - включить видимость');
|
||||
console.log('');
|
||||
|
||||
console.log('3. 🔄 Тест перезагрузки:');
|
||||
console.log(' - window.reloadAllColliders() - перезагрузить все коллайдеры');
|
||||
console.log(' - Проверьте, что прозрачность применяется корректно');
|
||||
console.log(' - Убедитесь, что коллайдеры с opacity = 0 невидимы');
|
||||
console.log('');
|
||||
|
||||
console.log('4. 📊 Тест синхронизации с редактором:');
|
||||
console.log(' - Откройте редактор коллизий');
|
||||
console.log(' - Установите прозрачность коллайдера в 0');
|
||||
console.log(' - Сохраните изменения');
|
||||
console.log(' - Вернитесь в игру');
|
||||
console.log(' - Выполните window.reloadAllColliders()');
|
||||
console.log(' - Коллайдер должен стать невидимым');
|
||||
console.log('');
|
||||
|
||||
console.log('5. 🎯 Тест с разными значениями прозрачности:');
|
||||
console.log(' - Создайте коллайдеры с разной прозрачностью (0, 0.3, 0.7, 1)');
|
||||
console.log(' - Сохраните изменения');
|
||||
console.log(' - Перезагрузите игру');
|
||||
console.log(' - Проверьте, что каждый коллайдер имеет правильную прозрачность');
|
||||
console.log('');
|
||||
|
||||
console.log('🎯 Ожидаемые результаты:');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Прозрачность в игре:');
|
||||
console.log('- [ ] Коллайдеры с opacity = 0 полностью невидимы');
|
||||
console.log('- [ ] Коллайдеры с opacity > 0 видимы с правильной прозрачностью');
|
||||
console.log('- [ ] Каждый коллайдер использует свою прозрачность из БД');
|
||||
console.log('- [ ] Fallback на 0.001 для старых коллайдеров');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Функции отладки:');
|
||||
console.log('- [ ] window.updateColliderOpacity() работает корректно');
|
||||
console.log('- [ ] window.toggleColliderVisibility() работает корректно');
|
||||
console.log('- [ ] window.reloadAllColliders() обновляет прозрачность');
|
||||
console.log('- [ ] window.checkCollidersInDB() показывает правильные данные');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Синхронизация с редактором:');
|
||||
console.log('- [ ] Изменения прозрачности в редакторе отражаются в игре');
|
||||
console.log('- [ ] Коллайдеры с opacity = 0 невидимы в обоих местах');
|
||||
console.log('- [ ] Отсутствие рассинхронизации');
|
||||
console.log('- [ ] Корректная работа автоматического сохранения');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Производительность:');
|
||||
console.log('- [ ] Быстрая загрузка коллайдеров с правильной прозрачностью');
|
||||
console.log('- [ ] Отсутствие задержек при перезагрузке');
|
||||
console.log('- [ ] Стабильная работа коллизий');
|
||||
console.log('- [ ] Корректная работа прозрачности');
|
||||
console.log('');
|
||||
|
||||
console.log('🔍 Отладочная информация:');
|
||||
console.log('');
|
||||
|
||||
console.log('📊 В консоли должно появляться:');
|
||||
console.log('- "📊 Коллайдеры в БД: X штук"');
|
||||
console.log('- "👁️ Обновляем прозрачность всех коллизионных объектов: Y"');
|
||||
console.log('- "✅ Прозрачность обновлена для Z коллизионных объектов"');
|
||||
console.log('- "👁️ Переключаем видимость коллизионных объектов: true/false"');
|
||||
console.log('- "✅ Видимость коллизионных объектов: включена/выключена"');
|
||||
console.log('');
|
||||
|
||||
console.log('🎯 Проверка в игре:');
|
||||
console.log('- Коллайдеры с opacity = 0 не должны быть видны');
|
||||
console.log('- Коллайдеры с opacity > 0 должны быть видны с правильной прозрачностью');
|
||||
console.log('- Функции отладки должны работать корректно');
|
||||
console.log('- Перезагрузка должна обновлять прозрачность');
|
||||
console.log('');
|
||||
|
||||
console.log('🚀 Исправления готовы к тестированию!');
|
||||
console.log('Откройте игру: http://localhost:4000');
|
||||
console.log('Протестируйте прозрачность коллизионных объектов и функции отладки');
|
||||
153
test-game-colliders-loading.js
Normal file
153
test-game-colliders-loading.js
Normal file
@@ -0,0 +1,153 @@
|
||||
// Исправление загрузки коллайдеров в игре
|
||||
// Файл: test-game-colliders-loading.js
|
||||
|
||||
console.log('🔧 Исправление загрузки коллайдеров в игре');
|
||||
console.log('');
|
||||
|
||||
console.log('❓ Проблема:');
|
||||
console.log('Редактор коллизий работает с базой данных, но сама игра загружает коллайдеры из JSON файла');
|
||||
console.log('Коллайдеры, созданные в редакторе, не отображаются в игре');
|
||||
console.log('');
|
||||
|
||||
console.log('🔍 Причина проблемы:');
|
||||
console.log('');
|
||||
|
||||
console.log('1. 🔄 Разные источники данных:');
|
||||
console.log(' - Редактор коллизий: загружает из /api/colliders/city/:cityId (база данных)');
|
||||
console.log(' - Игра: загружает из /colliders_city_1.json (JSON файл)');
|
||||
console.log(' - Данные не синхронизируются между источниками');
|
||||
console.log('');
|
||||
|
||||
console.log('2. 📊 Две функции загрузки в Game.js:');
|
||||
console.log(' - loadCollidersFromJSON(): для коллизионных данных (Box3)');
|
||||
console.log(' - loadCustomCollidersForCity(): для визуальных коллайдеров (Mesh)');
|
||||
console.log(' - Обе использовали только JSON файлы');
|
||||
console.log('');
|
||||
|
||||
console.log('3. 🗄️ Отсутствие fallback механизма:');
|
||||
console.log(' - Игра не могла загрузить данные из базы данных');
|
||||
console.log(' - Нет резервного варианта при недоступности БД');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Исправления:');
|
||||
console.log('');
|
||||
|
||||
console.log('1. 🔄 Обновление loadCollidersFromJSON():');
|
||||
console.log(' - Сначала пробует загрузить из /api/colliders/city/:cityId');
|
||||
console.log(' - При 500 ошибке fallback на /colliders_city_1.json');
|
||||
console.log(' - Обрабатывает данные из обоих источников');
|
||||
console.log('');
|
||||
|
||||
console.log('2. 🔄 Обновление loadCustomCollidersForCity():');
|
||||
console.log(' - Сначала пробует загрузить из /api/colliders/city/:cityId');
|
||||
console.log(' - При 500 ошибке fallback на /api/colliders?cityId=:cityId');
|
||||
console.log(' - Создает визуальные меши для коллайдеров');
|
||||
console.log('');
|
||||
|
||||
console.log('3. 📊 Улучшенная обработка данных:');
|
||||
console.log(' - Проверка формата данных (data.colliders vs Array)');
|
||||
console.log(' - Логирование источника данных');
|
||||
console.log(' - Отладочная информация для диагностики');
|
||||
console.log('');
|
||||
|
||||
console.log('🔧 Технические детали:');
|
||||
console.log('');
|
||||
|
||||
console.log('🔄 Логика загрузки:');
|
||||
console.log('- Первая попытка: /api/colliders/city/:cityId (база данных)');
|
||||
console.log('- Fallback: JSON файлы или старый API');
|
||||
console.log('- Проверка ответа: response.ok && response.status !== 500');
|
||||
console.log('- Обработка данных: data.colliders || data (массив)');
|
||||
console.log('');
|
||||
|
||||
console.log('📊 Два типа коллайдеров в игре:');
|
||||
console.log('- Коллизионные (Box3): для проверки столкновений');
|
||||
console.log('- Визуальные (Mesh): для отображения в сцене');
|
||||
console.log('- Оба типа теперь загружаются из базы данных');
|
||||
console.log('');
|
||||
|
||||
console.log('🗄️ API endpoints:');
|
||||
console.log('- Новый: GET /api/colliders/city/:cityId (база данных)');
|
||||
console.log('- Старый: GET /api/colliders?cityId=:cityId (JSON файлы)');
|
||||
console.log('- Fallback: GET /colliders_city_1.json (прямые файлы)');
|
||||
console.log('');
|
||||
|
||||
console.log('🧪 Как тестировать исправления:');
|
||||
console.log('');
|
||||
|
||||
console.log('1. 🎮 Запуск игры:');
|
||||
console.log(' - Откройте игру: http://localhost:4000');
|
||||
console.log(' - Проверьте консоль браузера');
|
||||
console.log(' - Должно появиться: "📊 Загружены коллайдеры из базы данных"');
|
||||
console.log(' - Или: "📄 Загружены коллайдеры из JSON файла" (fallback)');
|
||||
console.log('');
|
||||
|
||||
console.log('2. 🔍 Проверка коллайдеров:');
|
||||
console.log(' - Коллайдеры должны быть видны в игре');
|
||||
console.log(' - Коллизии должны работать корректно');
|
||||
console.log(' - Проверьте, что персонаж не проходит через коллайдеры');
|
||||
console.log('');
|
||||
|
||||
console.log('3. 🔄 Синхронизация с редактором:');
|
||||
console.log(' - Создайте коллайдер в редакторе коллизий');
|
||||
console.log(' - Сохраните изменения');
|
||||
console.log(' - Перезагрузите игру');
|
||||
console.log(' - Новый коллайдер должен появиться в игре');
|
||||
console.log('');
|
||||
|
||||
console.log('4. 🗄️ Тест fallback:');
|
||||
console.log(' - Остановите сервер базы данных');
|
||||
console.log(' - Перезагрузите игру');
|
||||
console.log(' - Должно появиться: "🔄 Новый API недоступен, пробуем старый JSON API"');
|
||||
console.log(' - Игра должна загрузиться с данными из JSON файлов');
|
||||
console.log('');
|
||||
|
||||
console.log('5. 📊 Отладочная информация:');
|
||||
console.log(' - Проверьте консоль на наличие ошибок');
|
||||
console.log(' - Должны быть логи о загрузке коллайдеров');
|
||||
console.log(' - Проверьте количество загруженных коллайдеров');
|
||||
console.log('');
|
||||
|
||||
console.log('🎯 Ожидаемые результаты:');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Загрузка из базы данных:');
|
||||
console.log('- [ ] Игра загружает коллайдеры из БД');
|
||||
console.log('- [ ] Коллайдеры из редактора видны в игре');
|
||||
console.log('- [ ] Коллизии работают корректно');
|
||||
console.log('- [ ] Синхронизация между редактором и игрой');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Fallback механизм:');
|
||||
console.log('- [ ] При недоступности БД загружаются JSON файлы');
|
||||
console.log('- [ ] Игра работает в любом случае');
|
||||
console.log('- [ ] Логирование источника данных');
|
||||
console.log('- [ ] Отсутствие критических ошибок');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Производительность:');
|
||||
console.log('- [ ] Быстрая загрузка коллайдеров');
|
||||
console.log('- [ ] Отсутствие задержек в игре');
|
||||
console.log('- [ ] Корректная работа коллизий');
|
||||
console.log('- [ ] Стабильная работа при переключении городов');
|
||||
console.log('');
|
||||
|
||||
console.log('🔍 Отладочная информация:');
|
||||
console.log('');
|
||||
|
||||
console.log('📊 В консоли должно появляться:');
|
||||
console.log('- "🔍 loadCollidersFromJSON вызвана для города: 1"');
|
||||
console.log('- "📊 Загружены коллайдеры из базы данных: X объектов"');
|
||||
console.log('- "🔍 loadCustomCollidersForCity для города: 1"');
|
||||
console.log('- "📊 Загружены кастомные коллайдеры из базы данных: X объектов"');
|
||||
console.log('');
|
||||
|
||||
console.log('🎯 Проверка в игре:');
|
||||
console.log('- Коллайдеры должны быть видны (если включена визуализация)');
|
||||
console.log('- Персонаж не должен проходить через коллайдеры');
|
||||
console.log('- Коллизии должны работать плавно');
|
||||
console.log('');
|
||||
|
||||
console.log('🚀 Исправления готовы к тестированию!');
|
||||
console.log('Откройте игру: http://localhost:4000');
|
||||
console.log('Проверьте консоль и убедитесь, что коллайдеры загружаются из базы данных');
|
||||
176
test-opacity-collision-fixes.js
Normal file
176
test-opacity-collision-fixes.js
Normal file
@@ -0,0 +1,176 @@
|
||||
// Исправление проблем с прозрачностью и коллизиями
|
||||
// Файл: test-opacity-collision-fixes.js
|
||||
|
||||
console.log('🔧 Исправление проблем с прозрачностью и коллизиями');
|
||||
console.log('');
|
||||
|
||||
console.log('❓ Проблемы:');
|
||||
console.log('1) Даже когда у коллайдера прозрачность 0, всё равно его видно');
|
||||
console.log('2) В старом json был объект, сейчас я удалил, его не видно, но при этом сквозь него я всё равно пройти не могу');
|
||||
console.log('');
|
||||
|
||||
console.log('🔍 Причины проблем:');
|
||||
console.log('');
|
||||
|
||||
console.log('1. 👁️ Проблема с прозрачностью:');
|
||||
console.log(' - В Three.js opacity = 0 не делает объект полностью невидимым');
|
||||
console.log(' - Нужно дополнительно установить visible = false');
|
||||
console.log(' - Или использовать alphaTest для правильной обработки прозрачности');
|
||||
console.log('');
|
||||
|
||||
console.log('2. 🚫 Проблема с коллизиями удаленных коллайдеров:');
|
||||
console.log(' - Игра загружает коллайдеры из разных источников');
|
||||
console.log(' - Коллизионные коллайдеры (Box3) и визуальные (Mesh) загружаются отдельно');
|
||||
console.log(' - При удалении коллайдера из редактора игра может не перезагрузить коллайдеры');
|
||||
console.log(' - Кэширование или рассинхронизация между источниками');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Исправления:');
|
||||
console.log('');
|
||||
|
||||
console.log('1. 👁️ Исправление прозрачности:');
|
||||
console.log(' - Добавлена проверка opacity === 0');
|
||||
console.log(' - При opacity = 0: material.visible = false, alphaTest = 0');
|
||||
console.log(' - При opacity > 0: material.visible = true, alphaTest = 0.1');
|
||||
console.log(' - Обновлены все функции создания и изменения коллайдеров');
|
||||
console.log('');
|
||||
|
||||
console.log('2. 🚫 Исправление коллизий удаленных коллайдеров:');
|
||||
console.log(' - Добавлена функция window.reloadAllColliders() в игре');
|
||||
console.log(' - Добавлена функция window.checkCollidersInDB() для диагностики');
|
||||
console.log(' - Перезагрузка как коллизионных, так и визуальных коллайдеров');
|
||||
console.log(' - Сравнение состояния БД с состоянием игры');
|
||||
console.log('');
|
||||
|
||||
console.log('3. 🔄 Улучшенная синхронизация:');
|
||||
console.log(' - Функция reloadColliders в редакторе');
|
||||
console.log(' - Кнопка "🔄 Синхронизировать" в UI редактора');
|
||||
console.log(' - Глобальные функции для отладки в игре');
|
||||
console.log('');
|
||||
|
||||
console.log('🔧 Технические детали:');
|
||||
console.log('');
|
||||
|
||||
console.log('👁️ Логика прозрачности:');
|
||||
console.log('- if (opacity === 0) { material.visible = false; alphaTest = 0; }');
|
||||
console.log('- else { material.visible = true; alphaTest = 0.1; }');
|
||||
console.log('- Применяется к colliderMaterial, загруженным коллайдерам, изменениям в UI');
|
||||
console.log('');
|
||||
|
||||
console.log('🚫 Логика перезагрузки коллайдеров:');
|
||||
console.log('- loadCollidersFromJSON(1) - коллизионные коллайдеры (Box3)');
|
||||
console.log('- loadCustomCollidersForCity(1) - визуальные коллайдеры (Mesh)');
|
||||
console.log('- window.reloadAllColliders() - перезагрузка всех типов');
|
||||
console.log('- window.checkCollidersInDB() - диагностика состояния');
|
||||
console.log('');
|
||||
|
||||
console.log('🔄 Источники коллайдеров в игре:');
|
||||
console.log('- Коллизионные: jsonCollidersRef.current (Box3 объекты)');
|
||||
console.log('- Визуальные: visualCollidersRef.current (Mesh объекты)');
|
||||
console.log('- Оба загружаются из /api/colliders/city/1 с fallback на JSON');
|
||||
console.log('');
|
||||
|
||||
console.log('🧪 Как тестировать исправления:');
|
||||
console.log('');
|
||||
|
||||
console.log('1. 👁️ Тест прозрачности:');
|
||||
console.log(' - Откройте редактор коллизий');
|
||||
console.log(' - Выберите коллайдер');
|
||||
console.log(' - Установите прозрачность в 0');
|
||||
console.log(' - Нажмите "Применить цвет"');
|
||||
console.log(' - Коллайдер должен стать полностью невидимым');
|
||||
console.log(' - Установите прозрачность обратно в 0.3');
|
||||
console.log(' - Коллайдер должен стать видимым');
|
||||
console.log('');
|
||||
|
||||
console.log('2. 🚫 Тест коллизий удаленных коллайдеров:');
|
||||
console.log(' - Откройте игру');
|
||||
console.log(' - Проверьте консоль: window.checkCollidersInDB()');
|
||||
console.log(' - Убедитесь, что коллайдеры загружены из БД');
|
||||
console.log(' - Откройте редактор коллизий');
|
||||
console.log(' - Удалите коллайдер');
|
||||
console.log(' - Вернитесь в игру');
|
||||
console.log(' - Выполните: window.reloadAllColliders()');
|
||||
console.log(' - Проверьте, что коллизии исчезли');
|
||||
console.log('');
|
||||
|
||||
console.log('3. 🔄 Тест синхронизации:');
|
||||
console.log(' - В редакторе: нажмите "🔄 Синхронизировать"');
|
||||
console.log(' - В игре: выполните window.reloadAllColliders()');
|
||||
console.log(' - Проверьте консоль на наличие ошибок');
|
||||
console.log(' - Убедитесь, что количество коллайдеров совпадает');
|
||||
console.log('');
|
||||
|
||||
console.log('4. 📊 Диагностика:');
|
||||
console.log(' - В игре: window.checkCollidersInDB()');
|
||||
console.log(' - Проверьте количество коллайдеров в БД vs в игре');
|
||||
console.log(' - Убедитесь, что данные синхронизированы');
|
||||
console.log('');
|
||||
|
||||
console.log('5. 🎯 Тест с несколькими коллайдерами:');
|
||||
console.log(' - Создайте несколько коллайдеров с разной прозрачностью');
|
||||
console.log(' - Удалите некоторые из них');
|
||||
console.log(' - Сохраните изменения');
|
||||
console.log(' - Перезагрузите игру');
|
||||
console.log(' - Выполните window.reloadAllColliders()');
|
||||
console.log(' - Проверьте, что только нужные коллайдеры остались');
|
||||
console.log('');
|
||||
|
||||
console.log('🎯 Ожидаемые результаты:');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Прозрачность:');
|
||||
console.log('- [ ] Коллайдеры с opacity = 0 полностью невидимы');
|
||||
console.log('- [ ] Коллайдеры с opacity > 0 видимы с правильной прозрачностью');
|
||||
console.log('- [ ] Изменения прозрачности применяются мгновенно');
|
||||
console.log('- [ ] Сохранение прозрачности работает корректно');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Коллизии удаленных коллайдеров:');
|
||||
console.log('- [ ] Удаленные коллайдеры не создают коллизий');
|
||||
console.log('- [ ] window.reloadAllColliders() обновляет все коллайдеры');
|
||||
console.log('- [ ] Синхронизация между редактором и игрой');
|
||||
console.log('- [ ] Отсутствие "призрачных" коллизий');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Синхронизация:');
|
||||
console.log('- [ ] Кнопка "Синхронизировать" в редакторе работает');
|
||||
console.log('- [ ] window.reloadAllColliders() в игре работает');
|
||||
console.log('- [ ] window.checkCollidersInDB() показывает правильные данные');
|
||||
console.log('- [ ] Отсутствие рассинхронизации');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Производительность:');
|
||||
console.log('- [ ] Быстрая перезагрузка коллайдеров');
|
||||
console.log('- [ ] Отсутствие задержек в игре');
|
||||
console.log('- [ ] Стабильная работа коллизий');
|
||||
console.log('- [ ] Корректная работа прозрачности');
|
||||
console.log('');
|
||||
|
||||
console.log('🔍 Отладочная информация:');
|
||||
console.log('');
|
||||
|
||||
console.log('📊 В консоли должно появляться:');
|
||||
console.log('- "🔄 Принудительная перезагрузка всех коллайдеров"');
|
||||
console.log('- "✅ Коллизионные коллайдеры перезагружены"');
|
||||
console.log('- "✅ Визуальные коллайдеры перезагружены"');
|
||||
console.log('- "📊 Коллайдеры в БД: X штук"');
|
||||
console.log('- "📊 Коллизионные коллайдеры в игре: Y штук"');
|
||||
console.log('');
|
||||
|
||||
console.log('🎯 Проверка прозрачности:');
|
||||
console.log('- Коллайдеры с opacity = 0 не должны быть видны');
|
||||
console.log('- Коллайдеры с opacity > 0 должны быть видны с правильной прозрачностью');
|
||||
console.log('- Изменения должны применяться мгновенно');
|
||||
console.log('');
|
||||
|
||||
console.log('🎯 Проверка коллизий:');
|
||||
console.log('- Удаленные коллайдеры не должны создавать коллизий');
|
||||
console.log('- Персонаж должен проходить через места, где были удаленные коллайдеры');
|
||||
console.log('- Коллизии должны работать только для существующих коллайдеров');
|
||||
console.log('');
|
||||
|
||||
console.log('🚀 Исправления готовы к тестированию!');
|
||||
console.log('Откройте редактор: http://localhost:4000/enhanced-collision-editor');
|
||||
console.log('Откройте игру: http://localhost:4000');
|
||||
console.log('Протестируйте прозрачность и коллизии удаленных коллайдеров');
|
||||
164
test-wireframe-fix.js
Normal file
164
test-wireframe-fix.js
Normal file
@@ -0,0 +1,164 @@
|
||||
// Исправление проблемы с рамками коллайдеров
|
||||
// Файл: test-wireframe-fix.js
|
||||
|
||||
console.log('🔧 Исправление проблемы с рамками коллайдеров');
|
||||
console.log('');
|
||||
|
||||
console.log('❓ Проблема:');
|
||||
console.log('У каждого коллайдера два объекта: один только рамка, другой полностью закрашен');
|
||||
console.log('При перемещении только рамки не сохраняется перемещение');
|
||||
console.log('При перемещении полностью закрашенного объекта всё сохраняется');
|
||||
console.log('');
|
||||
|
||||
console.log('🔍 Причина проблемы:');
|
||||
console.log('');
|
||||
|
||||
console.log('1. 🏗️ Структура коллайдеров:');
|
||||
console.log(' - Каждый коллайдер состоит из основного меша (mesh) и рамки (line)');
|
||||
console.log(' - Рамка добавляется как дочерний объект: mesh.add(line)');
|
||||
console.log(' - При клике можно выбрать либо основной меш, либо рамку');
|
||||
console.log('');
|
||||
|
||||
console.log('2. 🎯 Проблема выбора:');
|
||||
console.log(' - Рамка (LineSegments) не имеет userData с параметрами коллайдера');
|
||||
console.log(' - Только основной меш имеет правильные userData и обновляется в collidersRef');
|
||||
console.log(' - При выборе рамки TransformControls прикрепляется к ней, но данные не сохраняются');
|
||||
console.log('');
|
||||
|
||||
console.log('3. 💾 Проблема сохранения:');
|
||||
console.log(' - updateColliderData работает только с основными мешами');
|
||||
console.log(' - Рамки не участвуют в процессе сохранения');
|
||||
console.log(' - Перемещение рамки не влияет на позицию основного меша');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Исправления:');
|
||||
console.log('');
|
||||
|
||||
console.log('1. 🎯 Улучшенная логика выбора:');
|
||||
console.log(' - Raycaster теперь проверяет все объекты коллайдеров (меши + рамки)');
|
||||
console.log(' - При клике по рамке автоматически выбирается родительский меш');
|
||||
console.log(' - Проверка, что выбранный объект действительно является коллайдером');
|
||||
console.log('');
|
||||
|
||||
console.log('2. 🔲 Опция отключения рамок:');
|
||||
console.log(' - Новое состояние showWireframes для управления видимостью');
|
||||
console.log(' - Функция toggleWireframes для переключения видимости');
|
||||
console.log(' - Кнопка в UI для удобного управления');
|
||||
console.log('');
|
||||
|
||||
console.log('3. 🏗️ Обновление создания коллайдеров:');
|
||||
console.log(' - Новые коллайдеры учитывают настройку видимости рамок');
|
||||
console.log(' - Дублированные коллайдеры учитывают настройку видимости рамок');
|
||||
console.log(' - Загруженные коллайдеры учитывают настройку видимости рамок');
|
||||
console.log('');
|
||||
|
||||
console.log('🔧 Технические детали:');
|
||||
console.log('');
|
||||
|
||||
console.log('🎯 Логика выбора:');
|
||||
console.log('- allColliderObjects = [основные меши, рамки]');
|
||||
console.log('- if (clickedObject.type === "LineSegments") clickedObject = clickedObject.parent');
|
||||
console.log('- Проверка через collidersRef.current.find(c => c.mesh === clickedObject)');
|
||||
console.log('');
|
||||
|
||||
console.log('🔲 Управление рамками:');
|
||||
console.log('- showWireframes: boolean состояние');
|
||||
console.log('- toggleWireframes(): переключает видимость всех рамок');
|
||||
console.log('- line.visible = showWireframes при создании');
|
||||
console.log('- child.visible = newShowWireframes при переключении');
|
||||
console.log('');
|
||||
|
||||
console.log('🏗️ Структура коллайдера:');
|
||||
console.log('- mesh (основной меш с материалом)');
|
||||
console.log('- mesh.children[0] (рамка LineSegments)');
|
||||
console.log('- mesh.userData (параметры коллайдера)');
|
||||
console.log('- collidersRef содержит ссылки на основные меши');
|
||||
console.log('');
|
||||
|
||||
console.log('🧪 Как тестировать исправления:');
|
||||
console.log('');
|
||||
|
||||
console.log('1. 🎯 Выбор коллайдеров:');
|
||||
console.log(' - Загрузите редактор коллизий');
|
||||
console.log(' - Попробуйте кликнуть по рамке коллайдера');
|
||||
console.log(' - Проверьте консоль: "🎯 Кликнули по рамке, выбираем родительский меш"');
|
||||
console.log(' - Убедитесь, что TransformControls прикрепился к основному мешу');
|
||||
console.log(' - Переместите коллайдер и сохраните');
|
||||
console.log(' - Перезагрузите страницу и проверьте, что позиция сохранилась');
|
||||
console.log('');
|
||||
|
||||
console.log('2. 🔲 Переключение рамок:');
|
||||
console.log(' - Нажмите кнопку "🔲 Скрыть рамки"');
|
||||
console.log(' - Проверьте консоль: "🔲 Рамки отключены"');
|
||||
console.log(' - Убедитесь, что все рамки исчезли');
|
||||
console.log(' - Нажмите кнопку "🔲 Показать рамки"');
|
||||
console.log(' - Проверьте консоль: "🔲 Рамки включены"');
|
||||
console.log(' - Убедитесь, что все рамки появились');
|
||||
console.log('');
|
||||
|
||||
console.log('3. 🆕 Создание с отключенными рамками:');
|
||||
console.log(' - Отключите рамки');
|
||||
console.log(' - Создайте новый коллайдер');
|
||||
console.log(' - Убедитесь, что новый коллайдер создался без рамки');
|
||||
console.log(' - Включите рамки');
|
||||
console.log(' - Убедитесь, что рамка появилась у нового коллайдера');
|
||||
console.log('');
|
||||
|
||||
console.log('4. 🔄 Дублирование с отключенными рамками:');
|
||||
console.log(' - Отключите рамки');
|
||||
console.log(' - Дублируйте существующий коллайдер');
|
||||
console.log(' - Убедитесь, что дублированный коллайдер создался без рамки');
|
||||
console.log(' - Включите рамки');
|
||||
console.log(' - Убедитесь, что рамка появилась у дублированного коллайдера');
|
||||
console.log('');
|
||||
|
||||
console.log('5. 💾 Сохранение перемещений:');
|
||||
console.log(' - Кликните по рамке коллайдера');
|
||||
console.log(' - Переместите его в новое место');
|
||||
console.log(' - Нажмите "Сохранить сейчас"');
|
||||
console.log(' - Перезагрузите страницу');
|
||||
console.log(' - Убедитесь, что коллайдер остался в новом месте');
|
||||
console.log('');
|
||||
|
||||
console.log('🎯 Ожидаемые результаты:');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Выбор коллайдеров:');
|
||||
console.log('- [ ] Клик по рамке выбирает основной меш');
|
||||
console.log('- [ ] TransformControls прикрепляется к основному мешу');
|
||||
console.log('- [ ] Перемещение рамки перемещает весь коллайдер');
|
||||
console.log('- [ ] Сохранение работает корректно');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Управление рамками:');
|
||||
console.log('- [ ] Кнопка переключает видимость всех рамок');
|
||||
console.log('- [ ] Новые коллайдеры учитывают настройку');
|
||||
console.log('- [ ] Дублированные коллайдеры учитывают настройку');
|
||||
console.log('- [ ] Загруженные коллайдеры учитывают настройку');
|
||||
console.log('');
|
||||
|
||||
console.log('✅ Сохранение перемещений:');
|
||||
console.log('- [ ] Перемещение через рамку сохраняется');
|
||||
console.log('- [ ] Перемещение через основной меш сохраняется');
|
||||
console.log('- [ ] Автоматическое сохранение работает');
|
||||
console.log('- [ ] Ручное сохранение работает');
|
||||
console.log('');
|
||||
|
||||
console.log('🔍 Отладочная информация:');
|
||||
console.log('');
|
||||
|
||||
console.log('📊 В консоли должно появляться:');
|
||||
console.log('- "🎯 Кликнули по рамке, выбираем родительский меш"');
|
||||
console.log('- "🔲 Рамки включены/отключены"');
|
||||
console.log('- "🎯 Выбран коллайдер: [объект]"');
|
||||
console.log('');
|
||||
|
||||
console.log('🎯 Проверка структуры:');
|
||||
console.log('- selected.type должен быть "Mesh" (не "LineSegments")');
|
||||
console.log('- selected.userData должен содержать параметры коллайдера');
|
||||
console.log('- selected.children[0].type должен быть "LineSegments"');
|
||||
console.log('');
|
||||
|
||||
console.log('🚀 Исправления готовы к тестированию!');
|
||||
console.log('Откройте: http://localhost:4000/enhanced-collision-editor');
|
||||
console.log('Попробуйте кликнуть по рамке коллайдера и переместить его');
|
||||
Reference in New Issue
Block a user