mirror of
https://github.com/PrimeDecomp/retrotool.git
synced 2026-07-12 18:18:58 -07:00
Texture view updates
This commit is contained in:
@@ -70,10 +70,18 @@ unlicensed = "deny"
|
||||
# See https://spdx.org/licenses/ for list of possible licenses
|
||||
# [possible values: any SPDX 3.11 short identifier (+ optional exception)].
|
||||
allow = [
|
||||
"MIT",
|
||||
"Apache-2.0",
|
||||
"BSD-2-Clause",
|
||||
"BSD-3-Clause",
|
||||
"BSL-1.0",
|
||||
"CC0-1.0",
|
||||
"ISC",
|
||||
"LicenseRef-UFL-1.0",
|
||||
"MIT",
|
||||
"MIT-0",
|
||||
"OFL-1.1",
|
||||
"Unicode-DFS-2016",
|
||||
"Zlib",
|
||||
]
|
||||
# List of explictly disallowed licenses
|
||||
# See https://spdx.org/licenses/ for list of possible licenses
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
[package]
|
||||
name = "retrolib"
|
||||
description = "Tools for working with Retro game formats."
|
||||
authors = ["Luke Street <luke@street.dev>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
repository = "https://github.com/PrimeDecomp/retrotool"
|
||||
readme = "README.md"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.69"
|
||||
|
||||
@@ -774,7 +774,7 @@ pub struct ModelData<'a> {
|
||||
|
||||
impl ModelData<'_> {
|
||||
pub fn slice<'a>(data: &'a [u8], meta: &[u8], e: Endian) -> Result<ModelData<'a>> {
|
||||
let (cmdl_desc, mut cmdl_data, _) = FormDescriptor::slice(&data, Endian::Little)?;
|
||||
let (cmdl_desc, mut cmdl_data, _) = FormDescriptor::slice(data, Endian::Little)?;
|
||||
ensure!(cmdl_desc.id == K_FORM_CMDL);
|
||||
ensure!(cmdl_desc.version_a == 114);
|
||||
ensure!(cmdl_desc.version_b == 125);
|
||||
|
||||
+31
-6
@@ -19,7 +19,7 @@ pub const K_CHUNK_GPU: FourCC = FourCC(*b"GPU ");
|
||||
#[binrw]
|
||||
#[repr(u32)]
|
||||
#[brw(repr(u32))]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum ETextureType {
|
||||
_1D = 0,
|
||||
_2D = 1,
|
||||
@@ -35,7 +35,7 @@ pub enum ETextureType {
|
||||
#[binrw]
|
||||
#[repr(u8)]
|
||||
#[brw(repr(u8))]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum ETextureWrap {
|
||||
ClampToEdge = 0,
|
||||
Repeat = 1,
|
||||
@@ -48,7 +48,7 @@ pub enum ETextureWrap {
|
||||
#[binrw]
|
||||
#[repr(u8)]
|
||||
#[brw(repr(u8))]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum ETextureFilter {
|
||||
Nearest = 0,
|
||||
Linear = 1,
|
||||
@@ -57,7 +57,7 @@ pub enum ETextureFilter {
|
||||
#[binrw]
|
||||
#[repr(u8)]
|
||||
#[brw(repr(u8))]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum ETextureMipFilter {
|
||||
Nearest = 0,
|
||||
Linear = 1,
|
||||
@@ -66,7 +66,7 @@ pub enum ETextureMipFilter {
|
||||
#[binrw]
|
||||
#[repr(u8)]
|
||||
#[brw(repr(u8))]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum ETextureAnisotropicRatio {
|
||||
None = u8::MAX,
|
||||
_1 = 0,
|
||||
@@ -145,7 +145,7 @@ pub struct STextureMetaData {
|
||||
#[binrw]
|
||||
#[repr(u32)]
|
||||
#[brw(repr(u32))]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum ETextureFormat {
|
||||
R8Unorm = 0,
|
||||
R8Snorm = 1,
|
||||
@@ -303,6 +303,31 @@ impl ETextureFormat {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn is_srgb(self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
ETextureFormat::Rgba8Srgb
|
||||
| ETextureFormat::RgbaBc1Srgb
|
||||
| ETextureFormat::RgbaBc2Srgb
|
||||
| ETextureFormat::RgbaBc3Srgb
|
||||
| ETextureFormat::RgbaAstc4x4Srgb
|
||||
| ETextureFormat::RgbaAstc5x4Srgb
|
||||
| ETextureFormat::RgbaAstc5x5Srgb
|
||||
| ETextureFormat::RgbaAstc6x5Srgb
|
||||
| ETextureFormat::RgbaAstc6x6Srgb
|
||||
| ETextureFormat::RgbaAstc8x5Srgb
|
||||
| ETextureFormat::RgbaAstc8x6Srgb
|
||||
| ETextureFormat::RgbaAstc8x8Srgb
|
||||
| ETextureFormat::RgbaAstc10x5Srgb
|
||||
| ETextureFormat::RgbaAstc10x6Srgb
|
||||
| ETextureFormat::RgbaAstc10x8Srgb
|
||||
| ETextureFormat::RgbaAstc10x10Srgb
|
||||
| ETextureFormat::RgbaAstc12x10Srgb
|
||||
| ETextureFormat::RgbaAstc12x12Srgb
|
||||
| ETextureFormat::BptcUnormSrgb
|
||||
)
|
||||
}
|
||||
|
||||
pub fn bytes_per_pixel(self) -> u32 {
|
||||
match self {
|
||||
ETextureFormat::R8Unorm
|
||||
|
||||
@@ -15,7 +15,7 @@ use bevy::{
|
||||
prelude::*,
|
||||
};
|
||||
use binrw::Endian;
|
||||
use image::{ImageBuffer, RgbaImage};
|
||||
use image::{ RgbaImage};
|
||||
use retrolib::{
|
||||
format::{
|
||||
foot::locate_meta,
|
||||
@@ -54,7 +54,7 @@ impl AssetIo for RetroAssetIo {
|
||||
if let Some(id) =
|
||||
path.file_stem().and_then(|name| Uuid::try_parse(&name.to_string_lossy()).ok())
|
||||
{
|
||||
// Load pak header only
|
||||
// Find pak for UUID and load asset
|
||||
Box::pin(async move {
|
||||
let mut package_path: Option<PathBuf> = None;
|
||||
if let Ok(packages) = self.packages.packages.read() {
|
||||
@@ -182,20 +182,20 @@ impl AssetLoader for PackageAssetLoader {
|
||||
|
||||
#[derive(Debug, Clone, bevy::reflect::TypeUuid)]
|
||||
#[uuid = "83269869-1209-408e-8835-bc6f2496e828"]
|
||||
pub struct TxtrData {
|
||||
pub data: TextureData,
|
||||
pub struct TextureAsset {
|
||||
pub inner: TextureData,
|
||||
pub rgba: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
pub struct TxtrAssetLoader;
|
||||
pub struct TextureAssetLoader;
|
||||
|
||||
impl Plugin for TxtrAssetLoader {
|
||||
impl Plugin for TextureAssetLoader {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_asset::<TxtrData>().add_asset_loader(TxtrAssetLoader);
|
||||
app.add_asset::<TextureAsset>().add_asset_loader(TextureAssetLoader);
|
||||
}
|
||||
}
|
||||
|
||||
impl AssetLoader for TxtrAssetLoader {
|
||||
impl AssetLoader for TextureAssetLoader {
|
||||
fn load<'a>(
|
||||
&'a self,
|
||||
bytes: &'a [u8],
|
||||
@@ -220,7 +220,7 @@ impl AssetLoader for TxtrAssetLoader {
|
||||
rgba = Some(image.into_raw());
|
||||
}
|
||||
println!("Loaded texture {:?}", data.head);
|
||||
load_context.set_default_asset(LoadedAsset::new(TxtrData { data, rgba }));
|
||||
load_context.set_default_asset(LoadedAsset::new(TextureAsset { inner: data, rgba }));
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
+224
-74
@@ -1,12 +1,12 @@
|
||||
mod loaders;
|
||||
|
||||
use std::fs::FileType;
|
||||
|
||||
use bevy::{
|
||||
asset::LoadState,
|
||||
prelude::*,
|
||||
render::render_resource::{
|
||||
Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages,
|
||||
render::{
|
||||
render_resource::{
|
||||
Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages,
|
||||
},
|
||||
},
|
||||
};
|
||||
use bevy_egui::{
|
||||
@@ -15,29 +15,18 @@ use bevy_egui::{
|
||||
EguiContext, EguiPlugin, EguiSettings,
|
||||
};
|
||||
use egui::TextureId;
|
||||
use retrolib::format::txtr::K_FORM_TXTR;
|
||||
use retrolib::format::{
|
||||
txtr::{ETextureFormat, ETextureType, K_FORM_TXTR},
|
||||
FourCC,
|
||||
};
|
||||
use uuid::Uuid;
|
||||
use walkdir::{DirEntry, WalkDir};
|
||||
|
||||
use crate::loaders::{
|
||||
package_loader_system, PackageAssetLoader, PackageDirectory, RetroAssetIoPlugin,
|
||||
TxtrAssetLoader, TxtrData,
|
||||
package_loader_system, PackageAssetLoader, PackageDirectory, RetroAssetIoPlugin, TextureAsset,
|
||||
TextureAssetLoader,
|
||||
};
|
||||
|
||||
struct Images {
|
||||
bevy_icon: Handle<Image>,
|
||||
bevy_icon_inverted: Handle<Image>,
|
||||
}
|
||||
|
||||
impl FromWorld for Images {
|
||||
fn from_world(world: &mut World) -> Self {
|
||||
let asset_server = world.get_resource_mut::<AssetServer>().unwrap();
|
||||
Self {
|
||||
bevy_icon: asset_server.load("icon.png"),
|
||||
bevy_icon_inverted: asset_server.load("icon_inverted.png"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This example demonstrates the following functionality and use-cases of bevy_egui:
|
||||
/// - rendering loaded assets;
|
||||
/// - toggling hidpi scaling (by pressing '/' button);
|
||||
@@ -46,26 +35,17 @@ fn main() {
|
||||
App::new()
|
||||
.insert_resource(ClearColor(Color::rgb(0.0, 0.0, 0.0)))
|
||||
.insert_resource(Msaa { samples: 1 })
|
||||
.insert_resource(bevy::render::settings::WgpuSettings {
|
||||
features: bevy::render::settings::WgpuFeatures::TEXTURE_COMPRESSION_BC,
|
||||
..Default::default()
|
||||
})
|
||||
.init_resource::<UiState>()
|
||||
.init_resource::<Packages>()
|
||||
.init_resource::<Textures>()
|
||||
.init_resource::<OpenAsset>()
|
||||
.add_plugins(
|
||||
DefaultPlugins
|
||||
.build()
|
||||
// the custom asset io plugin must be inserted in-between the
|
||||
// `CorePlugin' and `AssetPlugin`. It needs to be after the
|
||||
// CorePlugin, so that the IO task pool has already been constructed.
|
||||
// And it must be before the `AssetPlugin` so that the asset plugin
|
||||
// doesn't create another instance of an asset server. In general,
|
||||
// the AssetPlugin should still run so that other aspects of the
|
||||
// asset system are initialized correctly.
|
||||
.add_before::<AssetPlugin, _>(RetroAssetIoPlugin),
|
||||
)
|
||||
.add_plugins(DefaultPlugins.build().add_before::<AssetPlugin, _>(RetroAssetIoPlugin))
|
||||
.add_plugin(PackageAssetLoader)
|
||||
.add_plugin(TxtrAssetLoader)
|
||||
.add_plugin(TextureAssetLoader)
|
||||
.add_plugin(EguiPlugin)
|
||||
.add_startup_system(configure_visuals)
|
||||
.add_startup_system(preload_package)
|
||||
.add_system(update_ui_scale_factor)
|
||||
.add_system(ui_example)
|
||||
@@ -74,9 +54,15 @@ fn main() {
|
||||
.run();
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Eq, PartialEq)]
|
||||
struct AssetRef {
|
||||
id: Uuid,
|
||||
kind: FourCC,
|
||||
}
|
||||
|
||||
enum TabType {
|
||||
Directory,
|
||||
Asset(HandleUntyped, Option<TextureId>),
|
||||
Texture(AssetRef, Handle<TextureAsset>, Vec<TextureId>),
|
||||
Empty,
|
||||
}
|
||||
|
||||
@@ -96,8 +82,9 @@ impl Default for UiState {
|
||||
struct TabViewer<'a> {
|
||||
server: Res<'a, AssetServer>,
|
||||
packages: Res<'a, Assets<PackageDirectory>>,
|
||||
textures: Res<'a, Assets<TxtrData>>,
|
||||
textures: Res<'a, Assets<TextureAsset>>,
|
||||
open_asset: ResMut<'a, OpenAsset>,
|
||||
tab_assets: Vec<AssetRef>,
|
||||
}
|
||||
|
||||
impl egui_dock::TabViewer for TabViewer<'_> {
|
||||
@@ -106,7 +93,10 @@ impl egui_dock::TabViewer for TabViewer<'_> {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, tab: &mut Self::Tab) {
|
||||
match tab {
|
||||
TabType::Directory => {
|
||||
for (_, package) in self.packages.iter() {
|
||||
let mut packages_sorted =
|
||||
self.packages.iter().map(|(_, p)| p).collect::<Vec<&PackageDirectory>>();
|
||||
packages_sorted.sort_by_key(|p| &p.name);
|
||||
for package in packages_sorted {
|
||||
egui::CollapsingHeader::new(&package.name).show(ui, |ui| {
|
||||
for entry in &package.entries {
|
||||
let mut job = LayoutJob::simple(
|
||||
@@ -122,30 +112,71 @@ impl egui_dock::TabViewer for TabViewer<'_> {
|
||||
TextFormat::simple(FontId::monospace(12.0), Color32::WHITE),
|
||||
);
|
||||
}
|
||||
if egui::SelectableLabel::new(false, job).ui(ui).clicked() {
|
||||
self.open_asset.0 = match entry.kind {
|
||||
let asset_ref = AssetRef { id: entry.id, kind: entry.kind };
|
||||
if egui::SelectableLabel::new(self.tab_assets.contains(&asset_ref), job)
|
||||
.ui(ui)
|
||||
.clicked()
|
||||
{
|
||||
*self.open_asset = OpenAsset(asset_ref, match entry.kind {
|
||||
K_FORM_TXTR => Some(
|
||||
self.server
|
||||
.load::<TxtrData, _>(format!(
|
||||
.load::<TextureAsset, _>(format!(
|
||||
"{}.{}",
|
||||
entry.id, entry.kind
|
||||
))
|
||||
.into(),
|
||||
),
|
||||
_ => None,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
TabType::Asset(handle, image) => {
|
||||
if let Some(txtr) = self.textures.get(&handle.typed_weak::<TxtrData>()) {
|
||||
if let Some(image) = image {
|
||||
ui.add(egui::widgets::Image::new(*image, egui::Vec2 {
|
||||
x: txtr.data.head.width as f32,
|
||||
y: txtr.data.head.height as f32,
|
||||
}));
|
||||
TabType::Texture(asset_ref, handle, images) => {
|
||||
ui.label(format!("{} {}", asset_ref.kind, asset_ref.id));
|
||||
if let Some(txtr) = self.textures.get(handle) {
|
||||
ui.label(format!("Type: {:?}", txtr.inner.head.kind));
|
||||
ui.label(format!("Format: {:?}", txtr.inner.head.format));
|
||||
ui.label(format!(
|
||||
"Dimensions: {}x{}x{} (mips: {})",
|
||||
txtr.inner.head.width,
|
||||
txtr.inner.head.height,
|
||||
txtr.inner.head.layers,
|
||||
txtr.inner.head.mip_sizes.len()
|
||||
));
|
||||
if txtr.inner.head.kind == ETextureType::Cube && images.len() == 6 {
|
||||
let width = txtr.inner.head.width * 2;
|
||||
let height = txtr.inner.head.height * 2;
|
||||
let (_, rect) = ui.allocate_space(egui::Vec2 {
|
||||
x: (width * 4) as f32,
|
||||
y: (height * 3) as f32,
|
||||
});
|
||||
let size = egui::Vec2 { x: width as f32, y: height as f32 };
|
||||
let mut draw_image = |i: usize, x: u32, y: u32| {
|
||||
let min = egui::Vec2 { x: (width * x) as f32, y: (height * y) as f32 };
|
||||
let max = egui::Vec2 {
|
||||
x: (width * (x + 1)) as f32,
|
||||
y: (height * (y + 1)) as f32,
|
||||
};
|
||||
egui::widgets::Image::new(images[i], size).paint_at(ui, egui::Rect {
|
||||
min: rect.min + min,
|
||||
max: rect.min + max,
|
||||
});
|
||||
};
|
||||
draw_image(2, 1, 0);
|
||||
draw_image(1, 0, 1);
|
||||
draw_image(4, 1, 1);
|
||||
draw_image(0, 2, 1);
|
||||
draw_image(5, 3, 1);
|
||||
draw_image(3, 1, 2);
|
||||
} else {
|
||||
for image in images {
|
||||
ui.add(egui::widgets::Image::new(*image, egui::Vec2 {
|
||||
x: txtr.inner.head.width as f32,
|
||||
y: txtr.inner.head.height as f32,
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -156,22 +187,16 @@ impl egui_dock::TabViewer for TabViewer<'_> {
|
||||
fn title(&mut self, tab: &mut Self::Tab) -> egui::WidgetText {
|
||||
match tab {
|
||||
TabType::Directory => "Directory".into(),
|
||||
TabType::Asset(_, _) => "Asset view".into(),
|
||||
TabType::Texture(asset_ref, _, _) => {
|
||||
format!("{} {}", asset_ref.kind, asset_ref.id).into()
|
||||
}
|
||||
TabType::Empty => "Placeholder".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn configure_visuals(mut egui_ctx: ResMut<EguiContext>) {
|
||||
// egui_ctx
|
||||
// .ctx_mut()
|
||||
// .set_visuals(egui::Visuals { window_rounding: 0.0.into(), ..Default::default() });
|
||||
}
|
||||
|
||||
#[derive(Default, Resource)]
|
||||
struct Packages(Vec<Handle<PackageDirectory>>);
|
||||
#[derive(Default, Resource)]
|
||||
struct Textures(Vec<Handle<TxtrData>>);
|
||||
|
||||
fn is_hidden(entry: &DirEntry) -> bool {
|
||||
entry.file_name().to_str().map(|s| s.starts_with('.')).unwrap_or(false)
|
||||
@@ -190,42 +215,147 @@ fn check_assets_ready(
|
||||
server: Res<AssetServer>,
|
||||
mut loading: ResMut<OpenAsset>,
|
||||
mut ui_state: ResMut<UiState>,
|
||||
textures: Res<Assets<TxtrData>>,
|
||||
textures: Res<Assets<TextureAsset>>,
|
||||
mut egui_ctx: ResMut<EguiContext>,
|
||||
mut images: ResMut<Assets<Image>>,
|
||||
) {
|
||||
if let Some(handle) = &loading.0 {
|
||||
let OpenAsset(asset_ref, opt_handle) = &mut *loading;
|
||||
if let Some(handle) = &*opt_handle {
|
||||
let state = server.get_load_state(handle);
|
||||
match state {
|
||||
LoadState::NotLoaded => {}
|
||||
LoadState::Loading => {}
|
||||
LoadState::Loaded => {
|
||||
let handle = std::mem::take(&mut loading.0).unwrap();
|
||||
let txtr = textures.get(&handle.typed_weak::<TxtrData>()).unwrap();
|
||||
let image = if let Some(rgba) = &txtr.rgba {
|
||||
let handle = std::mem::take(opt_handle).unwrap().typed::<TextureAsset>();
|
||||
let txtr = textures.get(&handle).unwrap();
|
||||
let mut texture_ids = Vec::new();
|
||||
if let Some(rgba) = &txtr.rgba {
|
||||
let image_handle = images.add(Image {
|
||||
data: rgba.clone(),
|
||||
texture_descriptor: TextureDescriptor {
|
||||
label: None,
|
||||
size: Extent3d {
|
||||
width: txtr.data.head.width,
|
||||
height: txtr.data.head.height,
|
||||
width: txtr.inner.head.width,
|
||||
height: txtr.inner.head.height,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: TextureDimension::D2,
|
||||
format: TextureFormat::Rgba8Unorm,
|
||||
format: if txtr.inner.head.format.is_srgb() {
|
||||
TextureFormat::Rgba8UnormSrgb
|
||||
} else {
|
||||
TextureFormat::Rgba8Unorm
|
||||
},
|
||||
usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST,
|
||||
},
|
||||
sampler_descriptor: Default::default(),
|
||||
texture_view_descriptor: None,
|
||||
});
|
||||
Some(egui_ctx.add_image(image_handle))
|
||||
texture_ids.push(egui_ctx.add_image(image_handle));
|
||||
} else {
|
||||
None
|
||||
let array_stride: usize = (txtr.inner.head.mip_sizes.iter().sum::<u32>()
|
||||
/ txtr.inner.head.layers)
|
||||
as usize;
|
||||
for layer in 0..txtr.inner.head.layers as usize {
|
||||
let image_handle = images.add(Image {
|
||||
data: txtr.inner.data
|
||||
[layer * array_stride..(layer * array_stride) + array_stride]
|
||||
.to_vec(),
|
||||
texture_descriptor: TextureDescriptor {
|
||||
label: None,
|
||||
size: Extent3d {
|
||||
width: txtr.inner.head.width,
|
||||
height: txtr.inner.head.height,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
mip_level_count: txtr.inner.head.mip_sizes.len() as u32,
|
||||
sample_count: 1,
|
||||
dimension: match txtr.inner.head.kind {
|
||||
ETextureType::_1D => TextureDimension::D1,
|
||||
ETextureType::_2D => TextureDimension::D2,
|
||||
ETextureType::_3D => TextureDimension::D3,
|
||||
ETextureType::Cube => TextureDimension::D2,
|
||||
ETextureType::_1DArray => TextureDimension::D1,
|
||||
ETextureType::_2DArray => TextureDimension::D2,
|
||||
ETextureType::_2DMultisample => TextureDimension::D2,
|
||||
ETextureType::_2DMultisampleArray => TextureDimension::D2,
|
||||
ETextureType::CubeArray => TextureDimension::D2,
|
||||
},
|
||||
format: match txtr.inner.head.format {
|
||||
ETextureFormat::R8Unorm => TextureFormat::Rgba8Unorm,
|
||||
ETextureFormat::R8Snorm => TextureFormat::R8Snorm,
|
||||
ETextureFormat::R8Uint => TextureFormat::R8Uint,
|
||||
ETextureFormat::R8Sint => TextureFormat::R8Sint,
|
||||
ETextureFormat::R16Unorm => TextureFormat::R16Unorm,
|
||||
ETextureFormat::R16Snorm => TextureFormat::R16Snorm,
|
||||
ETextureFormat::R16Uint => TextureFormat::R16Uint,
|
||||
ETextureFormat::R16Sint => TextureFormat::R16Sint,
|
||||
ETextureFormat::R16Float => TextureFormat::R16Float,
|
||||
ETextureFormat::R32Uint => TextureFormat::R32Uint,
|
||||
ETextureFormat::R32Sint => TextureFormat::R32Sint,
|
||||
ETextureFormat::Rgba8Unorm => TextureFormat::Rgba8Unorm,
|
||||
ETextureFormat::Rgba8Srgb => TextureFormat::Rgba8UnormSrgb,
|
||||
ETextureFormat::Rgba16Float => TextureFormat::Rgba16Float,
|
||||
ETextureFormat::Rgba32Float => TextureFormat::Rgba32Float,
|
||||
ETextureFormat::Depth16Unorm => TextureFormat::Depth16Unorm,
|
||||
ETextureFormat::Depth16Unorm2 => TextureFormat::Depth16Unorm,
|
||||
ETextureFormat::Depth24S8Unorm => {
|
||||
TextureFormat::Depth24PlusStencil8
|
||||
}
|
||||
ETextureFormat::Depth32Float => TextureFormat::Depth32Float,
|
||||
ETextureFormat::RgbaBc1Unorm => TextureFormat::Bc1RgbaUnorm,
|
||||
ETextureFormat::RgbaBc1Srgb => TextureFormat::Bc1RgbaUnormSrgb,
|
||||
ETextureFormat::RgbaBc2Unorm => TextureFormat::Bc2RgbaUnorm,
|
||||
ETextureFormat::RgbaBc2Srgb => TextureFormat::Bc2RgbaUnormSrgb,
|
||||
ETextureFormat::RgbaBc3Unorm => TextureFormat::Bc3RgbaUnorm,
|
||||
ETextureFormat::RgbaBc3Srgb => TextureFormat::Bc3RgbaUnormSrgb,
|
||||
ETextureFormat::RgbaBc4Unorm => TextureFormat::Bc4RUnorm,
|
||||
ETextureFormat::RgbaBc4Snorm => TextureFormat::Bc4RSnorm,
|
||||
ETextureFormat::RgbaBc5Unorm => TextureFormat::Bc5RgUnorm,
|
||||
ETextureFormat::RgbaBc5Snorm => TextureFormat::Bc5RgSnorm,
|
||||
ETextureFormat::Rg11B10Float => TextureFormat::Rg11b10Float,
|
||||
ETextureFormat::R32Float => TextureFormat::R32Float,
|
||||
ETextureFormat::Rg8Unorm => TextureFormat::Rg8Unorm,
|
||||
ETextureFormat::Rg8Snorm => TextureFormat::Rg8Snorm,
|
||||
ETextureFormat::Rg8Uint => TextureFormat::Rg8Uint,
|
||||
ETextureFormat::Rg8Sint => TextureFormat::Rg8Sint,
|
||||
ETextureFormat::Rg16Float => TextureFormat::Rg16Float,
|
||||
ETextureFormat::Rg16Unorm => TextureFormat::Rg16Unorm,
|
||||
ETextureFormat::Rg16Snorm => TextureFormat::Rg16Snorm,
|
||||
ETextureFormat::Rg16Uint => TextureFormat::Rg16Uint,
|
||||
ETextureFormat::Rg16Sint => TextureFormat::Rg16Sint,
|
||||
ETextureFormat::Rgb10A2Unorm => TextureFormat::Rgb10a2Unorm,
|
||||
ETextureFormat::Rg32Uint => TextureFormat::Rg32Uint,
|
||||
ETextureFormat::Rg32Sint => TextureFormat::Rg32Sint,
|
||||
ETextureFormat::Rg32Float => TextureFormat::Rg32Float,
|
||||
ETextureFormat::Rgba16Unorm => TextureFormat::Rgba16Unorm,
|
||||
ETextureFormat::Rgba16Snorm => TextureFormat::Rgba16Snorm,
|
||||
ETextureFormat::Rgba16Uint => TextureFormat::Rgba16Uint,
|
||||
ETextureFormat::Rgba16Sint => TextureFormat::Rgba16Sint,
|
||||
ETextureFormat::Rgba32Uint => TextureFormat::Rgba32Uint,
|
||||
ETextureFormat::Rgba32Sint => TextureFormat::Rgba32Sint,
|
||||
ETextureFormat::BptcUfloat => TextureFormat::Bc6hRgbUfloat,
|
||||
ETextureFormat::BptcSfloat => TextureFormat::Bc6hRgbSfloat,
|
||||
ETextureFormat::BptcUnorm => TextureFormat::Bc7RgbaUnorm,
|
||||
ETextureFormat::BptcUnormSrgb => {
|
||||
TextureFormat::Bc7RgbaUnormSrgb
|
||||
}
|
||||
_ => todo!(),
|
||||
},
|
||||
usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST,
|
||||
},
|
||||
sampler_descriptor: Default::default(),
|
||||
texture_view_descriptor: None,
|
||||
});
|
||||
texture_ids.push(egui_ctx.add_image(image_handle));
|
||||
}
|
||||
};
|
||||
ui_state.tree.push_to_first_leaf(TabType::Asset(handle, image));
|
||||
ui_state.tree.push_to_first_leaf(TabType::Texture(
|
||||
asset_ref.clone(),
|
||||
handle,
|
||||
texture_ids,
|
||||
));
|
||||
}
|
||||
LoadState::Failed => {}
|
||||
LoadState::Unloaded => {}
|
||||
@@ -251,13 +381,13 @@ fn update_ui_scale_factor(
|
||||
}
|
||||
|
||||
#[derive(Default, Resource)]
|
||||
struct OpenAsset(Option<HandleUntyped>);
|
||||
struct OpenAsset(AssetRef, Option<HandleUntyped>);
|
||||
|
||||
fn ui_example(
|
||||
mut egui_ctx: ResMut<EguiContext>,
|
||||
mut ui_state: ResMut<UiState>,
|
||||
packages: Res<Assets<PackageDirectory>>,
|
||||
textures: Res<Assets<TxtrData>>,
|
||||
textures: Res<Assets<TextureAsset>>,
|
||||
server: Res<AssetServer>,
|
||||
open_asset: ResMut<OpenAsset>,
|
||||
) {
|
||||
@@ -272,7 +402,27 @@ fn ui_example(
|
||||
});
|
||||
});
|
||||
|
||||
let mut tab_assets = vec![];
|
||||
for node in ui_state.tree.iter() {
|
||||
if let egui_dock::Node::Leaf { tabs, .. } = node {
|
||||
for tab in tabs {
|
||||
match tab {
|
||||
TabType::Directory => {}
|
||||
TabType::Texture(asset_ref, _, _) => {
|
||||
tab_assets.push(asset_ref.clone());
|
||||
}
|
||||
TabType::Empty => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
egui_dock::DockArea::new(&mut ui_state.tree)
|
||||
.style(egui_dock::Style::from_egui(egui_ctx.ctx_mut().style().as_ref()))
|
||||
.show(egui_ctx.ctx_mut(), &mut TabViewer { server, packages, textures, open_asset });
|
||||
.show(egui_ctx.ctx_mut(), &mut TabViewer {
|
||||
server,
|
||||
packages,
|
||||
textures,
|
||||
open_asset,
|
||||
tab_assets,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user