# Quick Start

If all you need is a quick and easy route to rendering a single 3D model in your Flutter application, start with `ViewerWidget`.

This is a simplified, Flutter-only wrapper around the underlying 3D rendering API with sane defaults for most people.

`ViewerWidget` handles all the setup and configuration of the underlying Thermion API, including:
- Loading 3D models (glTF assets)
- Configuring skyboxes and image-based lighting
- Setting up camera positions and manipulators
- Managing the rendering lifecycle

## Setup

Follow the steps listed in [Getting Started](./getting_started) to configure your Flutter installation and project.

If you're running Windows, delete the `examples/flutter/quickstart/assets` symlink and copy the `assets` folder from `examples/assets` to `examples/flutter/quickstart/assets`.

## Basic Usage

```dart
import 'package:flutter/material.dart';
import 'package:thermion_flutter/thermion_flutter.dart';
import 'path_to_your_viewer_widget.dart';

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: ViewerWidget(
          assetPath: 'assets/my_model.glb',
          initialCameraPosition: Vector3(0, 0, 5),
          manipulatorType: ManipulatorType.ORBIT,
        ),
      ),
    );
  }
}
```

## Properties

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `initial` | `Widget` | Red decorated box | Widget to display while the viewer is loading |
| `initialCameraPosition` | `Vector3` | `Vector3(0, 0, 5)` | The starting position for the camera (looking towards origin) |
| `showFpsCounter` | `bool` | `false` | Whether to show an FPS counter overlay |
| `assetPath` | `String?` | `null` | Path to the glTF asset to load |
| `skyboxPath` | `String?` | `null` | Path to a KTX skybox image |
| `iblPath` | `String?` | `null` | Path to a KTX image for image-based lighting |
| `directLightType` | `LightType?` | `null` | Type of direct light to add to the scene |
| `transformToUnitCube` | `bool` | `true` | If true, rescales the model to fit within a 1x1x1 cube |
| `postProcessing` | `bool` | `true` | Enables ACES tone mapping and basic anti-aliasing |
| `background` | `Color?` | `null` | Background color (not visible when skybox is provided) |
| `destroyEngineOnUnload` | `bool` | `false` | If true, disposes the engine when widget is disposed |
| `manipulatorType` | `ManipulatorType` | `ORBIT` | Type of camera control to use |
| `onViewerAvailable` | `Future Function(ThermionViewer)?` | `null` | Callback when viewer is ready |

## Camera Manipulators

`ViewerWidget` supports three different camera manipulation modes:

- `ManipulatorType.NONE`: No camera controls, static view
- `ManipulatorType.ORBIT`: Orbit controls (pinch to zoom, swipe to rotate)
- `ManipulatorType.FREE_FLIGHT`: Free flight controls for unrestricted movement

Example:

```dart
ViewerWidget(
  assetPath: 'assets/model.glb',
  manipulatorType: ManipulatorType.FREE_FLIGHT,
)
```

## Lighting

You can set up lighting in multiple ways:

### Image-Based Lighting

```dart
ViewerWidget(
  assetPath: 'assets/model.glb',
  iblPath: 'assets/environment.ktx',
)
```

### Direct Light

```dart
ViewerWidget(
  assetPath: 'assets/model.glb',
  directLightType: LightType.SUN,
)
```

## Advanced Usage

### Accessing the Viewer

You can get access to the underlying `ThermionViewer` object for more advanced control:

```dart
ViewerWidget(
  assetPath: 'assets/model.glb',
  onViewerAvailable: (viewer) async {
    // Now you can use the viewer directly
    final camera = await viewer.getActiveCamera();
    await camera.lookAt(Vector3(0, 1, 5));
    
    // Add custom lights, manipulate materials, etc.
  },
)
```

### Changing Manipulator at Runtime

The `manipulatorType` is the only property that can be changed after the widget is created:

```dart
class _MyWidgetState extends State<MyWidget> {
  ManipulatorType _manipulatorType = ManipulatorType.ORBIT;
  
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Expanded(
          child: ViewerWidget(
            assetPath: 'assets/model.glb',
            manipulatorType: _manipulatorType,
          ),
        ),
        Row(
          children: [
            ElevatedButton(
              onPressed: () {
                setState(() {
                  _manipulatorType = ManipulatorType.ORBIT;
                });
              },
              child: Text('Orbit'),
            ),
            ElevatedButton(
              onPressed: () {
                setState(() {
                  _manipulatorType = ManipulatorType.FREE_FLIGHT;
                });
              },
              child: Text('Free Flight'),
            ),
          ],
        ),
      ],
    );
  }
}
```

## Limitations

- Only the `manipulatorType` property can be changed at runtime. For any other property changes, create a new widget.
- The widget requires that you have the correct environment setup for Thermion (Flutter master channel with native assets enabled).

## Example

Here's a complete example showing how to use `ViewerWidget` with multiple configuration options:

```dart
import 'package:flutter/material.dart';
import 'package:thermion_flutter/thermion_flutter.dart';
import 'package:vector_math/vector_math_64.dart';

class ModelViewer extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('3D Model Viewer')),
      body: ViewerWidget(
        assetPath: 'assets/robot.glb',
        skyboxPath: 'assets/studio_skybox.ktx',
        iblPath: 'assets/studio_ibl.ktx',
        initialCameraPosition: Vector3(0, 1.5, 3),
        manipulatorType: ManipulatorType.ORBIT,
        showFpsCounter: true,
        background: Colors.grey,
        postProcessing: true,
        transformToUnitCube: true,
        onViewerAvailable: (viewer) async {
          // You can perform additional setup here
          print('Viewer is ready!');
        },
      ),
    );
  }
}
```