forked from LeenkxTeam/LNXSDK
merge upstream
This commit is contained in:
@ -8,6 +8,24 @@ import mathutils
|
||||
import bpy
|
||||
from bpy.props import *
|
||||
|
||||
# Helper functions for Blender version compatibility
|
||||
def get_panel_options():
|
||||
"""Get panel options compatible with current Blender version."""
|
||||
if bpy.app.version >= (2, 93, 0): # INSTANCED was introduced around 2.93
|
||||
return {'INSTANCED'}
|
||||
else:
|
||||
return set() # Empty set for older versions
|
||||
|
||||
def column_with_heading(layout, heading='', align=False):
|
||||
"""Create a column with optional heading, compatible across Blender versions."""
|
||||
if bpy.app.version >= (2, 92, 0):
|
||||
return layout.column(heading=heading, align=align)
|
||||
else:
|
||||
col = layout.column(align=align)
|
||||
if heading:
|
||||
col.label(text=heading)
|
||||
return col
|
||||
|
||||
from lnx.lightmapper.panels import scene
|
||||
|
||||
import lnx.api
|
||||
@ -63,6 +81,7 @@ class LNX_PT_ObjectPropsPanel(bpy.types.Panel):
|
||||
return
|
||||
|
||||
col = layout.column()
|
||||
col.prop(obj, 'lnx_sorting_index')
|
||||
col.prop(obj, 'lnx_export')
|
||||
if not obj.lnx_export:
|
||||
return
|
||||
@ -206,6 +225,7 @@ class LNX_PT_ParticlesPropsPanel(bpy.types.Panel):
|
||||
return
|
||||
|
||||
layout.prop(obj.settings, 'lnx_auto_start')
|
||||
layout.prop(obj.settings, 'lnx_dynamic_emitter')
|
||||
layout.prop(obj.settings, 'lnx_is_unique')
|
||||
layout.prop(obj.settings, 'lnx_loop')
|
||||
layout.prop(obj.settings, 'lnx_count_mult')
|
||||
@ -551,6 +571,51 @@ class LNX_OT_NewCustomMaterial(bpy.types.Operator):
|
||||
|
||||
return{'FINISHED'}
|
||||
|
||||
|
||||
class LNX_OT_NextPassMaterialSelector(bpy.types.Operator):
|
||||
"""Select material for next pass"""
|
||||
bl_idname = "lnx.next_pass_material_selector"
|
||||
bl_label = "Select Next Pass Material"
|
||||
|
||||
def execute(self, context):
|
||||
return {'FINISHED'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
context.window_manager.popup_menu(self.draw_menu, title="Select Next Pass Material", icon='MATERIAL')
|
||||
return {'FINISHED'}
|
||||
|
||||
def draw_menu(self, popup, context):
|
||||
layout = popup.layout
|
||||
|
||||
# Add 'None' option
|
||||
op = layout.operator("lnx.set_next_pass_material", text="")
|
||||
op.material_name = ""
|
||||
|
||||
# Add materials from the current object's material slots
|
||||
if context.object and hasattr(context.object, 'material_slots'):
|
||||
for slot in context.object.material_slots:
|
||||
if (slot.material is not None and slot.material != context.material):
|
||||
op = layout.operator("lnx.set_next_pass_material", text=slot.material.name)
|
||||
op.material_name = slot.material.name
|
||||
|
||||
class LNX_OT_SetNextPassMaterial(bpy.types.Operator):
|
||||
"""Set the next pass material"""
|
||||
bl_idname = "lnx.set_next_pass_material"
|
||||
bl_label = "Set Next Pass Material"
|
||||
|
||||
material_name: StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
if context.material:
|
||||
context.material.lnx_next_pass = self.material_name
|
||||
# Redraw the UI to update the display
|
||||
for area in context.screen.areas:
|
||||
if area.type == 'PROPERTIES':
|
||||
area.tag_redraw()
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
|
||||
class LNX_PG_BindTexturesListItem(bpy.types.PropertyGroup):
|
||||
uniform_name: StringProperty(
|
||||
name='Uniform Name',
|
||||
@ -634,18 +699,23 @@ class LNX_PT_MaterialPropsPanel(bpy.types.Panel):
|
||||
mat = bpy.context.material
|
||||
if mat is None:
|
||||
return
|
||||
|
||||
|
||||
layout.prop(mat, 'lnx_cast_shadow')
|
||||
columnb = layout.column()
|
||||
wrd = bpy.data.worlds['Lnx']
|
||||
columnb.enabled = len(wrd.lnx_rplist) > 0 and lnx.utils.get_rp().rp_renderer == 'Forward'
|
||||
columnb.prop(mat, 'lnx_receive_shadow')
|
||||
layout.prop(mat, 'lnx_ignore_irradiance')
|
||||
layout.prop(mat, 'lnx_compare_mode')
|
||||
layout.prop(mat, 'lnx_two_sided')
|
||||
columnb = layout.column()
|
||||
columnb.enabled = not mat.lnx_two_sided
|
||||
columnb.prop(mat, 'lnx_cull_mode')
|
||||
row = layout.row(align=True)
|
||||
row.prop(mat, 'lnx_next_pass', text="Next Pass")
|
||||
row.operator('lnx.next_pass_material_selector', text='', icon='MATERIAL')
|
||||
layout.prop(mat, 'lnx_material_id')
|
||||
layout.prop(mat, 'lnx_depth_write')
|
||||
layout.prop(mat, 'lnx_depth_read')
|
||||
layout.prop(mat, 'lnx_overlay')
|
||||
layout.prop(mat, 'lnx_decal')
|
||||
@ -887,13 +957,13 @@ class LNX_PT_LeenkxExporterPanel(bpy.types.Panel):
|
||||
col = layout.column()
|
||||
col.prop(wrd, 'lnx_project_icon')
|
||||
|
||||
col = layout.column(heading='Code Output', align=True)
|
||||
col = column_with_heading(layout, 'Code Output', align=True)
|
||||
col.prop(wrd, 'lnx_dce')
|
||||
col.prop(wrd, 'lnx_compiler_inline')
|
||||
col.prop(wrd, 'lnx_minify_js')
|
||||
col.prop(wrd, 'lnx_no_traces')
|
||||
|
||||
col = layout.column(heading='Data', align=True)
|
||||
col = column_with_heading(layout, 'Data', align=True)
|
||||
col.prop(wrd, 'lnx_minimize')
|
||||
col.prop(wrd, 'lnx_optimize_data')
|
||||
col.prop(wrd, 'lnx_asset_compression')
|
||||
@ -1126,32 +1196,32 @@ class LNX_PT_ProjectFlagsPanel(bpy.types.Panel):
|
||||
layout.use_property_decorate = False
|
||||
wrd = bpy.data.worlds['Lnx']
|
||||
|
||||
col = layout.column(heading='Debug', align=True)
|
||||
col = column_with_heading(layout, 'Debug', align=True)
|
||||
col.prop(wrd, 'lnx_verbose_output')
|
||||
col.prop(wrd, 'lnx_cache_build')
|
||||
col.prop(wrd, 'lnx_clear_on_compile')
|
||||
col.prop(wrd, 'lnx_assert_level')
|
||||
col.prop(wrd, 'lnx_assert_quit')
|
||||
|
||||
col = layout.column(heading='Runtime', align=True)
|
||||
col = column_with_heading(layout, 'Runtime', align=True)
|
||||
col.prop(wrd, 'lnx_live_patch')
|
||||
col.prop(wrd, 'lnx_stream_scene')
|
||||
col.prop(wrd, 'lnx_loadscreen')
|
||||
col.prop(wrd, 'lnx_write_config')
|
||||
|
||||
col = layout.column(heading='Renderer', align=True)
|
||||
col = column_with_heading(layout, 'Renderer', align=True)
|
||||
col.prop(wrd, 'lnx_batch_meshes')
|
||||
col.prop(wrd, 'lnx_batch_materials')
|
||||
col.prop(wrd, 'lnx_deinterleaved_buffers')
|
||||
col.prop(wrd, 'lnx_export_tangents')
|
||||
|
||||
col = layout.column(heading='Quality')
|
||||
col = column_with_heading(layout, 'Quality')
|
||||
row = col.row() # To expand below property UI horizontally
|
||||
row.prop(wrd, 'lnx_canvas_img_scaling_quality', expand=True)
|
||||
col.prop(wrd, 'lnx_texture_quality')
|
||||
col.prop(wrd, 'lnx_sound_quality')
|
||||
|
||||
col = layout.column(heading='External Assets')
|
||||
col = column_with_heading(layout, 'External Assets')
|
||||
col.prop(wrd, 'lnx_copy_override')
|
||||
col.operator('lnx.copy_to_bundled', icon='IMAGE_DATA')
|
||||
|
||||
@ -1229,7 +1299,8 @@ class LNX_PT_ProjectModulesPanel(bpy.types.Panel):
|
||||
|
||||
layout.prop_search(wrd, 'lnx_khafile', bpy.data, 'texts')
|
||||
layout.prop(wrd, 'lnx_project_root')
|
||||
|
||||
layout.prop(wrd, 'lnx_external_blends_path')
|
||||
|
||||
class LnxVirtualInputPanel(bpy.types.Panel):
|
||||
bl_label = "Leenkx Virtual Input"
|
||||
bl_space_type = "PROPERTIES"
|
||||
@ -1464,7 +1535,7 @@ class LNX_PT_TopbarPanel(bpy.types.Panel):
|
||||
bl_label = "Leenkx Player"
|
||||
bl_space_type = "VIEW_3D"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_options = {'INSTANCED'}
|
||||
bl_options = get_panel_options()
|
||||
|
||||
def draw_header(self, context):
|
||||
row = self.layout.row(align=True)
|
||||
@ -2269,7 +2340,10 @@ class LnxGenTerrainButton(bpy.types.Operator):
|
||||
node.location = (-200, -200)
|
||||
node.inputs[0].default_value = 5.0
|
||||
links.new(nodes['Bump'].inputs[2], nodes['_TerrainHeight'].outputs[0])
|
||||
links.new(nodes['Principled BSDF'].inputs[20], nodes['Bump'].outputs[0])
|
||||
if bpy.app.version[0] >= 4:
|
||||
links.new(nodes['Principled BSDF'].inputs[22], nodes['Bump'].outputs[0])
|
||||
else:
|
||||
links.new(nodes['Principled BSDF'].inputs[20], nodes['Bump'].outputs[0])
|
||||
|
||||
# Create sectors
|
||||
root_obj = bpy.data.objects.new("Terrain", None)
|
||||
@ -2302,7 +2376,16 @@ class LnxGenTerrainButton(bpy.types.Operator):
|
||||
disp_mod.texture.extension = 'EXTEND'
|
||||
disp_mod.texture.use_interpolation = False
|
||||
disp_mod.texture.use_mipmap = False
|
||||
disp_mod.texture.image = bpy.data.images.load(filepath=scn.lnx_terrain_textures+'/heightmap_' + j + '.png')
|
||||
try:
|
||||
disp_mod.texture.image = bpy.data.images.load(filepath=scn.lnx_terrain_textures+'/heightmap_' + j + '.png')
|
||||
except Exception as e:
|
||||
if i == 0: # Only show message once
|
||||
if scn.lnx_terrain_textures.startswith('//') and not bpy.data.filepath:
|
||||
self.report({'INFO'}, "Generating terrain... Save .blend file and add your heightmaps for each sector in "
|
||||
"the \"Bundled\" folder using the format \"heightmap_01.png\", \"heightmap_02.png\", etc.")
|
||||
else:
|
||||
self.report({'INFO'}, f"Heightmap not found: {scn.lnx_terrain_textures}/heightmap_{j}.png - using blank image")
|
||||
|
||||
f = 1
|
||||
levels = 0
|
||||
while f < disp_mod.texture.image.size[0]:
|
||||
@ -2858,7 +2941,7 @@ def draw_conditional_prop(layout: bpy.types.UILayout, heading: str, data: bpy.ty
|
||||
"""Draws a property row with a checkbox that enables a value field.
|
||||
The function fails when prop_condition is not a boolean property.
|
||||
"""
|
||||
col = layout.column(heading=heading)
|
||||
col = column_with_heading(layout, heading)
|
||||
row = col.row()
|
||||
row.prop(data, prop_condition, text='')
|
||||
sub = row.row()
|
||||
@ -2910,6 +2993,8 @@ __REG_CLASSES = (
|
||||
InvalidateCacheButton,
|
||||
InvalidateMaterialCacheButton,
|
||||
LNX_OT_NewCustomMaterial,
|
||||
LNX_OT_NextPassMaterialSelector,
|
||||
LNX_OT_SetNextPassMaterial,
|
||||
LNX_PG_BindTexturesListItem,
|
||||
LNX_UL_BindTexturesList,
|
||||
LNX_OT_BindTexturesListNewItem,
|
||||
|
||||
Reference in New Issue
Block a user