Skip to content

Commit f49f1ff

Browse files
committed
add stubs for Puppet2d and LipSync, add metadata util, add build script, update lib name in Cargo.toml
1 parent e75e9b2 commit f49f1ff

File tree

10 files changed

+204
-3
lines changed

10 files changed

+204
-3
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[package]
2-
name = "vpuppr-rust-lib"
2+
name = "libvpuppr"
33
version = "0.1.0"
44
edition = "2021"
55
authors = ["Tim Yuen<[email protected]>"]

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ with [godot-rust](https://github.com/godot-rust/gdext) for [vpuppr](https://gith
55

66
This repository is meant to be used as a git submodule in the main vpuppr repository.
77

8+
## Building
9+
10+
Run `python build.py --help` for possible options. This is a simple wrapper around
11+
`cargo build` and `cargo build --release` that also renames the output libraries
12+
to `libvpuppr.dll` or `libvpuppr.so` depending on platform.
13+
814
## License
915

1016
MPL-2.0

build.py

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# /usr/bin/env python
2+
3+
"""
4+
Utility script for building consistent shared libraries for vpuppr.
5+
"""
6+
7+
import os
8+
from os import path
9+
import subprocess
10+
from argparse import ArgumentParser
11+
from typing import Union, List
12+
from enum import Enum
13+
import platform
14+
15+
16+
# NOTE: this is technically the wrong way to name shared libs on Windows but whatever
17+
LIB_NAME_FORMAT: str = "libvpuppr.{}"
18+
19+
20+
def get_output_dir() -> Union[str, None]:
21+
"""
22+
The output path for `cargo build`.
23+
"""
24+
script_dir: str = path.dirname(__file__)
25+
output_dir: str = path.join(script_dir, "target")
26+
27+
return output_dir if path.isdir(output_dir) else None
28+
29+
30+
class BuildFlag(Enum):
31+
DEBUG = 0
32+
RELEASE = 1
33+
34+
35+
def build(flag: BuildFlag) -> None:
36+
command: List[str] = ["cargo", "build"]
37+
38+
if flag == BuildFlag.RELEASE:
39+
command.append("--release")
40+
41+
ret = subprocess.run(command, text=True)
42+
43+
if ret.returncode != 0:
44+
raise Exception("Failed to build: {}".format(ret.stderr))
45+
46+
output_dir = get_output_dir()
47+
if not output_dir:
48+
raise Exception("Unable to get output directory")
49+
50+
if flag == BuildFlag.DEBUG:
51+
output_dir = "{}/debug".format(output_dir)
52+
elif flag == BuildFlag.RELEASE:
53+
output_dir = "{}/release".format(output_dir)
54+
else:
55+
raise Exception("Bad build flag: {}".format(flag))
56+
57+
if not path.isdir(output_dir):
58+
raise Exception(
59+
"{} does not exist, the build probably failed".format(output_dir))
60+
61+
# Sorry MacOS, you will have to build manually since automating builds
62+
# on MacOS is a huge pain
63+
lib_ending: str = "dll" if platform.system() == "Windows" else "so"
64+
rename_count: int = 0
65+
66+
for file in os.listdir(os.fsencode(output_dir)):
67+
file_name: str = os.fsdecode(file)
68+
69+
if file_name.lower().endswith(lib_ending):
70+
rename_count += 1
71+
os.rename("{}/{}".format(output_dir, file_name),
72+
"{}/{}".format(output_dir, LIB_NAME_FORMAT.format(lib_ending)))
73+
74+
if rename_count != 1:
75+
# TODO just a warning for now
76+
print("Renamed an unexpected amount of files: {}".format(
77+
rename_count), flush=True)
78+
79+
80+
def main() -> None:
81+
# Make sure we are building in the correct directory
82+
os.chdir(path.dirname(__file__))
83+
84+
parser = ArgumentParser("libvpuppr-build")
85+
parser.add_argument("--debug", action="store_true",
86+
help="Build the lib in debug mode")
87+
parser.add_argument("--release", action="store_true",
88+
help="Build the lib in release mode")
89+
90+
args = parser.parse_args()
91+
92+
changed = False
93+
94+
# NOTE: I know it's possible to configure argparse to do this automatically, and I don't care
95+
if args.debug:
96+
changed = True
97+
build(BuildFlag.DEBUG)
98+
if args.release:
99+
changed = True
100+
build(BuildFlag.RELEASE)
101+
102+
if not changed:
103+
raise Exception("An option must be selected")
104+
105+
106+
if __name__ == "__main__":
107+
main()

libvpuppr.gdextension

+5-2
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,8 @@ entry_symbol = "gdext_rust_init"
33
compatibility_minimum = 4.1
44

55
[libraries]
6-
windows.debug.x86_64 = "res://vpuppr-rust-lib/target/debug/vpuppr_rust_lib.dll"
7-
windows.release.x86_64 = "res://vpuppr-rust-lib/target/release/vpuppr_rust_lib.dll"
6+
windows.debug.x86_64 = "res://libvpuppr/target/debug/libvpuppr.dll"
7+
windows.release.x86_64 = "res://libvpuppr/target/release/libvpuppr.dll"
8+
9+
linux.debug.x86_64 = "res://libvpuppr/target/debug/libvpuppr.so"
10+
linux.release.x86_64 = "res://libvpuppr/target/release/libvpuppr.so"

src/lib.rs

+34
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
mod logger;
2+
23
pub use logger::Logger;
34
pub mod model;
45
mod puppets;
@@ -22,6 +23,39 @@ macro_rules! vstring {
2223
}
2324
pub(crate) use vstring;
2425

26+
/// Helper struct for information about the libvpuppr library.
27+
#[derive(Debug, Default, GodotClass)]
28+
struct LibVpuppr;
29+
30+
#[godot_api]
31+
impl RefCountedVirtual for LibVpuppr {
32+
fn init(_base: godot::obj::Base<Self::Base>) -> Self {
33+
Self
34+
}
35+
}
36+
37+
#[godot_api]
38+
impl LibVpuppr {
39+
/// A mapping of various vpuppr metadata.
40+
#[func]
41+
fn metadata() -> Dictionary {
42+
let mut mapping = Dictionary::new();
43+
44+
let is_debug = if cfg!(debug_assertions) { true } else { false };
45+
mapping.insert("DEBUG", is_debug);
46+
mapping.insert("RELEASE", !is_debug);
47+
48+
mapping.insert("VERSION", env!("CARGO_PKG_VERSION"));
49+
mapping.insert("VERSION_MAJOR", env!("CARGO_PKG_VERSION_MAJOR"));
50+
mapping.insert("VERSION_MINOR", env!("CARGO_PKG_VERSION_MINOR"));
51+
mapping.insert("VERSION_PATCH", env!("CARGO_PKG_VERSION_PATCH"));
52+
53+
mapping.insert("LIBVPUPPR_AUTHORS", env!("CARGO_PKG_AUTHORS"));
54+
55+
mapping
56+
}
57+
}
58+
2559
struct GodotExtension;
2660

2761
#[gdextension]

src/puppets.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
mod puppet_2d;
12
mod puppet_3d;

src/puppets/puppet_2d.rs

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
use godot::prelude::*;
2+
3+
use crate::{gstring, vstring, Logger};
4+
5+
#[derive(Debug, GodotClass)]
6+
#[class(base = Node2D)]
7+
struct Puppet2d {
8+
#[var]
9+
logger: Gd<Logger>,
10+
11+
#[base]
12+
base: Base<Node2D>,
13+
}
14+
15+
#[godot_api]
16+
impl Node2DVirtual for Puppet2d {
17+
fn init(base: godot::obj::Base<Self::Base>) -> Self {
18+
Self {
19+
logger: Logger::create(gstring!("Puppet2d")),
20+
21+
base,
22+
}
23+
}
24+
25+
fn ready(&mut self) {
26+
// TODO stub
27+
}
28+
}
29+
30+
#[godot_api]
31+
impl Puppet2d {}

src/receivers.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
mod lip_sync;
12
mod meow_face;
23

34
use godot::{engine::global::Error, prelude::*};

src/receivers/lip_sync.rs

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*!
2+
A receiver for lip syncing data.
3+
4+
This implementation takes audio input from Godot, converts that audio to text,
5+
and then generates phonemes from them. The text and phonemes are both usable
6+
from vpuppr, allowing for both model lip-sync and actions based off of voice commands.
7+
*/
8+
9+
use godot::prelude::*;
10+
11+
// TODO maybe use https://github.com/tazz4843/whisper-rs instead of own impl
12+
// use in conjunction with https://github.com/Dalvany/rphonetic
13+
14+
struct LipSync {}

src/receivers/meow_face.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
/*!
2+
A receiver for [MeowFace](https://play.google.com/store/apps/details?id=com.suvidriel.meowface) data.
3+
*/
4+
15
use godot::{engine::global::Error, prelude::*};
26
use std::net::{IpAddr, Ipv4Addr};
37

0 commit comments

Comments
 (0)