flutter_dds 0.1.1
flutter_dds: ^0.1.1 copied to clipboard
Ein Flutter-Plugin zum Anzeigen, Bearbeiten und Exportieren von DirectDraw Surface (DDS) Texturdateien. Unterstützt DXT1 und DXT5 Formate sowie verschiedene Farbmodi.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:flutter_dds/flutter_dds.dart';
import 'package:file_picker/file_picker.dart';
/// Beispiel-Anwendung für den DDS-Viewer
///
/// Demonstriert die Verwendung des DDS-Flutter-Plugins zum
/// Laden, Anzeigen und Exportieren von DDS-Texturdateien.
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'DDS Viewer Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.blue,
brightness: Brightness.light,
),
useMaterial3: true,
),
darkTheme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.blue,
brightness: Brightness.dark,
),
useMaterial3: true,
),
themeMode: ThemeMode.system,
home: const HomePage(),
);
}
}
/// Hauptseite der Beispiel-App
///
/// Enthält eine Navigationsleiste für den Zugriff auf
/// verschiedene Demo-Funktionen
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _selectedIndex = 0;
final List<Widget> _pages = [
const ViewerDemo(),
const DirectViewDemo(),
const AboutPage(),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter DDS Demo'),
elevation: 2,
),
body: _pages[_selectedIndex],
bottomNavigationBar: NavigationBar(
selectedIndex: _selectedIndex,
onDestinationSelected: (index) {
setState(() {
_selectedIndex = index;
});
},
destinations: const [
NavigationDestination(
icon: Icon(Icons.visibility),
label: 'DDS Viewer',
),
NavigationDestination(
icon: Icon(Icons.image),
label: 'Direkt-Vorschau',
),
NavigationDestination(
icon: Icon(Icons.info),
label: 'Info',
),
],
),
);
}
}
/// Demo des vollständigen DDS-Viewers mit allen Funktionen
///
/// Zeigt den DDSViewerWidget, der das Laden, Anzeigen und
/// Exportieren von DDS-Dateien ermöglicht
class ViewerDemo extends StatelessWidget {
const ViewerDemo({super.key});
@override
Widget build(BuildContext context) {
return const DDSViewerWidget();
}
}
/// Demo der direkten DDS-Bildanzeige
///
/// Zeigt, wie man das DDSImageView-Widget direkt verwenden kann,
/// wenn der Dateipfad bekannt ist
class DirectViewDemo extends StatefulWidget {
const DirectViewDemo({super.key});
@override
State<DirectViewDemo> createState() => _DirectViewDemoState();
}
class _DirectViewDemoState extends State<DirectViewDemo> {
String? _selectedFilePath;
DDSColorMode _selectedColorMode = DDSColorMode.rgba2rgba;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Direkte DDS-Bildanzeige',
style: Theme.of(context).textTheme.headlineSmall,
),
const SizedBox(height: 8),
Text(
'Wähle eine DDS-Datei aus und zeige sie mit dem DDSImageView-Widget an.',
style: Theme.of(context).textTheme.bodyMedium,
),
const SizedBox(height: 16),
ElevatedButton.icon(
icon: const Icon(Icons.folder_open),
label: const Text('DDS-Datei auswählen'),
onPressed: _pickDDSFile,
),
const SizedBox(height: 16),
// Farbmodus-Auswahl
DropdownButtonFormField<DDSColorMode>(
decoration: const InputDecoration(
labelText: 'Farbmodus',
border: OutlineInputBorder(),
),
value: _selectedColorMode,
items: DDSColorMode.values.map((mode) {
return DropdownMenuItem(
value: mode,
child: Text(_colorModeToString(mode)),
);
}).toList(),
onChanged: (newMode) {
if (newMode != null) {
setState(() {
_selectedColorMode = newMode;
});
}
},
),
const SizedBox(height: 16),
if (_selectedFilePath != null) ...[
Expanded(
child: Card(
clipBehavior: Clip.antiAlias,
child: DDSImageView(
ddsPath: _selectedFilePath!,
colorMode: _selectedColorMode,
),
),
),
const SizedBox(height: 8),
Text(
'Datei: $_selectedFilePath',
style: Theme.of(context).textTheme.bodySmall,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
] else ...[
Expanded(
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.image, size: 64, color: Colors.grey),
const SizedBox(height: 16),
Text(
'Keine DDS-Datei ausgewählt',
style: Theme.of(context).textTheme.bodyLarge,
),
],
),
),
),
],
],
),
);
}
/// Öffnet den Datei-Dialog und wählt eine DDS-Datei aus
Future<void> _pickDDSFile() async {
try {
final result = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ['dds'],
);
if (result != null && result.files.single.path != null) {
setState(() {
_selectedFilePath = result.files.single.path!;
});
}
} catch (e) {
// Fehlerbehandlung
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Fehler: $e')),
);
}
}
}
/// Konvertiert DDSColorMode-Enum in lesbaren Text
String _colorModeToString(DDSColorMode mode) {
switch (mode) {
case DDSColorMode.bgra2rgba:
return 'BGRA → RGBA';
case DDSColorMode.rgba2rgba:
return 'Keine Konvertierung (Standard)';
case DDSColorMode.rgba2bgra:
return 'RGBA → BGRA';
}
}
}
/// Informationsseite über das DDS-Plugin
class AboutPage extends StatelessWidget {
const AboutPage({super.key});
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Flutter DDS Plugin',
style: Theme.of(context).textTheme.headlineMedium,
),
const SizedBox(height: 8),
Text(
'Version 1.0.0',
style: Theme.of(context).textTheme.bodyLarge,
),
const SizedBox(height: 16),
Text(
'Über das Plugin:',
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 8),
const Text(
'Das Flutter DDS Plugin ermöglicht das Laden, Anzeigen und Exportieren '
'von DirectDraw Surface (DDS) Texturdateien in Flutter-Anwendungen. '
'Es unterstützt verschiedene DDS-Formate und Farbmodi.',
),
const SizedBox(height: 16),
Text(
'Unterstützte Formate:',
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 8),
const _FeatureItem(title: 'DXT1', description: 'Mit und ohne Alpha-Kanal'),
const _FeatureItem(title: 'DXT5', description: 'Mit erweitertem Alpha-Kanal'),
const SizedBox(height: 16),
Text(
'Funktionen:',
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 8),
const _FeatureItem(
title: 'Farbkanal-Konvertierung',
description: 'BGRA → RGBA, RGBA → RGBA, RGBA → BGRA',
),
const _FeatureItem(
title: 'Export',
description: 'Speichern als PNG oder JPG',
),
const _FeatureItem(
title: 'Bildmanipulation',
description: 'Zoom und Pan im Betrachter',
),
const SizedBox(height: 24),
const Divider(),
const SizedBox(height: 16),
Text(
'Verwendung im Code:',
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 8),
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surfaceContainerHighest,
borderRadius: BorderRadius.circular(8),
),
child: const Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'// Vollständigen DDS-Viewer verwenden'
'\nconst DDSViewerWidget();\n'
'\n// Direkte Anzeige einer DDS-Datei'
'\nDDSImageView(\n'
' ddsPath: "/pfad/zur/datei.dds",\n'
' colorMode: DDSColorMode.rgba2rgba,\n'
');',
style: TextStyle(fontFamily: 'monospace'),
),
],
),
),
],
),
);
}
}
/// Hilfselement für die Anzeige von Features in der About-Seite
class _FeatureItem extends StatelessWidget {
final String title;
final String description;
const _FeatureItem({required this.title, required this.description});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(Icons.check_circle,
color: Theme.of(context).colorScheme.primary, size: 20),
const SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title,
style: const TextStyle(fontWeight: FontWeight.bold)),
Text(description),
],
),
),
],
),
);
}
}