forked from LeenkxTeam/LNXSDK
Merge pull request 'main' (#127) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#127
This commit is contained in:
@ -10,6 +10,7 @@ class SetFirstPersonControllerNode extends LogicNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override function run(from: Int): Void {
|
override function run(from: Int): Void {
|
||||||
|
#if lnx_physics
|
||||||
// Control de las var de FirstPersonController...
|
// Control de las var de FirstPersonController...
|
||||||
// Control FirstPersonController var
|
// Control FirstPersonController var
|
||||||
|
|
||||||
@ -60,6 +61,7 @@ class SetFirstPersonControllerNode extends LogicNode {
|
|||||||
// Alert the user if they do not have the trait assigning to the object.
|
// Alert the user if they do not have the trait assigning to the object.
|
||||||
trace("ERROR: The object '" + object.name + "' does not have the FirstPersonController script assigning(assign it from (Object->add trait->bundle)).");
|
trace("ERROR: The object '" + object.name + "' does not have the FirstPersonController script assigning(assign it from (Object->add trait->bundle)).");
|
||||||
}
|
}
|
||||||
|
#end
|
||||||
|
|
||||||
runOutput(0);
|
runOutput(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,7 @@ class SetOverheadPersonControllerNode extends LogicNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override function run(from: Int): Void {
|
override function run(from: Int): Void {
|
||||||
|
#if lnx_physics
|
||||||
// Control de las var de OverheadPersonController...
|
// Control de las var de OverheadPersonController...
|
||||||
// Control OverheadPersonController var
|
// Control OverheadPersonController var
|
||||||
|
|
||||||
@ -58,6 +59,7 @@ class SetOverheadPersonControllerNode extends LogicNode {
|
|||||||
// Alert the user if they do not have the trait assigning to the object..
|
// Alert the user if they do not have the trait assigning to the object..
|
||||||
trace("ERROR: The object '" + objectTrait.name + "' does not have the OverheadPersonController script assigning(assign it from (Object->add trait->bundle)).");
|
trace("ERROR: The object '" + objectTrait.name + "' does not have the OverheadPersonController script assigning(assign it from (Object->add trait->bundle)).");
|
||||||
}
|
}
|
||||||
|
#end
|
||||||
|
|
||||||
runOutput(0);
|
runOutput(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,7 +27,7 @@ class LivePatch extends iron.Trait {
|
|||||||
var id = Std.parseInt(lines[0]);
|
var id = Std.parseInt(lines[0]);
|
||||||
if (id > patchId) {
|
if (id > patchId) {
|
||||||
patchId = id;
|
patchId = id;
|
||||||
js.Lib.eval(lines[1]);
|
js.Syntax.code("var iron = {0}, LivePatch = {1}; eval({2})", Bridge, LivePatch, lines[1]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -67,10 +67,11 @@ def on_depsgraph_update_post(self):
|
|||||||
|
|
||||||
# Send last operator to Krom
|
# Send last operator to Krom
|
||||||
wrd = bpy.data.worlds['Lnx']
|
wrd = bpy.data.worlds['Lnx']
|
||||||
if state.proc_play is not None and state.target == 'krom' and wrd.lnx_live_patch:
|
if (state.proc_play is not None or make._viewport_processes) and state.target == 'krom' and wrd.lnx_live_patch:
|
||||||
ops = bpy.context.window_manager.operators
|
if not live_patch.on_depsgraph_update(depsgraph.updates):
|
||||||
if len(ops) > 0 and ops[-1] is not None:
|
ops = bpy.context.window_manager.operators
|
||||||
live_patch.on_operator(ops[-1].bl_idname)
|
if len(ops) > 0 and ops[-1] is not None:
|
||||||
|
live_patch.on_operator(ops[-1].bl_idname)
|
||||||
|
|
||||||
# Hacky solution to update leenkx props after operator executions.
|
# Hacky solution to update leenkx props after operator executions.
|
||||||
# bpy.context.active_operator doesn't always exist, in some cases
|
# bpy.context.active_operator doesn't always exist, in some cases
|
||||||
|
|||||||
@ -32,6 +32,9 @@ else:
|
|||||||
__running = False
|
__running = False
|
||||||
"""Whether live patch is currently active"""
|
"""Whether live patch is currently active"""
|
||||||
|
|
||||||
|
scene_cache = {}
|
||||||
|
"""Keys: (event_id, object_name) -> cached value tuple"""
|
||||||
|
|
||||||
# Any object can act as a message bus owner
|
# Any object can act as a message bus owner
|
||||||
msgbus_owner = object()
|
msgbus_owner = object()
|
||||||
|
|
||||||
@ -65,6 +68,62 @@ def stop():
|
|||||||
bpy.msgbus.clear_by_owner(msgbus_owner)
|
bpy.msgbus.clear_by_owner(msgbus_owner)
|
||||||
|
|
||||||
|
|
||||||
|
def get_obj_transforms(obj):
|
||||||
|
loc = (round(obj.location.x, 6), round(obj.location.y, 6), round(obj.location.z, 6))
|
||||||
|
rot = obj.rotation_euler.to_quaternion()
|
||||||
|
rot = (round(rot.x, 6), round(rot.y, 6), round(rot.z, 6), round(rot.w, 6))
|
||||||
|
scale = (round(obj.scale.x, 6), round(obj.scale.y, 6), round(obj.scale.z, 6))
|
||||||
|
return loc, rot, scale
|
||||||
|
|
||||||
|
|
||||||
|
def get_light_props(obj):
|
||||||
|
light = obj.data
|
||||||
|
color = (round(light.color[0], 6), round(light.color[1], 6), round(light.color[2], 6))
|
||||||
|
energy = round(light.energy, 6)
|
||||||
|
return color, energy
|
||||||
|
|
||||||
|
DEPSGRAPH_HANDLERS = {
|
||||||
|
'is_updated_transform': [
|
||||||
|
('obj_location', lambda obj: get_obj_transforms(obj)[0]),
|
||||||
|
('obj_rotation', lambda obj: get_obj_transforms(obj)[1]),
|
||||||
|
('obj_scale', lambda obj: get_obj_transforms(obj)[2]),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def on_depsgraph_update(updates):
|
||||||
|
if not __running:
|
||||||
|
return False
|
||||||
|
|
||||||
|
changed = False
|
||||||
|
|
||||||
|
for update in updates:
|
||||||
|
uid = update.id
|
||||||
|
|
||||||
|
if isinstance(uid, bpy.types.Object):
|
||||||
|
name = uid.name
|
||||||
|
|
||||||
|
if update.is_updated_transform:
|
||||||
|
for event_id, extractor in DEPSGRAPH_HANDLERS['is_updated_transform']:
|
||||||
|
current = extractor(uid)
|
||||||
|
cache_key = (event_id, name)
|
||||||
|
if current != scene_cache.get(cache_key):
|
||||||
|
scene_cache[cache_key] = current
|
||||||
|
send_event(event_id)
|
||||||
|
changed = True
|
||||||
|
|
||||||
|
if update.is_updated_shading and isinstance(uid.data, bpy.types.Light):
|
||||||
|
color, energy = get_light_props(uid)
|
||||||
|
for event_id, current in (('light_color', color), ('light_energy', energy)):
|
||||||
|
cache_key = (event_id, uid.data.name)
|
||||||
|
if current != scene_cache.get(cache_key):
|
||||||
|
scene_cache[cache_key] = current
|
||||||
|
send_event(event_id)
|
||||||
|
changed = True
|
||||||
|
|
||||||
|
return changed
|
||||||
|
|
||||||
|
|
||||||
def patch_export():
|
def patch_export():
|
||||||
"""Re-export the current scene and update the game accordingly."""
|
"""Re-export the current scene and update the game accordingly."""
|
||||||
if not __running or state.proc_build is not None:
|
if not __running or state.proc_build is not None:
|
||||||
|
|||||||
@ -521,12 +521,17 @@ def compile(assets_only=False):
|
|||||||
else:
|
else:
|
||||||
log.error('Build failed')
|
log.error('Build failed')
|
||||||
|
|
||||||
def build(target, is_play=False, is_publish=False, is_export=False):
|
def build(target, is_play=False, is_publish=False, is_export=False, is_viewport=False, viewport_width=1920, viewport_height=1080):
|
||||||
global profile_time
|
global profile_time
|
||||||
profile_time = time.time()
|
profile_time = time.time()
|
||||||
|
|
||||||
wrd = bpy.data.worlds['Lnx']
|
wrd = bpy.data.worlds['Lnx']
|
||||||
|
|
||||||
|
state.is_viewport = is_viewport
|
||||||
|
if is_viewport:
|
||||||
|
state.viewport_width = viewport_width
|
||||||
|
state.viewport_height = viewport_height
|
||||||
|
|
||||||
if is_play and wrd.lnx_runtime == 'Hashlink':
|
if is_play and wrd.lnx_runtime == 'Hashlink':
|
||||||
current_os = lnx.utils.get_os()
|
current_os = lnx.utils.get_os()
|
||||||
if current_os == 'win':
|
if current_os == 'win':
|
||||||
@ -690,7 +695,11 @@ def run_viewport_runtime(viewport_id, width=1920, height=1080):
|
|||||||
if not os.path.exists(path + '/krom.js'):
|
if not os.path.exists(path + '/krom.js'):
|
||||||
log.warn(f'Krom build not found at {path}/krom.js - build project first')
|
log.warn(f'Krom build not found at {path}/krom.js - build project first')
|
||||||
return None, None
|
return None, None
|
||||||
|
|
||||||
|
if wrd.lnx_live_patch:
|
||||||
|
live_patch.start()
|
||||||
|
open(path + '/krom.patch', 'w', encoding='utf-8').close()
|
||||||
|
|
||||||
os.chdir(krom_location)
|
os.chdir(krom_location)
|
||||||
|
|
||||||
cmd = [krom_path, path, path_resources]
|
cmd = [krom_path, path, path_resources]
|
||||||
@ -725,95 +734,6 @@ _viewport_build_in_progress = False
|
|||||||
_viewport_pending_launches = [] # List of (viewport_id, width, height) tuples
|
_viewport_pending_launches = [] # List of (viewport_id, width, height) tuples
|
||||||
_viewport_proc_build = None # Separate process tracker for viewport builds
|
_viewport_proc_build = None # Separate process tracker for viewport builds
|
||||||
|
|
||||||
def build_viewport(viewport_id, width=1920, height=1080):
|
|
||||||
"""Build project for viewport"""
|
|
||||||
global _viewport_build_in_progress, _viewport_pending_launches, profile_time, scripts_mtime
|
|
||||||
|
|
||||||
wrd = bpy.data.worlds.get('Lnx')
|
|
||||||
if not wrd:
|
|
||||||
log.warn('No Lnx world found - cannot build for viewport')
|
|
||||||
return
|
|
||||||
|
|
||||||
krom_js_path = lnx.utils.get_fp_build() + '/debug/krom/krom.js'
|
|
||||||
if os.path.exists(krom_js_path) and not wrd.lnx_recompile:
|
|
||||||
log.info(f'Using cached viewport build for {viewport_id}')
|
|
||||||
run_viewport_runtime(viewport_id, width, height)
|
|
||||||
return
|
|
||||||
|
|
||||||
pending_entry = (viewport_id, width, height)
|
|
||||||
if pending_entry not in _viewport_pending_launches:
|
|
||||||
_viewport_pending_launches.append(pending_entry)
|
|
||||||
log.info(f'Queued viewport {viewport_id} for launch after build')
|
|
||||||
|
|
||||||
# If a build is already in progress and there is an actual build process, wait
|
|
||||||
# _viewport_proc_build checks viewport ,not state.proc_build (which is for play button)
|
|
||||||
if _viewport_build_in_progress:
|
|
||||||
if _viewport_proc_build is not None and _viewport_proc_build.poll() is None:
|
|
||||||
log.info(f'Build in progress, viewport {viewport_id} will launch when ready')
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
log.info(f'Resetting stale viewport build state')
|
|
||||||
_viewport_build_in_progress = False
|
|
||||||
|
|
||||||
_viewport_build_in_progress = True
|
|
||||||
profile_time = time.time()
|
|
||||||
|
|
||||||
log.info(f'Starting viewport build for {len(_viewport_pending_launches)} viewport(s)')
|
|
||||||
|
|
||||||
# Set viewport mode flags but not the is_play flag meant for external launcher
|
|
||||||
state.is_viewport = True
|
|
||||||
state.viewport_width = width
|
|
||||||
state.viewport_height = height
|
|
||||||
state.target = 'krom'
|
|
||||||
state.is_play = False # NOT play mode
|
|
||||||
state.is_publish = False
|
|
||||||
state.is_export = False
|
|
||||||
|
|
||||||
# Recompile detection (matching play() behavior)
|
|
||||||
if not wrd.lnx_cache_build or \
|
|
||||||
not os.path.isfile(krom_js_path) or \
|
|
||||||
assets.khafile_defs_last != assets.khafile_defs or \
|
|
||||||
state.last_target != state.target:
|
|
||||||
wrd.lnx_recompile = True
|
|
||||||
|
|
||||||
state.last_target = state.target
|
|
||||||
|
|
||||||
# Trait sources modified
|
|
||||||
state.mod_scripts = []
|
|
||||||
script_path = lnx.utils.get_fp() + '/Sources/' + lnx.utils.safestr(wrd.lnx_project_package)
|
|
||||||
if os.path.isdir(script_path):
|
|
||||||
new_mtime = scripts_mtime
|
|
||||||
for fn in glob.iglob(os.path.join(script_path, '**', '*.hx'), recursive=True):
|
|
||||||
mtime = os.path.getmtime(fn)
|
|
||||||
if scripts_mtime < mtime:
|
|
||||||
lnx.utils.fetch_script_props(fn)
|
|
||||||
fn = fn.split('Sources/')[1]
|
|
||||||
fn = fn[:-3] #.hx
|
|
||||||
fn = fn.replace('/', '.')
|
|
||||||
state.mod_scripts.append(fn)
|
|
||||||
wrd.lnx_recompile = True
|
|
||||||
if new_mtime < mtime:
|
|
||||||
new_mtime = mtime
|
|
||||||
scripts_mtime = new_mtime
|
|
||||||
if len(state.mod_scripts) > 0:
|
|
||||||
lnx.utils.fetch_trait_props()
|
|
||||||
|
|
||||||
log.clear(clear_warnings=True, clear_errors=True)
|
|
||||||
|
|
||||||
sdk_path = lnx.utils.get_sdk_path()
|
|
||||||
fp = lnx.utils.get_fp()
|
|
||||||
os.chdir(fp)
|
|
||||||
|
|
||||||
sources_path = 'Sources/' + lnx.utils.safestr(wrd.lnx_project_package)
|
|
||||||
if not os.path.exists(sources_path):
|
|
||||||
os.makedirs(sources_path)
|
|
||||||
|
|
||||||
log.info('Exporting scene data...')
|
|
||||||
export_data(fp, sdk_path)
|
|
||||||
|
|
||||||
log.info('Starting Krom compilation for viewport...')
|
|
||||||
compile_viewport(assets_only=(not wrd.lnx_recompile))
|
|
||||||
|
|
||||||
def compile_viewport(assets_only=False):
|
def compile_viewport(assets_only=False):
|
||||||
"""Compile for viewport mode using separate process tracking."""
|
"""Compile for viewport mode using separate process tracking."""
|
||||||
global _viewport_proc_build
|
global _viewport_proc_build
|
||||||
@ -886,8 +806,8 @@ def viewport_build_done():
|
|||||||
|
|
||||||
def play_viewport(viewport_id, width=1920, height=1080):
|
def play_viewport(viewport_id, width=1920, height=1080):
|
||||||
"""Launch Krom in a viewport"""
|
"""Launch Krom in a viewport"""
|
||||||
global _viewport_build_in_progress, _viewport_pending_launches, _viewport_proc_build, scripts_mtime
|
global _viewport_build_in_progress, _viewport_pending_launches, _viewport_proc_build
|
||||||
|
|
||||||
if not viewport_id:
|
if not viewport_id:
|
||||||
log.error('No viewport_id: play_viewport requires an id')
|
log.error('No viewport_id: play_viewport requires an id')
|
||||||
return
|
return
|
||||||
@ -895,7 +815,7 @@ def play_viewport(viewport_id, width=1920, height=1080):
|
|||||||
if 'Lnx' not in bpy.data.worlds:
|
if 'Lnx' not in bpy.data.worlds:
|
||||||
log.error('No Lnx world found - cannot start viewport server')
|
log.error('No Lnx world found - cannot start viewport server')
|
||||||
return
|
return
|
||||||
|
|
||||||
wrd = bpy.data.worlds['Lnx']
|
wrd = bpy.data.worlds['Lnx']
|
||||||
|
|
||||||
krom_js_path = lnx.utils.get_fp_build() + '/debug/krom/krom.js'
|
krom_js_path = lnx.utils.get_fp_build() + '/debug/krom/krom.js'
|
||||||
@ -912,52 +832,11 @@ def play_viewport(viewport_id, width=1920, height=1080):
|
|||||||
log.info(f'Build in progress, viewport {viewport_id} will launch when ready')
|
log.info(f'Build in progress, viewport {viewport_id} will launch when ready')
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
_viewport_build_in_progress = False # Reset stale state
|
_viewport_build_in_progress = False
|
||||||
|
|
||||||
_viewport_build_in_progress = True
|
_viewport_build_in_progress = True
|
||||||
|
|
||||||
sdk_path = lnx.utils.get_sdk_path()
|
build(target='krom', is_viewport=True, viewport_width=width, viewport_height=height)
|
||||||
fp = lnx.utils.get_fp()
|
|
||||||
os.chdir(fp)
|
|
||||||
|
|
||||||
sources_path = 'Sources/' + lnx.utils.safestr(wrd.lnx_project_package)
|
|
||||||
if not os.path.exists(sources_path):
|
|
||||||
os.makedirs(sources_path)
|
|
||||||
|
|
||||||
# export data same as play() but without setting state.is_play
|
|
||||||
state.is_viewport = True
|
|
||||||
state.target = 'krom'
|
|
||||||
state.is_publish = False
|
|
||||||
state.is_export = False
|
|
||||||
|
|
||||||
if not wrd.lnx_cache_build or \
|
|
||||||
not os.path.isfile(krom_js_path) or \
|
|
||||||
assets.khafile_defs_last != assets.khafile_defs or \
|
|
||||||
state.last_target != state.target:
|
|
||||||
wrd.lnx_recompile = True
|
|
||||||
|
|
||||||
state.last_target = state.target
|
|
||||||
|
|
||||||
state.mod_scripts = []
|
|
||||||
script_path = lnx.utils.get_fp() + '/Sources/' + lnx.utils.safestr(wrd.lnx_project_package)
|
|
||||||
if os.path.isdir(script_path):
|
|
||||||
new_mtime = scripts_mtime
|
|
||||||
for fn in glob.iglob(os.path.join(script_path, '**', '*.hx'), recursive=True):
|
|
||||||
mtime = os.path.getmtime(fn)
|
|
||||||
if scripts_mtime < mtime:
|
|
||||||
lnx.utils.fetch_script_props(fn)
|
|
||||||
fn = fn.split('Sources/')[1]
|
|
||||||
fn = fn[:-3] #.hx
|
|
||||||
fn = fn.replace('/', '.')
|
|
||||||
state.mod_scripts.append(fn)
|
|
||||||
wrd.lnx_recompile = True
|
|
||||||
if new_mtime < mtime:
|
|
||||||
new_mtime = mtime
|
|
||||||
scripts_mtime = new_mtime
|
|
||||||
if len(state.mod_scripts) > 0:
|
|
||||||
lnx.utils.fetch_trait_props()
|
|
||||||
|
|
||||||
export_data(fp, sdk_path)
|
|
||||||
|
|
||||||
compile_viewport(assets_only=(not wrd.lnx_recompile))
|
compile_viewport(assets_only=(not wrd.lnx_recompile))
|
||||||
|
|
||||||
|
|||||||
@ -101,70 +101,9 @@ MOUSE_BUTTON_LEFT = 0
|
|||||||
MOUSE_BUTTON_RIGHT = 1
|
MOUSE_BUTTON_RIGHT = 1
|
||||||
MOUSE_BUTTON_MIDDLE = 2
|
MOUSE_BUTTON_MIDDLE = 2
|
||||||
|
|
||||||
_rendered_mode_pending = False
|
|
||||||
_rendered_mode_retries = 0
|
|
||||||
_msgbus_owner = object()
|
_msgbus_owner = object()
|
||||||
_make_module = None
|
_make_module = None
|
||||||
|
|
||||||
@bpy.app.handlers.persistent
|
|
||||||
def _on_depsgraph_update(scene, depsgraph):
|
|
||||||
"""Called on depsgraph update - check if render engine changed to Krom."""
|
|
||||||
try:
|
|
||||||
if scene.render.engine == 'KROM_VIEWPORT':
|
|
||||||
for window in bpy.context.window_manager.windows:
|
|
||||||
for area in window.screen.areas:
|
|
||||||
if area.type == 'VIEW_3D':
|
|
||||||
for space in area.spaces:
|
|
||||||
if space.type == 'VIEW_3D':
|
|
||||||
if space.shading.type != 'RENDERED':
|
|
||||||
space.shading.type = 'RENDERED'
|
|
||||||
area.tag_redraw()
|
|
||||||
return
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _deferred_set_rendered_mode():
|
|
||||||
"""Module-level timer callback to set rendered mode."""
|
|
||||||
global _rendered_mode_pending, _rendered_mode_retries
|
|
||||||
try:
|
|
||||||
current_engine = bpy.context.scene.render.engine
|
|
||||||
|
|
||||||
for window in bpy.context.window_manager.windows:
|
|
||||||
screen = window.screen
|
|
||||||
for area in screen.areas:
|
|
||||||
if area.type == 'VIEW_3D':
|
|
||||||
for space in area.spaces:
|
|
||||||
if space.type == 'VIEW_3D':
|
|
||||||
current_shading = space.shading.type
|
|
||||||
|
|
||||||
if current_shading == 'RENDERED':
|
|
||||||
_rendered_mode_pending = False
|
|
||||||
_rendered_mode_retries = 0
|
|
||||||
return None
|
|
||||||
|
|
||||||
space.shading.type = 'RENDERED'
|
|
||||||
area.tag_redraw()
|
|
||||||
|
|
||||||
_rendered_mode_pending = False
|
|
||||||
_rendered_mode_retries = 0
|
|
||||||
return None
|
|
||||||
|
|
||||||
_rendered_mode_retries += 1
|
|
||||||
if _rendered_mode_retries < 10:
|
|
||||||
print(f"Viewport VIEW_3D not found, retrying... ({_rendered_mode_retries})")
|
|
||||||
return 0.2
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Could not set rendered mode: {e}")
|
|
||||||
import traceback
|
|
||||||
traceback.print_exc()
|
|
||||||
_rendered_mode_retries += 1
|
|
||||||
if _rendered_mode_retries < 10:
|
|
||||||
return 0.2
|
|
||||||
_rendered_mode_pending = False
|
|
||||||
_rendered_mode_retries = 0
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
class KromViewportEngine(bpy.types.RenderEngine):
|
class KromViewportEngine(bpy.types.RenderEngine):
|
||||||
"""Leenkx render engine that displays Krom runtime output in viewport."""
|
"""Leenkx render engine that displays Krom runtime output in viewport."""
|
||||||
|
|
||||||
@ -190,12 +129,12 @@ class KromViewportEngine(bpy.types.RenderEngine):
|
|||||||
self._batch = None
|
self._batch = None
|
||||||
self._batch_dims = None
|
self._batch_dims = None
|
||||||
self._viewport_init_done = True
|
self._viewport_init_done = True
|
||||||
self._rendered_mode_set = False
|
|
||||||
self._last_shading_mode = None
|
self._last_shading_mode = None
|
||||||
self._viewport_id = None
|
self._viewport_id = None
|
||||||
self._shmem_name = None
|
self._shmem_name = None
|
||||||
self._krom_proc = None
|
self._krom_proc = None
|
||||||
self._krom_launch_attempted = False
|
self._krom_launch_attempted = False
|
||||||
|
self._viewport_stopped = False
|
||||||
self._pending_camera_sync = False
|
self._pending_camera_sync = False
|
||||||
self._input_enabled_state = None
|
self._input_enabled_state = None
|
||||||
self._last_region_dims = None
|
self._last_region_dims = None
|
||||||
@ -203,24 +142,6 @@ class KromViewportEngine(bpy.types.RenderEngine):
|
|||||||
self._engine_id = id(self)
|
self._engine_id = id(self)
|
||||||
# print(f"New engine instance created: {self._engine_id}")
|
# print(f"New engine instance created: {self._engine_id}")
|
||||||
|
|
||||||
def _set_rendered_mode(self, context):
|
|
||||||
if self._rendered_mode_set:
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
space = context.space_data
|
|
||||||
if space and hasattr(space, 'shading'):
|
|
||||||
current = space.shading.type
|
|
||||||
if current != 'RENDERED':
|
|
||||||
space.shading.type = 'RENDERED'
|
|
||||||
self._rendered_mode_set = True
|
|
||||||
# Disable viewport overlay so Krom output is unobstructed
|
|
||||||
if space and hasattr(space, 'overlay'):
|
|
||||||
if not hasattr(self, '_overlay_saved'):
|
|
||||||
self._overlay_saved = space.overlay.show_overlays
|
|
||||||
space.overlay.show_overlays = False
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Failed to set rendered mode: {e}")
|
|
||||||
|
|
||||||
def _restore_overlay(self, context=None):
|
def _restore_overlay(self, context=None):
|
||||||
try:
|
try:
|
||||||
if not hasattr(self, '_overlay_saved'):
|
if not hasattr(self, '_overlay_saved'):
|
||||||
@ -252,15 +173,15 @@ class KromViewportEngine(bpy.types.RenderEngine):
|
|||||||
current_mode = space.shading.type
|
current_mode = space.shading.type
|
||||||
|
|
||||||
if self._last_shading_mode == 'SOLID' and current_mode == 'RENDERED':
|
if self._last_shading_mode == 'SOLID' and current_mode == 'RENDERED':
|
||||||
|
self._viewport_stopped = False
|
||||||
self._initialized = False
|
self._initialized = False
|
||||||
self._rendered_mode_set = False
|
|
||||||
self._krom_launch_attempted = False
|
self._krom_launch_attempted = False
|
||||||
self._cleanup_shared_memory()
|
self._cleanup_shared_memory()
|
||||||
self._pending_camera_sync = True
|
self._pending_camera_sync = True
|
||||||
|
|
||||||
if self._last_shading_mode == 'RENDERED' and current_mode != 'RENDERED':
|
if self._last_shading_mode == 'RENDERED' and current_mode != 'RENDERED':
|
||||||
self._rendered_mode_set = False
|
# keep krom running in solid mode for switching back to rendered
|
||||||
# keep krom running in solid mode for switching back ti rendered
|
pass
|
||||||
|
|
||||||
self._last_shading_mode = current_mode
|
self._last_shading_mode = current_mode
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -337,13 +258,13 @@ class KromViewportEngine(bpy.types.RenderEngine):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def _stop_krom_process(self):
|
def _stop_krom_process(self):
|
||||||
if self._krom_proc:
|
import lnx.make as make
|
||||||
|
if self._viewport_id and self._viewport_id in make._viewport_processes:
|
||||||
try:
|
try:
|
||||||
import lnx.make as make
|
|
||||||
make.stop_viewport_runtime(self._viewport_id)
|
make.stop_viewport_runtime(self._viewport_id)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
self._krom_proc = None
|
self._krom_proc = None
|
||||||
self._krom_launch_attempted = False
|
self._krom_launch_attempted = False
|
||||||
self._initialized = False
|
self._initialized = False
|
||||||
self._cleanup_shared_memory()
|
self._cleanup_shared_memory()
|
||||||
@ -946,6 +867,10 @@ class KromViewportEngine(bpy.types.RenderEngine):
|
|||||||
if state.is_exporting:
|
if state.is_exporting:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if self._viewport_stopped:
|
||||||
|
self._draw_placeholder(context)
|
||||||
|
return
|
||||||
|
|
||||||
self._ensure_initialized()
|
self._ensure_initialized()
|
||||||
self._handle_mode_switch(context)
|
self._handle_mode_switch(context)
|
||||||
|
|
||||||
@ -984,8 +909,6 @@ class KromViewportEngine(bpy.types.RenderEngine):
|
|||||||
if self._viewport_id in _active_krom_engines:
|
if self._viewport_id in _active_krom_engines:
|
||||||
del _active_krom_engines[self._viewport_id]
|
del _active_krom_engines[self._viewport_id]
|
||||||
|
|
||||||
self._set_rendered_mode(context)
|
|
||||||
|
|
||||||
# TODO: input forwarding when viewport is active
|
# TODO: input forwarding when viewport is active
|
||||||
_active_krom_engine = self # legacy single-engine reference
|
_active_krom_engine = self # legacy single-engine reference
|
||||||
|
|
||||||
@ -1375,6 +1298,7 @@ class KROM_OT_stop_viewport(bpy.types.Operator):
|
|||||||
if viewport_id in _active_krom_engines:
|
if viewport_id in _active_krom_engines:
|
||||||
engine = _active_krom_engines[viewport_id]
|
engine = _active_krom_engines[viewport_id]
|
||||||
try:
|
try:
|
||||||
|
engine._viewport_stopped = True
|
||||||
engine._stop_krom_process()
|
engine._stop_krom_process()
|
||||||
engine._restore_overlay(context)
|
engine._restore_overlay(context)
|
||||||
except:
|
except:
|
||||||
@ -1422,8 +1346,6 @@ def register():
|
|||||||
for panel in get_panels():
|
for panel in get_panels():
|
||||||
panel.COMPAT_ENGINES.add('KROM_VIEWPORT')
|
panel.COMPAT_ENGINES.add('KROM_VIEWPORT')
|
||||||
|
|
||||||
if _on_depsgraph_update not in bpy.app.handlers.depsgraph_update_post:
|
|
||||||
bpy.app.handlers.depsgraph_update_post.append(_on_depsgraph_update)
|
|
||||||
atexit.register(_cleanup_krom_on_exit)
|
atexit.register(_cleanup_krom_on_exit)
|
||||||
|
|
||||||
|
|
||||||
@ -1435,9 +1357,6 @@ def unregister():
|
|||||||
_active_viewport_id = None
|
_active_viewport_id = None
|
||||||
_input_operator_running = False
|
_input_operator_running = False
|
||||||
|
|
||||||
if _on_depsgraph_update in bpy.app.handlers.depsgraph_update_post:
|
|
||||||
bpy.app.handlers.depsgraph_update_post.remove(_on_depsgraph_update)
|
|
||||||
|
|
||||||
_cleanup_krom_on_exit()
|
_cleanup_krom_on_exit()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
Reference in New Issue
Block a user