# Copyright (c) VOLVICON.
#
# This file is provided solely for educational purposes in connection with
# the Volvicon software and related documentation.
#
# You may use and modify this file for personal or internal purposes when
# working with Volvicon products. Any reproduction, distribution, or use
# of this file outside the Volvicon ecosystem is strictly prohibited
# without prior written authorization from VOLVICON.

"""
3D View Settings Tutorial.

This tutorial demonstrates how to control the options found in the
3D View Settings dialog through the scripting API, including performance,
visualization, floor shadows, back face coloring, and miscellaneous
scene appearance settings.

Topics covered:
- Performance (rendering quality, interactive update rate)
- Visualization (depth peeling, FXAA, hidden line removal)
- Ambient occlusion shadows for improved depth perception
- Floor shadows (enable, quality, softness, darkness, floor plane)
- Back face coloring
- Miscellaneous (scene bounding box color, axes labels color, axes scale)

Prerequisites:
- Volvicon application must be running
- A valid license must be active
"""

import ScriptingApi as api

# Create Application instance and get view operations
app = api.Application()
view_operations = app.get_view_operations()

# =============================================================================
# Performance - Rendering Quality
# =============================================================================
# Control how much detail is kept while the 3D scene is being rotated, panned,
# or zoomed. Higher quality preserves more detail but can lower the frame rate.
#
# Available quality levels:
#   api.RenderingQuality.Adaptive   - Detail is reduced automatically while
#                                     interacting to keep the view responsive
#   api.RenderingQuality.Normal     - A fixed balance between detail and speed
#   api.RenderingQuality.Maximum    - Full detail is kept at all times

# Set adaptive rendering quality (default)
view_operations.set_rendering_quality(api.RenderingQuality.Adaptive)

# Get the current rendering quality
quality = view_operations.get_rendering_quality()
print(f"Rendering quality: {quality}")

# Keep full detail while interacting (recommended with Mask 3D Preview (Direct))
# view_operations.set_rendering_quality(api.RenderingQuality.Maximum)

# =============================================================================
# Performance - Interactive Update Rate
# =============================================================================
# Set the target frames per second used while the scene is being manipulated.
# Higher values favor smoother interaction over detail. Valid range is 1 to 100.
#
# Note: the update rate has no effect while the rendering quality is set to
# api.RenderingQuality.Maximum, where full detail is always used.

# Set a 30 FPS interactive update rate
view_operations.set_rendering_update_rate(30.0)

# Get the current update rate
update_rate = view_operations.get_rendering_update_rate()
print(f"Interactive update rate: {update_rate} FPS")

# =============================================================================
# Visualization - Depth Peeling, FXAA, Hidden Line Removal
# =============================================================================
# Toggle rendering options that affect image quality in the 3D view.

# Depth peeling renders translucent geometry in the correct order.
# Enabling it can reduce rendering performance.
view_operations.set_depth_peeling_enabled(True)
print(f"Depth peeling enabled: {view_operations.is_depth_peeling_enabled()}")

# FXAA smooths the edges of 3D geometry (when supported by the graphics card).
view_operations.set_fxaa_enabled(True)
print(f"FXAA enabled: {view_operations.is_fxaa_enabled()}")

# Hidden line removal draws only the front wireframe surface.
view_operations.set_hidden_line_removal_enabled(False)
print(f"Hidden line removal enabled: {view_operations.is_hidden_line_removal_enabled()}")

# =============================================================================
# Visualization - Ambient Occlusion (Depth Perception)
# =============================================================================
# Ambient occlusion darkens crevices and contact areas so the shape of surfaces
# is easier to read. It is currently not applied to volume rendering.

# Enable ambient occlusion shadows
view_operations.set_ambient_occlusion_enabled(True)
print(f"Ambient occlusion enabled: {view_operations.is_ambient_occlusion_enabled()}")

# Set the ambient occlusion scale factor. Valid range is -3 to 3.
# A value of 0 enables automatic mode, where the scale is chosen automatically
# based on the sizes of the scene objects.
view_operations.set_ambient_occlusion_scale_factor(0.0)  # automatic
print(f"Ambient occlusion scale factor: {view_operations.get_ambient_occlusion_scale_factor()}")

# Use a fixed scale factor instead of automatic mode
# view_operations.set_ambient_occlusion_scale_factor(1.5)

# Disable ambient occlusion again
# view_operations.set_ambient_occlusion_enabled(False)

# =============================================================================
# Visualization - Floor Shadows
# =============================================================================
# Floor shadows let the scene lights cast soft shadows onto opaque surfaces and
# an invisible floor beneath the model. Shadows are cast by switched-on
# directional lights and spotlights whose cast-shadows option is enabled.
# Headlights, point lights, and volume rendering do not cast these shadows.

# Enable floor shadows
view_operations.set_floor_shadows_enabled(True)
print(f"Floor shadows enabled: {view_operations.is_floor_shadows_enabled()}")

# Set the shadow quality. Higher quality gives sharper outlines but uses more
# graphics memory and time.
#   api.FloorShadowsQuality.Low      - Lowest shadow detail
#   api.FloorShadowsQuality.Medium   - Balanced shadow detail (default)
#   api.FloorShadowsQuality.High     - High shadow detail
#   api.FloorShadowsQuality.Ultra    - Highest shadow detail
view_operations.set_floor_shadows_quality(api.FloorShadowsQuality.Medium)

# Set the shadow edge softness. Valid range is 0 to 8.
# 0 gives hard edges; higher values give softer, more diffuse shadows.
view_operations.set_floor_shadows_softness(3.0)

# Set the shadow darkness (strength). Valid range is 0 to 1.
# 0 gives no shadows; 1 gives the strongest shadows.
view_operations.set_floor_shadows_darkness(0.6)

# Align the invisible floor with a world plane:
#   api.ShadowFloorPlane.XY   - Floor on the XY plane (Z up)
#   api.ShadowFloorPlane.XZ   - Floor on the XZ plane (Y up)
#   api.ShadowFloorPlane.YZ   - Floor on the YZ plane (X up)
view_operations.set_floor_shadows_plane(api.ShadowFloorPlane.XY)

quality = view_operations.get_floor_shadows_quality()
softness = view_operations.get_floor_shadows_softness()
darkness = view_operations.get_floor_shadows_darkness()
plane = view_operations.get_floor_shadows_plane()
print(f"Floor shadows - quality: {quality}, softness: {softness}, darkness: {darkness}, plane: {plane}")

# Disable floor shadows again
# view_operations.set_floor_shadows_enabled(False)

# =============================================================================
# Visualization - Back Face Coloring
# =============================================================================
# Back face coloring draws the back faces of surfaces with a separate color,
# which helps distinguish inside and outside surfaces.
# Colors are specified as [r, g, b] arrays with component values in [0.0, 1.0].

# Enable back face coloring and set a magenta back face color
view_operations.set_back_face_coloring_enabled(True)
view_operations.set_back_face_color([0.94, 0.0, 0.98])

is_back_face_on = view_operations.is_back_face_coloring_enabled()
back_face_color = view_operations.get_back_face_color()
print(f"Back face coloring enabled: {is_back_face_on}, color: {back_face_color}")

# Disable back face coloring again
# view_operations.set_back_face_coloring_enabled(False)

# =============================================================================
# Miscellaneous - Scene Colors And Axes Scale
# =============================================================================
# Set the colors of the scene bounding box and axes labels, and the relative
# size of the origin and crosshair axes.
# Colors are specified as [r, g, b] arrays with component values in [0.0, 1.0].

# Set the scene bounding box color to black
view_operations.set_3d_scene_bounding_box_color([0.0, 0.0, 0.0])

# Set the scene axes labels color to black
view_operations.set_3d_scene_axes_labels_color([0.0, 0.0, 0.0])

bbox_color = view_operations.get_3d_scene_bounding_box_color()
labels_color = view_operations.get_3d_scene_axes_labels_color()
print(f"Scene bounding box color: {bbox_color}, axes labels color: {labels_color}")

# Set the origin and crosshair axes sizes as percentages (valid range 1 to 100)
view_operations.set_3d_origin_axes_scale(10.0)
view_operations.set_3d_crosshair_axes_scale(30.0)

origin_scale = view_operations.get_3d_origin_axes_scale()
crosshair_scale = view_operations.get_3d_crosshair_axes_scale()
print(f"Origin axes scale: {origin_scale}%, crosshair axes scale: {crosshair_scale}%")

print("3D view settings tutorial complete.")
