Skip to content

Load xac and xsm with cpp #444

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions extension/doc_classes/ModelSingleton.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,41 @@
<description>
</description>
</method>
<method name="get_xac_model">
<return type="Node3D" />
<param index="0" name="model_name" type="String" />
<param index="1" name="is_unit" type="bool" />
<description>
Gets the animation from an internal cache or file system using the provided file path.
</description>
</method>
<method name="get_xsm_animation">
<return type="Animation" />
<param index="0" name="animation_name" type="String" />
<description>
Gets the animation from an internal cache or file system using the provided file path.
</description>
</method>
<method name="set_scroll_material_texture">
<return type="int" />
<param index="0" name="texture_name" type="String" />
<description>
Adds the texture from the [code]gfx/anims[/code] folder to the scrolling textures shader's texture array and returns the index of the texture.
</description>
</method>
<method name="set_unit_material_texture">
<return type="int" />
<param index="0" name="type" type="int" />
<param index="1" name="texture_name" type="String" />
<description>
Adds the texture from the [code]gfx/anims[/code] folder to the unit shader's texture array and returns the index of the texture. [param type] specifies whether this is being inserted as a specular texture, or a diffuse texture.
</description>
</method>
<method name="setup_flag_shader">
<return type="int" enum="Error" />
<description>
Initializes the flag shader with the flags texture sheet and flags dimensions.
</description>
</method>
</methods>
</class>
153 changes: 153 additions & 0 deletions extension/src/openvic-extension/singletons/ModelSingleton.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "ModelSingleton.hpp"

#include <cstddef>
#include <cstdint>
#include <numbers>

#include <godot_cpp/variant/utility_functions.hpp>
Expand All @@ -9,6 +11,12 @@
#include "openvic-extension/singletons/GameSingleton.hpp"
#include "openvic-extension/utility/ClassBindings.hpp"
#include "openvic-extension/utility/Utilities.hpp"
#include "openvic-extension/utility/XSMLoader.hpp"
#include "godot_cpp/classes/global_constants.hpp"
#include "godot_cpp/classes/node3d.hpp"
#include "godot_cpp/classes/resource_loader.hpp"
#include "godot_cpp/classes/shader_material.hpp"
#include "godot_cpp/variant/string_name.hpp"

using namespace godot;
using namespace OpenVic;
Expand All @@ -19,6 +27,11 @@ void ModelSingleton::_bind_methods() {
OV_BIND_METHOD(ModelSingleton::get_cultural_helmet_model, { "culture" });
OV_BIND_METHOD(ModelSingleton::get_flag_model, { "floating" });
OV_BIND_METHOD(ModelSingleton::get_buildings);
OV_BIND_METHOD(ModelSingleton::get_xsm_animation,{ "animation_name" });
OV_BIND_METHOD(ModelSingleton::get_xac_model,{ "model_name", "is_unit" });
OV_BIND_METHOD(ModelSingleton::setup_flag_shader);
OV_BIND_METHOD(ModelSingleton::set_scroll_material_texture, {"texture_name"});
OV_BIND_METHOD(ModelSingleton::set_unit_material_texture, {"type", "texture_name"});
}

ModelSingleton* ModelSingleton::get_singleton() {
Expand Down Expand Up @@ -481,3 +494,143 @@ TypedArray<Dictionary> ModelSingleton::get_buildings() {

return ret;
}

Ref<Animation> ModelSingleton::get_xsm_animation(String source_file) {
const xsm_map_t::const_iterator it = xsm_cache.find(source_file);
if(it != xsm_cache.end()) {
return it->second;
}

GameSingleton const* game_singleton = GameSingleton::get_singleton();
ERR_FAIL_NULL_V(game_singleton, {});

String path = game_singleton->lookup_file_path(source_file);

Ref<Animation> anim = XsmLoader().load_xsm_animation(FileAccess::open(path, FileAccess::READ));
xsm_cache.emplace(source_file,anim);
return anim;
}

Node3D* ModelSingleton::get_xac_model(String source_file, bool is_unit) {
const xac_map_t::const_iterator it = xac_cache.find(source_file);
if(it != xac_cache.end()) {
Node3D* unit = (Node3D*)it->second->duplicate();
if(unit->has_method("unit_init")){
unit->call("unit_init", true);
}
return unit;
}

GameSingleton const* game_singleton = GameSingleton::get_singleton();
ERR_FAIL_NULL_V(game_singleton, {});

String path = game_singleton->lookup_file_path(source_file);
Node3D* node = XacLoader().load_xac_model(FileAccess::open(path, FileAccess::READ),is_unit);
xac_cache.emplace(source_file,node);

//if we return the "prototype" in the cache, then it will get scale by 1/256, and then all subsequent units
//duplicated from the cache will get effectively scaled by 1/256*1/256, among other problems.
Node3D* unit = (Node3D*)node->duplicate();
if(unit->has_method("unit_init")){
unit->call("unit_init", true);
}
return unit;
}

Error ModelSingleton::setup_flag_shader() {
Error result = OK;
GameSingleton const* game_singleton = GameSingleton::get_singleton();
ERR_FAIL_NULL_V(game_singleton, {});

static const StringName Param_flag_dimensions = "flag_dims";
static const StringName Param_flag_texture_sheet = "texture_flag_sheet_diffuse";
ResourceLoader* loader = ResourceLoader::get_singleton();
static const Ref<ShaderMaterial> flag_shader = loader->load("res://src/Game/Model/flag_mat.tres");

flag_shader->set_shader_parameter(Param_flag_dimensions, game_singleton->get_flag_dims());
flag_shader->set_shader_parameter(Param_flag_texture_sheet, game_singleton->get_flag_sheet_texture());
return result;
}

static void pushback_shader_array(Ref<ShaderMaterial> shader, String property, Variant value) {
Array arr = shader->get_shader_parameter(property);
arr.push_back(value);
shader->set_shader_parameter(property, arr);
}

Ref<ShaderMaterial> ModelSingleton::get_unit_shader() {
if(unit_shader.is_null()) {
ResourceLoader* loader = ResourceLoader::get_singleton();
unit_shader = loader->load("res://src/Game/Model/unit_colours_mat.tres");
}
return unit_shader;
}

Ref<ShaderMaterial> ModelSingleton::get_scroll_shader() {
if(scroll_shader.is_null()) {
ResourceLoader* loader = ResourceLoader::get_singleton();
scroll_shader = loader->load("res://src/Game/Model/scrolling_mat.tres");
}
return scroll_shader;
}

//TODO: put this back, 64 is likely needed because of names being added twice
// (due to 2 loaders operating)
static constexpr uint32_t MAX_UNIT_TEXTURES = 64;

int32_t ModelSingleton::set_unit_material_texture(int32_t type, String texture_name) {//MAP_TYPE::Values
shader_array_index_map_t& map = type==2 ? diffuse_texture_index_map : specular_texture_index_map; //OpenVic::MAP_TYPE::DIFFUSE
const shader_array_index_map_t::const_iterator it = map.find(texture_name);
if(it != map.end()) {
//UtilityFunctions::print(
// vformat("cached texture: %s type: %d, index %d", texture_name, type, it->second)
//);
return it->second; //return the index
}

int32_t index = map.size();
map.emplace(texture_name,index);
if (map.size() >= MAX_UNIT_TEXTURES) {
Logger::error("Number of textures exceeded max supported by a shader!");
return 0;
}

// Parameters for the default model shader
static const StringName Param_texture_diffuse = "texture_diffuse";
//red channel is specular, green and blue are nation colours
static const StringName Param_texture_nation_colors_mask = "texture_nation_colors_mask";
//static const StringName Param_texture_shadow = "texture_shadow";
String shader_param = type==2 ? Param_texture_diffuse : Param_texture_nation_colors_mask; //OpenVic::MAP_TYPE::DIFFUSE

pushback_shader_array(get_unit_shader(), shader_param, XacLoader::get_model_texture(texture_name));

return index;
}

int32_t ModelSingleton::set_scroll_material_texture(String texture_name) {
const shader_array_index_map_t::const_iterator it = scroll_index_map.find(texture_name);
if(it != scroll_index_map.end()) {
return it->second; //return the index
}

scroll_index_map.emplace(texture_name,scroll_index_map.size());
if (scroll_index_map.size() >= MAX_UNIT_TEXTURES) {
Logger::error("Number of textures exceeded max supported by a shader!");
return 0;
}

static const StringName Param_Scroll_texture_diffuse = "scroll_texture_diffuse";
static const StringName Param_Scroll_factor = "scroll_factor";

pushback_shader_array(get_scroll_shader(), Param_Scroll_texture_diffuse, XacLoader::get_model_texture(texture_name));

float scroll_factor = 0.0;
static const StringName tracks = "TexAnim";
static const StringName smoke = "Smoke";
if(texture_name == tracks) { scroll_factor = 2.5; }
else if(texture_name == smoke) { scroll_factor = 0.3; }

pushback_shader_array(get_scroll_shader(), Param_Scroll_factor, scroll_factor);

return scroll_index_map[texture_name];
}
31 changes: 31 additions & 0 deletions extension/src/openvic-extension/singletons/ModelSingleton.hpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
#pragma once

#include <cstdint>
#include <string_view>
#include <godot_cpp/classes/animation.hpp>
#include <godot_cpp/classes/object.hpp>

#include <openvic-simulation/interface/GFXObject.hpp>
#include <openvic-simulation/military/UnitInstanceGroup.hpp>
#include <openvic-simulation/types/OrderedContainers.hpp>
//#include "../utility/XSMLoader.hpp"
#include "../utility/XACLoader.hpp"
#include "godot_cpp/classes/shader.hpp"
#include "godot_cpp/classes/shader_material.hpp"
#include "godot_cpp/classes/node3d.hpp"

namespace OpenVic {

struct BuildingInstance;

class ModelSingleton : public godot::Object {
Expand All @@ -31,10 +40,23 @@ namespace OpenVic {

using animation_map_t = deque_ordered_map<GFX::Actor::Animation const*, godot::Dictionary>;
using model_map_t = deque_ordered_map<GFX::Actor const*, godot::Dictionary>;
using xsm_map_t = deque_ordered_map<godot::StringName, godot::Ref<godot::Animation>>;
using xac_map_t = deque_ordered_map<godot::StringName, godot::Node3D*>;
using shader_array_index_map_t = deque_ordered_map<godot::StringName, int32_t>;

animation_map_t animation_cache;
model_map_t model_cache;

xsm_map_t xsm_cache;
xac_map_t xac_cache;

godot::Ref<godot::ShaderMaterial> unit_shader;
godot::Ref<godot::ShaderMaterial> scroll_shader;
shader_array_index_map_t diffuse_texture_index_map;
shader_array_index_map_t specular_texture_index_map;
//shader_array_index_map_t shadow_texture_index_map;
shader_array_index_map_t scroll_index_map;

godot::Dictionary get_animation_dict(GFX::Actor::Animation const& animation);
godot::Dictionary get_model_dict(GFX::Actor const& actor);

Expand All @@ -56,5 +78,14 @@ namespace OpenVic {
godot::Dictionary get_flag_model(bool floating);

godot::TypedArray<godot::Dictionary> get_buildings();

godot::Ref<godot::Animation> get_xsm_animation(godot::String source_file);
godot::Node3D* get_xac_model(godot::String source_file, bool is_unit=false);
godot::Error setup_flag_shader();

godot::Ref<godot::ShaderMaterial> get_unit_shader();
godot::Ref<godot::ShaderMaterial> get_scroll_shader();
int32_t set_unit_material_texture(int32_t type, godot::String name); //MAP_TYPE::Values
int32_t set_scroll_material_texture(godot::String texture_name);
};
}
Loading
Loading