fix(rbxl-import): UDim2 viewport-relative + rbxasset URL filter
All checks were successful
All checks were successful
- UDim2: scale теперь умножается на viewport reference (1280×720), раньше игнорировался — фреймы получали 0×0 и фейлились на дефолт 100×30 или наоборот заполняли всё окно - _udim2_pair(): пара (x,y) через _udim2_to_rublox(axis='x'|'y') - Фильтр rbxasset:// rbxassetid:// rbxhttp:// rbxthumb:// URL'ов на пустую строку — браузер их не загружает, спам в console исчезает Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
624bbc636b
commit
cc6447b851
@ -725,22 +725,28 @@ class Converter:
|
||||
return None # top-level в ScreenGui = parentId=None в Rublox
|
||||
return f'rbx_gui_{parent_ref}'
|
||||
|
||||
def _udim2_to_rublox(self, udim2, default_scale=None) -> Tuple[float, float]:
|
||||
"""Roblox UDim2(scale, offset) → pixel x/y для Rublox GUI.
|
||||
Берём только offset (scale*screen игнорим: точную viewport-ширину не знаем
|
||||
в момент импорта). Если offset=0 а scale≠0 — used 1280×720 как референс.
|
||||
def _udim2_to_rublox(self, udim2, axis: str = 'x') -> int:
|
||||
"""Roblox UDim2(scale, offset) → pixel размер для Rublox GUI.
|
||||
Reference viewport: 1280×720 (стандарт Roblox при импорте).
|
||||
axis='x' → используется ширина 1280, 'y' → высота 720.
|
||||
"""
|
||||
if udim2 is None:
|
||||
return 0
|
||||
ref = 1280 if axis == 'x' else 720
|
||||
if isinstance(udim2, dict):
|
||||
scale = udim2.get('scale', 0) or 0
|
||||
offset = udim2.get('offset', 0) or 0
|
||||
return int(offset + scale * ref)
|
||||
return 0
|
||||
|
||||
def _udim2_pair(self, udim2) -> Tuple[int, int]:
|
||||
"""UDim2 = {x: UDim, y: UDim} → (px, py)."""
|
||||
if not isinstance(udim2, dict):
|
||||
return (0, 0)
|
||||
# Формат: UDim2 = {x: UDim(scale, offset), y: UDim(scale, offset)}
|
||||
x_obj = udim2.get('x') if isinstance(udim2, dict) else None
|
||||
y_obj = udim2.get('y') if isinstance(udim2, dict) else None
|
||||
def resolve(u):
|
||||
if not u: return 0
|
||||
scale = u.get('scale', 0) if isinstance(u, dict) else 0
|
||||
offset = u.get('offset', 0) if isinstance(u, dict) else 0
|
||||
return int(offset + scale * 1280)
|
||||
return (resolve(x_obj), resolve(y_obj))
|
||||
return (
|
||||
self._udim2_to_rublox(udim2.get('x'), 'x'),
|
||||
self._udim2_to_rublox(udim2.get('y'), 'y'),
|
||||
)
|
||||
|
||||
def _color3_to_hex(self, c3) -> str:
|
||||
if c3 is None:
|
||||
@ -770,12 +776,19 @@ class Converter:
|
||||
else:
|
||||
r_type = 'frame'
|
||||
|
||||
pos_x, pos_y = self._udim2_to_rublox(props.get('Position'))
|
||||
size_x, size_y = self._udim2_to_rublox(props.get('Size'))
|
||||
pos_x, pos_y = self._udim2_pair(props.get('Position'))
|
||||
size_x, size_y = self._udim2_pair(props.get('Size'))
|
||||
# Size может быть 0×0 (если только scale) — дефолтим в 100×30
|
||||
if size_x <= 0: size_x = 100
|
||||
if size_y <= 0: size_y = 30
|
||||
|
||||
# Фильтр Roblox CDN URL'ов: rbxasset://, rbxassetid://, rbxhttp:// —
|
||||
# браузер их не поймёт, даём пустую строку. В будущем asset_downloader
|
||||
# может подменить на cached_url.
|
||||
raw_image = str(props.get('Image', '') or '')
|
||||
if raw_image.startswith(('rbxasset://', 'rbxassetid://', 'rbxhttp://', 'rbxthumb://')):
|
||||
raw_image = ''
|
||||
|
||||
element = {
|
||||
'id': f'rbx_gui_{inst.referent}',
|
||||
'type': r_type,
|
||||
@ -797,7 +810,7 @@ class Converter:
|
||||
'textSize': int(props.get('TextSize', 14) or 14),
|
||||
'textAlign': 'center',
|
||||
'fontWeight': 700 if cls in ('TextButton',) else 500,
|
||||
'imageUrl': str(props.get('Image', '') or ''),
|
||||
'imageUrl': raw_image,
|
||||
'imageAsset': None,
|
||||
'zIndex': int(props.get('ZIndex', 1) or 1),
|
||||
'origin': 'roblox-' + cls.lower(),
|
||||
|
||||
@ -13,7 +13,7 @@ import { RobloxLuaSharedSandbox } from './RobloxLuaSharedSandbox.js';
|
||||
|
||||
/**
|
||||
* Распаковывает Lua-исходник из поля code упакованного rbxl-importer'ом.
|
||||
* Формат: `// @roblox-lua\n// {meta json}\n/* lua_source:\n<код>\n*/`
|
||||
* Формат: "// @roblox-lua\\n// {meta json}\\n/[*] lua_source:\\n<код>\\n[*]/"
|
||||
*/
|
||||
export function unpackRobloxLuaCode(code) {
|
||||
const openTag = '/* lua_source:\n';
|
||||
@ -153,8 +153,3 @@ export function handleLuaCommand(_scriptId, cmd, payload, runtime) {
|
||||
}
|
||||
}
|
||||
|
||||
/* ──────── Legacy single-script API (для обратной совместимости) ──────── */
|
||||
// Старая логика per-script Worker оставлена в RobloxLuaSandbox.js + RobloxLuaWorker.js,
|
||||
// но GameRuntime теперь использует startRobloxLuaShared. Эти экспорты не удалены
|
||||
// чтобы тесты в player/tests/ продолжали работать.
|
||||
export { startRobloxLuaShared as startRobloxLuaScript };
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user