412 lines
13 KiB
C++
412 lines
13 KiB
C++
// MassBuilderSaveTool
|
|
// Copyright (C) 2021-2024 Guillaume Jacquemin
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
#include "PropertyNames.h"
|
|
#include "../Logger/Logger.h"
|
|
#include "../Gvas/Types/ArrayProperty.h"
|
|
#include "../Gvas/Types/ColourStructProperty.h"
|
|
#include "../Gvas/Types/FloatProperty.h"
|
|
#include "../Gvas/Types/GenericStructProperty.h"
|
|
#include "../Gvas/Types/IntProperty.h"
|
|
|
|
#include "Mass.h"
|
|
|
|
using namespace Containers::Literals;
|
|
|
|
namespace mbst { namespace GameObjects {
|
|
|
|
Joints&
|
|
Mass::jointSliders() {
|
|
return _frame.joints;
|
|
}
|
|
|
|
void
|
|
Mass::getJointSliders() {
|
|
LOG_INFO("Getting joint sliders.");
|
|
|
|
auto unit_data = _mass->at<Gvas::Types::GenericStructProperty>(MASS_UNIT_DATA);
|
|
if(!unit_data) {
|
|
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_UNIT_DATA, _filename);
|
|
_state = State::Invalid;
|
|
return;
|
|
}
|
|
|
|
auto frame_prop = unit_data->at<Gvas::Types::GenericStructProperty>(MASS_FRAME);
|
|
if(!frame_prop) {
|
|
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_FRAME, _filename);
|
|
_state = State::Invalid;
|
|
return;
|
|
}
|
|
|
|
auto length = frame_prop->at<Gvas::Types::FloatProperty>(MASS_JOINT_NECK);
|
|
_frame.joints.neck = (length ? length->value : 0.0f);
|
|
length = frame_prop->at<Gvas::Types::FloatProperty>(MASS_JOINT_BODY);
|
|
_frame.joints.body = (length ? length->value : 0.0f);
|
|
length = frame_prop->at<Gvas::Types::FloatProperty>(MASS_JOINT_SHOULDER);
|
|
_frame.joints.shoulders = (length ? length->value : 0.0f);
|
|
length = frame_prop->at<Gvas::Types::FloatProperty>(MASS_JOINT_HIP);
|
|
_frame.joints.hips = (length ? length->value : 0.0f);
|
|
length = frame_prop->at<Gvas::Types::FloatProperty>(MASS_JOINT_ARM_UPPER);
|
|
_frame.joints.upperArms = (length ? length->value : 0.0f);
|
|
length = frame_prop->at<Gvas::Types::FloatProperty>(MASS_JOINT_ARM_LOWER);
|
|
_frame.joints.lowerArms = (length ? length->value : 0.0f);
|
|
length = frame_prop->at<Gvas::Types::FloatProperty>(MASS_JOINT_LEG_UPPER);
|
|
_frame.joints.upperLegs = (length ? length->value : 0.0f);
|
|
length = frame_prop->at<Gvas::Types::FloatProperty>(MASS_JOINT_LEG_LOWER);
|
|
_frame.joints.lowerLegs = (length ? length->value : 0.0f);
|
|
}
|
|
|
|
bool
|
|
Mass::writeJointSliders() {
|
|
LOG_INFO("Writing joint sliders");
|
|
|
|
auto unit_data = _mass->at<Gvas::Types::GenericStructProperty>(MASS_UNIT_DATA);
|
|
if(!unit_data) {
|
|
_lastError = "No unit data in "_s + _filename;
|
|
LOG_ERROR(_lastError);
|
|
_state = State::Invalid;
|
|
return false;
|
|
}
|
|
|
|
auto frame_prop = unit_data->at<Gvas::Types::GenericStructProperty>(MASS_FRAME);
|
|
|
|
if(!frame_prop) {
|
|
_lastError = "No frame data in "_s + _filename;
|
|
LOG_ERROR(_lastError);
|
|
_state = State::Invalid;
|
|
return false;
|
|
}
|
|
|
|
Containers::Array<Gvas::Types::UnrealPropertyBase::ptr> temp;
|
|
|
|
auto length = frame_prop->atMove<Gvas::Types::FloatProperty>(MASS_JOINT_NECK);
|
|
if(_frame.joints.neck != 0.0f) {
|
|
if(!length) {
|
|
length.emplace();
|
|
length->name.emplace(MASS_JOINT_NECK);
|
|
}
|
|
length->value = _frame.joints.neck;
|
|
arrayAppend(temp, Utility::move(length));
|
|
}
|
|
|
|
length = frame_prop->atMove<Gvas::Types::FloatProperty>(MASS_JOINT_BODY);
|
|
if(_frame.joints.body != 0.0f) {
|
|
if(!length) {
|
|
length.emplace();
|
|
length->name.emplace(MASS_JOINT_BODY);
|
|
}
|
|
length->value = _frame.joints.body;
|
|
arrayAppend(temp, Utility::move(length));
|
|
}
|
|
|
|
length = frame_prop->atMove<Gvas::Types::FloatProperty>(MASS_JOINT_SHOULDER);
|
|
if(_frame.joints.shoulders != 0.0f) {
|
|
if(!length) {
|
|
length.emplace();
|
|
length->name.emplace(MASS_JOINT_SHOULDER);
|
|
}
|
|
length->value = _frame.joints.shoulders;
|
|
arrayAppend(temp, Utility::move(length));
|
|
}
|
|
|
|
length = frame_prop->atMove<Gvas::Types::FloatProperty>(MASS_JOINT_ARM_UPPER);
|
|
if(_frame.joints.upperArms != 0.0f) {
|
|
if(!length) {
|
|
length.emplace();
|
|
length->name.emplace(MASS_JOINT_ARM_UPPER);
|
|
}
|
|
length->value = _frame.joints.upperArms;
|
|
arrayAppend(temp, Utility::move(length));
|
|
}
|
|
|
|
length = frame_prop->atMove<Gvas::Types::FloatProperty>(MASS_JOINT_ARM_LOWER);
|
|
if(_frame.joints.lowerArms != 0.0f) {
|
|
if(!length) {
|
|
length.emplace();
|
|
length->name.emplace(MASS_JOINT_ARM_LOWER);
|
|
}
|
|
length->value = _frame.joints.lowerArms;
|
|
arrayAppend(temp, Utility::move(length));
|
|
}
|
|
|
|
length = frame_prop->atMove<Gvas::Types::FloatProperty>(MASS_JOINT_HIP);
|
|
if(_frame.joints.hips != 0.0f) {
|
|
if(!length) {
|
|
length.emplace();
|
|
length->name.emplace(MASS_JOINT_HIP);
|
|
}
|
|
length->value = _frame.joints.hips;
|
|
arrayAppend(temp, Utility::move(length));
|
|
}
|
|
|
|
length = frame_prop->atMove<Gvas::Types::FloatProperty>(MASS_JOINT_LEG_UPPER);
|
|
if(_frame.joints.upperLegs != 0.0f) {
|
|
if(!length) {
|
|
length.emplace();
|
|
length->name.emplace(MASS_JOINT_LEG_UPPER);
|
|
}
|
|
length->value = _frame.joints.upperLegs;
|
|
arrayAppend(temp, Utility::move(length));
|
|
}
|
|
|
|
length = frame_prop->atMove<Gvas::Types::FloatProperty>(MASS_JOINT_LEG_LOWER);
|
|
if(_frame.joints.lowerLegs != 0.0f) {
|
|
if(!length) {
|
|
length.emplace();
|
|
length->name.emplace(MASS_JOINT_LEG_LOWER);
|
|
}
|
|
length->value = _frame.joints.lowerLegs;
|
|
arrayAppend(temp, Utility::move(length));
|
|
}
|
|
|
|
arrayAppend(temp, Utility::move(frame_prop->properties[frame_prop->properties.size() - 3]));
|
|
arrayAppend(temp, Utility::move(frame_prop->properties[frame_prop->properties.size() - 2]));
|
|
arrayAppend(temp, Utility::move(frame_prop->properties[frame_prop->properties.size() - 1]));
|
|
|
|
frame_prop->properties = Utility::move(temp);
|
|
|
|
if(!_mass->saveToFile()) {
|
|
_lastError = _mass->lastError();
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
Containers::ArrayView<std::int32_t>
|
|
Mass::frameStyles() {
|
|
return _frame.styles;
|
|
}
|
|
|
|
void
|
|
Mass::getFrameStyles() {
|
|
LOG_INFO("Getting frame styles.");
|
|
|
|
auto unit_data = _mass->at<Gvas::Types::GenericStructProperty>(MASS_UNIT_DATA);
|
|
if(!unit_data) {
|
|
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_UNIT_DATA, _filename);
|
|
_state = State::Invalid;
|
|
return;
|
|
}
|
|
|
|
auto frame_prop = unit_data->at<Gvas::Types::GenericStructProperty>(MASS_FRAME);
|
|
if(!frame_prop) {
|
|
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_FRAME, _filename);
|
|
_state = State::Invalid;
|
|
return;
|
|
}
|
|
|
|
auto frame_styles = frame_prop->at<Gvas::Types::ArrayProperty>(MASS_FRAME_STYLES);
|
|
if(!frame_styles) {
|
|
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_FRAME_STYLES, _filename);
|
|
_state = State::Invalid;
|
|
return;
|
|
}
|
|
|
|
if(frame_styles->items.size() != _frame.styles.size()) {
|
|
LOG_ERROR_FORMAT("Frame style arrays are not of the same size. Expected {}, got {} instead.",
|
|
_frame.styles.size(), frame_styles->items.size());
|
|
_state = State::Invalid;
|
|
return;
|
|
}
|
|
|
|
for(std::uint32_t i = 0; i < frame_styles->items.size(); i++) {
|
|
_frame.styles[i] = frame_styles->at<Gvas::Types::IntProperty>(i)->value;
|
|
}
|
|
}
|
|
|
|
bool
|
|
Mass::writeFrameStyles() {
|
|
LOG_INFO("Writing frame styles.");
|
|
|
|
auto unit_data = _mass->at<Gvas::Types::GenericStructProperty>(MASS_UNIT_DATA);
|
|
if(!unit_data) {
|
|
_lastError = "No unit data in "_s + _filename;
|
|
LOG_ERROR(_lastError);
|
|
_state = State::Invalid;
|
|
return false;
|
|
}
|
|
|
|
auto frame = unit_data->at<Gvas::Types::GenericStructProperty>(MASS_FRAME);
|
|
if(!frame) {
|
|
_lastError = "No frame data in "_s + _filename;
|
|
LOG_ERROR(_lastError);
|
|
_state = State::Invalid;
|
|
return false;
|
|
}
|
|
|
|
auto frame_styles = frame->at<Gvas::Types::ArrayProperty>(MASS_FRAME_STYLES);
|
|
if(!frame_styles) {
|
|
_lastError = "No frame styles in "_s + _filename;
|
|
LOG_ERROR(_lastError);
|
|
_state = State::Invalid;
|
|
return false;
|
|
}
|
|
|
|
for(std::uint32_t i = 0; i < frame_styles->items.size(); i++) {
|
|
frame_styles->at<Gvas::Types::IntProperty>(i)->value = _frame.styles[i];
|
|
}
|
|
|
|
if(!_mass->saveToFile()) {
|
|
_lastError = _mass->lastError();
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
Color4&
|
|
Mass::eyeFlareColour() {
|
|
return _frame.eyeFlare;
|
|
}
|
|
|
|
void
|
|
Mass::getEyeFlareColour() {
|
|
LOG_INFO("Getting the eye flare colour.");
|
|
|
|
auto unit_data = _mass->at<Gvas::Types::GenericStructProperty>(MASS_UNIT_DATA);
|
|
if(!unit_data) {
|
|
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_UNIT_DATA, _filename);
|
|
_state = State::Invalid;
|
|
return;
|
|
}
|
|
|
|
auto frame_prop = unit_data->at<Gvas::Types::GenericStructProperty>(MASS_FRAME);
|
|
if(!frame_prop) {
|
|
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_FRAME, _filename);
|
|
_state = State::Invalid;
|
|
return;
|
|
}
|
|
|
|
auto eye_flare_prop = frame_prop->at<Gvas::Types::ColourStructProperty>(MASS_EYE_FLARE);
|
|
if(!eye_flare_prop) {
|
|
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_EYE_FLARE, _filename);
|
|
_state = State::Invalid;
|
|
return;
|
|
}
|
|
|
|
_frame.eyeFlare = Color4{eye_flare_prop->r, eye_flare_prop->g, eye_flare_prop->b, eye_flare_prop->a};
|
|
}
|
|
|
|
bool
|
|
Mass::writeEyeFlareColour() {
|
|
LOG_INFO("Writing the eye flare colour.");
|
|
|
|
auto unit_data = _mass->at<Gvas::Types::GenericStructProperty>(MASS_UNIT_DATA);
|
|
if(!unit_data) {
|
|
_lastError = "No unit data in "_s + _filename;
|
|
LOG_ERROR(_lastError);
|
|
_state = State::Invalid;
|
|
return false;
|
|
}
|
|
|
|
auto frame = unit_data->at<Gvas::Types::GenericStructProperty>(MASS_FRAME);
|
|
if(!frame) {
|
|
_lastError = "No frame data in "_s + _filename;
|
|
LOG_ERROR(_lastError);
|
|
_state = State::Invalid;
|
|
return false;
|
|
}
|
|
|
|
auto eye_flare_prop = frame->at<Gvas::Types::ColourStructProperty>(MASS_EYE_FLARE);
|
|
if(!eye_flare_prop) {
|
|
_lastError = "No eye flare property in "_s + _filename;
|
|
LOG_ERROR(_lastError);
|
|
_state = State::Invalid;
|
|
return false;
|
|
}
|
|
|
|
eye_flare_prop->r = _frame.eyeFlare.r();
|
|
eye_flare_prop->g = _frame.eyeFlare.g();
|
|
eye_flare_prop->b = _frame.eyeFlare.b();
|
|
eye_flare_prop->a = _frame.eyeFlare.a();
|
|
|
|
if(!_mass->saveToFile()) {
|
|
_lastError = _mass->lastError();
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
Containers::ArrayView<CustomStyle>
|
|
Mass::frameCustomStyles() {
|
|
return _frame.customStyles;
|
|
}
|
|
|
|
void
|
|
Mass::getFrameCustomStyles() {
|
|
LOG_INFO("Getting the frame's custom styles.");
|
|
|
|
auto unit_data = _mass->at<Gvas::Types::GenericStructProperty>(MASS_UNIT_DATA);
|
|
if(!unit_data) {
|
|
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_UNIT_DATA, _filename);
|
|
_state = State::Invalid;
|
|
return;
|
|
}
|
|
|
|
auto frame_styles = unit_data->at<Gvas::Types::ArrayProperty>(MASS_CUSTOM_FRAME_STYLES);
|
|
if(!frame_styles) {
|
|
LOG_ERROR_FORMAT("Couldn't find {} in {}.", MASS_CUSTOM_FRAME_STYLES, _filename);
|
|
_state = State::Invalid;
|
|
return;
|
|
}
|
|
|
|
if(frame_styles->items.size() != _frame.customStyles.size()) {
|
|
LOG_ERROR_FORMAT("Frame custom style arrays are not of the same size. Expected {}, got {} instead.",
|
|
_frame.customStyles.size(), frame_styles->items.size());
|
|
_state = State::Invalid;
|
|
return;
|
|
}
|
|
|
|
getCustomStyles(_frame.customStyles, frame_styles);
|
|
|
|
for(auto& style : _frame.customStyles) {
|
|
style.type = CustomStyle::Type::Frame;
|
|
}
|
|
}
|
|
|
|
bool
|
|
Mass::writeFrameCustomStyle(std::size_t index) {
|
|
LOG_INFO_FORMAT("Writing frame custom style number {}.", index);
|
|
|
|
if(index > _frame.customStyles.size()) {
|
|
_lastError = "Style index out of range."_s;
|
|
LOG_ERROR(_lastError);
|
|
return false;
|
|
}
|
|
|
|
auto unit_data = _mass->at<Gvas::Types::GenericStructProperty>(MASS_UNIT_DATA);
|
|
if(!unit_data) {
|
|
_lastError = "No unit data in "_s + _filename;
|
|
LOG_ERROR(_lastError);
|
|
_state = State::Invalid;
|
|
return false;
|
|
}
|
|
|
|
auto frame_styles = unit_data->at<Gvas::Types::ArrayProperty>(MASS_CUSTOM_FRAME_STYLES);
|
|
if(!frame_styles) {
|
|
_lastError = "No frame styles in "_s + _filename;
|
|
LOG_ERROR(_lastError);
|
|
_state = State::Invalid;
|
|
return false;
|
|
}
|
|
|
|
return writeCustomStyle(_frame.customStyles[index], index, frame_styles);
|
|
}
|
|
|
|
}}
|