Merge remote-tracking branch 'refs/remotes/origin/ch' into addRender
# Conflicts: # RenderPipelineFile/config/daytime.yaml
This commit is contained in:
commit
0c25623606
2
.idea/EG.iml
generated
2
.idea/EG.iml
generated
@ -5,7 +5,7 @@
|
||||
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Python 3.10 (EG)" jdkType="Python SDK" />
|
||||
<orderEntry type="jdk" jdkName="Python 3.10 (eg)" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
<component name="PyDocumentationSettings">
|
||||
|
||||
@ -5,6 +5,9 @@ import sys
|
||||
project_root = os.path.dirname(os.path.abspath(__file__))
|
||||
sys.path.insert(0, project_root)
|
||||
|
||||
# 设置工作目录为项目根目录
|
||||
os.chdir(project_root)
|
||||
|
||||
# 添加 RenderPipeline 到路径(注意路径名称应与实际目录一致)
|
||||
render_pipeline_path = os.path.join(project_root, "RenderPipeline")
|
||||
sys.path.insert(0, render_pipeline_path)
|
||||
|
||||
@ -11,5 +11,8 @@
|
||||
"enable_ssr": false,
|
||||
"shadow_quality": "medium",
|
||||
"ao_quality": "low"
|
||||
}
|
||||
},
|
||||
"anti_aliasing": "4x",
|
||||
"refresh_rate": "90Hz",
|
||||
"async_reprojection": true
|
||||
}
|
||||
95
tools/open_source_rate.py
Normal file
95
tools/open_source_rate.py
Normal file
@ -0,0 +1,95 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
THIRD_PARTY_DIR_NAMES = {
|
||||
'node_modules', 'vendor', 'third_party', 'third-party', 'extern', 'external', 'deps',
|
||||
'Cesium', 'Cesium-1.132', 'dist', 'build'
|
||||
}
|
||||
|
||||
CODE_EXTENSIONS = {
|
||||
'.py', '.js', '.ts', '.tsx', '.jsx', '.css', '.scss', '.html', '.c', '.h', '.cpp', '.hpp',
|
||||
'.cc', '.hh', '.m', '.mm', '.java', '.go', '.rs', '.cs', '.vue', '.svelte'
|
||||
}
|
||||
|
||||
SKIP_DIR_NAMES = {
|
||||
'.git', '.hg', '.svn', '__pycache__', '.mypy_cache', '.pytest_cache', '.idea', '.vscode',
|
||||
'.venv', 'venv', 'env', '.tox', '.cache', 'Resources', 'icons', 'tex', 'terminal'
|
||||
}
|
||||
|
||||
MAX_FILE_SIZE_BYTES = 2 * 1024 * 1024 # 2 MiB
|
||||
|
||||
|
||||
def is_third_party(path: Path) -> bool:
|
||||
for part in path.parts:
|
||||
# normalize case on Windows
|
||||
name = part.lower()
|
||||
if name in {n.lower() for n in THIRD_PARTY_DIR_NAMES}:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def should_skip_dir(dirname: str) -> bool:
|
||||
return dirname.lower() in {n.lower() for n in SKIP_DIR_NAMES}
|
||||
|
||||
|
||||
def is_code_file(path: Path) -> bool:
|
||||
return path.suffix.lower() in CODE_EXTENSIONS
|
||||
|
||||
|
||||
def count_lines(path: Path) -> int:
|
||||
try:
|
||||
if path.stat().st_size > MAX_FILE_SIZE_BYTES:
|
||||
return 0
|
||||
# Try text read with universal newlines, fallback to binary
|
||||
try:
|
||||
with path.open('r', encoding='utf-8', errors='ignore') as f:
|
||||
return sum(1 for _ in f)
|
||||
except Exception:
|
||||
with path.open('rb') as f:
|
||||
return f.read().count(b'\n')
|
||||
except Exception:
|
||||
return 0
|
||||
|
||||
|
||||
def main(root: Path) -> None:
|
||||
third_party_loc = 0
|
||||
first_party_loc = 0
|
||||
third_party_files = 0
|
||||
first_party_files = 0
|
||||
|
||||
for dirpath, dirnames, filenames in os.walk(root):
|
||||
# prune directories
|
||||
dirnames[:] = [d for d in dirnames if not should_skip_dir(d)]
|
||||
|
||||
current = Path(dirpath)
|
||||
current_is_third = is_third_party(current)
|
||||
|
||||
for fn in filenames:
|
||||
p = current / fn
|
||||
if not is_code_file(p):
|
||||
continue
|
||||
loc = count_lines(p)
|
||||
if current_is_third:
|
||||
third_party_loc += loc
|
||||
third_party_files += 1
|
||||
else:
|
||||
first_party_loc += loc
|
||||
first_party_files += 1
|
||||
|
||||
total_loc = first_party_loc + third_party_loc
|
||||
open_source_rate = (third_party_loc / total_loc) * 100 if total_loc else 0.0
|
||||
|
||||
print('Open-Source Rate (by LOC): {:.2f}%'.format(open_source_rate))
|
||||
print('\nBreakdown:')
|
||||
print(' First-party LOC : {} ({} files)'.format(first_party_loc, first_party_files))
|
||||
print(' Third-party LOC : {} ({} files)'.format(third_party_loc, third_party_files))
|
||||
print(' Total LOC : {}'.format(total_loc))
|
||||
print('\nNotes:')
|
||||
print(' - Third-party directories are heuristically detected by common names: {}'.format(', '.join(sorted(THIRD_PARTY_DIR_NAMES))))
|
||||
print(' - Static asset directories are skipped: {}'.format(', '.join(sorted(SKIP_DIR_NAMES))))
|
||||
print(' - Counted code extensions: {}'.format(', '.join(sorted(CODE_EXTENSIONS))))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(Path('.').resolve())
|
||||
|
||||
@ -9790,6 +9790,12 @@ except Exception as e:
|
||||
collision_group.setLayout(collision_layout)
|
||||
self._propertyLayout.addWidget(collision_group)
|
||||
|
||||
# 同步一次状态,确保主按钮与可见性按钮齐全
|
||||
try:
|
||||
self._updateCollisionPanelState(model)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
except Exception as e:
|
||||
print(f"创建碰撞面板失败: {e}")
|
||||
import traceback
|
||||
@ -10144,8 +10150,9 @@ except Exception as e:
|
||||
collision_np.show()
|
||||
print(f"显示碰撞:{model.getName()}")
|
||||
|
||||
# 立即更新按钮状态
|
||||
# 立即更新按钮状态,并同步更新面板(确保缺失主按钮时补建)
|
||||
self._updateCollisionVisibilityButton(model)
|
||||
self._updateCollisionPanelState(model)
|
||||
|
||||
except Exception as e:
|
||||
print(f"切换碰撞可见性失败: {e}")
|
||||
@ -10353,26 +10360,18 @@ except Exception as e:
|
||||
has_collision = self._hasCollision(model)
|
||||
print(f"模型 {model.getName()} 是否有碰撞体: {has_collision}-------------------------------------------------")
|
||||
|
||||
# 更新状态徽章(使用固定宽度)
|
||||
if has_collision:
|
||||
new_badge = self.createFixedStatusBadge("已启用", "green")
|
||||
else:
|
||||
new_badge = self.createFixedStatusBadge("未启用", "red")
|
||||
|
||||
# 替换旧的徽章
|
||||
old_badge = self.collision_status_badge
|
||||
parent_layout = old_badge.parent().layout()
|
||||
if parent_layout:
|
||||
# 找到旧徽章在布局中的位置
|
||||
for i in range(parent_layout.count()):
|
||||
item = parent_layout.itemAt(i)
|
||||
if item and item.widget() == old_badge:
|
||||
# 移除旧徽章并添加新徽章
|
||||
parent_layout.removeWidget(old_badge)
|
||||
old_badge.deleteLater()
|
||||
parent_layout.addWidget(new_badge, 0, 0, 1, 1) # 状态徽章在第0行第1列
|
||||
self.collision_status_badge = new_badge
|
||||
break
|
||||
# 更新状态徽章(直接修改现有控件,避免布局冲突)
|
||||
if hasattr(self, 'collision_status_badge') and self.collision_status_badge:
|
||||
if has_collision:
|
||||
self.collision_status_badge.setText("已启用")
|
||||
# 使用固定宽度的绿色样式,保持尺寸一致
|
||||
self.collision_status_badge.setStyleSheet(self.badge_style_green_fixed)
|
||||
else:
|
||||
self.collision_status_badge.setText("未启用")
|
||||
# 使用固定宽度的红色样式,保持尺寸一致
|
||||
self.collision_status_badge.setStyleSheet(self.badge_style_red_fixed)
|
||||
# 触发重绘,确保立即可见
|
||||
self.collision_status_badge.update()
|
||||
|
||||
if has_collision:
|
||||
# 有碰撞:显示移除按钮,下拉框变为只读并显示当前类型
|
||||
@ -10388,6 +10387,18 @@ except Exception as e:
|
||||
except:
|
||||
pass
|
||||
self.collision_button.clicked.connect(lambda: self._removeCollisionAndUpdate(model))
|
||||
else:
|
||||
# 若不存在主按钮,则创建“移除碰撞”按钮并加入布局
|
||||
try:
|
||||
self.collision_button = self.createModernButton("移除碰撞")
|
||||
self.collision_button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
||||
self.collision_button.setStyleSheet(self._collision_button_style())
|
||||
self.collision_button.clicked.connect(lambda: self._removeCollisionAndUpdate(model))
|
||||
if hasattr(self, 'collision_layout') and self.collision_layout is not None:
|
||||
row = self.collision_layout.rowCount()
|
||||
self.collision_layout.addWidget(self.collision_button, row, 0, 1, 4)
|
||||
except Exception as _e:
|
||||
print(f"创建移除碰撞按钮失败: {_e}")
|
||||
|
||||
# 获取并显示当前碰撞类型,设置为只读
|
||||
current_shape = self._getCurrentCollisionShape(model)
|
||||
@ -10407,6 +10418,13 @@ except Exception as e:
|
||||
self.collision_visibility_button.setVisible(True)
|
||||
self._updateCollisionVisibilityButton(model)
|
||||
|
||||
# 确保按钮顺序:可见性按钮在上,主按钮在下
|
||||
if hasattr(self, 'collision_layout'):
|
||||
try:
|
||||
self._repositionButtons(self.collision_layout.rowCount())
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
print(f"碰撞面板状态更新:有碰撞 - {current_shape}")
|
||||
|
||||
else:
|
||||
@ -10422,6 +10440,18 @@ except Exception as e:
|
||||
except:
|
||||
pass
|
||||
self.collision_button.clicked.connect(lambda: self._addCollisionAndUpdate(model))
|
||||
else:
|
||||
# 若不存在主按钮,则创建“添加碰撞”按钮并加入布局
|
||||
try:
|
||||
self.collision_button = self.createModernButton("添加碰撞")
|
||||
self.collision_button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
||||
self.collision_button.setStyleSheet(self._collision_button_style())
|
||||
self.collision_button.clicked.connect(lambda: self._addCollisionAndUpdate(model))
|
||||
if hasattr(self, 'collision_layout') and self.collision_layout is not None:
|
||||
row = self.collision_layout.rowCount()
|
||||
self.collision_layout.addWidget(self.collision_button, row, 0, 1, 4)
|
||||
except Exception as _e:
|
||||
print(f"创建添加碰撞按钮失败: {_e}")
|
||||
|
||||
# 恢复为可编辑状态
|
||||
self.collision_shape_combo.setEnabled(True)
|
||||
@ -10435,6 +10465,13 @@ except Exception as e:
|
||||
if hasattr(self, 'collision_visibility_button'):
|
||||
self.collision_visibility_button.setVisible(False)
|
||||
|
||||
# 确保按钮顺序:主按钮位于底部
|
||||
if hasattr(self, 'collision_layout'):
|
||||
try:
|
||||
self._repositionButtons(self.collision_layout.rowCount())
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
print(f"碰撞面板状态更新:无碰撞 - 可编辑")
|
||||
|
||||
except Exception as e:
|
||||
@ -11097,13 +11134,24 @@ except Exception as e:
|
||||
layout = self.collision_layout
|
||||
is_collision_visible = self._isCollisionVisible(model)
|
||||
|
||||
# 找到合适的行位置
|
||||
# 放在当前最后一行
|
||||
current_row = layout.rowCount()
|
||||
|
||||
self.collision_visibility_button = QPushButton("隐藏碰撞" if is_collision_visible else "显示碰撞")
|
||||
self.collision_visibility_button.setStyleSheet(self._collision_button_style())
|
||||
self.collision_visibility_button.clicked.connect(lambda: self._toggleCollisionVisibility(model))
|
||||
layout.addWidget(self.collision_visibility_button, current_row - 1, 0, 1, 4)
|
||||
layout.addWidget(self.collision_visibility_button, current_row, 0, 1, 4)
|
||||
|
||||
# 确保存在主按钮(有碰撞时应显示移除碰撞)
|
||||
if self._hasCollision(model) and not hasattr(self, 'collision_button'):
|
||||
try:
|
||||
self.collision_button = self.createModernButton("移除碰撞")
|
||||
self.collision_button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
||||
self.collision_button.setStyleSheet(self._collision_button_style())
|
||||
self.collision_button.clicked.connect(lambda: self._removeCollisionAndUpdate(model))
|
||||
layout.addWidget(self.collision_button, current_row + 1, 0, 1, 4)
|
||||
except Exception as _e:
|
||||
print(f"在可见性按钮后创建移除碰撞按钮失败: {_e}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"添加可见性按钮失败: {e}")
|
||||
@ -11114,22 +11162,39 @@ except Exception as e:
|
||||
if hasattr(self, 'collision_layout'):
|
||||
layout = self.collision_layout
|
||||
|
||||
# 移动可见性按钮
|
||||
if hasattr(self, 'collision_visibility_button'):
|
||||
layout.addWidget(self.collision_visibility_button, new_row, 0, 1, 4)
|
||||
new_row += 1
|
||||
def _remove_if_present(w):
|
||||
try:
|
||||
if not w:
|
||||
return
|
||||
# 从布局中移除该控件(如果已存在)
|
||||
for i in range(layout.count()):
|
||||
item = layout.itemAt(i)
|
||||
if item and item.widget() is w:
|
||||
layout.removeWidget(w)
|
||||
break
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 移动主按钮
|
||||
if hasattr(self, 'collision_button'):
|
||||
layout.addWidget(self.collision_button, new_row, 0, 1, 4)
|
||||
# 计算底部行
|
||||
bottom_row = layout.rowCount()
|
||||
|
||||
# 按固定顺序重新放置:先可见性按钮,再主按钮
|
||||
if hasattr(self, 'collision_visibility_button') and self.collision_visibility_button:
|
||||
_remove_if_present(self.collision_visibility_button)
|
||||
layout.addWidget(self.collision_visibility_button, bottom_row, 0, 1, 4)
|
||||
bottom_row += 1
|
||||
|
||||
if hasattr(self, 'collision_button') and self.collision_button:
|
||||
_remove_if_present(self.collision_button)
|
||||
layout.addWidget(self.collision_button, bottom_row, 0, 1, 4)
|
||||
|
||||
except Exception as e:
|
||||
print(f"重新定位按钮失败: {e}")
|
||||
|
||||
def _hideCollisionParameterControls(self):
|
||||
"""隐藏碰撞参数控件(保留按钮)"""
|
||||
"""隐藏并移除碰撞参数控件与其所在的行(保留状态/形状/按钮行)"""
|
||||
try:
|
||||
# 清理属性引用,但保留按钮
|
||||
# 1) 先清理对象属性引用,避免残留信号
|
||||
param_attrs = [
|
||||
'collision_pos_x', 'collision_pos_y', 'collision_pos_z',
|
||||
'collision_radius',
|
||||
@ -11137,47 +11202,72 @@ except Exception as e:
|
||||
'collision_capsule_radius', 'collision_capsule_height',
|
||||
'collision_normal_x', 'collision_normal_y', 'collision_normal_z'
|
||||
]
|
||||
|
||||
# 隐藏并删除参数控件
|
||||
for attr in param_attrs:
|
||||
if hasattr(self, attr):
|
||||
widget = getattr(self, attr)
|
||||
if widget:
|
||||
widget.setVisible(False)
|
||||
widget.setParent(None)
|
||||
widget.deleteLater()
|
||||
try:
|
||||
if widget:
|
||||
widget.setParent(None)
|
||||
widget.deleteLater()
|
||||
except Exception:
|
||||
pass
|
||||
delattr(self, attr)
|
||||
|
||||
# 同时清理可能的标签控件
|
||||
if hasattr(self, 'collision_layout'):
|
||||
# 2) 深度移除布局中第2行(索引>=2)之后的所有参数相关项,保留按钮
|
||||
if hasattr(self, 'collision_layout') and self.collision_layout is not None:
|
||||
layout = self.collision_layout
|
||||
|
||||
# 收集需要移除的控件(不包括基本控件和按钮)
|
||||
widgets_to_remove = []
|
||||
def _remove_layout_recursive(q_layout):
|
||||
try:
|
||||
while q_layout.count():
|
||||
child = q_layout.takeAt(0)
|
||||
if child.widget():
|
||||
w = child.widget()
|
||||
w.setParent(None)
|
||||
w.deleteLater()
|
||||
elif child.layout():
|
||||
_remove_layout_recursive(child.layout())
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
for i in range(layout.rowCount()):
|
||||
if i >= 2: # 从第3行开始检查
|
||||
for j in range(layout.columnCount()):
|
||||
item = layout.itemAtPosition(i, j)
|
||||
if item:
|
||||
widget = item.widget()
|
||||
if widget and hasattr(widget, 'text'):
|
||||
# 检查是否是参数相关的标签
|
||||
text = widget.text()
|
||||
if any(keyword in text for keyword in
|
||||
['位置偏移', 'X:', 'Y:', 'Z:', '半径:', '尺寸:', '宽度:', '长度:', '高度:',
|
||||
'法向量:', 'Nx:', 'Ny:', 'Nz:']):
|
||||
widgets_to_remove.append(widget)
|
||||
row_count = layout.rowCount()
|
||||
col_count = layout.columnCount()
|
||||
# 从参数区域开始清理(行索引2及以后),但跳过我们要保留的按钮
|
||||
for i in range(2, row_count):
|
||||
for j in range(0, col_count):
|
||||
item = layout.itemAtPosition(i, j)
|
||||
if not item:
|
||||
continue
|
||||
# 若是按钮,且是保留的按钮,则跳过
|
||||
w = item.widget()
|
||||
if w is not None:
|
||||
try:
|
||||
if (hasattr(self, 'collision_button') and w == self.collision_button) or (hasattr(self, 'collision_visibility_button') and w == self.collision_visibility_button):
|
||||
continue
|
||||
except Exception:
|
||||
pass
|
||||
layout.removeWidget(w)
|
||||
w.setParent(None)
|
||||
w.deleteLater()
|
||||
elif item.layout():
|
||||
# 移除嵌套布局(包含标签与输入框)
|
||||
nested = item.layout()
|
||||
_remove_layout_recursive(nested)
|
||||
layout.removeItem(nested)
|
||||
|
||||
# 移除参数标签
|
||||
for widget in widgets_to_remove:
|
||||
widget.setVisible(False)
|
||||
widget.setParent(None)
|
||||
widget.deleteLater()
|
||||
# 尝试把保留的按钮移动到参数区域第一行(行2)下方,保持整洁
|
||||
try:
|
||||
next_row = 2
|
||||
if hasattr(self, 'collision_visibility_button'):
|
||||
self.collision_visibility_button.setVisible(False)
|
||||
if hasattr(self, 'collision_button') and self.collision_button is not None:
|
||||
layout.addWidget(self.collision_button, next_row, 0, 1, 4)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
print("隐藏碰撞参数控件完成(保留按钮)")
|
||||
print("隐藏碰撞参数控件完成(仅保留状态、形状与按钮)")
|
||||
|
||||
except Exception as e:
|
||||
print(f"隐藏碰撞参数控件失败: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
traceback.print_exc()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user