code:
use std::collections::HashSet;
use std::io::BufRead;
use crate::solution::Solution;

type Map = HashSet<(i32, i32)>;

pub fn solve(input: impl BufRead) -> Solution<usize> {
    let mut sol = Solution::new();

    let mut map: Map = HashSet::new();
    let mut folds = vec![];

    for line in input.lines() {
        let line = line.unwrap();

        if let Some((x, y)) = line.split_once(',') {
            let x = x.parse().unwrap();
            let y = y.parse().unwrap();
            map.insert((x, y));
        } else if let Some((along, num)) = line.split_once('=') {
            let along = along.chars().nth(11).unwrap();
            let num: i32 = num.parse().unwrap();
            folds.push((along, num));
        }
    }

    for (dir, num) in folds {
        map = map.into_iter()
            .map(|(x, y)| {
                match dir {
                    'x' => {
                        if x > num {
                            let diff = x - num;
                            (num - diff, y)
                        } else {
                            (x, y)
                        }
                    },
                    'y' => {
                        if y > num {
                            let diff = y - num;
                            (x, num - diff)
                        } else {
                            (x, y)
                        }
                    },
                    _ => unreachable!()
                }
            })
            .collect::<HashSet<_>>();

        if sol.r1.is_none() { sol.ve_1(map.len()) }
    }

    print_map(&map);

    sol
}

fn map_bounds(map: &Map) -> (i32, i32) {
    map.iter().fold((0, 0), |(max_x, max_y), (x, y)| (max_x.max(*x), max_y.max(*y)))
}

fn print_map(map: &Map) {
    let (max_x, max_y) = map_bounds(&map);
    for y in 0..=max_y {
        for x in 0..=max_x {
            match map.get(&(x, y)) {
                Some(_) => print!("#"),
                None => print!(".")
            }
        }
        println!("");
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Cursor;
    use indoc::indoc;

    #[test]
    fn part1() {
        let example = indoc! { "
            6,10
            0,14
            9,10
            0,3
            10,4
            4,11
            6,0
            6,12
            4,1
            0,13
            10,12
            3,4
            3,0
            8,4
            1,10
            2,14
            8,10
            9,0

            fold along y=7
            fold along x=5
        " };

        let sol = solve(Cursor::new(example));

        assert_eq!(sol.r1, Some(17));
    }
}


code:
use std::io::BufRead;
use crate::solution::Solution;
use std::collections::HashMap;

fn step(input: Vec<i64>, next_index: &[[usize; 2]]) -> Vec<i64> {
    let mut output = input.iter().map(|_| 0).collect::<Vec<_>>();

    for (i, n) in input.into_iter().enumerate() {
        let indices = next_index[i];
        output[indices[0]] += n;
        output[indices[1]] += n;
    }

    output
}

fn letter_count(pair_count: &[i64], insertion_rules: &[(String, char)]) -> HashMap<char, i64> {
    let mut count = HashMap::new();

    for (i, pair) in pair_count.iter().enumerate() {
        for c in insertion_rules[i].0.chars() {
            *count.entry(c).or_insert(0) += pair;
        }
    }

    for (_, v) in count.iter_mut() {
        let n = *v as f64 / 2.0;
        *v = n.ceil() as i64;
    }

    count
}

pub fn solve(input: impl BufRead) -> Solution<i64> {
    let mut sol = Solution::new();

    let mut lines = input.lines().map(|l| l.unwrap());

    let template = lines.next().unwrap().chars().collect::<Vec<_>>();
    lines.next().unwrap();

    let insertion_rules = lines
        .map(|l| {
            let (adj, ins) = l.split_once(" -> ").unwrap();
            (adj.to_owned(), ins.chars().next().unwrap())
        })
        .collect::<Vec<_>>();
    let mut pair_count = insertion_rules.iter().map(|_| 0).collect::<Vec<_>>();

    for pair in template.windows(2) {
        let pair = pair.iter().collect::<String>();
        let idx = insertion_rules.iter().position(|(adj, _)| *adj == pair).unwrap();
        pair_count[idx] += 1;
    }

    let next_index = insertion_rules.iter()
        .map(|(adj, ins)| {
            let mut chars = adj.chars();

            let first_half  = [chars.next().unwrap(), *ins].iter().collect::<String>();
            let second_half = [*ins, chars.next().unwrap()].iter().collect::<String>();

            let first_idx  = insertion_rules.iter().position(|(adj, _)| *adj == first_half).unwrap();
            let second_idx = insertion_rules.iter().position(|(adj, _)| *adj == second_half).unwrap();

            [first_idx, second_idx]
        })
        .collect::<Vec<_>>();

    for _ in 1..=10 {
        pair_count = step(pair_count, &next_index);
    }

    let count = letter_count(&pair_count, &insertion_rules);

    let (min, max) = count.iter()
        .map(|(_, v)| v)
        .fold((i64::MAX, 0), |(min, max), &n| (min.min(n), max.max(n)));

    sol.ve_1(max - min);

    for _ in 11..=40 {
        pair_count = step(pair_count, &next_index);
    }

    let count = letter_count(&pair_count, &insertion_rules);

    let (min, max) = count.iter()
        .map(|(_, v)| v)
        .fold((i64::MAX, 0), |(min, max), &n| (min.min(n), max.max(n)));

    sol.ve_2(max - min);

    sol
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Cursor;
    use indoc::indoc;

    #[test]
    fn both() {
        let example = indoc! { "
            NNCB

            CH -> B
            HH -> N
            CB -> H
            NH -> C
            HB -> C
            HC -> B
            HN -> C
            NN -> C
            BH -> H
            NC -> B
            NB -> B
            BN -> B
            BB -> N
            BC -> B
            CC -> N
            CN -> C
        " };

        let sol = solve(Cursor::new(example));

        assert_eq!(sol.r1, Some(1588));
        assert_eq!(sol.r2, Some(2188189693529));
    }
}

repo_name: nixx/advent

license: unknown


code:
use ansi_term::Style;
use std::cmp::Reverse;
use std::collections::BinaryHeap;
use std::io::BufRead;
use crate::solution::Solution;

fn print_path(map: &[i32], path: &[(usize, usize)], size: usize) {
    for y in 0..size {
        for x in 0..size {
            let n = map[y * size + x];
            if path.contains(&(x, y)) {
                print!("{}", Style::new().bold().paint(format!("{}", n)));
            } else {
                print!("{}", n);
            }
        }
        println!("");
    }
}

struct ExpandedMap<'a> {
    base: &'a [i32],
    size: usize
}

impl<'a> ExpandedMap<'a> {
    fn index(&self, pos: (usize, usize)) -> i32 {
        let (x, y) = pos;

        let x_pow = (x / self.size) as i32;
        let y_pow = (y / self.size) as i32;

        let real_x = x % self.size;
        let real_y = y % self.size;

        let n = self.base[real_y * self.size + real_x] + x_pow + y_pow;

        match n % 9 {
            0 => 9,
            v => v
        }
    }

    fn print_path(&self, path: &[(usize, usize)]) {
        for y in 0..(self.size*5) {
            for x in 0..(self.size*5) {
                let n = self.index((x, y));
                if path.contains(&(x, y)) {
                    print!("{}", Style::new().bold().paint(format!("{}", n)));
                } else {
                    print!("{}", n);
                }
            }
            println!("");
        }
    }
}

pub fn solve(input: impl BufRead) -> Solution<i32> {
    let mut sol = Solution::new();

    let mut size = 0;
    let map = input.lines()
        .map(|l| l.unwrap())
        .map(|l| { size = l.len(); l })
        .flat_map(|row| row.bytes()
            .map(|b| b - b'0')
            .map(|n| n as i32)
            .collect::<Vec<_>>()
        )
        .collect::<Vec<_>>();
    let mut visited = vec![false; size * size];

    let mut heap = BinaryHeap::new();
    let mut best_path: Option<Vec<(usize, usize)>> = None;
    let mut best_path_score = i32::MAX;
    heap.push((Reverse(0), vec![(0, 0)]));

    while heap.peek().map(|(score, _)| score.0).unwrap_or(i32::MAX) < best_path_score {
        let work = heap.pop().unwrap();

        let (cur_x, cur_y) = work.1.last().unwrap();

        if visited[cur_y * size + cur_x] { continue }
        visited[cur_y * size + cur_x] = true;

        for (inc_x, inc_y) in [(0, 1), (1, 0), (-1, 0), (0, -1)] {
            let x = (*cur_x as i32 + inc_x) as usize;
            let y = (*cur_y as i32 + inc_y) as usize;

            if x >= size || y >= size { continue }

            let next_score = work.0.0 + map[y * size + x];
            let mut full_path = work.1.clone();
            full_path.push((x, y));

            if x == size - 1 && y == size - 1 {
                if next_score < best_path_score {
                    best_path = Some(full_path);
                    best_path_score = next_score;
                }
            } else {
                heap.push((Reverse(next_score), full_path));
            }
        }
    }

    println!("{:?}", best_path);
    println!("{:?}", best_path_score);
    //println!("{:?}", heap);

    let best_path = best_path.unwrap();

    print_path(&map, &best_path, size);

    sol.ve_1(best_path_score);

    let expanded = ExpandedMap{ base: &map, size };
    let mut visited = vec![false; size * size * 25];

    let mut heap = BinaryHeap::new();
    let mut best_path: Option<Vec<(usize, usize)>> = None;
    let mut best_path_score = i32::MAX;
    heap.push((Reverse(0), vec![(0, 0)]));

    let target = size * 5 - 1;

    println!("target? {}", target);

    while heap.peek().map(|(score, _)| score.0).unwrap_or(i32::MAX) < best_path_score {
        let work = heap.pop().unwrap();

        let (cur_x, cur_y) = work.1.last().unwrap();

        if visited[cur_y * size * 5 + cur_x] { continue }
        visited[cur_y * size * 5 + cur_x] = true;

        for (inc_x, inc_y) in [(0, 1), (1, 0), (-1, 0), (0, -1)] {
            let x = (*cur_x as i32 + inc_x) as usize;
            let y = (*cur_y as i32 + inc_y) as usize;

            if x >= size * 5 || y >= size * 5 { continue }

            let next_score = work.0.0 + expanded.index((x, y));
            let mut full_path = work.1.clone();
            full_path.push((x, y));

            if x == target && y == target {
                if next_score < best_path_score {
                    best_path = Some(full_path);
                    best_path_score = next_score;
                }
            } else {
                heap.push((Reverse(next_score), full_path));
            }
        }
    }
    sol.ve_2(best_path_score);

    expanded.print_path(&best_path.unwrap());

    sol
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Cursor;
    use indoc::indoc;

    #[test]
    fn both() {
        let example = indoc! { "
            1163751742
            1381373672
            2136511328
            3694931569
            7463417111
            1319128137
            1359912421
            3125421639
            1293138521
            2311944581
        " };

        let sol = solve(Cursor::new(example));

        assert_eq!(sol.r1, Some(40));
        assert_eq!(sol.r2, Some(315));
    }
}


code:
use std::io::Read;
use crate::solution::Solution;

#[derive(Debug, PartialEq)]
enum Packet {
    Literal(i64, i64),
    Operator(i64, i64, Vec<Packet>)
}

fn hex_to_bitstring(hex: &str) -> String {
    hex.chars()
        .map(|c| match c {
            '0' => "0000",
            '1' => "0001",
            '2' => "0010",
            '3' => "0011",
            '4' => "0100",
            '5' => "0101",
            '6' => "0110",
            '7' => "0111",
            '8' => "1000",
            '9' => "1001",
            'A' => "1010",
            'B' => "1011",
            'C' => "1100",
            'D' => "1101",
            'E' => "1110",
            'F' => "1111",
            _ => unreachable!("not a valid hex string")
        })
        .collect::<String>()
}

fn parse_packet(input: &str) -> (usize, Packet) {
    let p_version = i64::from_str_radix(&input[..3], 2).unwrap();
    let p_type = i64::from_str_radix(&input[3..6], 2).unwrap();

    if p_type == 4 {
        let mut offset = 6;
        let mut bits = String::new();
        loop {
            bits.push_str(&input[offset+1..offset+5]);
            if &input[offset..offset+1] != "1" { break }
            offset += 5;
        }
        let value = i64::from_str_radix(&bits, 2).unwrap();
        return (offset + 5, Packet::Literal(p_version, value))
    }

    // else - it's an operator

    if &input[6..7] == "0" {
        let length = usize::from_str_radix(&input[7..22], 2).unwrap();
        let mut sub_packets = vec![];

        let mut offset = 0;
        while offset < length {
            let res = parse_packet(&input[(22+offset)..]);
            offset += res.0;
            sub_packets.push(res.1);
        }
        (22 + offset, Packet::Operator(p_version, p_type, sub_packets))
    } else {
        let sub_no = usize::from_str_radix(&input[7..18], 2).unwrap();
        let mut sub_packets = vec![];

        let mut offset = 0;
        for _ in 0..sub_no {
            let res = parse_packet(&input[(18+offset)..]);
            offset += res.0;
            sub_packets.push(res.1);
        }
        (18 + offset, Packet::Operator(p_version, p_type, sub_packets))
    }
}

fn acc_version(packet: &Packet) -> i64 {
    match packet {
        Packet::Literal(v, _) => *v,
        Packet::Operator(v, _, sub) => *v + sub.iter().map(|p| acc_version(p)).sum::<i64>()
    }
}

fn value_of(packet: &Packet) -> i64 {
    match packet {
        Packet::Literal(_, v) => *v,
        Packet::Operator(_, 0, sub) => sub.iter().map(|p| value_of(p)).sum(),
        Packet::Operator(_, 1, sub) => sub.iter().map(|p| value_of(p)).product(),
        Packet::Operator(_, 2, sub) => sub.iter().map(|p| value_of(p)).min().unwrap(),
        Packet::Operator(_, 3, sub) => sub.iter().map(|p| value_of(p)).max().unwrap(),
        Packet::Operator(_, 5, sub) => if value_of(&sub[0]) > value_of(&sub[1]) { 1 } else { 0 },
        Packet::Operator(_, 6, sub) => if value_of(&sub[0]) < value_of(&sub[1]) { 1 } else { 0 },
        Packet::Operator(_, 7, sub) => if value_of(&sub[0]) == value_of(&sub[1]) { 1 } else { 0 },
        _ => unreachable!("invalid packet")
    }
}

pub fn solve(mut input: impl Read) -> Solution<i64> {
    let mut sol = Solution::new();

    let mut packet = String::new();
    input.read_to_string(&mut packet).unwrap();
    let packet = parse_packet(&hex_to_bitstring(&packet)).1;

    sol.ve_1(acc_version(&packet));
    sol.ve_2(value_of(&packet));

    sol
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Cursor;

    #[test]
    fn examples() {
        assert_eq!(hex_to_bitstring("D2FE28"), "110100101111111000101000");
        assert_eq!(parse_packet("110100101111111000101000").1, Packet::Literal(6, 2021));

        assert_eq!(parse_packet(&hex_to_bitstring("38006F45291200")).1, Packet::Operator(1, 6, vec![
            Packet::Literal(6, 10),
            Packet::Literal(2, 20)
        ]));
        assert_eq!(parse_packet(&hex_to_bitstring("EE00D40C823060")).1, Packet::Operator(7, 3, vec![
            Packet::Literal(2, 1),
            Packet::Literal(4, 2),
            Packet::Literal(1, 3)
        ]));
    }

    #[test]
    fn part1() {
        assert_eq!(solve(Cursor::new("8A004A801A8002F478")).r1, Some(16));
        assert_eq!(solve(Cursor::new("620080001611562C8802118E34")).r1, Some(12));
        assert_eq!(solve(Cursor::new("C0015000016115A2E0802F182340")).r1, Some(23));
        assert_eq!(solve(Cursor::new("A0016C880162017C3686B18A3D4780")).r1, Some(31));
    }

    #[test]
    fn part2() {
        assert_eq!(solve(Cursor::new("C200B40A82")).r2, Some(3));
        assert_eq!(solve(Cursor::new("04005AC33890")).r2, Some(54));
        assert_eq!(solve(Cursor::new("880086C3E88112")).r2, Some(7));
        assert_eq!(solve(Cursor::new("CE00C43D881120")).r2, Some(9));
        assert_eq!(solve(Cursor::new("D8005AC2A8F0")).r2, Some(1));
        assert_eq!(solve(Cursor::new("F600BC2D8F")).r2, Some(0));
        assert_eq!(solve(Cursor::new("9C005AC2F8F0")).r2, Some(0));
        assert_eq!(solve(Cursor::new("9C0141080250320F1802104A08")).r2, Some(1));
    }
}


code:
use std::ops::RangeInclusive;
use std::io::Read;
use regex::Regex;
use crate::solution::Solution;

#[derive(Debug)]
struct Area {
    x: RangeInclusive<i32>,
    y: RangeInclusive<i32>,
}

impl Area {
    fn new(input: &str) -> Area {
        let re = Regex::new(r"target area: x=([\d-]+)..([\d-]+), y=([\d-]+)..([\d-]+)").unwrap();
        let caps = re.captures(input).unwrap();

        let x_start = (&caps[1]).parse().unwrap();
        let x_end   = (&caps[2]).parse().unwrap();
        let y_start = (&caps[3]).parse().unwrap();
        let y_end   = (&caps[4]).parse().unwrap();

        Area { x: x_start..=x_end, y: y_start..=y_end }
    }

    fn contains(&self, pos: &(i32, i32)) -> bool {
        self.x.contains(&pos.0) && self.y.contains(&pos.1)
    }

    fn passed(&self, pos: &(i32, i32)) -> bool {
        pos.1 < *self.y.end()
    }

    fn overshoot(&self, pos: &(i32, i32)) -> bool {
        pos.0 > *self.x.end()
    }
}

struct TrajectoryIterator {
    x_pos: i32,
    y_pos: i32,
    x_vel: i32,
    y_vel: i32,
}

impl TrajectoryIterator {
    fn new(x_vel: i32, y_vel: i32) -> TrajectoryIterator {
        TrajectoryIterator { x_pos: 0, y_pos: 0, x_vel, y_vel }
    }
}

impl Iterator for TrajectoryIterator {
    type Item = (i32, i32);

    fn next(&mut self) -> Option<(i32, i32)> {
        self.x_pos += self.x_vel;
        self.y_pos += self.y_vel;
        self.x_vel -= self.x_vel.signum();
        self.y_vel -= 1;

        Some((self.x_pos, self.y_pos))
    }
}

#[derive(Debug, PartialEq)]
enum TrajectoryResult {
    Miss, // undershoot or flew straight through
    Hit,
    Overshoot
}

fn hits_area(trj: &mut TrajectoryIterator, area: &Area) -> TrajectoryResult {
    loop {
        let pos = trj.next().unwrap();

        if area.contains(&pos) { return TrajectoryResult::Hit }
        if area.passed(&pos) {
            if area.overshoot(&pos) {
                return TrajectoryResult::Overshoot
            } else {
                return TrajectoryResult::Miss
            }
        }
    }
}

pub fn solve(mut input: impl Read) -> Solution<i32> {
    let mut sol = Solution::new();

    let mut target_area = String::new();
    input.read_to_string(&mut target_area).unwrap();
    let target_area = Area::new(&target_area);

    let mut best = None;
    let mut count = 0;

    for y in (-30)..1000 {
        for x in 0..100 {
            let mut trajectory = TrajectoryIterator::new(x, y);
            let result = hits_area(&mut trajectory, &target_area);

            if result == TrajectoryResult::Hit {
                best = Some((x, y));
                count += 1;
                println!("{:?}", (x, y));
            }

            if result == TrajectoryResult::Overshoot {
                // break
            }
        }
    }

    let best = best.unwrap();
    let trajectory = TrajectoryIterator::new(best.0, best.1);
    sol.ve_1(trajectory.map(|(_, y)| y).take_while(|y| y.is_positive()).max().unwrap());
    sol.ve_2(count);

    sol
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Cursor;

    #[test]
    fn examples() {
        let target_area = Area::new("target area: x=20..30, y=-10..-5");

        assert_eq!(hits_area(&mut TrajectoryIterator::new(7, 2), &target_area), TrajectoryResult::Hit);
        assert_eq!(hits_area(&mut TrajectoryIterator::new(6, 3), &target_area), TrajectoryResult::Hit);
        assert_eq!(hits_area(&mut TrajectoryIterator::new(9, 0), &target_area), TrajectoryResult::Hit);
        assert_eq!(hits_area(&mut TrajectoryIterator::new(17, -4), &target_area), TrajectoryResult::Overshoot);
    }

    #[test]
    fn both() {
        let sol = solve(Cursor::new("target area: x=20..30, y=-10..-5"));

        assert_eq!(sol.r1, Some(45));
        assert_eq!(sol.r2, Some(112));
    }
}


code:
---
BasedOnStyle: LLVM
ColumnLimit: 200
UseTab: Never
TabWidth: 2
---
Language: Cpp
DerivePointerAlignment: false
PointerAlignment: Left
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
IndentCaseLabels: false
AllowShortBlocksOnASingleLine: Always
AlignOperands: true
AlignTrailingComments: true
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BreakConstructorInitializersBeforeComma: true
AlwaysBreakAfterReturnType: None
AlwaysBreakAfterDefinitionReturnType: None
AllowShortFunctionsOnASingleLine: All
Cpp11BracedListStyle: true
NamespaceIndentation: None
BinPackArguments: true
BinPackParameters: true
SortIncludes: CaseInsensitive
AccessModifierOffset: -2
ConstructorInitializerIndentWidth: 0
PackConstructorInitializers: Never

repo_name: Antidote/openrpgeditor

path: .clang-format

license: mit


code:
extern/**
build-*/**
cmake-*/**

path: .clang-format-ignore


code:
---
Checks: >
  *,
  -android-*,
  -abseil-*,
  -altera-*,
  -darwin-*,
  -fuchsia-*,
  -google-*,
  -objc-*,
  -zircon-*,
  -llvm*,
  -hicpp*,
  -cppcoreguidelines-non-private-member-variables-in-classes,
  -cppcoreguidelines-pro-bounds-pointer-arithmetic,
  -cppcoreguidelines-macro-usage,
  -cppcoreguidelines-pro-type-vararg,
  -cppcoreguidelines-avoid-magic-numbers,
  -cppcoreguidelines-pro-bounds-array-to-pointer-decay,
  -readability-magic-numbers,
  -readability-function-cognitive-complexity,
  -misc-non-private-member-variables-in-classes,
  -clang-analyzer-optin.cplusplus.UninitializedObject,
  -misc-static-assert,
  -modernize-use-trailing-return-type,
  -modernize-use-nullptr,
  -bugprone-easily-swappable-parameters,
  -bugprone-exception-escape,
  -cert-env33-c,
  -cert-err58-cpp

# -modernize-use-nullptr is deactivated for x86
# See: https://github.com/llvm/llvm-project/issues/53778

WarningsAsErrors: '*'
HeaderFilterRegex: ''
FormatStyle: none

CheckOptions:
  - { key: readability-identifier-naming.NamespaceCase,              value: CamelCase }
  - { key: readability-identifier-naming.ClassCase,                  value: CamelCase }
  - { key: readability-identifier-naming.PrivateMemberPrefix,        value: m_ }
  - { key: readability-identifier-naming.StructCase,                 value: CamelCase }
  - { key: readability-identifier-naming.ClassMethodCase,            value: CamelCase }
  - { key: readability-identifier-naming.ClassMemberCase,            value: CamelCase }
  - { key: readability-identifier-naming.FunctionCase,               value: CamelCase }
  - { key: readability-identifier-naming.VariableCase,               value: CamelCase }
  - { key: readability-identifier-naming.GlobalConstantCase,         value: UPPER_CASE }
  - { key: readability-identifier-length.MinimumVariableNameLength,  value: 2 }
  - { key: readability-identifier-length.MinimumParameterNameLength, value: 2 }
  - { key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors, value: '1' }
  - { key: misc-include-cleaner.IgnoreHeaders, value: "SDL2/SDL\.h" }

path: .clang-tidy


code:
# Application build output
build/
distribution/
**/share/

# Created by CPack when executing tests.
Testing/

# Generated by the profiler on debug.
profile.json
*-profile.json

# Created by running the application.
*.log

# This file is template generated
**/ProjectInfo.cpp

# User defined CMake preset file.
CMakeUserPresets.json
CMakePresets.json

# CLion configuration
.idea/
cmake-*
out

# Visual Studio Code
.vscode/
*.code-workspace
.history/

# Visual Studio
.vs/
_deps/
CMakeFiles/

*.vcxproj
*.filters
*.sln
*.user
*.gmo

CMakeCache.txt
CPackConfig.cmake
CPackSourceConfig.cmake
cmake_install.cmake

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/

[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/

path: .gitignore


code:
[main]
host = https://app.transifex.com

[o:openrpgeditor:p:openrpgeditor:r:openrpgeditorpot]
file_filter            = i18n/locales/po/<lang>.po
source_file            = i18n/locales/openrpgeditor.pot
type                   = PO
minimum_perc           = 0
resource_name          = openrpgeditor.pot
replace_edited_strings = false
keep_translations      = false

path: .tx/config


code:
cmake_minimum_required(VERSION 3.22)

include(cmake/AppleBuild.cmake)

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_C_STANDARD 23)

add_definitions(-DJSON_DIAGNOSTICS=1)
set(NAME "OpenRPGEditor")

project(
        ${NAME}
        DESCRIPTION "A drop-in replacement for RPG Maker MV."
        VERSION 0.0.0
        LANGUAGES CXX C)

# We only need OBJC on macOS
if (APPLE)
    enable_language(OBJC)
    enable_language(OBJCXX)
endif()

set(GETTEXT_DOMAIN openrpgeditor)
set(GETTEXT_OUTPUT_DIR locales)

set(PROJECT_COMPANY_NAME "OpenRPGEditor Team")
set(PROJECT_COMPANY_NAMESPACE "io.gitgud.antidote.openrgpeditor") # Reverse
# domain name
# notation

#add_compile_options(-fsanitize=address)
#add_link_options(-fsanitize=address)

include(cmake/StandardProjectSettings.cmake)
include(GNUInstallDirs)

# Link this "library" to use the warnings specified in CompilerWarnings.cmake.
include(cmake/CompilerWarnings.cmake)

# enable_testing()

add_subdirectory(packaging)
add_subdirectory(vendor)
add_subdirectory(src)
add_subdirectory(extern/angelscript/angelscript/projects/cmake)
add_subdirectory(extern/angelscript_addon_cmake)
add_subdirectory(extern/inih)
add_subdirectory(i18n)

target_link_libraries(librpgm PRIVATE
        moloader::moloader
)
target_include_directories(librpgm PUBLIC
        i18n
        ${moloader_SOURCE_DIR}/include
)
target_compile_definitions(librpgm PUBLIC GETTEXT_DOMAIN="${GETTEXT_DOMAIN}" GETTEXT_OUTPUT_DIR="${GETTEXT_OUTPUT_DIR}")

target_link_libraries(librpgmeventcmds PRIVATE
        moloader::moloader
)
target_compile_definitions(librpgmeventcmds PUBLIC GETTEXT_DOMAIN="${GETTEXT_DOMAIN}" GETTEXT_OUTPUT_DIR="${GETTEXT_OUTPUT_DIR}")

target_include_directories(librpgmeventcmds PUBLIC
        i18n
        ${moloader_SOURCE_DIR}/include
)

target_link_libraries(librpgmmovementroutecmds PRIVATE
        moloader::moloader
)
target_include_directories(librpgmmovementroutecmds PUBLIC
        i18n
        ${moloader_SOURCE_DIR}/include
)
target_compile_definitions(librpgmmovementroutecmds PUBLIC GETTEXT_DOMAIN="${GETTEXT_DOMAIN}" GETTEXT_OUTPUT_DIR="${GETTEXT_OUTPUT_DIR}")


code:
 For the purposes of legal copyright OpenRPGEditor, henceforth ORE, is not in
 any way affiliated with condoned, nor endorsed by Kodakawa Corporation/Yoji Ojima.

 ORE is a community developed editor replacement for RPG Maker MV/MZ and as
 such strongly urges its users to obtain a legal copy of said software before
 using ORE.

 ORE does not ship with the required corescripts necessary to develop a working
 game and those must be obtained from a legal copy of the aforementioned software.

path: DISCLAIMER


Example Plugin

author: Example Author

license: MIT

description: An example plugin to demonstrate how to create a plugin

main-script: main


code:
json@[] nullJsonArray() {
    return { };
}

json@ nullJsonObject() {
    return json();
}

class TestChild {
    TestChild() {
    }
    TestChild(const json&in j) {
        m_child = bool(j is null ? false : j["child"] is null ? false : j["child"]);
    }
    json opImplConv() {
        json@ j = json();
        j["child"] = m_child;
        return j;
    }

    void setChild(bool child) {
        m_child = child;
    }
    bool m_child = false;
};

class TestJSON {
    TestJSON() {
    }
    TestJSON(const json&in j) {
        m_child = j["child"] ;
        m_test = double(j["test"]);
        m_isOpen = bool(j["isOpen"]);
        json testArray = j["testArray"];
        for (uint i = 0; i < testArray.getSize(); ++i) {
            m_testArray.insertAt(i, testArray[i]);
        }
    }

    json opImplConv() {
        json@ j = json();

        j["child"] = m_child;
        j["test2"] = nullJsonObject();
        j["test"] = m_test;
        j["isOpen"] = m_isOpen;
        j["testArray"] = nullJsonArray();
        foreach (TestChild ch : m_testArray) {
            j["testArray"].push_back(ch);
        }

        return j;
    }

    private TestChild m_child;
    private double m_test = 1.0;
    private bool m_isOpen = false;
    array<TestChild> m_testArray;
}

void initialize() {
    return;
    // print(LogLevel::Info, "Initialize");
    // json@ j = jsonParseFile("test.json");

    // TestJSON test = j is null ? TestJSON() : j;
    // json@ js = test;
    // print(LogLevel::Info, "\n" + js.dump(4));
    // jsonWriteFile(js, "test.json");
}

bool didDraw = false;
void draw() {
    if (!didDraw) {
        print(LogLevel::Info, "Draw");
        didDraw = true;
    }
}

void shutdown() {
    print(LogLevel::Info, "Shutdown");

}


code:
enum jsonType {
	OBJECT_VALUE,
	ARRAY_VALUE,
	BOOLEAN_VALUE,
	STRING_VALUE,
	NUMBER_VALUE,
	REAL_VALUE,
	NULL_VALUE
}
enum LogLevel {
	Message,
	Info,
	Warning,
	Error,
	Fatal
}
enum ToolbarCategory {
	File,
	UI,
	MapOperation
}
class array<T>{
	T& opIndex(uint index);
	const T& opIndex(uint index) const;
	uint opForBegin() const;
	bool opForEnd(uint) const;
	uint opForNext(uint) const;
	const T& opForValue0(uint index) const;
	uint opForValue1(uint index) const;
	T[]& opAssign(const T[]&in);
	void insertAt(uint index, const T&in value);
	void insertAt(uint index, const T[]&inout arr);
	void insertLast(const T&in value);
	void removeAt(uint index);
	void removeLast();
	void removeRange(uint start, uint count);
	uint length() const;
	void reserve(uint length);
	void resize(uint length);
	void sortAsc();
	void sortAsc(uint startAt, uint count);
	void sortDesc();
	void sortDesc(uint startAt, uint count);
	void reverse();
	int find(const T&in value) const;
	int find(uint startAt, const T&in value) const;
	int findByRef(const T&in value) const;
	int findByRef(uint startAt, const T&in value) const;
	bool opEquals(const T[]&in) const;
	bool isEmpty() const;
	void sort(T[]::less&in, uint startAt = 0, uint count = uint(-1));
	funcdef bool less(const T&in, const T&in);
}
class string{
	~string();
	string();
	string(const string&in);
	string& opAssign(const string&in);
	string& opAddAssign(const string&in);
	bool opEquals(const string&in) const;
	int opCmp(const string&in) const;
	string opAdd(const string&in) const;
	uint length() const;
	void resize(uint);
	bool isEmpty() const;
	uint8& opIndex(uint);
	const uint8& opIndex(uint) const;
	string& opAssign(double);
	string& opAddAssign(double);
	string opAdd(double) const;
	string opAdd_r(double) const;
	string& opAssign(float);
	string& opAddAssign(float);
	string opAdd(float) const;
	string opAdd_r(float) const;
	string& opAssign(int64);
	string& opAddAssign(int64);
	string opAdd(int64) const;
	string opAdd_r(int64) const;
	string& opAssign(uint64);
	string& opAddAssign(uint64);
	string opAdd(uint64) const;
	string opAdd_r(uint64) const;
	string& opAssign(bool);
	string& opAddAssign(bool);
	string opAdd(bool) const;
	string opAdd_r(bool) const;
	string substr(uint start = 0, int count = -1) const;
	int findFirst(const string&in, uint start = 0) const;
	int findFirstOf(const string&in, uint start = 0) const;
	int findFirstNotOf(const string&in, uint start = 0) const;
	int findLast(const string&in, int start = -1) const;
	int findLastOf(const string&in, int start = -1) const;
	int findLastNotOf(const string&in, int start = -1) const;
	void insert(uint pos, const string&in other);
	void erase(uint pos, int count = -1);
	int regexFind(const string&in regex, uint start = 0, uint&out lengthOfMatch = void) const;
	string[]@ split(const string&in) const;
}
class ref{
	~ref();
	ref();
	ref(const ref&in);
	ref(const ?&in);
	void opCast(?&out);
	ref& opHndlAssign(const ref&in);
	ref& opHndlAssign(const ?&in);
	bool opEquals(const ref&in) const;
	bool opEquals(const ?&in) const;
}
class weakref<T>{
	~weakref();
	weakref(int&in);
	weakref(int&in, T@);
	T@ opImplCast();
	T@ get() const;
	weakref<T>& opHndlAssign(const weakref<T>&in);
	weakref<T>& opAssign(const weakref<T>&in);
	bool opEquals(const weakref<T>&in) const;
	weakref<T>& opHndlAssign(T@);
	bool opEquals(const T@) const;
}
class const_weakref<T>{
	~const_weakref();
	const_weakref(int&in);
	const_weakref(int&in, const T@);
	const T@ opImplCast() const;
	const T@ get() const;
	const_weakref<T>& opHndlAssign(const const_weakref<T>&in);
	const_weakref<T>& opAssign(const const_weakref<T>&in);
	bool opEquals(const const_weakref<T>&in) const;
	const_weakref<T>& opHndlAssign(const T@);
	bool opEquals(const T@) const;
	const_weakref<T>& opHndlAssign(const weakref<T>&in);
	bool opEquals(const weakref<T>&in) const;
}
class complex{
	complex();
	complex(const complex&in);
	complex(float);
	complex(float, float);
	complex& opAddAssign(const complex&in);
	complex& opSubAssign(const complex&in);
	complex& opMulAssign(const complex&in);
	complex& opDivAssign(const complex&in);
	bool opEquals(const complex&in) const;
	complex opAdd(const complex&in) const;
	complex opSub(const complex&in) const;
	complex opMul(const complex&in) const;
	complex opDiv(const complex&in) const;
	float abs() const;
	complex get_ri() const;
	complex get_ir() const;
	void set_ri(const complex&in);
	void set_ir(const complex&in);
	float r;
	float i;
}
class dictionaryValue{
	~dictionaryValue();
	dictionaryValue();
	dictionaryValue& opAssign(const dictionaryValue&in);
	dictionaryValue& opHndlAssign(const ?&in);
	dictionaryValue& opHndlAssign(const dictionaryValue&in);
	dictionaryValue& opAssign(const ?&in);
	dictionaryValue& opAssign(double);
	dictionaryValue& opAssign(int64);
	void opCast(?&out);
	void opConv(?&out);
	int64 opConv();
	double opConv();
}
class dictionary{
	dictionary& opAssign(const dictionary&in);
	void set(const string&in, const ?&in);
	bool get(const string&in, ?&out) const;
	void set(const string&in, const int64&in);
	bool get(const string&in, int64&out) const;
	void set(const string&in, const double&in);
	bool get(const string&in, double&out) const;
	bool exists(const string&in) const;
	bool isEmpty() const;
	uint getSize() const;
	bool delete(const string&in);
	void deleteAll();
	string[]@ getKeys() const;
	dictionaryValue& opIndex(const string&in);
	const dictionaryValue& opIndex(const string&in) const;
	dictionaryIter@ opForBegin() const;
	bool opForEnd(dictionaryIter@) const;
	dictionaryIter@ opForNext(dictionaryIter@) const;
	const dictionaryValue& opForValue0(dictionaryIter@) const;
	const string& opForValue1(dictionaryIter@) const;
}
class dictionaryIter{
}
class json{
	json& opAssign(bool);
	json& opAssign(int64);
	json& opAssign(double);
	json& opAssign(const string&in);
	json& opAssign(const json@[]&in);
	json& opAssign(const json&in);
	void set(const string&in, const bool&in);
	bool get(const string&in, bool&out) const;
	void set(const string&in, const int64&in);
	bool get(const string&in, int64&out) const;
	void set(const string&in, const double&in);
	bool get(const string&in, double&out) const;
	void set(const string&in, const string&in);
	bool get(const string&in, string&out) const;
	void set(const string&in, const json@[]&in);
	bool get(const string&in, json@[]&out) const;
	bool exists(const string&in) const;
	bool isEmpty() const;
	uint getSize() const;
	void clear();
	jsonType getType();
	json& opIndex(const string&in);
	const json& opIndex(const string&in) const;
	json& opIndex(uint);
	const json& opIndex(uint) const;
	void push_back(json&in) const;
	bool opConv();
	string opConv();
	int opConv();
	double opConv();
	json@[]& opConv();
	string dump(int depth = -1);
}
class any{
	any& opAssign(any&in);
	void store(?&in);
	void store(const int64&in);
	void store(const double&in);
	bool retrieve(?&out) const;
	bool retrieve(int64&out) const;
	bool retrieve(double&out) const;
}
class ImVec2{
	~ImVec2();
	ImVec2();
	ImVec2(float, float);
	ImVec2& opAssign(const ImVec2&in);
	float& opIndex(uint index);
	ImVec2 opMul(const float);
	ImVec2 opMul(const ImVec2&in);
	ImVec2 opDiv(const float);
	ImVec2 opAdd(const ImVec2&in);
	ImVec2 opSub(const ImVec2&in);
	ImVec2 opDiv(const ImVec2&in);
	ImVec2 opNeg();
	ImVec2& opMulAssign(const float);
	ImVec2& opDivAssign(const float);
	ImVec2& opAddAssign(const ImVec2&in);
	ImVec2& opSubAssign(const ImVec2&in);
	ImVec2& opMulAssign(const ImVec2&in);
	ImVec2& opDivAssign(const ImVec2&in);
	ImVec2 opEquals(const ImVec2&in);
	float x;
	float y;
}
class ImVec4{
	~ImVec4();
	ImVec4();
	ImVec4(float, float, float, float);
	ImVec4& opAssign(const ImVec4&in);
	ImVec4 opMul(const ImVec4&in);
	ImVec4 opSub(const ImVec4&in);
	ImVec4 opEquals(const ImVec4&in);
	float x;
	float y;
	float z;
	float w;
}
uint scan(const string&in str, ?&out...);
string format(const string&in fmt, const ?&in...);
string formatInt(int64 val, const string&in options = "", uint width = 0);
string formatUInt(uint64 val, const string&in options = "", uint width = 0);
string formatFloat(double val, const string&in options = "", uint width = 0, uint precision = 0);
int64 parseInt(const string&in, uint base = 10, uint&out byteCount = 0);
uint64 parseUInt(const string&in, uint base = 10, uint&out byteCount = 0);
double parseFloat(const string&in, uint&out byteCount = 0);
string join(const string[]&in, const string&in);
float fpFromIEEE(uint);
uint fpToIEEE(float);
double fpFromIEEE(uint64);
uint64 fpToIEEE(double);
bool closeTo(float, float, float = 0.00001f);
bool closeTo(double, double, double = 0.0000000001);
float cos(float);
float sin(float);
float tan(float);
float acos(float);
float asin(float);
float atan(float);
float atan2(float, float);
float cosh(float);
float sinh(float);
float tanh(float);
float log(float);
float log10(float);
float pow(float, float);
float sqrt(float);
float ceil(float);
float abs(float);
float floor(float);
float fraction(float);
json@ jsonParseFile(const string&in);
json@ jsonParse(const string&in);
bool jsonWriteFile(const json&in json, const string&in);
bool jsonWrite(const json&in json, string&out);
void print(LogLevel level, const string&in);
void addToolbarButton(const string&in, ToolbarCategory category, ToolBarButtonClicked@const cb);
namespace ImGui { string GetVersion(); }
namespace ImGui { bool Begin(const string&in id, bool show_close_button = false, bool&out p_open = false, int window_flags = 0); }
namespace ImGui { void End(); }
namespace ImGui { bool BeginChild(const string&in id, const ImVec2&in size = ImVec2(), int child_flags = 0, int window_flags = 0); }
namespace ImGui { bool BeginChild(uint id, const ImVec2&in size = ImVec2(), int child_flags = 0, int window_flags = 0); }
namespace ImGui { void EndChild(); }
namespace ImGui { bool IsWindowAppearing(); }
namespace ImGui { bool IsWindowCollapsed(); }
namespace ImGui { bool IsWindowFocused(int flags = 0); }
namespace ImGui { bool IsWindowHovered(int flags = 0); }
namespace ImGui { float GetDpiScale(); }
namespace ImGui { void SetNextWindowPos(const ImVec2&in pos, int cond = 0, const ImVec2&in pivot = ImVec2()); }
namespace ImGui { void SetNextWindowSize(const ImVec2&in size, int cond = 0); }
namespace ImGui { void SetNextWindowSizeConstraints(const ImVec2&in size_min, const ImVec2&in size_max, int cond = 0); }
namespace ImGui { void SetNextWindowContentSize(const ImVec2&in size, int cond = 0); }
namespace ImGui { void SetNextWindowCollapsed(bool collapsed, int cond = 0); }
namespace ImGui { void SetNextWindowFocus(); }
namespace ImGui { void SetNextWindowScroll(const ImVec2&in scroll); }
namespace ImGui { void SetNextWindowBgAlpha(float alpha); }
namespace ImGui { void SetNextWindowViewport(uint viewport_id); }
namespace ImGui { void SetWindowPos(const ImVec2&in pos, int cond = 0); }
namespace ImGui { void SetWindowSize(const ImVec2&in size, int cond = 0); }
namespace ImGui { void SetWindowCollapsed(bool collapsed, int cond = 0); }
namespace ImGui { void SetWindowFocus(); }
namespace ImGui { void SetWindowFontScale(float scale); }
namespace ImGui { void SetWindowPos(const string&in name, const ImVec2&in pos, int cond = 0); }
namespace ImGui { void SetWindowSize(const string&in name, const ImVec2&in size, int cond = 0); }
namespace ImGui { void SetWindowCollapsed(const string&in name, bool collapsed, int cond = 0); }
namespace ImGui { void SetWindowFocus(const string&in name); }
namespace ImGui { float GetScrollX(); }
namespace ImGui { float GetScrollY(); }
namespace ImGui { void SetScrollX(float scroll_x); }
namespace ImGui { void SetScrollY(float scroll_y); }
namespace ImGui { float GetScrollMaxX(); }
namespace ImGui { float GetScrollMaxY(); }
namespace ImGui { void SetScrollHereX(float center_x_ratio = 0.5f); }
namespace ImGui { void SetScrollHereY(float center_y_ratio = 0.5f); }
namespace ImGui { void SetScrollFromPosX(float local_x, float center_x_ratio = 0.5f); }
namespace ImGui { void SetScrollFromPosY(float local_y, float center_y_ratio = 0.5f); }
namespace ImGui { void Text(const string&in); }
namespace ImGui { double GetTime(); }
namespace ImGui { int GetFrameCount(); }
typedef uint ImGuiID;
typedef int8 ImS8;
typedef uint8 ImU8;
typedef int16 ImS16;
typedef uint16 ImU16;
typedef int ImS32;
typedef uint ImU32;
typedef int64 ImS64;
typedef uint64 ImU64;
typedef int ImGuiCol;
typedef int ImGuiCond;
typedef int ImGuiDataType;
typedef int ImGuiMouseButton;
typedef int ImGuiMouseCursor;
typedef int ImGuiStyleVar;
typedef int ImGuiTableBgTarget;
typedef int ImDrawFlags;
typedef int ImDrawListFlags;
typedef int ImFontAtlasFlags;
typedef int ImGuiBackendFlags;
typedef int ImGuiChildFlags;
typedef int ImGuiColorEditFlags;
typedef int ImGuiConfigFlags;
typedef int ImGuiComboFlags;
typedef int ImGuiDockNodeFlags;
typedef int ImGuiDragDropFlags;
typedef int ImGuiFocusedFlags;
typedef int ImGuiHoveredFlags;
typedef int ImGuiInputFlags;
typedef int ImGuiInputTextFlags;
typedef int ImGuiItemFlags;
typedef int ImGuiKeyChord;
typedef int ImGuiPopupFlags;
typedef int ImGuiMultiSelectFlags;
typedef int ImGuiSelectableFlags;
typedef int ImGuiSliderFlags;
typedef int ImGuiTabBarFlags;
typedef int ImGuiTabItemFlags;
typedef int ImGuiTableFlags;
typedef int ImGuiTableColumnFlags;
typedef int ImGuiTableRowFlags;
typedef int ImGuiTreeNodeFlags;
typedef int ImGuiViewportFlags;
typedef int ImGuiWindowFlags;
typedef uint64 ImTextureID;
typedef uint ImWchar32;
typedef uint16 ImWchar16;
typedef uint16 ImWchar;
typedef int64 ImGuiSelectionUserData;


code:
# This file needs to be included before calling `project`.
if (APPLE AND "${CMAKE_GENERATOR}" STREQUAL "Xcode")
  # Define apple architecture for Release builds, use default. For an explicit
  # universal executable use `x86_64;arm64`.
  set(CMAKE_OSX_ARCHITECTURES "$(ARCHS_STANDARD)" CACHE INTERNAL "OS X architecture")

  # Support older macOS versions.
  set(CMAKE_OSX_DEPLOYMENT_TARGET 10.15 CACHE STRING "Minimum OS X deployment version")
endif ()


code:
# https://github.com/lefticus/cppbestpractices/blob/master/02-Use_the_Tools_Available.md

function(set_project_warnings project_name)
  option(WARNINGS_AS_ERRORS "Treat compiler warnings as errors" TRUE)
  message(STATUS "Treat compiler warnings as errors")

  set(MSVC_WARNINGS
    /W4 # Baseline reasonable warnings
    /w14242 # 'identifier': conversion from 'type1' to 'type1', possible loss
    # of data
    /w14254 # 'operator': conversion from 'type1:field_bits' to
    # 'type2:field_bits', possible loss of data
    /w14263 # 'function': member function does not override any base class
    # virtual member function
    /w14265 # 'classname': class has virtual functions, but destructor is not
    # virtual instances of this class may not be destructed correctly
    /w14287 # 'operator': unsigned/negative constant mismatch
    /we4289 # nonstandard extension used: 'variable': loop control variable
    # declared in the for-loop is used outside the for-loop scope
    /w14296 # 'operator': expression is always 'boolean_value'
    /w14311 # 'variable': pointer truncation from 'type1' to 'type2'
    /w14545 # expression before comma evaluates to a function which is missing
    # an argument list
    /w14546 # function call before comma missing argument list
    /w14547 # 'operator': operator before comma has no effect; expected
    # operator with side-effect
    /w14549 # 'operator': operator before comma has no effect; did you intend
    # 'operator'?
    /w14555 # expression has no effect; expected expression with side- effect
    /w14619 # pragma warning: there is no warning number 'number'
    /w14640 # Enable warning on thread un-safe static member initialization
    /w14826 # Conversion from 'type1' to 'type_2' is sign-extended. This may
    # cause unexpected runtime behavior.
    /w14905 # wide string literal cast to 'LPSTR'
    /w14906 # string literal cast to 'LPWSTR'
    /w14928 # illegal copy-initialization; more than one user-defined
    # conversion has been implicitly applied
    /permissive- # standards conformance mode for MSVC compiler.
    )

  set(CLANG_WARNINGS
    -Wall
    -Wextra # reasonable and standard
    -Wshadow # warn the user if a variable declaration shadows one from a
    # parent context
    -Wnon-virtual-dtor # warn the user if a class with virtual functions has a
    # non-virtual destructor. This helps catch hard to
    # track down memory errors
    -Wcast-align # warn for potential performance problem casts
    -Wunused # warn on anything being unused
    -Woverloaded-virtual # warn if you overload (not override) a virtual
    # function
    -Wpedantic # warn if non-standard C++ is used
    -Wconversion # warn on type conversions that may lose data
    -Wsign-conversion # warn on sign conversions
    -Wnull-dereference # warn if a null dereference is detected
    -Wformat=2 # warn on security issues around functions that format output
    # (ie printf)
    )

  if (WARNINGS_AS_ERRORS)
    set(CLANG_WARNINGS ${CLANG_WARNINGS} -Werror)
    set(MSVC_WARNINGS ${MSVC_WARNINGS} /WX)
  endif ()

  set(GCC_WARNINGS
    ${CLANG_WARNINGS}
    -Wmisleading-indentation # warn if indentation implies blocks where blocks
    # @todo: Somehow those make problems in some versions of Clang in Windows. So I deactivate them for now.
    # -Wduplicated-branches # warn if if / else branches have duplicated code
    # -Wduplicated-cond # warn if if / else chain has duplicated conditions
    # -Wlogical-op # warn about logical operations being used where bitwise were
    # -Wuseless-cast # warn if you perform a cast to the same type
    )

  if (MSVC)
    set(PROJECT_WARNINGS ${MSVC_WARNINGS})
  elseif (CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
    set(PROJECT_WARNINGS ${CLANG_WARNINGS})
  elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
    set(PROJECT_WARNINGS ${GCC_WARNINGS})
  else ()
    message(AUTHOR_WARNING "No compiler warnings set for '${CMAKE_CXX_COMPILER_ID}' compiler.")
  endif ()

  target_compile_options(${project_name} INTERFACE ${PROJECT_WARNINGS})

endfunction()


code:
function(get_target_sources_with_paths target sources_with_paths)
    get_target_property(sources ${target} SOURCES)
    get_target_property(source_dir ${target} SOURCE_DIR)

    foreach (source ${sources})
        # Check if the source file is a generator expression
        if (NOT "${source}" MATCHES "^<")
            # Construct the full path to the source file
            get_filename_component(abs_source_path "${source_dir}/${source}" ABSOLUTE)
            file(RELATIVE_PATH source_path ${CMAKE_SOURCE_DIR} ${abs_source_path})
            list(APPEND ${sources_with_paths} "${source_path}")
        else ()
            # Append generator expressions as they are
            list(APPEND ${sources_with_paths} "${source}")
        endif ()
    endforeach ()

    set(${sources_with_paths} ${${sources_with_paths}} PARENT_SCOPE)
endfunction()


code:
find_program(GETTEXT_XGETTEXT_COMMAND xgettext)
find_program(GETTEXT_MSGFMT_COMMAND msgfmt)
find_program(GETTEXT_MSGINIT_COMMAND msginit)
find_program(GETTEXT_MSGMERGE_COMMAND msgmerge)

# configure_gettext(
#     DOMAIN <domain-name>
#     TARGET_NAME <target-name>
#     SOURCES <file> ...
#     POTFILE_DESTINATION <dir>
#     POFILE_DESTINATION <dir>
#     GMOFILE_DESTINATION <dir>
#     LANGUAGES <file> ...
#     [ALL]
#     [INSTALL_DESTINATION <dest>]
#     [INSTALL_COMPONENT <dest>]
#     [BUILD_DESTINATION <dest>]
#     [XGETTEXT_ARGS <args> ...
#     [MSGMERGE_ARGS <args> ...]
#     [MSGINIT_ARGS <args> ...]
#     [MSGFMT_ARGS <args> ... ]
#     )

function(configure_gettext)
    # Ensure the utility programs are available
    if(NOT GETTEXT_XGETTEXT_COMMAND OR NOT GETTEXT_MSGFMT_COMMAND
            OR NOT GETTEXT_MSGMERGE_COMMAND OR NOT GETTEXT_MSGINIT_COMMAND)
        message(FATAL_ERROR "Could not find required programs!")
    endif()

    set(options ALL)
    set(one_value_args
            DOMAIN INSTALL_DESTINATION INSTALL_COMPONENT TARGET_NAME
            POTFILE_DESTINATION POFILE_DESTINATION GMOFILE_DESTINATION
            BUILD_DESTINATION
    )
    set(multi_args SOURCES LANGUAGES XGETTEXT_ARGS MSGFMT_ARGS MSGINIT_ARGS MSGMERGE_ARGS)
    cmake_parse_arguments(GETTEXT
            "${options}" "${one_value_args}" "${multi_args}" ${ARGV})

    if(NOT GETTEXT_DOMAIN)
        message(FATAL_ERROR "Must supply a DOMAIN!")
    elseif(NOT GETTEXT_POTFILE_DESTINATION)
        message(FATAL_ERROR "Must supply a POTFILE_DESTINATION!")
    elseif(NOT GETTEXT_LANGUAGES)
        message(FATAL_ERROR "No LANGUAGES specified!")
    elseif(NOT GETTEXT_TARGET_NAME)
        message(FATAL_ERROR "No TARGET_NAME specified!")
    elseif(NOT GETTEXT_SOURCES)
        message(FATAL_ERROR "No SOURCES supplied!")
    elseif(GETTEXT_INSTALL_COMPONENT AND NOT GETTEXT_INSTALL_DESTINATION)
        message(FATAL_ERROR "INSTALL_COMPONENT relies on INSTALL_DESTINATION")
    endif()

    if(NOT GETTEXT_POFILE_DESTINATION)
        set(GETTEXT_POFILE_DESTINATION "${GETTEXT_POTFILE_DESTINATION}/po/")
        message(STATUS "POFILE_DESTINATION defaulting to POTFILE_DESTINATION/po/")
    endif()
    if(NOT GETTEXT_GMOFILE_DESTINATION)
        set(GETTEXT_GMOFILE_DESTINATION "${GETTEXT_POFILE_DESTINATION}")
        message(STATUS "GMOFILE_DESTINATION defaulting to POFILE_DESTINATION")
    endif()

    # Make input directories absolute in relation to the current directory
    if(NOT IS_ABSOLUTE "${GETTEXT_POTFILE_DESTINATION}")
        set(GETTEXT_POTFILE_DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/${GETTEXT_POTFILE_DESTINATION}")
        file(TO_CMAKE_PATH "${GETTEXT_POTFILE_DESTINATION}" GETTEXT_POTFILE_DESTINATION)
    endif()
    if(NOT IS_ABSOLUTE "${GETTEXT_POFILE_DESTINATION}")
        set(GETTEXT_POFILE_DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/${GETTEXT_POFILE_DESTINATION}")
        file(TO_CMAKE_PATH "${GETTEXT_POFILE_DESTINATION}" GETTEXT_POFILE_DESTINATION)
    endif()
    if(NOT IS_ABSOLUTE "${GETTEXT_GMOFILE_DESTINATION}")
        set(GETTEXT_GMOFILE_DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/${GETTEXT_GMOFILE_DESTINATION}")
        file(TO_CMAKE_PATH "${GETTEXT_GMOFILE_DESTINATION}" GETTEXT_GMOFILE_DESTINATION)
    endif()

    # Create needed directories
    if(NOT EXISTS "${GETTEXT_POTFILE_DESTINATION}")
        file(MAKE_DIRECTORY "${GETTEXT_POTFILE_DESTINATION}")
    endif()
    if(NOT EXISTS "${GETTEXT_POFILE_DESTINATION}")
        file(MAKE_DIRECTORY "${GETTEXT_POFILE_DESTINATION}")
    endif()
    if(NOT EXISTS "${GETTEXT_GMOFILE_DESTINATION}")
        file(MAKE_DIRECTORY "${GETTEXT_GMOFILE_DESTINATION}")
    endif()

    if(GETTEXT_ALL)
        add_custom_target("${GETTEXT_TARGET_NAME}" ALL)
    else()
        add_custom_target("${GETTEXT_TARGET_NAME}")
    endif()

    # Generate the .pot file from the program sources
    # sources ---{xgettext}---> .pot
    if(NOT EXISTS "${GETTEXT_POTFILE_DESTINATION}/${GETTEXT_DOMAIN}.pot")
        message(STATUS "Creating initial .pot file")
        execute_process(
                COMMAND "${GETTEXT_XGETTEXT_COMMAND}" ${GETTEXT_XGETTEXT_ARGS}
                ${GETTEXT_SOURCES}
                "--output=${GETTEXT_POTFILE_DESTINATION}/${GETTEXT_DOMAIN}.pot"
                WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
    endif()
    add_custom_command(
            OUTPUT "${GETTEXT_POTFILE_DESTINATION}/${GETTEXT_DOMAIN}.pot"
            COMMAND "${GETTEXT_XGETTEXT_COMMAND}" ${GETTEXT_XGETTEXT_ARGS}
            ${GETTEXT_SOURCES}
            "--output=${GETTEXT_POTFILE_DESTINATION}/${GETTEXT_DOMAIN}.pot"
            DEPENDS ${GETTEXT_SOURCES}
            WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
            COMMENT "Generating a .pot file from program sources")

    foreach(lang IN LISTS GETTEXT_LANGUAGES)
        # Create needed directories
        if(NOT EXISTS "${GETTEXT_POFILE_DESTINATION}/${lang}")
            file(MAKE_DIRECTORY "${GETTEXT_POFILE_DESTINATION}/${lang}")
        endif()
        if(NOT EXISTS "${GETTEXT_GMOFILE_DESTINATION}/${lang}")
            file(MAKE_DIRECTORY "${GETTEXT_GMOFILE_DESTINATION}/${lang}")
        endif()

        # .pot ---{msginit}---> .po
        if(NOT EXISTS "${GETTEXT_POFILE_DESTINATION}/${lang}/${GETTEXT_DOMAIN}.po")
            message(STATUS "Creating initial .po file for ${lang}")
            execute_process(
                    COMMAND "${GETTEXT_MSGINIT_COMMAND}" ${GETTEXT_MSGINIT_ARGS}
                    "--input=${GETTEXT_POTFILE_DESTINATION}/${GETTEXT_DOMAIN}.pot"
                    "--output-file=${GETTEXT_POFILE_DESTINATION}/${lang}/${GETTEXT_DOMAIN}.po"
                    "--locale=${lang}"
                    WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
        endif()
        add_custom_command(
                OUTPUT "${GETTEXT_POFILE_DESTINATION}/${lang}/${GETTEXT_DOMAIN}.po"
                COMMAND "${GETTEXT_MSGMERGE_COMMAND}" ${GETTEXT_MSGMERGE_ARGS}
                "${GETTEXT_POFILE_DESTINATION}/${lang}/${GETTEXT_DOMAIN}.po"
                "${GETTEXT_POTFILE_DESTINATION}/${GETTEXT_DOMAIN}.pot"
                "--output-file=${GETTEXT_POFILE_DESTINATION}/${lang}/${GETTEXT_DOMAIN}.po"
                DEPENDS "${GETTEXT_POTFILE_DESTINATION}/${GETTEXT_DOMAIN}.pot"
                WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
                COMMENT "Updating the ${lang} .po file from the .pot file")

        add_custom_command(
                OUTPUT "${GETTEXT_GMOFILE_DESTINATION}/${lang}/${GETTEXT_DOMAIN}.gmo"
                COMMAND "${GETTEXT_MSGFMT_COMMAND}" ${GETTEXT_MSGFMT_ARGS}
                "${GETTEXT_POFILE_DESTINATION}/${lang}/${GETTEXT_DOMAIN}.po"
                "--output-file=${GETTEXT_GMOFILE_DESTINATION}/${lang}/${GETTEXT_DOMAIN}.gmo"
                DEPENDS "${GETTEXT_POFILE_DESTINATION}/${lang}/${GETTEXT_DOMAIN}.po"
                WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
                COMMENT "Creating the ${lang} .gmo file from the .po file")

        add_custom_target("${GETTEXT_TARGET_NAME}-${lang}"
                DEPENDS "${GETTEXT_GMOFILE_DESTINATION}/${lang}/${GETTEXT_DOMAIN}.gmo")
        add_dependencies("${GETTEXT_TARGET_NAME}" "${GETTEXT_TARGET_NAME}-${lang}")

        if(GETTEXT_INSTALL_DESTINATION)
            if(GETTEXT_INSTALL_COMPONENT)
                set(comp_line "COMPONENT" "${GETTEXT_INSTALL_COMPONENT}")
            else()
                set(comp_line)
            endif()

            install(FILES "${GETTEXT_GMOFILE_DESTINATION}/${lang}/${GETTEXT_DOMAIN}.gmo"
                    DESTINATION "${GETTEXT_INSTALL_DESTINATION}/${lang}/LC_MESSAGES/"
                    ${comp_line}
                    RENAME "${GETTEXT_DOMAIN}.mo")
        endif()

        if(GETTEXT_BUILD_DESTINATION)
            add_custom_command(
                    TARGET "${GETTEXT_TARGET_NAME}-${lang}" PRE_BUILD
                    COMMAND ${CMAKE_COMMAND} -E copy
                    "${GETTEXT_GMOFILE_DESTINATION}/${lang}/${GETTEXT_DOMAIN}.gmo"
                    "${GETTEXT_BUILD_DESTINATION}/${lang}/LC_MESSAGES/${GETTEXT_DOMAIN}.mo"
            )
        endif()

    endforeach() # lang IN LISTS GETTEXT_LANGUAGES

endfunction() # configure_gettext


code:
# Set a default build type if none was specified
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
  message(STATUS "Setting build type to 'Debug' as none was specified.")
  set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE)

  # Set the possible values of build type for cmake-gui, ccmake
  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "RelWithDebInfo")
endif ()

find_program(CCACHE ccache)
if (CCACHE)
  message(STATUS "Using ccache")
  set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE})
else ()
  message(STATUS "Ccache not found")
endif ()

# Generate compile_commands.json to make it easier to work with clang based tools
set(CMAKE_EXPORT_COMPILE_COMMANDS OFF)

option(DEACTIVATE_LOGGING "Disable logging" OFF)
if (DEACTIVATE_LOGGING)
  add_compile_definitions(APP_DEACTIVATE_LOGGING)
endif ()

option(DEBUG "Enable debug statements and asserts" OFF)
if (DEBUG OR CMAKE_BUILD_TYPE STREQUAL "Debug")
  add_compile_definitions(DEBUG APP_PROFILE)
endif ()


code:
if (NOT CMAKE_BUILD_TYPE STREQUAL "Release")
  find_program(CLANGTIDY clang-tidy)
  if (CLANGTIDY)
    message(STATUS "Using clang-tidy, found ${CLANGTIDY}")
    set(CMAKE_CXX_CLANG_TIDY "${CLANGTIDY};-extra-arg=-Wno-unknown-warning-option")
    # Explicitly enable exceptions on Windows
    if (WIN32)
      set(CMAKE_CXX_CLANG_TIDY "${CMAKE_CXX_CLANG_TIDY};--extra-arg=/EHsc")
    endif ()
  else ()
    message(WARNING "clang-tidy requested but executable not found")
  endif ()

  # This will gradually increase memory usage of the program,
  # discovered on Apple M1, 13.0.
  if (NOT WIN32)
    message(STATUS "Using address sanitizer")
    add_compile_options(-O0 -fsanitize=address -g)
    add_link_options(-O0 -fsanitize=address -g)
  endif ()
endif ()


code:
#ifndef AS_GEN_WRAPPER_H
#define AS_GEN_WRAPPER_H

#ifndef ANGELSCRIPT_H
// Avoid having to inform include path if header is already include before
#include <angelscript.h>
#endif
#include <new>

namespace gw {

template <typename T> class Proxy {
	public:
		T value;
		Proxy(T value) : value(value) {}
		static T cast(void * ptr) {
			return reinterpret_cast<Proxy<T> *>(&ptr)->value;
		}
	private:
		Proxy(const Proxy &);
		Proxy & operator=(const Proxy &);
};

template <typename T> struct Wrapper {};
template <typename T> struct WrapperGlobal {};
template <typename T> struct ObjFirst {};
template <typename T> struct ObjLast {};
template <typename T> struct Constructor {};

template <typename T>
void destroy(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
	static_cast<T *>(gen->GetObject())->~T();
}
template <>
struct Wrapper<void (*)(void)> {
	template <void (*fp)(void)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * /*gen*/) {
		((fp)());
	}
};
template <typename R>
struct Wrapper<R (*)(void)> {
	template <R (*fp)(void)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)());
	}
};
template <typename T>
struct Wrapper<void (T::*)(void)> {
	template <void (T::*fp)(void)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((static_cast<T *>(gen->GetObject())->*fp)());
	}
};
template <typename T, typename R>
struct Wrapper<R (T::*)(void)> {
	template <R (T::*fp)(void)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetObject())->*fp)());
	}
};
template <typename T>
struct Wrapper<void (T::*)(void) const> {
	template <void (T::*fp)(void) const>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((static_cast<T *>(gen->GetObject())->*fp)());
	}
};
template <typename T, typename R>
struct Wrapper<R (T::*)(void) const> {
	template <R (T::*fp)(void) const>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetObject())->*fp)());
	}
};
template <typename T>
struct WrapperGlobal<void (T::*)(void)> {
	template <void (T::*fp)(void)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((static_cast<T *>(gen->GetAuxiliary())->*fp)());
	}
};
template <typename T, typename R>
struct WrapperGlobal<R (T::*)(void)> {
	template <R (T::*fp)(void)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetAuxiliary())->*fp)());
	}
};
template <typename T>
struct WrapperGlobal<void (T::*)(void) const> {
	template <void (T::*fp)(void) const>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((static_cast<T *>(gen->GetAuxiliary())->*fp)());
	}
};
template <typename T, typename R>
struct WrapperGlobal<R (T::*)(void) const> {
	template <R (T::*fp)(void) const>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetAuxiliary())->*fp)());
	}
};
template <typename T>
struct ObjFirst<void (*)(T)> {
	template <void (*fp)(T)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((fp)(
				Proxy<T>::cast(gen->GetObject())));
	}
};
template <typename T, typename R>
struct ObjFirst<R (*)(T)> {
	template <R (*fp)(T)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
				Proxy<T>::cast(gen->GetObject())));
	}
};
template <typename T>
struct ObjLast<void (*)(T)> {
	template <void (*fp)(T)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((fp)(
				Proxy<T>::cast(gen->GetObject())));
	}
};
template <typename T, typename R>
struct ObjLast<R (*)(T)> {
	template <R (*fp)(T)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
				Proxy<T>::cast(gen->GetObject())));
	}
};
template <typename T>
struct Constructor <T ()> {
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetObject()) T();
	}
};
template <typename A0>
struct Wrapper<void (*)(A0)> {
	template <void (*fp)(A0)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value));
	}
};
template <typename R, typename A0>
struct Wrapper<R (*)(A0)> {
	template <R (*fp)(A0)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value));
	}
};
template <typename T, typename A0>
struct Wrapper<void (T::*)(A0)> {
	template <void (T::*fp)(A0)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((static_cast<T *>(gen->GetObject())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value));
	}
};
template <typename T, typename R, typename A0>
struct Wrapper<R (T::*)(A0)> {
	template <R (T::*fp)(A0)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetObject())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value));
	}
};
template <typename T, typename A0>
struct Wrapper<void (T::*)(A0) const> {
	template <void (T::*fp)(A0) const>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((static_cast<T *>(gen->GetObject())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value));
	}
};
template <typename T, typename R, typename A0>
struct Wrapper<R (T::*)(A0) const> {
	template <R (T::*fp)(A0) const>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetObject())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value));
	}
};
template <typename T, typename A0>
struct WrapperGlobal<void (T::*)(A0)> {
	template <void (T::*fp)(A0)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((static_cast<T *>(gen->GetAuxiliary())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value));
	}
};
template <typename T, typename R, typename A0>
struct WrapperGlobal<R (T::*)(A0)> {
	template <R (T::*fp)(A0)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetAuxiliary())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value));
	}
};
template <typename T, typename A0>
struct WrapperGlobal<void (T::*)(A0) const> {
	template <void (T::*fp)(A0) const>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((static_cast<T *>(gen->GetAuxiliary())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value));
	}
};
template <typename T, typename R, typename A0>
struct WrapperGlobal<R (T::*)(A0) const> {
	template <R (T::*fp)(A0) const>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetAuxiliary())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value));
	}
};
template <typename T, typename A0>
struct ObjFirst<void (*)(T, A0)> {
	template <void (*fp)(T, A0)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((fp)(
				Proxy<T>::cast(gen->GetObject()),
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value));
	}
};
template <typename T, typename R, typename A0>
struct ObjFirst<R (*)(T, A0)> {
	template <R (*fp)(T, A0)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
				Proxy<T>::cast(gen->GetObject()),
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value));
	}
};
template <typename T, typename A0>
struct ObjLast<void (*)(A0, T)> {
	template <void (*fp)(A0, T)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				Proxy<T>::cast(gen->GetObject())));
	}
};
template <typename T, typename R, typename A0>
struct ObjLast<R (*)(A0, T)> {
	template <R (*fp)(A0, T)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				Proxy<T>::cast(gen->GetObject())));
	}
};
template <typename T, typename A0>
struct Constructor <T (A0)> {
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetObject()) T(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value);
	}
};
template <typename A0, typename A1>
struct Wrapper<void (*)(A0, A1)> {
	template <void (*fp)(A0, A1)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value));
	}
};
template <typename R, typename A0, typename A1>
struct Wrapper<R (*)(A0, A1)> {
	template <R (*fp)(A0, A1)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value));
	}
};
template <typename T, typename A0, typename A1>
struct Wrapper<void (T::*)(A0, A1)> {
	template <void (T::*fp)(A0, A1)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((static_cast<T *>(gen->GetObject())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value));
	}
};
template <typename T, typename R, typename A0, typename A1>
struct Wrapper<R (T::*)(A0, A1)> {
	template <R (T::*fp)(A0, A1)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetObject())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value));
	}
};
template <typename T, typename A0, typename A1>
struct Wrapper<void (T::*)(A0, A1) const> {
	template <void (T::*fp)(A0, A1) const>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((static_cast<T *>(gen->GetObject())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value));
	}
};
template <typename T, typename R, typename A0, typename A1>
struct Wrapper<R (T::*)(A0, A1) const> {
	template <R (T::*fp)(A0, A1) const>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetObject())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value));
	}
};
template <typename T, typename A0, typename A1>
struct WrapperGlobal<void (T::*)(A0, A1)> {
	template <void (T::*fp)(A0, A1)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((static_cast<T *>(gen->GetAuxiliary())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value));
	}
};
template <typename T, typename R, typename A0, typename A1>
struct WrapperGlobal<R (T::*)(A0, A1)> {
	template <R (T::*fp)(A0, A1)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetAuxiliary())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value));
	}
};
template <typename T, typename A0, typename A1>
struct WrapperGlobal<void (T::*)(A0, A1) const> {
	template <void (T::*fp)(A0, A1) const>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((static_cast<T *>(gen->GetAuxiliary())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value));
	}
};
template <typename T, typename R, typename A0, typename A1>
struct WrapperGlobal<R (T::*)(A0, A1) const> {
	template <R (T::*fp)(A0, A1) const>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetAuxiliary())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value));
	}
};
template <typename T, typename A0, typename A1>
struct ObjFirst<void (*)(T, A0, A1)> {
	template <void (*fp)(T, A0, A1)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((fp)(
				Proxy<T>::cast(gen->GetObject()),
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value));
	}
};
template <typename T, typename R, typename A0, typename A1>
struct ObjFirst<R (*)(T, A0, A1)> {
	template <R (*fp)(T, A0, A1)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
				Proxy<T>::cast(gen->GetObject()),
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value));
	}
};
template <typename T, typename A0, typename A1>
struct ObjLast<void (*)(A0, A1, T)> {
	template <void (*fp)(A0, A1, T)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				Proxy<T>::cast(gen->GetObject())));
	}
};
template <typename T, typename R, typename A0, typename A1>
struct ObjLast<R (*)(A0, A1, T)> {
	template <R (*fp)(A0, A1, T)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				Proxy<T>::cast(gen->GetObject())));
	}
};
template <typename T, typename A0, typename A1>
struct Constructor <T (A0, A1)> {
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetObject()) T(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value);
	}
};
template <typename A0, typename A1, typename A2>
struct Wrapper<void (*)(A0, A1, A2)> {
	template <void (*fp)(A0, A1, A2)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value));
	}
};
template <typename R, typename A0, typename A1, typename A2>
struct Wrapper<R (*)(A0, A1, A2)> {
	template <R (*fp)(A0, A1, A2)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value));
	}
};
template <typename T, typename A0, typename A1, typename A2>
struct Wrapper<void (T::*)(A0, A1, A2)> {
	template <void (T::*fp)(A0, A1, A2)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((static_cast<T *>(gen->GetObject())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value));
	}
};
template <typename T, typename R, typename A0, typename A1, typename A2>
struct Wrapper<R (T::*)(A0, A1, A2)> {
	template <R (T::*fp)(A0, A1, A2)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetObject())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value));
	}
};
template <typename T, typename A0, typename A1, typename A2>
struct Wrapper<void (T::*)(A0, A1, A2) const> {
	template <void (T::*fp)(A0, A1, A2) const>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((static_cast<T *>(gen->GetObject())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value));
	}
};
template <typename T, typename R, typename A0, typename A1, typename A2>
struct Wrapper<R (T::*)(A0, A1, A2) const> {
	template <R (T::*fp)(A0, A1, A2) const>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetObject())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value));
	}
};
template <typename T, typename A0, typename A1, typename A2>
struct WrapperGlobal<void (T::*)(A0, A1, A2)> {
	template <void (T::*fp)(A0, A1, A2)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((static_cast<T *>(gen->GetAuxiliary())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value));
	}
};
template <typename T, typename R, typename A0, typename A1, typename A2>
struct WrapperGlobal<R (T::*)(A0, A1, A2)> {
	template <R (T::*fp)(A0, A1, A2)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetAuxiliary())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value));
	}
};
template <typename T, typename A0, typename A1, typename A2>
struct WrapperGlobal<void (T::*)(A0, A1, A2) const> {
	template <void (T::*fp)(A0, A1, A2) const>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((static_cast<T *>(gen->GetAuxiliary())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value));
	}
};
template <typename T, typename R, typename A0, typename A1, typename A2>
struct WrapperGlobal<R (T::*)(A0, A1, A2) const> {
	template <R (T::*fp)(A0, A1, A2) const>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetAuxiliary())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value));
	}
};
template <typename T, typename A0, typename A1, typename A2>
struct ObjFirst<void (*)(T, A0, A1, A2)> {
	template <void (*fp)(T, A0, A1, A2)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((fp)(
				Proxy<T>::cast(gen->GetObject()),
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value));
	}
};
template <typename T, typename R, typename A0, typename A1, typename A2>
struct ObjFirst<R (*)(T, A0, A1, A2)> {
	template <R (*fp)(T, A0, A1, A2)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
				Proxy<T>::cast(gen->GetObject()),
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value));
	}
};
template <typename T, typename A0, typename A1, typename A2>
struct ObjLast<void (*)(A0, A1, A2, T)> {
	template <void (*fp)(A0, A1, A2, T)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
				Proxy<T>::cast(gen->GetObject())));
	}
};
template <typename T, typename R, typename A0, typename A1, typename A2>
struct ObjLast<R (*)(A0, A1, A2, T)> {
	template <R (*fp)(A0, A1, A2, T)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
				Proxy<T>::cast(gen->GetObject())));
	}
};
template <typename T, typename A0, typename A1, typename A2>
struct Constructor <T (A0, A1, A2)> {
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetObject()) T(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value);
	}
};
template <typename A0, typename A1, typename A2, typename A3>
struct Wrapper<void (*)(A0, A1, A2, A3)> {
	template <void (*fp)(A0, A1, A2, A3)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
				static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value));
	}
};
template <typename R, typename A0, typename A1, typename A2, typename A3>
struct Wrapper<R (*)(A0, A1, A2, A3)> {
	template <R (*fp)(A0, A1, A2, A3)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
				static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value));
	}
};
template <typename T, typename A0, typename A1, typename A2, typename A3>
struct Wrapper<void (T::*)(A0, A1, A2, A3)> {
	template <void (T::*fp)(A0, A1, A2, A3)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((static_cast<T *>(gen->GetObject())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
				static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value));
	}
};
template <typename T, typename R, typename A0, typename A1, typename A2, typename A3>
struct Wrapper<R (T::*)(A0, A1, A2, A3)> {
	template <R (T::*fp)(A0, A1, A2, A3)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetObject())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
				static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value));
	}
};
template <typename T, typename A0, typename A1, typename A2, typename A3>
struct Wrapper<void (T::*)(A0, A1, A2, A3) const> {
	template <void (T::*fp)(A0, A1, A2, A3) const>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((static_cast<T *>(gen->GetObject())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
				static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value));
	}
};
template <typename T, typename R, typename A0, typename A1, typename A2, typename A3>
struct Wrapper<R (T::*)(A0, A1, A2, A3) const> {
	template <R (T::*fp)(A0, A1, A2, A3) const>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetObject())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
				static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value));
	}
};
template <typename T, typename A0, typename A1, typename A2, typename A3>
struct WrapperGlobal<void (T::*)(A0, A1, A2, A3)> {
	template <void (T::*fp)(A0, A1, A2, A3)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((static_cast<T *>(gen->GetAuxiliary())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
				static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value));
	}
};
template <typename T, typename R, typename A0, typename A1, typename A2, typename A3>
struct WrapperGlobal<R (T::*)(A0, A1, A2, A3)> {
	template <R (T::*fp)(A0, A1, A2, A3)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetAuxiliary())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
				static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value));
	}
};
template <typename T, typename A0, typename A1, typename A2, typename A3>
struct WrapperGlobal<void (T::*)(A0, A1, A2, A3) const> {
	template <void (T::*fp)(A0, A1, A2, A3) const>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((static_cast<T *>(gen->GetAuxiliary())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
				static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value));
	}
};
template <typename T, typename R, typename A0, typename A1, typename A2, typename A3>
struct WrapperGlobal<R (T::*)(A0, A1, A2, A3) const> {
	template <R (T::*fp)(A0, A1, A2, A3) const>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetAuxiliary())->*fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
				static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value));
	}
};
template <typename T, typename A0, typename A1, typename A2, typename A3>
struct ObjFirst<void (*)(T, A0, A1, A2, A3)> {
	template <void (*fp)(T, A0, A1, A2, A3)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((fp)(
				Proxy<T>::cast(gen->GetObject()),
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
				static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value));
	}
};
template <typename T, typename R, typename A0, typename A1, typename A2, typename A3>
struct ObjFirst<R (*)(T, A0, A1, A2, A3)> {
	template <R (*fp)(T, A0, A1, A2, A3)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
				Proxy<T>::cast(gen->GetObject()),
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
				static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value));
	}
};
template <typename T, typename A0, typename A1, typename A2, typename A3>
struct ObjLast<void (*)(A0, A1, A2, A3, T)> {
	template <void (*fp)(A0, A1, A2, A3, T)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		((fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
				static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value,
				Proxy<T>::cast(gen->GetObject())));
	}
};
template <typename T, typename R, typename A0, typename A1, typename A2, typename A3>
struct ObjLast<R (*)(A0, A1, A2, A3, T)> {
	template <R (*fp)(A0, A1, A2, A3, T)>
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
				static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value,
				Proxy<T>::cast(gen->GetObject())));
	}
};
template <typename T, typename A0, typename A1, typename A2, typename A3>
struct Constructor <T (A0, A1, A2, A3)> {
	static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
		new (gen->GetObject()) T(
				static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
				static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
				static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
				static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value);
	}
};
template <typename T>
struct Id {
	template <T fn_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr  f(void) { return AS_NAMESPACE_QUALIFIER asFUNCTION(&Wrapper<T>::template f<fn_ptr>); }
	template <T fn_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr fg(void) { return AS_NAMESPACE_QUALIFIER asFUNCTION(&WrapperGlobal<T>::template f<fn_ptr>); }
	template <T fn_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr of(void) { return AS_NAMESPACE_QUALIFIER asFUNCTION(&ObjFirst<T>::template f<fn_ptr>); }
	template <T fn_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr ol(void) { return AS_NAMESPACE_QUALIFIER asFUNCTION(&ObjLast<T>::template f<fn_ptr>); }
};

template <typename T>
Id<T> id(T /*fn_ptr*/) { return Id<T>(); }

// On GNUC it is necessary to use the template keyword as disambiguator.
// MSVC seems to accept both with or without the template keyword.
#if defined(__GNUC__)
	#define TMPL template
#else
	#define TMPL
#endif

#define WRAP_FN(name)             (::gw::id(name).TMPL f< name >())
#define WRAP_MFN(ClassType, name) (::gw::id(&ClassType::name).TMPL f< &ClassType::name >())
#define WRAP_MFN_GLOBAL(ClassType, name) (::gw::id(&ClassType::name).TMPL fg< &ClassType::name >())
#define WRAP_OBJ_FIRST(name)      (::gw::id(name).TMPL of< name >())
#define WRAP_OBJ_LAST(name)       (::gw::id(name).TMPL ol< name >())

#define WRAP_FN_PR(name, Parameters, ReturnType)             asFUNCTION((::gw::Wrapper<ReturnType (*)Parameters>::TMPL f< name >))
#if defined(__clang__)
 // Clang doesn't like the use of AS_METHOD_AMBIGUITY_CAST in the inner template
 #define WRAP_MFN_PR(ClassType, name, Parameters, ReturnType) asFUNCTION((::gw::Wrapper<ReturnType (ClassType::*)Parameters>::TMPL f< &ClassType::name >))
 #define WRAP_MFN_GLOBAL_PR(ClassType, name, Parameters, ReturnType) asFUNCTION((::gw::WrapperGlobal<ReturnType (ClassType::*)Parameters>::TMPL f< &ClassType::name >))
#else
 #define WRAP_MFN_PR(ClassType, name, Parameters, ReturnType) asFUNCTION((::gw::Wrapper<ReturnType (ClassType::*)Parameters>::TMPL f< AS_METHOD_AMBIGUITY_CAST(ReturnType (ClassType::*)Parameters)(&ClassType::name) >))
 #define WRAP_MFN_GLOBAL_PR(ClassType, name, Parameters, ReturnType) asFUNCTION((::gw::WrapperGlobal<ReturnType (ClassType::*)Parameters>::TMPL f< AS_METHOD_AMBIGUITY_CAST(ReturnType (ClassType::*)Parameters)(&ClassType::name) >))
#endif
#define WRAP_OBJ_FIRST_PR(name, Parameters, ReturnType)      asFUNCTION((::gw::ObjFirst<ReturnType (*)Parameters>::TMPL f< name >))
#define WRAP_OBJ_LAST_PR(name, Parameters, ReturnType)       asFUNCTION((::gw::ObjLast<ReturnType (*)Parameters>::TMPL f< name >))

#define WRAP_CON(ClassType, Parameters) asFUNCTION((::gw::Constructor<ClassType Parameters>::f))
#define WRAP_DES(ClassType)             asFUNCTION((::gw::destroy<ClassType>))

} // end namespace gw

#endif