Began implementing Artificer Refinement window. Release Build 11440.
This commit is contained in:
parent
50820d34a5
commit
8303665828
@ -531,6 +531,10 @@
|
|||||||
</SubType>
|
</SubType>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="MenuItemLoadoutButton.h" />
|
<ClInclude Include="MenuItemLoadoutButton.h" />
|
||||||
|
<ClInclude Include="MenuRefineLabel.h">
|
||||||
|
<SubType>
|
||||||
|
</SubType>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="MenuType.h">
|
<ClInclude Include="MenuType.h">
|
||||||
<SubType>
|
<SubType>
|
||||||
</SubType>
|
</SubType>
|
||||||
|
@ -696,6 +696,9 @@
|
|||||||
<ClInclude Include="MenuDecal.h">
|
<ClInclude Include="MenuDecal.h">
|
||||||
<Filter>Header Files\Interface</Filter>
|
<Filter>Header Files\Interface</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="MenuRefineLabel.h">
|
||||||
|
<Filter>Header Files\Interface</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="Player.cpp">
|
<ClCompile Include="Player.cpp">
|
||||||
|
@ -39,52 +39,72 @@ All rights reserved.
|
|||||||
#include "Menu.h"
|
#include "Menu.h"
|
||||||
#include "AdventuresInLestoria.h"
|
#include "AdventuresInLestoria.h"
|
||||||
#include "RowInventoryScrollableWindowComponent.h"
|
#include "RowInventoryScrollableWindowComponent.h"
|
||||||
#include "MenuLabel.h"
|
|
||||||
#include "MenuItemItemButton.h"
|
#include "MenuItemItemButton.h"
|
||||||
|
#include "MenuRefineLabel.h"
|
||||||
|
#include "PlayerMoneyLabel.h"
|
||||||
|
|
||||||
INCLUDE_game
|
INCLUDE_game
|
||||||
|
|
||||||
void Menu::InitializeArtificerRefineWindow(){
|
void Menu::InitializeArtificerRefineWindow(){
|
||||||
Menu*artificerRefineWindow=CreateMenu(ARTIFICER_REFINE,CENTERED,game->GetScreenSize()-vi2d{52,52});
|
Menu*const artificerRefineWindow{CreateMenu(ARTIFICER_REFINE,CENTERED,game->GetScreenSize()-vi2d{52,52})};
|
||||||
|
|
||||||
auto disassemblyTitleLabel{artificerRefineWindow->ADD("Disassembly Title Label",MenuLabel)(geom2d::rect<float>{{},{artificerRefineWindow->size.x,24.f}},"Accessory Disassembly",2.f,ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END};
|
auto disassemblyTitleLabel{artificerRefineWindow->ADD("Disassembly Title Label",MenuLabel)(geom2d::rect<float>{{0.f,-16.f},{artificerRefineWindow->size.x,24.f}},"Accessory Disassembly",2.f,ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END};
|
||||||
|
|
||||||
auto inventoryLabel=artificerRefineWindow->ADD("Accessory List Label",MenuLabel)(geom2d::rect<float>{{0.f,28.f},{180.f,12.f}},"Choose Accessory:",1.f,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END;
|
auto inventoryLabel{artificerRefineWindow->ADD("Accessory List Label",MenuLabel)(geom2d::rect<float>{{0.f,12.f},{180.f,12.f}},"Choose Accessory:",1.f,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END};
|
||||||
|
|
||||||
auto itemIcon{artificerRefineWindow->ADD("Item Icon",MenuItemItemButton)(geom2d::rect<float>({artificerRefineWindow->size.x/2+4.f,44.f},{48,48}),Item::BLANK,DO_NOTHING,"","Item Description",IconButtonAttr::NOT_SELECTABLE)END};
|
auto itemIcon{artificerRefineWindow->ADD("Item Icon",MenuItemItemButton)(geom2d::rect<float>({artificerRefineWindow->size.x/2+4.f,28.f},{48,48}),Item::BLANK,DO_NOTHING,"","Item Description",IconButtonAttr::NOT_SELECTABLE)END};
|
||||||
itemIcon->SetIconScale({2.f,2.f});
|
itemIcon->SetIconScale({2.f,2.f});
|
||||||
itemIcon->SetCompactDescriptions(true);
|
itemIcon->SetCompactDescriptions(true);
|
||||||
|
|
||||||
auto accessoryDescription{artificerRefineWindow->ADD("Item Description",MenuLabel)(geom2d::rect<float>{{artificerRefineWindow->size.x/2+56.f,44.f},{artificerRefineWindow->size.x/2-56.f,72.f}},"",0.5f,ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE|ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END};
|
auto accessoryDescription{artificerRefineWindow->ADD("Item Description",MenuLabel)(geom2d::rect<float>{{artificerRefineWindow->size.x/2+56.f,28.f},{artificerRefineWindow->size.x/2-56.f,72.f}},"",0.5f,ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE|ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END};
|
||||||
|
|
||||||
const auto ResetDisassemblyDisplay=[artificerRefineWindow](){
|
const auto ResetRefineDisplay{[artificerRefineWindow](){
|
||||||
MenuType menuType{artificerRefineWindow->GetType()};
|
MenuType menuType{artificerRefineWindow->GetType()};
|
||||||
};
|
Component<MenuItemItemButton>(menuType,"Item Icon")->SetItem(Item::BLANK);
|
||||||
const auto EnableDisassemblyDisplay=[artificerRefineWindow](){
|
Component<MenuRefineLabel>(menuType,"Stats Block")->SetItem(Item::BLANK);
|
||||||
|
}};
|
||||||
|
const auto EnableRefineDisplay{[artificerRefineWindow](){
|
||||||
MenuType menuType{artificerRefineWindow->GetType()};
|
MenuType menuType{artificerRefineWindow->GetType()};
|
||||||
};
|
}};
|
||||||
|
|
||||||
auto inventoryDisplay=artificerRefineWindow->ADD("Accessory List",RowInventoryScrollableWindowComponent)(geom2d::rect<float>{{0.f,44.f},{artificerRefineWindow->size.x/2-4.f,artificerRefineWindow->size.y-60}},"","",[](MenuFuncData data){
|
auto inventoryDisplay{artificerRefineWindow->ADD("Accessory List",RowInventoryScrollableWindowComponent)(geom2d::rect<float>{{0.f,28.f},{artificerRefineWindow->size.x/2-4.f,artificerRefineWindow->size.y-44}},"","",[](MenuFuncData data){
|
||||||
|
OnClick:
|
||||||
RowItemDisplay&item{*DYNAMIC_POINTER_CAST<RowItemDisplay>(data.component)};
|
RowItemDisplay&item{*DYNAMIC_POINTER_CAST<RowItemDisplay>(data.component)};
|
||||||
DYNAMIC_POINTER_CAST<RowInventoryScrollableWindowComponent>(data.parentComponent.lock())->SelectChild(DYNAMIC_POINTER_CAST<RowItemDisplay>(data.component));
|
DYNAMIC_POINTER_CAST<RowInventoryScrollableWindowComponent>(data.parentComponent.lock())->SelectChild(DYNAMIC_POINTER_CAST<RowItemDisplay>(data.component));
|
||||||
return true;
|
return true;
|
||||||
},[](MenuFuncData data){
|
},[EnableRefineDisplay](MenuFuncData data){OnHover:
|
||||||
RowItemDisplay&item{*DYNAMIC_POINTER_CAST<RowItemDisplay>(data.component)};
|
RowItemDisplay&item{*DYNAMIC_POINTER_CAST<RowItemDisplay>(data.component)};
|
||||||
return true;
|
EnableRefineDisplay();
|
||||||
},[](MenuFuncData data){
|
Component<MenuItemItemButton>(data.menu.type,"Item Icon")->SetItem(item.GetItem());
|
||||||
|
Component<MenuRefineLabel>(data.menu.type,"Stats Block")->SetItem(item.GetItem());
|
||||||
|
return true;
|
||||||
|
},[ResetRefineDisplay,EnableRefineDisplay](MenuFuncData data){OnMouseOut:
|
||||||
|
ResetRefineDisplay();
|
||||||
auto childComponent{DYNAMIC_POINTER_CAST<RowInventoryScrollableWindowComponent>(data.parentComponent.lock())->GetSelectedChild()};
|
auto childComponent{DYNAMIC_POINTER_CAST<RowInventoryScrollableWindowComponent>(data.parentComponent.lock())->GetSelectedChild()};
|
||||||
if(childComponent){
|
if(childComponent){
|
||||||
RowItemDisplay&item{childComponent.value().get()};
|
RowItemDisplay&item{childComponent.value().get()};
|
||||||
|
EnableRefineDisplay();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
InventoryCreator::RowPlayer_InventoryUpdate,
|
InventoryCreator::RowPlayer_InventoryUpdate,
|
||||||
InventoryWindowOptions{.padding=1,.size={artificerRefineWindow->size.x/2-5.f-12.f,28}})END;
|
InventoryWindowOptions{.padding=1,.size={artificerRefineWindow->size.x/2-5.f-12.f,28}})END};
|
||||||
|
|
||||||
auto backButton=artificerRefineWindow->ADD("Back",MenuComponent)(geom2d::rect<float>{{0.f,artificerRefineWindow->size.y-12.f},{96.f,16.f}},"Back",[](MenuFuncData data){
|
auto statsBlock{artificerRefineWindow->ADD("Stats Block",MenuRefineLabel)(geom2d::rect<float>{{artificerRefineWindow->size.x/2+4.f,104.f},{artificerRefineWindow->size.x/2-4.f,44.f}},Item::BLANK,1.f,ComponentAttr::BACKGROUND|ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::FIXED_WIDTH_FONT|ComponentAttr::FIT_TO_LABEL|ComponentAttr::LEFT_ALIGN)END};
|
||||||
|
|
||||||
|
#pragma region Money Display
|
||||||
|
vf2d moneyIconPos{artificerRefineWindow->size.x/2-28.f,artificerRefineWindow->size.y-12.f};
|
||||||
|
auto moneyIcon=artificerRefineWindow->ADD("Money Icon",MenuIconButton)(geom2d::rect<float>{moneyIconPos,{24,24}},GFX["money.png"].Decal(),DO_NOTHING,IconButtonAttr::NOT_SELECTABLE|IconButtonAttr::NO_OUTLINE|IconButtonAttr::NO_BACKGROUND)END;
|
||||||
|
std::string moneyText=std::to_string(game->GetPlayer()->GetMoney());
|
||||||
|
vf2d moneyTextSize=game->GetTextSizeProp(moneyText)*2;
|
||||||
|
auto moneyDisplay=artificerRefineWindow->ADD("Money Label",PlayerMoneyLabel)(geom2d::rect<float>{moneyIconPos+vf2d{26.f,4.f},moneyTextSize},2,1.85f,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN|ComponentAttr::FIT_TO_LABEL)END;
|
||||||
|
Player::AddMoneyListener(moneyDisplay);
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
auto backButton{artificerRefineWindow->ADD("Back",MenuComponent)(geom2d::rect<float>{{0.f,artificerRefineWindow->size.y-12.f},{96.f,16.f}},"Back",[](MenuFuncData data){
|
||||||
Menu::CloseMenu();
|
Menu::CloseMenu();
|
||||||
return true;
|
return true;
|
||||||
})END;
|
})END};
|
||||||
|
|
||||||
|
|
||||||
Menu::AddInventoryListener(inventoryDisplay,"Accessories");
|
Menu::AddInventoryListener(inventoryDisplay,"Accessories");
|
||||||
|
@ -115,15 +115,15 @@ type DYNAMIC_CAST(auto variable){
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T,typename U>
|
template<typename T,typename U>
|
||||||
std::shared_ptr<T>DYNAMIC_POINTER_CAST(const std::shared_ptr<U>&variable){
|
const std::shared_ptr<T>DYNAMIC_POINTER_CAST(const std::shared_ptr<U>&variable){
|
||||||
std::shared_ptr<T> newVariable=dynamic_pointer_cast<T>(variable);
|
const std::shared_ptr<T> newVariable=dynamic_pointer_cast<T>(variable);
|
||||||
if(!newVariable)ERR("Could not dynamic cast to pointer type "<<typeid(newVariable).name()<<"!");
|
if(!newVariable)ERR("Could not dynamic cast to pointer type "<<typeid(newVariable).name()<<"!");
|
||||||
return newVariable;
|
return newVariable;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T,typename U>
|
template<typename T,typename U>
|
||||||
std::shared_ptr<T>DYNAMIC_POINTER_CAST(const std::weak_ptr<U>&variable){
|
const std::shared_ptr<T>DYNAMIC_POINTER_CAST(const std::weak_ptr<U>&variable){
|
||||||
std::shared_ptr<T> newVariable=dynamic_pointer_cast<T>(variable.lock());
|
const std::shared_ptr<T> newVariable=dynamic_pointer_cast<T>(variable.lock());
|
||||||
if(!newVariable)ERR("Could not dynamic cast to pointer type "<<typeid(newVariable).name()<<"!");
|
if(!newVariable)ERR("Could not dynamic cast to pointer type "<<typeid(newVariable).name()<<"!");
|
||||||
return newVariable;
|
return newVariable;
|
||||||
}
|
}
|
||||||
|
@ -1087,8 +1087,7 @@ const std::string Stats::GetStatsString(const Stats&maxStats,CompactText compact
|
|||||||
|
|
||||||
std::string col="";
|
std::string col="";
|
||||||
if(maxStats.attributes.count(attr)&&int(val)>=int(maxStats.attributes.at(attr))){
|
if(maxStats.attributes.count(attr)&&int(val)>=int(maxStats.attributes.at(attr))){
|
||||||
Pixel shimmeringCol=PixelLerp({255,196,60},{254,217,133},sin((70*game->GetRunTime())/2.f+0.5f));
|
col=Stats::GetShimmeringColor().toHTMLColorCode();
|
||||||
col=shimmeringCol.toHTMLColorCode();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
description+=col+std::string(attr.Name())+": "+statNumber+(attr.DisplayAsPercent()?"%":"")+"#FFFFFF";
|
description+=col+std::string(attr.Name())+": "+statNumber+(attr.DisplayAsPercent()?"%":"")+"#FFFFFF";
|
||||||
@ -1513,4 +1512,8 @@ const bool Item::SelectedEquipIsDifferent(const std::weak_ptr<Item>equipAttempti
|
|||||||
}
|
}
|
||||||
const std::optional<std::string>&ItemInfo::FragmentIcon()const{
|
const std::optional<std::string>&ItemInfo::FragmentIcon()const{
|
||||||
return fragmentIcon;
|
return fragmentIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Pixel Stats::GetShimmeringColor(){
|
||||||
|
return PixelLerp({255,196,60},{254,217,133},sin((70*game->GetRunTime())/2.f+0.5f));
|
||||||
}
|
}
|
@ -111,6 +111,7 @@ public:
|
|||||||
}
|
}
|
||||||
const std::string GetStatsString(const Stats&maxStats,CompactText compact=NON_COMPACT)const;
|
const std::string GetStatsString(const Stats&maxStats,CompactText compact=NON_COMPACT)const;
|
||||||
friend const bool operator==(const Stats&lhs,const Stats&rhs){return lhs.attributes==rhs.attributes;}
|
friend const bool operator==(const Stats&lhs,const Stats&rhs){return lhs.attributes==rhs.attributes;}
|
||||||
|
static const Pixel GetShimmeringColor();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Stats;
|
struct Stats;
|
||||||
|
78
Adventures in Lestoria/MenuRefineLabel.h
Normal file
78
Adventures in Lestoria/MenuRefineLabel.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#pragma region License
|
||||||
|
/*
|
||||||
|
License (OLC-3)
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Copyright 2024 Joshua Sigona <sigonasr2@gmail.com>
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions or derivations of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions or derivative works in binary form must reproduce the above
|
||||||
|
copyright notice. This list of conditions and the following disclaimer must be
|
||||||
|
reproduced in the documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software without specific
|
||||||
|
prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||||
|
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGE.
|
||||||
|
|
||||||
|
Portions of this software are copyright © 2024 The FreeType
|
||||||
|
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
|
||||||
|
All rights reserved.
|
||||||
|
*/
|
||||||
|
#pragma endregion
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "MenuLabel.h"
|
||||||
|
|
||||||
|
INCLUDE_DATA
|
||||||
|
INCLUDE_ITEM_DATA
|
||||||
|
|
||||||
|
class MenuRefineLabel:public MenuLabel{
|
||||||
|
public:
|
||||||
|
inline MenuRefineLabel(const geom2d::rect<float>rect,const std::weak_ptr<Item>itemRef,const float scale=1,ComponentAttr attributes=ComponentAttr::NONE)
|
||||||
|
:itemRef(itemRef),MenuLabel(rect,"",scale,attributes){}
|
||||||
|
|
||||||
|
inline virtual void Update(AiL*game)override{
|
||||||
|
std::string label{};
|
||||||
|
|
||||||
|
if(!ISBLANK(itemRef)){
|
||||||
|
std::string longestStatName{};
|
||||||
|
const Stats&maxStats{ITEM_DATA.at(itemRef.lock()->ActualName()).GetMaxStats()};
|
||||||
|
for(const auto&[attr,val]:maxStats){
|
||||||
|
const std::string displayName{attr.Name()};
|
||||||
|
if(displayName.size()>longestStatName.size())longestStatName=displayName;
|
||||||
|
}
|
||||||
|
const std::string statNameVFormatStr{"{:"+std::to_string(longestStatName.size()+1)+"}"};
|
||||||
|
|
||||||
|
for(const auto&[attr,val]:itemRef.lock()->RandomStats()){
|
||||||
|
const bool IsMaxedOut{val>=maxStats.A_Read(attr.ActualName())};
|
||||||
|
label+=util::vformat("{}"+statNameVFormatStr+"+{:3}{:1}{}{:>5}\n",IsMaxedOut?Stats::GetShimmeringColor().toHTMLColorCode():"#FFFFFF",attr.Name(),int(round(val)),attr.DisplayAsPercent()?"%":"",IsMaxedOut?"#FF0000":"#00FF00",IsMaxedOut?"MAX":" +???");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetLabel(label);
|
||||||
|
MenuLabel::Update(game);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetItem(const std::weak_ptr<Item>itemRef){
|
||||||
|
this->itemRef=itemRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::weak_ptr<Item>itemRef;
|
||||||
|
};
|
@ -56,7 +56,7 @@ public:
|
|||||||
SetLabel(std::to_string(newMoney));
|
SetLabel(std::to_string(newMoney));
|
||||||
std::string moneyText=std::to_string(newMoney);
|
std::string moneyText=std::to_string(newMoney);
|
||||||
vf2d moneyTextSize=game->GetTextSizeProp(moneyText)*scale;
|
vf2d moneyTextSize=game->GetTextSizeProp(moneyText)*scale;
|
||||||
rect.pos.x=anchorPointX-moneyTextSize.x;
|
if(rightAligned)rect.pos.x=anchorPointX-moneyTextSize.x;
|
||||||
rect.size=moneyTextSize;
|
rect.size=moneyTextSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ All rights reserved.
|
|||||||
#define VERSION_MAJOR 1
|
#define VERSION_MAJOR 1
|
||||||
#define VERSION_MINOR 2
|
#define VERSION_MINOR 2
|
||||||
#define VERSION_PATCH 5
|
#define VERSION_PATCH 5
|
||||||
#define VERSION_BUILD 11417
|
#define VERSION_BUILD 11440
|
||||||
|
|
||||||
#define stringify(a) stringify_(a)
|
#define stringify(a) stringify_(a)
|
||||||
#define stringify_(a) #a
|
#define stringify_(a) #a
|
||||||
|
@ -86,17 +86,17 @@ namespace olc::util{
|
|||||||
std::wstring to_wstring(const std::string&str);
|
std::wstring to_wstring(const std::string&str);
|
||||||
|
|
||||||
template<class..._Args>
|
template<class..._Args>
|
||||||
std::string vformat(std::string str,_Args&..._Vals){
|
const std::string vformat(const std::string_view str,_Args..._Vals){
|
||||||
return std::vformat(str,std::make_format_args(_Vals...));
|
return std::vformat(str,std::make_format_args(_Vals...));
|
||||||
}
|
}
|
||||||
template<class..._Args>
|
template<class..._Args>
|
||||||
std::wstring wformat(std::string str,_Args&..._Vals){
|
const std::wstring wformat(const std::string_view str,_Args..._Vals){
|
||||||
return util::to_wstring(std::vformat(str,std::make_format_args(_Vals...)));
|
return util::to_wstring(std::vformat(str,std::make_format_args(_Vals...)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
T map_range(T x, T in_min, T in_max, T out_min, T out_max) {
|
T map_range(T x, T in_min, T in_max, T out_min, T out_max) {
|
||||||
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user