mirror of
https://github.com/Theaninova/mhlib.git
synced 2026-01-05 00:02:49 +00:00
93 lines
3.0 KiB
Rust
93 lines
3.0 KiB
Rust
use crate::lwo::object::lightwave_to_gd;
|
|
use dds::{Compression, PixelFormat, DDS};
|
|
use godot::bind::{godot_api, GodotClass};
|
|
use godot::builtin::{GodotString, PackedByteArray, StringName, ToVariant, Variant};
|
|
use godot::engine::global::Error;
|
|
use godot::engine::image::Format;
|
|
use godot::engine::{Image, ImageTexture, ResourceFormatLoader, ResourceFormatLoaderVirtual};
|
|
use godot::obj::{Base, Gd};
|
|
use lightwave_3d::LightWaveObject;
|
|
use starforcelib::sarc::SarcArchive;
|
|
use std::fs::File;
|
|
use std::io::Cursor;
|
|
|
|
const SAR_PATH: &str = r#"../games/Moorhuhn Kart 3/data.sar"#;
|
|
|
|
#[derive(GodotClass)]
|
|
#[class(base=ResourceFormatLoader)]
|
|
pub struct SarLoader {
|
|
pub archive: SarcArchive,
|
|
|
|
#[base]
|
|
pub base: Base<ResourceFormatLoader>,
|
|
}
|
|
|
|
#[godot_api]
|
|
impl SarLoader {}
|
|
|
|
#[godot_api]
|
|
impl ResourceFormatLoaderVirtual for SarLoader {
|
|
fn init(base: Base<Self::Base>) -> Self {
|
|
let mut file = File::open(SAR_PATH).unwrap();
|
|
let archive = SarcArchive::read(&mut file).unwrap();
|
|
|
|
Self { base, archive }
|
|
}
|
|
|
|
fn recognize_path(&self, path: GodotString, type_: StringName) -> bool {
|
|
path.to_string().starts_with("sar://")
|
|
}
|
|
|
|
fn load(
|
|
&self,
|
|
path: GodotString,
|
|
original_path: GodotString,
|
|
use_sub_threads: bool,
|
|
cache_mode: i64,
|
|
) -> Variant {
|
|
let internal_path = original_path
|
|
.to_string()
|
|
.strip_prefix("sar://")
|
|
.unwrap()
|
|
.replace('/', "\\");
|
|
|
|
match path.to_string().rsplit_once('.') {
|
|
Some((_, "lwo")) => {
|
|
let mut f = File::open(SAR_PATH).unwrap();
|
|
let data = self
|
|
.archive
|
|
.extract(&mut f, internal_path.as_str())
|
|
.unwrap();
|
|
let obj = LightWaveObject::read(&mut Cursor::new(data)).unwrap();
|
|
lightwave_to_gd(obj).to_variant()
|
|
}
|
|
Some((_, "bmp" | "dds")) => {
|
|
let mut f = File::open(SAR_PATH).unwrap();
|
|
|
|
let mut image = Image::new();
|
|
if let Ok(bmp) = self.archive.extract(&mut f, internal_path.as_str()) {
|
|
image.load_bmp_from_buffer(PackedByteArray::from(bmp.as_slice()));
|
|
} else if let Ok(dds) = self
|
|
.archive
|
|
.extract(&mut f, format!("{}.dds", internal_path).as_str())
|
|
{
|
|
let data = DDS::decode(&mut Cursor::new(dds)).unwrap();
|
|
image.set_data(
|
|
data.header.width as i64,
|
|
data.header.height as i64,
|
|
false,
|
|
Format::FORMAT_RGBA8,
|
|
data.layers[0]
|
|
.iter()
|
|
.flat_map(|px| [px.r, px.g, px.b, px.a])
|
|
.collect(),
|
|
)
|
|
}
|
|
image.to_variant()
|
|
}
|
|
None => Error::ERR_FILE_UNRECOGNIZED.to_variant(),
|
|
_ => Error::ERR_BUG.to_variant(),
|
|
}
|
|
}
|
|
}
|