Compare commits
No commits in common. "1.3" and "master" have entirely different histories.
164
.editorconfig
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
# C# files
|
||||
[*.cs]
|
||||
indent_size = 4
|
||||
# New line preferences
|
||||
csharp_new_line_before_open_brace = all
|
||||
csharp_new_line_before_else = true
|
||||
csharp_new_line_before_catch = true
|
||||
csharp_new_line_before_finally = true
|
||||
csharp_new_line_before_members_in_object_initializers = true
|
||||
csharp_new_line_before_members_in_anonymous_types = true
|
||||
csharp_new_line_within_query_expression_clauses = true
|
||||
|
||||
# Code files
|
||||
[*.{cs,csx,vb,vbx}]
|
||||
indent_size = 4
|
||||
|
||||
# Indentation preferences
|
||||
csharp_indent_block_contents = true
|
||||
csharp_indent_braces = false
|
||||
csharp_indent_case_contents = true
|
||||
csharp_indent_switch_labels = true
|
||||
csharp_indent_labels = one_less_than_current
|
||||
|
||||
# avoid this. unless absolutely necessary
|
||||
dotnet_style_qualification_for_field = false:suggestion
|
||||
dotnet_style_qualification_for_property = false:suggestion
|
||||
dotnet_style_qualification_for_method = false:suggestion
|
||||
dotnet_style_qualification_for_event = false:suggestion
|
||||
|
||||
# only use var when it's obvious what the variable type is
|
||||
csharp_style_var_for_built_in_types = false:none
|
||||
csharp_style_var_when_type_is_apparent = false:none
|
||||
csharp_style_var_elsewhere = false:suggestion
|
||||
|
||||
# use language keywords instead of BCL types
|
||||
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
|
||||
dotnet_style_predefined_type_for_member_access = true:suggestion
|
||||
|
||||
# name all constant fields using PascalCase
|
||||
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
|
||||
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
|
||||
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
|
||||
|
||||
dotnet_naming_symbols.constant_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.constant_fields.required_modifiers = const
|
||||
|
||||
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
|
||||
|
||||
# internal and private fields should be _camelCase
|
||||
dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion
|
||||
dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
|
||||
dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
|
||||
|
||||
dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
|
||||
|
||||
dotnet_naming_style.camel_case_underscore_style.required_prefix = _
|
||||
dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
|
||||
|
||||
# Code style defaults
|
||||
dotnet_sort_system_directives_first = true
|
||||
csharp_preserve_single_line_blocks = true
|
||||
csharp_preserve_single_line_statements = false
|
||||
|
||||
# Expression-level preferences
|
||||
dotnet_style_object_initializer = true:suggestion
|
||||
dotnet_style_collection_initializer = true:suggestion
|
||||
dotnet_style_explicit_tuple_names = true:suggestion
|
||||
dotnet_style_coalesce_expression = true:suggestion
|
||||
dotnet_style_null_propagation = true:suggestion
|
||||
|
||||
# Expression-bodied members
|
||||
csharp_style_expression_bodied_methods = false:none
|
||||
csharp_style_expression_bodied_constructors = false:none
|
||||
csharp_style_expression_bodied_operators = false:none
|
||||
csharp_style_expression_bodied_properties = true:none
|
||||
csharp_style_expression_bodied_indexers = true:none
|
||||
csharp_style_expression_bodied_accessors = true:none
|
||||
|
||||
# Pattern matching
|
||||
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
|
||||
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
|
||||
csharp_style_inlined_variable_declaration = true:suggestion
|
||||
|
||||
# Null checking preferences
|
||||
csharp_style_throw_expression = true:suggestion
|
||||
csharp_style_conditional_delegate_call = true:suggestion
|
||||
|
||||
# Space preferences
|
||||
csharp_space_after_cast = true
|
||||
csharp_space_after_colon_in_inheritance_clause = true
|
||||
csharp_space_after_comma = true
|
||||
csharp_space_after_dot = false
|
||||
csharp_space_after_keywords_in_control_flow_statements = true
|
||||
csharp_space_after_semicolon_in_for_statement = true
|
||||
csharp_space_around_binary_operators = before_and_after
|
||||
csharp_space_around_declaration_statements = do_not_ignore
|
||||
csharp_space_before_colon_in_inheritance_clause = true
|
||||
csharp_space_before_comma = false
|
||||
csharp_space_before_dot = false
|
||||
csharp_space_before_open_square_brackets = false
|
||||
csharp_space_before_semicolon_in_for_statement = false
|
||||
csharp_space_between_empty_square_brackets = false
|
||||
csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_call_name_and_opening_parenthesis = false
|
||||
csharp_space_between_method_call_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_name_and_open_parenthesis = false
|
||||
csharp_space_between_method_declaration_parameter_list_parentheses = false
|
||||
csharp_space_between_parentheses = false
|
||||
csharp_space_between_square_brackets = false
|
||||
|
||||
[*.{asm,inc}]
|
||||
indent_size = 8
|
||||
|
||||
# Visual Studio Solution Files
|
||||
[*.sln]
|
||||
indent_style = tab
|
||||
|
||||
# Visual Studio XML Project Files
|
||||
[*.{csproj,vbproj,vcxproj.filters,proj,projitems,shproj}]
|
||||
indent_size = 2
|
||||
|
||||
# XML Configuration Files
|
||||
[*.{xml,config,props,targets,nuspec,resx,ruleset,vsixmanifest,vsct}]
|
||||
indent_size = 2
|
||||
|
||||
[CMakeLists.txt]
|
||||
indent_size = 2
|
||||
|
||||
# Makefiles
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
|
||||
# Batch Files
|
||||
[*.{cmd,bat}]
|
||||
indent_size = 2
|
||||
end_of_line = crlf
|
||||
|
||||
# Bash Files
|
||||
[*.sh]
|
||||
end_of_line = lf
|
||||
|
||||
# Web Files
|
||||
[*.{htm,html,js,jsm,ts,tsx,css,sass,scss,less,pcss,svg,vue}]
|
||||
indent_size = 2
|
||||
|
||||
# Markdown Files
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
# JSON Files
|
||||
[*.{json,json5,webmanifest}]
|
||||
indent_size = 2
|
||||
1
.github/FUNDING.yml
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
custom: "https://fmodel.app/donate"
|
||||
45
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
name: Bug Report
|
||||
description: File a bug report
|
||||
title: "Bug Title"
|
||||
labels: [bug]
|
||||
assignees:
|
||||
- iAmAsval
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report! Keep in mind that screenshots and log files help us a lot so don't forget to provide one or both of those (drag and drop files in a text area).
|
||||
Your bug report will be closed without explanation if you don't follow the following rules:
|
||||
- Bad bug explanation will result in bad support and probably on a negative tone
|
||||
- This template shouldn't be used to ask how to use FModel or a certain feature FModel provides
|
||||
- Bug reports must always use the latest FModel with the latest available version of the game you use
|
||||
- If you can't load files, it's probably because of your AES key, no need to file a report
|
||||
- We absolutely do not support modding
|
||||
- type: input
|
||||
id: game
|
||||
attributes:
|
||||
label: Game
|
||||
placeholder: ex. Fortnite, Valorant, ...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: error
|
||||
attributes:
|
||||
label: Error
|
||||
description: Tell us what FModel says about the error, from the console and / or the log file
|
||||
placeholder: ex. [ERR] Could not export 'EditorClientAssetRegistry.bin'
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: repro
|
||||
attributes:
|
||||
label: Reproduction steps
|
||||
description: How do you trigger this bug? Please walk us through it step by step.
|
||||
placeholder: |
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
...
|
||||
validations:
|
||||
required: true
|
||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Discord Server
|
||||
url: https://fmodel.app/discord
|
||||
about: Please ask and answer questions here.
|
||||
22
.github/ISSUE_TEMPLATE/feature.yml
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
name: Feature Request
|
||||
description: Submit a new feature request
|
||||
title: "Feature Title"
|
||||
labels: [suggestion]
|
||||
assignees:
|
||||
- iAmAsval
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this feature request! Before going any further, make sure what you're about to submit doesn't already exist.
|
||||
Your feature request will be closed without explanation if you don't follow the following rules:
|
||||
- This template shouldn't be used to ask how to use FModel or a certain feature FModel provides
|
||||
- We absolutely do not support modding
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: Tell us what you want FModel to be able to do
|
||||
placeholder: Please describe with details and how it could be done if possible...
|
||||
validations:
|
||||
required: true
|
||||
48
.github/workflows/main.yml
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
name: FModel Builder
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
appVersion:
|
||||
description: 'FModel Version And Release Tag'
|
||||
required: true
|
||||
default: '4.0.X.X'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: GIT Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
|
||||
- name: Fetch Submodules Recursively
|
||||
run: git submodule update --init --recursive
|
||||
|
||||
- name: .NET 8 Setup
|
||||
uses: actions/setup-dotnet@v2
|
||||
with:
|
||||
dotnet-version: '8.0.x'
|
||||
|
||||
- name: .NET Restore
|
||||
run: dotnet restore FModel
|
||||
|
||||
- name: .NET Publish
|
||||
run: dotnet publish FModel -c Release --no-self-contained -r win-x64 -f net8.0-windows -o "./FModel/bin/Publish/" -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:DebugType=None -p:GenerateDocumentationFile=false -p:DebugSymbols=false -p:AssemblyVersion=${{ github.event.inputs.appVersion }} -p:FileVersion=${{ github.event.inputs.appVersion }}
|
||||
|
||||
- name: ZIP File
|
||||
uses: papeloto/action-zip@v1
|
||||
with:
|
||||
files: ./FModel/bin/Publish/FModel.exe
|
||||
dest: FModel.zip # will end up in working directory not the Publish folder
|
||||
|
||||
- name: GIT Release
|
||||
uses: marvinpinto/action-automatic-releases@latest
|
||||
with:
|
||||
title: "FModel v${{ github.event.inputs.appVersion }}"
|
||||
automatic_release_tag: ${{ github.event.inputs.appVersion }}
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
prerelease: false
|
||||
files: FModel.zip
|
||||
65
.github/workflows/qa.yml
vendored
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
name: FModel QA Builder
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ dev ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: GIT Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: .NET 8 Setup
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: '8.0.x'
|
||||
|
||||
- name: .NET Restore
|
||||
run: dotnet restore FModel
|
||||
|
||||
- name: .NET Publish
|
||||
run: dotnet publish "./FModel/FModel.csproj" -c Release --no-restore --no-self-contained -r win-x64 -f net8.0-windows -o "./FModel/bin/Publish/" -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:DebugType=None -p:GenerateDocumentationFile=false -p:DebugSymbols=false
|
||||
|
||||
- name: ZIP File
|
||||
uses: thedoctor0/zip-release@0.7.6
|
||||
with:
|
||||
type: zip
|
||||
filename: ${{ github.sha }}.zip # will end up in working directory not the Publish folder
|
||||
path: ./FModel/bin/Publish/FModel.exe
|
||||
|
||||
- name: Edit QA Artifact
|
||||
uses: ncipollo/release-action@v1.14.0
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: 'FModel QA Testing'
|
||||
body: 'Dev builds'
|
||||
tag: 'qa'
|
||||
artifacts: ${{ github.sha }}.zip
|
||||
prerelease: true
|
||||
allowUpdates: true
|
||||
|
||||
- name: Get Version
|
||||
id: package_version
|
||||
uses: kzrnm/get-net-sdk-project-versions-action@v2
|
||||
with:
|
||||
proj-path: ./FModel/FModel.csproj
|
||||
|
||||
- name: FModel Auth
|
||||
id: fmodel_auth
|
||||
uses: fjogeleit/http-request-action@v1.15.5
|
||||
with:
|
||||
url: "https://api.fmodel.app/v1/oauth/token"
|
||||
data: '{"username": "${{ secrets.API_USERNAME }}", "password": "${{ secrets.API_PASSWORD }}"}'
|
||||
|
||||
- name: FModel Deploy Build
|
||||
uses: fjogeleit/http-request-action@v1.15.5
|
||||
with:
|
||||
url: "https://api.fmodel.app/v1/infos/${{ secrets.QA_ID }}"
|
||||
method: "PATCH"
|
||||
bearerToken: ${{ fromJson(steps.fmodel_auth.outputs.response).accessToken }}
|
||||
data: '{"version": "${{ steps.package_version.outputs.version }}-dev+${{ github.sha }}", "downloadUrl": "https://github.com/4sval/FModel/releases/download/qa/${{ github.sha }}.zip"}'
|
||||
53
.gitignore
vendored
|
|
@ -4,6 +4,7 @@
|
|||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
|
|
@ -12,6 +13,9 @@
|
|||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Mono auto generated files
|
||||
mono_crash.*
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
|
|
@ -19,13 +23,17 @@
|
|||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
.idea/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
|
|
@ -36,9 +44,10 @@ Generated\ Files/
|
|||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUNIT
|
||||
# NUnit
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
nunit-*.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
|
|
@ -52,7 +61,6 @@ BenchmarkDotNet.Artifacts/
|
|||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
**/Properties/launchSettings.json
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
|
@ -60,7 +68,7 @@ StyleCopReport.xml
|
|||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
|
|
@ -77,6 +85,7 @@ StyleCopReport.xml
|
|||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
|
|
@ -119,9 +128,6 @@ _ReSharper*/
|
|||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding add-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
|
|
@ -179,6 +185,8 @@ PublishScripts/
|
|||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# NuGet Symbol Packages
|
||||
*.snupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
|
|
@ -203,12 +211,14 @@ BundleArtifacts/
|
|||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
*.appxbundle
|
||||
*.appxupload
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
|
|
@ -221,7 +231,7 @@ ClientBin/
|
|||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
|
|
@ -252,6 +262,9 @@ ServiceFabricBackup/
|
|||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- [Bb]ackup.rdl
|
||||
*- [Bb]ackup ([0-9]).rdl
|
||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
|
@ -287,12 +300,8 @@ paket-files/
|
|||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# JetBrains Rider
|
||||
.idea/
|
||||
*.sln.iml
|
||||
|
||||
# CodeRush
|
||||
.cr/
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
|
|
@ -317,7 +326,7 @@ __pycache__/
|
|||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
|
|
@ -326,5 +335,17 @@ ASALocalRun/
|
|||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||
MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
|
|
|
|||
3
.gitmodules
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[submodule "CUE4Parse"]
|
||||
path = CUE4Parse
|
||||
url = https://github.com/FabianFG/CUE4Parse
|
||||
1
CUE4Parse
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 455b72e5e38bfe9476b5823bc642fc8ef488347f
|
||||
25
FModel.sln
|
|
@ -1,25 +0,0 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.28307.136
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FModel", "FModel\FModel.csproj", "{71A31C47-30BC-4CB5-AD89-81E5008F4BEB}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{71A31C47-30BC-4CB5-AD89-81E5008F4BEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{71A31C47-30BC-4CB5-AD89-81E5008F4BEB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{71A31C47-30BC-4CB5-AD89-81E5008F4BEB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{71A31C47-30BC-4CB5-AD89-81E5008F4BEB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {CBD904D1-57AE-4FCF-B773-F675B4C3C0A6}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
|
||||
<section name="FModel.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
|
||||
</startup>
|
||||
<userSettings>
|
||||
<FModel.Properties.Settings>
|
||||
<setting name="ExtractOutput" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
<setting name="FortnitePAKs" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
<setting name="mergerFileName" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
<setting name="mergerImagesRow" serializeAs="String">
|
||||
<value>0</value>
|
||||
</setting>
|
||||
<setting name="createIconForCosmetics" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="createIconForConsumablesWeapons" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="createIconForTraps" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="createIconForVariants" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="createIconForChallenges" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="IconName" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
</FModel.Properties.Settings>
|
||||
</userSettings>
|
||||
</configuration>
|
||||
19
FModel/App.xaml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<Application x:Class="FModel.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:adonisUi="clr-namespace:AdonisUI;assembly=AdonisUI"
|
||||
StartupUri="MainWindow.xaml" ShutdownMode="OnMainWindowClose"
|
||||
Exit="AppExit" DispatcherUnhandledException="OnUnhandledException">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/AdonisUI;component/ColorSchemes/Dark.xaml"/>
|
||||
<ResourceDictionary Source="pack://application:,,,/AdonisUI.ClassicTheme;component/Resources.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<Color x:Key="{x:Static adonisUi:Colors.AccentColor}">#206BD4</Color>
|
||||
<Color x:Key="{x:Static adonisUi:Colors.AlertColor}">#D49220</Color>
|
||||
<Color x:Key="{x:Static adonisUi:Colors.ErrorColor}">#C22B2B</Color>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
178
FModel/App.xaml.cs
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
using AdonisUI.Controls;
|
||||
using Microsoft.Win32;
|
||||
using Serilog;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
using FModel.Framework;
|
||||
using FModel.Services;
|
||||
using FModel.Settings;
|
||||
using Newtonsoft.Json;
|
||||
using Serilog.Sinks.SystemConsole.Themes;
|
||||
using MessageBox = AdonisUI.Controls.MessageBox;
|
||||
using MessageBoxImage = AdonisUI.Controls.MessageBoxImage;
|
||||
using MessageBoxResult = AdonisUI.Controls.MessageBoxResult;
|
||||
|
||||
namespace FModel;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App
|
||||
{
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern bool AttachConsole(int dwProcessId);
|
||||
|
||||
[DllImport("winbrand.dll", CharSet = CharSet.Unicode)]
|
||||
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
|
||||
static extern string BrandingFormatString(string format);
|
||||
|
||||
protected override void OnStartup(StartupEventArgs e)
|
||||
{
|
||||
#if DEBUG
|
||||
AttachConsole(-1);
|
||||
#endif
|
||||
base.OnStartup(e);
|
||||
|
||||
try
|
||||
{
|
||||
UserSettings.Default = JsonConvert.DeserializeObject<UserSettings>(
|
||||
File.ReadAllText(UserSettings.FilePath), JsonNetSerializer.SerializerSettings);
|
||||
}
|
||||
catch
|
||||
{
|
||||
UserSettings.Default = new UserSettings();
|
||||
}
|
||||
|
||||
var createMe = false;
|
||||
if (!Directory.Exists(UserSettings.Default.OutputDirectory))
|
||||
{
|
||||
var currentDir = Directory.GetCurrentDirectory();
|
||||
var dirInfo = new DirectoryInfo(currentDir);
|
||||
if (dirInfo.Attributes.HasFlag(FileAttributes.Archive))
|
||||
throw new Exception("FModel cannot be run from an archive file. Please extract it and try again.");
|
||||
if (dirInfo.Attributes.HasFlag(FileAttributes.ReadOnly))
|
||||
throw new Exception("FModel cannot be run from a read-only directory. Please move it to a writable location.");
|
||||
|
||||
UserSettings.Default.OutputDirectory = Path.Combine(currentDir, "Output");
|
||||
}
|
||||
|
||||
if (!Directory.Exists(UserSettings.Default.RawDataDirectory))
|
||||
{
|
||||
createMe = true;
|
||||
UserSettings.Default.RawDataDirectory = Path.Combine(UserSettings.Default.OutputDirectory, "Exports");
|
||||
}
|
||||
|
||||
if (!Directory.Exists(UserSettings.Default.PropertiesDirectory))
|
||||
{
|
||||
createMe = true;
|
||||
UserSettings.Default.PropertiesDirectory = Path.Combine(UserSettings.Default.OutputDirectory, "Exports");
|
||||
}
|
||||
|
||||
if (!Directory.Exists(UserSettings.Default.TextureDirectory))
|
||||
{
|
||||
createMe = true;
|
||||
UserSettings.Default.TextureDirectory = Path.Combine(UserSettings.Default.OutputDirectory, "Exports");
|
||||
}
|
||||
|
||||
if (!Directory.Exists(UserSettings.Default.AudioDirectory))
|
||||
{
|
||||
createMe = true;
|
||||
UserSettings.Default.AudioDirectory = Path.Combine(UserSettings.Default.OutputDirectory, "Exports");
|
||||
}
|
||||
|
||||
if (!Directory.Exists(UserSettings.Default.ModelDirectory))
|
||||
{
|
||||
createMe = true;
|
||||
UserSettings.Default.ModelDirectory = Path.Combine(UserSettings.Default.OutputDirectory, "Exports");
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "FModel"));
|
||||
Directory.CreateDirectory(Path.Combine(UserSettings.Default.OutputDirectory, "Backups"));
|
||||
if (createMe) Directory.CreateDirectory(Path.Combine(UserSettings.Default.OutputDirectory, "Exports"));
|
||||
Directory.CreateDirectory(Path.Combine(UserSettings.Default.OutputDirectory, "Logs"));
|
||||
Directory.CreateDirectory(Path.Combine(UserSettings.Default.OutputDirectory, ".data"));
|
||||
|
||||
#if DEBUG
|
||||
Log.Logger = new LoggerConfiguration().WriteTo.Console(theme: AnsiConsoleTheme.Literate).WriteTo.File(
|
||||
Path.Combine(UserSettings.Default.OutputDirectory, "Logs", $"FModel-Debug-Log-{DateTime.Now:yyyy-MM-dd}.txt"),
|
||||
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [FModel] [{Level:u3}] {Message:lj}{NewLine}{Exception}").CreateLogger();
|
||||
#else
|
||||
Log.Logger = new LoggerConfiguration().WriteTo.Console(theme: AnsiConsoleTheme.Literate).WriteTo.File(
|
||||
Path.Combine(UserSettings.Default.OutputDirectory, "Logs", $"FModel-Log-{DateTime.Now:yyyy-MM-dd}.txt"),
|
||||
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [FModel] [{Level:u3}] {Message:lj}{NewLine}{Exception}").CreateLogger();
|
||||
#endif
|
||||
|
||||
Log.Information("Version {Version} ({CommitId})", Constants.APP_VERSION, Constants.APP_COMMIT_ID);
|
||||
Log.Information("{OS}", GetOperatingSystemProductName());
|
||||
Log.Information("{RuntimeVer}", RuntimeInformation.FrameworkDescription);
|
||||
Log.Information("Culture {SysLang}", CultureInfo.CurrentCulture);
|
||||
}
|
||||
|
||||
private void AppExit(object sender, ExitEventArgs e)
|
||||
{
|
||||
Log.Information("––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––");
|
||||
Log.CloseAndFlush();
|
||||
UserSettings.Save();
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
private void OnUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
|
||||
{
|
||||
Log.Error("{Exception}", e.Exception);
|
||||
|
||||
var messageBox = new MessageBoxModel
|
||||
{
|
||||
Text = $"An unhandled exception occurred: {e.Exception.Message}",
|
||||
Caption = "Fatal Error",
|
||||
Icon = MessageBoxImage.Error,
|
||||
Buttons = new[]
|
||||
{
|
||||
MessageBoxButtons.Custom("Reset Settings", EErrorKind.ResetSettings),
|
||||
MessageBoxButtons.Custom("Restart", EErrorKind.Restart),
|
||||
MessageBoxButtons.Custom("OK", EErrorKind.Ignore)
|
||||
},
|
||||
IsSoundEnabled = false
|
||||
};
|
||||
|
||||
MessageBox.Show(messageBox);
|
||||
if (messageBox.Result == MessageBoxResult.Custom && (EErrorKind) messageBox.ButtonPressed.Id != EErrorKind.Ignore)
|
||||
{
|
||||
if ((EErrorKind) messageBox.ButtonPressed.Id == EErrorKind.ResetSettings)
|
||||
UserSettings.Delete();
|
||||
|
||||
ApplicationService.ApplicationView.Restart();
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private string GetOperatingSystemProductName()
|
||||
{
|
||||
var productName = string.Empty;
|
||||
try
|
||||
{
|
||||
productName = BrandingFormatString("%WINDOWS_LONG%");
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(productName))
|
||||
productName = Environment.OSVersion.VersionString;
|
||||
|
||||
return $"{productName} ({(Environment.Is64BitOperatingSystem ? "64" : "32")}-bit)";
|
||||
}
|
||||
|
||||
public static string GetRegistryValue(string path, string name = null, RegistryHive root = RegistryHive.CurrentUser)
|
||||
{
|
||||
using var rk = RegistryKey.OpenBaseKey(root, RegistryView.Default).OpenSubKey(path);
|
||||
if (rk != null)
|
||||
return rk.GetValue(name, null) as string;
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
10
FModel/AssemblyInfo.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
using System.Windows;
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||
//(used if a resource is not found in the page,
|
||||
// or application resource dictionaries)
|
||||
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||
//(used if a resource is not found in the page,
|
||||
// app, or any theme specific resource dictionaries)
|
||||
)]
|
||||
57
FModel/Constants.cs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
using CUE4Parse.UE4.Objects.Core.Misc;
|
||||
using FModel.Extensions;
|
||||
|
||||
namespace FModel;
|
||||
|
||||
public static class Constants
|
||||
{
|
||||
public static readonly string APP_PATH = Path.GetFullPath(Environment.GetCommandLineArgs()[0]);
|
||||
public static readonly string APP_VERSION = FileVersionInfo.GetVersionInfo(APP_PATH).FileVersion;
|
||||
public static readonly string APP_COMMIT_ID = FileVersionInfo.GetVersionInfo(APP_PATH).ProductVersion.SubstringAfter('+');
|
||||
public static readonly string APP_SHORT_COMMIT_ID = APP_COMMIT_ID[..7];
|
||||
|
||||
public const string ZERO_64_CHAR = "0000000000000000000000000000000000000000000000000000000000000000";
|
||||
public static readonly FGuid ZERO_GUID = new(0U);
|
||||
|
||||
public const float SCALE_DOWN_RATIO = 0.01F;
|
||||
public const int SAMPLES_COUNT = 4;
|
||||
|
||||
public const string WHITE = "#DAE5F2";
|
||||
public const string GRAY = "#BBBBBB";
|
||||
public const string RED = "#E06C75";
|
||||
public const string GREEN = "#98C379";
|
||||
public const string YELLOW = "#E5C07B";
|
||||
public const string BLUE = "#528BCC";
|
||||
|
||||
public const string ISSUE_LINK = "https://github.com/4sval/FModel/discussions/categories/q-a";
|
||||
public const string GH_REPO = "https://api.github.com/repos/4sval/FModel";
|
||||
public const string GH_COMMITS_HISTORY = GH_REPO + "/commits";
|
||||
public const string GH_RELEASES = GH_REPO + "/releases";
|
||||
public const string DONATE_LINK = "https://fmodel.app/donate";
|
||||
public const string DISCORD_LINK = "https://fmodel.app/discord";
|
||||
|
||||
public const string _FN_LIVE_TRIGGER = "fortnite-live.manifest";
|
||||
public const string _VAL_LIVE_TRIGGER = "valorant-live.manifest";
|
||||
|
||||
public const string _NO_PRESET_TRIGGER = "Hand Made";
|
||||
|
||||
public static int PALETTE_LENGTH => COLOR_PALETTE.Length;
|
||||
public static readonly Vector3[] COLOR_PALETTE =
|
||||
{
|
||||
new (0.231f, 0.231f, 0.231f), // Dark gray
|
||||
new (0.376f, 0.490f, 0.545f), // Teal
|
||||
new (0.957f, 0.263f, 0.212f), // Red
|
||||
new (0.196f, 0.804f, 0.196f), // Green
|
||||
new (0.957f, 0.647f, 0.212f), // Orange
|
||||
new (0.612f, 0.153f, 0.690f), // Purple
|
||||
new (0.129f, 0.588f, 0.953f), // Blue
|
||||
new (1.000f, 0.920f, 0.424f), // Yellow
|
||||
new (0.824f, 0.412f, 0.118f), // Brown
|
||||
new (0.612f, 0.800f, 0.922f) // Light blue
|
||||
};
|
||||
}
|
||||
42
FModel/Creator/Bases/BB/BaseBreakersIcon.cs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Objects.Core.i18N;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using FModel.Creator.Bases.FN;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace FModel.Creator.Bases.BB;
|
||||
|
||||
public class BaseBreakersIcon : BaseIcon
|
||||
{
|
||||
public BaseBreakersIcon(UObject uObject, EIconStyle style) : base(uObject, style)
|
||||
{
|
||||
SeriesBackground = Utils.GetBitmap("WorldExplorers/Content/UMG/Materials/t_TextGradient.t_TextGradient");
|
||||
Background = new[] { SKColor.Parse("D0D0D0"), SKColor.Parse("636363") };
|
||||
Border = new[] { SKColor.Parse("D0D0D0"), SKColor.Parse("FFFFFF") };
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
if (Object.TryGetValue(out FSoftObjectPath iconTextureAssetData, "IconTextureAssetData", "UnlockPortraitGuideImage"))
|
||||
Preview = Utils.GetBitmap(iconTextureAssetData);
|
||||
|
||||
if (Object.TryGetValue(out FText displayName, "DisplayName", "RegionDisplayName", "ZoneName"))
|
||||
DisplayName = displayName.Text;
|
||||
if (Object.TryGetValue(out FText description, "Description", "RegionShortName", "ZoneDescription"))
|
||||
Description = description.Text;
|
||||
}
|
||||
|
||||
public override SKBitmap[] Draw()
|
||||
{
|
||||
var ret = new SKBitmap(Width, Height, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
using var c = new SKCanvas(ret);
|
||||
|
||||
DrawBackground(c);
|
||||
DrawPreview(c);
|
||||
DrawTextBackground(c);
|
||||
DrawDisplayName(c);
|
||||
DrawDescription(c);
|
||||
|
||||
return new[] { ret };
|
||||
}
|
||||
}
|
||||
139
FModel/Creator/Bases/FN/BaseBundle.cs
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
using System.Collections.Generic;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Assets.Objects;
|
||||
using CUE4Parse.UE4.Objects.Core.i18N;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using FModel.Extensions;
|
||||
using FModel.Framework;
|
||||
using SkiaSharp;
|
||||
using SkiaSharp.HarfBuzz;
|
||||
|
||||
namespace FModel.Creator.Bases.FN;
|
||||
|
||||
public class BaseBundle : UCreator
|
||||
{
|
||||
private IList<BaseQuest> _quests;
|
||||
private const int _headerHeight = 100;
|
||||
|
||||
public BaseBundle(UObject uObject, EIconStyle style) : base(uObject, style)
|
||||
{
|
||||
Width = 1024;
|
||||
Height = _headerHeight;
|
||||
Margin = 0;
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
_quests = new List<BaseQuest>();
|
||||
|
||||
if (Object.TryGetValue(out FText displayName, "DisplayName", "ItemName"))
|
||||
DisplayName = displayName.Text.ToUpperInvariant();
|
||||
|
||||
if (Object.TryGetValue(out FStructFallback[] quests, "QuestInfos")) // prout :)
|
||||
{
|
||||
foreach (var quest in quests)
|
||||
{
|
||||
if (!quest.TryGetValue(out FSoftObjectPath questDefinition, "QuestDefinition")) continue;
|
||||
|
||||
BaseQuest q;
|
||||
var path = questDefinition.AssetPathName.Text;
|
||||
do
|
||||
{
|
||||
if (!Utils.TryLoadObject(path, out UObject uObject)) break;
|
||||
|
||||
q = new BaseQuest(uObject, Style);
|
||||
q.ParseForInfo();
|
||||
_quests.Add(q);
|
||||
path = path.SubstringBeforeWithLast('/') + q.NextQuestName + "." + q.NextQuestName;
|
||||
} while (!string.IsNullOrEmpty(q.NextQuestName));
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.TryGetValue(out FStructFallback[] completionRewards, "BundleCompletionRewards"))
|
||||
{
|
||||
foreach (var completionReward in completionRewards)
|
||||
{
|
||||
if (!completionReward.TryGetValue(out int completionCount, "CompletionCount") ||
|
||||
!completionReward.TryGetValue(out FStructFallback[] rewards, "Rewards")) continue;
|
||||
|
||||
foreach (var reward in rewards)
|
||||
{
|
||||
if (!reward.TryGetValue(out int quantity, "Quantity") ||
|
||||
!reward.TryGetValue(out string templateId, "TemplateId") ||
|
||||
!reward.TryGetValue(out FSoftObjectPath itemDefinition, "ItemDefinition")) continue;
|
||||
|
||||
if (!itemDefinition.AssetPathName.IsNone &&
|
||||
!itemDefinition.AssetPathName.Text.Contains("/Items/Tokens/") &&
|
||||
!itemDefinition.AssetPathName.Text.Contains("/Items/Quests"))
|
||||
{
|
||||
_quests.Add(new BaseQuest(completionCount, itemDefinition, Style));
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(templateId))
|
||||
{
|
||||
_quests.Add(new BaseQuest(completionCount, quantity, templateId, Style));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Height += 256 * _quests.Count;
|
||||
}
|
||||
|
||||
public override SKBitmap[] Draw()
|
||||
{
|
||||
var ret = new SKBitmap(Width, Height, SKColorType.Rgba8888, SKAlphaType.Opaque);
|
||||
using var c = new SKCanvas(ret);
|
||||
|
||||
DrawHeader(c);
|
||||
DrawDisplayName(c);
|
||||
DrawQuests(c);
|
||||
|
||||
return new[] { ret };
|
||||
}
|
||||
|
||||
private readonly SKPaint _headerPaint = new()
|
||||
{
|
||||
IsAntialias = true, FilterQuality = SKFilterQuality.High,
|
||||
Typeface = Utils.Typefaces.Bundle, TextSize = 50,
|
||||
TextAlign = SKTextAlign.Center, Color = SKColor.Parse("#262630")
|
||||
};
|
||||
|
||||
private void DrawHeader(SKCanvas c)
|
||||
{
|
||||
c.DrawRect(new SKRect(0, 0, Width, _headerHeight), _headerPaint);
|
||||
|
||||
var background = _quests.Count > 0 ? _quests[0].Background : Background;
|
||||
_headerPaint.Shader = SKShader.CreateRadialGradient(new SKPoint(Width / 2, _headerHeight / 2), Width / 5 * 4,
|
||||
new[] { background[0].WithAlpha(50), background[1].WithAlpha(50) }, SKShaderTileMode.Clamp);
|
||||
c.DrawRect(new SKRect(0, 0, Width, _headerHeight), _headerPaint);
|
||||
|
||||
_headerPaint.Shader = SKShader.CreateLinearGradient(new SKPoint(Width / 2, _headerHeight), new SKPoint(Width / 2, 75),
|
||||
new[] { SKColors.Black.WithAlpha(25), background[1].WithAlpha(0) }, SKShaderTileMode.Clamp);
|
||||
c.DrawRect(new SKRect(0, 75, Width, _headerHeight), _headerPaint);
|
||||
}
|
||||
|
||||
private new void DrawDisplayName(SKCanvas c)
|
||||
{
|
||||
if (string.IsNullOrEmpty(DisplayName)) return;
|
||||
|
||||
_headerPaint.Shader = null;
|
||||
_headerPaint.Color = SKColors.White;
|
||||
while (_headerPaint.MeasureText(DisplayName) > Width)
|
||||
{
|
||||
_headerPaint.TextSize -= 1;
|
||||
}
|
||||
|
||||
var shaper = new CustomSKShaper(_headerPaint.Typeface);
|
||||
c.DrawShapedText(shaper, DisplayName, Width / 2f, _headerHeight / 2f + _headerPaint.TextSize / 2 - 10, _headerPaint);
|
||||
}
|
||||
|
||||
private void DrawQuests(SKCanvas c)
|
||||
{
|
||||
var y = _headerHeight;
|
||||
foreach (var quest in _quests)
|
||||
{
|
||||
quest.DrawQuest(c, y);
|
||||
y += quest.Height;
|
||||
}
|
||||
}
|
||||
}
|
||||
278
FModel/Creator/Bases/FN/BaseCommunity.cs
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
using System.Linq;
|
||||
using CUE4Parse.GameTypes.FN.Enums;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Assets.Objects;
|
||||
using CUE4Parse.UE4.Objects.GameplayTags;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using CUE4Parse.UE4.Versions;
|
||||
using FModel.Extensions;
|
||||
using FModel.Framework;
|
||||
using FModel.Services;
|
||||
using FModel.Settings;
|
||||
using FModel.ViewModels.ApiEndpoints.Models;
|
||||
using SkiaSharp;
|
||||
using SkiaSharp.HarfBuzz;
|
||||
|
||||
namespace FModel.Creator.Bases.FN;
|
||||
|
||||
public class BaseCommunity : BaseIcon
|
||||
{
|
||||
private readonly CommunityDesign _design;
|
||||
private string _rarityName;
|
||||
private string _source;
|
||||
private string _season;
|
||||
private bool _lowerDrawn;
|
||||
|
||||
public BaseCommunity(UObject uObject, EIconStyle style, string designName) : base(uObject, style)
|
||||
{
|
||||
Margin = 0;
|
||||
_lowerDrawn = false;
|
||||
_design = ApplicationService.ApiEndpointView.FModelApi.GetDesign(designName);
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
ParseForReward(UserSettings.Default.CosmeticDisplayAsset);
|
||||
|
||||
if (Object.TryGetValue(out FPackageIndex series, "Series"))
|
||||
{
|
||||
_rarityName = series.Name;
|
||||
}
|
||||
else if (Object.TryGetValue(out FInstancedStruct[] dataList, "DataList") &&
|
||||
dataList.FirstOrDefault(d => d.NonConstStruct?.TryGetValue(out FPackageIndex _, "Series") == true) is { } dl)
|
||||
{
|
||||
_rarityName = dl.NonConstStruct?.Get<FPackageIndex>("Series").Name;
|
||||
}
|
||||
else if (Object.TryGetValue(out FStructFallback componentContainer, "ComponentContainer") &&
|
||||
componentContainer.TryGetValue(out FPackageIndex[] components, "Components") &&
|
||||
components.FirstOrDefault(c => c.Name.Contains("Series")) is { } seriesDef &&
|
||||
seriesDef.TryLoad(out var seriesDefObj) && seriesDefObj is not null &&
|
||||
seriesDefObj.TryGetValue(out series, "Series"))
|
||||
{
|
||||
_rarityName = series.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
_rarityName = Object.GetOrDefault("Rarity", EFortRarity.Uncommon).GetDescription();
|
||||
}
|
||||
|
||||
if (Object.TryGetValue(out FGameplayTagContainer gameplayTags, "GameplayTags"))
|
||||
CheckGameplayTags(gameplayTags);
|
||||
if (Object.TryGetValue(out FPackageIndex cosmeticItem, "cosmetic_item"))
|
||||
CosmeticSource = cosmeticItem.Name.ToUpper();
|
||||
|
||||
DisplayName = DisplayName.ToUpper();
|
||||
Description = Description.ToUpper();
|
||||
}
|
||||
|
||||
public override SKBitmap[] Draw()
|
||||
{
|
||||
var ret = new SKBitmap(Width, Height, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
using var c = new SKCanvas(ret);
|
||||
|
||||
if (_design == null)
|
||||
{
|
||||
base.Draw(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawBackground(c);
|
||||
DrawPreview(c);
|
||||
DrawTextBackground(c);
|
||||
DrawDisplayName(c);
|
||||
DrawDescription(c);
|
||||
if (_design.DrawSeason && _design.Fonts.TryGetValue("Season", out var font))
|
||||
DrawToBottom(c, font, _season);
|
||||
if (_design.DrawSource && _design.Fonts.TryGetValue("Source", out font))
|
||||
DrawToBottom(c, font, _source);
|
||||
DrawUserFacingFlags(c, _design.GameplayTags.DrawCustomOnly);
|
||||
}
|
||||
|
||||
return new[] { ret };
|
||||
}
|
||||
|
||||
private void CheckGameplayTags(FGameplayTagContainer gameplayTags)
|
||||
{
|
||||
if (_design == null) return;
|
||||
if (_design.DrawSource)
|
||||
{
|
||||
if (gameplayTags.TryGetGameplayTag("Cosmetics.Source.", out var source))
|
||||
_source = source.Text["Cosmetics.Source.".Length..].ToUpper();
|
||||
else if (gameplayTags.TryGetGameplayTag("Athena.ItemAction.", out var action))
|
||||
_source = action.Text["Athena.ItemAction.".Length..].ToUpper();
|
||||
}
|
||||
|
||||
if (_design.DrawSet && gameplayTags.TryGetGameplayTag("Cosmetics.Set.", out var set))
|
||||
Description += GetCosmeticSet(set.Text, _design.DrawSetShort);
|
||||
if (_design.DrawSeason && gameplayTags.TryGetGameplayTag("Cosmetics.Filter.Season.", out var season))
|
||||
_season = GetCosmeticSeason(season.Text, _design.DrawSeasonShort);
|
||||
|
||||
var triggers = _design.GameplayTags.DrawCustomOnly ? new[] { "Cosmetics.UserFacingFlags." } : new[] { "Cosmetics.UserFacingFlags.", "Homebase.Class.", "NPC.CharacterType.Survivor.Defender." };
|
||||
GetUserFacingFlags(gameplayTags.GetAllGameplayTags(triggers));
|
||||
}
|
||||
|
||||
private string GetCosmeticSet(string setName, bool bShort)
|
||||
{
|
||||
return bShort ? setName["Cosmetics.Set.".Length..] : base.GetCosmeticSet(setName);
|
||||
}
|
||||
|
||||
private string GetCosmeticSeason(string seasonNumber, bool bShort)
|
||||
{
|
||||
if (!bShort) return base.GetCosmeticSeason(seasonNumber);
|
||||
var s = seasonNumber["Cosmetics.Filter.Season.".Length..];
|
||||
(int chapterIdx, int seasonIdx) = GetInternalSID(int.Parse(s));
|
||||
return $"C{chapterIdx} S{seasonIdx}";
|
||||
}
|
||||
|
||||
private new void DrawBackground(SKCanvas c)
|
||||
{
|
||||
if (_design.Rarities.TryGetValue(_rarityName, out var rarity))
|
||||
{
|
||||
c.DrawBitmap(rarity.Background, 0, 0, ImagePaint);
|
||||
c.DrawBitmap(rarity.Upper, 0, 0, ImagePaint);
|
||||
}
|
||||
else
|
||||
{
|
||||
base.DrawBackground(c);
|
||||
}
|
||||
}
|
||||
|
||||
private new void DrawTextBackground(SKCanvas c)
|
||||
{
|
||||
if (!_lowerDrawn && string.IsNullOrEmpty(DisplayName) && string.IsNullOrEmpty(Description)) return;
|
||||
|
||||
_lowerDrawn = true;
|
||||
if (_design.Rarities.TryGetValue(_rarityName, out var rarity))
|
||||
{
|
||||
c.DrawBitmap(rarity.Lower, 0, 0, ImagePaint);
|
||||
}
|
||||
else
|
||||
{
|
||||
base.DrawTextBackground(c);
|
||||
}
|
||||
}
|
||||
|
||||
private new void DrawDisplayName(SKCanvas c)
|
||||
{
|
||||
if (string.IsNullOrEmpty(DisplayName)) return;
|
||||
if (_design.Fonts.TryGetValue(nameof(DisplayName), out var font))
|
||||
{
|
||||
DisplayNamePaint.TextSize = font.FontSize;
|
||||
DisplayNamePaint.TextScaleX = font.FontScale;
|
||||
DisplayNamePaint.Color = font.FontColor;
|
||||
DisplayNamePaint.TextSkewX = font.SkewValue;
|
||||
DisplayNamePaint.TextAlign = font.Alignment;
|
||||
if (font.ShadowValue > 0)
|
||||
DisplayNamePaint.ImageFilter = SKImageFilter.CreateDropShadow(2, 2, 4, 4, new SKColor(0, 0, 0, font.ShadowValue));
|
||||
if (font.Typeface.TryGetValue(UserSettings.Default.AssetLanguage, out var path) ||
|
||||
font.Typeface.TryGetValue(ELanguage.English, out path))
|
||||
DisplayNamePaint.Typeface = Utils.Typefaces.OnTheFly(path);
|
||||
|
||||
while (DisplayNamePaint.MeasureText(DisplayName) > Width - Margin * 2)
|
||||
{
|
||||
DisplayNamePaint.TextSize -= 1;
|
||||
}
|
||||
|
||||
var shaper = new CustomSKShaper(DisplayNamePaint.Typeface);
|
||||
var x = font.Alignment switch
|
||||
{
|
||||
SKTextAlign.Center => Width / 2f,
|
||||
_ => font.X
|
||||
};
|
||||
|
||||
c.DrawShapedText(shaper, DisplayName, x, font.Y, DisplayNamePaint);
|
||||
}
|
||||
else
|
||||
{
|
||||
base.DrawDisplayName(c);
|
||||
}
|
||||
}
|
||||
|
||||
private new void DrawDescription(SKCanvas c)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Description)) return;
|
||||
if (_design.Fonts.TryGetValue(nameof(Description), out var font))
|
||||
{
|
||||
DescriptionPaint.TextSize = font.FontSize;
|
||||
DescriptionPaint.TextScaleX = font.FontScale;
|
||||
DescriptionPaint.Color = font.FontColor;
|
||||
DescriptionPaint.TextSkewX = font.SkewValue;
|
||||
DescriptionPaint.TextAlign = font.Alignment;
|
||||
if (font.ShadowValue > 0)
|
||||
DescriptionPaint.ImageFilter = SKImageFilter.CreateDropShadow(2, 2, 4, 4, new SKColor(0, 0, 0, font.ShadowValue));
|
||||
if (font.Typeface.TryGetValue(UserSettings.Default.AssetLanguage, out var path) ||
|
||||
font.Typeface.TryGetValue(ELanguage.English, out path))
|
||||
DescriptionPaint.Typeface = Utils.Typefaces.OnTheFly(path);
|
||||
|
||||
while (DescriptionPaint.MeasureText(Description) > Width - Margin * 2)
|
||||
{
|
||||
DescriptionPaint.TextSize -= 1;
|
||||
}
|
||||
|
||||
var shaper = new CustomSKShaper(DescriptionPaint.Typeface);
|
||||
var x = font.Alignment switch
|
||||
{
|
||||
SKTextAlign.Center => Width / 2f,
|
||||
_ => font.X
|
||||
};
|
||||
|
||||
if (font.MaxLineCount < 2)
|
||||
{
|
||||
c.DrawShapedText(shaper, Description, x, font.Y, DescriptionPaint);
|
||||
}
|
||||
else
|
||||
{
|
||||
Utils.DrawMultilineText(c, Description, Width - Margin * 2, Margin, DescriptionPaint.TextAlign,
|
||||
new SKRect(Margin, font.Y, Width - Margin, Height), DescriptionPaint, out _);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
base.DrawDescription(c);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawToBottom(SKCanvas c, FontDesign font, string text)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text)) return;
|
||||
if (!_lowerDrawn)
|
||||
{
|
||||
_lowerDrawn = true;
|
||||
DrawTextBackground(c);
|
||||
}
|
||||
|
||||
DisplayNamePaint.TextSize = font.FontSize;
|
||||
DisplayNamePaint.TextScaleX = font.FontScale;
|
||||
DisplayNamePaint.Color = font.FontColor;
|
||||
DisplayNamePaint.TextSkewX = font.SkewValue;
|
||||
DisplayNamePaint.TextAlign = font.Alignment;
|
||||
if (font.ShadowValue > 0)
|
||||
DisplayNamePaint.ImageFilter = SKImageFilter.CreateDropShadow(2, 2, 4, 4, new SKColor(0, 0, 0, font.ShadowValue));
|
||||
if (font.Typeface.TryGetValue(UserSettings.Default.AssetLanguage, out var path) ||
|
||||
font.Typeface.TryGetValue(ELanguage.English, out path))
|
||||
DisplayNamePaint.Typeface = Utils.Typefaces.OnTheFly(path);
|
||||
|
||||
var shaper = new CustomSKShaper(DisplayNamePaint.Typeface);
|
||||
var x = font.Alignment switch
|
||||
{
|
||||
SKTextAlign.Center => Width / 2f,
|
||||
_ => font.X
|
||||
};
|
||||
|
||||
c.DrawShapedText(shaper, text, x, font.Y, DisplayNamePaint);
|
||||
}
|
||||
|
||||
private void DrawUserFacingFlags(SKCanvas c, bool customOnly)
|
||||
{
|
||||
if (UserFacingFlags == null || UserFacingFlags.Count < 1) return;
|
||||
if (customOnly)
|
||||
{
|
||||
c.DrawBitmap(_design.GameplayTags.Custom, 0, 0, ImagePaint);
|
||||
}
|
||||
else
|
||||
{
|
||||
// add size to api
|
||||
// draw
|
||||
}
|
||||
}
|
||||
}
|
||||
325
FModel/Creator/Bases/FN/BaseIcon.cs
Normal file
|
|
@ -0,0 +1,325 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using CUE4Parse.GameTypes.FN.Enums;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Assets.Exports.Engine;
|
||||
using CUE4Parse.UE4.Assets.Exports.Material;
|
||||
using CUE4Parse.UE4.Assets.Exports.Texture;
|
||||
using CUE4Parse.UE4.Assets.Objects;
|
||||
using CUE4Parse.UE4.Objects.Core.i18N;
|
||||
using CUE4Parse.UE4.Objects.Core.Math;
|
||||
using CUE4Parse.UE4.Objects.GameplayTags;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using CUE4Parse_Conversion.Textures;
|
||||
using FModel.Settings;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace FModel.Creator.Bases.FN;
|
||||
|
||||
public class BaseIcon : UCreator
|
||||
{
|
||||
public SKBitmap SeriesBackground { get; protected set; }
|
||||
protected string ShortDescription { get; set; }
|
||||
protected string CosmeticSource { get; set; }
|
||||
protected Dictionary<string, SKBitmap> UserFacingFlags { get; set; }
|
||||
|
||||
public BaseIcon(UObject uObject, EIconStyle style) : base(uObject, style) { }
|
||||
|
||||
public void ParseForReward(bool isUsingDisplayAsset)
|
||||
{
|
||||
// rarity
|
||||
if (Object.TryGetValue(out FPackageIndex series, "Series")) GetSeries(series);
|
||||
else if (Object.TryGetValue(out FStructFallback componentContainer, "ComponentContainer")) GetSeries(componentContainer);
|
||||
else GetRarity(Object.GetOrDefault("Rarity", EFortRarity.Uncommon)); // default is uncommon
|
||||
|
||||
if (Object.TryGetValue(out FInstancedStruct[] dataList, "DataList"))
|
||||
{
|
||||
GetSeries(dataList);
|
||||
Preview = Utils.GetBitmap(dataList);
|
||||
}
|
||||
|
||||
// preview
|
||||
if (Preview is null)
|
||||
{
|
||||
if (isUsingDisplayAsset && Utils.TryGetDisplayAsset(Object, out var preview))
|
||||
Preview = preview;
|
||||
else if (Object.TryGetValue(out FPackageIndex itemDefinition, "HeroDefinition", "WeaponDefinition"))
|
||||
Preview = Utils.GetBitmap(itemDefinition);
|
||||
else if (Object.TryGetValue(out FSoftObjectPath largePreview, "LargePreviewImage", "EntryListIcon", "SmallPreviewImage", "BundleImage", "ItemDisplayAsset", "LargeIcon", "ToastIcon", "SmallIcon"))
|
||||
Preview = Utils.GetBitmap(largePreview);
|
||||
else if (Object.TryGetValue(out string s, "LargePreviewImage") && !string.IsNullOrEmpty(s))
|
||||
Preview = Utils.GetBitmap(s);
|
||||
else if (Object.TryGetValue(out FPackageIndex otherPreview, "SmallPreviewImage", "ToastIcon", "access_item"))
|
||||
Preview = Utils.GetBitmap(otherPreview);
|
||||
else if (Object.TryGetValue(out UMaterialInstanceConstant materialInstancePreview, "EventCalloutImage"))
|
||||
Preview = Utils.GetBitmap(materialInstancePreview);
|
||||
else if (Object.TryGetValue(out FStructFallback brush, "IconBrush") && brush.TryGetValue(out UTexture2D res, "ResourceObject"))
|
||||
Preview = Utils.GetBitmap(res);
|
||||
}
|
||||
|
||||
// text
|
||||
if (Object.TryGetValue(out FText displayName, "DisplayName", "ItemName", "BundleName", "DefaultHeaderText", "UIDisplayName", "EntryName", "EventCalloutTitle"))
|
||||
DisplayName = displayName.Text;
|
||||
if (Object.TryGetValue(out FText description, "Description", "ItemDescription", "BundleDescription", "GeneralDescription", "DefaultBodyText", "UIDescription", "UIDisplayDescription", "EntryDescription", "EventCalloutDescription"))
|
||||
Description = description.Text;
|
||||
else if (Object.TryGetValue(out FText[] descriptions, "Description"))
|
||||
Description = string.Join('\n', descriptions.Select(x => x.Text));
|
||||
if (Object.TryGetValue(out FText shortDescription, "ShortDescription", "UIDisplaySubName"))
|
||||
ShortDescription = shortDescription.Text;
|
||||
else if (Object.ExportType.Equals("AthenaItemWrapDefinition", StringComparison.OrdinalIgnoreCase))
|
||||
ShortDescription = Utils.GetLocalizedResource("Fort.Cosmetics", "ItemWrapShortDescription", "Wrap");
|
||||
|
||||
// Only works on non-cataba designs
|
||||
if (Object.TryGetValue(out FStructFallback eventArrowColor, "EventArrowColor") &&
|
||||
eventArrowColor.TryGetValue(out FLinearColor specifiedArrowColor, "SpecifiedColor") &&
|
||||
Object.TryGetValue(out FStructFallback eventArrowShadowColor, "EventArrowShadowColor") &&
|
||||
eventArrowShadowColor.TryGetValue(out FLinearColor specifiedShadowColor, "SpecifiedColor"))
|
||||
{
|
||||
Background = new[] { SKColor.Parse(specifiedArrowColor.Hex), SKColor.Parse(specifiedShadowColor.Hex) };
|
||||
Border = new[] { SKColor.Parse(specifiedShadowColor.Hex), SKColor.Parse(specifiedArrowColor.Hex) };
|
||||
}
|
||||
|
||||
Description = Utils.RemoveHtmlTags(Description);
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
ParseForReward(UserSettings.Default.CosmeticDisplayAsset);
|
||||
|
||||
if (Object.TryGetValue(out FGameplayTagContainer gameplayTags, "GameplayTags"))
|
||||
CheckGameplayTags(gameplayTags);
|
||||
if (Object.TryGetValue(out FPackageIndex cosmeticItem, "cosmetic_item"))
|
||||
CosmeticSource = cosmeticItem.Name;
|
||||
}
|
||||
|
||||
protected void Draw(SKCanvas c)
|
||||
{
|
||||
switch (Style)
|
||||
{
|
||||
case EIconStyle.NoBackground:
|
||||
DrawPreview(c);
|
||||
break;
|
||||
case EIconStyle.NoText:
|
||||
DrawBackground(c);
|
||||
DrawPreview(c);
|
||||
DrawUserFacingFlags(c);
|
||||
break;
|
||||
default:
|
||||
DrawBackground(c);
|
||||
DrawPreview(c);
|
||||
DrawTextBackground(c);
|
||||
DrawDisplayName(c);
|
||||
DrawDescription(c);
|
||||
DrawToBottom(c, SKTextAlign.Right, CosmeticSource);
|
||||
if (Description != ShortDescription)
|
||||
DrawToBottom(c, SKTextAlign.Left, ShortDescription);
|
||||
DrawUserFacingFlags(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override SKBitmap[] Draw()
|
||||
{
|
||||
var ret = new SKBitmap(Width, Height, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
using var c = new SKCanvas(ret);
|
||||
|
||||
Draw(c);
|
||||
|
||||
return new[] { ret };
|
||||
}
|
||||
|
||||
private void GetSeries(FPackageIndex s)
|
||||
{
|
||||
if (!Utils.TryGetPackageIndexExport(s, out UObject export)) return;
|
||||
|
||||
GetSeries(export);
|
||||
}
|
||||
|
||||
private void GetSeries(FInstancedStruct[] s)
|
||||
{
|
||||
if (s.FirstOrDefault(d => d.NonConstStruct?.TryGetValue(out FPackageIndex _, "Series") == true) is { } dl)
|
||||
GetSeries(dl.NonConstStruct?.Get<FPackageIndex>("Series"));
|
||||
}
|
||||
|
||||
private void GetSeries(FStructFallback s)
|
||||
{
|
||||
if (!s.TryGetValue(out FPackageIndex[] components, "Components")) return;
|
||||
if (components.FirstOrDefault(c => c.Name.Contains("Series")) is not { } seriesDef ||
|
||||
!seriesDef.TryLoad(out var seriesDefObj) || seriesDefObj is null ||
|
||||
!seriesDefObj.TryGetValue(out UObject series, "Series")) return;
|
||||
|
||||
GetSeries(series);
|
||||
}
|
||||
|
||||
protected void GetSeries(UObject uObject)
|
||||
{
|
||||
if (uObject is UTexture2D texture2D)
|
||||
{
|
||||
SeriesBackground = texture2D.Decode();
|
||||
return;
|
||||
}
|
||||
|
||||
if (uObject.TryGetValue(out FSoftObjectPath backgroundTexture, "BackgroundTexture"))
|
||||
{
|
||||
SeriesBackground = Utils.GetBitmap(backgroundTexture);
|
||||
}
|
||||
|
||||
if (uObject.TryGetValue(out FStructFallback colors, "Colors") &&
|
||||
colors.TryGetValue(out FLinearColor color1, "Color1") &&
|
||||
colors.TryGetValue(out FLinearColor color2, "Color2") &&
|
||||
colors.TryGetValue(out FLinearColor color3, "Color3"))
|
||||
{
|
||||
Background = new[] { SKColor.Parse(color1.Hex), SKColor.Parse(color3.Hex) };
|
||||
Border = new[] { SKColor.Parse(color2.Hex), SKColor.Parse(color1.Hex) };
|
||||
}
|
||||
|
||||
if (uObject.Name.Equals("PlatformSeries") &&
|
||||
uObject.TryGetValue(out FSoftObjectPath itemCardMaterial, "ItemCardMaterial") &&
|
||||
Utils.TryLoadObject(itemCardMaterial.AssetPathName.Text, out UMaterialInstanceConstant material))
|
||||
{
|
||||
foreach (var vectorParameter in material.VectorParameterValues)
|
||||
{
|
||||
if (vectorParameter.ParameterValue == null || !vectorParameter.ParameterInfo.Name.Text.Equals("ColorCircuitBackground"))
|
||||
continue;
|
||||
|
||||
Background[0] = SKColor.Parse(vectorParameter.ParameterValue.Value.Hex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void GetRarity(EFortRarity r)
|
||||
{
|
||||
if (!Utils.TryLoadObject("FortniteGame/Content/Balance/RarityData.RarityData", out UObject export)) return;
|
||||
|
||||
if (export.GetByIndex<FStructFallback>((int) r) is { } data &&
|
||||
data.TryGetValue(out FLinearColor color1, "Color1") &&
|
||||
data.TryGetValue(out FLinearColor color2, "Color2") &&
|
||||
data.TryGetValue(out FLinearColor color3, "Color3"))
|
||||
{
|
||||
Background = new[] { SKColor.Parse(color1.Hex), SKColor.Parse(color3.Hex) };
|
||||
Border = new[] { SKColor.Parse(color2.Hex), SKColor.Parse(color1.Hex) };
|
||||
}
|
||||
}
|
||||
|
||||
protected string GetCosmeticSet(string setName)
|
||||
{
|
||||
if (!Utils.TryLoadObject("FortniteGame/Content/Athena/Items/Cosmetics/Metadata/CosmeticSets.CosmeticSets", out UDataTable cosmeticSets))
|
||||
return string.Empty;
|
||||
|
||||
if (!cosmeticSets.TryGetDataTableRow(setName, StringComparison.OrdinalIgnoreCase, out var uObject))
|
||||
return string.Empty;
|
||||
|
||||
var name = string.Empty;
|
||||
if (uObject.TryGetValue(out FText displayName, "DisplayName"))
|
||||
name = displayName.Text;
|
||||
|
||||
var format = Utils.GetLocalizedResource("Fort.Cosmetics", "CosmeticItemDescription_SetMembership_NotRich", "\nPart of the {0} set.");
|
||||
return string.Format(format, name);
|
||||
}
|
||||
|
||||
protected (int, int) GetInternalSID(int number)
|
||||
{
|
||||
static int GetSeasonsInChapter(int chapter) => chapter switch
|
||||
{
|
||||
1 => 10,
|
||||
2 => 8,
|
||||
3 => 4,
|
||||
4 => 5,
|
||||
_ => 10
|
||||
};
|
||||
|
||||
var chapterIdx = 0;
|
||||
var seasonIdx = 0;
|
||||
while (number > 0)
|
||||
{
|
||||
var seasonsInChapter = GetSeasonsInChapter(++chapterIdx);
|
||||
if (number > seasonsInChapter)
|
||||
number -= seasonsInChapter;
|
||||
else
|
||||
{
|
||||
seasonIdx = number;
|
||||
number = 0;
|
||||
}
|
||||
}
|
||||
return (chapterIdx, seasonIdx);
|
||||
}
|
||||
|
||||
protected string GetCosmeticSeason(string seasonNumber)
|
||||
{
|
||||
var s = seasonNumber["Cosmetics.Filter.Season.".Length..];
|
||||
var initial = int.Parse(s);
|
||||
(int chapterIdx, int seasonIdx) = GetInternalSID(initial);
|
||||
|
||||
var season = Utils.GetLocalizedResource("AthenaSeasonItemDefinitionInternal", "SeasonTextFormat", "Season {0}");
|
||||
var introduced = Utils.GetLocalizedResource("Fort.Cosmetics", "CosmeticItemDescription_Season", "\nIntroduced in <SeasonText>{0}</>.");
|
||||
if (initial <= 10) return Utils.RemoveHtmlTags(string.Format(introduced, string.Format(season, s)));
|
||||
|
||||
var chapter = Utils.GetLocalizedResource("AthenaSeasonItemDefinitionInternal", "ChapterTextFormat", "Chapter {0}");
|
||||
var chapterFormat = Utils.GetLocalizedResource("AthenaSeasonItemDefinitionInternal", "ChapterSeasonTextFormat", "{0}, {1}");
|
||||
var d = string.Format(chapterFormat, string.Format(chapter, chapterIdx), string.Format(season, seasonIdx));
|
||||
return Utils.RemoveHtmlTags(string.Format(introduced, d));
|
||||
}
|
||||
|
||||
private void CheckGameplayTags(FGameplayTagContainer gameplayTags)
|
||||
{
|
||||
if (gameplayTags.TryGetGameplayTag("Cosmetics.Source.", out var source))
|
||||
CosmeticSource = source.Text["Cosmetics.Source.".Length..];
|
||||
else if (gameplayTags.TryGetGameplayTag("Athena.ItemAction.", out var action))
|
||||
CosmeticSource = action.Text["Athena.ItemAction.".Length..];
|
||||
|
||||
if (gameplayTags.TryGetGameplayTag("Cosmetics.Set.", out var set))
|
||||
Description += GetCosmeticSet(set.Text);
|
||||
if (gameplayTags.TryGetGameplayTag("Cosmetics.Filter.Season.", out var season))
|
||||
Description += GetCosmeticSeason(season.Text);
|
||||
|
||||
GetUserFacingFlags(gameplayTags.GetAllGameplayTags(
|
||||
"Cosmetics.UserFacingFlags.", "Homebase.Class.", "NPC.CharacterType.Survivor.Defender."));
|
||||
}
|
||||
|
||||
protected void GetUserFacingFlags(IList<string> userFacingFlags)
|
||||
{
|
||||
if (userFacingFlags.Count < 1 || !Utils.TryLoadObject("FortniteGame/Content/Items/ItemCategories.ItemCategories", out UObject itemCategories))
|
||||
return;
|
||||
|
||||
if (!itemCategories.TryGetValue(out FStructFallback[] tertiaryCategories, "TertiaryCategories"))
|
||||
return;
|
||||
|
||||
UserFacingFlags = new Dictionary<string, SKBitmap>(userFacingFlags.Count);
|
||||
foreach (var flag in userFacingFlags)
|
||||
{
|
||||
if (flag.Equals("Cosmetics.UserFacingFlags.HasUpgradeQuests", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (Object.ExportType.Equals("AthenaPetCarrierItemDefinition", StringComparison.OrdinalIgnoreCase))
|
||||
UserFacingFlags[flag] = SKBitmap.Decode(Application.GetResourceStream(new Uri("pack://application:,,,/Resources/T-Icon-Pets-64.png"))?.Stream);
|
||||
else UserFacingFlags[flag] = SKBitmap.Decode(Application.GetResourceStream(new Uri("pack://application:,,,/Resources/T-Icon-Quests-64.png"))?.Stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var category in tertiaryCategories)
|
||||
{
|
||||
if (category.TryGetValue(out FGameplayTagContainer tagContainer, "TagContainer") && tagContainer.TryGetGameplayTag(flag, out _) &&
|
||||
category.TryGetValue(out FStructFallback categoryBrush, "CategoryBrush") && categoryBrush.TryGetValue(out FStructFallback brushXxs, "Brush_XXS") &&
|
||||
brushXxs.TryGetValue(out FPackageIndex resourceObject, "ResourceObject") && Utils.TryGetPackageIndexExport(resourceObject, out UTexture2D texture))
|
||||
{
|
||||
UserFacingFlags[flag] = Utils.GetBitmap(texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawUserFacingFlags(SKCanvas c)
|
||||
{
|
||||
if (UserFacingFlags == null) return;
|
||||
|
||||
const int size = 25;
|
||||
var x = Margin * (int) 2.5;
|
||||
foreach (var flag in UserFacingFlags.Values.Where(flag => flag != null))
|
||||
{
|
||||
c.DrawBitmap(flag.Resize(size), new SKPoint(x, Margin * (int) 2.5), ImagePaint);
|
||||
x += size;
|
||||
}
|
||||
}
|
||||
}
|
||||
293
FModel/Creator/Bases/FN/BaseIconStats.cs
Normal file
|
|
@ -0,0 +1,293 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using CUE4Parse.GameTypes.FN.Enums;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Assets.Exports.Engine;
|
||||
using CUE4Parse.UE4.Assets.Objects;
|
||||
using CUE4Parse.UE4.Objects.Core.i18N;
|
||||
using CUE4Parse.UE4.Objects.Engine.Curves;
|
||||
using CUE4Parse.UE4.Objects.GameplayTags;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using FModel.Extensions;
|
||||
using FModel.Framework;
|
||||
using SkiaSharp;
|
||||
using SkiaSharp.HarfBuzz;
|
||||
|
||||
namespace FModel.Creator.Bases.FN;
|
||||
|
||||
public class BaseIconStats : BaseIcon
|
||||
{
|
||||
private readonly IList<IconStat> _statistics;
|
||||
private const int _headerHeight = 128;
|
||||
private bool _screenLayer;
|
||||
|
||||
public BaseIconStats(UObject uObject, EIconStyle style) : base(uObject, style)
|
||||
{
|
||||
Width = 1024;
|
||||
Height = _headerHeight;
|
||||
Margin = 0;
|
||||
_statistics = new List<IconStat>();
|
||||
_screenLayer = uObject.ExportType.Equals("FortAccoladeItemDefinition", StringComparison.OrdinalIgnoreCase);
|
||||
DefaultPreview = Utils.GetBitmap("FortniteGame/Content/Athena/HUD/Quests/Art/T_NPC_Default.T_NPC_Default");
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
base.ParseForInfo();
|
||||
DisplayName = DisplayName.ToUpperInvariant();
|
||||
|
||||
if (Object.TryGetValue(out FName accoladeType, "AccoladeType") &&
|
||||
accoladeType.Text.Equals("EFortAccoladeType::Medal", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_screenLayer = false;
|
||||
}
|
||||
|
||||
if (Object.TryGetValue(out FGameplayTagContainer poiLocations, "POILocations") &&
|
||||
Utils.TryLoadObject("FortniteGame/Content/Quests/QuestIndicatorData.QuestIndicatorData", out UObject uObject) &&
|
||||
uObject.TryGetValue(out FStructFallback[] challengeMapPoiData, "ChallengeMapPoiData"))
|
||||
{
|
||||
foreach (var location in poiLocations)
|
||||
{
|
||||
var locationName = "Unknown";
|
||||
foreach (var poi in challengeMapPoiData)
|
||||
{
|
||||
if (!poi.TryGetValue(out FStructFallback locationTag, "LocationTag") || !locationTag.TryGetValue(out FName tagName, "TagName") ||
|
||||
tagName != location.TagName || !poi.TryGetValue(out FText text, "Text")) continue;
|
||||
|
||||
locationName = text.Text;
|
||||
break;
|
||||
}
|
||||
|
||||
_statistics.Add(new IconStat(Utils.GetLocalizedResource("", "B0C091D7409B1657423C5F97E9CF4C77", "LOCATION NAME"), locationName.ToUpper()));
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.TryGetValue(out FStructFallback maxStackSize, "MaxStackSize"))
|
||||
{
|
||||
if (maxStackSize.TryGetValue(out float v, "Value") && v > 0)
|
||||
{
|
||||
_statistics.Add(new IconStat("Max Stack", v, 15));
|
||||
}
|
||||
else if (TryGetCurveTableStat(maxStackSize, out var s))
|
||||
{
|
||||
_statistics.Add(new IconStat("Max Stack", s, 15));
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.TryGetValue(out FStructFallback xpRewardAmount, "XpRewardAmount") && TryGetCurveTableStat(xpRewardAmount, out var x))
|
||||
{
|
||||
_statistics.Add(new IconStat("XP Amount", x));
|
||||
}
|
||||
|
||||
if (Object.TryGetValue(out FStructFallback weaponStatHandle, "WeaponStatHandle") &&
|
||||
weaponStatHandle.TryGetValue(out FName weaponRowName, "RowName") &&
|
||||
weaponStatHandle.TryGetValue(out UDataTable dataTable, "DataTable") &&
|
||||
dataTable.TryGetDataTableRow(weaponRowName.Text, StringComparison.OrdinalIgnoreCase, out var weaponRowValue))
|
||||
{
|
||||
if (weaponRowValue.TryGetValue(out int bpc, "BulletsPerCartridge"))
|
||||
{
|
||||
var multiplier = bpc != 0f ? bpc : 1;
|
||||
if (weaponRowValue.TryGetValue(out float dmgPb, "DmgPB") && dmgPb != 0f)
|
||||
{
|
||||
_statistics.Add(new IconStat(Utils.GetLocalizedResource("", "35D04D1B45737BEA25B69686D9E085B9", "Damage"), dmgPb * multiplier, 200));
|
||||
}
|
||||
|
||||
if (weaponRowValue.TryGetValue(out float mdpc, "MaxDamagePerCartridge") && mdpc >= 0f)
|
||||
{
|
||||
_statistics.Add(new IconStat(Utils.GetLocalizedResource("", "0DEF2455463B008C4499FEA03D149EDF", "Headshot Damage"), mdpc, 200));
|
||||
}
|
||||
else if (weaponRowValue.TryGetValue(out float dmgCritical, "DamageZone_Critical"))
|
||||
{
|
||||
_statistics.Add(new IconStat(Utils.GetLocalizedResource("", "0DEF2455463B008C4499FEA03D149EDF", "Headshot Damage"), dmgPb * dmgCritical * multiplier, 200));
|
||||
}
|
||||
}
|
||||
|
||||
if (weaponRowValue.TryGetValue(out int clipSize, "ClipSize") && clipSize != 0)
|
||||
{
|
||||
_statistics.Add(new IconStat(Utils.GetLocalizedResource("", "068239DD4327B36124498C9C5F61C038", "Magazine Size"), clipSize, 50));
|
||||
}
|
||||
|
||||
if (weaponRowValue.TryGetValue(out float firingRate, "FiringRate") && firingRate != 0f)
|
||||
{
|
||||
_statistics.Add(new IconStat(Utils.GetLocalizedResource("", "27B80BA44805ABD5A2D2BAB2902B250C", "Fire Rate"), firingRate, 15));
|
||||
}
|
||||
|
||||
if (weaponRowValue.TryGetValue(out float armTime, "ArmTime") && armTime != 0f)
|
||||
{
|
||||
_statistics.Add(new IconStat(Utils.GetLocalizedResource("", "3BFEB8BD41A677CC5F45B9A90D6EAD6F", "Arming Delay"), armTime, 125));
|
||||
}
|
||||
|
||||
if (weaponRowValue.TryGetValue(out float reloadTime, "ReloadTime") && reloadTime != 0f)
|
||||
{
|
||||
_statistics.Add(new IconStat(Utils.GetLocalizedResource("", "6EA26D1A4252034FBD869A90F9A6E49A", "Reload Time"), reloadTime, 15));
|
||||
}
|
||||
|
||||
if ((Object.ExportType.Equals("FortContextTrapItemDefinition", StringComparison.OrdinalIgnoreCase) ||
|
||||
Object.ExportType.Equals("FortTrapItemDefinition", StringComparison.OrdinalIgnoreCase)) &&
|
||||
weaponRowValue.TryGetValue(out UDataTable durabilityTable, "Durability") &&
|
||||
weaponRowValue.TryGetValue(out FName durabilityRowName, "DurabilityRowName") &&
|
||||
durabilityTable.TryGetDataTableRow(durabilityRowName.Text, StringComparison.OrdinalIgnoreCase, out var durability) &&
|
||||
durability.TryGetValue(out int duraByRarity, Object.GetOrDefault("Rarity", EFortRarity.Uncommon).GetDescription()))
|
||||
{
|
||||
_statistics.Add(new IconStat(Utils.GetLocalizedResource("", "6FA2882140CB69DE32FD73A392F0585B", "Durability"), duraByRarity, 20));
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(Description))
|
||||
Height += 40 + (int) _informationPaint.TextSize * Utils.SplitLines(Description, _informationPaint, Width - 20).Count;
|
||||
Height += 50 * _statistics.Count;
|
||||
}
|
||||
|
||||
public override SKBitmap[] Draw()
|
||||
{
|
||||
var ret = new SKBitmap(Width, Height, SKColorType.Rgba8888, SKAlphaType.Opaque);
|
||||
using var c = new SKCanvas(ret);
|
||||
|
||||
DrawHeader(c);
|
||||
DrawDisplayName(c);
|
||||
DrawStatistics(c);
|
||||
|
||||
return new[] { ret };
|
||||
}
|
||||
|
||||
private bool TryGetCurveTableStat(FStructFallback property, out float statValue)
|
||||
{
|
||||
if (property.TryGetValue(out FStructFallback curve, "Curve") &&
|
||||
curve.TryGetValue(out FName rowName, "RowName") &&
|
||||
curve.TryGetValue(out UCurveTable curveTable, "CurveTable") &&
|
||||
curveTable.TryFindCurve(rowName, out var rowValue) &&
|
||||
rowValue is FSimpleCurve s && s.Keys.Length > 0)
|
||||
{
|
||||
statValue = s.Keys[0].Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
statValue = 0F;
|
||||
return false;
|
||||
}
|
||||
|
||||
private readonly SKPaint _informationPaint = new()
|
||||
{
|
||||
IsAntialias = true, FilterQuality = SKFilterQuality.High,
|
||||
Color = SKColor.Parse("#262630"), TextSize = 16,
|
||||
Typeface = Utils.Typefaces.Description
|
||||
};
|
||||
|
||||
private void DrawHeader(SKCanvas c)
|
||||
{
|
||||
c.DrawRect(new SKRect(0, 0, Width, Height), _informationPaint);
|
||||
|
||||
_informationPaint.Shader = SKShader.CreateRadialGradient(new SKPoint(Width / 2, _headerHeight / 2), Width / 5 * 4,
|
||||
new[] { Background[0].WithAlpha(180), Background[1].WithAlpha(220) }, SKShaderTileMode.Clamp);
|
||||
c.DrawRect(new SKRect(_headerHeight, 0, Width, _headerHeight), _informationPaint);
|
||||
|
||||
_informationPaint.Shader = SKShader.CreateRadialGradient(new SKPoint(Width / 2, _headerHeight / 2), Width / 5 * 4,
|
||||
new[] { SKColor.Parse("#262630"), SKColor.Parse("#1f1f26") }, SKShaderTileMode.Clamp);
|
||||
c.DrawRect(new SKRect(0, _headerHeight, Width, Height), _informationPaint);
|
||||
|
||||
_informationPaint.Shader = SKShader.CreateLinearGradient(new SKPoint(Width / 2, _headerHeight), new SKPoint(Width / 2, 75),
|
||||
new[] { SKColors.Black.WithAlpha(25), Background[1].WithAlpha(0) }, SKShaderTileMode.Clamp);
|
||||
c.DrawRect(new SKRect(0, 75, Width, _headerHeight), _informationPaint);
|
||||
|
||||
_informationPaint.Shader = SKShader.CreateRadialGradient(new SKPoint(Width / 2, _headerHeight / 2), Width / 5 * 4, Background, SKShaderTileMode.Clamp);
|
||||
using var rect = new SKPath { FillType = SKPathFillType.EvenOdd };
|
||||
rect.MoveTo(0, 0);
|
||||
rect.LineTo(_headerHeight + _headerHeight / 3, 0);
|
||||
rect.LineTo(_headerHeight, _headerHeight);
|
||||
rect.LineTo(0, _headerHeight);
|
||||
rect.Close();
|
||||
c.DrawPath(rect, _informationPaint);
|
||||
|
||||
_informationPaint.Shader = SKShader.CreateLinearGradient(new SKPoint(_headerHeight / 2, _headerHeight / 2), new SKPoint(_headerHeight / 2 + 100, _headerHeight / 2),
|
||||
new[] { SKColors.Black.WithAlpha(25), Background[1].WithAlpha(0) }, SKShaderTileMode.Clamp);
|
||||
c.DrawPath(rect, _informationPaint);
|
||||
|
||||
_informationPaint.Shader = null;
|
||||
|
||||
ImagePaint.BlendMode = _screenLayer ? SKBlendMode.Screen : Preview == null ? SKBlendMode.ColorBurn : SKBlendMode.SrcOver;
|
||||
c.DrawBitmap((Preview ?? DefaultPreview).Resize(_headerHeight), 0, 0, ImagePaint);
|
||||
}
|
||||
|
||||
private new void DrawDisplayName(SKCanvas c)
|
||||
{
|
||||
if (string.IsNullOrEmpty(DisplayName)) return;
|
||||
|
||||
_informationPaint.TextSize = 50;
|
||||
_informationPaint.Color = SKColors.White;
|
||||
_informationPaint.Typeface = Utils.Typefaces.Bundle;
|
||||
while (_informationPaint.MeasureText(DisplayName) > Width - _headerHeight * 2)
|
||||
{
|
||||
_informationPaint.TextSize -= 1;
|
||||
}
|
||||
|
||||
var shaper = new CustomSKShaper(_informationPaint.Typeface);
|
||||
c.DrawShapedText(shaper, DisplayName, _headerHeight + _headerHeight / 3 + 10, _headerHeight / 2f + _informationPaint.TextSize / 3, _informationPaint);
|
||||
}
|
||||
|
||||
private void DrawStatistics(SKCanvas c)
|
||||
{
|
||||
var outY = _headerHeight + 25f;
|
||||
if (!string.IsNullOrEmpty(Description))
|
||||
{
|
||||
_informationPaint.TextSize = 16;
|
||||
_informationPaint.Color = SKColors.White.WithAlpha(175);
|
||||
_informationPaint.Typeface = Utils.Typefaces.Description;
|
||||
Utils.DrawMultilineText(c, Description, Width - 40, 0, SKTextAlign.Center,
|
||||
new SKRect(20, outY, Width - 20, Height), _informationPaint, out outY);
|
||||
outY += 25;
|
||||
}
|
||||
|
||||
foreach (var stat in _statistics)
|
||||
{
|
||||
stat.Draw(c, Border[0].WithAlpha(100), Width, _headerHeight, ref outY);
|
||||
outY += 50;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class IconStat
|
||||
{
|
||||
private readonly string _statName;
|
||||
private readonly object _value;
|
||||
private readonly float _maxValue;
|
||||
|
||||
public IconStat(string statName, object value, float maxValue = 0)
|
||||
{
|
||||
_statName = statName.ToUpperInvariant();
|
||||
_value = value;
|
||||
_maxValue = maxValue;
|
||||
}
|
||||
|
||||
private readonly SKPaint _statPaint = new()
|
||||
{
|
||||
IsAntialias = true, FilterQuality = SKFilterQuality.High,
|
||||
TextSize = 25, Typeface = Utils.Typefaces.DisplayName,
|
||||
Color = SKColors.White
|
||||
};
|
||||
|
||||
public void Draw(SKCanvas c, SKColor sliderColor, int width, int height, ref float y)
|
||||
{
|
||||
while (_statPaint.MeasureText(_statName) > height * 2 - 40)
|
||||
{
|
||||
_statPaint.TextSize -= 1;
|
||||
}
|
||||
|
||||
var shaper = new CustomSKShaper(_statPaint.Typeface);
|
||||
c.DrawShapedText(shaper, _statName, 50, y + 10, _statPaint);
|
||||
|
||||
_statPaint.TextAlign = SKTextAlign.Right;
|
||||
_statPaint.Typeface = Utils.Typefaces.BundleNumber;
|
||||
_statPaint.Color = sliderColor;
|
||||
var sliderRight = width - 100 - _statPaint.MeasureText(_value.ToString());
|
||||
c.DrawRect(new SKRect(height * 2, y, Math.Min(width - height, sliderRight), y + 5), _statPaint);
|
||||
|
||||
_statPaint.Color = SKColors.White;
|
||||
c.DrawText(_value.ToString(), new SKPoint(width - 50, y + 10), _statPaint);
|
||||
|
||||
if (_maxValue < 1 || !float.TryParse(_value.ToString(), out var floatValue)) return;
|
||||
if (floatValue < 0)
|
||||
floatValue = 0;
|
||||
var sliderWidth = (sliderRight - height * 2) * (floatValue / _maxValue);
|
||||
c.DrawRect(new SKRect(height * 2, y, Math.Min(height * 2 + sliderWidth, sliderRight), y + 5), _statPaint);
|
||||
}
|
||||
}
|
||||
99
FModel/Creator/Bases/FN/BaseItemAccessToken.cs
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Objects.Core.i18N;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using FModel.Framework;
|
||||
using SkiaSharp;
|
||||
using SkiaSharp.HarfBuzz;
|
||||
|
||||
namespace FModel.Creator.Bases.FN;
|
||||
|
||||
public class BaseItemAccessToken : UCreator
|
||||
{
|
||||
private readonly SKBitmap _locked, _unlocked;
|
||||
private string _unlockedDescription, _exportName;
|
||||
private BaseIcon _icon;
|
||||
|
||||
public BaseItemAccessToken(UObject uObject, EIconStyle style) : base(uObject, style)
|
||||
{
|
||||
_unlocked = Utils.GetBitmap("FortniteGame/Content/UI/Foundation/Textures/Icons/Locks/T-Icon-Unlocked-128.T-Icon-Unlocked-128").Resize(24);
|
||||
_locked = Utils.GetBitmap("FortniteGame/Content/UI/Foundation/Textures/Icons/Locks/T-Icon-Lock-128.T-Icon-Lock-128").Resize(24);
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
if (Object.TryGetValue(out FPackageIndex accessItem, "access_item") &&
|
||||
Utils.TryGetPackageIndexExport(accessItem, out UObject uObject))
|
||||
{
|
||||
_exportName = uObject.Name;
|
||||
_icon = new BaseIcon(uObject, EIconStyle.Default);
|
||||
_icon.ParseForReward(false);
|
||||
}
|
||||
|
||||
if (Object.TryGetValue(out FText displayName, "DisplayName", "ItemName") && displayName.Text != "TBD")
|
||||
DisplayName = displayName.Text;
|
||||
else
|
||||
DisplayName = _icon?.DisplayName;
|
||||
|
||||
Description = Object.TryGetValue(out FText description, "Description", "ItemDescription") ? description.Text : _icon?.Description;
|
||||
if (Object.TryGetValue(out FText unlockDescription, "UnlockDescription")) _unlockedDescription = unlockDescription.Text;
|
||||
}
|
||||
|
||||
public override SKBitmap[] Draw()
|
||||
{
|
||||
var ret = new SKBitmap(Width, Height, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
using var c = new SKCanvas(ret);
|
||||
|
||||
switch (Style)
|
||||
{
|
||||
case EIconStyle.NoBackground:
|
||||
Preview = _icon.Preview;
|
||||
DrawPreview(c);
|
||||
break;
|
||||
case EIconStyle.NoText:
|
||||
Preview = _icon.Preview;
|
||||
_icon.DrawBackground(c);
|
||||
DrawPreview(c);
|
||||
break;
|
||||
default:
|
||||
_icon.DrawBackground(c);
|
||||
DrawInformation(c);
|
||||
DrawToBottom(c, SKTextAlign.Right, _exportName);
|
||||
break;
|
||||
}
|
||||
|
||||
return new[] { ret };
|
||||
}
|
||||
|
||||
private void DrawInformation(SKCanvas c)
|
||||
{
|
||||
var size = 45;
|
||||
var left = Width / 2;
|
||||
|
||||
while (DisplayNamePaint.MeasureText(DisplayName) > Width - _icon.Margin * 2)
|
||||
{
|
||||
DisplayNamePaint.TextSize = size -= 2;
|
||||
}
|
||||
|
||||
var shaper = new CustomSKShaper(DisplayNamePaint.Typeface);
|
||||
var shapedText = shaper.Shape(DisplayName, DisplayNamePaint);
|
||||
c.DrawShapedText(shaper, DisplayName, left - shapedText.Width / 2, _icon.Margin * 8 + size, DisplayNamePaint);
|
||||
|
||||
float topBase = _icon.Margin + size * 2;
|
||||
if (!string.IsNullOrEmpty(_unlockedDescription))
|
||||
{
|
||||
c.DrawBitmap(_locked, new SKRect(50, topBase, 50 + _locked.Width, topBase + _locked.Height), ImagePaint);
|
||||
Utils.DrawMultilineText(c, _unlockedDescription, Width, _icon.Margin, SKTextAlign.Left,
|
||||
new SKRect(70 + _locked.Width, topBase + 10, Width - 50, 256), DescriptionPaint, out topBase);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(Description))
|
||||
{
|
||||
c.DrawBitmap(_unlocked, new SKRect(50, topBase, 50 + _unlocked.Width, topBase + _unlocked.Height), ImagePaint);
|
||||
Utils.DrawMultilineText(c, Description, Width, _icon.Margin, SKTextAlign.Left,
|
||||
new SKRect(70 + _unlocked.Width, topBase + 10, Width - 50, 256), DescriptionPaint, out topBase);
|
||||
}
|
||||
|
||||
var h = Width - _icon.Margin - topBase;
|
||||
c.DrawBitmap(_icon.Preview ?? _icon.DefaultPreview, new SKRect(left - h / 2, topBase, left + h / 2, Width - _icon.Margin), ImagePaint);
|
||||
}
|
||||
}
|
||||
49
FModel/Creator/Bases/FN/BaseJuno.cs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Assets.Objects;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace FModel.Creator.Bases.FN;
|
||||
|
||||
public class BaseJuno : BaseIcon
|
||||
{
|
||||
private BaseIcon _character;
|
||||
|
||||
public BaseJuno(UObject uObject, EIconStyle style) : base(uObject, style)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
if (Object.TryGetValue(out FSoftObjectPath baseCid, "BaseAthenaCharacterItemDefinition") &&
|
||||
Utils.TryLoadObject(baseCid.AssetPathName.Text, out UObject cid))
|
||||
{
|
||||
_character = new BaseIcon(cid, Style);
|
||||
_character.ParseForInfo();
|
||||
|
||||
if (Object.TryGetValue(out FSoftObjectPath assembledMeshSchema, "AssembledMeshSchema", "LowDetailsAssembledMeshSchema") &&
|
||||
Utils.TryLoadObject(assembledMeshSchema.AssetPathName.Text, out UObject meshSchema) &&
|
||||
meshSchema.TryGetValue(out FInstancedStruct[] additionalData, "AdditionalData"))
|
||||
{
|
||||
foreach (var data in additionalData)
|
||||
{
|
||||
if (data.NonConstStruct?.TryGetValue(out FSoftObjectPath largePreview, "LargePreviewImage", "SmallPreviewImage") ?? false)
|
||||
{
|
||||
_character.Preview = Utils.GetBitmap(largePreview);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.TryGetValue(out FSoftObjectPath baseEid, "BaseAthenaDanceItemDefinition") &&
|
||||
Utils.TryLoadObject(baseEid.AssetPathName.Text, out UObject eid))
|
||||
{
|
||||
_character = new BaseIcon(eid, Style);
|
||||
_character.ParseForInfo();
|
||||
}
|
||||
}
|
||||
|
||||
public override SKBitmap[] Draw() => _character.Draw();
|
||||
}
|
||||
92
FModel/Creator/Bases/FN/BaseMaterialInstance.cs
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
using System.Linq;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Assets.Exports.Material;
|
||||
using CUE4Parse.UE4.Assets.Exports.Texture;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace FModel.Creator.Bases.FN;
|
||||
|
||||
public class BaseMaterialInstance : BaseIcon
|
||||
{
|
||||
public BaseMaterialInstance(UObject uObject, EIconStyle style) : base(uObject, style)
|
||||
{
|
||||
Background = new[] { SKColor.Parse("4F4F69"), SKColor.Parse("4F4F69") };
|
||||
Border = new[] { SKColor.Parse("9092AB") };
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
if (Object is not UMaterialInstanceConstant material) return;
|
||||
|
||||
texture_finding:
|
||||
foreach (var textureParameter in material.TextureParameterValues) // get texture from base material
|
||||
{
|
||||
if (!textureParameter.ParameterValue.TryLoad<UTexture2D>(out var texture) || Preview != null) continue;
|
||||
switch (textureParameter.ParameterInfo.Name.Text)
|
||||
{
|
||||
case "SeriesTexture":
|
||||
GetSeries(texture);
|
||||
break;
|
||||
case "TextureA":
|
||||
case "TextureB":
|
||||
case "OfferImage":
|
||||
case "CarTexture":
|
||||
Preview = Utils.GetBitmap(texture);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (material.VectorParameterValues.Length == 0 || // try to get color from parent if not found here
|
||||
material.VectorParameterValues.All(x => x.ParameterInfo.Name.Text.Equals("FallOff_Color"))) // use parent if it only contains FallOff_Color
|
||||
{
|
||||
if (material.TryGetValue(out FPackageIndex parent, "Parent"))
|
||||
Utils.TryGetPackageIndexExport(parent, out material);
|
||||
else return;
|
||||
|
||||
if (material == null) return;
|
||||
}
|
||||
|
||||
if (Preview == null)
|
||||
{
|
||||
if (material.TryGetValue(out FPackageIndex parent, "Parent"))
|
||||
Utils.TryGetPackageIndexExport(parent, out material);
|
||||
|
||||
goto texture_finding;
|
||||
}
|
||||
|
||||
foreach (var vectorParameter in material.VectorParameterValues)
|
||||
{
|
||||
if (vectorParameter.ParameterValue == null) continue;
|
||||
switch (vectorParameter.ParameterInfo.Name.Text)
|
||||
{
|
||||
case "Background_Color_A":
|
||||
Background[0] = SKColor.Parse(vectorParameter.ParameterValue.Value.Hex);
|
||||
Border[0] = Background[0];
|
||||
break;
|
||||
case "Background_Color_B": // Border color can be defaulted here in some case where Background_Color_A should be taken from parent but Background_Color_B from base
|
||||
Background[1] = SKColor.Parse(vectorParameter.ParameterValue.Value.Hex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override SKBitmap[] Draw()
|
||||
{
|
||||
var ret = new SKBitmap(Width, Height, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
using var c = new SKCanvas(ret);
|
||||
|
||||
switch (Style)
|
||||
{
|
||||
case EIconStyle.NoBackground:
|
||||
DrawPreview(c);
|
||||
break;
|
||||
default:
|
||||
DrawBackground(c);
|
||||
DrawPreview(c);
|
||||
break;
|
||||
}
|
||||
|
||||
return new[] { ret };
|
||||
}
|
||||
}
|
||||
83
FModel/Creator/Bases/FN/BaseMtxOffer.cs
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Assets.Objects;
|
||||
using CUE4Parse.UE4.Objects.Core.i18N;
|
||||
using CUE4Parse.UE4.Objects.Core.Math;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace FModel.Creator.Bases.FN;
|
||||
|
||||
public class BaseMtxOffer : UCreator
|
||||
{
|
||||
public BaseMtxOffer(UObject uObject, EIconStyle style) : base(uObject, style)
|
||||
{
|
||||
Background = new[] { SKColor.Parse("4F4F69"), SKColor.Parse("4F4F69") };
|
||||
Border = new[] { SKColor.Parse("9092AB") };
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
if (Object.TryGetValue(out FSoftObjectPath image, "SoftDetailsImage", "SoftTileImage"))
|
||||
{
|
||||
Preview = Utils.GetBitmap(image);
|
||||
}
|
||||
|
||||
if (Object.TryGetValue(out FStructFallback gradient, "Gradient") &&
|
||||
gradient.TryGetValue(out FLinearColor start, "Start") &&
|
||||
gradient.TryGetValue(out FLinearColor stop, "Stop"))
|
||||
{
|
||||
Background = new[] { SKColor.Parse(start.Hex), SKColor.Parse(stop.Hex) };
|
||||
}
|
||||
|
||||
if (Object.TryGetValue(out FLinearColor background, "Background"))
|
||||
Border = new[] { SKColor.Parse(background.Hex) };
|
||||
if (Object.TryGetValue(out FText displayName, "DisplayName"))
|
||||
DisplayName = displayName.Text;
|
||||
if (Object.TryGetValue(out FText shortDescription, "ShortDescription"))
|
||||
Description = shortDescription.Text;
|
||||
|
||||
if (Object.TryGetValue(out FStructFallback[] details, "DetailsAttributes"))
|
||||
{
|
||||
foreach (var detail in details)
|
||||
{
|
||||
if (detail.TryGetValue(out FText detailName, "Name"))
|
||||
{
|
||||
Description += $"\n- {detailName.Text.TrimEnd()}";
|
||||
}
|
||||
|
||||
if (detail.TryGetValue(out FText detailValue, "Value") && !string.IsNullOrEmpty(detailValue.Text))
|
||||
{
|
||||
Description += $" ({detailValue.Text})";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Description = Utils.RemoveHtmlTags(Description);
|
||||
}
|
||||
|
||||
public override SKBitmap[] Draw()
|
||||
{
|
||||
var ret = new SKBitmap(Width, Height, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
using var c = new SKCanvas(ret);
|
||||
|
||||
switch (Style)
|
||||
{
|
||||
case EIconStyle.NoBackground:
|
||||
DrawPreview(c);
|
||||
break;
|
||||
case EIconStyle.NoText:
|
||||
DrawBackground(c);
|
||||
DrawPreview(c);
|
||||
break;
|
||||
default:
|
||||
DrawBackground(c);
|
||||
DrawPreview(c);
|
||||
DrawTextBackground(c);
|
||||
DrawDisplayName(c);
|
||||
DrawDescription(c);
|
||||
break;
|
||||
}
|
||||
|
||||
return new[] { ret };
|
||||
}
|
||||
}
|
||||
45
FModel/Creator/Bases/FN/BaseOfferDisplayData.cs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
using System.Collections.Generic;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Assets.Exports.Material;
|
||||
using CUE4Parse.UE4.Assets.Objects;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace FModel.Creator.Bases.FN;
|
||||
|
||||
public class BaseOfferDisplayData : UCreator
|
||||
{
|
||||
private readonly List<BaseMaterialInstance> _offerImages;
|
||||
|
||||
public BaseOfferDisplayData(UObject uObject, EIconStyle style) : base(uObject, style)
|
||||
{
|
||||
_offerImages = new List<BaseMaterialInstance>();
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
if (!Object.TryGetValue(out FStructFallback[] contextualPresentations, "ContextualPresentations"))
|
||||
return;
|
||||
|
||||
for (var i = 0; i < contextualPresentations.Length; i++)
|
||||
{
|
||||
if (!contextualPresentations[i].TryGetValue(out FSoftObjectPath material, "Material") ||
|
||||
!material.TryLoad(out UMaterialInterface presentation)) continue;
|
||||
|
||||
var offerImage = new BaseMaterialInstance(presentation, Style);
|
||||
offerImage.ParseForInfo();
|
||||
_offerImages.Add(offerImage);
|
||||
}
|
||||
}
|
||||
|
||||
public override SKBitmap[] Draw()
|
||||
{
|
||||
var ret = new SKBitmap[_offerImages.Count];
|
||||
for (var i = 0; i < ret.Length; i++)
|
||||
{
|
||||
ret[i] = _offerImages[i]?.Draw()[0];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
77
FModel/Creator/Bases/FN/BasePlaylist.cs
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Assets.Exports.Texture;
|
||||
using CUE4Parse.UE4.Objects.Core.i18N;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using FModel.Services;
|
||||
using FModel.ViewModels;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace FModel.Creator.Bases.FN;
|
||||
|
||||
public class BasePlaylist : UCreator
|
||||
{
|
||||
private ApiEndpointViewModel _apiEndpointView => ApplicationService.ApiEndpointView;
|
||||
private SKBitmap _missionIcon;
|
||||
|
||||
public BasePlaylist(UObject uObject, EIconStyle style) : base(uObject, style)
|
||||
{
|
||||
Margin = 0;
|
||||
Width = 1024;
|
||||
Height = 512;
|
||||
Preview = Utils.GetBitmap("FortniteGame/Content/UI/Foundation/Textures/Tiles/T_Athena_Tile_Matchmaking_Default.T_Athena_Tile_Matchmaking_Default");
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
if (Object.TryGetValue(out FText displayName, "UIDisplayName", "DisplayName"))
|
||||
DisplayName = displayName.Text;
|
||||
if (Object.TryGetValue(out FText description, "UIDescription", "Description"))
|
||||
Description = description.Text;
|
||||
if (Object.TryGetValue(out UTexture2D missionIcon, "MissionIcon"))
|
||||
_missionIcon = Utils.GetBitmap(missionIcon).Resize(25);
|
||||
|
||||
if (!Object.TryGetValue(out FName playlistName, "PlaylistName") || string.IsNullOrWhiteSpace(playlistName.Text))
|
||||
return;
|
||||
|
||||
var playlist = _apiEndpointView.FortniteApi.GetPlaylist(playlistName.Text);
|
||||
if (!playlist.IsSuccess || playlist.Data.Images is not { HasShowcase: true } ||
|
||||
!_apiEndpointView.FortniteApi.TryGetBytes(playlist.Data.Images.Showcase, out var image))
|
||||
return;
|
||||
|
||||
Preview = Utils.GetBitmap(image).ResizeWithRatio(1024, 512);
|
||||
Width = Preview.Width;
|
||||
Height = Preview.Height;
|
||||
}
|
||||
|
||||
public override SKBitmap[] Draw()
|
||||
{
|
||||
var ret = new SKBitmap(Width, Height, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
using var c = new SKCanvas(ret);
|
||||
|
||||
switch (Style)
|
||||
{
|
||||
case EIconStyle.NoBackground:
|
||||
DrawPreview(c);
|
||||
break;
|
||||
case EIconStyle.NoText:
|
||||
DrawPreview(c);
|
||||
DrawMissionIcon(c);
|
||||
break;
|
||||
default:
|
||||
DrawPreview(c);
|
||||
DrawTextBackground(c);
|
||||
DrawDisplayName(c);
|
||||
DrawDescription(c);
|
||||
DrawMissionIcon(c);
|
||||
break;
|
||||
}
|
||||
|
||||
return new[] { ret };
|
||||
}
|
||||
|
||||
private void DrawMissionIcon(SKCanvas c)
|
||||
{
|
||||
if (_missionIcon == null) return;
|
||||
c.DrawBitmap(_missionIcon, new SKPoint(5, 5), ImagePaint);
|
||||
}
|
||||
}
|
||||
278
FModel/Creator/Bases/FN/BaseQuest.cs
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Assets.Exports.Engine;
|
||||
using CUE4Parse.UE4.Assets.Exports.Material;
|
||||
using CUE4Parse.UE4.Assets.Exports.Texture;
|
||||
using CUE4Parse.UE4.Assets.Objects;
|
||||
using CUE4Parse.UE4.Objects.Core.i18N;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using FModel.Extensions;
|
||||
using FModel.Framework;
|
||||
using SkiaSharp;
|
||||
using SkiaSharp.HarfBuzz;
|
||||
|
||||
namespace FModel.Creator.Bases.FN;
|
||||
|
||||
public class BaseQuest : BaseIcon
|
||||
{
|
||||
private int _count;
|
||||
private Reward _reward;
|
||||
private readonly bool _screenLayer;
|
||||
private readonly string[] _unauthorizedReward = { "Token", "ChallengeBundle", "GiftBox" };
|
||||
|
||||
public string NextQuestName { get; private set; }
|
||||
|
||||
public BaseQuest(UObject uObject, EIconStyle style) : base(uObject, style)
|
||||
{
|
||||
Margin = 0;
|
||||
Width = 1024;
|
||||
Height = 256;
|
||||
DefaultPreview = Utils.GetBitmap("FortniteGame/Content/Athena/HUD/Quests/Art/T_NPC_Default.T_NPC_Default");
|
||||
if (uObject != null)
|
||||
{
|
||||
_screenLayer = uObject.ExportType.Equals("FortFeatItemDefinition", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
private BaseQuest(int completionCount, EIconStyle style) : this(null, style) // completion
|
||||
{
|
||||
var description = completionCount < 0 ?
|
||||
Utils.GetLocalizedResource("AthenaChallengeDetailsEntry", "CompletionRewardFormat_All", "Complete <text color=\"FFF\" case=\"upper\" fontface=\"black\">all {0} challenges</> to earn the reward item") :
|
||||
Utils.GetLocalizedResource("AthenaChallengeDetailsEntry", "CompletionRewardFormat", "Complete <text color=\"FFF\" case=\"upper\" fontface=\"black\">any {0} challenges</> to earn the reward item");
|
||||
|
||||
DisplayName = ReformatString(description, completionCount.ToString(), completionCount < 0);
|
||||
}
|
||||
|
||||
public BaseQuest(int completionCount, FSoftObjectPath itemDefinition, EIconStyle style) : this(completionCount, style) // completion
|
||||
{
|
||||
_reward = Utils.TryLoadObject(itemDefinition.AssetPathName.Text, out UObject uObject) ? new Reward(uObject) : new Reward();
|
||||
}
|
||||
|
||||
public BaseQuest(int completionCount, int quantity, string reward, EIconStyle style) : this(completionCount, style) // completion
|
||||
{
|
||||
_reward = new Reward(quantity, reward);
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
ParseForReward(false);
|
||||
|
||||
if (Object.TryGetValue(out FStructFallback urgentQuestData, "UrgentQuestData"))
|
||||
{
|
||||
if (urgentQuestData.TryGetValue(out FText eventTitle, "EventTitle"))
|
||||
DisplayName = eventTitle.Text;
|
||||
if (urgentQuestData.TryGetValue(out FText eventDescription, "EventDescription"))
|
||||
Description = eventDescription.Text;
|
||||
if (urgentQuestData.TryGetValue(out FPackageIndex alertIcon, "AlertIcon", "BountyPriceImage"))
|
||||
Preview = Utils.GetBitmap(alertIcon);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!string.IsNullOrEmpty(ShortDescription))
|
||||
Description = ShortDescription;
|
||||
if (string.IsNullOrEmpty(DisplayName) && !string.IsNullOrEmpty(Description))
|
||||
DisplayName = Description;
|
||||
if (DisplayName == Description)
|
||||
Description = string.Empty;
|
||||
|
||||
if ((Object.TryGetValue(out FSoftObjectPath icon, "QuestGiverWidgetIcon", "NotificationIconOverride") &&
|
||||
Utils.TryLoadObject(icon.AssetPathName.Text, out UObject iconObject)) ||
|
||||
(Object.TryGetValue(out FSoftObjectPath tandemCharacterData, "TandemCharacterData") &&
|
||||
Utils.TryLoadObject(tandemCharacterData.AssetPathName.Text, out UObject uObject) &&
|
||||
uObject.TryGetValue(out FSoftObjectPath tandemIcon, "EntryListIcon", "ToastIcon") &&
|
||||
Utils.TryLoadObject(tandemIcon.AssetPathName.Text, out iconObject)))
|
||||
{
|
||||
Preview = iconObject switch
|
||||
{
|
||||
UTexture2D text => Utils.GetBitmap(text),
|
||||
UMaterialInstanceConstant mat => Utils.GetBitmap(mat),
|
||||
_ => Preview
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.TryGetValue(out int objectiveCompletionCount, "ObjectiveCompletionCount"))
|
||||
_count = objectiveCompletionCount;
|
||||
|
||||
if (Object.TryGetValue(out FStructFallback[] objectives, "Objectives") && objectives.Length > 0)
|
||||
{
|
||||
// actual description doesn't exist
|
||||
if (string.IsNullOrEmpty(Description) && objectives[0].TryGetValue(out FText description, "Description"))
|
||||
Description = description.Text;
|
||||
|
||||
// ObjectiveCompletionCount doesn't exist
|
||||
if (_count == 0)
|
||||
{
|
||||
if (objectives[0].TryGetValue(out int count, "Count") && count > 1)
|
||||
_count = count;
|
||||
else
|
||||
_count = objectives.Length;
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.TryGetValue(out FStructFallback[] rewards, "Rewards"))
|
||||
{
|
||||
foreach (var reward in rewards)
|
||||
{
|
||||
if (!reward.TryGetValue(out FStructFallback itemPrimaryAssetId, "ItemPrimaryAssetId") ||
|
||||
!reward.TryGetValue(out int quantity, "Quantity")) continue;
|
||||
|
||||
if (!itemPrimaryAssetId.TryGetValue(out FStructFallback primaryAssetType, "PrimaryAssetType") ||
|
||||
!itemPrimaryAssetId.TryGetValue(out FName primaryAssetName, "PrimaryAssetName") ||
|
||||
!primaryAssetType.TryGetValue(out FName name, "Name")) continue;
|
||||
|
||||
if (name.Text.Equals("Quest", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
NextQuestName = primaryAssetName.Text;
|
||||
}
|
||||
else if (!_unauthorizedReward.Contains(name.Text))
|
||||
{
|
||||
_reward = new Reward(quantity, $"{name}:{primaryAssetName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_reward == null)
|
||||
{
|
||||
FName rowName = null;
|
||||
if (Object.TryGetValue(out UDataTable rewardsTable, "RewardsTable"))
|
||||
rowName = new FName("Default");
|
||||
else if (Object.TryGetValue(out FStructFallback[] rewardTableRows, "IndividualRewardTableRows") &&
|
||||
rewardTableRows.Length > 0 && rewardTableRows[0].TryGetValue(out rowName, "RowName") &&
|
||||
rewardTableRows[0].TryGetValue(out rewardsTable, "DataTable")) {}
|
||||
|
||||
if (rewardsTable != null && rowName != null && rewardsTable.TryGetDataTableRow(rowName.Text, StringComparison.InvariantCulture, out var row))
|
||||
{
|
||||
if (row.TryGetValue(out FName templateId, "TemplateId") &&
|
||||
row.TryGetValue(out int quantity, "Quantity"))
|
||||
{
|
||||
_reward = new Reward(quantity, templateId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_reward == null && Object.TryGetValue(out FStructFallback[] hiddenRewards, "HiddenRewards"))
|
||||
{
|
||||
foreach (var hiddenReward in hiddenRewards)
|
||||
{
|
||||
if (!hiddenReward.TryGetValue(out FName templateId, "TemplateId") ||
|
||||
!hiddenReward.TryGetValue(out int quantity, "Quantity")) continue;
|
||||
|
||||
_reward = new Reward(quantity, templateId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_reward ??= new Reward();
|
||||
}
|
||||
|
||||
public void DrawQuest(SKCanvas c, int y)
|
||||
{
|
||||
DrawBackground(c, y);
|
||||
DrawPreview(c, y);
|
||||
DrawTexts(c, y);
|
||||
}
|
||||
|
||||
public override SKBitmap[] Draw()
|
||||
{
|
||||
var ret = new SKBitmap(Width, Height, SKColorType.Rgba8888, SKAlphaType.Opaque);
|
||||
using var c = new SKCanvas(ret);
|
||||
|
||||
DrawQuest(c, 0);
|
||||
|
||||
return new[] { ret };
|
||||
}
|
||||
|
||||
private string ReformatString(string s, string completionCount, bool isAll)
|
||||
{
|
||||
s = s.Replace("({0})", "{0}").Replace("{QuestNumber}", "<text color=\"FFF\" case=\"upper\" fontface=\"black\">{0}</>");
|
||||
var index = s.IndexOf("{0}|plural(", StringComparison.OrdinalIgnoreCase);
|
||||
if (index > -1)
|
||||
{
|
||||
var p = s.Substring(index, s[index..].IndexOf(')') + 1);
|
||||
s = s.Replace(p, string.Empty);
|
||||
s = s.Insert(s.IndexOf("</>", StringComparison.OrdinalIgnoreCase), p.SubstringAfter("(").SubstringAfter("=").SubstringBefore(","));
|
||||
}
|
||||
|
||||
var upper = s.SubstringAfter(">").SubstringBefore("</>");
|
||||
return string.Format(Utils.RemoveHtmlTags(s.Replace(upper, upper.ToUpper())), isAll ? string.Empty : completionCount).Replace(" ", " ");
|
||||
}
|
||||
|
||||
private readonly SKPaint _informationPaint = new()
|
||||
{
|
||||
IsAntialias = true, FilterQuality = SKFilterQuality.High,
|
||||
Color = SKColor.Parse("#262630")
|
||||
};
|
||||
|
||||
private void DrawBackground(SKCanvas c, int y)
|
||||
{
|
||||
c.DrawRect(new SKRect(Margin, y, Width, y + Height), _informationPaint);
|
||||
|
||||
_informationPaint.Shader = SKShader.CreateRadialGradient(new SKPoint(Width / 2, y + Height / 2), Width / 5 * 4,
|
||||
new[] { Background[0].WithAlpha(50), Background[1].WithAlpha(50) }, SKShaderTileMode.Clamp);
|
||||
c.DrawRect(new SKRect(Height / 2, y, Width, y + Height), _informationPaint);
|
||||
|
||||
_informationPaint.Shader = SKShader.CreateLinearGradient(new SKPoint(Width / 2, y + Height), new SKPoint(Width / 2, 75),
|
||||
new[] { SKColors.Black.WithAlpha(25), Background[1].WithAlpha(0) }, SKShaderTileMode.Clamp);
|
||||
c.DrawRect(new SKRect(0, y + 75, Width, y + Height), _informationPaint);
|
||||
|
||||
_informationPaint.Shader = SKShader.CreateRadialGradient(new SKPoint(Width / 2, y + Height / 2), Width / 5 * 4, Background, SKShaderTileMode.Clamp);
|
||||
c.DrawRect(new SKRect(Margin, y, Height / 2, y + Height), _informationPaint);
|
||||
|
||||
_informationPaint.Shader = SKShader.CreateLinearGradient(new SKPoint(Height / 2, y + Height / 2), new SKPoint(Height / 2 + 100, y + Height / 2),
|
||||
new[] { SKColors.Black.WithAlpha(25), Background[1].WithAlpha(0) }, SKShaderTileMode.Clamp);
|
||||
c.DrawRect(new SKRect(Height / 2, y, Height / 2 + 100, y + Height), _informationPaint);
|
||||
}
|
||||
|
||||
private void DrawPreview(SKCanvas c, int y)
|
||||
{
|
||||
ImagePaint.BlendMode = _screenLayer ? SKBlendMode.Screen : Preview == null ? SKBlendMode.ColorBurn : SKBlendMode.SrcOver;
|
||||
c.DrawBitmap(Preview ?? DefaultPreview, new SKRect(Margin, y, Height - Margin, y + Height), ImagePaint);
|
||||
}
|
||||
|
||||
private void DrawTexts(SKCanvas c, int y)
|
||||
{
|
||||
_informationPaint.Shader = null;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(DisplayName))
|
||||
{
|
||||
_informationPaint.TextSize = 40;
|
||||
_informationPaint.Color = SKColors.White;
|
||||
_informationPaint.Typeface = Utils.Typefaces.Bundle;
|
||||
while (_informationPaint.MeasureText(DisplayName) > Width - Height - 10)
|
||||
{
|
||||
_informationPaint.TextSize -= 1;
|
||||
}
|
||||
|
||||
var shaper = new CustomSKShaper(_informationPaint.Typeface);
|
||||
c.DrawShapedText(shaper, DisplayName, Height, y + 50, _informationPaint);
|
||||
}
|
||||
|
||||
var outY = y + 75f;
|
||||
if (!string.IsNullOrWhiteSpace(Description))
|
||||
{
|
||||
_informationPaint.TextSize = 16;
|
||||
_informationPaint.Color = SKColors.White.WithAlpha(175);
|
||||
_informationPaint.Typeface = Utils.Typefaces.Description;
|
||||
Utils.DrawMultilineText(c, Description, Width - Height, y, SKTextAlign.Left,
|
||||
new SKRect(Height, outY, Width - 10, y + Height), _informationPaint, out outY);
|
||||
}
|
||||
|
||||
_informationPaint.Color = Border[0].WithAlpha(100);
|
||||
c.DrawRect(new SKRect(Height, outY, Width - 150, outY + 5), _informationPaint);
|
||||
|
||||
if (_count > 0)
|
||||
{
|
||||
_informationPaint.TextSize = 25;
|
||||
_informationPaint.Color = SKColors.White;
|
||||
_informationPaint.Typeface = Utils.Typefaces.BundleNumber;
|
||||
c.DrawText("0 / ", new SKPoint(Width - 130, outY + 10), _informationPaint);
|
||||
|
||||
_informationPaint.Color = Border[0];
|
||||
c.DrawText(_count.ToString(), new SKPoint(Width - 95, outY + 10), _informationPaint);
|
||||
}
|
||||
|
||||
_reward.DrawQuest(c, new SKRect(Height, outY + 25, Width - 20, y + Height - 25));
|
||||
}
|
||||
}
|
||||
158
FModel/Creator/Bases/FN/BaseSeason.cs
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Assets.Objects;
|
||||
using CUE4Parse.UE4.Objects.Core.i18N;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using FModel.Framework;
|
||||
using SkiaSharp;
|
||||
using SkiaSharp.HarfBuzz;
|
||||
|
||||
namespace FModel.Creator.Bases.FN;
|
||||
|
||||
public class Page
|
||||
{
|
||||
public int LevelsNeededForUnlock;
|
||||
public int RewardsNeededForUnlock;
|
||||
public Reward[] RewardEntryList;
|
||||
}
|
||||
|
||||
public class BaseSeason : UCreator
|
||||
{
|
||||
private Reward _firstWinReward;
|
||||
private Page[] _bookXpSchedule;
|
||||
private const int _headerHeight = 150;
|
||||
// keep the list because rewards are ordered by least to most important
|
||||
// we only care about the most but we also have filters so we can't just take the last reward
|
||||
|
||||
public BaseSeason(UObject uObject, EIconStyle style) : base(uObject, style)
|
||||
{
|
||||
Width = 1024;
|
||||
Height = _headerHeight + 50;
|
||||
Margin = 0;
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
_bookXpSchedule = Array.Empty<Page>();
|
||||
|
||||
if (Object.TryGetValue(out FText displayName, "DisplayName", "ItemName"))
|
||||
DisplayName = displayName.Text.ToUpperInvariant();
|
||||
|
||||
if (Object.TryGetValue(out FStructFallback seasonFirstWinRewards, "SeasonFirstWinRewards") &&
|
||||
seasonFirstWinRewards.TryGetValue(out FStructFallback[] rewards, "Rewards"))
|
||||
{
|
||||
foreach (var reward in rewards)
|
||||
{
|
||||
if (!reward.TryGetValue(out FSoftObjectPath itemDefinition, "ItemDefinition") ||
|
||||
!Utils.TryLoadObject(itemDefinition.AssetPathName.Text, out UObject uObject)) continue;
|
||||
|
||||
_firstWinReward = new Reward(uObject);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.TryGetValue(out FPackageIndex[] additionalSeasonData, "AdditionalSeasonData"))
|
||||
{
|
||||
foreach (var data in additionalSeasonData)
|
||||
{
|
||||
if (!Utils.TryGetPackageIndexExport(data, out UObject packageIndex) ||
|
||||
!packageIndex.TryGetValue(out FStructFallback[] pageList, "PageList")) continue;
|
||||
|
||||
var i = 0;
|
||||
_bookXpSchedule = new Page[pageList.Length];
|
||||
foreach (var page in pageList)
|
||||
{
|
||||
if (!page.TryGetValue(out int levelsNeededForUnlock, "LevelsNeededForUnlock") ||
|
||||
!page.TryGetValue(out int rewardsNeededForUnlock, "RewardsNeededForUnlock") ||
|
||||
!page.TryGetValue(out FPackageIndex[] rewardEntryList, "RewardEntryList"))
|
||||
continue;
|
||||
|
||||
var p = new Page
|
||||
{
|
||||
LevelsNeededForUnlock = levelsNeededForUnlock,
|
||||
RewardsNeededForUnlock = rewardsNeededForUnlock,
|
||||
RewardEntryList = new Reward[rewardEntryList.Length]
|
||||
};
|
||||
|
||||
for (var j = 0; j < p.RewardEntryList.Length; j++)
|
||||
{
|
||||
if (!Utils.TryGetPackageIndexExport(rewardEntryList[j], out packageIndex) ||
|
||||
!packageIndex.TryGetValue(out FStructFallback battlePassOffer, "BattlePassOffer") ||
|
||||
!battlePassOffer.TryGetValue(out FStructFallback rewardItem, "RewardItem") ||
|
||||
!rewardItem.TryGetValue(out FSoftObjectPath itemDefinition, "ItemDefinition") ||
|
||||
!Utils.TryLoadObject(itemDefinition.AssetPathName.Text, out UObject uObject)) continue;
|
||||
|
||||
p.RewardEntryList[j] = new Reward(uObject);
|
||||
}
|
||||
|
||||
_bookXpSchedule[i++] = p;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Height += 100 * _bookXpSchedule.Sum(x => x.RewardEntryList.Length) / _bookXpSchedule.Length;
|
||||
}
|
||||
|
||||
public override SKBitmap[] Draw()
|
||||
{
|
||||
var ret = new SKBitmap(Width, Height, SKColorType.Rgba8888, SKAlphaType.Opaque);
|
||||
using var c = new SKCanvas(ret);
|
||||
|
||||
DrawHeader(c);
|
||||
_firstWinReward?.DrawSeasonWin(c, _headerHeight);
|
||||
DrawBookSchedule(c);
|
||||
|
||||
return new[] { ret };
|
||||
}
|
||||
|
||||
private const int _DEFAULT_AREA_SIZE = 80;
|
||||
private readonly SKPaint _headerPaint = new()
|
||||
{
|
||||
IsAntialias = true, FilterQuality = SKFilterQuality.High,
|
||||
Typeface = Utils.Typefaces.Bundle, TextSize = 50,
|
||||
TextAlign = SKTextAlign.Center, Color = SKColor.Parse("#262630")
|
||||
};
|
||||
|
||||
public void DrawHeader(SKCanvas c)
|
||||
{
|
||||
c.DrawRect(new SKRect(0, 0, Width, Height), _headerPaint);
|
||||
|
||||
_headerPaint.Shader = SKShader.CreateRadialGradient(new SKPoint(Width / 2, _headerHeight / 2), Width / 5 * 4,
|
||||
new[] { SKColors.SkyBlue.WithAlpha(50), SKColors.Blue.WithAlpha(50) }, SKShaderTileMode.Clamp);
|
||||
c.DrawRect(new SKRect(0, 0, Width, Height), _headerPaint);
|
||||
|
||||
_headerPaint.Shader = SKShader.CreateLinearGradient(new SKPoint(Width / 2, _headerHeight), new SKPoint(Width / 2, 75),
|
||||
new[] { SKColors.Black.WithAlpha(25), SKColors.Blue.WithAlpha(0) }, SKShaderTileMode.Clamp);
|
||||
c.DrawRect(new SKRect(0, 75, Width, _headerHeight), _headerPaint);
|
||||
|
||||
_headerPaint.Shader = null;
|
||||
_headerPaint.Color = SKColors.White;
|
||||
while (_headerPaint.MeasureText(DisplayName) > Width)
|
||||
{
|
||||
_headerPaint.TextSize -= 1;
|
||||
}
|
||||
|
||||
var shaper = new CustomSKShaper(_headerPaint.Typeface);
|
||||
c.DrawShapedText(shaper, DisplayName, Width / 2f, _headerHeight / 2f + _headerPaint.TextSize / 2 - 10, _headerPaint);
|
||||
}
|
||||
|
||||
private void DrawBookSchedule(SKCanvas c)
|
||||
{
|
||||
var x = 20;
|
||||
var y = _headerHeight + 50;
|
||||
foreach (var page in _bookXpSchedule)
|
||||
{
|
||||
foreach (var reward in page.RewardEntryList)
|
||||
{
|
||||
reward.DrawSeason(c, x, y, _DEFAULT_AREA_SIZE);
|
||||
x += _DEFAULT_AREA_SIZE + 20;
|
||||
}
|
||||
|
||||
y += _DEFAULT_AREA_SIZE + 20;
|
||||
x = 20;
|
||||
}
|
||||
}
|
||||
}
|
||||
26
FModel/Creator/Bases/FN/BaseSeries.cs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace FModel.Creator.Bases.FN;
|
||||
|
||||
public class BaseSeries : BaseIcon
|
||||
{
|
||||
public BaseSeries(UObject uObject, EIconStyle style) : base(uObject, style)
|
||||
{
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
GetSeries(Object);
|
||||
}
|
||||
|
||||
public override SKBitmap[] Draw()
|
||||
{
|
||||
var ret = new SKBitmap(Width, Height, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
using var c = new SKCanvas(ret);
|
||||
|
||||
DrawBackground(c);
|
||||
|
||||
return new []{ret};
|
||||
}
|
||||
}
|
||||
228
FModel/Creator/Bases/FN/BaseTandem.cs
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
using System;
|
||||
using System.Windows;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Objects.Core.i18N;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using CUE4Parse.UE4.Versions;
|
||||
using FModel.Framework;
|
||||
using FModel.Settings;
|
||||
using SkiaSharp;
|
||||
using SkiaSharp.HarfBuzz;
|
||||
|
||||
namespace FModel.Creator.Bases.FN;
|
||||
|
||||
public class BaseTandem : BaseIcon
|
||||
{
|
||||
private string _generalDescription, _additionalDescription;
|
||||
|
||||
public BaseTandem(UObject uObject, EIconStyle style) : base(uObject, style)
|
||||
{
|
||||
DefaultPreview = Utils.GetBitmap("FortniteGame/Content/UI/Foundation/Textures/BattleRoyale/FeaturedItems/Outfit/T-AthenaSoldiers-CID-883-Athena-Commando-M-ChOneJonesy.T-AthenaSoldiers-CID-883-Athena-Commando-M-ChOneJonesy");
|
||||
Margin = 0;
|
||||
Width = 690;
|
||||
Height = 1080;
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
base.ParseForInfo();
|
||||
|
||||
string sidePanel = string.Empty, entryList = string.Empty;
|
||||
|
||||
if (Object.TryGetValue(out FSoftObjectPath sidePanelIcon, "SidePanelIcon"))
|
||||
sidePanel = sidePanelIcon.AssetPathName.Text;
|
||||
if (Object.TryGetValue(out FSoftObjectPath entryListIcon, "EntryListIcon"))
|
||||
entryList = entryListIcon.AssetPathName.Text;
|
||||
|
||||
// Overrides for generic "default" images Epic uses for Quest-only or unfinished NPCs
|
||||
if (sidePanel.Contains("Clown") && entryList.Contains("Clown"))
|
||||
Preview = null;
|
||||
else if (sidePanel.Contains("Bane") && !Object.Name.Contains("Sorana"))
|
||||
Preview = Utils.GetBitmap(entryList);
|
||||
else if (!string.IsNullOrWhiteSpace(sidePanel) && !sidePanel.Contains("Clown"))
|
||||
Preview = Utils.GetBitmap(sidePanel);
|
||||
else if ((string.IsNullOrWhiteSpace(sidePanel) || sidePanel.Contains("Clown")) && !string.IsNullOrWhiteSpace(entryList))
|
||||
Preview = Utils.GetBitmap(entryList);
|
||||
|
||||
if (Object.TryGetValue(out FText genDesc, "GeneralDescription"))
|
||||
_generalDescription = genDesc.Text;
|
||||
if (Object.TryGetValue(out FText addDesc, "AdditionalDescription"))
|
||||
_additionalDescription = addDesc.Text;
|
||||
}
|
||||
|
||||
public override SKBitmap[] Draw()
|
||||
{
|
||||
var ret = new SKBitmap(Width, Height, SKColorType.Rgba8888, SKAlphaType.Opaque);
|
||||
using var c = new SKCanvas(ret);
|
||||
|
||||
DrawBackground(c);
|
||||
DrawPreview(c);
|
||||
DrawHaze(c);
|
||||
|
||||
// Korean is slightly smaller than other languages, so the font size is increased slightly
|
||||
DrawName(c);
|
||||
DrawGeneralDescription(c);
|
||||
DrawAdditionalDescription(c);
|
||||
|
||||
return new[] { ret };
|
||||
}
|
||||
|
||||
private readonly SKPaint _panelPaint = new() { IsAntialias = true, FilterQuality = SKFilterQuality.High, Color = SKColor.Parse("#0045C7") };
|
||||
|
||||
private new void DrawBackground(SKCanvas c)
|
||||
{
|
||||
c.DrawBitmap(SKBitmap.Decode(Application.GetResourceStream(new Uri("pack://application:,,,/Resources/npcleftside.png"))?.Stream).Resize(Width, Height), 0, 0, new SKPaint { IsAntialias = false, FilterQuality = SKFilterQuality.None, ImageFilter = SKImageFilter.CreateBlur(0, 25) });
|
||||
|
||||
using var rect1 = new SKPath { FillType = SKPathFillType.EvenOdd };
|
||||
_panelPaint.Color = SKColor.Parse("#002A8C");
|
||||
rect1.MoveTo(29, 0);
|
||||
rect1.LineTo(62, Height);
|
||||
rect1.LineTo(Width, Height);
|
||||
rect1.LineTo(Width, 0);
|
||||
rect1.LineTo(29, 0);
|
||||
rect1.Close();
|
||||
c.DrawPath(rect1, _panelPaint);
|
||||
|
||||
_panelPaint.Shader = SKShader.CreateLinearGradient(new SKPoint(29, 0), new SKPoint(Width, Height),
|
||||
new[] { SKColor.Parse("#002A8C") }, SKShaderTileMode.Clamp);
|
||||
c.DrawPath(rect1, _panelPaint);
|
||||
|
||||
_panelPaint.Shader = SKShader.CreateRadialGradient(new SKPoint(348, 196), 300, new[] { SKColor.Parse("#0049CE"), SKColor.Parse("#002A8C") }, SKShaderTileMode.Clamp);
|
||||
c.DrawPath(rect1, _panelPaint);
|
||||
|
||||
using var rect2 = new SKPath { FillType = SKPathFillType.EvenOdd };
|
||||
|
||||
rect2.MoveTo(10, 0);
|
||||
rect2.LineTo(30, 0);
|
||||
rect2.LineTo(63, Height);
|
||||
rect2.LineTo(56, Height);
|
||||
rect2.LineTo(10, 0);
|
||||
rect2.Close();
|
||||
c.DrawPath(rect2, _panelPaint);
|
||||
|
||||
_panelPaint.Shader = SKShader.CreateLinearGradient(new SKPoint(10, 0), new SKPoint(62, Height),
|
||||
new[] { SKColor.Parse("#0045C7") }, SKShaderTileMode.Clamp);
|
||||
c.DrawPath(rect2, _panelPaint);
|
||||
}
|
||||
|
||||
private new void DrawPreview(SKCanvas c)
|
||||
{
|
||||
var previewToUse = Preview ?? DefaultPreview;
|
||||
|
||||
if (Preview == null)
|
||||
{
|
||||
previewToUse = DefaultPreview;
|
||||
ImagePaint.BlendMode = SKBlendMode.DstOut;
|
||||
ImagePaint.Color = SKColor.Parse("#00175F");
|
||||
}
|
||||
|
||||
var x = -125;
|
||||
|
||||
switch (previewToUse.Width)
|
||||
{
|
||||
case 512 when previewToUse.Height == 1024:
|
||||
previewToUse = previewToUse.ResizeWithRatio(500, 1000);
|
||||
x = 100;
|
||||
break;
|
||||
case 512 when previewToUse.Height == 512:
|
||||
case 128 when previewToUse.Height == 128:
|
||||
previewToUse = previewToUse.Resize(512);
|
||||
x = 125;
|
||||
break;
|
||||
default:
|
||||
previewToUse = previewToUse.Resize(1000, 1000);
|
||||
break;
|
||||
}
|
||||
|
||||
c.DrawBitmap(previewToUse, x, 30, ImagePaint);
|
||||
}
|
||||
|
||||
private void DrawHaze(SKCanvas c)
|
||||
{
|
||||
using var rect1 = new SKPath { FillType = SKPathFillType.EvenOdd };
|
||||
rect1.MoveTo(29, 0);
|
||||
rect1.LineTo(62, Height);
|
||||
rect1.LineTo(Width, Height);
|
||||
rect1.LineTo(Width, 0);
|
||||
rect1.LineTo(29, 0);
|
||||
rect1.Close();
|
||||
|
||||
_panelPaint.Shader = SKShader.CreateLinearGradient(new SKPoint(343, 0), new SKPoint(343, Height),
|
||||
new[] { SKColors.Transparent, SKColor.Parse("#001E70FF"), SKColor.Parse("#001E70").WithAlpha(200), SKColor.Parse("#001E70").WithAlpha(245), SKColor.Parse("#001E70") }, new[] { 0, (float) .1, (float) .65, (float) .85, 1 }, SKShaderTileMode.Clamp);
|
||||
c.DrawPath(rect1, _panelPaint);
|
||||
}
|
||||
|
||||
private void DrawName(SKCanvas c)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(DisplayName)) return;
|
||||
|
||||
DisplayNamePaint.TextSize = UserSettings.Default.AssetLanguage switch
|
||||
{
|
||||
ELanguage.Korean => 56,
|
||||
_ => 42
|
||||
};
|
||||
|
||||
DisplayNamePaint.TextScaleX = (float) 1.1;
|
||||
DisplayNamePaint.Color = SKColors.White;
|
||||
DisplayNamePaint.TextSkewX = (float) -.25;
|
||||
DisplayNamePaint.TextAlign = SKTextAlign.Left;
|
||||
|
||||
var typeface = Utils.Typefaces.TandemDisplayName;
|
||||
if (typeface == Utils.Typefaces.Default)
|
||||
{
|
||||
DisplayNamePaint.TextSize = 30;
|
||||
}
|
||||
|
||||
DisplayNamePaint.Typeface = typeface;
|
||||
var shaper = new CustomSKShaper(DisplayNamePaint.Typeface);
|
||||
c.DrawShapedText(shaper, DisplayName.ToUpper(), 97, 900, DisplayNamePaint);
|
||||
}
|
||||
|
||||
private void DrawGeneralDescription(SKCanvas c)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(_generalDescription)) return;
|
||||
|
||||
DescriptionPaint.TextSize = UserSettings.Default.AssetLanguage switch
|
||||
{
|
||||
ELanguage.Korean => 20,
|
||||
_ => 17
|
||||
};
|
||||
|
||||
DescriptionPaint.Color = SKColor.Parse("#00FFFB");
|
||||
DescriptionPaint.TextAlign = SKTextAlign.Left;
|
||||
|
||||
var typeface = Utils.Typefaces.TandemGenDescription;
|
||||
if (typeface == Utils.Typefaces.Default)
|
||||
{
|
||||
DescriptionPaint.TextSize = 21;
|
||||
}
|
||||
|
||||
DescriptionPaint.Typeface = typeface;
|
||||
var shaper = new CustomSKShaper(DescriptionPaint.Typeface);
|
||||
c.DrawShapedText(shaper, _generalDescription.ToUpper(), 97, 930, DescriptionPaint);
|
||||
}
|
||||
|
||||
private void DrawAdditionalDescription(SKCanvas c)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(_additionalDescription)) return;
|
||||
|
||||
DescriptionPaint.TextSize = UserSettings.Default.AssetLanguage switch
|
||||
{
|
||||
ELanguage.Korean => 22,
|
||||
_ => 18
|
||||
};
|
||||
|
||||
DescriptionPaint.Color = SKColor.Parse("#89D8FF");
|
||||
DescriptionPaint.TextAlign = SKTextAlign.Left;
|
||||
|
||||
var typeface = Utils.Typefaces.TandemAddDescription;
|
||||
if (typeface == Utils.Typefaces.Default)
|
||||
{
|
||||
DescriptionPaint.TextSize = 20;
|
||||
}
|
||||
|
||||
DescriptionPaint.Typeface = typeface;
|
||||
Utils.DrawMultilineText(c, _additionalDescription, Width, 0, SKTextAlign.Left,
|
||||
new SKRect(97, 960, Width - 10, Height), DescriptionPaint, out _);
|
||||
}
|
||||
}
|
||||
191
FModel/Creator/Bases/FN/BaseUserControl.cs
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Assets.Objects;
|
||||
using CUE4Parse.UE4.Objects.Core.i18N;
|
||||
using CUE4Parse.UE4.Objects.Core.Math;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using FModel.Framework;
|
||||
using SkiaSharp;
|
||||
using SkiaSharp.HarfBuzz;
|
||||
|
||||
namespace FModel.Creator.Bases.FN;
|
||||
|
||||
public class BaseUserControl : UCreator
|
||||
{
|
||||
private List<Options> _optionValues = new();
|
||||
|
||||
private readonly SKPaint _displayNamePaint = new()
|
||||
{
|
||||
IsAntialias = true, FilterQuality = SKFilterQuality.High,
|
||||
Typeface = Utils.Typefaces.DisplayName, TextSize = 45,
|
||||
Color = SKColors.White, TextAlign = SKTextAlign.Left
|
||||
};
|
||||
private readonly SKPaint _descriptionPaint = new()
|
||||
{
|
||||
IsAntialias = true, FilterQuality = SKFilterQuality.High,
|
||||
Typeface = Utils.Typefaces.DisplayName, TextSize = 25,
|
||||
Color = SKColor.Parse("88DBFF"), TextAlign = SKTextAlign.Left
|
||||
};
|
||||
|
||||
public BaseUserControl(UObject uObject, EIconStyle style) : base(uObject, style)
|
||||
{
|
||||
Width = 512;
|
||||
Height = 128;
|
||||
Margin = 32;
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
if (Object.TryGetValue(out FText optionDisplayName, "OptionDisplayName", "OptionText"))
|
||||
DisplayName = optionDisplayName.Text.ToUpperInvariant();
|
||||
if (Object.TryGetValue(out FText optionDescription, "OptionDescription", "OptionToolTip"))
|
||||
{
|
||||
Description = optionDescription.Text;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(Description)) return;
|
||||
Height += (int) _descriptionPaint.TextSize * Utils.SplitLines(Description, _descriptionPaint, Width - Margin).Count;
|
||||
Height += (int) _descriptionPaint.TextSize;
|
||||
}
|
||||
|
||||
if (Object.TryGetValue(out FStructFallback[] optionValues, "OptionValues", "Options"))
|
||||
{
|
||||
_optionValues = new List<Options>();
|
||||
foreach (var option in optionValues)
|
||||
{
|
||||
if (option.TryGetValue(out FText displayName, "DisplayName", "DisplayText"))
|
||||
{
|
||||
var opt = new Options { Option = displayName.Text.ToUpperInvariant() };
|
||||
if (option.TryGetValue(out FLinearColor color, "Value"))
|
||||
opt.Color = SKColor.Parse(color.Hex).WithAlpha(150);
|
||||
|
||||
_optionValues.Add(opt);
|
||||
}
|
||||
else if (option.TryGetValue(out FName primaryAssetName, "PrimaryAssetName"))
|
||||
{
|
||||
_optionValues.Add(new Options { Option = primaryAssetName.Text });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.TryGetValue(out FText optionOnText, "OptionOnText"))
|
||||
_optionValues.Add(new Options { Option = optionOnText.Text });
|
||||
if (Object.TryGetValue(out FText optionOffText, "OptionOffText"))
|
||||
_optionValues.Add(new Options { Option = optionOffText.Text });
|
||||
|
||||
if (Object.TryGetValue(out int iMin, "Min", "DefaultValue") &&
|
||||
Object.TryGetValue(out int iMax, "Max"))
|
||||
{
|
||||
var increment = iMin;
|
||||
if (Object.TryGetValue(out int incrementValue, "IncrementValue"))
|
||||
increment = incrementValue;
|
||||
|
||||
var format = "{0}";
|
||||
if (Object.TryGetValue(out FText unitName, "UnitName"))
|
||||
format = unitName.Text;
|
||||
|
||||
for (var i = iMin; i <= iMax; i += increment)
|
||||
{
|
||||
_optionValues.Add(new Options { Option = string.Format(format, i) });
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.TryGetValue(out float fMin, "Min", "DefaultValue") &&
|
||||
Object.TryGetValue(out float fMax, "Max"))
|
||||
{
|
||||
var increment = fMin;
|
||||
if (Object.TryGetValue(out float incrementValue, "IncrementValue"))
|
||||
increment = incrementValue;
|
||||
|
||||
var format = "{0}";
|
||||
if (Object.TryGetValue(out FText unitName, "UnitName"))
|
||||
format = unitName.Text;
|
||||
|
||||
for (var i = fMin; i <= fMax; i += increment)
|
||||
{
|
||||
_optionValues.Add(new Options { Option = string.Format(format, i) });
|
||||
}
|
||||
}
|
||||
|
||||
Height += Margin;
|
||||
Height += 35 * _optionValues.Count;
|
||||
}
|
||||
|
||||
public override SKBitmap[] Draw()
|
||||
{
|
||||
var ret = new SKBitmap(Width, Height, SKColorType.Rgba8888, SKAlphaType.Opaque);
|
||||
using var c = new SKCanvas(ret);
|
||||
|
||||
DrawBackground(c);
|
||||
DrawInformation(c);
|
||||
|
||||
return new[] { ret };
|
||||
}
|
||||
|
||||
private new void DrawBackground(SKCanvas c)
|
||||
{
|
||||
c.DrawRect(new SKRect(0, 0, Width, Height),
|
||||
new SKPaint
|
||||
{
|
||||
IsAntialias = true,
|
||||
FilterQuality = SKFilterQuality.High,
|
||||
Shader = SKShader.CreateLinearGradient(
|
||||
new SKPoint(Width / 2, Height),
|
||||
new SKPoint(Width, Height / 4),
|
||||
new[] { SKColor.Parse("01369C"), SKColor.Parse("1273C8") },
|
||||
SKShaderTileMode.Clamp)
|
||||
});
|
||||
}
|
||||
|
||||
private void DrawInformation(SKCanvas c)
|
||||
{
|
||||
// display name
|
||||
while (_displayNamePaint.MeasureText(DisplayName) > Width - Margin * 2)
|
||||
{
|
||||
_displayNamePaint.TextSize -= 2;
|
||||
}
|
||||
|
||||
var shaper = new CustomSKShaper(_displayNamePaint.Typeface);
|
||||
c.DrawShapedText(shaper, DisplayName, Margin, Margin + _displayNamePaint.TextSize, _displayNamePaint);
|
||||
#if DEBUG
|
||||
c.DrawRect(new SKRect(Margin, Margin, Width - Margin, Margin + _displayNamePaint.TextSize), new SKPaint { Color = SKColors.Blue, IsStroke = true });
|
||||
#endif
|
||||
|
||||
// description
|
||||
float y = Margin;
|
||||
if (!string.IsNullOrEmpty(DisplayName)) y += _displayNamePaint.TextSize;
|
||||
if (!string.IsNullOrEmpty(Description)) y += _descriptionPaint.TextSize + Margin / 2F;
|
||||
|
||||
Utils.DrawMultilineText(c, Description, Width, Margin, SKTextAlign.Left,
|
||||
new SKRect(Margin, y, Width - Margin, 256), _descriptionPaint, out var top);
|
||||
|
||||
// options
|
||||
foreach (var option in _optionValues)
|
||||
{
|
||||
option.Draw(c, Margin, Width, ref top);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Options
|
||||
{
|
||||
private const int _SPACE = 5;
|
||||
private const int _HEIGHT = 30;
|
||||
|
||||
private readonly SKPaint _optionPaint = new()
|
||||
{
|
||||
IsAntialias = true, FilterQuality = SKFilterQuality.High,
|
||||
Typeface = Utils.Typefaces.DisplayName, TextSize = 20,
|
||||
Color = SKColor.Parse("EEFFFF"), TextAlign = SKTextAlign.Left
|
||||
};
|
||||
|
||||
public string Option;
|
||||
public SKColor Color = SKColor.Parse("55C5FC").WithAlpha(150);
|
||||
|
||||
public void Draw(SKCanvas c, int margin, int width, ref float top)
|
||||
{
|
||||
c.DrawRect(new SKRect(margin, top, width - margin, top + _HEIGHT), new SKPaint { IsAntialias = true, FilterQuality = SKFilterQuality.High, Color = Color });
|
||||
c.DrawText(Option, margin + _SPACE * 2, top + 20 * 1.1f, _optionPaint);
|
||||
top += _HEIGHT + _SPACE;
|
||||
}
|
||||
}
|
||||
151
FModel/Creator/Bases/FN/Reward.cs
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
using System;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using FModel.Framework;
|
||||
using SkiaSharp;
|
||||
using SkiaSharp.HarfBuzz;
|
||||
|
||||
namespace FModel.Creator.Bases.FN;
|
||||
|
||||
public class Reward
|
||||
{
|
||||
private string _rewardQuantity;
|
||||
private BaseIcon _theReward;
|
||||
|
||||
public bool HasReward() => _theReward != null;
|
||||
|
||||
public Reward()
|
||||
{
|
||||
_rewardQuantity = "x0";
|
||||
}
|
||||
|
||||
public Reward(int quantity, FName primaryAssetName) : this(quantity, primaryAssetName.Text)
|
||||
{
|
||||
}
|
||||
|
||||
public Reward(int quantity, string assetName) : this()
|
||||
{
|
||||
_rewardQuantity = $"x{quantity:###,###,###}".Trim();
|
||||
|
||||
if (assetName.Contains(':'))
|
||||
{
|
||||
var parts = assetName.Split(':');
|
||||
|
||||
if (parts[0].Equals("HomebaseBannerIcon", StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
if (!Utils.TryLoadObject($"FortniteGame/Content/Items/BannerIcons/{parts[1]}.{parts[1]}", out UObject p))
|
||||
return;
|
||||
|
||||
_theReward = new BaseIcon(p, EIconStyle.Default);
|
||||
_theReward.ParseForReward(false);
|
||||
_theReward.Border[0] = SKColors.White;
|
||||
_rewardQuantity = _theReward.DisplayName;
|
||||
}
|
||||
else GetReward(parts[1]);
|
||||
}
|
||||
else GetReward(assetName);
|
||||
}
|
||||
|
||||
public Reward(UObject uObject)
|
||||
{
|
||||
_theReward = new BaseIcon(uObject, EIconStyle.Default);
|
||||
_theReward.ParseForReward(false);
|
||||
_theReward.Border[0] = SKColors.White;
|
||||
_rewardQuantity = _theReward.DisplayName;
|
||||
}
|
||||
|
||||
private readonly SKPaint _rewardPaint = new()
|
||||
{
|
||||
IsAntialias = true, FilterQuality = SKFilterQuality.High
|
||||
};
|
||||
|
||||
public void DrawQuest(SKCanvas c, SKRect rect)
|
||||
{
|
||||
_rewardPaint.TextSize = 50;
|
||||
if (HasReward())
|
||||
{
|
||||
c.DrawBitmap((_theReward.Preview ?? _theReward.DefaultPreview).Resize((int) rect.Height), new SKPoint(rect.Left, rect.Top), _rewardPaint);
|
||||
|
||||
_rewardPaint.Color = _theReward.Border[0];
|
||||
_rewardPaint.Typeface = _rewardQuantity.StartsWith("x") ? Utils.Typefaces.BundleNumber : Utils.Typefaces.Bundle;
|
||||
_rewardPaint.ImageFilter = SKImageFilter.CreateDropShadow(0, 0, 5, 5, _theReward.Background[0].WithAlpha(150));
|
||||
while (_rewardPaint.MeasureText(_rewardQuantity) > rect.Width)
|
||||
{
|
||||
_rewardPaint.TextSize -= 1;
|
||||
}
|
||||
|
||||
var shaper = new CustomSKShaper(_rewardPaint.Typeface);
|
||||
c.DrawShapedText(shaper, _rewardQuantity, rect.Left + rect.Height + 25, rect.MidY + 20, _rewardPaint);
|
||||
}
|
||||
else
|
||||
{
|
||||
_rewardPaint.Color = SKColors.White;
|
||||
_rewardPaint.Typeface = Utils.Typefaces.BundleNumber;
|
||||
c.DrawText("No Reward", new SKPoint(rect.Left, rect.MidY + 20), _rewardPaint);
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawSeasonWin(SKCanvas c, int size)
|
||||
{
|
||||
if (!HasReward()) return;
|
||||
c.DrawBitmap((_theReward.Preview ?? _theReward.DefaultPreview).Resize(size), new SKPoint(0, 0), _rewardPaint);
|
||||
}
|
||||
|
||||
public void DrawSeason(SKCanvas c, int x, int y, int areaSize)
|
||||
{
|
||||
if (!HasReward()) return;
|
||||
|
||||
// area + icon
|
||||
_rewardPaint.Color = SKColor.Parse("#0F5CAF");
|
||||
c.DrawRect(new SKRect(x, y, x + areaSize, y + areaSize), _rewardPaint);
|
||||
c.DrawBitmap(_theReward.Preview.Resize(areaSize), new SKPoint(x, y), _rewardPaint);
|
||||
|
||||
// rarity color
|
||||
_rewardPaint.Color = _theReward.Background[0];
|
||||
var pathBottom = new SKPath {FillType = SKPathFillType.EvenOdd};
|
||||
pathBottom.MoveTo(x, y + areaSize);
|
||||
pathBottom.LineTo(x, y + areaSize - areaSize / 25 * 2.5f);
|
||||
pathBottom.LineTo(x + areaSize, y + areaSize - areaSize / 25 * 4.5f);
|
||||
pathBottom.LineTo(x + areaSize, y + areaSize);
|
||||
pathBottom.Close();
|
||||
c.DrawPath(pathBottom, _rewardPaint);
|
||||
}
|
||||
|
||||
private void GetReward(string trigger)
|
||||
{
|
||||
switch (trigger.ToLower())
|
||||
{
|
||||
// case "athenabattlestar":
|
||||
// _theReward = new BaseIcon(null, EIconStyle.Default);
|
||||
// _theReward.Border[0] = SKColor.Parse("FFDB67");
|
||||
// _theReward.Background[0] = SKColor.Parse("8F4A20");
|
||||
// _theReward.Preview = Utils.GetBitmap("FortniteGame/Content/Athena/UI/Frontend/Art/T_UI_BP_BattleStar_L.T_UI_BP_BattleStar_L");
|
||||
// break;
|
||||
// case "athenaseasonalxp":
|
||||
// _theReward = new BaseIcon(null, EIconStyle.Default);
|
||||
// _theReward.Border[0] = SKColor.Parse("E6FDB1");
|
||||
// _theReward.Background[0] = SKColor.Parse("51830F");
|
||||
// _theReward.Preview = Utils.GetBitmap("FortniteGame/Content/UI/Foundation/Textures/Icons/Items/T-FNBR-XPUncommon-L.T-FNBR-XPUncommon-L");
|
||||
// break;
|
||||
// case "mtxgiveaway":
|
||||
// _theReward = new BaseIcon(null, EIconStyle.Default);
|
||||
// _theReward.Border[0] = SKColor.Parse("DCE6FF");
|
||||
// _theReward.Background[0] = SKColor.Parse("64A0AF");
|
||||
// _theReward.Preview = Utils.GetBitmap("FortniteGame/Content/UI/Foundation/Textures/Icons/Items/T-Items-MTX.T-Items-MTX");
|
||||
// break;
|
||||
default:
|
||||
{
|
||||
var path = Utils.GetFullPath($"FortniteGame/(?:Content/Athena|Content/Items|Plugins/GameFeatures)/.*?/{trigger}.uasset"); // path has no objectname and its needed so we push the trigger again as the objectname
|
||||
if (!string.IsNullOrWhiteSpace(path) && Utils.TryLoadObject(path.Replace("uasset", trigger), out UObject d))
|
||||
{
|
||||
_theReward = new BaseIcon(d, EIconStyle.Default);
|
||||
_theReward.ParseForReward(false);
|
||||
_theReward.Border[0] = SKColors.White;
|
||||
_rewardQuantity = $"{_theReward.DisplayName} ({_rewardQuantity})";
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
287
FModel/Creator/Bases/MV/BaseFighter.cs
Normal file
|
|
@ -0,0 +1,287 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Assets.Exports.Engine;
|
||||
using CUE4Parse.UE4.Assets.Exports.Material;
|
||||
using CUE4Parse.UE4.Assets.Objects;
|
||||
using CUE4Parse.UE4.Objects.Core.i18N;
|
||||
using CUE4Parse.UE4.Objects.Core.Math;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using FModel.Extensions;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace FModel.Creator.Bases.MV;
|
||||
|
||||
public class BaseFighter : UCreator
|
||||
{
|
||||
private float _xOffset = 1f;
|
||||
private float _yOffset = 1f;
|
||||
private float _zoom = 1f;
|
||||
|
||||
private readonly SKBitmap _pattern;
|
||||
private readonly SKBitmap _perk;
|
||||
private readonly SKBitmap _emote;
|
||||
private readonly SKBitmap _skin;
|
||||
|
||||
private (SKBitmap, List<string>) _fighterType;
|
||||
private readonly List<SKBitmap> _recommendedPerks;
|
||||
private readonly List<SKBitmap> _availableTaunts;
|
||||
private readonly List<SKBitmap> _skins;
|
||||
|
||||
public BaseFighter(UObject uObject, EIconStyle style) : base(uObject, style)
|
||||
{
|
||||
Width = 1024;
|
||||
DisplayNamePaint.TextSize = 100;
|
||||
DisplayNamePaint.TextAlign = SKTextAlign.Left;
|
||||
DisplayNamePaint.Typeface = Utils.Typefaces.TandemDisplayName;
|
||||
DescriptionPaint.TextSize = 25;
|
||||
DescriptionPaint.Typeface = Utils.Typefaces.TandemGenDescription;
|
||||
DefaultPreview = Utils.GetBitmap("/Game/Panda_Main/UI/PreMatch/Images/DiamondPortraits/0010_Random.0010_Random");
|
||||
|
||||
_pattern = Utils.GetBitmap("/Game/Panda_Main/UI/Assets/UI_Textures/halftone_jagged.halftone_jagged");
|
||||
_perk = Utils.GetBitmap("/Game/Panda_Main/UI/Assets/Icons/ui_icons_perks.ui_icons_perks");
|
||||
_emote = Utils.GetBitmap("/Game/Panda_Main/UI/Assets/Icons/ui_icons_emote.ui_icons_emote");
|
||||
_skin = Utils.GetBitmap("/Game/Panda_Main/UI/Assets/Icons/ui_icons_skins.ui_icons_skins");
|
||||
_fighterType.Item2 = new List<string>();
|
||||
_recommendedPerks = new List<SKBitmap>();
|
||||
_availableTaunts = new List<SKBitmap>();
|
||||
_skins = new List<SKBitmap>();
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
if (Object.TryGetValue(out FLinearColor backgroundColor, "BackgroundColor"))
|
||||
Background = new[] { SKColor.Parse(backgroundColor.Hex) };
|
||||
|
||||
if (Object.TryGetValue(out FSoftObjectPath portraitMaterial, "CollectionsPortraitMaterial") &&
|
||||
portraitMaterial.TryLoad(out UMaterialInstanceConstant portrait))
|
||||
{
|
||||
_xOffset = Math.Abs(portrait.ScalarParameterValues.FirstOrDefault(x => x.ParameterInfo.Name.Text == "XOffset")?.ParameterValue ?? 1f);
|
||||
_yOffset = Math.Abs(portrait.ScalarParameterValues.FirstOrDefault(x => x.ParameterInfo.Name.Text == "YOffset")?.ParameterValue / 10 ?? 1f);
|
||||
_zoom = Math.Clamp(portrait.ScalarParameterValues.FirstOrDefault(x => x.ParameterInfo.Name.Text == "Zoom")?.ParameterValue ?? 1f, 0, 1);
|
||||
Preview = Utils.GetBitmap(portrait);
|
||||
}
|
||||
else if (Object.TryGetValue(out FSoftObjectPath portraitTexture, "NewCharacterSelectPortraitTexture", "HUDPortraitTexture"))
|
||||
Preview = Utils.GetBitmap(portraitTexture);
|
||||
|
||||
if (Object.TryGetValue(out FText displayName, "DisplayName"))
|
||||
DisplayName = displayName.Text;
|
||||
|
||||
GetFighterClassInfo(Object.GetOrDefault("Class", EFighterClass.Support));
|
||||
_fighterType.Item2.Add(Utils.GetLocalizedResource(Object.GetOrDefault("Type", EFighterType.Horizontal)));
|
||||
if (Object.TryGetValue(out FText property, "Property"))
|
||||
_fighterType.Item2.Add(property.Text);
|
||||
|
||||
if (Object.TryGetValue(out UScriptSet recommendedPerks, "RecommendedPerkDatas")) // PORCO DIO WB USE ARRAYS!!!!!!
|
||||
{
|
||||
foreach (var recommendedPerk in recommendedPerks.Properties)
|
||||
{
|
||||
if (recommendedPerk.GenericValue is not FPackageIndex packageIndex ||
|
||||
!Utils.TryGetPackageIndexExport(packageIndex, out UObject export) ||
|
||||
!export.TryGetValue(out FSoftObjectPath rewardThumbnail, "RewardThumbnail"))
|
||||
continue;
|
||||
|
||||
_recommendedPerks.Add(Utils.GetBitmap(rewardThumbnail));
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.TryGetValue(out FSoftObjectPath[] availableTaunts, "AvailableTauntData"))
|
||||
{
|
||||
foreach (var taunt in availableTaunts)
|
||||
{
|
||||
if (!Utils.TryLoadObject(taunt.AssetPathName.Text, out UObject export) ||
|
||||
!export.TryGetValue(out FSoftObjectPath rewardThumbnail, "RewardThumbnail"))
|
||||
continue;
|
||||
|
||||
_availableTaunts.Add(Utils.GetBitmap(rewardThumbnail));
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.TryGetValue(out FSoftObjectPath[] skins, "Skins"))
|
||||
{
|
||||
foreach (var skin in skins)
|
||||
{
|
||||
if (!Utils.TryLoadObject(skin.AssetPathName.Text, out UObject export) ||
|
||||
!export.TryGetValue(out FSoftObjectPath rewardThumbnail, "RewardThumbnail"))
|
||||
continue;
|
||||
|
||||
_skins.Add(Utils.GetBitmap(rewardThumbnail));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override SKBitmap[] Draw()
|
||||
{
|
||||
var ret = new SKBitmap(Width, Height, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
using var c = new SKCanvas(ret);
|
||||
|
||||
DrawBackground(c);
|
||||
DrawPreview(c);
|
||||
DrawDisplayName(c);
|
||||
DrawFighterInfo(c);
|
||||
DrawRecommendedPerks(c);
|
||||
DrawAvailableTaunts(c);
|
||||
DrawSkins(c);
|
||||
|
||||
return new[] { ret };
|
||||
}
|
||||
|
||||
private void GetFighterClassInfo(EFighterClass clas)
|
||||
{
|
||||
if (!Utils.TryLoadObject("/Game/Panda_Main/UI/In-Game/Data/UICharacterClassInfo_Datatable.UICharacterClassInfo_Datatable", out UDataTable dataTable))
|
||||
return;
|
||||
|
||||
var row = dataTable.RowMap.ElementAt((int) clas).Value;
|
||||
if (!row.TryGetValue(out FText displayName, "DisplayName_5_9DB5DDFF490E1F4AD72329866F96B81D") ||
|
||||
!row.TryGetValue(out FPackageIndex icon, "Icon_8_711534AD4F240D4B001AA6A471EA1895"))
|
||||
return;
|
||||
|
||||
_fighterType.Item1 = Utils.GetBitmap(icon);
|
||||
_fighterType.Item2.Add(displayName.Text);
|
||||
}
|
||||
|
||||
private new void DrawBackground(SKCanvas c)
|
||||
{
|
||||
c.DrawRect(new SKRect(0, 0, Width, Height),
|
||||
new SKPaint
|
||||
{
|
||||
IsAntialias = true, FilterQuality = SKFilterQuality.High, Color = Background[0]
|
||||
});
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(DisplayName))
|
||||
{
|
||||
c.DrawText(DisplayName, -50, 125, new()
|
||||
{
|
||||
IsAntialias = true, FilterQuality = SKFilterQuality.High,
|
||||
Typeface = Utils.Typefaces.DisplayName, TextSize = 200,
|
||||
TextScaleX = .95f, TextSkewX = -0.25f, Color = SKColors.Black.WithAlpha(25)
|
||||
});
|
||||
}
|
||||
|
||||
c.DrawBitmap(_pattern, new SKRect(0, Height / 2, Width, Height), new SKPaint
|
||||
{
|
||||
IsAntialias = true, FilterQuality = SKFilterQuality.High, BlendMode = SKBlendMode.SoftLight
|
||||
});
|
||||
|
||||
var path = new SKPath { FillType = SKPathFillType.EvenOdd };
|
||||
path.MoveTo(0, Height);
|
||||
path.LineTo(0, Height - 20);
|
||||
path.LineTo(Width, Height - 60);
|
||||
path.LineTo(Width, Height);
|
||||
path.Close();
|
||||
c.DrawPath(path, new SKPaint
|
||||
{
|
||||
IsAntialias = true,
|
||||
FilterQuality = SKFilterQuality.High,
|
||||
Color = SKColor.Parse("#141629")
|
||||
});
|
||||
}
|
||||
|
||||
private new void DrawPreview(SKCanvas c)
|
||||
{
|
||||
var img = (Preview ?? DefaultPreview).ResizeWithRatio(_zoom);
|
||||
var x_offset = img.Width * _xOffset;
|
||||
var y_offset = img.Height * -_yOffset;
|
||||
c.DrawBitmap(img, new SKRect(Width + x_offset - img.Width, y_offset, Width + x_offset, img.Height + y_offset), ImagePaint);
|
||||
}
|
||||
|
||||
private new void DrawDisplayName(SKCanvas c)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(DisplayName)) return;
|
||||
c.DrawText(DisplayName.ToUpper(), 50, 100, DisplayNamePaint);
|
||||
}
|
||||
|
||||
private void DrawFighterInfo(SKCanvas c)
|
||||
{
|
||||
if (_fighterType.Item1 != null)
|
||||
c.DrawBitmap(_fighterType.Item1, new SKRect(50, 112.5f, 98, 160.5f), ImagePaint);
|
||||
|
||||
c.DrawText(string.Join(" | ", _fighterType.Item2), 98, 145, DescriptionPaint);
|
||||
}
|
||||
|
||||
private void DrawRecommendedPerks(SKCanvas c)
|
||||
{
|
||||
const int x = 50;
|
||||
const int y = 200;
|
||||
const int size = 64;
|
||||
|
||||
ImagePaint.ImageFilter = null;
|
||||
ImagePaint.BlendMode = SKBlendMode.SoftLight;
|
||||
c.DrawBitmap(_perk, new SKRect(x, y, x + size / 2, y + size / 2), ImagePaint);
|
||||
if (_recommendedPerks.Count < 1) return;
|
||||
|
||||
ImagePaint.BlendMode = SKBlendMode.SrcOver;
|
||||
ImagePaint.ImageFilter = SKImageFilter.CreateDropShadow(0, 0, 2.5f, 2.5f, SKColors.Black);
|
||||
c.DrawBitmap(_recommendedPerks[1], new SKRect(161, y, 225, y + size), ImagePaint);
|
||||
c.DrawBitmap(_recommendedPerks[2], new SKRect(193, y + size / 2, 257, y + size * 1.5f), ImagePaint);
|
||||
c.DrawBitmap(_recommendedPerks[3], new SKRect(161, y + size, 225, y + size * 2), ImagePaint);
|
||||
|
||||
ImagePaint.ImageFilter = SKImageFilter.CreateDropShadow(0, 0, 5, 5, SKColors.Black.WithAlpha(150));
|
||||
c.DrawBitmap(_recommendedPerks[0], new SKRect(x, y, x + size * 2, y + size * 2), ImagePaint);
|
||||
}
|
||||
|
||||
private void DrawAvailableTaunts(SKCanvas c)
|
||||
{
|
||||
var x = 300;
|
||||
const int y = 232;
|
||||
const int size = 64;
|
||||
|
||||
ImagePaint.ImageFilter = null;
|
||||
ImagePaint.BlendMode = SKBlendMode.SoftLight;
|
||||
c.DrawBitmap(_emote, new SKRect(x, y - size / 2, x + size / 2, y), ImagePaint);
|
||||
if (_availableTaunts.Count < 1) return;
|
||||
|
||||
ImagePaint.BlendMode = SKBlendMode.SrcOver;
|
||||
ImagePaint.ImageFilter = SKImageFilter.CreateDropShadow(0, 0, 1.5f, 1.5f, SKColors.Black);
|
||||
|
||||
foreach (var taunt in _availableTaunts)
|
||||
{
|
||||
c.DrawBitmap(taunt, new SKRect(x, y, x + size, y + size), ImagePaint);
|
||||
x += size;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawSkins(SKCanvas c)
|
||||
{
|
||||
var x = 50;
|
||||
const int y = 333;
|
||||
const int size = 128;
|
||||
|
||||
ImagePaint.ImageFilter = null;
|
||||
ImagePaint.BlendMode = SKBlendMode.SoftLight;
|
||||
c.DrawBitmap(_skin, new SKRect(x, y, x + size / 4, y + size / 4), ImagePaint);
|
||||
if (_skins.Count < 1) return;
|
||||
|
||||
ImagePaint.BlendMode = SKBlendMode.SrcOver;
|
||||
ImagePaint.ImageFilter = SKImageFilter.CreateDropShadow(0, 0, 1.5f, 1.5f, SKColors.Black);
|
||||
foreach (var skin in _skins)
|
||||
{
|
||||
c.DrawBitmap(skin, new SKRect(x, y, x + size, y + size), ImagePaint);
|
||||
x += size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum EFighterClass : byte
|
||||
{
|
||||
Mage = 4,
|
||||
Tank = 3,
|
||||
Fighter = 2,
|
||||
Bruiser = 2,
|
||||
Assassin = 1,
|
||||
Support = 0 // Default
|
||||
}
|
||||
|
||||
public enum EFighterType : byte
|
||||
{
|
||||
[Description("B980C82D40FF37FD359C74A339CE1B3A")]
|
||||
Hybrid = 2,
|
||||
|
||||
[Description("2C55443D47164019BE73A5ABDC670F36")]
|
||||
Vertical = 1,
|
||||
|
||||
[Description("97A60DD54AA23D4B93D5B891F729BF5C")]
|
||||
Horizontal = 0 // Default
|
||||
}
|
||||
344
FModel/Creator/Bases/MV/BasePandaIcon.cs
Normal file
|
|
@ -0,0 +1,344 @@
|
|||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Assets.Exports.Engine;
|
||||
using CUE4Parse.UE4.Objects.Core.i18N;
|
||||
using CUE4Parse.UE4.Objects.Core.Math;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace FModel.Creator.Bases.MV;
|
||||
|
||||
public class BasePandaIcon : UCreator
|
||||
{
|
||||
private float _y_offset;
|
||||
private ERewardRarity _rarity;
|
||||
private string _type;
|
||||
|
||||
protected readonly List<(SKBitmap, string)> Pictos;
|
||||
|
||||
public BasePandaIcon(UObject uObject, EIconStyle style) : base(uObject, style)
|
||||
{
|
||||
Width = 1024;
|
||||
Margin = 30;
|
||||
DisplayNamePaint.TextSize = 50;
|
||||
DisplayNamePaint.TextAlign = SKTextAlign.Left;
|
||||
DisplayNamePaint.Color = SKColor.Parse("#191C33");
|
||||
DescriptionPaint.TextSize = 25;
|
||||
DefaultPreview = Utils.GetBitmap("/Game/Panda_Main/UI/PreMatch/Images/DiamondPortraits/0010_Random.0010_Random");
|
||||
|
||||
_y_offset = Height / 2 + DescriptionPaint.TextSize;
|
||||
Pictos = new List<(SKBitmap, string)>();
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
var category = Object.GetOrDefault("Category", EPerkCategory.Offense);
|
||||
_rarity = Object.GetOrDefault("Rarity", ERewardRarity.None);
|
||||
|
||||
_type = Object.ExportType;
|
||||
var t = _type switch // ERewardType like
|
||||
{
|
||||
"StatTrackingBundleData" => EItemType.Badge,
|
||||
"AnnouncerPackData" => EItemType.Announcer,
|
||||
"CharacterGiftData" => EItemType.ExperiencePoints,
|
||||
"ProfileIconData" => EItemType.ProfileIcon,
|
||||
"RingOutVfxData" => EItemType.Ringout,
|
||||
"BannerData" => EItemType.Banner,
|
||||
"EmoteData" => EItemType.Sticker,
|
||||
"QuestData" => EItemType.Mission,
|
||||
"TauntData" => EItemType.Emote,
|
||||
"SkinData" => EItemType.Variant,
|
||||
"PerkData" when category == EPerkCategory.CharacterSpecific => EItemType.SignaturePerk,
|
||||
"PerkData" => EItemType.Perk,
|
||||
_ => EItemType.Unknown
|
||||
};
|
||||
|
||||
if (t == EItemType.SignaturePerk) _rarity = ERewardRarity.Legendary;
|
||||
Background = GetRarityBackground(_rarity);
|
||||
|
||||
if (Object.TryGetValue(out FSoftObjectPath rewardThumbnail, "RewardThumbnail", "DisplayTextureRef", "Texture"))
|
||||
Preview = Utils.GetBitmap(rewardThumbnail);
|
||||
else if (Object.TryGetValue(out FPackageIndex icon, "Icon"))
|
||||
Preview = Utils.GetBitmap(icon);
|
||||
|
||||
if (Object.TryGetValue(out FText displayName, "DisplayName", "QuestName"))
|
||||
DisplayName = displayName.Text;
|
||||
if (Object.TryGetValue(out FText description, "Description", "QuestDescription"))
|
||||
Description = Utils.RemoveHtmlTags(description.Text);
|
||||
|
||||
var unlockLocation = Object.GetOrDefault("UnlockLocation", EUnlockLocation.None);
|
||||
if (t == EItemType.Unknown && unlockLocation == EUnlockLocation.CharacterMastery) t = EItemType.MasteryLevel;
|
||||
|
||||
Pictos.Add((Utils.GetBitmap("/Game/Panda_Main/UI/Assets/Icons/ui_icons_unlocked.ui_icons_unlocked"), Utils.GetLocalizedResource(unlockLocation)));
|
||||
if (Object.TryGetValue(out string slug, "Slug"))
|
||||
{
|
||||
t = _type switch
|
||||
{
|
||||
"HydraSyncedDataAsset" when slug == "gold" => EItemType.Gold,
|
||||
"HydraSyncedDataAsset" when slug == "gleamium" => EItemType.Gleamium,
|
||||
"HydraSyncedDataAsset" when slug == "match_toasts" => EItemType.Toast,
|
||||
_ => t
|
||||
};
|
||||
Pictos.Add((Utils.GetBitmap("/Game/Panda_Main/UI/Assets/Icons/ui_icons_link.ui_icons_link"), slug));
|
||||
}
|
||||
|
||||
if (Object.TryGetValue(out int xpValue, "XPValue"))
|
||||
DisplayName += $" (+{xpValue})";
|
||||
|
||||
if (Utils.TryLoadObject("/Game/Panda_Main/UI/Prototype/Foundation/Types/DT_EconomyGlossary.DT_EconomyGlossary", out UDataTable dataTable))
|
||||
{
|
||||
if (t != EItemType.Unknown &&
|
||||
dataTable.RowMap.ElementAt((int) t).Value.TryGetValue(out FText name, "Name_14_7F75AD6047CBDEA7B252B1BD76EF84B9"))
|
||||
_type = name.Text;
|
||||
}
|
||||
}
|
||||
|
||||
public override SKBitmap[] Draw()
|
||||
{
|
||||
var ret = new SKBitmap(Width, Height, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
using var c = new SKCanvas(ret);
|
||||
|
||||
DrawBackground(c);
|
||||
DrawPreview(c);
|
||||
DrawDisplayName(c);
|
||||
DrawDescription(c);
|
||||
DrawPictos(c);
|
||||
|
||||
return new[] { ret };
|
||||
}
|
||||
|
||||
private SKColor[] GetRarityBackground(ERewardRarity rarity)
|
||||
{
|
||||
return rarity switch // the colors here are the base color and brighter color that the game uses for rarities from the "Rarity to Color" blueprint function
|
||||
{
|
||||
ERewardRarity.Common => new[]
|
||||
{
|
||||
SKColor.Parse(new FLinearColor(0.068478f, 0.651406f, 0.016807f, 1.000000f).Hex),
|
||||
SKColor.Parse(new FLinearColor(0.081422f, 1.000000f, 0.000000f, 1.000000f).Hex)
|
||||
},
|
||||
ERewardRarity.Rare => new[]
|
||||
{
|
||||
SKColor.Parse(new FLinearColor(0.035911f, 0.394246f, 0.900000f, 1.000000f).Hex),
|
||||
SKColor.Parse(new FLinearColor(0.033333f, 0.434207f, 1.000000f, 1.000000f).Hex)
|
||||
},
|
||||
ERewardRarity.Epic => new[]
|
||||
{
|
||||
SKColor.Parse(new FLinearColor(0.530391f, 0.060502f, 0.900000f, 1.000000f).Hex),
|
||||
SKColor.Parse(new FLinearColor(0.579907f, 0.045833f, 1.000000f, 1.000000f).Hex)
|
||||
},
|
||||
ERewardRarity.Legendary => new[]
|
||||
{
|
||||
SKColor.Parse(new FLinearColor(1.000000f, 0.223228f, 0.002428f, 1.000000f).Hex),
|
||||
SKColor.Parse(new FLinearColor(1.000000f, 0.479320f, 0.030713f, 1.000000f).Hex)
|
||||
},
|
||||
_ => new[]
|
||||
{
|
||||
SKColor.Parse(new FLinearColor(0.194618f, 0.651406f, 0.630757f, 1.000000f).Hex),
|
||||
SKColor.Parse(new FLinearColor(0.273627f, 0.955208f, 0.914839f, 1.000000f).Hex)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private new void DrawBackground(SKCanvas c)
|
||||
{
|
||||
c.DrawRect(new SKRect(0, 0, Width, Height),
|
||||
new SKPaint
|
||||
{
|
||||
IsAntialias = true, FilterQuality = SKFilterQuality.High, Color = SKColor.Parse("#F3FCF0")
|
||||
});
|
||||
|
||||
var has_tr = _rarity != ERewardRarity.None;
|
||||
var tr = Utils.GetLocalizedResource(_rarity);
|
||||
var tr_paint = new SKPaint
|
||||
{
|
||||
IsAntialias = true,
|
||||
FilterQuality = SKFilterQuality.High,
|
||||
TextAlign = SKTextAlign.Right,
|
||||
TextSize = 35,
|
||||
Color = SKColors.White,
|
||||
Typeface = Utils.Typefaces.DisplayName
|
||||
};
|
||||
|
||||
var path = new SKPath { FillType = SKPathFillType.EvenOdd };
|
||||
path.MoveTo(0, Height);
|
||||
path.LineTo(14, Height);
|
||||
path.LineTo(20, 20);
|
||||
if (has_tr)
|
||||
{
|
||||
const int margin = 15;
|
||||
var width = tr_paint.MeasureText(tr);
|
||||
path.LineTo(Width - width - margin * 2, 15);
|
||||
path.LineTo(Width - width - margin * 2.5f, 60);
|
||||
path.LineTo(Width, 55);
|
||||
}
|
||||
else
|
||||
{
|
||||
path.LineTo(Width, 14);
|
||||
}
|
||||
path.LineTo(Width, 0);
|
||||
path.LineTo(0, 0);
|
||||
path.LineTo(0, Height);
|
||||
path.Close();
|
||||
c.DrawPath(path, new SKPaint
|
||||
{
|
||||
IsAntialias = true,
|
||||
FilterQuality = SKFilterQuality.High,
|
||||
Shader = SKShader.CreateLinearGradient(
|
||||
new SKPoint(Width / 2, Height), new SKPoint(Width, Height / 4), Background, SKShaderTileMode.Clamp)
|
||||
});
|
||||
|
||||
if (has_tr)
|
||||
{
|
||||
var x = Width - 20f;
|
||||
foreach (var a in tr.Select(character => character.ToString()).Reverse())
|
||||
{
|
||||
c.DrawText(a, x, 40, tr_paint);
|
||||
x -= tr_paint.MeasureText(a) - 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private new void DrawPreview(SKCanvas c)
|
||||
{
|
||||
const int size = 384;
|
||||
var y = Height - size - Margin * 2;
|
||||
c.DrawBitmap(Preview ?? DefaultPreview, new SKRect(Margin, y, size + Margin, y + size), ImagePaint);
|
||||
}
|
||||
|
||||
private new void DrawDisplayName(SKCanvas c)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(DisplayName))
|
||||
return;
|
||||
|
||||
var x = 450f;
|
||||
while (DisplayNamePaint.MeasureText(DisplayName) > Width - x / 1.25)
|
||||
{
|
||||
DisplayNamePaint.TextSize -= 1;
|
||||
}
|
||||
|
||||
var y = Height / 2 - DisplayNamePaint.TextSize / 4;
|
||||
foreach (var a in DisplayName.Select(character => character.ToString()))
|
||||
{
|
||||
c.DrawText(a, x, y, DisplayNamePaint);
|
||||
x += DisplayNamePaint.MeasureText(a) - 4;
|
||||
}
|
||||
}
|
||||
|
||||
private new void DrawDescription(SKCanvas c)
|
||||
{
|
||||
const int x = 450;
|
||||
DescriptionPaint.Color = Background[0];
|
||||
c.DrawText(_type.ToUpper(), x, 170, DescriptionPaint);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(Description)) return;
|
||||
|
||||
DescriptionPaint.Color = SKColor.Parse("#191C33");
|
||||
Utils.DrawMultilineText(c, Description, Width - x, Margin, SKTextAlign.Left,
|
||||
new SKRect(x, _y_offset, Width - Margin, Height - Margin), DescriptionPaint, out _y_offset);
|
||||
}
|
||||
|
||||
private void DrawPictos(SKCanvas c)
|
||||
{
|
||||
if (Pictos.Count < 1) return;
|
||||
|
||||
const float x = 450f;
|
||||
const int size = 24;
|
||||
var color = SKColor.Parse("#495B6E");
|
||||
var paint = new SKPaint
|
||||
{
|
||||
IsAntialias = true,
|
||||
FilterQuality = SKFilterQuality.High,
|
||||
TextSize = 27,
|
||||
Color = color,
|
||||
Typeface = Utils.Typefaces.Default
|
||||
};
|
||||
|
||||
ImagePaint.ColorFilter = SKColorFilter.CreateBlendMode(color, SKBlendMode.SrcIn);
|
||||
|
||||
foreach (var picto in Pictos)
|
||||
{
|
||||
c.DrawBitmap(picto.Item1, new SKRect(x, _y_offset + 10, x + size, _y_offset + 10 + size), ImagePaint);
|
||||
c.DrawText(picto.Item2, x + size + 10, _y_offset + size + 6, paint);
|
||||
_y_offset += size + 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum ERewardRarity : byte
|
||||
{
|
||||
[Description("0D4B15CE4FB6F2BC5E5F5FAA9E8B376C")]
|
||||
None = 0, // Default
|
||||
|
||||
[Description("0FCDEF47485E2C3D0D477988C481D8E3")]
|
||||
Common = 1,
|
||||
|
||||
[Description("18241CA7441AE16AAFB6EFAB499FF981")]
|
||||
Rare = 2,
|
||||
|
||||
[Description("D999D9CB4754D1078BF9A1B34A231005")]
|
||||
Epic = 3,
|
||||
|
||||
[Description("705AE967407D6EF8870E988A08C6900E")]
|
||||
Legendary = 4
|
||||
}
|
||||
|
||||
public enum EUnlockLocation : byte
|
||||
{
|
||||
[Description("0D4B15CE4FB6F2BC5E5F5FAA9E8B376C")]
|
||||
None = 0, // Default
|
||||
|
||||
[Description("0AFBCE5F41D930D6E9B5138C8EBCFE87")]
|
||||
Shop = 1,
|
||||
|
||||
[Description("062F178B4EE74502C9AD9D878F3D7CEA")]
|
||||
AccountLevel = 2,
|
||||
|
||||
[Description("1AE7A5DF477B2B5F4B3CCC8DCD732884")]
|
||||
CharacterMastery = 3,
|
||||
|
||||
[Description("0B37731C49DC9AE1EAC566950C1A329D")]
|
||||
Battlepass = 4,
|
||||
|
||||
[Description("16F160084187479E5D471786190AE5B7")]
|
||||
CharacterAffinity = 5,
|
||||
|
||||
[Description("E5C1E35C406C585E83B5D18A817FA0B4")]
|
||||
GuildBoss = 6,
|
||||
|
||||
[Description("4A89F5DD432113750EF52D8B58977DCE")]
|
||||
Tutorial = 7
|
||||
}
|
||||
|
||||
public enum EPerkCategory : byte
|
||||
{
|
||||
Offense = 0, // Default
|
||||
Defense = 1,
|
||||
Utility = 2,
|
||||
CharacterSpecific = 3
|
||||
}
|
||||
|
||||
public enum EItemType
|
||||
{
|
||||
Unknown = -1,
|
||||
Announcer,
|
||||
Badge,
|
||||
Banner,
|
||||
BattlePassPoints,
|
||||
Emote,
|
||||
ExperiencePoints,
|
||||
Gleamium,
|
||||
Gold,
|
||||
MasteryLevel,
|
||||
Mission,
|
||||
Perk,
|
||||
PlayerLevel,
|
||||
ProfileIcon,
|
||||
Rested,
|
||||
Ringout,
|
||||
SignaturePerk,
|
||||
Sticker,
|
||||
Toast,
|
||||
Variant
|
||||
}
|
||||
45
FModel/Creator/Bases/MV/BasePerkGroup.cs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
using System.Collections.Generic;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Assets.Objects;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace FModel.Creator.Bases.MV;
|
||||
|
||||
public class BasePerkGroup : UCreator
|
||||
{
|
||||
private readonly List<BasePandaIcon> _perks;
|
||||
|
||||
public BasePerkGroup(UObject uObject, EIconStyle style) : base(uObject, style)
|
||||
{
|
||||
_perks = new List<BasePandaIcon>();
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
if (Object.TryGetValue(out UScriptSet perks, "Perks")) // PORCO DIO WB USE ARRAYS!!!!!!
|
||||
{
|
||||
foreach (var perk in perks.Properties)
|
||||
{
|
||||
if (perk.GenericValue is not FPackageIndex packageIndex ||
|
||||
!Utils.TryGetPackageIndexExport(packageIndex, out UObject export))
|
||||
continue;
|
||||
|
||||
var icon = new BasePandaIcon(export, Style);
|
||||
icon.ParseForInfo();
|
||||
_perks.Add(icon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override SKBitmap[] Draw()
|
||||
{
|
||||
var ret = new SKBitmap[_perks.Count];
|
||||
for (var i = 0; i < ret.Length; i++)
|
||||
{
|
||||
ret[i] = _perks[i].Draw()[0];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
54
FModel/Creator/Bases/MV/BaseQuest.cs
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
using System.ComponentModel;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Assets.Objects;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using FModel.Extensions;
|
||||
|
||||
namespace FModel.Creator.Bases.MV;
|
||||
|
||||
public class BaseQuest : BasePandaIcon
|
||||
{
|
||||
public BaseQuest(UObject uObject, EIconStyle style) : base(uObject, style)
|
||||
{
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
if (Object.TryGetValue(out FStructFallback[] questCompletionRewards, "QuestCompletionRewards") &&
|
||||
questCompletionRewards.Length > 0 && questCompletionRewards[0] is { } actualReward)
|
||||
{
|
||||
var rewardType = actualReward.GetOrDefault("RewardType", EQuestRewardType.Inventory);
|
||||
var count = actualReward.GetOrDefault("Count", 0);
|
||||
Pictos.Add((Utils.GetBitmap("/Game/Panda_Main/UI/Assets/Icons/ui_icons_plus.ui_icons_plus"), count.ToString()));
|
||||
|
||||
base.ParseForInfo();
|
||||
|
||||
if (actualReward.TryGetValue(out FPackageIndex assetReward, "AssetReward") &&
|
||||
Utils.TryGetPackageIndexExport(assetReward, out UObject export))
|
||||
{
|
||||
var item = new BasePandaIcon(export, Style);
|
||||
item.ParseForInfo();
|
||||
Preview = item.Preview;
|
||||
}
|
||||
else if (rewardType != EQuestRewardType.Inventory)
|
||||
{
|
||||
Preview = Utils.GetBitmap(rewardType.GetDescription());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
base.ParseForInfo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum EQuestRewardType : byte
|
||||
{
|
||||
Inventory = 0, // Default
|
||||
|
||||
[Description("/Game/Panda_Main/UI/Assets/Icons/UI_CharacterTicket.UI_CharacterTicket")]
|
||||
AccountXP = 1,
|
||||
|
||||
[Description("/Game/Panda_Main/UI/Assets/Icons/UI_BattlepassToken.UI_BattlepassToken")]
|
||||
BattlepassXP = 2
|
||||
}
|
||||
47
FModel/Creator/Bases/SB/BaseDivision.cs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Objects.Core.i18N;
|
||||
using CUE4Parse.UE4.Objects.Core.Math;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace FModel.Creator.Bases.SB;
|
||||
|
||||
public class BaseDivision : UCreator
|
||||
{
|
||||
public BaseDivision(UObject uObject, EIconStyle style) : base(uObject, style)
|
||||
{
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
if (Object.TryGetValue(out FPackageIndex icon, "Icon", "IconNoTier"))
|
||||
{
|
||||
Preview = Utils.GetBitmap(icon);
|
||||
}
|
||||
|
||||
if (Object.TryGetValue(out FLinearColor lightColor, "UILightColor") &&
|
||||
Object.TryGetValue(out FLinearColor mediumColor, "UIMediumColor") &&
|
||||
Object.TryGetValue(out FLinearColor darkColor, "UIDarkColor") &&
|
||||
Object.TryGetValue(out FLinearColor cardColor, "UICardColor"))
|
||||
{
|
||||
Background = new[] { SKColor.Parse(lightColor.Hex), SKColor.Parse(cardColor.Hex) };
|
||||
Border = new[] { SKColor.Parse(mediumColor.Hex), SKColor.Parse(darkColor.Hex) };
|
||||
}
|
||||
|
||||
if (Object.TryGetValue(out FText displayName, "DisplayName"))
|
||||
DisplayName = displayName.Text;
|
||||
}
|
||||
|
||||
public override SKBitmap[] Draw()
|
||||
{
|
||||
var ret = new SKBitmap(Width, Height, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
using var c = new SKCanvas(ret);
|
||||
|
||||
DrawBackground(c);
|
||||
DrawPreview(c);
|
||||
DrawTextBackground(c);
|
||||
DrawDisplayName(c);
|
||||
|
||||
return new[] { ret };
|
||||
}
|
||||
}
|
||||
49
FModel/Creator/Bases/SB/BaseGameModeInfo.cs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Assets.Exports.Material;
|
||||
using CUE4Parse.UE4.Assets.Exports.Texture;
|
||||
using CUE4Parse.UE4.Objects.Core.i18N;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace FModel.Creator.Bases.SB;
|
||||
|
||||
public class BaseGameModeInfo : UCreator
|
||||
{
|
||||
private SKBitmap _icon;
|
||||
|
||||
public BaseGameModeInfo(UObject uObject, EIconStyle style) : base(uObject, style)
|
||||
{
|
||||
Width = 738;
|
||||
Height = 1024;
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
if (Object.TryGetValue(out FText displayName, "DisplayName"))
|
||||
DisplayName = displayName.Text;
|
||||
if (Object.TryGetValue(out FText description, "Description"))
|
||||
Description = description.Text;
|
||||
if (Object.TryGetValue(out UMaterialInstanceConstant portrait, "Portrait"))
|
||||
Preview = Utils.GetBitmap(portrait);
|
||||
if (Object.TryGetValue(out UTexture2D icon, "Icon"))
|
||||
_icon = Utils.GetBitmap(icon).Resize(25);
|
||||
}
|
||||
|
||||
public override SKBitmap[] Draw()
|
||||
{
|
||||
var ret = new SKBitmap(Width, Height, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
using var c = new SKCanvas(ret);
|
||||
|
||||
DrawPreview(c);
|
||||
DrawTextBackground(c);
|
||||
DrawDisplayName(c);
|
||||
DrawIcon(c);
|
||||
|
||||
return new[] { ret };
|
||||
}
|
||||
|
||||
private void DrawIcon(SKCanvas c)
|
||||
{
|
||||
if (_icon == null) return;
|
||||
c.DrawBitmap(_icon, new SKPoint(5, 5), ImagePaint);
|
||||
}
|
||||
}
|
||||
54
FModel/Creator/Bases/SB/BaseLeague.cs
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Objects.Core.i18N;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace FModel.Creator.Bases.SB;
|
||||
|
||||
public class BaseLeague : UCreator
|
||||
{
|
||||
private int _promotionXp, _xpLostPerMatch;
|
||||
|
||||
public BaseLeague(UObject uObject, EIconStyle style) : base(uObject, style)
|
||||
{
|
||||
_promotionXp = 0;
|
||||
_xpLostPerMatch = 0;
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
if (Object.TryGetValue(out int promotionXp, "PromotionXP"))
|
||||
_promotionXp = promotionXp;
|
||||
if (Object.TryGetValue(out int xpLostPerMatch, "XPLostPerMatch"))
|
||||
_xpLostPerMatch = xpLostPerMatch;
|
||||
|
||||
if (Object.TryGetValue(out FPackageIndex division, "Division") &&
|
||||
Utils.TryGetPackageIndexExport(division, out UObject div))
|
||||
{
|
||||
var d = new BaseDivision(div, Style);
|
||||
d.ParseForInfo();
|
||||
Preview = d.Preview;
|
||||
Background = d.Background;
|
||||
Border = d.Border;
|
||||
}
|
||||
|
||||
if (Object.TryGetValue(out FText displayName, "DisplayName"))
|
||||
DisplayName = displayName.Text;
|
||||
}
|
||||
|
||||
public override SKBitmap[] Draw()
|
||||
{
|
||||
var ret = new SKBitmap(Width, Height, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
using var c = new SKCanvas(ret);
|
||||
|
||||
DrawBackground(c);
|
||||
DrawPreview(c);
|
||||
DrawTextBackground(c);
|
||||
DrawDisplayName(c);
|
||||
|
||||
DrawToBottom(c, SKTextAlign.Left, $"PromotionXP: {_promotionXp}");
|
||||
DrawToBottom(c, SKTextAlign.Right, $"XPLostPerMatch: {_xpLostPerMatch}");
|
||||
|
||||
return new[] { ret };
|
||||
}
|
||||
}
|
||||
97
FModel/Creator/Bases/SB/BaseSpellIcon.cs
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
using System;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Assets.Exports.Engine;
|
||||
using CUE4Parse.UE4.Objects.Core.i18N;
|
||||
using CUE4Parse.UE4.Objects.Core.Math;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using FModel.Creator.Bases.FN;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace FModel.Creator.Bases.SB;
|
||||
|
||||
public class BaseSpellIcon : BaseIcon
|
||||
{
|
||||
private SKBitmap _seriesBackground2;
|
||||
|
||||
private readonly SKPaint _overlayPaint = new()
|
||||
{
|
||||
FilterQuality = SKFilterQuality.High,
|
||||
IsAntialias = true,
|
||||
Color = SKColors.Transparent.WithAlpha(75)
|
||||
};
|
||||
|
||||
public BaseSpellIcon(UObject uObject, EIconStyle style) : base(uObject, style)
|
||||
{
|
||||
Background = new[] { SKColor.Parse("FFFFFF"), SKColor.Parse("636363") };
|
||||
Border = new[] { SKColor.Parse("D0D0D0"), SKColor.Parse("FFFFFF") };
|
||||
Width = Object.ExportType.StartsWith("GCosmeticCard") ? 1536 : 512;
|
||||
Height = Object.ExportType.StartsWith("GCosmeticCard") ? 450 : 512;
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
if (Object.TryGetValue(out FName rarity, "Rarity"))
|
||||
GetRarity(rarity);
|
||||
|
||||
if (Object.TryGetValue(out FSoftObjectPath preview, "IconTexture", "OfferTexture", "PortraitTexture"))
|
||||
Preview = Utils.GetBitmap(preview);
|
||||
else if (Object.TryGetValue(out FPackageIndex icon, "IconTexture", "OfferTexture", "PortraitTexture"))
|
||||
Preview = Utils.GetBitmap(icon);
|
||||
|
||||
if (Object.TryGetValue(out FText displayName, "DisplayName", "Title", "Name"))
|
||||
DisplayName = displayName.Text;
|
||||
if (Object.TryGetValue(out FText description, "Description"))
|
||||
Description = description.Text;
|
||||
|
||||
SeriesBackground = Utils.GetBitmap("g3/Content/UI/Textures/assets/HUDAccentFillBox.HUDAccentFillBox");
|
||||
_seriesBackground2 = Utils.GetBitmap("g3/Content/UI/Textures/assets/store/ItemBGStatic_UIT.ItemBGStatic_UIT");
|
||||
}
|
||||
|
||||
public override SKBitmap[] Draw()
|
||||
{
|
||||
var ret = new SKBitmap(Width, Height, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
using var c = new SKCanvas(ret);
|
||||
|
||||
DrawBackgrounds(c);
|
||||
DrawBackground(c);
|
||||
DrawPreview(c);
|
||||
DrawTextBackground(c);
|
||||
DrawDisplayName(c);
|
||||
DrawDescription(c);
|
||||
|
||||
return new[] { ret };
|
||||
}
|
||||
|
||||
private void DrawBackgrounds(SKCanvas c)
|
||||
{
|
||||
if (SeriesBackground != null)
|
||||
c.DrawBitmap(SeriesBackground, new SKRect(0, 0, Width, Height), ImagePaint);
|
||||
if (_seriesBackground2 != null)
|
||||
c.DrawBitmap(_seriesBackground2, new SKRect(0, 0, Width, Height), _overlayPaint);
|
||||
|
||||
var x = Margin * (int) 2.5;
|
||||
const int radi = 15;
|
||||
c.DrawCircle(x + radi, x + radi, radi, new SKPaint
|
||||
{
|
||||
IsAntialias = true,
|
||||
FilterQuality = SKFilterQuality.High,
|
||||
Shader = SKShader.CreateRadialGradient(
|
||||
new SKPoint(radi, radi), radi * 2 / 5 * 4,
|
||||
Background, SKShaderTileMode.Clamp)
|
||||
});
|
||||
}
|
||||
|
||||
private void GetRarity(FName n)
|
||||
{
|
||||
if (!Utils.TryLoadObject("g3/Content/UI/UIKit/DT_RarityColors.DT_RarityColors", out UDataTable rarity)) return;
|
||||
|
||||
if (rarity.TryGetDataTableRow(n.Text["EXRarity::".Length..], StringComparison.Ordinal, out var row))
|
||||
{
|
||||
if (row.TryGetValue(out FLinearColor[] colors, "Colors"))
|
||||
{
|
||||
Background = new[] { SKColor.Parse(colors[0].Hex), SKColor.Parse(colors[2].Hex) };
|
||||
Border = new[] { SKColor.Parse(colors[1].Hex), SKColor.Parse(colors[0].Hex) };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
228
FModel/Creator/Bases/UCreator.cs
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
using System;
|
||||
using System.Windows;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using FModel.Creator.Bases.FN;
|
||||
using FModel.Framework;
|
||||
using SkiaSharp;
|
||||
using SkiaSharp.HarfBuzz;
|
||||
|
||||
namespace FModel.Creator.Bases;
|
||||
|
||||
public abstract class UCreator
|
||||
{
|
||||
protected UObject Object { get; }
|
||||
protected EIconStyle Style { get; }
|
||||
public SKBitmap DefaultPreview { get; set; }
|
||||
public SKBitmap Preview { get; set; }
|
||||
public SKColor[] Background { get; protected set; }
|
||||
public SKColor[] Border { get; protected set; }
|
||||
public string DisplayName { get; protected set; }
|
||||
public string Description { get; protected set; }
|
||||
public int Margin { get; protected set; }
|
||||
public int Width { get; protected set; }
|
||||
public int Height { get; protected set; }
|
||||
|
||||
public abstract void ParseForInfo();
|
||||
public abstract SKBitmap[] Draw();
|
||||
|
||||
protected UCreator(UObject uObject, EIconStyle style)
|
||||
{
|
||||
DefaultPreview = SKBitmap.Decode(Application.GetResourceStream(new Uri("pack://application:,,,/Resources/T_Placeholder_Item_Image.png"))?.Stream);
|
||||
Background = new[] { SKColor.Parse("5BFD00"), SKColor.Parse("003700") };
|
||||
Border = new[] { SKColor.Parse("1E8500"), SKColor.Parse("5BFD00") };
|
||||
DisplayName = string.Empty;
|
||||
Description = string.Empty;
|
||||
Width = 512;
|
||||
Height = 512;
|
||||
Margin = 2;
|
||||
Object = uObject;
|
||||
Style = style;
|
||||
}
|
||||
|
||||
private const int _STARTER_TEXT_POSITION = 380, _NAME_TEXT_SIZE = 45, _BOTTOM_TEXT_SIZE = 15;
|
||||
protected readonly SKPaint DisplayNamePaint = new()
|
||||
{
|
||||
IsAntialias = true, FilterQuality = SKFilterQuality.High,
|
||||
Typeface = Utils.Typefaces.DisplayName, TextSize = _NAME_TEXT_SIZE,
|
||||
Color = SKColors.White, TextAlign = SKTextAlign.Center
|
||||
};
|
||||
protected readonly SKPaint DescriptionPaint = new()
|
||||
{
|
||||
IsAntialias = true, FilterQuality = SKFilterQuality.High,
|
||||
Typeface = Utils.Typefaces.Description, TextSize = 13,
|
||||
Color = SKColors.White
|
||||
};
|
||||
protected readonly SKPaint ImagePaint = new()
|
||||
{
|
||||
IsAntialias = true, FilterQuality = SKFilterQuality.High
|
||||
};
|
||||
private readonly SKPaint _textBackgroundPaint = new()
|
||||
{
|
||||
IsAntialias = true, FilterQuality = SKFilterQuality.High, Color = new SKColor(0, 0, 50, 75)
|
||||
};
|
||||
private readonly SKPaint _shortDescriptionPaint = new()
|
||||
{
|
||||
IsAntialias = true, FilterQuality = SKFilterQuality.High,
|
||||
Color = SKColors.White
|
||||
};
|
||||
|
||||
public void DrawBackground(SKCanvas c)
|
||||
{
|
||||
// reverse doesn't affect basic rarities
|
||||
if (Background[0] == Background[1]) Background[0] = Border[0];
|
||||
Background[0].ToHsl(out _, out _, out var l1);
|
||||
Background[1].ToHsl(out _, out _, out var l2);
|
||||
var reverse = l1 > l2;
|
||||
|
||||
// border
|
||||
c.DrawRect(new SKRect(0, 0, Width, Height),
|
||||
new SKPaint
|
||||
{
|
||||
IsAntialias = true, FilterQuality = SKFilterQuality.High,
|
||||
Shader = SKShader.CreateLinearGradient(
|
||||
new SKPoint(Width / 2, Height), new SKPoint(Width, Height / 4), Border, SKShaderTileMode.Clamp)
|
||||
});
|
||||
|
||||
if (this is BaseIcon { SeriesBackground: { } } baseIcon)
|
||||
c.DrawBitmap(baseIcon.SeriesBackground, new SKRect(baseIcon.Margin, baseIcon.Margin, baseIcon.Width - baseIcon.Margin,
|
||||
baseIcon.Height - baseIcon.Margin), ImagePaint);
|
||||
else
|
||||
{
|
||||
switch (Style)
|
||||
{
|
||||
case EIconStyle.Flat:
|
||||
{
|
||||
c.DrawRect(new SKRect(Margin, Margin, Width - Margin, Height - Margin),
|
||||
new SKPaint
|
||||
{
|
||||
IsAntialias = true, FilterQuality = SKFilterQuality.High,
|
||||
Shader = SKShader.CreateLinearGradient(new SKPoint(Width / 2, Height), new SKPoint(Width, Height / 4),
|
||||
new[] { Background[reverse ? 0 : 1].WithAlpha(150), Border[0] }, SKShaderTileMode.Clamp)
|
||||
});
|
||||
if (string.IsNullOrEmpty(DisplayName) && string.IsNullOrEmpty(Description)) return;
|
||||
|
||||
var pathTop = new SKPath { FillType = SKPathFillType.EvenOdd };
|
||||
pathTop.MoveTo(Margin, Margin);
|
||||
pathTop.LineTo(Margin + Width / 17 * 10, Margin);
|
||||
pathTop.LineTo(Margin, Margin + Height / 17);
|
||||
pathTop.Close();
|
||||
c.DrawPath(pathTop, new SKPaint
|
||||
{
|
||||
IsAntialias = true,
|
||||
FilterQuality = SKFilterQuality.High,
|
||||
Color = Background[1].WithAlpha(75)
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
c.DrawRect(new SKRect(Margin, Margin, Width - Margin, Height - Margin),
|
||||
new SKPaint
|
||||
{
|
||||
IsAntialias = true, FilterQuality = SKFilterQuality.High,
|
||||
Shader = SKShader.CreateRadialGradient(new SKPoint(Width / 2, Height / 2), Width / 5 * 4,
|
||||
new[] { Background[reverse ? 0 : 1], Background[reverse ? 1 : 0] },
|
||||
SKShaderTileMode.Clamp)
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawPreview(SKCanvas c)
|
||||
=> c.DrawBitmap(Preview ?? DefaultPreview, new SKRect(Margin, Margin, Width - Margin, Height - Margin), ImagePaint);
|
||||
|
||||
protected void DrawTextBackground(SKCanvas c)
|
||||
{
|
||||
if (string.IsNullOrEmpty(DisplayName) && string.IsNullOrEmpty(Description)) return;
|
||||
switch (Style)
|
||||
{
|
||||
case EIconStyle.Flat:
|
||||
{
|
||||
var pathBottom = new SKPath { FillType = SKPathFillType.EvenOdd };
|
||||
pathBottom.MoveTo(Margin, Height - Margin);
|
||||
pathBottom.LineTo(Margin, Height - Margin - Height / 17 * 2.5f);
|
||||
pathBottom.LineTo(Width - Margin, Height - Margin - Height / 17 * 4.5f);
|
||||
pathBottom.LineTo(Width - Margin, Height - Margin);
|
||||
pathBottom.Close();
|
||||
c.DrawPath(pathBottom, _textBackgroundPaint);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
c.DrawRect(new SKRect(Margin, _STARTER_TEXT_POSITION, Width - Margin, Height - Margin), _textBackgroundPaint);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawDisplayName(SKCanvas c)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(DisplayName)) return;
|
||||
|
||||
while (DisplayNamePaint.MeasureText(DisplayName) > Width - Margin * 2)
|
||||
{
|
||||
DisplayNamePaint.TextSize -= 1;
|
||||
}
|
||||
|
||||
var shaper = new CustomSKShaper(DisplayNamePaint.Typeface);
|
||||
var shapedText = shaper.Shape(DisplayName, DisplayNamePaint);
|
||||
var x = Width / 2f;
|
||||
var y = _STARTER_TEXT_POSITION + _NAME_TEXT_SIZE;
|
||||
|
||||
switch (Style)
|
||||
{
|
||||
case EIconStyle.Flat:
|
||||
{
|
||||
DisplayNamePaint.TextAlign = SKTextAlign.Right;
|
||||
x = Width - Margin * 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
var halfWidth = shapedText.Width / 2f;
|
||||
c.DrawLine(x - halfWidth, 0, x - halfWidth, Width, new SKPaint { Color = SKColors.Blue, IsStroke = true });
|
||||
c.DrawLine(x + halfWidth, 0, x + halfWidth, Width, new SKPaint { Color = SKColors.Blue, IsStroke = true });
|
||||
c.DrawRect(new SKRect(Margin, _STARTER_TEXT_POSITION, Width - Margin, y), new SKPaint { Color = SKColors.Blue, IsStroke = true });
|
||||
#endif
|
||||
|
||||
c.DrawShapedText(shaper, DisplayName, x, y, DisplayNamePaint);
|
||||
}
|
||||
|
||||
protected void DrawDescription(SKCanvas c)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Description)) return;
|
||||
|
||||
var maxLine = string.IsNullOrEmpty(DisplayName) ? 8 : 4;
|
||||
var side = SKTextAlign.Center;
|
||||
switch (Style)
|
||||
{
|
||||
case EIconStyle.Flat:
|
||||
side = SKTextAlign.Right;
|
||||
break;
|
||||
}
|
||||
|
||||
Utils.DrawCenteredMultilineText(c, Description, maxLine, Width, Margin, side,
|
||||
new SKRect(Margin, string.IsNullOrEmpty(DisplayName) ? _STARTER_TEXT_POSITION : _STARTER_TEXT_POSITION + _NAME_TEXT_SIZE, Width - Margin, Height - _BOTTOM_TEXT_SIZE), DescriptionPaint);
|
||||
}
|
||||
|
||||
protected void DrawToBottom(SKCanvas c, SKTextAlign side, string text)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text)) return;
|
||||
|
||||
_shortDescriptionPaint.TextAlign = side;
|
||||
_shortDescriptionPaint.TextSize = Utils.Typefaces.Bottom == null ? 15 : 13;
|
||||
switch (side)
|
||||
{
|
||||
case SKTextAlign.Left:
|
||||
_shortDescriptionPaint.Typeface = Utils.Typefaces.Bottom ?? Utils.Typefaces.DisplayName;
|
||||
var shaper = new CustomSKShaper(_shortDescriptionPaint.Typeface);
|
||||
c.DrawShapedText(shaper, text, Margin * 2.5f, Width - Margin * 2.5f, _shortDescriptionPaint);
|
||||
break;
|
||||
case SKTextAlign.Right:
|
||||
_shortDescriptionPaint.Typeface = Utils.Typefaces.Bottom ?? Utils.Typefaces.Default;
|
||||
c.DrawText(text, Width - Margin * 2.5f, Width - Margin * 2.5f, _shortDescriptionPaint);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
256
FModel/Creator/CreatorPackage.cs
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using FModel.Creator.Bases;
|
||||
using FModel.Creator.Bases.BB;
|
||||
using FModel.Creator.Bases.FN;
|
||||
using FModel.Creator.Bases.MV;
|
||||
using FModel.Creator.Bases.SB;
|
||||
|
||||
namespace FModel.Creator;
|
||||
|
||||
public class CreatorPackage : IDisposable
|
||||
{
|
||||
private UObject _object;
|
||||
private EIconStyle _style;
|
||||
|
||||
public CreatorPackage(UObject uObject, EIconStyle style)
|
||||
{
|
||||
_object = uObject;
|
||||
_style = style;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public UCreator ConstructCreator()
|
||||
{
|
||||
TryConstructCreator(out var creator);
|
||||
return creator;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool TryConstructCreator(out UCreator creator)
|
||||
{
|
||||
switch (_object.ExportType)
|
||||
{
|
||||
// Fortnite
|
||||
case "FortCreativeWeaponMeleeItemDefinition":
|
||||
case "AthenaConsumableEmoteItemDefinition":
|
||||
case "AthenaSkyDiveContrailItemDefinition":
|
||||
case "AthenaLoadingScreenItemDefinition":
|
||||
case "AthenaVictoryPoseItemDefinition":
|
||||
case "AthenaPetCarrierItemDefinition":
|
||||
case "AthenaMusicPackItemDefinition":
|
||||
case "AthenaBattleBusItemDefinition":
|
||||
case "AthenaCharacterItemDefinition":
|
||||
case "AthenaMapMarkerItemDefinition":
|
||||
case "AthenaBackpackItemDefinition":
|
||||
case "AthenaPickaxeItemDefinition":
|
||||
case "AthenaGadgetItemDefinition":
|
||||
case "AthenaGliderItemDefinition":
|
||||
case "AthenaSprayItemDefinition":
|
||||
case "AthenaDanceItemDefinition":
|
||||
case "AthenaEmojiItemDefinition":
|
||||
case "AthenaItemWrapDefinition":
|
||||
case "AthenaToyItemDefinition":
|
||||
case "FortHeroType":
|
||||
case "FortTokenType":
|
||||
case "FortAbilityKit":
|
||||
case "FortWorkerType":
|
||||
case "RewardGraphToken":
|
||||
case "JunoKnowledgeBundle":
|
||||
case "FortBannerTokenType":
|
||||
case "FortVariantTokenType":
|
||||
case "FortDecoItemDefinition":
|
||||
case "FortStatItemDefinition":
|
||||
case "FortAmmoItemDefinition":
|
||||
case "FortEmoteItemDefinition":
|
||||
case "FortBadgeItemDefinition":
|
||||
case "SparksMicItemDefinition":
|
||||
case "FortAwardItemDefinition":
|
||||
case "FortStackItemDefinition":
|
||||
case "FortWorldItemDefinition":
|
||||
case "SparksAuraItemDefinition":
|
||||
case "SparksDrumItemDefinition":
|
||||
case "SparksBassItemDefinition":
|
||||
case "FortGadgetItemDefinition":
|
||||
case "AthenaCharmItemDefinition":
|
||||
case "FortPlaysetItemDefinition":
|
||||
case "FortGiftBoxItemDefinition":
|
||||
case "FortOutpostItemDefinition":
|
||||
case "FortVehicleItemDefinition":
|
||||
case "FortMissionItemDefinition":
|
||||
case "FortAccountItemDefinition":
|
||||
case "SparksGuitarItemDefinition":
|
||||
case "FortCardPackItemDefinition":
|
||||
case "FortDefenderItemDefinition":
|
||||
case "FortCurrencyItemDefinition":
|
||||
case "FortResourceItemDefinition":
|
||||
case "FortBackpackItemDefinition":
|
||||
case "FortEventQuestMapDataAsset":
|
||||
case "FortBuildingItemDefinition":
|
||||
case "FortWeaponModItemDefinition":
|
||||
case "FortCodeTokenItemDefinition":
|
||||
case "FortSchematicItemDefinition":
|
||||
case "FortAlterableItemDefinition":
|
||||
case "SparksKeyboardItemDefinition":
|
||||
case "FortWorldMultiItemDefinition":
|
||||
case "FortAlterationItemDefinition":
|
||||
case "FortExpeditionItemDefinition":
|
||||
case "FortIngredientItemDefinition":
|
||||
case "FortConsumableItemDefinition":
|
||||
case "StWFortAccoladeItemDefinition":
|
||||
case "FortAccountBuffItemDefinition":
|
||||
case "FortWeaponMeleeItemDefinition":
|
||||
case "FortPlayerPerksItemDefinition":
|
||||
case "FortPlaysetPropItemDefinition":
|
||||
case "FortPrerollDataItemDefinition":
|
||||
case "JunoRecipeBundleItemDefinition":
|
||||
case "FortHomebaseNodeItemDefinition":
|
||||
case "FortNeverPersistItemDefinition":
|
||||
case "FortPlayerAugmentItemDefinition":
|
||||
case "FortSmartBuildingItemDefinition":
|
||||
case "FortGiftBoxUnlockItemDefinition":
|
||||
case "FortWeaponModItemDefinitionOptic":
|
||||
case "RadioContentSourceItemDefinition":
|
||||
case "FortPlaysetGrenadeItemDefinition":
|
||||
case "JunoWeaponCreatureItemDefinition":
|
||||
case "FortEventDependentItemDefinition":
|
||||
case "FortPersonalVehicleItemDefinition":
|
||||
case "FortGameplayModifierItemDefinition":
|
||||
case "FortHardcoreModifierItemDefinition":
|
||||
case "FortWeaponModItemDefinitionMagazine":
|
||||
case "FortConsumableAccountItemDefinition":
|
||||
case "FortConversionControlItemDefinition":
|
||||
case "FortAccountBuffCreditItemDefinition":
|
||||
case "JunoBuildInstructionsItemDefinition":
|
||||
case "FortCharacterCosmeticItemDefinition":
|
||||
case "JunoBuildingSetAccountItemDefinition":
|
||||
case "FortEventCurrencyItemDefinitionRedir":
|
||||
case "FortPersistentResourceItemDefinition":
|
||||
case "FortWeaponMeleeOffhandItemDefinition":
|
||||
case "FortHomebaseBannerIconItemDefinition":
|
||||
case "FortVehicleCosmeticsVariantTokenType":
|
||||
case "JunoBuildingPropAccountItemDefinition":
|
||||
case "FortCampaignHeroLoadoutItemDefinition":
|
||||
case "FortConditionalResourceItemDefinition":
|
||||
case "FortChallengeBundleScheduleDefinition":
|
||||
case "FortWeaponMeleeDualWieldItemDefinition":
|
||||
case "FortDailyRewardScheduleTokenDefinition":
|
||||
case "FortCreativeWeaponRangedItemDefinition":
|
||||
case "FortVehicleCosmeticsItemDefinition_Body":
|
||||
case "FortVehicleCosmeticsItemDefinition_Skin":
|
||||
case "FortVehicleCosmeticsItemDefinition_Wheel":
|
||||
case "FortCreativeRealEstatePlotItemDefinition":
|
||||
case "FortDeployableBaseCloudSaveItemDefinition":
|
||||
case "FortVehicleCosmeticsItemDefinition_Booster":
|
||||
case "AthenaDanceItemDefinition_AdHocSquadsJoin_C":
|
||||
case "FortVehicleCosmeticsItemDefinition_DriftSmoke":
|
||||
case "FortVehicleCosmeticsItemDefinition_EngineAudio":
|
||||
creator = _style switch
|
||||
{
|
||||
EIconStyle.Cataba => new BaseCommunity(_object, _style, "Cataba"),
|
||||
_ => new BaseIcon(_object, _style)
|
||||
};
|
||||
return true;
|
||||
case "JunoAthenaCharacterItemOverrideDefinition":
|
||||
case "JunoAthenaDanceItemOverrideDefinition":
|
||||
creator = new BaseJuno(_object, _style);
|
||||
return true;
|
||||
case "FortTandemCharacterData":
|
||||
creator = new BaseTandem(_object, _style);
|
||||
return true;
|
||||
case "FortTrapItemDefinition":
|
||||
case "FortSpyTechItemDefinition":
|
||||
case "FortAccoladeItemDefinition":
|
||||
case "FortContextTrapItemDefinition":
|
||||
case "FortWeaponRangedItemDefinition":
|
||||
case "Daybreak_LevelExitVehicle_PartItemDefinition_C":
|
||||
creator = new BaseIconStats(_object, _style);
|
||||
return true;
|
||||
case "FortItemSeriesDefinition":
|
||||
creator = new BaseSeries(_object, _style);
|
||||
return true;
|
||||
case "MaterialInstanceConstant"
|
||||
when _object.Owner != null &&
|
||||
(_object.Owner.Name.Contains("/MI_OfferImages/", StringComparison.OrdinalIgnoreCase) ||
|
||||
_object.Owner.Name.EndsWith($"/RenderSwitch_Materials/{_object.Name}", StringComparison.OrdinalIgnoreCase) ||
|
||||
_object.Owner.Name.EndsWith($"/MI_BPTile/{_object.Name}", StringComparison.OrdinalIgnoreCase)):
|
||||
creator = new BaseMaterialInstance(_object, _style);
|
||||
return true;
|
||||
case "AthenaItemShopOfferDisplayData":
|
||||
creator = new BaseOfferDisplayData(_object, _style);
|
||||
return true;
|
||||
case "FortMtxOfferData":
|
||||
creator = new BaseMtxOffer(_object, _style);
|
||||
return true;
|
||||
case "FortPlaylistAthena":
|
||||
creator = new BasePlaylist(_object, _style);
|
||||
return true;
|
||||
case "FortFeatItemDefinition":
|
||||
case "FortQuestItemDefinition":
|
||||
case "FortQuestItemDefinition_Athena":
|
||||
case "FortQuestItemDefinition_Campaign":
|
||||
case "AthenaDailyQuestDefinition":
|
||||
case "FortUrgentQuestItemDefinition":
|
||||
creator = new Bases.FN.BaseQuest(_object, _style);
|
||||
return true;
|
||||
case "FortCompendiumItemDefinition":
|
||||
case "FortChallengeBundleItemDefinition":
|
||||
creator = new BaseBundle(_object, _style);
|
||||
return true;
|
||||
// case "AthenaSeasonItemDefinition":
|
||||
// creator = new BaseSeason(_object, _style);
|
||||
// return true;
|
||||
case "FortItemAccessTokenType":
|
||||
creator = new BaseItemAccessToken(_object, _style);
|
||||
return true;
|
||||
case "FortCreativeOption":
|
||||
case "PlaylistUserOptionEnum":
|
||||
case "PlaylistUserOptionBool":
|
||||
case "PlaylistUserOptionString":
|
||||
case "PlaylistUserOptionIntEnum":
|
||||
case "PlaylistUserOptionIntRange":
|
||||
case "PlaylistUserOptionColorEnum":
|
||||
case "PlaylistUserOptionFloatEnum":
|
||||
case "PlaylistUserOptionFloatRange":
|
||||
case "PlaylistUserTintedIconIntEnum":
|
||||
case "PlaylistUserOptionPrimaryAsset":
|
||||
case "PlaylistUserOptionCollisionProfileEnum":
|
||||
creator = new BaseUserControl(_object, _style);
|
||||
return true;
|
||||
// PandaGame
|
||||
case "CharacterData":
|
||||
creator = new BaseFighter(_object, _style);
|
||||
return true;
|
||||
case "PerkGroup":
|
||||
creator = new BasePerkGroup(_object, _style);
|
||||
return true;
|
||||
case "StatTrackingBundleData":
|
||||
case "HydraSyncedDataAsset":
|
||||
case "AnnouncerPackData":
|
||||
case "CharacterGiftData":
|
||||
case "ProfileIconData":
|
||||
case "RingOutVfxData":
|
||||
case "BannerData":
|
||||
case "EmoteData":
|
||||
case "TauntData":
|
||||
case "SkinData":
|
||||
case "PerkData":
|
||||
creator = new BasePandaIcon(_object, _style);
|
||||
return true;
|
||||
case "QuestData":
|
||||
creator = new Bases.MV.BaseQuest(_object, _style);
|
||||
return true;
|
||||
default:
|
||||
creator = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString() => $"{_object.ExportType} | {_style}";
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_object = null;
|
||||
}
|
||||
}
|
||||
199
FModel/Creator/Typefaces.cs
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using CUE4Parse.UE4.Versions;
|
||||
using FModel.Settings;
|
||||
using FModel.ViewModels;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace FModel.Creator;
|
||||
|
||||
public class Typefaces
|
||||
{
|
||||
private readonly Uri _BURBANK_BIG_CONDENSED_BOLD = new("pack://application:,,,/Resources/BurbankBigCondensed-Bold.ttf");
|
||||
private const string _EXT = ".ufont";
|
||||
|
||||
// FortniteGame
|
||||
private const string _FORTNITE_BASE_PATH = "/Game/UI/Foundation/Fonts/";
|
||||
private const string _ASIA_ERINM = "AsiaERINM"; // korean fortnite
|
||||
private const string _BURBANK_BIG_CONDENSED_BLACK = "BurbankBigCondensed-Black"; // russian
|
||||
private const string _BURBANK_BIG_REGULAR_BLACK = "BurbankBigRegular-Black";
|
||||
private const string _BURBANK_BIG_REGULAR_BOLD = "BurbankBigRegular-Bold"; // official fortnite ig
|
||||
private const string _BURBANK_SMALL_MEDIUM = "BurbankSmall-Medium";
|
||||
private const string _DROID_SANS_FORTNITE_SUBSET = "DroidSans-Fortnite-Subset";
|
||||
private const string _NOTO_COLOR_EMOJI = "NotoColorEmoji";
|
||||
private const string _NOTO_SANS_BOLD = "NotoSans-Bold";
|
||||
private const string _NOTO_SANS_FORTNITE_BOLD = "NotoSans-Fortnite-Bold";
|
||||
private const string _NOTO_SANS_FORTNITE_ITALIC = "NotoSans-Fortnite-Italic";
|
||||
private const string _NOTO_SANS_FORTNITE_REGULAR = "NotoSans-Fortnite-Regular";
|
||||
private const string _NOTO_SANS_ITALIC = "NotoSans-Italic";
|
||||
private const string _NOTO_SANS_REGULAR = "NotoSans-Regular";
|
||||
private const string _NOTO_SANS_ARABIC_BLACK = "NotoSansArabic-Black"; // arabic fortnite
|
||||
private const string _NOTO_SANS_ARABIC_BOLD = "NotoSansArabic-Bold";
|
||||
private const string _NOTO_SANS_ARABIC_REGULAR = "NotoSansArabic-Regular";
|
||||
private const string _NOTO_SANS_JP_BOLD = "NotoSansJP-Bold"; // japanese fortnite
|
||||
private const string _NOTO_SANS_KR_REGULAR = "NotoSansKR-Regular";
|
||||
private const string _NOTO_SANS_SC_BLACK = "NotoSansSC-Black"; // simplified chinese fortnite
|
||||
private const string _NOTO_SANS_SC_REGULAR = "NotoSansSC-Regular";
|
||||
private const string _NOTO_SANS_TC_BLACK = "NotoSansTC-Black"; // traditional chinese fortnite
|
||||
private const string _NOTO_SANS_TC_REGULAR = "NotoSansTC-Regular";
|
||||
private const string _BURBANK_SMALL_BLACK = "burbanksmall-black";
|
||||
private const string _BURBANK_SMALL_BOLD = "burbanksmall-bold";
|
||||
|
||||
// PandaGame
|
||||
private const string _PANDAGAME_BASE_PATH = "/Game/Panda_Main/UI/Fonts/";
|
||||
private const string _NORMS_STD_CONDENSED_EXTRABOLD_ITALIC = "Norms/TT_Norms_Std_Condensed_ExtraBold_Italic";
|
||||
private const string _NORMS_PRO_EXTRABOLD_ITALIC = "Norms/TT_Norms_Pro_ExtraBold_Italic";
|
||||
private const string _NORMS_STD_CONDENSED_MEDIUM = "Norms/TT_Norms_Std_Condensed_Medium";
|
||||
private const string _XIANGHEHEI_SC_PRO_BLACK = "XiangHeHei_SC/MXiangHeHeiSCPro-Black";
|
||||
private const string _XIANGHEHEI_SC_PRO_HEAVY = "XiangHeHei_SC/MXiangHeHeiSCPro-Heavy";
|
||||
|
||||
private readonly CUE4ParseViewModel _viewModel;
|
||||
|
||||
public readonly SKTypeface Default; // used as a fallback font for all untranslated strings (item source, ...)
|
||||
public readonly SKTypeface DisplayName;
|
||||
public readonly SKTypeface Description;
|
||||
public readonly SKTypeface Bottom; // must be null for non-latin base languages
|
||||
public readonly SKTypeface Bundle;
|
||||
public readonly SKTypeface BundleNumber;
|
||||
public readonly SKTypeface TandemDisplayName;
|
||||
public readonly SKTypeface TandemGenDescription;
|
||||
public readonly SKTypeface TandemAddDescription;
|
||||
|
||||
public Typefaces(CUE4ParseViewModel viewModel)
|
||||
{
|
||||
_viewModel = viewModel;
|
||||
var language = UserSettings.Default.AssetLanguage;
|
||||
|
||||
Default = SKTypeface.FromStream(Application.GetResourceStream(_BURBANK_BIG_CONDENSED_BOLD)?.Stream);
|
||||
|
||||
switch (viewModel.Provider.InternalGameName.ToUpperInvariant())
|
||||
{
|
||||
case "FORTNITEGAME":
|
||||
{
|
||||
DisplayName = OnTheFly(_FORTNITE_BASE_PATH +
|
||||
language switch
|
||||
{
|
||||
ELanguage.Korean => _ASIA_ERINM,
|
||||
ELanguage.Russian => _BURBANK_BIG_CONDENSED_BLACK,
|
||||
ELanguage.Japanese => _NOTO_SANS_JP_BOLD,
|
||||
ELanguage.Arabic => _NOTO_SANS_ARABIC_BLACK,
|
||||
ELanguage.TraditionalChinese => _NOTO_SANS_TC_BLACK,
|
||||
ELanguage.Chinese => _NOTO_SANS_SC_BLACK,
|
||||
_ => string.Empty
|
||||
} + _EXT);
|
||||
|
||||
Description = OnTheFly(_FORTNITE_BASE_PATH +
|
||||
language switch
|
||||
{
|
||||
ELanguage.Korean => _NOTO_SANS_KR_REGULAR,
|
||||
ELanguage.Japanese => _NOTO_SANS_JP_BOLD,
|
||||
ELanguage.Arabic => _NOTO_SANS_ARABIC_REGULAR,
|
||||
ELanguage.TraditionalChinese => _NOTO_SANS_TC_REGULAR,
|
||||
ELanguage.Chinese => _NOTO_SANS_SC_REGULAR,
|
||||
_ => _NOTO_SANS_REGULAR
|
||||
} + _EXT);
|
||||
|
||||
Bottom = OnTheFly(_FORTNITE_BASE_PATH +
|
||||
language switch
|
||||
{
|
||||
ELanguage.Korean => string.Empty,
|
||||
ELanguage.Japanese => string.Empty,
|
||||
ELanguage.Arabic => string.Empty,
|
||||
ELanguage.TraditionalChinese => string.Empty,
|
||||
ELanguage.Chinese => string.Empty,
|
||||
_ => _BURBANK_SMALL_BOLD
|
||||
} + _EXT, true);
|
||||
|
||||
BundleNumber = OnTheFly(_FORTNITE_BASE_PATH + _BURBANK_BIG_CONDENSED_BLACK + _EXT);
|
||||
|
||||
Bundle = OnTheFly(_FORTNITE_BASE_PATH +
|
||||
language switch
|
||||
{
|
||||
ELanguage.Korean => _ASIA_ERINM,
|
||||
ELanguage.Russian => _BURBANK_BIG_CONDENSED_BLACK,
|
||||
ELanguage.Japanese => _NOTO_SANS_JP_BOLD,
|
||||
ELanguage.Arabic => _NOTO_SANS_ARABIC_BLACK,
|
||||
ELanguage.TraditionalChinese => _NOTO_SANS_TC_BLACK,
|
||||
ELanguage.Chinese => _NOTO_SANS_SC_BLACK,
|
||||
_ => string.Empty
|
||||
} + _EXT, true) ?? BundleNumber;
|
||||
|
||||
TandemDisplayName = OnTheFly(_FORTNITE_BASE_PATH +
|
||||
language switch
|
||||
{
|
||||
ELanguage.Korean => _ASIA_ERINM,
|
||||
ELanguage.Russian => _BURBANK_BIG_CONDENSED_BLACK,
|
||||
ELanguage.Japanese => _NOTO_SANS_JP_BOLD,
|
||||
ELanguage.Arabic => _NOTO_SANS_ARABIC_BLACK,
|
||||
ELanguage.TraditionalChinese => _NOTO_SANS_TC_BLACK,
|
||||
ELanguage.Chinese => _NOTO_SANS_SC_BLACK,
|
||||
_ => _BURBANK_BIG_REGULAR_BLACK
|
||||
} + _EXT);
|
||||
|
||||
TandemGenDescription = OnTheFly(_FORTNITE_BASE_PATH +
|
||||
language switch
|
||||
{
|
||||
ELanguage.Korean => _ASIA_ERINM,
|
||||
ELanguage.Japanese => _NOTO_SANS_JP_BOLD,
|
||||
ELanguage.Arabic => _NOTO_SANS_ARABIC_BLACK,
|
||||
ELanguage.TraditionalChinese => _NOTO_SANS_TC_BLACK,
|
||||
ELanguage.Chinese => _NOTO_SANS_SC_BLACK,
|
||||
_ => _BURBANK_SMALL_BLACK
|
||||
} + _EXT);
|
||||
|
||||
TandemAddDescription = OnTheFly(_FORTNITE_BASE_PATH +
|
||||
language switch
|
||||
{
|
||||
ELanguage.Korean => _ASIA_ERINM,
|
||||
ELanguage.Japanese => _NOTO_SANS_JP_BOLD,
|
||||
ELanguage.Arabic => _NOTO_SANS_ARABIC_BLACK,
|
||||
ELanguage.TraditionalChinese => _NOTO_SANS_TC_BLACK,
|
||||
ELanguage.Chinese => _NOTO_SANS_SC_BLACK,
|
||||
_ => _BURBANK_SMALL_BOLD
|
||||
} + _EXT);
|
||||
break;
|
||||
}
|
||||
case "MULTIVERSUS":
|
||||
{
|
||||
DisplayName = OnTheFly(_PANDAGAME_BASE_PATH + language switch
|
||||
{
|
||||
ELanguage.Chinese => _XIANGHEHEI_SC_PRO_HEAVY,
|
||||
_ => _NORMS_PRO_EXTRABOLD_ITALIC
|
||||
} + _EXT);
|
||||
|
||||
Description = OnTheFly(_PANDAGAME_BASE_PATH + language switch
|
||||
{
|
||||
ELanguage.Chinese => _XIANGHEHEI_SC_PRO_BLACK,
|
||||
_ => _NORMS_STD_CONDENSED_MEDIUM
|
||||
} + _EXT);
|
||||
|
||||
TandemDisplayName = OnTheFly(_PANDAGAME_BASE_PATH + language switch
|
||||
{
|
||||
ELanguage.Chinese => _XIANGHEHEI_SC_PRO_BLACK,
|
||||
_ => _NORMS_STD_CONDENSED_EXTRABOLD_ITALIC
|
||||
} + _EXT);
|
||||
|
||||
TandemGenDescription = OnTheFly(_PANDAGAME_BASE_PATH + language switch
|
||||
{
|
||||
ELanguage.Chinese => _XIANGHEHEI_SC_PRO_HEAVY,
|
||||
_ => _NORMS_STD_CONDENSED_MEDIUM
|
||||
} + _EXT);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
DisplayName = Default;
|
||||
Description = Default;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SKTypeface OnTheFly(string path, bool fallback = false)
|
||||
{
|
||||
if (!_viewModel.Provider.TrySaveAsset(path, out var data)) return fallback ? null : Default;
|
||||
var m = new MemoryStream(data) { Position = 0 };
|
||||
return SKTypeface.FromStream(m);
|
||||
}
|
||||
}
|
||||
420
FModel/Creator/Utils.cs
Normal file
|
|
@ -0,0 +1,420 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Assets.Exports.Material;
|
||||
using CUE4Parse.UE4.Assets.Exports.Texture;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using CUE4Parse.UE4.Versions;
|
||||
using CUE4Parse_Conversion.Textures;
|
||||
using CUE4Parse.UE4.Assets.Objects;
|
||||
using FModel.Framework;
|
||||
using FModel.Extensions;
|
||||
using FModel.Services;
|
||||
using FModel.Settings;
|
||||
using FModel.ViewModels;
|
||||
using SkiaSharp;
|
||||
using SkiaSharp.HarfBuzz;
|
||||
|
||||
namespace FModel.Creator;
|
||||
|
||||
public static class Utils
|
||||
{
|
||||
private static ApplicationViewModel _applicationView => ApplicationService.ApplicationView;
|
||||
private static readonly Regex _htmlRegex = new("<.*?>");
|
||||
public static Typefaces Typefaces;
|
||||
|
||||
public static string RemoveHtmlTags(string s)
|
||||
{
|
||||
var match = _htmlRegex.Match(s);
|
||||
while (match.Success)
|
||||
{
|
||||
s = s.Replace(match.Value, string.Empty);
|
||||
match = match.NextMatch();
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
public static bool TryGetDisplayAsset(UObject uObject, out SKBitmap preview)
|
||||
{
|
||||
if (uObject.TryGetValue(out FSoftObjectPath sidePanelIcon, "SidePanelIcon"))
|
||||
{
|
||||
preview = GetBitmap(sidePanelIcon);
|
||||
return preview != null;
|
||||
}
|
||||
|
||||
var path = $"/Game/Catalog/MI_OfferImages/MI_{uObject.Name.Replace("Athena_Commando_", string.Empty)}";
|
||||
if (!TryLoadObject(path, out UMaterialInstanceConstant material)) // non-obfuscated item definition
|
||||
{
|
||||
if (!TryLoadObject($"{path[..path.LastIndexOf('_')]}_{path.SubstringAfterLast('_').ToLower()}", out material)) // Try to get MI with lowercase obfuscation
|
||||
TryLoadObject(path[..path.LastIndexOf('_')], out material); // hopefully gets obfuscated item definition
|
||||
}
|
||||
|
||||
preview = GetBitmap(material);
|
||||
return preview != null;
|
||||
}
|
||||
|
||||
public static SKBitmap GetBitmap(FPackageIndex packageIndex)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (!TryGetPackageIndexExport(packageIndex, out UObject export)) return null;
|
||||
switch (export)
|
||||
{
|
||||
case UTexture2D texture:
|
||||
return GetBitmap(texture);
|
||||
case UMaterialInstanceConstant material:
|
||||
return GetBitmap(material);
|
||||
default:
|
||||
{
|
||||
if (export.TryGetValue(out FInstancedStruct[] dataList, "DataList")) return GetBitmap(dataList);
|
||||
if (export.TryGetValue(out FSoftObjectPath previewImage, "LargePreviewImage", "SmallPreviewImage")) return GetBitmap(previewImage);
|
||||
if (export.TryGetValue(out string largePreview, "LargePreviewImage")) return GetBitmap(largePreview);
|
||||
if (export.TryGetValue(out FPackageIndex smallPreview, "SmallPreviewImage"))
|
||||
{
|
||||
packageIndex = smallPreview;
|
||||
continue;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static SKBitmap GetBitmap(FInstancedStruct[] structs)
|
||||
{
|
||||
if (structs.FirstOrDefault(d => d.NonConstStruct?.TryGetValue(out FSoftObjectPath p, "LargeIcon") == true && !p.AssetPathName.IsNone) is { NonConstStruct: not null } isl)
|
||||
{
|
||||
return GetBitmap(isl.NonConstStruct.Get<FSoftObjectPath>("LargeIcon"));
|
||||
}
|
||||
|
||||
if (structs.FirstOrDefault(d => d.NonConstStruct?.TryGetValue(out FSoftObjectPath p, "Icon") == true && !p.AssetPathName.IsNone) is { NonConstStruct: not null } isi)
|
||||
{
|
||||
return GetBitmap(isi.NonConstStruct.Get<FSoftObjectPath>("Icon"));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static SKBitmap GetBitmap(UMaterialInstanceConstant material)
|
||||
{
|
||||
if (material == null) return null;
|
||||
foreach (var textureParameter in material.TextureParameterValues)
|
||||
{
|
||||
if (!textureParameter.ParameterValue.TryLoad<UTexture2D>(out var texture)) continue;
|
||||
switch (textureParameter.ParameterInfo.Name.Text)
|
||||
{
|
||||
case "MainTex":
|
||||
case "Texture":
|
||||
case "TextureA":
|
||||
case "TextureB":
|
||||
case "OfferImage":
|
||||
case "KeyArtTexture":
|
||||
case "NPC-Portrait":
|
||||
{
|
||||
return GetBitmap(texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static SKBitmap GetB64Bitmap(string b64) => SKBitmap.Decode(new MemoryStream(Convert.FromBase64String(b64)) { Position = 0 });
|
||||
public static SKBitmap GetBitmap(FSoftObjectPath softObjectPath) => GetBitmap(softObjectPath.AssetPathName.Text);
|
||||
public static SKBitmap GetBitmap(string fullPath) => TryLoadObject(fullPath, out UTexture2D texture) ? GetBitmap(texture) : null;
|
||||
public static SKBitmap GetBitmap(UTexture2D texture) => texture.Decode(UserSettings.Default.CurrentDir.TexturePlatform);
|
||||
public static SKBitmap GetBitmap(byte[] data) => SKBitmap.Decode(data);
|
||||
|
||||
public static SKBitmap ResizeWithRatio(this SKBitmap me, double width, double height)
|
||||
{
|
||||
var ratioX = width / me.Width;
|
||||
var ratioY = height / me.Height;
|
||||
return ResizeWithRatio(me, ratioX < ratioY ? ratioX : ratioY);
|
||||
}
|
||||
public static SKBitmap ResizeWithRatio(this SKBitmap me, double ratio)
|
||||
{
|
||||
return me.Resize(Convert.ToInt32(me.Width * ratio), Convert.ToInt32(me.Height * ratio));
|
||||
}
|
||||
|
||||
public static SKBitmap Resize(this SKBitmap me, int size) => me.Resize(size, size);
|
||||
public static SKBitmap Resize(this SKBitmap me, int width, int height)
|
||||
{
|
||||
var bmp = new SKBitmap(new SKImageInfo(width, height), SKBitmapAllocFlags.ZeroPixels);
|
||||
using var pixmap = bmp.PeekPixels();
|
||||
me.ScalePixels(pixmap, SKFilterQuality.Medium);
|
||||
return bmp;
|
||||
}
|
||||
|
||||
public static bool TryGetPackageIndexExport<T>(FPackageIndex packageIndex, out T export) where T : UObject
|
||||
{
|
||||
return packageIndex.TryLoad(out export);
|
||||
}
|
||||
|
||||
// fullpath must be either without any extension or with the export objectname
|
||||
public static bool TryLoadObject<T>(string fullPath, out T export) where T : UObject
|
||||
{
|
||||
return _applicationView.CUE4Parse.Provider.TryLoadObject(fullPath, out export);
|
||||
}
|
||||
|
||||
public static IEnumerable<UObject> LoadExports(string packagePath)
|
||||
{
|
||||
return _applicationView.CUE4Parse.Provider.LoadAllObjects(packagePath);
|
||||
}
|
||||
|
||||
public static float GetMaxFontSize(double sectorSize, SKTypeface typeface, string text, float degreeOfCertainty = 1f, float maxFont = 100f)
|
||||
{
|
||||
var max = maxFont;
|
||||
var min = 0f;
|
||||
var last = -1f;
|
||||
float value;
|
||||
while (true)
|
||||
{
|
||||
value = min + ((max - min) / 2);
|
||||
using (SKFont ft = new SKFont(typeface, value))
|
||||
using (SKPaint paint = new SKPaint(ft))
|
||||
{
|
||||
if (paint.MeasureText(text) > sectorSize)
|
||||
{
|
||||
last = value;
|
||||
max = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
min = value;
|
||||
if (Math.Abs(last - value) <= degreeOfCertainty)
|
||||
return last;
|
||||
|
||||
last = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetLocalizedResource(string @namespace, string key, string defaultValue)
|
||||
{
|
||||
return _applicationView.CUE4Parse.Provider.GetLocalizedString(@namespace, key, defaultValue);
|
||||
}
|
||||
public static string GetLocalizedResource<T>(T @enum) where T : Enum
|
||||
{
|
||||
var resource = _applicationView.CUE4Parse.Provider.GetLocalizedString("", @enum.GetDescription(), @enum.ToString());
|
||||
return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(resource.ToLower());
|
||||
}
|
||||
|
||||
public static string GetFullPath(string partialPath)
|
||||
{
|
||||
var regex = new Regex(partialPath, RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
foreach (var path in _applicationView.CUE4Parse.Provider.Files.Keys)
|
||||
{
|
||||
if (regex.IsMatch(path))
|
||||
{
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public static void DrawCenteredMultilineText(SKCanvas c, string text, int maxCount, int size, int margin, SKTextAlign side, SKRect area, SKPaint paint)
|
||||
{
|
||||
var lineHeight = paint.TextSize * 1.2f;
|
||||
var lines = SplitLines(text, paint, area.Width - margin);
|
||||
|
||||
#if DEBUG
|
||||
c.DrawRect(new SKRect(area.Left, area.Top, area.Right, area.Bottom), new SKPaint { Color = SKColors.Red, IsStroke = true });
|
||||
#endif
|
||||
|
||||
if (lines == null) return;
|
||||
if (lines.Count <= maxCount) maxCount = lines.Count;
|
||||
var height = maxCount * lineHeight;
|
||||
var y = area.MidY - height / 2;
|
||||
|
||||
var shaper = new CustomSKShaper(paint.Typeface);
|
||||
for (var i = 0; i < maxCount; i++)
|
||||
{
|
||||
var line = lines[i];
|
||||
if (line == null) continue;
|
||||
|
||||
var lineText = line.Trim();
|
||||
var shapedText = shaper.Shape(lineText, paint);
|
||||
|
||||
y += lineHeight;
|
||||
var x = side switch
|
||||
{
|
||||
SKTextAlign.Center => area.MidX - shapedText.Width / 2,
|
||||
SKTextAlign.Right => size - margin - shapedText.Width,
|
||||
SKTextAlign.Left => margin,
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
|
||||
c.DrawShapedText(shaper, lineText, x, y, paint);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawMultilineText(SKCanvas c, string text, int size, int margin, SKTextAlign side, SKRect area, SKPaint paint, out float yPos)
|
||||
{
|
||||
yPos = area.Top;
|
||||
var lineHeight = paint.TextSize * 1.2f;
|
||||
var lines = SplitLines(text, paint, area.Width);
|
||||
if (lines == null) return;
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var fontSize = GetMaxFontSize(area.Width, paint.Typeface, line);
|
||||
if (paint.TextSize > fontSize) // if the text is not fitting in the line decrease the font size (CKJ languages)
|
||||
{
|
||||
paint.TextSize = fontSize;
|
||||
lineHeight = paint.TextSize * 1.2f;
|
||||
}
|
||||
|
||||
if (line == null) continue;
|
||||
var lineText = line.Trim();
|
||||
var shaper = new CustomSKShaper(paint.Typeface);
|
||||
var shapedText = shaper.Shape(lineText, paint);
|
||||
|
||||
var x = side switch
|
||||
{
|
||||
SKTextAlign.Center => area.MidX - shapedText.Width / 2,
|
||||
SKTextAlign.Right => size - margin - shapedText.Width,
|
||||
SKTextAlign.Left => area.Left,
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
|
||||
c.DrawShapedText(shaper, lineText, x, yPos, paint);
|
||||
yPos += lineHeight;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
c.DrawRect(new SKRect(area.Left, area.Top - paint.TextSize, area.Right, yPos), new SKPaint { Color = SKColors.Red, IsStroke = true });
|
||||
#endif
|
||||
}
|
||||
|
||||
#region Chinese, Korean and Japanese text split
|
||||
|
||||
// https://github.com/YoungjaeKim/mikan.sharp/blob/master/MikanSharp/Mikan/Mikan.cs
|
||||
|
||||
static string joshi = @"(でなければ|について|かしら|くらい|けれど|なのか|ばかり|ながら|ことよ|こそ|こと|さえ|しか|した|たり|だけ|だに|だの|つつ|ても|てよ|でも|とも|から|など|なり|ので|のに|ほど|まで|もの|やら|より|って|で|と|な|に|ね|の|も|は|ば|へ|や|わ|を|か|が|さ|し|ぞ|て)";
|
||||
static string keywords = @"(\ |[a-zA-Z0-9]+\.[a-z]{2,}|[一-龠々〆ヵヶゝ]+|[ぁ-んゝ]+|[ァ-ヴー]+|[a-zA-Z0-9]+|[a-zA-Z0-9]+)";
|
||||
static string periods = @"([\.\,。、!\!?\?]+)$";
|
||||
static string bracketsBegin = @"([〈《「『「((\[【〔〚〖〘❮❬❪❨(<{❲❰{❴])";
|
||||
static string bracketsEnd = @"([〉》」』」))\]】〕〗〙〛}>\)❩❫❭❯❱❳❵}])";
|
||||
|
||||
public static string[] SplitCKJText(string str)
|
||||
{
|
||||
var line1 = Regex.Split(str, keywords).ToList();
|
||||
var line2 = line1.SelectMany((o, _) => Regex.Split(o, joshi)).ToList();
|
||||
var line3 = line2.SelectMany((o, _) => Regex.Split(o, bracketsBegin)).ToList();
|
||||
var line4 = line3.SelectMany((o, _) => Regex.Split(o, bracketsEnd)).ToList();
|
||||
var words = line4.Where(o => !string.IsNullOrEmpty(o)).ToList();
|
||||
|
||||
var prevType = string.Empty;
|
||||
var prevWord = string.Empty;
|
||||
List<string> result = new List<string>();
|
||||
|
||||
words.ForEach(word =>
|
||||
{
|
||||
var token = Regex.IsMatch(word, periods) || Regex.IsMatch(word, joshi);
|
||||
|
||||
if (Regex.IsMatch(word, bracketsBegin))
|
||||
{
|
||||
prevType = "braketBegin";
|
||||
prevWord = word;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Regex.IsMatch(word, bracketsEnd))
|
||||
{
|
||||
result[result.Count - 1] += word;
|
||||
prevType = "braketEnd";
|
||||
prevWord = word;
|
||||
return;
|
||||
}
|
||||
|
||||
if (prevType == "braketBegin")
|
||||
{
|
||||
word = prevWord + word;
|
||||
prevWord = string.Empty;
|
||||
prevType = string.Empty;
|
||||
}
|
||||
|
||||
// すでに文字が入っている上で助詞が続く場合は結合する
|
||||
if (result.Count > 0 && token && prevType == string.Empty)
|
||||
{
|
||||
result[result.Count - 1] += word;
|
||||
prevType = "keyword";
|
||||
prevWord = word;
|
||||
return;
|
||||
}
|
||||
|
||||
// 単語のあとの文字がひらがななら結合する
|
||||
if (result.Count > 1 && token || (prevType == "keyword" && Regex.IsMatch(word, @"[ぁ-んゝ]+")))
|
||||
{
|
||||
result[result.Count - 1] += word;
|
||||
prevType = string.Empty;
|
||||
prevWord = word;
|
||||
return;
|
||||
}
|
||||
|
||||
result.Add(word);
|
||||
prevType = "keyword";
|
||||
prevWord = word;
|
||||
});
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static List<string> SplitLines(string text, SKPaint paint, float maxWidth)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text)) return null;
|
||||
|
||||
var spaceWidth = paint.MeasureText(" ");
|
||||
var lines = text.Split('\n', StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
var ret = new List<string>(lines.Length);
|
||||
foreach (var line in lines)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(line)) continue;
|
||||
|
||||
float width = 0;
|
||||
var isCJK = false;
|
||||
var words = line.Split(' ', StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if (words.Length <= 1 && UserSettings.Default.AssetLanguage is ELanguage.Japanese or ELanguage.Korean or ELanguage.Chinese or ELanguage.TraditionalChinese)
|
||||
{
|
||||
words = SplitCKJText(line);
|
||||
isCJK = true;
|
||||
}
|
||||
|
||||
var lineResult = new StringBuilder();
|
||||
foreach (var word in words)
|
||||
{
|
||||
var wordWidth = paint.MeasureText(word);
|
||||
var wordWithSpaceWidth = wordWidth + spaceWidth;
|
||||
var wordWithSpace = isCJK ? word : word + " ";
|
||||
|
||||
if (width + wordWidth > maxWidth)
|
||||
{
|
||||
ret.Add(lineResult.ToString());
|
||||
lineResult = new StringBuilder(wordWithSpace);
|
||||
width = wordWithSpaceWidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
lineResult.Append(wordWithSpace);
|
||||
width += wordWithSpaceWidth;
|
||||
}
|
||||
}
|
||||
|
||||
ret.Add(lineResult.ToString());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace FModel
|
||||
{
|
||||
public class SplitButton : Button
|
||||
{
|
||||
[DefaultValue(null), Browsable(true),
|
||||
DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
public ContextMenuStrip Menu { get; set; }
|
||||
|
||||
[DefaultValue(20), Browsable(true),
|
||||
DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
public int SplitWidth { get; set; }
|
||||
|
||||
public SplitButton()
|
||||
{
|
||||
SplitWidth = 20;
|
||||
}
|
||||
|
||||
protected override void OnMouseDown(MouseEventArgs mevent)
|
||||
{
|
||||
var splitRect = new Rectangle(this.Width - this.SplitWidth, 0, this.SplitWidth, this.Height);
|
||||
|
||||
// Figure out if the button click was on the button itself or the menu split
|
||||
if (Menu != null &&
|
||||
mevent.Button == MouseButtons.Left &&
|
||||
splitRect.Contains(mevent.Location))
|
||||
{
|
||||
Menu.Show(this, 0, this.Height); // Shows menu under button
|
||||
//Menu.Show(this, mevent.Location); // Shows menu at click location
|
||||
}
|
||||
else
|
||||
{
|
||||
base.OnMouseDown(mevent);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs pevent)
|
||||
{
|
||||
base.OnPaint(pevent);
|
||||
|
||||
if (this.Menu != null && this.SplitWidth > 0)
|
||||
{
|
||||
// Draw the arrow glyph on the right side of the button
|
||||
int arrowX = ClientRectangle.Width - 14;
|
||||
int arrowY = ClientRectangle.Height / 2 - 1;
|
||||
|
||||
var arrowBrush = Enabled ? SystemBrushes.ControlText : SystemBrushes.ButtonShadow;
|
||||
var arrows = new[] { new Point(arrowX, arrowY), new Point(arrowX + 7, arrowY), new Point(arrowX + 3, arrowY + 4) };
|
||||
pevent.Graphics.FillPolygon(arrowBrush, arrows);
|
||||
|
||||
// Draw a dashed separator on the left of the arrow
|
||||
int lineX = ClientRectangle.Width - this.SplitWidth;
|
||||
int lineYFrom = arrowY - 4;
|
||||
int lineYTo = arrowY + 8;
|
||||
using (var separatorPen = new Pen(Brushes.DarkGray) { DashStyle = DashStyle.Dot })
|
||||
{
|
||||
pevent.Graphics.DrawLine(separatorPen, lineX, lineYFrom, lineX, lineYTo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
116
FModel/Enums.cs
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace FModel;
|
||||
|
||||
public enum EBuildKind
|
||||
{
|
||||
Debug,
|
||||
Release,
|
||||
Unknown
|
||||
}
|
||||
|
||||
public enum EErrorKind
|
||||
{
|
||||
Ignore,
|
||||
Restart,
|
||||
ResetSettings
|
||||
}
|
||||
|
||||
public enum SettingsOut
|
||||
{
|
||||
ReloadLocres,
|
||||
ReloadMappings
|
||||
}
|
||||
|
||||
public enum EStatusKind
|
||||
{
|
||||
Ready, // ready
|
||||
Loading, // doing stuff
|
||||
Stopping, // trying to stop
|
||||
Stopped, // stopped
|
||||
Failed, // crashed
|
||||
Completed // worked
|
||||
}
|
||||
|
||||
public enum EAesReload
|
||||
{
|
||||
[Description("Always")]
|
||||
Always,
|
||||
[Description("Never")]
|
||||
Never,
|
||||
[Description("Once Per Day")]
|
||||
OncePerDay
|
||||
}
|
||||
|
||||
public enum EDiscordRpc
|
||||
{
|
||||
[Description("Always")]
|
||||
Always,
|
||||
[Description("Never")]
|
||||
Never
|
||||
}
|
||||
|
||||
public enum ELoadingMode
|
||||
{
|
||||
[Description("Multiple")]
|
||||
Multiple,
|
||||
[Description("All")]
|
||||
All,
|
||||
[Description("All (New)")]
|
||||
AllButNew,
|
||||
[Description("All (Modified)")]
|
||||
AllButModified
|
||||
}
|
||||
|
||||
// public enum EUpdateMode
|
||||
// {
|
||||
// [Description("Stable")]
|
||||
// Stable,
|
||||
// [Description("Beta")]
|
||||
// Beta,
|
||||
// [Description("QA Testing")]
|
||||
// Qa
|
||||
// }
|
||||
|
||||
public enum ECompressedAudio
|
||||
{
|
||||
[Description("Play the decompressed data")]
|
||||
PlayDecompressed,
|
||||
[Description("Play the compressed data (might not always be a valid audio data)")]
|
||||
PlayCompressed
|
||||
}
|
||||
|
||||
public enum EIconStyle
|
||||
{
|
||||
[Description("Default")]
|
||||
Default,
|
||||
[Description("No Background")]
|
||||
NoBackground,
|
||||
[Description("No Text")]
|
||||
NoText,
|
||||
[Description("Flat")]
|
||||
Flat,
|
||||
[Description("Cataba")]
|
||||
Cataba,
|
||||
// [Description("Community")]
|
||||
// CommunityMade
|
||||
}
|
||||
|
||||
public enum EEndpointType
|
||||
{
|
||||
Aes,
|
||||
Mapping
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum EBulkType
|
||||
{
|
||||
None = 0,
|
||||
Auto = 1 << 0,
|
||||
Properties = 1 << 1,
|
||||
Textures = 1 << 2,
|
||||
Meshes = 1 << 3,
|
||||
Skeletons = 1 << 4,
|
||||
Animations = 1 << 5
|
||||
}
|
||||
54
FModel/Extensions/AvalonExtensions.cs
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Xml;
|
||||
using ICSharpCode.AvalonEdit.Highlighting;
|
||||
using ICSharpCode.AvalonEdit.Highlighting.Xshd;
|
||||
|
||||
namespace FModel.Extensions;
|
||||
|
||||
public static class AvalonExtensions
|
||||
{
|
||||
private static readonly IHighlightingDefinition _jsonHighlighter = LoadHighlighter("Json.xshd");
|
||||
private static readonly IHighlightingDefinition _iniHighlighter = LoadHighlighter("Ini.xshd");
|
||||
private static readonly IHighlightingDefinition _xmlHighlighter = LoadHighlighter("Xml.xshd");
|
||||
private static readonly IHighlightingDefinition _cppHighlighter = LoadHighlighter("Cpp.xshd");
|
||||
private static readonly IHighlightingDefinition _changelogHighlighter = LoadHighlighter("Changelog.xshd");
|
||||
private static readonly IHighlightingDefinition _verseHighlighter = LoadHighlighter("Verse.xshd");
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static IHighlightingDefinition LoadHighlighter(string resourceName)
|
||||
{
|
||||
var executingAssembly = Assembly.GetExecutingAssembly();
|
||||
using var stream = executingAssembly.GetManifestResourceStream($"{executingAssembly.GetName().Name}.Resources.{resourceName}");
|
||||
using var reader = new XmlTextReader(stream);
|
||||
return HighlightingLoader.Load(reader, HighlightingManager.Instance);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static IHighlightingDefinition HighlighterSelector(string ext)
|
||||
{
|
||||
switch (ext)
|
||||
{
|
||||
case "ini":
|
||||
case "csv":
|
||||
return _iniHighlighter;
|
||||
case "xml":
|
||||
case "tps":
|
||||
return _xmlHighlighter;
|
||||
case "h":
|
||||
case "cpp":
|
||||
return _cppHighlighter;
|
||||
case "changelog":
|
||||
return _changelogHighlighter;
|
||||
case "verse":
|
||||
return _verseHighlighter;
|
||||
case "bat":
|
||||
case "txt":
|
||||
case "pem":
|
||||
case "po":
|
||||
return null;
|
||||
default:
|
||||
return _jsonHighlighter;
|
||||
}
|
||||
}
|
||||
}
|
||||
198
FModel/Extensions/ClipboardExtensions.cs
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
using SkiaSharp;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
|
||||
namespace FModel.Extensions;
|
||||
|
||||
public static class ClipboardExtensions
|
||||
{
|
||||
public static void SetImage(byte[] pngBytes, string fileName = null)
|
||||
{
|
||||
Clipboard.Clear();
|
||||
var data = new DataObject();
|
||||
using var pngMs = new MemoryStream(pngBytes);
|
||||
using var image = Image.FromStream(pngMs);
|
||||
// As standard bitmap, without transparency support
|
||||
data.SetData(DataFormats.Bitmap, image, true);
|
||||
// As PNG. Gimp will prefer this over the other two
|
||||
data.SetData("PNG", pngMs, false);
|
||||
// As DIB. This is (wrongly) accepted as ARGB by many applications
|
||||
using var dibMemStream = new MemoryStream(ConvertToDib(image));
|
||||
data.SetData(DataFormats.Dib, dibMemStream, false);
|
||||
// Optional fileName
|
||||
if (!string.IsNullOrEmpty(fileName))
|
||||
{
|
||||
var htmlFragment = GenerateHTMLFragment($"<img src=\"{fileName}\"/>");
|
||||
data.SetData(DataFormats.Html, htmlFragment);
|
||||
}
|
||||
// The 'copy=true' argument means the MemoryStreams can be safely disposed after the operation
|
||||
Clipboard.SetDataObject(data, true);
|
||||
}
|
||||
|
||||
public static byte[] ConvertToDib(Image image)
|
||||
{
|
||||
byte[] bm32bData;
|
||||
var width = image.Width;
|
||||
var height = image.Height;
|
||||
|
||||
// Ensure image is 32bppARGB by painting it on a new 32bppARGB image.
|
||||
using (var bm32b = new Bitmap(width, height, PixelFormat.Format32bppPArgb))
|
||||
{
|
||||
using (var gr = Graphics.FromImage(bm32b))
|
||||
{
|
||||
gr.DrawImage(image, new Rectangle(0, 0, width, height));
|
||||
}
|
||||
|
||||
// Bitmap format has its lines reversed.
|
||||
bm32b.RotateFlip(RotateFlipType.Rotate180FlipX);
|
||||
bm32bData = GetRawBytes(bm32b);
|
||||
}
|
||||
|
||||
// BITMAPINFOHEADER struct for DIB.
|
||||
const int hdrSize = 0x28;
|
||||
var fullImage = new byte[hdrSize + 12 + bm32bData.Length];
|
||||
//Int32 biSize;
|
||||
WriteIntToByteArray(fullImage, 0x00, 4, true, hdrSize);
|
||||
//Int32 biWidth;
|
||||
WriteIntToByteArray(fullImage, 0x04, 4, true, (uint) width);
|
||||
//Int32 biHeight;
|
||||
WriteIntToByteArray(fullImage, 0x08, 4, true, (uint) height);
|
||||
//Int16 biPlanes;
|
||||
WriteIntToByteArray(fullImage, 0x0C, 2, true, 1);
|
||||
//Int16 biBitCount;
|
||||
WriteIntToByteArray(fullImage, 0x0E, 2, true, 32);
|
||||
//BITMAPCOMPRESSION biCompression = BITMAPCOMPRESSION.BITFIELDS;
|
||||
WriteIntToByteArray(fullImage, 0x10, 4, true, 3);
|
||||
//Int32 biSizeImage;
|
||||
WriteIntToByteArray(fullImage, 0x14, 4, true, (uint) bm32bData.Length);
|
||||
// These are all 0. Since .net clears new arrays, don't bother writing them.
|
||||
//Int32 biXPelsPerMeter = 0;
|
||||
//Int32 biYPelsPerMeter = 0;
|
||||
//Int32 biClrUsed = 0;
|
||||
//Int32 biClrImportant = 0;
|
||||
|
||||
// The aforementioned "BITFIELDS": colour masks applied to the Int32 pixel value to get the R, G and B values.
|
||||
WriteIntToByteArray(fullImage, hdrSize + 0, 4, true, 0x00FF0000);
|
||||
WriteIntToByteArray(fullImage, hdrSize + 4, 4, true, 0x0000FF00);
|
||||
WriteIntToByteArray(fullImage, hdrSize + 8, 4, true, 0x000000FF);
|
||||
|
||||
Unsafe.CopyBlockUnaligned(ref fullImage[hdrSize + 12], ref bm32bData[0], (uint) bm32bData.Length);
|
||||
return fullImage;
|
||||
}
|
||||
|
||||
private static byte[] ConvertToDib(byte[] pngBytes = null)
|
||||
{
|
||||
byte[] bm32bData;
|
||||
int width, height;
|
||||
|
||||
using (var skBmp = SKBitmap.Decode(pngBytes))
|
||||
{
|
||||
width = skBmp.Width;
|
||||
height = skBmp.Height;
|
||||
using var rotated = new SKBitmap(new SKImageInfo(width, height, skBmp.ColorType));
|
||||
using var canvas = new SKCanvas(rotated);
|
||||
canvas.Scale(1, -1, 0, height / 2.0f);
|
||||
canvas.DrawBitmap(skBmp, SKPoint.Empty);
|
||||
canvas.Flush();
|
||||
bm32bData = rotated.Bytes;
|
||||
}
|
||||
|
||||
// BITMAPINFOHEADER struct for DIB.
|
||||
const int hdrSize = 0x28;
|
||||
var fullImage = new byte[hdrSize + 12 + bm32bData.Length];
|
||||
//Int32 biSize;
|
||||
WriteIntToByteArray(fullImage, 0x00, 4, true, hdrSize);
|
||||
//Int32 biWidth;
|
||||
WriteIntToByteArray(fullImage, 0x04, 4, true, (uint) width);
|
||||
//Int32 biHeight;
|
||||
WriteIntToByteArray(fullImage, 0x08, 4, true, (uint) height);
|
||||
//Int16 biPlanes;
|
||||
WriteIntToByteArray(fullImage, 0x0C, 2, true, 1);
|
||||
//Int16 biBitCount;
|
||||
WriteIntToByteArray(fullImage, 0x0E, 2, true, 32);
|
||||
//BITMAPCOMPRESSION biCompression = BITMAPCOMPRESSION.BITFIELDS;
|
||||
WriteIntToByteArray(fullImage, 0x10, 4, true, 3);
|
||||
//Int32 biSizeImage;
|
||||
WriteIntToByteArray(fullImage, 0x14, 4, true, (uint) bm32bData.Length);
|
||||
// These are all 0. Since .net clears new arrays, don't bother writing them.
|
||||
//Int32 biXPelsPerMeter = 0;
|
||||
//Int32 biYPelsPerMeter = 0;
|
||||
//Int32 biClrUsed = 0;
|
||||
//Int32 biClrImportant = 0;
|
||||
|
||||
// The aforementioned "BITFIELDS": colour masks applied to the Int32 pixel value to get the R, G and B values.
|
||||
WriteIntToByteArray(fullImage, hdrSize + 0, 4, true, 0x00FF0000);
|
||||
WriteIntToByteArray(fullImage, hdrSize + 4, 4, true, 0x0000FF00);
|
||||
WriteIntToByteArray(fullImage, hdrSize + 8, 4, true, 0x000000FF);
|
||||
|
||||
Unsafe.CopyBlockUnaligned(ref fullImage[hdrSize + 12], ref bm32bData[0], (uint) bm32bData.Length);
|
||||
return fullImage;
|
||||
}
|
||||
|
||||
public static unsafe byte[] GetRawBytes(Bitmap bmp)
|
||||
{
|
||||
var rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
|
||||
var bmpData = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat);
|
||||
var bytes = (uint) (Math.Abs(bmpData.Stride) * bmp.Height);
|
||||
var buffer = new byte[bytes];
|
||||
fixed (byte* pBuffer = buffer)
|
||||
{
|
||||
Unsafe.CopyBlockUnaligned(pBuffer, bmpData.Scan0.ToPointer(), bytes);
|
||||
}
|
||||
|
||||
bmp.UnlockBits(bmpData);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
private static void WriteIntToByteArray(byte[] data, int startIndex, int bytes, bool littleEndian, uint value)
|
||||
{
|
||||
var lastByte = bytes - 1;
|
||||
|
||||
if (data.Length < startIndex + bytes)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(startIndex), "Data array is too small to write a " + bytes + "-byte value at offset " + startIndex + ".");
|
||||
}
|
||||
|
||||
for (var index = 0; index < bytes; index++)
|
||||
{
|
||||
var offs = startIndex + (littleEndian ? index : lastByte - index);
|
||||
data[offs] = (byte) (value >> 8 * index & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
private static string GenerateHTMLFragment(string html)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
const string header = "Version:0.9\r\nStartHTML:<<<<<<<<<1\r\nEndHTML:<<<<<<<<<2\r\nStartFragment:<<<<<<<<<3\r\nEndFragment:<<<<<<<<<4\r\n";
|
||||
const string startHTML = "<html>\r\n<body>\r\n";
|
||||
const string startFragment = "<!--StartFragment-->";
|
||||
const string endFragment = "<!--EndFragment-->";
|
||||
const string endHTML = "\r\n</body>\r\n</html>";
|
||||
|
||||
sb.Append(header);
|
||||
|
||||
var startHTMLLength = header.Length;
|
||||
var startFragmentLength = startHTMLLength + startHTML.Length + startFragment.Length;
|
||||
var endFragmentLength = startFragmentLength + Encoding.UTF8.GetByteCount(html);
|
||||
var endHTMLLength = endFragmentLength + endFragment.Length + endHTML.Length;
|
||||
|
||||
sb.Replace("<<<<<<<<<1", startHTMLLength.ToString("D10"));
|
||||
sb.Replace("<<<<<<<<<2", endHTMLLength.ToString("D10"));
|
||||
sb.Replace("<<<<<<<<<3", startFragmentLength.ToString("D10"));
|
||||
sb.Replace("<<<<<<<<<4", endFragmentLength.ToString("D10"));
|
||||
|
||||
sb.Append(startHTML);
|
||||
sb.Append(startFragment);
|
||||
sb.Append(html);
|
||||
sb.Append(endFragment);
|
||||
sb.Append(endHTML);
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
36
FModel/Extensions/CollectionExtensions.cs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace FModel.Extensions;
|
||||
|
||||
public static class CollectionExtensions
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static T Next<T>(this IList<T> collection, T value)
|
||||
{
|
||||
var i = collection.IndexOf(value) + 1;
|
||||
return i >= collection.Count ? collection.First() : collection[i];
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static T Next<T>(this IList<T> collection, int index)
|
||||
{
|
||||
var i = index + 1;
|
||||
return i >= collection.Count ? collection.First() : collection[i];
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static T Previous<T>(this IList<T> collection, T value)
|
||||
{
|
||||
var i = collection.IndexOf(value) - 1;
|
||||
return i < 0 ? collection.Last() : collection[i];
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static T Previous<T>(this IList<T> collection, int index)
|
||||
{
|
||||
var i = index - 1;
|
||||
return i < 0 ? collection.Last() : collection[i];
|
||||
}
|
||||
}
|
||||
59
FModel/Extensions/EnumExtensions.cs
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace FModel.Extensions;
|
||||
|
||||
public static class EnumExtensions
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static string GetDescription(this Enum value)
|
||||
{
|
||||
var fi = value.GetType().GetField(value.ToString());
|
||||
if (fi == null) return $"{value} ({value:D})";
|
||||
|
||||
var attributes = (DescriptionAttribute[]) fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||
if (attributes.Length > 0) return attributes[0].Description;
|
||||
|
||||
|
||||
var suffix = $"{value:D}";
|
||||
var current = Convert.ToInt32(suffix);
|
||||
var target = current & ~0xF;
|
||||
if (current != target)
|
||||
{
|
||||
var values = Enum.GetValues(value.GetType());
|
||||
var index = Array.IndexOf(values, value);
|
||||
suffix = values.GetValue(index - (current - target))?.ToString();
|
||||
}
|
||||
return $"{value} ({suffix})";
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static T ToEnum<T>(this string value, T defaultValue) where T : struct => !Enum.TryParse(value, true, out T ret) ? defaultValue : ret;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool HasAnyFlags<T>(this T flags, T contains) where T : Enum, IConvertible => (flags.ToInt32(null) & contains.ToInt32(null)) != 0;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static int GetIndex(this Enum value)
|
||||
{
|
||||
var values = Enum.GetValues(value.GetType());
|
||||
return Array.IndexOf(values, value);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static T Next<T>(this Enum value)
|
||||
{
|
||||
var values = Enum.GetValues(value.GetType());
|
||||
var i = Array.IndexOf(values, value) + 1;
|
||||
return i == values.Length ? (T) values.GetValue(0) : (T) values.GetValue(i);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static T Previous<T>(this Enum value)
|
||||
{
|
||||
var values = Enum.GetValues(value.GetType());
|
||||
var i = Array.IndexOf(values, value) - 1;
|
||||
return i == -1 ? (T) values.GetValue(values.Length - 1) : (T) values.GetValue(i);
|
||||
}
|
||||
}
|
||||
30
FModel/Extensions/StreamExtensions.cs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace FModel.Extensions;
|
||||
|
||||
public enum Endianness
|
||||
{
|
||||
LittleEndian,
|
||||
BigEndian
|
||||
}
|
||||
|
||||
public static class StreamExtensions
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static uint ReadUInt32(this Stream s, Endianness endian = Endianness.LittleEndian)
|
||||
{
|
||||
var b1 = s.ReadByte();
|
||||
var b2 = s.ReadByte();
|
||||
var b3 = s.ReadByte();
|
||||
var b4 = s.ReadByte();
|
||||
|
||||
return endian switch
|
||||
{
|
||||
Endianness.LittleEndian => (uint) (b4 << 24 | b3 << 16 | b2 << 8 | b1),
|
||||
Endianness.BigEndian => (uint) (b1 << 24 | b2 << 16 | b3 << 8 | b4),
|
||||
_ => throw new Exception("unknown endianness")
|
||||
};
|
||||
}
|
||||
}
|
||||
185
FModel/Extensions/StringExtensions.cs
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using ICSharpCode.AvalonEdit.Document;
|
||||
|
||||
namespace FModel.Extensions;
|
||||
|
||||
public static class StringExtensions
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static string GetReadableSize(double size)
|
||||
{
|
||||
if (size == 0) return "0 B";
|
||||
|
||||
string[] sizes = { "B", "KB", "MB", "GB", "TB" };
|
||||
var order = 0;
|
||||
while (size >= 1024 && order < sizes.Length - 1)
|
||||
{
|
||||
order++;
|
||||
size /= 1024;
|
||||
}
|
||||
|
||||
return $"{size:# ###.##} {sizes[order]}".TrimStart();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static string SubstringBefore(this string s, char delimiter)
|
||||
{
|
||||
var index = s.IndexOf(delimiter);
|
||||
return index == -1 ? s : s[..index];
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static string SubstringBefore(this string s, string delimiter, StringComparison comparisonType = StringComparison.Ordinal)
|
||||
{
|
||||
var index = s.IndexOf(delimiter, comparisonType);
|
||||
return index == -1 ? s : s[..index];
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static string SubstringAfter(this string s, char delimiter)
|
||||
{
|
||||
var index = s.IndexOf(delimiter);
|
||||
return index == -1 ? s : s.Substring(index + 1, s.Length - index - 1);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static string SubstringAfter(this string s, string delimiter, StringComparison comparisonType = StringComparison.Ordinal)
|
||||
{
|
||||
var index = s.IndexOf(delimiter, comparisonType);
|
||||
return index == -1 ? s : s.Substring(index + delimiter.Length, s.Length - index - delimiter.Length);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static string SubstringBeforeLast(this string s, char delimiter)
|
||||
{
|
||||
var index = s.LastIndexOf(delimiter);
|
||||
return index == -1 ? s : s[..index];
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static string SubstringBeforeLast(this string s, string delimiter, StringComparison comparisonType = StringComparison.Ordinal)
|
||||
{
|
||||
var index = s.LastIndexOf(delimiter, comparisonType);
|
||||
return index == -1 ? s : s[..index];
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static string SubstringBeforeWithLast(this string s, char delimiter)
|
||||
{
|
||||
var index = s.LastIndexOf(delimiter);
|
||||
return index == -1 ? s : s[..(index + 1)];
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static string SubstringBeforeWithLast(this string s, string delimiter, StringComparison comparisonType = StringComparison.Ordinal)
|
||||
{
|
||||
var index = s.LastIndexOf(delimiter, comparisonType);
|
||||
return index == -1 ? s : s[..(index + 1)];
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static string SubstringAfterLast(this string s, char delimiter)
|
||||
{
|
||||
var index = s.LastIndexOf(delimiter);
|
||||
return index == -1 ? s : s.Substring(index + 1, s.Length - index - 1);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static string SubstringAfterLast(this string s, string delimiter, StringComparison comparisonType = StringComparison.Ordinal)
|
||||
{
|
||||
var index = s.LastIndexOf(delimiter, comparisonType);
|
||||
return index == -1 ? s : s.Substring(index + delimiter.Length, s.Length - index - delimiter.Length);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static int GetNameLineNumber(this string s, string lineToFind)
|
||||
{
|
||||
if (int.TryParse(lineToFind, out var index))
|
||||
return s.GetLineNumber(index);
|
||||
|
||||
lineToFind = $" \"Name\": \"{lineToFind}\",";
|
||||
using var reader = new StringReader(s);
|
||||
var lineNum = 0;
|
||||
string line;
|
||||
while ((line = reader.ReadLine()) != null)
|
||||
{
|
||||
lineNum++;
|
||||
if (line.Equals(lineToFind, StringComparison.OrdinalIgnoreCase))
|
||||
return lineNum;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static string GetParentExportType(this TextDocument doc, int startOffset)
|
||||
{
|
||||
var line = doc.GetLineByOffset(startOffset);
|
||||
var lineNumber = line.LineNumber - 1;
|
||||
|
||||
while (doc.GetText(line.Offset, line.Length) is { } content)
|
||||
{
|
||||
if (content.StartsWith(" \"Type\": \"", StringComparison.OrdinalIgnoreCase))
|
||||
return content.Split("\"")[3];
|
||||
|
||||
lineNumber--;
|
||||
if (lineNumber < 1) break;
|
||||
line = doc.GetLineByNumber(lineNumber);
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static int GetKismetLineNumber(this string s, string input)
|
||||
{
|
||||
var match = Regex.Match(input, @"^(.+)\[(\d+)\]$");
|
||||
var name = match.Groups[1].Value;
|
||||
int index = int.Parse(match.Groups[2].Value);
|
||||
var lineToFind = $" \"Name\": \"{name}\",";
|
||||
var offset = $"\"StatementIndex\": {index}";
|
||||
using var reader = new StringReader(s);
|
||||
var lineNum = 0;
|
||||
string line;
|
||||
|
||||
while ((line = reader.ReadLine()) != null)
|
||||
{
|
||||
lineNum++;
|
||||
if (line.Equals(lineToFind, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var objectLine = lineNum;
|
||||
while ((line = reader.ReadLine()) != null)
|
||||
{
|
||||
lineNum++;
|
||||
if (line.Contains(offset, StringComparison.OrdinalIgnoreCase))
|
||||
return lineNum;
|
||||
}
|
||||
return objectLine;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static int GetLineNumber(this string s, int index)
|
||||
{
|
||||
using var reader = new StringReader(s);
|
||||
var lineNum = 0;
|
||||
string line;
|
||||
while ((line = reader.ReadLine()) != null)
|
||||
{
|
||||
lineNum++;
|
||||
if (line.Equals(" {"))
|
||||
index--;
|
||||
|
||||
if (index == -1)
|
||||
return lineNum + 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,188 +1,275 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{71A31C47-30BC-4CB5-AD89-81E5008F4BEB}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>FModel</RootNamespace>
|
||||
<AssemblyName>FModel</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>true</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>false</MapFileExtensions>
|
||||
<WebPage>publish.htm</WebPage>
|
||||
<OpenBrowserOnPublish>false</OpenBrowserOnPublish>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<PublishWizardCompleted>true</PublishWizardCompleted>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<UseWPF>true</UseWPF>
|
||||
<ApplicationIcon>FModel.ico</ApplicationIcon>
|
||||
<Version>4.4.4.0</Version>
|
||||
<AssemblyVersion>4.4.4.0</AssemblyVersion>
|
||||
<FileVersion>4.4.4.0</FileVersion>
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsPublishable>true</IsPublishable>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<PublishSingleFile Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">true</PublishSingleFile>
|
||||
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
|
||||
<StartupObject>FModel.App</StartupObject>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<NoWarn>1701;1702;NU1701</NoWarn>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<NoWarn>NU1701</NoWarn>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>FNTools_Logo.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<StartupObject>FModel.Program</StartupObject>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ManifestCertificateThumbprint>3ED5A42E3C4689AF46F18366F8BF30D245116948</ManifestCertificateThumbprint>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ManifestKeyFile>FModel_TemporaryKey.pfx</ManifestKeyFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<GenerateManifests>false</GenerateManifests>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SignManifests>false</SignManifests>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetZone>LocalIntranet</TargetZone>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup />
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ScintillaNET, Version=3.6.3.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\jacobslusser.ScintillaNET.3.6.3\lib\net40\ScintillaNET.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<None Remove="Resources\android.png" />
|
||||
<None Remove="Resources\apple.png" />
|
||||
<None Remove="Resources\battlebreakers.png" />
|
||||
<None Remove="Resources\blueprint.png" />
|
||||
<None Remove="Resources\borderlands.png" />
|
||||
<None Remove="Resources\empty_folder.png" />
|
||||
<None Remove="Resources\engine.png" />
|
||||
<None Remove="Resources\fallenorder.png" />
|
||||
<None Remove="Resources\FModel.ico" />
|
||||
<None Remove="Resources\folder.png" />
|
||||
<None Remove="Resources\label.png" />
|
||||
<None Remove="Resources\fortnite.png" />
|
||||
<None Remove="Resources\fortnitebr.png" />
|
||||
<None Remove="Resources\gear.png" />
|
||||
<None Remove="Resources\localization.png" />
|
||||
<None Remove="Resources\materialicon.png" />
|
||||
<None Remove="Resources\square.png" />
|
||||
<None Remove="Resources\square_off.png" />
|
||||
<None Remove="Resources\cube.png" />
|
||||
<None Remove="Resources\cube_off.png" />
|
||||
<None Remove="Resources\light.png" />
|
||||
<None Remove="Resources\light_off.png" />
|
||||
<None Remove="Resources\pc.png" />
|
||||
<None Remove="Resources\puzzle.png" />
|
||||
<None Remove="Resources\roguecompany.png" />
|
||||
<None Remove="Resources\sound.png" />
|
||||
<None Remove="Resources\creative.png" />
|
||||
<None Remove="Resources\spellbreak.png" />
|
||||
<None Remove="Resources\texture.png" />
|
||||
<None Remove="Resources\thecycle.png" />
|
||||
<None Remove="Resources\ui.png" />
|
||||
<None Remove="Resources\valorant.png" />
|
||||
<None Remove="Resources\weapon.png" />
|
||||
<None Remove="Resources\windows.png" />
|
||||
<None Remove="Resources\cinematics.png" />
|
||||
<None Remove="Resources\archive.png" />
|
||||
<None Remove="Resources\archive_enabled.png" />
|
||||
<None Remove="Resources\archive_disabled.png" />
|
||||
<None Remove="Resources\unknown_asset.png" />
|
||||
<None Remove="Resources\asset.png" />
|
||||
<None Remove="Resources\asset_ini.png" />
|
||||
<None Remove="Resources\asset_psd.png" />
|
||||
<None Remove="Resources\asset_png.png" />
|
||||
<None Remove="Resources\athena.png" />
|
||||
<None Remove="Resources\Json.xshd" />
|
||||
<None Remove="Resources\Ini.xshd" />
|
||||
<None Remove="Resources\Verse.xshd" />
|
||||
<None Remove="Resources\Xml.xshd" />
|
||||
<None Remove="Resources\Cpp.xshd" />
|
||||
<None Remove="Resources\Changelog.xshd" />
|
||||
<None Remove="Resources\unix.png" />
|
||||
<None Remove="Resources\linux.png" />
|
||||
<None Remove="Resources\stateofdecay2.png" />
|
||||
<None Remove="Resources\T_Placeholder_Item_Image.png" />
|
||||
<None Remove="Resources\checker.png" />
|
||||
<None Remove="Resources\T_ClipSize_Weapon_Stats.png" />
|
||||
<None Remove="Resources\T_DamagePerBullet_Weapon_Stats.png" />
|
||||
<None Remove="Resources\T_ReloadTime_Weapon_Stats.png" />
|
||||
<None Remove="Resources\T-Icon-Pets-64.png" />
|
||||
<None Remove="Resources\T-Icon-Quests-64.png" />
|
||||
<None Remove="Resources\Default.png" />
|
||||
<None Remove="Resources\NoBackground.png" />
|
||||
<None Remove="Resources\NoText.png" />
|
||||
<None Remove="Resources\Flat.png" />
|
||||
<None Remove="Resources\Cataba.png" />
|
||||
<None Remove="Resources\BurbankBigCondensed-Bold.ttf" />
|
||||
<None Remove="Resources\add_directory.png" />
|
||||
<None Remove="Resources\delete.png" />
|
||||
<None Remove="Resources\edit.png" />
|
||||
<None Remove="Resources\go_to_directory.png" />
|
||||
<None Remove="Resources\npcleftside.png" />
|
||||
<None Remove="Resources\default.frag" />
|
||||
<None Remove="Resources\default.vert" />
|
||||
<None Remove="Resources\grid.frag" />
|
||||
<None Remove="Resources\grid.vert" />
|
||||
<None Remove="Resources\skybox.frag" />
|
||||
<None Remove="Resources\skybox.vert" />
|
||||
<None Remove="Resources\framebuffer.frag" />
|
||||
<None Remove="Resources\framebuffer.vert" />
|
||||
<None Remove="Resources\outline.frag" />
|
||||
<None Remove="Resources\outline.vert" />
|
||||
<None Remove="Resources\picking.frag" />
|
||||
<None Remove="Resources\picking.vert" />
|
||||
<None Remove="Resources\light.frag" />
|
||||
<None Remove="Resources\light.vert" />
|
||||
<None Remove="Resources\bone.frag" />
|
||||
<None Remove="Resources\bone.vert" />
|
||||
<None Remove="Resources\collision.vert" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="Options.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Options.Designer.cs">
|
||||
<DependentUpon>Options.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="PAKWindow.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="PAKWindow.Designer.cs">
|
||||
<DependentUpon>PAKWindow.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Parser\ChallengeBundleIdParser.cs" />
|
||||
<Compile Include="Parser\ItemsIDParser.cs" />
|
||||
<Compile Include="Parser\QuestParser.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Custom\SplitButtonControl.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Options.resx">
|
||||
<DependentUpon>Options.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="PAKWindow.resx">
|
||||
<DependentUpon>PAKWindow.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<EmbeddedResource Include="Resources\Json.xshd" />
|
||||
<EmbeddedResource Include="Resources\Ini.xshd" />
|
||||
<EmbeddedResource Include="Resources\Verse.xshd" />
|
||||
<EmbeddedResource Include="Resources\Xml.xshd" />
|
||||
<EmbeddedResource Include="Resources\Cpp.xshd" />
|
||||
<EmbeddedResource Include="Resources\Changelog.xshd" />
|
||||
<EmbeddedResource Include="Resources\default.frag" />
|
||||
<EmbeddedResource Include="Resources\default.vert" />
|
||||
<EmbeddedResource Include="Resources\grid.frag" />
|
||||
<EmbeddedResource Include="Resources\grid.vert" />
|
||||
<EmbeddedResource Include="Resources\skybox.frag" />
|
||||
<EmbeddedResource Include="Resources\skybox.vert" />
|
||||
<EmbeddedResource Include="Resources\framebuffer.frag" />
|
||||
<EmbeddedResource Include="Resources\framebuffer.vert" />
|
||||
<EmbeddedResource Include="Resources\outline.frag" />
|
||||
<EmbeddedResource Include="Resources\outline.vert" />
|
||||
<EmbeddedResource Include="Resources\picking.frag" />
|
||||
<EmbeddedResource Include="Resources\picking.vert" />
|
||||
<EmbeddedResource Include="Resources\light.frag" />
|
||||
<EmbeddedResource Include="Resources\light.vert" />
|
||||
<EmbeddedResource Include="Resources\bone.frag" />
|
||||
<EmbeddedResource Include="Resources\bone.vert" />
|
||||
<EmbeddedResource Include="Resources\collision.vert" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AdonisUI" Version="1.17.1" />
|
||||
<PackageReference Include="AdonisUI.ClassicTheme" Version="1.17.1" />
|
||||
<PackageReference Include="Autoupdater.NET.Official" Version="1.9.2" />
|
||||
<PackageReference Include="AvalonEdit" Version="6.3.0.90" />
|
||||
<PackageReference Include="CSCore" Version="1.2.1.2" />
|
||||
<PackageReference Include="DiscordRichPresence" Version="1.2.1.24" />
|
||||
<PackageReference Include="EpicManifestParser" Version="2.3.3" />
|
||||
<PackageReference Include="ImGui.NET" Version="1.91.0.1" />
|
||||
<PackageReference Include="K4os.Compression.LZ4.Streams" Version="1.3.8" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NVorbis" Version="0.10.5" />
|
||||
<PackageReference Include="Ookii.Dialogs.Wpf" Version="5.0.1" />
|
||||
<PackageReference Include="OpenTK" Version="4.8.2" />
|
||||
<PackageReference Include="RestSharp" Version="112.1.0" />
|
||||
<PackageReference Include="Serilog" Version="4.0.2" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" />
|
||||
<PackageReference Include="SkiaSharp.HarfBuzz" Version="2.88.8" />
|
||||
<PackageReference Include="SkiaSharp.Svg" Version="1.60.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CUE4Parse\CUE4Parse-Conversion\CUE4Parse-Conversion.csproj" />
|
||||
<ProjectReference Include="..\CUE4Parse\CUE4Parse\CUE4Parse.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\android.png" />
|
||||
<Resource Include="Resources\apple.png" />
|
||||
<Resource Include="Resources\battlebreakers.png" />
|
||||
<Resource Include="Resources\blueprint.png" />
|
||||
<Resource Include="Resources\borderlands.png" />
|
||||
<Resource Include="Resources\fallenorder.png" />
|
||||
<Resource Include="Resources\FModel.ico" />
|
||||
<Resource Include="Resources\folder.png" />
|
||||
<Resource Include="Resources\label.png" />
|
||||
<Resource Include="Resources\fortnite.png" />
|
||||
<Resource Include="Resources\fortnitebr.png" />
|
||||
<Resource Include="Resources\empty_folder.png" />
|
||||
<Resource Include="Resources\engine.png" />
|
||||
<Resource Include="Resources\gear.png" />
|
||||
<Resource Include="Resources\localization.png" />
|
||||
<Resource Include="Resources\materialicon.png" />
|
||||
<Resource Include="Resources\square.png" />
|
||||
<Resource Include="Resources\square_off.png" />
|
||||
<Resource Include="Resources\cube.png" />
|
||||
<Resource Include="Resources\cube_off.png" />
|
||||
<Resource Include="Resources\light.png" />
|
||||
<Resource Include="Resources\light_off.png" />
|
||||
<Resource Include="Resources\pc.png" />
|
||||
<Resource Include="Resources\puzzle.png" />
|
||||
<Resource Include="Resources\roguecompany.png" />
|
||||
<Resource Include="Resources\spellbreak.png" />
|
||||
<Resource Include="Resources\sound.png" />
|
||||
<Resource Include="Resources\creative.png" />
|
||||
<Resource Include="Resources\texture.png" />
|
||||
<Resource Include="Resources\thecycle.png" />
|
||||
<Resource Include="Resources\valorant.png" />
|
||||
<Resource Include="Resources\ui.png" />
|
||||
<Resource Include="Resources\weapon.png" />
|
||||
<Resource Include="Resources\windows.png" />
|
||||
<Resource Include="Resources\cinematics.png" />
|
||||
<Resource Include="Resources\archive.png" />
|
||||
<Resource Include="Resources\archive_enabled.png" />
|
||||
<Resource Include="Resources\archive_disabled.png" />
|
||||
<Resource Include="Resources\unknown_asset.png" />
|
||||
<Resource Include="Resources\asset.png" />
|
||||
<Resource Include="Resources\asset_ini.png" />
|
||||
<Resource Include="Resources\asset_psd.png" />
|
||||
<Resource Include="Resources\asset_png.png" />
|
||||
<Resource Include="Resources\athena.png" />
|
||||
<Resource Include="Resources\unix.png" />
|
||||
<Resource Include="Resources\linux.png" />
|
||||
<Resource Include="Resources\stateofdecay2.png" />
|
||||
<Resource Include="Resources\T_Placeholder_Item_Image.png" />
|
||||
<Resource Include="Resources\checker.png" />
|
||||
<Resource Include="Resources\T_ClipSize_Weapon_Stats.png" />
|
||||
<Resource Include="Resources\T_DamagePerBullet_Weapon_Stats.png" />
|
||||
<Resource Include="Resources\T_ReloadTime_Weapon_Stats.png" />
|
||||
<Resource Include="Resources\T-Icon-Pets-64.png" />
|
||||
<Resource Include="Resources\T-Icon-Quests-64.png" />
|
||||
<Resource Include="Resources\Default.png" />
|
||||
<Resource Include="Resources\NoBackground.png" />
|
||||
<Resource Include="Resources\NoText.png" />
|
||||
<Resource Include="Resources\Flat.png" />
|
||||
<Resource Include="Resources\Cataba.png" />
|
||||
<Resource Include="Resources\BurbankBigCondensed-Bold.ttf" />
|
||||
<Resource Include="Resources\add_directory.png" />
|
||||
<Resource Include="Resources\delete.png" />
|
||||
<Resource Include="Resources\edit.png" />
|
||||
<Resource Include="Resources\go_to_directory.png" />
|
||||
<Resource Include="Resources\npcleftside.png" />
|
||||
<Resource Include="Resources\nx.png" />
|
||||
<Resource Include="Resources\ny.png" />
|
||||
<Resource Include="Resources\nz.png" />
|
||||
<Resource Include="Resources\px.png" />
|
||||
<Resource Include="Resources\py.png" />
|
||||
<Resource Include="Resources\pz.png" />
|
||||
<Resource Include="Resources\pointlight.png" />
|
||||
<Resource Include="Resources\spotlight.png" />
|
||||
<Resource Include="Resources\link_on.png" />
|
||||
<Resource Include="Resources\link_off.png" />
|
||||
<Resource Include="Resources\link_has.png" />
|
||||
<Resource Include="Resources\tl_play.png" />
|
||||
<Resource Include="Resources\tl_pause.png" />
|
||||
<Resource Include="Resources\tl_rewind.png" />
|
||||
<Resource Include="Resources\tl_forward.png" />
|
||||
<Resource Include="Resources\tl_previous.png" />
|
||||
<Resource Include="Resources\tl_next.png" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<None Include="packages.config" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<EmbeddedResource Update="Properties\Resources.resx">
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="FNTools_Logo.ico" />
|
||||
<None Include="Resources\Quest.png" />
|
||||
<None Include="Resources\BurbankBigCondensed-Black.otf" />
|
||||
<None Include="Resources\FNTools_Logo.png" />
|
||||
<None Include="Resources\BurbankBigCondensed-Bold.otf" />
|
||||
<None Include="Resources\T512.png" />
|
||||
<None Include="Resources\M512.png" />
|
||||
<None Include="Resources\I512.png" />
|
||||
<None Include="Resources\unknown512.png" />
|
||||
<None Include="Resources\U512.png" />
|
||||
<None Include="Resources\R512.png" />
|
||||
<None Include="Resources\L512.png" />
|
||||
<None Include="Resources\E512.png" />
|
||||
<None Include="Resources\C512.png" />
|
||||
<None Include="Resources\BG512.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include=".NETFramework,Version=v4.6.1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>Microsoft .NET Framework 4.6.1 %28x86 et x64%29</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="AfterResolveReferences">
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'">
|
||||
<LogicalName>%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)</LogicalName>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
BIN
FModel/FModel.ico
Normal file
|
After Width: | Height: | Size: 47 KiB |
37
FModel/FModel.sln
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31912.275
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FModel", "FModel.csproj", "{B1F494EA-90A6-4C24-800E-2F724A1884CA}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUE4Parse", "..\CUE4Parse\CUE4Parse\CUE4Parse.csproj", "{C4620341-BBB7-4384-AC7D-5082D3E0386E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUE4Parse-Conversion", "..\CUE4Parse\CUE4Parse-Conversion\CUE4Parse-Conversion.csproj", "{D0E1E8F7-F56D-469A-8E24-C2439B9FFD83}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{B1F494EA-90A6-4C24-800E-2F724A1884CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B1F494EA-90A6-4C24-800E-2F724A1884CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B1F494EA-90A6-4C24-800E-2F724A1884CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B1F494EA-90A6-4C24-800E-2F724A1884CA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C4620341-BBB7-4384-AC7D-5082D3E0386E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C4620341-BBB7-4384-AC7D-5082D3E0386E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C4620341-BBB7-4384-AC7D-5082D3E0386E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C4620341-BBB7-4384-AC7D-5082D3E0386E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D0E1E8F7-F56D-469A-8E24-C2439B9FFD83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D0E1E8F7-F56D-469A-8E24-C2439B9FFD83}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D0E1E8F7-F56D-469A-8E24-C2439B9FFD83}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D0E1E8F7-F56D-469A-8E24-C2439B9FFD83}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {53DB7A15-4E15-4575-9402-0110BDF2794E}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
Before Width: | Height: | Size: 44 KiB |
32
FModel/Framework/AsyncQueue.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks.Dataflow;
|
||||
|
||||
namespace FModel.Framework;
|
||||
|
||||
public class AsyncQueue<T> : IAsyncEnumerable<T>
|
||||
{
|
||||
private readonly SemaphoreSlim _semaphore = new(1);
|
||||
private readonly BufferBlock<T> _buffer = new();
|
||||
|
||||
public int Count => _buffer.Count;
|
||||
|
||||
public void Enqueue(T item) => _buffer.Post(item);
|
||||
|
||||
public async IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken token = default)
|
||||
{
|
||||
await _semaphore.WaitAsync(token);
|
||||
try
|
||||
{
|
||||
while (Count > 0)
|
||||
{
|
||||
token.ThrowIfCancellationRequested();
|
||||
yield return await _buffer.ReceiveAsync(token);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_semaphore.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
18
FModel/Framework/Command.cs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
using System;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace FModel.Framework;
|
||||
|
||||
public abstract class Command : ICommand
|
||||
{
|
||||
public abstract void Execute(object parameter);
|
||||
|
||||
public abstract bool CanExecute(object parameter);
|
||||
|
||||
public void RaiseCanExecuteChanged()
|
||||
{
|
||||
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public event EventHandler CanExecuteChanged;
|
||||
}
|
||||
90
FModel/Framework/CustomSKShaper.cs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
using System;
|
||||
using HarfBuzzSharp;
|
||||
using SkiaSharp;
|
||||
using SkiaSharp.HarfBuzz;
|
||||
using Buffer = HarfBuzzSharp.Buffer;
|
||||
|
||||
namespace FModel.Framework;
|
||||
|
||||
public class CustomSKShaper : SKShaper
|
||||
{
|
||||
private const int _FONT_SIZE_SCALE = 512;
|
||||
private readonly Font _font;
|
||||
|
||||
public CustomSKShaper(SKTypeface typeface) : base(typeface)
|
||||
{
|
||||
using var blob = Typeface.OpenStream(out var index).ToHarfBuzzBlob();
|
||||
using var face = new Face(blob, index);
|
||||
face.Index = index;
|
||||
face.UnitsPerEm = Typeface.UnitsPerEm;
|
||||
|
||||
_font = new Font(face);
|
||||
_font.SetScale(_FONT_SIZE_SCALE, _FONT_SIZE_SCALE);
|
||||
_font.SetFunctionsOpenType();
|
||||
}
|
||||
|
||||
public new Result Shape(Buffer buffer, float xOffset, float yOffset, SKPaint paint)
|
||||
{
|
||||
if (buffer == null)
|
||||
throw new ArgumentNullException(nameof(buffer));
|
||||
|
||||
if (paint == null)
|
||||
throw new ArgumentNullException(nameof(paint));
|
||||
|
||||
// do the shaping
|
||||
_font.Shape(buffer);
|
||||
|
||||
// get the shaping results
|
||||
var len = buffer.Length;
|
||||
var info = buffer.GlyphInfos;
|
||||
var pos = buffer.GlyphPositions;
|
||||
|
||||
// get the sizes
|
||||
var textSizeY = paint.TextSize / _FONT_SIZE_SCALE;
|
||||
var textSizeX = textSizeY * paint.TextScaleX;
|
||||
|
||||
var points = new SKPoint[len];
|
||||
var clusters = new uint[len];
|
||||
var codepoints = new uint[len];
|
||||
|
||||
for (var i = 0; i < len; i++)
|
||||
{
|
||||
// move the cursor
|
||||
xOffset += pos[i].XAdvance * textSizeX;
|
||||
yOffset += pos[i].YAdvance * textSizeY;
|
||||
|
||||
codepoints[i] = info[i].Codepoint;
|
||||
clusters[i] = info[i].Cluster;
|
||||
points[i] = new SKPoint(xOffset + pos[i].XOffset * textSizeX, yOffset - pos[i].YOffset * textSizeY);
|
||||
}
|
||||
|
||||
return new Result(codepoints, clusters, points, points[^1].X);
|
||||
}
|
||||
|
||||
public new Result Shape(string text, SKPaint paint) => Shape(text, 0, 0, paint);
|
||||
|
||||
public new Result Shape(string text, float xOffset, float yOffset, SKPaint paint)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text))
|
||||
return new Result();
|
||||
|
||||
using var buffer = new Buffer();
|
||||
switch (paint.TextEncoding)
|
||||
{
|
||||
case SKTextEncoding.Utf8:
|
||||
buffer.AddUtf8(text);
|
||||
break;
|
||||
case SKTextEncoding.Utf16:
|
||||
buffer.AddUtf16(text);
|
||||
break;
|
||||
case SKTextEncoding.Utf32:
|
||||
buffer.AddUtf32(text);
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException("TextEncoding of type GlyphId is not supported.");
|
||||
}
|
||||
|
||||
buffer.GuessSegmentProperties();
|
||||
return Shape(buffer, xOffset, yOffset, paint);
|
||||
}
|
||||
}
|
||||
19
FModel/Framework/FRestRequest.cs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
using RestSharp;
|
||||
|
||||
namespace FModel.Framework;
|
||||
|
||||
public class FRestRequest : RestRequest
|
||||
{
|
||||
private const int TimeoutSeconds = 5;
|
||||
|
||||
public FRestRequest(string url, Method method = Method.Get) : base(url, method)
|
||||
{
|
||||
Timeout = TimeSpan.FromSeconds(TimeoutSeconds);
|
||||
}
|
||||
|
||||
public FRestRequest(Uri uri, Method method = Method.Get) : base(uri, method)
|
||||
{
|
||||
Timeout = TimeSpan.FromSeconds(TimeoutSeconds);
|
||||
}
|
||||
}
|
||||
45
FModel/Framework/FStatus.cs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
namespace FModel.Framework;
|
||||
|
||||
public class FStatus : ViewModel
|
||||
{
|
||||
private bool _isReady;
|
||||
public bool IsReady
|
||||
{
|
||||
get => _isReady;
|
||||
private set => SetProperty(ref _isReady, value);
|
||||
}
|
||||
|
||||
private EStatusKind _kind;
|
||||
public EStatusKind Kind
|
||||
{
|
||||
get => _kind;
|
||||
private set
|
||||
{
|
||||
SetProperty(ref _kind, value);
|
||||
IsReady = Kind != EStatusKind.Loading && Kind != EStatusKind.Stopping;
|
||||
}
|
||||
}
|
||||
|
||||
private string _label;
|
||||
public string Label
|
||||
{
|
||||
get => _label;
|
||||
private set => SetProperty(ref _label, value);
|
||||
}
|
||||
|
||||
public FStatus()
|
||||
{
|
||||
SetStatus(EStatusKind.Loading);
|
||||
}
|
||||
|
||||
public void SetStatus(EStatusKind kind, string label = "")
|
||||
{
|
||||
Kind = kind;
|
||||
UpdateStatusLabel(label);
|
||||
}
|
||||
|
||||
public void UpdateStatusLabel(string label, string prefix = null)
|
||||
{
|
||||
Label = Kind == EStatusKind.Loading ? $"{prefix ?? Kind.ToString()} {label}".Trim() : Kind.ToString();
|
||||
}
|
||||
}
|
||||
116
FModel/Framework/FullyObservableCollection.cs
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace FModel.Framework;
|
||||
|
||||
public class FullyObservableCollection<T> : ObservableCollection<T> where T : INotifyPropertyChanged
|
||||
{
|
||||
/// <summary>
|
||||
/// Occurs when a property is changed within an item.
|
||||
/// </summary>
|
||||
public event EventHandler<ItemPropertyChangedEventArgs> ItemPropertyChanged;
|
||||
|
||||
public FullyObservableCollection()
|
||||
{
|
||||
}
|
||||
|
||||
public FullyObservableCollection(List<T> list) : base(list)
|
||||
{
|
||||
ObserveAll();
|
||||
}
|
||||
|
||||
public FullyObservableCollection(IEnumerable<T> enumerable) : base(enumerable)
|
||||
{
|
||||
ObserveAll();
|
||||
}
|
||||
|
||||
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (e.Action is NotifyCollectionChangedAction.Remove or
|
||||
NotifyCollectionChangedAction.Replace)
|
||||
{
|
||||
foreach (T item in e.OldItems)
|
||||
item.PropertyChanged -= ChildPropertyChanged;
|
||||
}
|
||||
|
||||
if (e.Action is NotifyCollectionChangedAction.Add or
|
||||
NotifyCollectionChangedAction.Replace)
|
||||
{
|
||||
foreach (T item in e.NewItems)
|
||||
item.PropertyChanged += ChildPropertyChanged;
|
||||
}
|
||||
|
||||
base.OnCollectionChanged(e);
|
||||
}
|
||||
|
||||
protected void OnItemPropertyChanged(ItemPropertyChangedEventArgs e)
|
||||
{
|
||||
ItemPropertyChanged?.Invoke(this, e);
|
||||
}
|
||||
|
||||
protected void OnItemPropertyChanged(int index, PropertyChangedEventArgs e)
|
||||
{
|
||||
OnItemPropertyChanged(new ItemPropertyChangedEventArgs(index, e));
|
||||
}
|
||||
|
||||
protected override void ClearItems()
|
||||
{
|
||||
foreach (T item in Items)
|
||||
item.PropertyChanged -= ChildPropertyChanged;
|
||||
|
||||
base.ClearItems();
|
||||
}
|
||||
|
||||
private void ObserveAll()
|
||||
{
|
||||
foreach (var item in Items)
|
||||
item.PropertyChanged += ChildPropertyChanged;
|
||||
}
|
||||
|
||||
private void ChildPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
var typedSender = (T) sender;
|
||||
var i = Items.IndexOf(typedSender);
|
||||
|
||||
if (i < 0)
|
||||
throw new ArgumentException("Received property notification from item not in collection");
|
||||
|
||||
OnItemPropertyChanged(i, e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides data for the <see cref="FullyObservableCollection{T}.ItemPropertyChanged"/> event.
|
||||
/// </summary>
|
||||
public class ItemPropertyChangedEventArgs : PropertyChangedEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the index in the collection for which the property change has occurred.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Index in parent collection.
|
||||
/// </value>
|
||||
public int CollectionIndex { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ItemPropertyChangedEventArgs"/> class.
|
||||
/// </summary>
|
||||
/// <param name="index">The index in the collection of changed item.</param>
|
||||
/// <param name="name">The name of the property that changed.</param>
|
||||
public ItemPropertyChangedEventArgs(int index, string name) : base(name)
|
||||
{
|
||||
CollectionIndex = index;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ItemPropertyChangedEventArgs"/> class.
|
||||
/// </summary>
|
||||
/// <param name="index">The index.</param>
|
||||
/// <param name="args">The <see cref="PropertyChangedEventArgs"/> instance containing the event data.</param>
|
||||
public ItemPropertyChangedEventArgs(int index, PropertyChangedEventArgs args) : this(index, args.PropertyName)
|
||||
{
|
||||
}
|
||||
}
|
||||
49
FModel/Framework/Hotkey.cs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
using System.Text;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace FModel.Framework;
|
||||
|
||||
public class Hotkey : ViewModel
|
||||
{
|
||||
private Key _key;
|
||||
public Key Key
|
||||
{
|
||||
get => _key;
|
||||
set => SetProperty(ref _key, value);
|
||||
}
|
||||
|
||||
private ModifierKeys _modifiers;
|
||||
public ModifierKeys Modifiers
|
||||
{
|
||||
get => _modifiers;
|
||||
set => SetProperty(ref _modifiers, value);
|
||||
}
|
||||
|
||||
public Hotkey(Key key, ModifierKeys modifiers = ModifierKeys.None)
|
||||
{
|
||||
Key = key;
|
||||
Modifiers = modifiers;
|
||||
}
|
||||
|
||||
public bool IsTriggered(Key e)
|
||||
{
|
||||
return e == Key && Keyboard.Modifiers.HasFlag(Modifiers);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var str = new StringBuilder();
|
||||
|
||||
if (Modifiers.HasFlag(ModifierKeys.Control))
|
||||
str.Append("Ctrl + ");
|
||||
if (Modifiers.HasFlag(ModifierKeys.Shift))
|
||||
str.Append("Shift + ");
|
||||
if (Modifiers.HasFlag(ModifierKeys.Alt))
|
||||
str.Append("Alt + ");
|
||||
if (Modifiers.HasFlag(ModifierKeys.Windows))
|
||||
str.Append("Win + ");
|
||||
|
||||
str.Append(Key);
|
||||
return str.ToString();
|
||||
}
|
||||
}
|
||||
608
FModel/Framework/ImGuiController.cs
Normal file
|
|
@ -0,0 +1,608 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
using FModel.Settings;
|
||||
using ImGuiNET;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
using OpenTK.Windowing.Desktop;
|
||||
using OpenTK.Windowing.GraphicsLibraryFramework;
|
||||
using ErrorCode = OpenTK.Graphics.OpenGL4.ErrorCode;
|
||||
using Keys = OpenTK.Windowing.GraphicsLibraryFramework.Keys;
|
||||
|
||||
namespace FModel.Framework;
|
||||
|
||||
public class ImGuiController : IDisposable
|
||||
{
|
||||
private bool _frameBegun;
|
||||
|
||||
private int _vertexArray;
|
||||
private int _vertexBuffer;
|
||||
private int _vertexBufferSize;
|
||||
private int _indexBuffer;
|
||||
private int _indexBufferSize;
|
||||
|
||||
//private Texture _fontTexture;
|
||||
|
||||
private int _fontTexture;
|
||||
|
||||
private int _shader;
|
||||
private int _shaderFontTextureLocation;
|
||||
private int _shaderProjectionMatrixLocation;
|
||||
|
||||
private int _windowWidth;
|
||||
private int _windowHeight;
|
||||
|
||||
public ImFontPtr FontNormal;
|
||||
public ImFontPtr FontBold;
|
||||
public ImFontPtr FontSemiBold;
|
||||
|
||||
private readonly Vector2 _scaleFactor = Vector2.One;
|
||||
public readonly float DpiScale = GetDpiScale();
|
||||
|
||||
private static bool KHRDebugAvailable = false;
|
||||
|
||||
public ImGuiController(int width, int height)
|
||||
{
|
||||
_windowWidth = width;
|
||||
_windowHeight = height;
|
||||
|
||||
int major = GL.GetInteger(GetPName.MajorVersion);
|
||||
int minor = GL.GetInteger(GetPName.MinorVersion);
|
||||
|
||||
KHRDebugAvailable = (major == 4 && minor >= 3) || IsExtensionSupported("KHR_debug");
|
||||
|
||||
IntPtr context = ImGui.CreateContext();
|
||||
ImGui.SetCurrentContext(context);
|
||||
|
||||
var io = ImGui.GetIO();
|
||||
unsafe
|
||||
{
|
||||
var iniFileNamePtr = Marshal.StringToCoTaskMemUTF8(Path.Combine(UserSettings.Default.OutputDirectory, ".data", "imgui.ini"));
|
||||
io.NativePtr->IniFilename = (byte*)iniFileNamePtr;
|
||||
}
|
||||
FontNormal = io.Fonts.AddFontFromFileTTF("C:\\Windows\\Fonts\\segoeui.ttf", 16 * DpiScale);
|
||||
FontBold = io.Fonts.AddFontFromFileTTF("C:\\Windows\\Fonts\\segoeuib.ttf", 16 * DpiScale);
|
||||
FontSemiBold = io.Fonts.AddFontFromFileTTF("C:\\Windows\\Fonts\\seguisb.ttf", 16 * DpiScale);
|
||||
|
||||
io.BackendFlags |= ImGuiBackendFlags.RendererHasVtxOffset;
|
||||
io.ConfigFlags |= ImGuiConfigFlags.NavEnableKeyboard;
|
||||
io.ConfigFlags |= ImGuiConfigFlags.DockingEnable;
|
||||
io.Fonts.Flags |= ImFontAtlasFlags.NoBakedLines;
|
||||
|
||||
CreateDeviceResources();
|
||||
|
||||
SetPerFrameImGuiData(1f / 60f);
|
||||
|
||||
ImGui.NewFrame();
|
||||
_frameBegun = true;
|
||||
}
|
||||
|
||||
public void Bold() => PushFont(FontBold);
|
||||
public void SemiBold() => PushFont(FontSemiBold);
|
||||
|
||||
public void PopFont()
|
||||
{
|
||||
ImGui.PopFont();
|
||||
PushFont(FontNormal);
|
||||
}
|
||||
|
||||
private void PushFont(ImFontPtr ptr) => ImGui.PushFont(ptr);
|
||||
|
||||
public void WindowResized(int width, int height)
|
||||
{
|
||||
_windowWidth = width;
|
||||
_windowHeight = height;
|
||||
}
|
||||
|
||||
public void DestroyDeviceObjects()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
public void CreateDeviceResources()
|
||||
{
|
||||
_vertexBufferSize = 10000;
|
||||
_indexBufferSize = 2000;
|
||||
|
||||
int prevVAO = GL.GetInteger(GetPName.VertexArrayBinding);
|
||||
int prevArrayBuffer = GL.GetInteger(GetPName.ArrayBufferBinding);
|
||||
|
||||
_vertexArray = GL.GenVertexArray();
|
||||
GL.BindVertexArray(_vertexArray);
|
||||
LabelObject(ObjectLabelIdentifier.VertexArray, _vertexArray, "ImGui");
|
||||
|
||||
_vertexBuffer = GL.GenBuffer();
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBuffer);
|
||||
LabelObject(ObjectLabelIdentifier.Buffer, _vertexBuffer, "VBO: ImGui");
|
||||
GL.BufferData(BufferTarget.ArrayBuffer, _vertexBufferSize, IntPtr.Zero, BufferUsageHint.DynamicDraw);
|
||||
|
||||
_indexBuffer = GL.GenBuffer();
|
||||
GL.BindBuffer(BufferTarget.ElementArrayBuffer, _indexBuffer);
|
||||
LabelObject(ObjectLabelIdentifier.Buffer, _indexBuffer, "EBO: ImGui");
|
||||
GL.BufferData(BufferTarget.ElementArrayBuffer, _indexBufferSize, IntPtr.Zero, BufferUsageHint.DynamicDraw);
|
||||
|
||||
RecreateFontDeviceTexture();
|
||||
|
||||
string VertexSource = @"#version 460 core
|
||||
uniform mat4 projection_matrix;
|
||||
layout(location = 0) in vec2 in_position;
|
||||
layout(location = 1) in vec2 in_texCoord;
|
||||
layout(location = 2) in vec4 in_color;
|
||||
out vec4 color;
|
||||
out vec2 texCoord;
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection_matrix * vec4(in_position, 0, 1);
|
||||
color = in_color;
|
||||
texCoord = in_texCoord;
|
||||
}";
|
||||
string FragmentSource = @"#version 460 core
|
||||
uniform sampler2D in_fontTexture;
|
||||
in vec4 color;
|
||||
in vec2 texCoord;
|
||||
out vec4 outputColor;
|
||||
void main()
|
||||
{
|
||||
outputColor = color * texture(in_fontTexture, texCoord);
|
||||
}";
|
||||
|
||||
_shader = CreateProgram("ImGui", VertexSource, FragmentSource);
|
||||
_shaderProjectionMatrixLocation = GL.GetUniformLocation(_shader, "projection_matrix");
|
||||
_shaderFontTextureLocation = GL.GetUniformLocation(_shader, "in_fontTexture");
|
||||
|
||||
int stride = Unsafe.SizeOf<ImDrawVert>();
|
||||
GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, stride, 0);
|
||||
GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, stride, 8);
|
||||
GL.VertexAttribPointer(2, 4, VertexAttribPointerType.UnsignedByte, true, stride, 16);
|
||||
|
||||
GL.EnableVertexAttribArray(0);
|
||||
GL.EnableVertexAttribArray(1);
|
||||
GL.EnableVertexAttribArray(2);
|
||||
|
||||
GL.BindVertexArray(prevVAO);
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, prevArrayBuffer);
|
||||
|
||||
CheckGLError("End of ImGui setup");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recreates the device texture used to render text.
|
||||
/// </summary>
|
||||
public void RecreateFontDeviceTexture()
|
||||
{
|
||||
ImGuiIOPtr io = ImGui.GetIO();
|
||||
io.Fonts.GetTexDataAsRGBA32(out IntPtr pixels, out int width, out int height, out int bytesPerPixel);
|
||||
|
||||
int mips = (int)Math.Floor(Math.Log(Math.Max(width, height), 2));
|
||||
|
||||
int prevActiveTexture = GL.GetInteger(GetPName.ActiveTexture);
|
||||
GL.ActiveTexture(TextureUnit.Texture0);
|
||||
int prevTexture2D = GL.GetInteger(GetPName.TextureBinding2D);
|
||||
|
||||
_fontTexture = GL.GenTexture();
|
||||
GL.BindTexture(TextureTarget.Texture2D, _fontTexture);
|
||||
GL.TexStorage2D(TextureTarget2d.Texture2D, mips, SizedInternalFormat.Rgba8, width, height);
|
||||
LabelObject(ObjectLabelIdentifier.Texture, _fontTexture, "ImGui Text Atlas");
|
||||
|
||||
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, width, height, PixelFormat.Bgra, PixelType.UnsignedByte, pixels);
|
||||
|
||||
GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
|
||||
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
|
||||
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMaxLevel, mips - 1);
|
||||
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
|
||||
|
||||
// Restore state
|
||||
GL.BindTexture(TextureTarget.Texture2D, prevTexture2D);
|
||||
GL.ActiveTexture((TextureUnit)prevActiveTexture);
|
||||
|
||||
io.Fonts.SetTexID((IntPtr)_fontTexture);
|
||||
|
||||
io.Fonts.ClearTexData();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the ImGui draw list data.
|
||||
/// </summary>
|
||||
public void Render()
|
||||
{
|
||||
if (_frameBegun)
|
||||
{
|
||||
_frameBegun = false;
|
||||
ImGui.Render();
|
||||
RenderImDrawData(ImGui.GetDrawData());
|
||||
}
|
||||
CheckGLError("End of frame");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates ImGui input and IO configuration state.
|
||||
/// </summary>
|
||||
public void Update(GameWindow wnd, float deltaSeconds)
|
||||
{
|
||||
if (_frameBegun)
|
||||
{
|
||||
ImGui.Render();
|
||||
}
|
||||
|
||||
SetPerFrameImGuiData(deltaSeconds);
|
||||
UpdateImGuiInput(wnd);
|
||||
|
||||
_frameBegun = true;
|
||||
ImGui.NewFrame();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets per-frame data based on the associated window.
|
||||
/// This is called by Update(float).
|
||||
/// </summary>
|
||||
private void SetPerFrameImGuiData(float deltaSeconds)
|
||||
{
|
||||
ImGuiIOPtr io = ImGui.GetIO();
|
||||
// if (io.WantSaveIniSettings) ImGui.SaveIniSettingsToDisk(_iniPath);
|
||||
io.DisplaySize = new Vector2(
|
||||
_windowWidth / _scaleFactor.X,
|
||||
_windowHeight / _scaleFactor.Y);
|
||||
io.DisplayFramebufferScale = _scaleFactor;
|
||||
io.DeltaTime = deltaSeconds; // DeltaTime is in seconds.
|
||||
}
|
||||
|
||||
readonly List<char> PressedChars = new List<char>();
|
||||
|
||||
private void UpdateImGuiInput(GameWindow wnd)
|
||||
{
|
||||
ImGuiIOPtr io = ImGui.GetIO();
|
||||
var mState = wnd.MouseState;
|
||||
var kState = wnd.KeyboardState;
|
||||
|
||||
io.AddMousePosEvent(mState.X, mState.Y);
|
||||
io.AddMouseButtonEvent(0, mState[MouseButton.Left]);
|
||||
io.AddMouseButtonEvent(1, mState[MouseButton.Right]);
|
||||
io.AddMouseButtonEvent(2, mState[MouseButton.Middle]);
|
||||
io.AddMouseButtonEvent(3, mState[MouseButton.Button1]);
|
||||
io.AddMouseButtonEvent(4, mState[MouseButton.Button2]);
|
||||
io.AddMouseWheelEvent(mState.ScrollDelta.X, mState.ScrollDelta.Y);
|
||||
|
||||
foreach (Keys key in Enum.GetValues(typeof(Keys)))
|
||||
{
|
||||
if (key == Keys.Unknown) continue;
|
||||
io.AddKeyEvent(TranslateKey(key), kState.IsKeyDown(key));
|
||||
}
|
||||
|
||||
foreach (var c in PressedChars)
|
||||
{
|
||||
io.AddInputCharacter(c);
|
||||
}
|
||||
PressedChars.Clear();
|
||||
|
||||
io.KeyShift = kState.IsKeyDown(Keys.LeftShift) || kState.IsKeyDown(Keys.RightShift);
|
||||
io.KeyCtrl = kState.IsKeyDown(Keys.LeftControl) || kState.IsKeyDown(Keys.RightControl);
|
||||
io.KeyAlt = kState.IsKeyDown(Keys.LeftAlt) || kState.IsKeyDown(Keys.RightAlt);
|
||||
io.KeySuper = kState.IsKeyDown(Keys.LeftSuper) || kState.IsKeyDown(Keys.RightSuper);
|
||||
}
|
||||
|
||||
public void PressChar(char keyChar)
|
||||
{
|
||||
PressedChars.Add(keyChar);
|
||||
}
|
||||
|
||||
private void RenderImDrawData(ImDrawDataPtr draw_data)
|
||||
{
|
||||
if (draw_data.CmdListsCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Get intial state.
|
||||
int prevVAO = GL.GetInteger(GetPName.VertexArrayBinding);
|
||||
int prevArrayBuffer = GL.GetInteger(GetPName.ArrayBufferBinding);
|
||||
int prevProgram = GL.GetInteger(GetPName.CurrentProgram);
|
||||
bool prevBlendEnabled = GL.GetBoolean(GetPName.Blend);
|
||||
bool prevScissorTestEnabled = GL.GetBoolean(GetPName.ScissorTest);
|
||||
int prevBlendEquationRgb = GL.GetInteger(GetPName.BlendEquationRgb);
|
||||
int prevBlendEquationAlpha = GL.GetInteger(GetPName.BlendEquationAlpha);
|
||||
int prevBlendFuncSrcRgb = GL.GetInteger(GetPName.BlendSrcRgb);
|
||||
int prevBlendFuncSrcAlpha = GL.GetInteger(GetPName.BlendSrcAlpha);
|
||||
int prevBlendFuncDstRgb = GL.GetInteger(GetPName.BlendDstRgb);
|
||||
int prevBlendFuncDstAlpha = GL.GetInteger(GetPName.BlendDstAlpha);
|
||||
bool prevCullFaceEnabled = GL.GetBoolean(GetPName.CullFace);
|
||||
bool prevDepthTestEnabled = GL.GetBoolean(GetPName.DepthTest);
|
||||
int prevActiveTexture = GL.GetInteger(GetPName.ActiveTexture);
|
||||
GL.ActiveTexture(TextureUnit.Texture0);
|
||||
int prevTexture2D = GL.GetInteger(GetPName.TextureBinding2D);
|
||||
Span<int> prevScissorBox = stackalloc int[4];
|
||||
unsafe
|
||||
{
|
||||
fixed (int* iptr = &prevScissorBox[0])
|
||||
{
|
||||
GL.GetInteger(GetPName.ScissorBox, iptr);
|
||||
}
|
||||
}
|
||||
|
||||
// Bind the element buffer (thru the VAO) so that we can resize it.
|
||||
GL.BindVertexArray(_vertexArray);
|
||||
// Bind the vertex buffer so that we can resize it.
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBuffer);
|
||||
for (int i = 0; i < draw_data.CmdListsCount; i++)
|
||||
{
|
||||
ImDrawListPtr cmd_list = draw_data.CmdLists[i];
|
||||
|
||||
int vertexSize = cmd_list.VtxBuffer.Size * Unsafe.SizeOf<ImDrawVert>();
|
||||
if (vertexSize > _vertexBufferSize)
|
||||
{
|
||||
int newSize = (int)Math.Max(_vertexBufferSize * 1.5f, vertexSize);
|
||||
|
||||
GL.BufferData(BufferTarget.ArrayBuffer, newSize, IntPtr.Zero, BufferUsageHint.DynamicDraw);
|
||||
_vertexBufferSize = newSize;
|
||||
}
|
||||
|
||||
int indexSize = cmd_list.IdxBuffer.Size * sizeof(ushort);
|
||||
if (indexSize > _indexBufferSize)
|
||||
{
|
||||
int newSize = (int)Math.Max(_indexBufferSize * 1.5f, indexSize);
|
||||
GL.BufferData(BufferTarget.ElementArrayBuffer, newSize, IntPtr.Zero, BufferUsageHint.DynamicDraw);
|
||||
_indexBufferSize = newSize;
|
||||
}
|
||||
}
|
||||
|
||||
// Setup orthographic projection matrix into our constant buffer
|
||||
ImGuiIOPtr io = ImGui.GetIO();
|
||||
var mvp = OpenTK.Mathematics.Matrix4.CreateOrthographicOffCenter(
|
||||
0.0f,
|
||||
io.DisplaySize.X,
|
||||
io.DisplaySize.Y,
|
||||
0.0f,
|
||||
-1.0f,
|
||||
1.0f);
|
||||
|
||||
GL.UseProgram(_shader);
|
||||
GL.UniformMatrix4(_shaderProjectionMatrixLocation, false, ref mvp);
|
||||
GL.Uniform1(_shaderFontTextureLocation, 0);
|
||||
CheckGLError("Projection");
|
||||
|
||||
GL.BindVertexArray(_vertexArray);
|
||||
CheckGLError("VAO");
|
||||
|
||||
draw_data.ScaleClipRects(io.DisplayFramebufferScale);
|
||||
|
||||
GL.Enable(EnableCap.Blend);
|
||||
GL.Enable(EnableCap.ScissorTest);
|
||||
GL.BlendEquation(BlendEquationMode.FuncAdd);
|
||||
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
|
||||
GL.Disable(EnableCap.CullFace);
|
||||
GL.Disable(EnableCap.DepthTest);
|
||||
|
||||
// Render command lists
|
||||
for (int n = 0; n < draw_data.CmdListsCount; n++)
|
||||
{
|
||||
ImDrawListPtr cmd_list = draw_data.CmdLists[n];
|
||||
|
||||
GL.BufferSubData(BufferTarget.ArrayBuffer, IntPtr.Zero, cmd_list.VtxBuffer.Size * Unsafe.SizeOf<ImDrawVert>(), cmd_list.VtxBuffer.Data);
|
||||
CheckGLError($"Data Vert {n}");
|
||||
|
||||
GL.BufferSubData(BufferTarget.ElementArrayBuffer, IntPtr.Zero, cmd_list.IdxBuffer.Size * sizeof(ushort), cmd_list.IdxBuffer.Data);
|
||||
CheckGLError($"Data Idx {n}");
|
||||
|
||||
for (int cmd_i = 0; cmd_i < cmd_list.CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
ImDrawCmdPtr pcmd = cmd_list.CmdBuffer[cmd_i];
|
||||
if (pcmd.UserCallback != IntPtr.Zero)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
else
|
||||
{
|
||||
GL.ActiveTexture(TextureUnit.Texture0);
|
||||
GL.BindTexture(TextureTarget.Texture2D, (int)pcmd.TextureId);
|
||||
CheckGLError("Texture");
|
||||
|
||||
// We do _windowHeight - (int)clip.W instead of (int)clip.Y because gl has flipped Y when it comes to these coordinates
|
||||
var clip = pcmd.ClipRect;
|
||||
GL.Scissor((int)clip.X, _windowHeight - (int)clip.W, (int)(clip.Z - clip.X), (int)(clip.W - clip.Y));
|
||||
CheckGLError("Scissor");
|
||||
|
||||
if ((io.BackendFlags & ImGuiBackendFlags.RendererHasVtxOffset) != 0)
|
||||
{
|
||||
GL.DrawElementsBaseVertex(PrimitiveType.Triangles, (int)pcmd.ElemCount, DrawElementsType.UnsignedShort, (IntPtr)(pcmd.IdxOffset * sizeof(ushort)), unchecked((int)pcmd.VtxOffset));
|
||||
}
|
||||
else
|
||||
{
|
||||
GL.DrawElements(BeginMode.Triangles, (int)pcmd.ElemCount, DrawElementsType.UnsignedShort, (int)pcmd.IdxOffset * sizeof(ushort));
|
||||
}
|
||||
CheckGLError("Draw");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GL.Disable(EnableCap.Blend);
|
||||
GL.Disable(EnableCap.ScissorTest);
|
||||
|
||||
// Reset state
|
||||
GL.BindTexture(TextureTarget.Texture2D, prevTexture2D);
|
||||
GL.ActiveTexture((TextureUnit)prevActiveTexture);
|
||||
GL.UseProgram(prevProgram);
|
||||
GL.BindVertexArray(prevVAO);
|
||||
GL.Scissor(prevScissorBox[0], prevScissorBox[1], prevScissorBox[2], prevScissorBox[3]);
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, prevArrayBuffer);
|
||||
GL.BlendEquationSeparate((BlendEquationMode)prevBlendEquationRgb, (BlendEquationMode)prevBlendEquationAlpha);
|
||||
GL.BlendFuncSeparate(
|
||||
(BlendingFactorSrc)prevBlendFuncSrcRgb,
|
||||
(BlendingFactorDest)prevBlendFuncDstRgb,
|
||||
(BlendingFactorSrc)prevBlendFuncSrcAlpha,
|
||||
(BlendingFactorDest)prevBlendFuncDstAlpha);
|
||||
if (prevBlendEnabled) GL.Enable(EnableCap.Blend); else GL.Disable(EnableCap.Blend);
|
||||
if (prevDepthTestEnabled) GL.Enable(EnableCap.DepthTest); else GL.Disable(EnableCap.DepthTest);
|
||||
if (prevCullFaceEnabled) GL.Enable(EnableCap.CullFace); else GL.Disable(EnableCap.CullFace);
|
||||
if (prevScissorTestEnabled) GL.Enable(EnableCap.ScissorTest); else GL.Disable(EnableCap.ScissorTest);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Frees all graphics resources used by the renderer.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
GL.DeleteVertexArray(_vertexArray);
|
||||
GL.DeleteBuffer(_vertexBuffer);
|
||||
GL.DeleteBuffer(_indexBuffer);
|
||||
|
||||
GL.DeleteTexture(_fontTexture);
|
||||
GL.DeleteProgram(_shader);
|
||||
}
|
||||
|
||||
public static void LabelObject(ObjectLabelIdentifier objLabelIdent, int glObject, string name)
|
||||
{
|
||||
if (KHRDebugAvailable)
|
||||
GL.ObjectLabel(objLabelIdent, glObject, name.Length, name);
|
||||
}
|
||||
|
||||
static bool IsExtensionSupported(string name)
|
||||
{
|
||||
int n = GL.GetInteger(GetPName.NumExtensions);
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
string extension = GL.GetString(StringNameIndexed.Extensions, i);
|
||||
if (extension == name) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int CreateProgram(string name, string vertexSource, string fragmentSoruce)
|
||||
{
|
||||
int program = GL.CreateProgram();
|
||||
LabelObject(ObjectLabelIdentifier.Program, program, $"Program: {name}");
|
||||
|
||||
int vertex = CompileShader(name, ShaderType.VertexShader, vertexSource);
|
||||
int fragment = CompileShader(name, ShaderType.FragmentShader, fragmentSoruce);
|
||||
|
||||
GL.AttachShader(program, vertex);
|
||||
GL.AttachShader(program, fragment);
|
||||
|
||||
GL.LinkProgram(program);
|
||||
|
||||
GL.GetProgram(program, GetProgramParameterName.LinkStatus, out int success);
|
||||
if (success == 0)
|
||||
{
|
||||
string info = GL.GetProgramInfoLog(program);
|
||||
Debug.WriteLine($"GL.LinkProgram had info log [{name}]:\n{info}");
|
||||
}
|
||||
|
||||
GL.DetachShader(program, vertex);
|
||||
GL.DetachShader(program, fragment);
|
||||
|
||||
GL.DeleteShader(vertex);
|
||||
GL.DeleteShader(fragment);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
private static int CompileShader(string name, ShaderType type, string source)
|
||||
{
|
||||
int shader = GL.CreateShader(type);
|
||||
LabelObject(ObjectLabelIdentifier.Shader, shader, $"Shader: {name}");
|
||||
|
||||
GL.ShaderSource(shader, source);
|
||||
GL.CompileShader(shader);
|
||||
|
||||
GL.GetShader(shader, ShaderParameter.CompileStatus, out int success);
|
||||
if (success == 0)
|
||||
{
|
||||
string info = GL.GetShaderInfoLog(shader);
|
||||
Debug.WriteLine($"GL.CompileShader for shader '{name}' [{type}] had info log:\n{info}");
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
public static void CheckGLError(string title)
|
||||
{
|
||||
ErrorCode error;
|
||||
int i = 1;
|
||||
while ((error = GL.GetError()) != ErrorCode.NoError)
|
||||
{
|
||||
Debug.Print($"{title} ({i++}): {error}");
|
||||
}
|
||||
}
|
||||
|
||||
public static float GetDpiScale()
|
||||
{
|
||||
return Math.Max((float)(Screen.PrimaryScreen.Bounds.Width / SystemParameters.PrimaryScreenWidth), (float)(Screen.PrimaryScreen.Bounds.Height / SystemParameters.PrimaryScreenHeight));
|
||||
}
|
||||
|
||||
public static ImGuiKey TranslateKey(Keys key)
|
||||
{
|
||||
if (key is >= Keys.D0 and <= Keys.D9)
|
||||
return key - Keys.D0 + ImGuiKey._0;
|
||||
|
||||
if (key is >= Keys.A and <= Keys.Z)
|
||||
return key - Keys.A + ImGuiKey.A;
|
||||
|
||||
if (key is >= Keys.KeyPad0 and <= Keys.KeyPad9)
|
||||
return key - Keys.KeyPad0 + ImGuiKey.Keypad0;
|
||||
|
||||
if (key is >= Keys.F1 and <= Keys.F24)
|
||||
return key - Keys.F1 + ImGuiKey.F24;
|
||||
|
||||
return key switch
|
||||
{
|
||||
Keys.Tab => ImGuiKey.Tab,
|
||||
Keys.Left => ImGuiKey.LeftArrow,
|
||||
Keys.Right => ImGuiKey.RightArrow,
|
||||
Keys.Up => ImGuiKey.UpArrow,
|
||||
Keys.Down => ImGuiKey.DownArrow,
|
||||
Keys.PageUp => ImGuiKey.PageUp,
|
||||
Keys.PageDown => ImGuiKey.PageDown,
|
||||
Keys.Home => ImGuiKey.Home,
|
||||
Keys.End => ImGuiKey.End,
|
||||
Keys.Insert => ImGuiKey.Insert,
|
||||
Keys.Delete => ImGuiKey.Delete,
|
||||
Keys.Backspace => ImGuiKey.Backspace,
|
||||
Keys.Space => ImGuiKey.Space,
|
||||
Keys.Enter => ImGuiKey.Enter,
|
||||
Keys.Escape => ImGuiKey.Escape,
|
||||
Keys.Apostrophe => ImGuiKey.Apostrophe,
|
||||
Keys.Comma => ImGuiKey.Comma,
|
||||
Keys.Minus => ImGuiKey.Minus,
|
||||
Keys.Period => ImGuiKey.Period,
|
||||
Keys.Slash => ImGuiKey.Slash,
|
||||
Keys.Semicolon => ImGuiKey.Semicolon,
|
||||
Keys.Equal => ImGuiKey.Equal,
|
||||
Keys.LeftBracket => ImGuiKey.LeftBracket,
|
||||
Keys.Backslash => ImGuiKey.Backslash,
|
||||
Keys.RightBracket => ImGuiKey.RightBracket,
|
||||
Keys.GraveAccent => ImGuiKey.GraveAccent,
|
||||
Keys.CapsLock => ImGuiKey.CapsLock,
|
||||
Keys.ScrollLock => ImGuiKey.ScrollLock,
|
||||
Keys.NumLock => ImGuiKey.NumLock,
|
||||
Keys.PrintScreen => ImGuiKey.PrintScreen,
|
||||
Keys.Pause => ImGuiKey.Pause,
|
||||
Keys.KeyPadDecimal => ImGuiKey.KeypadDecimal,
|
||||
Keys.KeyPadDivide => ImGuiKey.KeypadDivide,
|
||||
Keys.KeyPadMultiply => ImGuiKey.KeypadMultiply,
|
||||
Keys.KeyPadSubtract => ImGuiKey.KeypadSubtract,
|
||||
Keys.KeyPadAdd => ImGuiKey.KeypadAdd,
|
||||
Keys.KeyPadEnter => ImGuiKey.KeypadEnter,
|
||||
Keys.KeyPadEqual => ImGuiKey.KeypadEqual,
|
||||
Keys.LeftShift => ImGuiKey.LeftShift,
|
||||
Keys.LeftControl => ImGuiKey.LeftCtrl,
|
||||
Keys.LeftAlt => ImGuiKey.LeftAlt,
|
||||
Keys.LeftSuper => ImGuiKey.LeftSuper,
|
||||
Keys.RightShift => ImGuiKey.RightShift,
|
||||
Keys.RightControl => ImGuiKey.RightCtrl,
|
||||
Keys.RightAlt => ImGuiKey.RightAlt,
|
||||
Keys.RightSuper => ImGuiKey.RightSuper,
|
||||
Keys.Menu => ImGuiKey.Menu,
|
||||
_ => ImGuiKey.None
|
||||
};
|
||||
}
|
||||
}
|
||||
30
FModel/Framework/JsonNetSerializer.cs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using RestSharp;
|
||||
using RestSharp.Serializers;
|
||||
|
||||
namespace FModel.Framework;
|
||||
|
||||
public class JsonNetSerializer : IRestSerializer, ISerializer, IDeserializer
|
||||
{
|
||||
public static readonly JsonSerializerSettings SerializerSettings = new()
|
||||
{
|
||||
NullValueHandling = NullValueHandling.Ignore,
|
||||
MissingMemberHandling = MissingMemberHandling.Ignore,
|
||||
ContractResolver = new CamelCasePropertyNamesContractResolver()
|
||||
};
|
||||
|
||||
public string Serialize(Parameter parameter) => JsonConvert.SerializeObject(parameter.Value);
|
||||
public string Serialize(object obj) => JsonConvert.SerializeObject(obj);
|
||||
public T Deserialize<T>(RestResponse response) => JsonConvert.DeserializeObject<T>(response.Content!, SerializerSettings);
|
||||
|
||||
public ISerializer Serializer => this;
|
||||
public IDeserializer Deserializer => this;
|
||||
|
||||
public ContentType ContentType { get; set; } = ContentType.Json;
|
||||
public string[] AcceptedContentTypes => ContentType.JsonAccept;
|
||||
public SupportsContentType SupportsContentType => contentType => contentType.Value.EndsWith("json", StringComparison.InvariantCultureIgnoreCase);
|
||||
|
||||
public DataFormat DataFormat => DataFormat.Json;
|
||||
}
|
||||
46
FModel/Framework/NavigationList.cs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace FModel.Framework;
|
||||
|
||||
public class NavigationList<T> : List<T>
|
||||
{
|
||||
private int _currentIndex;
|
||||
public int CurrentIndex
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_currentIndex > Count - 1)
|
||||
{
|
||||
_currentIndex = Count - 1;
|
||||
}
|
||||
|
||||
if (_currentIndex < 0)
|
||||
{
|
||||
_currentIndex = 0;
|
||||
}
|
||||
|
||||
return _currentIndex;
|
||||
}
|
||||
set => _currentIndex = value;
|
||||
}
|
||||
|
||||
public T MoveNext
|
||||
{
|
||||
get
|
||||
{
|
||||
_currentIndex++;
|
||||
return this[CurrentIndex];
|
||||
}
|
||||
}
|
||||
|
||||
public T MovePrevious
|
||||
{
|
||||
get
|
||||
{
|
||||
_currentIndex--;
|
||||
return this[CurrentIndex];
|
||||
}
|
||||
}
|
||||
|
||||
public T Current => this[CurrentIndex];
|
||||
}
|
||||
41
FModel/Framework/RangeObservableCollection.cs
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
|
||||
namespace FModel.Framework;
|
||||
|
||||
public sealed class RangeObservableCollection<T> : ObservableCollection<T>
|
||||
{
|
||||
private bool _suppressNotification;
|
||||
|
||||
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (!_suppressNotification)
|
||||
base.OnCollectionChanged(e);
|
||||
}
|
||||
|
||||
public void AddRange(IEnumerable<T> list)
|
||||
{
|
||||
if (list == null)
|
||||
throw new ArgumentNullException(nameof(list));
|
||||
|
||||
_suppressNotification = true;
|
||||
|
||||
foreach (var item in list)
|
||||
Add(item);
|
||||
|
||||
_suppressNotification = false;
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
}
|
||||
|
||||
public void SetSuppressionState(bool state)
|
||||
{
|
||||
_suppressNotification = state;
|
||||
}
|
||||
|
||||
public void InvokeOnCollectionChanged(NotifyCollectionChangedAction changedAction = NotifyCollectionChangedAction.Reset)
|
||||
{
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(changedAction));
|
||||
}
|
||||
}
|
||||
75
FModel/Framework/ViewModel.cs
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace FModel.Framework;
|
||||
|
||||
public class ViewModel : INotifyPropertyChanged, INotifyDataErrorInfo, IDataErrorInfo
|
||||
{
|
||||
private readonly Dictionary<string, IList<string>> _validationErrors = new();
|
||||
|
||||
public string this[string propertyName]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(propertyName))
|
||||
return Error;
|
||||
|
||||
return _validationErrors.ContainsKey(propertyName) ? string.Join(Environment.NewLine, _validationErrors[propertyName]) : string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore] public string Error => string.Join(Environment.NewLine, GetAllErrors());
|
||||
[JsonIgnore] public bool HasErrors => _validationErrors.Any();
|
||||
|
||||
public IEnumerable GetErrors(string propertyName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(propertyName))
|
||||
return _validationErrors.SelectMany(kvp => kvp.Value);
|
||||
|
||||
return _validationErrors.TryGetValue(propertyName, out var errors) ? errors : Enumerable.Empty<object>();
|
||||
}
|
||||
|
||||
private IEnumerable<string> GetAllErrors()
|
||||
{
|
||||
return _validationErrors.SelectMany(kvp => kvp.Value).Where(e => !string.IsNullOrEmpty(e));
|
||||
}
|
||||
|
||||
public void AddValidationError(string propertyName, string errorMessage)
|
||||
{
|
||||
if (!_validationErrors.ContainsKey(propertyName))
|
||||
_validationErrors.Add(propertyName, new List<string>());
|
||||
|
||||
_validationErrors[propertyName].Add(errorMessage);
|
||||
}
|
||||
|
||||
public void ClearValidationErrors(string propertyName)
|
||||
{
|
||||
if (_validationErrors.ContainsKey(propertyName))
|
||||
_validationErrors.Remove(propertyName);
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
#pragma warning disable 67
|
||||
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
|
||||
#pragma warning disable 67
|
||||
|
||||
protected void RaisePropertyChanged(string propertyName)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
|
||||
{
|
||||
if (EqualityComparer<T>.Default.Equals(storage, value))
|
||||
return false;
|
||||
|
||||
storage = value;
|
||||
RaisePropertyChanged(propertyName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
49
FModel/Framework/ViewModelCommand.cs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
using System;
|
||||
|
||||
namespace FModel.Framework;
|
||||
|
||||
public abstract class ViewModelCommand<TContextViewModel> : Command where TContextViewModel : ViewModel
|
||||
{
|
||||
private WeakReference _parent;
|
||||
|
||||
public TContextViewModel ContextViewModel
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_parent is { IsAlive: true })
|
||||
return (TContextViewModel) _parent.Target;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private set
|
||||
{
|
||||
if (ContextViewModel == value)
|
||||
return;
|
||||
|
||||
_parent = value != null ? new WeakReference(value) : null;
|
||||
}
|
||||
}
|
||||
|
||||
protected ViewModelCommand(TContextViewModel contextViewModel)
|
||||
{
|
||||
ContextViewModel = contextViewModel /*?? throw new ArgumentNullException(nameof(contextViewModel))*/;
|
||||
}
|
||||
|
||||
public sealed override void Execute(object parameter)
|
||||
{
|
||||
Execute(ContextViewModel, parameter);
|
||||
}
|
||||
|
||||
public abstract void Execute(TContextViewModel contextViewModel, object parameter);
|
||||
|
||||
public sealed override bool CanExecute(object parameter)
|
||||
{
|
||||
return CanExecute(ContextViewModel, parameter);
|
||||
}
|
||||
|
||||
public virtual bool CanExecute(TContextViewModel contextViewModel, object parameter)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
114
FModel/Helper.cs
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Windows;
|
||||
|
||||
namespace FModel;
|
||||
|
||||
public static class Helper
|
||||
{
|
||||
public static string FixKey(string key)
|
||||
{
|
||||
if (string.IsNullOrEmpty(key))
|
||||
return string.Empty;
|
||||
|
||||
var keySpan = key.AsSpan().Trim();
|
||||
if (keySpan.Length > sizeof(char) * (2 /* 0x */ + 32 /* FAES = 256 bit */)) // maybe strictly check for length?
|
||||
return string.Empty; // bullshit key
|
||||
|
||||
Span<char> resultSpan = stackalloc char[keySpan.Length + 2 /* pad for 0x */];
|
||||
keySpan.ToUpperInvariant(resultSpan[2..]);
|
||||
|
||||
if (resultSpan[2..].StartsWith("0X"))
|
||||
resultSpan = resultSpan[2..];
|
||||
else
|
||||
resultSpan[0] = '0';
|
||||
|
||||
resultSpan[1] = 'x';
|
||||
|
||||
return new string(resultSpan);
|
||||
}
|
||||
|
||||
public static void OpenWindow<T>(string windowName, Action action) where T : Window
|
||||
{
|
||||
if (!IsWindowOpen<T>(windowName))
|
||||
{
|
||||
action();
|
||||
}
|
||||
else
|
||||
{
|
||||
var w = GetOpenedWindow<T>(windowName);
|
||||
if (windowName == "Search View") w.WindowState = WindowState.Normal;
|
||||
w.Focus();
|
||||
}
|
||||
}
|
||||
|
||||
public static T GetWindow<T>(string windowName, Action action) where T : Window
|
||||
{
|
||||
if (!IsWindowOpen<T>(windowName))
|
||||
{
|
||||
action();
|
||||
}
|
||||
|
||||
var ret = (T) GetOpenedWindow<T>(windowName);
|
||||
ret.Focus();
|
||||
ret.Activate();
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void CloseWindow<T>(string windowName) where T : Window
|
||||
{
|
||||
if (!IsWindowOpen<T>(windowName)) return;
|
||||
GetOpenedWindow<T>(windowName).Close();
|
||||
}
|
||||
|
||||
private static bool IsWindowOpen<T>(string name = "") where T : Window
|
||||
{
|
||||
return string.IsNullOrEmpty(name)
|
||||
? Application.Current.Windows.OfType<T>().Any()
|
||||
: Application.Current.Windows.OfType<T>().Any(w => w.Title.Equals(name));
|
||||
}
|
||||
|
||||
private static Window GetOpenedWindow<T>(string name) where T : Window
|
||||
{
|
||||
return Application.Current.Windows.OfType<T>().FirstOrDefault(w => w.Title.Equals(name));
|
||||
}
|
||||
|
||||
public static bool IsNaN(double value)
|
||||
{
|
||||
var ulongValue = Unsafe.As<double, ulong>(ref value);
|
||||
var exp = ulongValue & 0xfff0000000000000;
|
||||
var man = ulongValue & 0x000fffffffffffff;
|
||||
return exp is 0x7ff0000000000000 or 0xfff0000000000000 && man != 0;
|
||||
}
|
||||
|
||||
public static bool AreVirtuallyEqual(double d1, double d2)
|
||||
{
|
||||
if (double.IsPositiveInfinity(d1))
|
||||
return double.IsPositiveInfinity(d2);
|
||||
|
||||
if (double.IsNegativeInfinity(d1))
|
||||
return double.IsNegativeInfinity(d2);
|
||||
|
||||
if (IsNaN(d1))
|
||||
return IsNaN(d2);
|
||||
|
||||
var n = d1 - d2;
|
||||
var d = (Math.Abs(d1) + Math.Abs(d2) + 10) * 1.0e-15;
|
||||
return -d < n && d > n;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static float DegreesToRadians(float degrees)
|
||||
{
|
||||
const float ratio = MathF.PI / 180f;
|
||||
return ratio * degrees;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static float RadiansToDegrees(float radians)
|
||||
{
|
||||
const float ratio = 180f / MathF.PI;
|
||||
return radians * ratio;
|
||||
}
|
||||
}
|
||||
815
FModel/MainWindow.xaml
Normal file
|
|
@ -0,0 +1,815 @@
|
|||
<adonisControls:AdonisWindow x:Class="FModel.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:FModel"
|
||||
xmlns:controls="clr-namespace:FModel.Views.Resources.Controls"
|
||||
xmlns:converters="clr-namespace:FModel.Views.Resources.Converters"
|
||||
xmlns:settings="clr-namespace:FModel.Settings"
|
||||
xmlns:services="clr-namespace:FModel.Services"
|
||||
xmlns:adonisUi="clr-namespace:AdonisUI;assembly=AdonisUI"
|
||||
xmlns:adonisControls="clr-namespace:AdonisUI.Controls;assembly=AdonisUI"
|
||||
xmlns:adonisExtensions="clr-namespace:AdonisUI.Extensions;assembly=AdonisUI"
|
||||
WindowStartupLocation="CenterScreen" Closing="OnClosing" Loaded="OnLoaded" PreviewKeyDown="OnWindowKeyDown"
|
||||
Height="{Binding Source={x:Static SystemParameters.MaximizedPrimaryScreenHeight}, Converter={converters:RatioConverter}, ConverterParameter='0.85'}"
|
||||
Width="{Binding Source={x:Static SystemParameters.MaximizedPrimaryScreenWidth}, Converter={converters:RatioConverter}, ConverterParameter='0.75'}">
|
||||
<adonisControls:AdonisWindow.Style>
|
||||
<Style TargetType="adonisControls:AdonisWindow" BasedOn="{StaticResource {x:Type adonisControls:AdonisWindow}}" >
|
||||
<Setter Property="Title" Value="{Binding DataContext.InitialWindowTitle, RelativeSource={RelativeSource Self}}" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding DataContext.TitleExtra, RelativeSource={RelativeSource Self}, Converter={x:Static converters:IsNullToBoolReversedConverter.Instance}}" Value="True">
|
||||
<Setter Property="Title">
|
||||
<Setter.Value>
|
||||
<MultiBinding StringFormat="{}{0} - {1} {2}">
|
||||
<Binding Path="DataContext.InitialWindowTitle" RelativeSource="{RelativeSource Self}" />
|
||||
<Binding Path="DataContext.GameDisplayName" RelativeSource="{RelativeSource Self}" />
|
||||
<Binding Path="DataContext.TitleExtra" RelativeSource="{RelativeSource Self}" />
|
||||
</MultiBinding>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</adonisControls:AdonisWindow.Style>
|
||||
<adonisControls:AdonisWindow.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="Views/Resources/Resources.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</adonisControls:AdonisWindow.Resources>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="{adonisUi:Space 1}" />
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Menu Grid.Row="0">
|
||||
<MenuItem Header="Directory">
|
||||
<MenuItem Header="Selector" Command="{Binding MenuCommand}" CommandParameter="Directory_Selector">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource DirectoryIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="AES" Command="{Binding MenuCommand}" CommandParameter="Directory_AES" IsEnabled="{Binding Status.IsReady}">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource KeyIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Backup" Command="{Binding MenuCommand}" CommandParameter="Directory_Backup" IsEnabled="{Binding Status.IsReady}">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource BackupIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Archives Info" Command="{Binding MenuCommand}" CommandParameter="Directory_ArchivesInfo" IsEnabled="{Binding Status.IsReady}">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource InfoIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Packages">
|
||||
<MenuItem Header="Search" IsEnabled="{Binding Status.IsReady}" InputGestureText="Ctrl+Shift+F" Click="OnSearchViewClick">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource SearchIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Favorite Directories" ItemsSource="{Binding CustomDirectories.Directories}" IsEnabled="{Binding Status.IsReady}">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource DirectoriesIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<Separator />
|
||||
<MenuItem Header="Auto Open Sounds" IsCheckable="True" StaysOpenOnClick="True"
|
||||
IsChecked="{Binding IsAutoOpenSounds, Source={x:Static settings:UserSettings.Default}}" />
|
||||
</MenuItem>
|
||||
<MenuItem Header="Views">
|
||||
<MenuItem Header="3D Viewer" Command="{Binding MenuCommand}" CommandParameter="Views_3dViewer">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.AccentForegroundBrush}}" Data="{StaticResource MeshIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Audio Player" Command="{Binding MenuCommand}" CommandParameter="Views_AudioPlayer">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.AccentForegroundBrush}}" Data="{StaticResource AudioIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Image Merger" Command="{Binding MenuCommand}" CommandParameter="Views_ImageMerger">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.AccentForegroundBrush}}" Data="{StaticResource ImageMergerIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Settings" Command="{Binding MenuCommand}" CommandParameter="Settings" />
|
||||
<MenuItem Header="Help" >
|
||||
<MenuItem Header="Donate" Command="{Binding MenuCommand}" CommandParameter="Help_Donate">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.AccentForegroundBrush}}" Data="{StaticResource GiftIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Releases" Command="{Binding MenuCommand}" CommandParameter="Help_Releases">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.AccentForegroundBrush}}" Data="{StaticResource GitHubIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Bugs Report" Command="{Binding MenuCommand}" CommandParameter="Help_BugsReport">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.AccentForegroundBrush}}" Data="{StaticResource BugIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Discord Server" Command="{Binding MenuCommand}" CommandParameter="Help_Discord">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.AccentForegroundBrush}}" Data="{StaticResource DiscordIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="About FModel" Command="{Binding MenuCommand}" CommandParameter="Help_About">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.AccentForegroundBrush}}" Data="{StaticResource InfoIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
|
||||
<Grid x:Name="RootGrid" Grid.Row="2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" MinWidth="400" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<GroupBox Grid.Column="0" adonisExtensions:LayerExtension.Layer="2"
|
||||
Padding="{adonisUi:Space 0}" Background="Transparent">
|
||||
<TabControl x:Name="LeftTabControl" SelectionChanged="OnTabItemChange">
|
||||
<TabItem Style="{StaticResource TabItemFillSpace}" Header="Archives">
|
||||
<DockPanel>
|
||||
<Grid DockPanel.Dock="Top">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="5" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="10" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Loading Mode" VerticalAlignment="Center" />
|
||||
<ComboBox Grid.Row="0" Grid.Column="2" ItemsSource="{Binding LoadingModes.Modes}" IsEnabled="{Binding Status.IsReady}"
|
||||
SelectedItem="{Binding LoadingMode, Source={x:Static settings:UserSettings.Default}, Mode=TwoWay}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Converter={x:Static converters:EnumToStringConverter.Instance}}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
<Button Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3" Content="Load"
|
||||
Command="{Binding LoadingModes.LoadCommand}" IsEnabled="{Binding Status.IsReady}"
|
||||
CommandParameter="{Binding SelectedItems, ElementName=DirectoryFilesListBox}" />
|
||||
</Grid>
|
||||
<Grid DockPanel.Dock="Top">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Separator Grid.Row="0" Style="{StaticResource CustomSeparator}" Tag="GAME ARCHIVES" />
|
||||
<ListBox Grid.Row="1" x:Name="DirectoryFilesListBox" Style="{StaticResource DirectoryFilesListBox}" MouseDoubleClick="OnMouseDoubleClick" />
|
||||
<Separator Grid.Row="2" Style="{StaticResource CustomSeparator}" Tag="INFORMATION" />
|
||||
<StackPanel Grid.Row="3" Orientation="Vertical" Margin="0 0 0 5">
|
||||
<Grid HorizontalAlignment="Stretch">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding SelectedItem.MountPoint, ElementName=DirectoryFilesListBox, FallbackValue='/', Converter={x:Static converters:TrimRightToLeftConverter.Instance}, ConverterParameter=275}" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" Text="Mount Point" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="{Binding SelectedItem.FileCount, ElementName=DirectoryFilesListBox, FallbackValue='0', StringFormat={}{0} Files}" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" Text="File Count" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="{Binding SelectedItem.IsEncrypted, ElementName=DirectoryFilesListBox, FallbackValue='False'}" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Grid.Row="2" Grid.Column="1" Text="Is Encrypted" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="{Binding SelectedItem.Guid, ElementName=DirectoryFilesListBox, FallbackValue='00000000000000000000000000000000'}" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Grid.Row="3" Grid.Column="1" Text="Global Unique Identifier" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</TabItem>
|
||||
<TabItem Style="{StaticResource TabItemFillSpace}" Header="Folders">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="5" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<StackPanel Grid.Column="0" Orientation="Horizontal">
|
||||
<Image Source="/FModel;component/Resources/label.png"
|
||||
Width="16" Height="16" HorizontalAlignment="Center" Margin="0 0 3.5 0" />
|
||||
<TextBlock HorizontalAlignment="Left" VerticalAlignment="Center" TextTrimming="CharacterEllipsis">
|
||||
<TextBlock.Text>
|
||||
<MultiBinding StringFormat="{}'{0}' has {1} folders and {2} packages">
|
||||
<Binding Path="SelectedItem.Header" ElementName="AssetsFolderName" FallbackValue="None" />
|
||||
<Binding Path="SelectedItem.FoldersView.Count" ElementName="AssetsFolderName" FallbackValue="0" />
|
||||
<Binding Path="SelectedItem.AssetsList.Assets.Count" ElementName="AssetsFolderName" FallbackValue="0" />
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Button Style="{DynamicResource {x:Static adonisUi:Styles.ToolbarButton}}" ToolTip="Bring Selected Folder To View" Padding="4"
|
||||
Command="{Binding MenuCommand}" CommandParameter="{Binding SelectedItem, ElementName=AssetsFolderName}">
|
||||
<Viewbox Width="16" Height="16" HorizontalAlignment="Center">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource LocateMeIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</Button>
|
||||
<!-- <Button Style="{DynamicResource {x:Static adonisUi:Styles.ToolbarButton}}" ToolTip="Expand All (not appropriate for huge amount of folders)" Padding="4" -->
|
||||
<!-- Command="{Binding MenuCommand}" CommandParameter="ToolBox_Expand_All"> -->
|
||||
<!-- <Viewbox Width="16" Height="16" HorizontalAlignment="Center"> -->
|
||||
<!-- <Canvas Width="24" Height="24"> -->
|
||||
<!-- <Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource UnfoldIcon}" /> -->
|
||||
<!-- </Canvas> -->
|
||||
<!-- </Viewbox> -->
|
||||
<!-- </Button> -->
|
||||
<Button Style="{DynamicResource {x:Static adonisUi:Styles.ToolbarButton}}" ToolTip="Collapse All" Padding="4"
|
||||
Command="{Binding MenuCommand}" CommandParameter="ToolBox_Collapse_All">
|
||||
<Viewbox Width="16" Height="16" HorizontalAlignment="Center">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource FoldIcon}"/>
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Separator Grid.Row="1" Style="{StaticResource CustomSeparator}" Margin="0" />
|
||||
<TreeView Grid.Row="2" x:Name="AssetsFolderName" Style="{StaticResource AssetsFolderTreeView}" PreviewMouseDoubleClick="OnAssetsTreeMouseDoubleClick">
|
||||
<TreeView.ContextMenu>
|
||||
<ContextMenu>
|
||||
<!-- <MenuItem Header="Extract Folder's Packages" Click="OnFolderExtractClick"> -->
|
||||
<!-- <MenuItem.Icon> -->
|
||||
<!-- <Viewbox Width="16" Height="16"> -->
|
||||
<!-- <Canvas Width="24" Height="24"> -->
|
||||
<!-- <Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource ExtractIcon}" /> -->
|
||||
<!-- </Canvas> -->
|
||||
<!-- </Viewbox> -->
|
||||
<!-- </MenuItem.Icon> -->
|
||||
<!-- </MenuItem> -->
|
||||
<!-- <Separator /> -->
|
||||
<MenuItem Header="Export Folder's Packages Raw Data (.uasset)" Click="OnFolderExportClick">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource ExportIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Save Folder's Packages Properties (.json)" Click="OnFolderSaveClick">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource SaveIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Save Folder's Packages Textures" Click="OnFolderTextureClick">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource TextureIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Save Folder's Packages Models" Click="OnFolderModelClick">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource ModelIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Save Folder's Packages Animations" Click="OnFolderAnimationClick">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource AnimationIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<Separator />
|
||||
<MenuItem Header="Favorite Directory" Click="OnFavoriteDirectoryClick">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource DirectoriesAddIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Copy Directory Path" Click="OnCopyDirectoryPathClick">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource CopyIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</ContextMenu>
|
||||
</TreeView.ContextMenu>
|
||||
</TreeView>
|
||||
<Separator Grid.Row="3" Style="{StaticResource CustomSeparator}" Tag="INFORMATION" />
|
||||
<StackPanel Grid.Row="4" Orientation="Vertical" Margin="0 0 0 5">
|
||||
<Grid HorizontalAlignment="Stretch">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding SelectedItem.AssetsList.Assets.Count, ElementName=AssetsFolderName, FallbackValue=0}" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" Text="Packages Count" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="{Binding SelectedItem.FoldersView.Count, ElementName=AssetsFolderName, FallbackValue=0}" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" Text="Folders Count" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="{Binding SelectedItem.Archive, ElementName=AssetsFolderName, FallbackValue='None'}" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Grid.Row="2" Grid.Column="1" Text="Included In Archive" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="{Binding SelectedItem.MountPoint, ElementName=AssetsFolderName, FallbackValue='/', Converter={x:Static converters:TrimRightToLeftConverter.Instance}, ConverterParameter=275}" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Grid.Row="3" Grid.Column="1" Text="Archive Mount Point" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Row="4" Grid.Column="0" Text="{Binding SelectedItem.Version, ElementName=AssetsFolderName, FallbackValue='VER_UE4_LATEST', Converter={x:Static converters:TrimRightToLeftConverter.Instance}, ConverterParameter=275}" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Grid.Row="4" Grid.Column="1" Text="Archive Version" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
<TabItem Style="{StaticResource TabItemFillSpace}"
|
||||
Header="{Binding SelectedItem.AssetsList.Assets.Count, FallbackValue=0, ElementName=AssetsFolderName}"
|
||||
HeaderStringFormat="{}{0} Packages">
|
||||
<DockPanel>
|
||||
<Grid DockPanel.Dock="Top" ZIndex="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Grid Grid.Column="0" ZIndex="1" HorizontalAlignment="Left" Margin="5 2 0 0">
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource SearchIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</Grid>
|
||||
<TextBox Grid.Column="0" Grid.ColumnSpan="2" x:Name="AssetsSearchName" AcceptsTab="False" AcceptsReturn="False"
|
||||
Padding="25 0 0 0" HorizontalAlignment="Stretch" TextChanged="OnFilterTextChanged"
|
||||
adonisExtensions:WatermarkExtension.Watermark="Search by name..." />
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal">
|
||||
<Button ToolTip="Clear Search Filter" Padding="5" Style="{DynamicResource {x:Static adonisUi:Styles.ToolbarButton}}" Click="OnDeleteSearchClick">
|
||||
<Viewbox Width="16" Height="16" HorizontalAlignment="Center">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource BackspaceIcon}"/>
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Grid DockPanel.Dock="Top">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<controls:Breadcrumb Grid.Row="0" MaxWidth="{Binding ActualWidth, ElementName=AssetsSearchName}" HorizontalAlignment="Left" Margin="0 5 0 5"
|
||||
DataContext="{Binding SelectedItem.PathAtThisPoint, ElementName=AssetsFolderName, FallbackValue='No/Directory/Detected/In/Folder'}"/>
|
||||
|
||||
<ListBox Grid.Row="1" x:Name="AssetsListName" Style="{StaticResource AssetsListBox}" PreviewMouseDoubleClick="OnAssetsListMouseDoubleClick" PreviewKeyDown="OnPreviewKeyDown">
|
||||
<ListBox.ContextMenu>
|
||||
<ContextMenu DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}">
|
||||
<MenuItem Header="Extract in New Tab" Command="{Binding DataContext.RightClickMenuCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="Assets_Extract_New_Tab" />
|
||||
<Binding Path="SelectedItems" />
|
||||
</MultiBinding>
|
||||
</MenuItem.CommandParameter>
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource ExtractIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<Separator />
|
||||
<MenuItem Header="Export Raw Data (.uasset)" Command="{Binding DataContext.RightClickMenuCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="Assets_Export_Data" />
|
||||
<Binding Path="SelectedItems" />
|
||||
</MultiBinding>
|
||||
</MenuItem.CommandParameter>
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource ExportIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Save Properties (.json)" Command="{Binding DataContext.RightClickMenuCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="Assets_Save_Properties" />
|
||||
<Binding Path="SelectedItems" />
|
||||
</MultiBinding>
|
||||
</MenuItem.CommandParameter>
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource SaveIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Save Texture" Command="{Binding DataContext.RightClickMenuCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="Assets_Save_Textures" />
|
||||
<Binding Path="SelectedItems" />
|
||||
</MultiBinding>
|
||||
</MenuItem.CommandParameter>
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource TextureIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Save Model" Command="{Binding DataContext.RightClickMenuCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="Assets_Save_Models" />
|
||||
<Binding Path="SelectedItems" />
|
||||
</MultiBinding>
|
||||
</MenuItem.CommandParameter>
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource ModelIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Save Animation" Command="{Binding DataContext.RightClickMenuCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="Assets_Save_Animations" />
|
||||
<Binding Path="SelectedItems" />
|
||||
</MultiBinding>
|
||||
</MenuItem.CommandParameter>
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource AnimationIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<Separator />
|
||||
<MenuItem Header="Copy">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource CopyIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
<MenuItem Header="Package Path" Command="{Binding DataContext.CopyCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="File_Path" />
|
||||
<Binding Path="SelectedItems" />
|
||||
</MultiBinding>
|
||||
</MenuItem.CommandParameter>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Package Name" Command="{Binding DataContext.CopyCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="File_Name" />
|
||||
<Binding Path="SelectedItems" />
|
||||
</MultiBinding>
|
||||
</MenuItem.CommandParameter>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Directory Path" Command="{Binding DataContext.CopyCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="Directory_Path" />
|
||||
<Binding Path="SelectedItems" />
|
||||
</MultiBinding>
|
||||
</MenuItem.CommandParameter>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Package Path w/o Extension" Command="{Binding DataContext.CopyCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="File_Path_No_Extension" />
|
||||
<Binding Path="SelectedItems" />
|
||||
</MultiBinding>
|
||||
</MenuItem.CommandParameter>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Package Name w/o Extension" Command="{Binding DataContext.CopyCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="File_Name_No_Extension" />
|
||||
<Binding Path="SelectedItems" />
|
||||
</MultiBinding>
|
||||
</MenuItem.CommandParameter>
|
||||
</MenuItem>
|
||||
</MenuItem>
|
||||
</ContextMenu>
|
||||
</ListBox.ContextMenu>
|
||||
</ListBox>
|
||||
<Separator Grid.Row="2" Style="{StaticResource CustomSeparator}" Tag="INFORMATION" />
|
||||
<StackPanel Grid.Row="3" Orientation="Vertical" Margin="0 0 0 5">
|
||||
<Grid HorizontalAlignment="Stretch">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding SelectedItem.Offset, ElementName=AssetsListName, FallbackValue=0, StringFormat='{}0x{0:X}'}" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" Text="Offset" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="{Binding SelectedItem.Size, ElementName=AssetsListName, FallbackValue=0, Converter={x:Static converters:SizeToStringConverter.Instance}}" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" Text="Size" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="{Binding SelectedItem.Compression, ElementName=AssetsListName, FallbackValue='Unknown'}" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Grid.Row="2" Grid.Column="1" Text="Compression Method" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="{Binding SelectedItem.IsEncrypted, ElementName=AssetsListName, FallbackValue='False'}" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Grid.Row="3" Grid.Column="1" Text="Is Encrypted" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Row="4" Grid.Column="0" Text="{Binding SelectedItem.Archive, ElementName=AssetsListName, FallbackValue='None'}" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Grid.Row="4" Grid.Column="1" Text="Included In Archive" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</GroupBox>
|
||||
|
||||
<GridSplitter Grid.Column="1" ResizeDirection="Columns" Width="4" VerticalAlignment="Stretch"
|
||||
ResizeBehavior="PreviousAndNext" MouseDoubleClick="OnGridSplitterDoubleClick"
|
||||
Background="{DynamicResource {x:Static adonisUi:Brushes.Layer0BackgroundBrush}}" />
|
||||
|
||||
<GroupBox Grid.Column="2" adonisExtensions:LayerExtension.Layer="2"
|
||||
Padding="{adonisUi:Space 0}" Background="Transparent">
|
||||
<Grid Margin="0 0 3 0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TabControl Grid.Row="0" x:Name="TabControlName" Style="{StaticResource GameFilesTabControl}" />
|
||||
<Expander Grid.Row="1" Margin="0 5 0 5" ExpandDirection="Down"
|
||||
IsExpanded="{Binding IsLoggerExpanded, Source={x:Static settings:UserSettings.Default}}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="2" />
|
||||
<ColumnDefinition Width="24" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<controls:CustomRichTextBox Grid.Column="0" Grid.ColumnSpan="3" x:Name="LogRtbName" Style="{StaticResource CustomRichTextBox}" />
|
||||
<StackPanel Grid.Column="2" Orientation="Vertical" VerticalAlignment="Bottom" Margin="-5 -5 5 5">
|
||||
<Button Style="{DynamicResource {x:Static adonisUi:Styles.ToolbarButton}}" ToolTip="Open Output Folder" Padding="0,4,0,4"
|
||||
Command="{Binding MenuCommand}" CommandParameter="ToolBox_Open_Output_Directory">
|
||||
<Viewbox Width="16" Height="16" HorizontalAlignment="Center">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource FolderIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</Button>
|
||||
<Button Style="{DynamicResource {x:Static adonisUi:Styles.ToolbarButton}}" ToolTip="Clear Logs" Padding="0,4,0,4"
|
||||
Command="{Binding MenuCommand}" CommandParameter="ToolBox_Clear_Logs">
|
||||
<Viewbox Width="16" Height="16" HorizontalAlignment="Center">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource TrashIcon}"/>
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Expander>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
|
||||
<StatusBar Grid.Row="3" MinHeight="28" MaxHeight="28"
|
||||
adonisExtensions:LayerExtension.Layer="3">
|
||||
<StatusBar.Style>
|
||||
<Style TargetType="{x:Type StatusBar}" BasedOn="{StaticResource {x:Type StatusBar}}">
|
||||
<Style.Triggers>
|
||||
<!--don't mind me, MultiDataTrigger just sucks-->
|
||||
<DataTrigger Binding="{Binding Status.Kind}" Value="{x:Static local:EStatusKind.Ready}">
|
||||
<Setter Property="Background" Value="{DynamicResource {x:Static adonisUi:Brushes.AccentBrush}}" />
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Status.Kind}" Value="{x:Static local:EStatusKind.Completed}">
|
||||
<Setter Property="Background" Value="{DynamicResource {x:Static adonisUi:Brushes.AccentBrush}}" />
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Status.Kind}" Value="{x:Static local:EStatusKind.Loading}">
|
||||
<Setter Property="Background" Value="{DynamicResource {x:Static adonisUi:Brushes.AlertBrush}}" />
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Status.Kind}" Value="{x:Static local:EStatusKind.Stopping}">
|
||||
<Setter Property="Background" Value="{DynamicResource {x:Static adonisUi:Brushes.AlertBrush}}" />
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Status.Kind}" Value="{x:Static local:EStatusKind.Stopped}">
|
||||
<Setter Property="Background" Value="{DynamicResource {x:Static adonisUi:Brushes.ErrorBrush}}" />
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Status.Kind}" Value="{x:Static local:EStatusKind.Failed}">
|
||||
<Setter Property="Background" Value="{DynamicResource {x:Static adonisUi:Brushes.ErrorBrush}}" />
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding StatusChangeAttempted, Source={x:Static services:ApplicationService.ThreadWorkerView}}" Value="True">
|
||||
<DataTrigger.EnterActions>
|
||||
<BeginStoryboard>
|
||||
<Storyboard Duration="0:0:0.8">
|
||||
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(StatusBar.Background).(SolidColorBrush.Color)" FillBehavior="Stop">
|
||||
<ColorAnimationUsingKeyFrames.KeyFrames>
|
||||
<DiscreteColorKeyFrame KeyTime="0:0:0" Value="#CE5555" />
|
||||
<DiscreteColorKeyFrame KeyTime="0:0:0.2" Value="#C22B2B" />
|
||||
<DiscreteColorKeyFrame KeyTime="0:0:0.4" Value="#CE5555" />
|
||||
<DiscreteColorKeyFrame KeyTime="0:0:0.6" Value="#C22B2B" />
|
||||
<DiscreteColorKeyFrame KeyTime="0:0:0.8" Value="#CE5555" />
|
||||
</ColorAnimationUsingKeyFrames.KeyFrames>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</DataTrigger.EnterActions>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding OperationCancelled, Source={x:Static services:ApplicationService.ThreadWorkerView}}" Value="True">
|
||||
<DataTrigger.EnterActions>
|
||||
<BeginStoryboard>
|
||||
<Storyboard Duration="0:0:1">
|
||||
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(StatusBar.Background).(SolidColorBrush.Color)" FillBehavior="Stop">
|
||||
<ColorAnimationUsingKeyFrames.KeyFrames>
|
||||
<DiscreteColorKeyFrame KeyTime="0:0:0" Value="#C22B2B" />
|
||||
<DiscreteColorKeyFrame KeyTime="0:0:1" Value="#CE5555" />
|
||||
</ColorAnimationUsingKeyFrames.KeyFrames>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</DataTrigger.EnterActions>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</StatusBar.Style>
|
||||
|
||||
<StatusBarItem Margin="5,0,0,0" >
|
||||
<TextBlock>
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="{x:Type TextBlock}">
|
||||
<Setter Property="Text" Value="{Binding Status.Label}" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Status.Kind}" Value="{x:Static local:EStatusKind.Loading}">
|
||||
<Setter Property="Text" Value="{Binding Status.Label, StringFormat='{}{0} …'}" />
|
||||
</DataTrigger>
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding CanBeCanceled, Source={x:Static services:ApplicationService.ThreadWorkerView}}" Value="True" />
|
||||
<Condition Binding="{Binding Status.Kind}" Value="{x:Static local:EStatusKind.Loading}" />
|
||||
</MultiDataTrigger.Conditions>
|
||||
<Setter Property="Text" Value="{Binding Status.Label, StringFormat='{}{0} … ESC to Cancel'}" />
|
||||
</MultiDataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</StatusBarItem>
|
||||
|
||||
<StatusBarItem Margin="0 0 5 0" HorizontalAlignment="Right">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<StatusBarItem Margin="0 0 10 0" HorizontalContentAlignment="Stretch">
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.AccentForegroundBrush}}" Data="{StaticResource StatusBarIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</StatusBarItem>
|
||||
|
||||
<StatusBarItem Width="30" HorizontalContentAlignment="Stretch" ToolTip="Auto Open Sounds Enabled">
|
||||
<StatusBarItem.Style>
|
||||
<Style TargetType="StatusBarItem">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsAutoOpenSounds, Source={x:Static settings:UserSettings.Default}}" Value="False">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</StatusBarItem.Style>
|
||||
<TextBlock HorizontalAlignment="Center" FontWeight="SemiBold" Text="SND" />
|
||||
</StatusBarItem>
|
||||
|
||||
<StatusBarItem Margin="10 0 0 0">
|
||||
<TextBlock Text="{Binding LastUpdateCheck, Source={x:Static local:Settings.UserSettings.Default}, Converter={x:Static converters:RelativeDateTimeConverter.Instance}, StringFormat=Last Refresh: {0}}" />
|
||||
</StatusBarItem>
|
||||
</StackPanel>
|
||||
</StatusBarItem>
|
||||
</StatusBar>
|
||||
</Grid>
|
||||
</adonisControls:AdonisWindow>
|
||||
282
FModel/MainWindow.xaml.cs
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using AdonisUI.Controls;
|
||||
using FModel.Extensions;
|
||||
using FModel.Services;
|
||||
using FModel.Settings;
|
||||
using FModel.ViewModels;
|
||||
using FModel.Views;
|
||||
using FModel.Views.Resources.Controls;
|
||||
using ICSharpCode.AvalonEdit.Editing;
|
||||
|
||||
namespace FModel;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
public partial class MainWindow
|
||||
{
|
||||
public static MainWindow YesWeCats;
|
||||
private ThreadWorkerViewModel _threadWorkerView => ApplicationService.ThreadWorkerView;
|
||||
private ApplicationViewModel _applicationView => ApplicationService.ApplicationView;
|
||||
private DiscordHandler _discordHandler => DiscordService.DiscordHandler;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
CommandBindings.Add(new CommandBinding(new RoutedCommand("ReloadMappings", typeof(MainWindow), new InputGestureCollection { new KeyGesture(Key.F12) }), OnMappingsReload));
|
||||
CommandBindings.Add(new CommandBinding(ApplicationCommands.Find, (_, _) => OnOpenAvalonFinder()));
|
||||
|
||||
DataContext = _applicationView;
|
||||
InitializeComponent();
|
||||
|
||||
FLogger.Logger = LogRtbName;
|
||||
YesWeCats = this;
|
||||
}
|
||||
|
||||
private void OnClosing(object sender, CancelEventArgs e)
|
||||
{
|
||||
_discordHandler.Dispose();
|
||||
}
|
||||
|
||||
private async void OnLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var newOrUpdated = UserSettings.Default.ShowChangelog;
|
||||
#if !DEBUG
|
||||
ApplicationService.ApiEndpointView.FModelApi.CheckForUpdates(true);
|
||||
#endif
|
||||
|
||||
switch (UserSettings.Default.AesReload)
|
||||
{
|
||||
case EAesReload.Always:
|
||||
await _applicationView.CUE4Parse.RefreshAes();
|
||||
break;
|
||||
case EAesReload.OncePerDay when UserSettings.Default.CurrentDir.LastAesReload != DateTime.Today:
|
||||
UserSettings.Default.CurrentDir.LastAesReload = DateTime.Today;
|
||||
await _applicationView.CUE4Parse.RefreshAes();
|
||||
break;
|
||||
}
|
||||
|
||||
await ApplicationViewModel.InitOodle();
|
||||
await ApplicationViewModel.InitZlib();
|
||||
await _applicationView.CUE4Parse.Initialize();
|
||||
await _applicationView.AesManager.InitAes();
|
||||
await _applicationView.UpdateProvider(true);
|
||||
#if !DEBUG
|
||||
await _applicationView.CUE4Parse.InitInformation();
|
||||
#endif
|
||||
await Task.WhenAll(
|
||||
_applicationView.CUE4Parse.VerifyConsoleVariables(),
|
||||
_applicationView.CUE4Parse.VerifyOnDemandArchives(),
|
||||
_applicationView.CUE4Parse.InitMappings(),
|
||||
ApplicationViewModel.InitVgmStream(),
|
||||
ApplicationViewModel.InitImGuiSettings(newOrUpdated),
|
||||
Task.Run(() =>
|
||||
{
|
||||
if (UserSettings.Default.DiscordRpc == EDiscordRpc.Always)
|
||||
_discordHandler.Initialize(_applicationView.GameDisplayName);
|
||||
})
|
||||
).ConfigureAwait(false);
|
||||
|
||||
#if DEBUG
|
||||
// await _threadWorkerView.Begin(cancellationToken =>
|
||||
// _applicationView.CUE4Parse.Extract(cancellationToken,
|
||||
// "FortniteGame/Content/Athena/Apollo/Maps/UI/Apollo_Terrain_Minimap.uasset"));
|
||||
// await _threadWorkerView.Begin(cancellationToken =>
|
||||
// _applicationView.CUE4Parse.Extract(cancellationToken,
|
||||
// "FortniteGame/Content/Environments/Helios/Props/GlacierHotel/GlacierHotel_Globe_A/Meshes/SM_GlacierHotel_Globe_A.uasset"));
|
||||
#endif
|
||||
}
|
||||
|
||||
private void OnGridSplitterDoubleClick(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
RootGrid.ColumnDefinitions[0].Width = GridLength.Auto;
|
||||
}
|
||||
|
||||
private void OnWindowKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.OriginalSource is TextBox || e.OriginalSource is TextArea && Keyboard.Modifiers.HasFlag(ModifierKeys.Control))
|
||||
return;
|
||||
|
||||
if (_threadWorkerView.CanBeCanceled && e.Key == Key.Escape)
|
||||
{
|
||||
_applicationView.Status.SetStatus(EStatusKind.Stopping);
|
||||
_threadWorkerView.Cancel();
|
||||
}
|
||||
else if (_applicationView.Status.IsReady && e.Key == Key.F && Keyboard.Modifiers.HasFlag(ModifierKeys.Control) && Keyboard.Modifiers.HasFlag(ModifierKeys.Shift))
|
||||
OnSearchViewClick(null, null);
|
||||
else if (e.Key == Key.Left && _applicationView.CUE4Parse.TabControl.SelectedTab.HasImage)
|
||||
_applicationView.CUE4Parse.TabControl.SelectedTab.GoPreviousImage();
|
||||
else if (e.Key == Key.Right && _applicationView.CUE4Parse.TabControl.SelectedTab.HasImage)
|
||||
_applicationView.CUE4Parse.TabControl.SelectedTab.GoNextImage();
|
||||
else if (UserSettings.Default.AssetAddTab.IsTriggered(e.Key))
|
||||
_applicationView.CUE4Parse.TabControl.AddTab();
|
||||
else if (UserSettings.Default.AssetRemoveTab.IsTriggered(e.Key))
|
||||
_applicationView.CUE4Parse.TabControl.RemoveTab();
|
||||
else if (UserSettings.Default.AssetLeftTab.IsTriggered(e.Key))
|
||||
_applicationView.CUE4Parse.TabControl.GoLeftTab();
|
||||
else if (UserSettings.Default.AssetRightTab.IsTriggered(e.Key))
|
||||
_applicationView.CUE4Parse.TabControl.GoRightTab();
|
||||
else if (UserSettings.Default.DirLeftTab.IsTriggered(e.Key) && LeftTabControl.SelectedIndex > 0)
|
||||
LeftTabControl.SelectedIndex--;
|
||||
else if (UserSettings.Default.DirRightTab.IsTriggered(e.Key) && LeftTabControl.SelectedIndex < LeftTabControl.Items.Count - 1)
|
||||
LeftTabControl.SelectedIndex++;
|
||||
}
|
||||
|
||||
private void OnSearchViewClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Helper.OpenWindow<AdonisWindow>("Search View", () => new SearchView().Show());
|
||||
}
|
||||
|
||||
private void OnTabItemChange(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (e.OriginalSource is not TabControl tabControl)
|
||||
return;
|
||||
|
||||
(tabControl.SelectedItem as System.Windows.Controls.TabItem)?.Focus();
|
||||
}
|
||||
|
||||
private async void OnMappingsReload(object sender, ExecutedRoutedEventArgs e)
|
||||
{
|
||||
await _applicationView.CUE4Parse.InitMappings(true);
|
||||
}
|
||||
|
||||
private void OnOpenAvalonFinder()
|
||||
{
|
||||
_applicationView.CUE4Parse.TabControl.SelectedTab.HasSearchOpen = true;
|
||||
AvalonEditor.YesWeSearch.Focus();
|
||||
AvalonEditor.YesWeSearch.SelectAll();
|
||||
}
|
||||
|
||||
private void OnAssetsTreeMouseDoubleClick(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (sender is not TreeView { SelectedItem: TreeItem treeItem } || treeItem.Folders.Count > 0) return;
|
||||
|
||||
LeftTabControl.SelectedIndex++;
|
||||
}
|
||||
|
||||
private async void OnAssetsListMouseDoubleClick(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (sender is not ListBox listBox) return;
|
||||
|
||||
var selectedItems = listBox.SelectedItems.Cast<AssetItem>().ToList();
|
||||
await _threadWorkerView.Begin(cancellationToken => { _applicationView.CUE4Parse.ExtractSelected(cancellationToken, selectedItems); });
|
||||
}
|
||||
|
||||
private async void OnFolderExtractClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (AssetsFolderName.SelectedItem is TreeItem folder)
|
||||
{
|
||||
await _threadWorkerView.Begin(cancellationToken => { _applicationView.CUE4Parse.ExtractFolder(cancellationToken, folder); });
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnFolderExportClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (AssetsFolderName.SelectedItem is TreeItem folder)
|
||||
{
|
||||
await _threadWorkerView.Begin(cancellationToken => { _applicationView.CUE4Parse.ExportFolder(cancellationToken, folder); });
|
||||
FLogger.Append(ELog.Information, () =>
|
||||
{
|
||||
FLogger.Text("Successfully exported ", Constants.WHITE);
|
||||
FLogger.Link(folder.PathAtThisPoint, UserSettings.Default.RawDataDirectory, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnFolderSaveClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (AssetsFolderName.SelectedItem is TreeItem folder)
|
||||
{
|
||||
await _threadWorkerView.Begin(cancellationToken => { _applicationView.CUE4Parse.SaveFolder(cancellationToken, folder); });
|
||||
FLogger.Append(ELog.Information, () =>
|
||||
{
|
||||
FLogger.Text("Successfully saved ", Constants.WHITE);
|
||||
FLogger.Link(folder.PathAtThisPoint, UserSettings.Default.PropertiesDirectory, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnFolderTextureClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (AssetsFolderName.SelectedItem is TreeItem folder)
|
||||
{
|
||||
await _threadWorkerView.Begin(cancellationToken => { _applicationView.CUE4Parse.TextureFolder(cancellationToken, folder); });
|
||||
FLogger.Append(ELog.Information, () =>
|
||||
{
|
||||
FLogger.Text("Successfully saved ", Constants.WHITE);
|
||||
FLogger.Link(folder.PathAtThisPoint, UserSettings.Default.TextureDirectory, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnFolderModelClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (AssetsFolderName.SelectedItem is TreeItem folder)
|
||||
{
|
||||
await _threadWorkerView.Begin(cancellationToken => { _applicationView.CUE4Parse.ModelFolder(cancellationToken, folder); });
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnFolderAnimationClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (AssetsFolderName.SelectedItem is TreeItem folder)
|
||||
{
|
||||
await _threadWorkerView.Begin(cancellationToken => { _applicationView.CUE4Parse.AnimationFolder(cancellationToken, folder); });
|
||||
}
|
||||
}
|
||||
|
||||
private void OnFavoriteDirectoryClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (AssetsFolderName.SelectedItem is not TreeItem folder) return;
|
||||
|
||||
_applicationView.CustomDirectories.Add(new CustomDirectory(folder.Header, folder.PathAtThisPoint));
|
||||
FLogger.Append(ELog.Information, () =>
|
||||
FLogger.Text($"Successfully saved '{folder.PathAtThisPoint}' as a new favorite directory", Constants.WHITE, true));
|
||||
}
|
||||
|
||||
private void OnCopyDirectoryPathClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (AssetsFolderName.SelectedItem is not TreeItem folder) return;
|
||||
Clipboard.SetText(folder.PathAtThisPoint);
|
||||
}
|
||||
|
||||
private void OnDeleteSearchClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
AssetsSearchName.Text = string.Empty;
|
||||
AssetsListName.ScrollIntoView(AssetsListName.SelectedItem);
|
||||
}
|
||||
|
||||
private void OnFilterTextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
if (sender is not TextBox textBox || AssetsFolderName.SelectedItem is not TreeItem folder)
|
||||
return;
|
||||
|
||||
var filters = textBox.Text.Trim().Split(' ');
|
||||
folder.AssetsList.AssetsView.Filter = o => { return o is AssetItem assetItem && filters.All(x => assetItem.FullPath.SubstringAfterLast('/').Contains(x, StringComparison.OrdinalIgnoreCase)); };
|
||||
}
|
||||
|
||||
private void OnMouseDoubleClick(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (!_applicationView.Status.IsReady || sender is not ListBox listBox) return;
|
||||
UserSettings.Default.LoadingMode = ELoadingMode.Multiple;
|
||||
_applicationView.LoadingModes.LoadCommand.Execute(listBox.SelectedItems);
|
||||
}
|
||||
|
||||
private async void OnPreviewKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (!_applicationView.Status.IsReady || sender is not ListBox listBox) return;
|
||||
|
||||
switch (e.Key)
|
||||
{
|
||||
case Key.Enter:
|
||||
var selectedItems = listBox.SelectedItems.Cast<AssetItem>().ToList();
|
||||
await _threadWorkerView.Begin(cancellationToken => { _applicationView.CUE4Parse.ExtractSelected(cancellationToken, selectedItems); });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
355
FModel/Options.Designer.cs
generated
|
|
@ -1,355 +0,0 @@
|
|||
namespace FModel
|
||||
{
|
||||
partial class OptionsWindow
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(OptionsWindow));
|
||||
this.optionsOKButton = new System.Windows.Forms.Button();
|
||||
this.textBox1 = new System.Windows.Forms.TextBox();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.checkBox1 = new System.Windows.Forms.CheckBox();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.textBox3 = new System.Windows.Forms.TextBox();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||
this.imgsPerRow = new System.Windows.Forms.NumericUpDown();
|
||||
this.label5 = new System.Windows.Forms.Label();
|
||||
this.groupBox2 = new System.Windows.Forms.GroupBox();
|
||||
this.groupBox3 = new System.Windows.Forms.GroupBox();
|
||||
this.textBox2 = new System.Windows.Forms.TextBox();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.groupBox4 = new System.Windows.Forms.GroupBox();
|
||||
this.checkBox6 = new System.Windows.Forms.CheckBox();
|
||||
this.checkBox5 = new System.Windows.Forms.CheckBox();
|
||||
this.checkBox4 = new System.Windows.Forms.CheckBox();
|
||||
this.checkBox3 = new System.Windows.Forms.CheckBox();
|
||||
this.checkBox2 = new System.Windows.Forms.CheckBox();
|
||||
this.label6 = new System.Windows.Forms.Label();
|
||||
this.label7 = new System.Windows.Forms.Label();
|
||||
this.comboBox1 = new System.Windows.Forms.ComboBox();
|
||||
this.groupBox1.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.imgsPerRow)).BeginInit();
|
||||
this.groupBox2.SuspendLayout();
|
||||
this.groupBox3.SuspendLayout();
|
||||
this.groupBox4.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// optionsOKButton
|
||||
//
|
||||
this.optionsOKButton.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.optionsOKButton.Location = new System.Drawing.Point(475, 245);
|
||||
this.optionsOKButton.Name = "optionsOKButton";
|
||||
this.optionsOKButton.Size = new System.Drawing.Size(97, 21);
|
||||
this.optionsOKButton.TabIndex = 1;
|
||||
this.optionsOKButton.Text = "OK";
|
||||
this.optionsOKButton.UseVisualStyleBackColor = true;
|
||||
this.optionsOKButton.Click += new System.EventHandler(this.optionsOKButton_Click);
|
||||
//
|
||||
// textBox1
|
||||
//
|
||||
this.textBox1.Location = new System.Drawing.Point(54, 19);
|
||||
this.textBox1.Name = "textBox1";
|
||||
this.textBox1.Size = new System.Drawing.Size(500, 20);
|
||||
this.textBox1.TabIndex = 2;
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(6, 22);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(42, 13);
|
||||
this.label1.TabIndex = 3;
|
||||
this.label1.Text = "Output:";
|
||||
//
|
||||
// checkBox1
|
||||
//
|
||||
this.checkBox1.AutoSize = true;
|
||||
this.checkBox1.Checked = true;
|
||||
this.checkBox1.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.checkBox1.Location = new System.Drawing.Point(448, 45);
|
||||
this.checkBox1.Name = "checkBox1";
|
||||
this.checkBox1.Size = new System.Drawing.Size(101, 17);
|
||||
this.checkBox1.TabIndex = 4;
|
||||
this.checkBox1.Text = "Always Serialize";
|
||||
this.checkBox1.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.ForeColor = System.Drawing.Color.Red;
|
||||
this.label2.Location = new System.Drawing.Point(374, 46);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(68, 13);
|
||||
this.label2.TabIndex = 5;
|
||||
this.label2.Text = "Advisable -->";
|
||||
//
|
||||
// textBox3
|
||||
//
|
||||
this.textBox3.Location = new System.Drawing.Point(69, 19);
|
||||
this.textBox3.Name = "textBox3";
|
||||
this.textBox3.Size = new System.Drawing.Size(195, 20);
|
||||
this.textBox3.TabIndex = 8;
|
||||
//
|
||||
// label4
|
||||
//
|
||||
this.label4.AutoSize = true;
|
||||
this.label4.Location = new System.Drawing.Point(6, 22);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(57, 13);
|
||||
this.label4.TabIndex = 9;
|
||||
this.label4.Text = "File Name:";
|
||||
//
|
||||
// groupBox1
|
||||
//
|
||||
this.groupBox1.Controls.Add(this.imgsPerRow);
|
||||
this.groupBox1.Controls.Add(this.label5);
|
||||
this.groupBox1.Controls.Add(this.textBox3);
|
||||
this.groupBox1.Controls.Add(this.label4);
|
||||
this.groupBox1.Location = new System.Drawing.Point(12, 220);
|
||||
this.groupBox1.Name = "groupBox1";
|
||||
this.groupBox1.Size = new System.Drawing.Size(414, 46);
|
||||
this.groupBox1.TabIndex = 10;
|
||||
this.groupBox1.TabStop = false;
|
||||
this.groupBox1.Text = "Merger";
|
||||
//
|
||||
// imgsPerRow
|
||||
//
|
||||
this.imgsPerRow.Location = new System.Drawing.Point(364, 19);
|
||||
this.imgsPerRow.Maximum = new decimal(new int[] {
|
||||
20,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.imgsPerRow.Name = "imgsPerRow";
|
||||
this.imgsPerRow.ReadOnly = true;
|
||||
this.imgsPerRow.Size = new System.Drawing.Size(44, 20);
|
||||
this.imgsPerRow.TabIndex = 12;
|
||||
this.imgsPerRow.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
this.imgsPerRow.ThousandsSeparator = true;
|
||||
//
|
||||
// label5
|
||||
//
|
||||
this.label5.AutoSize = true;
|
||||
this.label5.Location = new System.Drawing.Point(270, 22);
|
||||
this.label5.Name = "label5";
|
||||
this.label5.Size = new System.Drawing.Size(88, 13);
|
||||
this.label5.TabIndex = 10;
|
||||
this.label5.Text = "Images Per Row:";
|
||||
//
|
||||
// groupBox2
|
||||
//
|
||||
this.groupBox2.Controls.Add(this.textBox1);
|
||||
this.groupBox2.Controls.Add(this.checkBox1);
|
||||
this.groupBox2.Controls.Add(this.label1);
|
||||
this.groupBox2.Controls.Add(this.label2);
|
||||
this.groupBox2.Location = new System.Drawing.Point(12, 67);
|
||||
this.groupBox2.Name = "groupBox2";
|
||||
this.groupBox2.Size = new System.Drawing.Size(560, 71);
|
||||
this.groupBox2.TabIndex = 11;
|
||||
this.groupBox2.TabStop = false;
|
||||
this.groupBox2.Text = "Extraction";
|
||||
//
|
||||
// groupBox3
|
||||
//
|
||||
this.groupBox3.Controls.Add(this.textBox2);
|
||||
this.groupBox3.Controls.Add(this.label3);
|
||||
this.groupBox3.Location = new System.Drawing.Point(12, 12);
|
||||
this.groupBox3.Name = "groupBox3";
|
||||
this.groupBox3.Size = new System.Drawing.Size(560, 49);
|
||||
this.groupBox3.TabIndex = 12;
|
||||
this.groupBox3.TabStop = false;
|
||||
this.groupBox3.Text = ".PAK files";
|
||||
//
|
||||
// textBox2
|
||||
//
|
||||
this.textBox2.Location = new System.Drawing.Point(46, 19);
|
||||
this.textBox2.Name = "textBox2";
|
||||
this.textBox2.Size = new System.Drawing.Size(508, 20);
|
||||
this.textBox2.TabIndex = 2;
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.Location = new System.Drawing.Point(6, 22);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(34, 13);
|
||||
this.label3.TabIndex = 3;
|
||||
this.label3.Text = "Input:";
|
||||
//
|
||||
// groupBox4
|
||||
//
|
||||
this.groupBox4.Controls.Add(this.comboBox1);
|
||||
this.groupBox4.Controls.Add(this.label7);
|
||||
this.groupBox4.Controls.Add(this.checkBox6);
|
||||
this.groupBox4.Controls.Add(this.checkBox5);
|
||||
this.groupBox4.Controls.Add(this.checkBox4);
|
||||
this.groupBox4.Controls.Add(this.checkBox3);
|
||||
this.groupBox4.Controls.Add(this.checkBox2);
|
||||
this.groupBox4.Controls.Add(this.label6);
|
||||
this.groupBox4.Location = new System.Drawing.Point(12, 144);
|
||||
this.groupBox4.Name = "groupBox4";
|
||||
this.groupBox4.Size = new System.Drawing.Size(560, 70);
|
||||
this.groupBox4.TabIndex = 13;
|
||||
this.groupBox4.TabStop = false;
|
||||
this.groupBox4.Text = "Icon Creation";
|
||||
//
|
||||
// checkBox6
|
||||
//
|
||||
this.checkBox6.AutoSize = true;
|
||||
this.checkBox6.Location = new System.Drawing.Point(476, 19);
|
||||
this.checkBox6.Name = "checkBox6";
|
||||
this.checkBox6.Size = new System.Drawing.Size(78, 17);
|
||||
this.checkBox6.TabIndex = 14;
|
||||
this.checkBox6.Text = "Challenges";
|
||||
this.checkBox6.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// checkBox5
|
||||
//
|
||||
this.checkBox5.AutoSize = true;
|
||||
this.checkBox5.Location = new System.Drawing.Point(189, 19);
|
||||
this.checkBox5.Name = "checkBox5";
|
||||
this.checkBox5.Size = new System.Drawing.Size(64, 17);
|
||||
this.checkBox5.TabIndex = 4;
|
||||
this.checkBox5.Text = "Variants";
|
||||
this.checkBox5.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// checkBox4
|
||||
//
|
||||
this.checkBox4.AutoSize = true;
|
||||
this.checkBox4.Location = new System.Drawing.Point(415, 19);
|
||||
this.checkBox4.Name = "checkBox4";
|
||||
this.checkBox4.Size = new System.Drawing.Size(53, 17);
|
||||
this.checkBox4.TabIndex = 3;
|
||||
this.checkBox4.Text = "Traps";
|
||||
this.checkBox4.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// checkBox3
|
||||
//
|
||||
this.checkBox3.AutoSize = true;
|
||||
this.checkBox3.Location = new System.Drawing.Point(261, 19);
|
||||
this.checkBox3.Name = "checkBox3";
|
||||
this.checkBox3.Size = new System.Drawing.Size(147, 17);
|
||||
this.checkBox3.TabIndex = 2;
|
||||
this.checkBox3.Text = "Consumables && Weapons";
|
||||
this.checkBox3.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// checkBox2
|
||||
//
|
||||
this.checkBox2.AutoSize = true;
|
||||
this.checkBox2.Location = new System.Drawing.Point(108, 19);
|
||||
this.checkBox2.Name = "checkBox2";
|
||||
this.checkBox2.Size = new System.Drawing.Size(74, 17);
|
||||
this.checkBox2.TabIndex = 1;
|
||||
this.checkBox2.Text = "Cosmetics";
|
||||
this.checkBox2.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// label6
|
||||
//
|
||||
this.label6.AutoSize = true;
|
||||
this.label6.Location = new System.Drawing.Point(6, 20);
|
||||
this.label6.Name = "label6";
|
||||
this.label6.Size = new System.Drawing.Size(96, 13);
|
||||
this.label6.TabIndex = 0;
|
||||
this.label6.Text = "Supported Folders:";
|
||||
//
|
||||
// label7
|
||||
//
|
||||
this.label7.AutoSize = true;
|
||||
this.label7.Location = new System.Drawing.Point(6, 45);
|
||||
this.label7.Name = "label7";
|
||||
this.label7.Size = new System.Drawing.Size(57, 13);
|
||||
this.label7.TabIndex = 15;
|
||||
this.label7.Text = "File Name:";
|
||||
//
|
||||
// comboBox1
|
||||
//
|
||||
this.comboBox1.FormattingEnabled = true;
|
||||
this.comboBox1.Items.AddRange(new object[] {
|
||||
"Selected Item Name (i.e. CID_001_Athena_Commando_F_Default)",
|
||||
"displayName (i.e. Recruit)"});
|
||||
this.comboBox1.Location = new System.Drawing.Point(69, 42);
|
||||
this.comboBox1.Name = "comboBox1";
|
||||
this.comboBox1.Size = new System.Drawing.Size(485, 21);
|
||||
this.comboBox1.TabIndex = 16;
|
||||
//
|
||||
// OptionsWindow
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(584, 277);
|
||||
this.Controls.Add(this.groupBox4);
|
||||
this.Controls.Add(this.groupBox3);
|
||||
this.Controls.Add(this.groupBox2);
|
||||
this.Controls.Add(this.groupBox1);
|
||||
this.Controls.Add(this.optionsOKButton);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "OptionsWindow";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "FModel Options";
|
||||
this.groupBox1.ResumeLayout(false);
|
||||
this.groupBox1.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.imgsPerRow)).EndInit();
|
||||
this.groupBox2.ResumeLayout(false);
|
||||
this.groupBox2.PerformLayout();
|
||||
this.groupBox3.ResumeLayout(false);
|
||||
this.groupBox3.PerformLayout();
|
||||
this.groupBox4.ResumeLayout(false);
|
||||
this.groupBox4.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
private System.Windows.Forms.Button optionsOKButton;
|
||||
private System.Windows.Forms.TextBox textBox1;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.CheckBox checkBox1;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.TextBox textBox3;
|
||||
private System.Windows.Forms.Label label4;
|
||||
private System.Windows.Forms.GroupBox groupBox1;
|
||||
private System.Windows.Forms.GroupBox groupBox2;
|
||||
private System.Windows.Forms.GroupBox groupBox3;
|
||||
private System.Windows.Forms.TextBox textBox2;
|
||||
private System.Windows.Forms.Label label3;
|
||||
private System.Windows.Forms.Label label5;
|
||||
private System.Windows.Forms.NumericUpDown imgsPerRow;
|
||||
private System.Windows.Forms.GroupBox groupBox4;
|
||||
private System.Windows.Forms.CheckBox checkBox2;
|
||||
private System.Windows.Forms.Label label6;
|
||||
private System.Windows.Forms.CheckBox checkBox3;
|
||||
private System.Windows.Forms.CheckBox checkBox4;
|
||||
private System.Windows.Forms.CheckBox checkBox5;
|
||||
private System.Windows.Forms.CheckBox checkBox6;
|
||||
private System.Windows.Forms.ComboBox comboBox1;
|
||||
private System.Windows.Forms.Label label7;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,122 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace FModel
|
||||
{
|
||||
public partial class OptionsWindow : Form
|
||||
{
|
||||
private static string PAKBefore;
|
||||
private static string OutputBefore;
|
||||
|
||||
public OptionsWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
checkBox1.Checked = Properties.Settings.Default.ExtractAndSerialize;
|
||||
textBox1.Text = Properties.Settings.Default.ExtractOutput;
|
||||
textBox2.Text = Properties.Settings.Default.FortnitePAKs;
|
||||
textBox3.Text = Properties.Settings.Default.mergerFileName;
|
||||
imgsPerRow.Value = Properties.Settings.Default.mergerImagesRow;
|
||||
checkBox2.Checked = Properties.Settings.Default.createIconForCosmetics;
|
||||
checkBox5.Checked = Properties.Settings.Default.createIconForVariants;
|
||||
checkBox3.Checked = Properties.Settings.Default.createIconForConsumablesWeapons;
|
||||
checkBox4.Checked = Properties.Settings.Default.createIconForTraps;
|
||||
checkBox6.Checked = Properties.Settings.Default.createIconForChallenges;
|
||||
comboBox1.SelectedItem = Properties.Settings.Default.IconName;
|
||||
|
||||
PAKBefore = Properties.Settings.Default.FortnitePAKs;
|
||||
OutputBefore = Properties.Settings.Default.ExtractOutput;
|
||||
}
|
||||
|
||||
private void optionsOKButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (checkBox1.Checked == true)
|
||||
{
|
||||
Properties.Settings.Default.ExtractAndSerialize = true;
|
||||
}
|
||||
if (checkBox1.Checked == false)
|
||||
{
|
||||
Properties.Settings.Default.ExtractAndSerialize = false;
|
||||
}
|
||||
if (checkBox2.Checked == true)
|
||||
{
|
||||
Properties.Settings.Default.createIconForCosmetics = true;
|
||||
}
|
||||
if (checkBox2.Checked == false)
|
||||
{
|
||||
Properties.Settings.Default.createIconForCosmetics = false;
|
||||
}
|
||||
if (checkBox5.Checked == true)
|
||||
{
|
||||
Properties.Settings.Default.createIconForVariants = true;
|
||||
}
|
||||
if (checkBox5.Checked == false)
|
||||
{
|
||||
Properties.Settings.Default.createIconForVariants = false;
|
||||
}
|
||||
if (checkBox3.Checked == true)
|
||||
{
|
||||
Properties.Settings.Default.createIconForConsumablesWeapons = true;
|
||||
}
|
||||
if (checkBox3.Checked == false)
|
||||
{
|
||||
Properties.Settings.Default.createIconForConsumablesWeapons = false;
|
||||
}
|
||||
if (checkBox4.Checked == true)
|
||||
{
|
||||
Properties.Settings.Default.createIconForTraps = true;
|
||||
}
|
||||
if (checkBox4.Checked == false)
|
||||
{
|
||||
Properties.Settings.Default.createIconForTraps = false;
|
||||
}
|
||||
if (checkBox6.Checked == true)
|
||||
{
|
||||
Properties.Settings.Default.createIconForChallenges = true;
|
||||
}
|
||||
if (checkBox6.Checked == false)
|
||||
{
|
||||
Properties.Settings.Default.createIconForChallenges = false;
|
||||
}
|
||||
if (comboBox1.SelectedItem == null)
|
||||
{
|
||||
Properties.Settings.Default.IconName = "Selected Item Name (i.e. CID_001_Athena_Commando_F_Default)";
|
||||
}
|
||||
else
|
||||
{
|
||||
Properties.Settings.Default.IconName = comboBox1.SelectedItem.ToString();
|
||||
}
|
||||
|
||||
Properties.Settings.Default.ExtractOutput = textBox1.Text;
|
||||
Properties.Settings.Default.FortnitePAKs = textBox2.Text;
|
||||
Properties.Settings.Default.mergerFileName = textBox3.Text;
|
||||
Properties.Settings.Default.mergerImagesRow = Decimal.ToInt32(imgsPerRow.Value);
|
||||
|
||||
if (!Directory.Exists(Properties.Settings.Default.ExtractOutput))
|
||||
Directory.CreateDirectory(Properties.Settings.Default.ExtractOutput);
|
||||
|
||||
string PAKAfter = Properties.Settings.Default.FortnitePAKs;
|
||||
if (PAKBefore != PAKAfter)
|
||||
{
|
||||
MessageBox.Show("Please, restart FModel to apply your new input path", "FModel Path Changed", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
|
||||
string OutputAfter = Properties.Settings.Default.ExtractOutput;
|
||||
if (OutputBefore != OutputAfter)
|
||||
{
|
||||
MessageBox.Show("Please, restart FModel to apply your new output path", "FModel Path Changed", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
|
||||
Properties.Settings.Default.Save();
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,878 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
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
|
||||
JP8wHyD/MB8g/zIiI/80JCT/NSUm/zQmJ/80Jyf/Mygo/zInJ/8xJyf/MCgo5jEpKTswKSkAMSgoADAo
|
||||
KF0xKCj+Migo/zMnJ/80Jyj/NSYn/zUlJv87Kyz/pJ2e/7WvsP+OhYb/Z1pb/zsrK/83Jib/NiUm/zYl
|
||||
Jv81Jif/NCcn/zMoKP8yKCj/MSgo/jAoKFwwKCgAMikpADEoKF0zKCj+NCgo/zQnJ/81Jib/NiYm/zYl
|
||||
Jv89LC3/yMTE////////////4N3d/009Pv82JCX/NyYm/zclJv82JSb/NSYm/zQnJ/80KCj/Migo/jEo
|
||||
KFwyKCgAMigoADEnJ10yKCj+NCgo/zUmJ/81JSb/NiUm/zcmJv8+LS3/yMPD////////////5ePj/08/
|
||||
QP82JCT/NyUm/zgmJ/83Jif/NiUm/zUmJ/8zJyj/Migo/jIoKFwyKCgAMigoADInJ10zKCj+NSgo/zYm
|
||||
J/83Jib/NyYm/zglJv8/LS3/yMPD////////////5OLi/1A+P/84JCX/OSYm/zgmJv84Jif/NyYm/zYm
|
||||
J/80Jyj/Mygo/jMoKFwzKCgAMicnADInKF0zKCj+NScn/zYmJv83JSb/NyUm/zglJv8/LC3/yMPD////
|
||||
////////5OHi/1E+Pv85JCX/OSUm/zkmJ/83JSb/NiUm/zYmJv81Jyf/Mygo/jIoKFwyKCgAMygoADMo
|
||||
KF00KCj+NSYn/zYlJv83JSb/OCUm/zsnJ/9ALC3/yMPD////////////4+Hh/1A9Pv85JCT/OiUm/zwn
|
||||
KP84Jif/NiUm/zYmJv81Jif/Mycn/jInJ1wyJycAMycnADInJ100Jyj+NSYn/zcmJv83Jib/OCUm/zom
|
||||
J/9ALC3/ycPD////////////4+Hh/1NAQP89Jyj/Oycn/zsmJ/84Jib/NyUm/zYmJv81Jif/Mycn/jMo
|
||||
KFwzKCgAMicnADInJ100KCj+NSYn/zYmJv83Jib/OCUm/zklJv9ALC3/ycPE////////////9vX1/8bA
|
||||
wP++t7f/bF1e/zcjJP84Jib/OCYn/zYlJv82Jif/NCcn/jMoKFwzKCgAMicnADInJ10zJyf+NSYm/zYl
|
||||
Jv83Jif/NyUm/zglJv8/LC3/yMPD////////////////////////////hXl6/zUiIv84JSb/NyYm/zYl
|
||||
Jv81Jif/Mycn/jInJ1wyJycAMygoADIoKF00KCj+NScn/zYlJv83Jif/NyUm/zglJv8/LC3/yMPE////
|
||||
////////////////////////iX9//zUiI/84Jib/NyYm/zYlJv81Jyf/Mygo/jInJ1wyJycAMykpADMo
|
||||
KF00KCj+NSgo/zUmJv82Jib/NyYm/zclJv8+LC3/yMPD////////////+vr6/9fT0//Qzc3/e3Bw/zUj
|
||||
JP83JSb/NiUm/zUmJv81KCj/NCgo/jIoKFwzKCgAMigoADIoKF0yKCj+NCgo/zUmJ/81JSb/NiUm/zcl
|
||||
Jv8+LS3/yMPD////////////6ejo/1tLTP8/LS7/PCor/zcmJv83Jif/NiUm/zUmJ/80KCj/Migo/jIo
|
||||
KFwyKCgAMSgoADAnJ10yKCj+Mygo/zQoKP81Jif/NiYn/zclJv8+LS3/yMPD////////////5+Xl/04+
|
||||
P/8zICH/NSMk/zcmJv83Jif/NSYn/zQnKP8zKCj/Migo/jEoKFwyKCgAMCcnADAnJ10wKCj+Migo/zMo
|
||||
KP80Jyf/NSYm/zUlJv88LC3/x8PD////////////7evr/3xxcf9nWlv/XE9P/zkpKf81Jib/NCcn/zMn
|
||||
KP8yKCj/MSgo/jAoKFwwKCgALygoAC8oKF0wKCj+MCcn/zInJ/8zJyf/NCcn/zYnKP88LC3/x8PD////
|
||||
/////////v7+//j4+P/4+Pj/1tPU/0g6O/8zJib/Mycn/zIoKP8xKCj/Lycn/i8nJ1wvJycALycoAC8o
|
||||
KF0vKCj+MCcn/zEoKP8yKCj/Mycn/zUoKP86Li7/x8TE////////////////////////////6+rq/1RK
|
||||
Sv8xJib/Micn/zEnKP8wJyj/Lycn/i8oKFwvKCgALicnAC4nJ14vKCj+Lygo/zAoKP8wKCj/MScn/zEn
|
||||
J/85Li7/x8XF////////////////////////////9fX1/2JbW/8vJSX/MSgo/y8nJ/8wKCj/Lygo/i8o
|
||||
KFwvKCgALigoAC4oKFkuJyj9Licn/y8nJ/8wKCj/MCcn/zAnJ/80Kyv/gHp6/6Cbm/+empr/npqa/56a
|
||||
mv+fmpr/m5eX/1BJSf8uJib/MCgo/y8nJ/8uJyf/Licn/S4oKFcuKCgAMCoqADErKyouKCnXLicn/y4n
|
||||
J/8wKCj/Lycn/y8nJ/8wKCj/LyYm/y4lJf8uJSX/LiUl/y4lJf8vJib/LSUl/y8nJ/8vKCj/Lygo/y4n
|
||||
J/8uKCj/Ligo1jArKykvKioA/wD/APwAPwDgAAcAgAABAIAAAQCAAAEAgAABAIAAAQCAAAEAgAABAIAA
|
||||
AQCAAAEAgAABAIAAAQCAAAEAgAABAIAAAQCAAAEAgAABAIAAAQCAAAEAgAABAIAAAQCAAAEAKAAAACAA
|
||||
AABAAAAAAQAgAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAABQSUkAMSgoADgwMAo1LCxEMyoqpjEoKPUwKCj0MikppTQsLEM5MDEKMSgoAFNO
|
||||
TgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAABMQEAAc2RjADowMBc0KipaMikpsTIoKO0xJyf/LyUl/y8lJf8wJib/Migo7TIp
|
||||
KbA0KipZOS8vFnVnZwBNQUEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAP///wA4Li8AOjIyBDYsLCw2Kyt9NSoqzzInJ/ovJSX/MSYm/0E3N/5kXFz9XlZW/T0z
|
||||
M/4xJib/MCUl/zEnJ/o0KirPNiwsfDYsLCw8NDQEOTAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAFBKSgAWDQ0AODAwDjQrK0gzKSmgMigo5jIoKP4zKCj/PDIy/mBXV/2YkpL8z83N/fHx
|
||||
8f7u7u7+ycfH/ZOOjvxeVVX9PDEx/jMoKP8yKCj+Migo5TMpKZ80KytHNi8vDh4VFQBMRkYAAAAAAAAA
|
||||
AAAAAAAAAAAAADs0NABDPj4BNCwsHjIqKmoyKSnAMigo9DIoKP8yJyf/Mycn/zUpKf5KQED7bWRk/Hty
|
||||
c/18c3T9e3Jy/Xtxcv19c3T9e3Jy/WtiY/xKQED7NSkp/jMnJ/8zKCj/Mygo/zIoKPQxKCi/MioqaTQt
|
||||
LR1FP0ABOzQ0AAAAAAA/OjoAKR8fADMrK1AwKCjWMCcn/TEnJ/8xJyf/Mycn/zMnJ/80Jyf/NCYn/zQl
|
||||
Jv8xISL/MSAh/zIhIv8yIiP/MiIj/zIiI/8yIiP/MyMk/zQlJv80Jif/Mycn/zMnJ/8zJyf/Micn/zEn
|
||||
J/8wKCj8MCgo1TIqK04qICAAQDo7ADIrKwAzLCwHMCgotTAnJ/8xJyf/MScn/zMoKP81KCn/NCcn/zUm
|
||||
Jv81JSb/Nyco/1FDRP9NPj//PCwt/zUkJf8zIiP/NSQl/zcmJ/83Jyf/NiYm/zUlJv81Jib/NSco/zQo
|
||||
KP8yJyf/Micn/zEnJ/8wJyf/MCgoszMsLAYyKysALycnAC8nJwoxKCi/Migo/zIoKP8zJyj/Mycn/zQn
|
||||
J/81Jib/NSUm/zYlJv85KCn/sqys/+Ti4v/Ev7//oZma/3xxcv9IOTr/NiQl/zcmJv83JSb/NiUm/zUl
|
||||
Jv81Jib/NCcn/zMnJ/8zKCj/Mygo/zEoKP8wKCi+LycnCS8nJwAvJycALycnCjIoKL8zKCj/Mygo/zQo
|
||||
KP8zJyf/NiYn/zYmJ/82JSb/NiUm/zkoKf+7trb/////////////////+vr6/3pub/80IiP/OCYm/zgm
|
||||
J/83JSb/NiUm/zUlJv81Jib/NCcn/zQoKP8zKCj/Mygo/zEoKL0uJycJLycnADAnJwAwJycKMigovzIo
|
||||
KP80KCj/NCco/zUmJv81JSb/NiUm/zclJv83Jib/Oikp/7u2tv/////////////////9/f3/fHFx/zQh
|
||||
Iv83JSb/NyUm/zclJv83Jif/NyYm/zUlJv81Jib/NCgo/zMoKP8yKCj/MigovS8nJwkwJycAMScnADEn
|
||||
JwoxJye/Micn/zMnJ/81Jyf/NSUm/zYlJv83Jib/NyYm/zknJ/88KSr/u7a2//////////////////z8
|
||||
/P98cHD/NiIj/zkmJv84Jib/OCUm/zknJ/84Jif/NiYm/zYmJv80Jyf/Mycn/zInJ/8yKCi9MigoCTIo
|
||||
KAAxJycAMCYmCjIoKL80KCj/NSgo/zYnJ/82Jib/NyYm/zcmJ/83JSb/OCYm/zwpKf+8trb/////////
|
||||
/////////Pz8/3xvcP83IiP/OiYm/zomJ/84JSb/OCYn/zgmJ/83Jib/NiYm/zYmJ/80KCj/NCgo/zMo
|
||||
Kb0zKCgJMygoADInJwAxJycKMicnvzMnJ/80Jyf/NiYm/zYlJv83JSb/NyUm/zglJv85JSb/PCgp/7y2
|
||||
tv/////////////////8/Pz/fG5v/zgiI/86JSb/OSUm/zklJv84Jib/NyUm/zYlJv82JSb/NSUm/zQn
|
||||
J/8zKCj/MigovTEoKAkyKCgAMygoADIoKAozKCi/NCgo/zQmJ/81JSb/NiYm/zclJv83JSb/OSYn/zsm
|
||||
J/88KCn/vLa2//////////////////z8/P97bW7/OSIj/zolJv85JSb/OyYn/zomJ/84Jib/NiUm/zcm
|
||||
Jv82Jib/NScn/zMnJ/8yJye9MSgoCTIoKAAzKCgAMigoCjMoKL80KCj/NSYn/zYlJv83Jib/NyUm/zcl
|
||||
Jv87Jyj/PSco/zwoKf+8trb/////////////////+/v7/3psbf85IiP/OyUm/zolJv88Jyj/PCgo/zgm
|
||||
Jv82JSb/NiYm/zYmJv81Jif/Mycn/zMnJ70xKCgJMicnADInJwAxJycKMycnvzQnKP81Jib/NiYm/zcm
|
||||
Jv83Jib/NyUm/zomJ/86Jib/PSgp/7y2tv/////////////////7+/v/emtr/zgiIv87JSb/OiUm/zsm
|
||||
J/85Jif/OCYm/zclJv83Jib/NiUm/zUmJ/8zJyf/MygovTEoKAkyKCgAMScnADAnJwoyJye/NSgo/zUm
|
||||
J/82Jib/NyYm/zcmJv84JSb/OSYm/zklJv89KSn/vba2//////////////////7+/v/Jw8P/raWl/6+n
|
||||
p/9xZGT/OCQl/zglJv84Jif/OCYn/zcmJv81JSb/Nicn/zQnJ/8zKCi9MSgoCTIoKAAxJycAMCcnCjIn
|
||||
J780Jyf/NSYm/zUlJv82JSb/NyUm/zclJv84JSb/OSUm/zwoKf+8trb/////////////////////////
|
||||
/////////////5mQkP83IyP/OCUm/zclJv83Jib/NyYm/zUlJv81Jif/Mycn/zInJ70wJycJMScnADEn
|
||||
JwAwJycKMicnvzMnJ/81Jif/NSUm/zcmJv84Jif/OCYm/zclJv85JSb/PSkp/7y2tv//////////////
|
||||
////////////////////////m5KS/zYjI/84JSb/OCYn/zcmJv82JSb/NiUm/zUmJ/8zJyf/MicnvTAn
|
||||
JwkxJycAMScnADAnJwozKCi/NCgo/zQnJ/81JSb/NiUm/zcmJ/83JSb/NyUm/zglJv88KCn/vLa2////
|
||||
//////////////////////////////////+hmJn/NiMk/zglJv83JSb/NyYm/zYlJv82Jib/NScn/zMo
|
||||
KP8yJye9MCcnCTEnJwAxJycAMScnCjMoKL80KCj/NSgo/zYmJ/81JSb/NyYn/zcmJ/83JSb/OCUm/zso
|
||||
Kf+8trb///////////////////////b19f/v7e7/8fHx/6CYmf83JSX/NyUm/zYlJv82JSb/NSUm/zYm
|
||||
J/81KCj/NCgo/zMoKL0xJycJMScnADEnJwAxJycKMigovzMoKP80KCj/NScn/zUlJv82JSb/NiUm/zcm
|
||||
Jv84Jib/Oigp/7u2tv/////////////////+////m5KS/1lKS/9cTU7/TT4+/zgmJv83Jif/NyYm/zYl
|
||||
Jv81JSb/NScn/zQoKP8zKCj/MigovTEnJwkxJycAMCcnAC8nJwoxJye/Micn/zMnJ/80Jyf/NSYm/zUl
|
||||
Jv82JSb/NyUm/zgmJ/87KSr/u7a2//////////////////7+/v+AdXb/Mh8g/zUjJP82JCX/NyUm/zgn
|
||||
J/83Jif/NiUm/zUmJ/80Jyf/Mycn/zInJ/8yKCi9MCgoCTEoKAAvJycALSYmCjEoKL8yKCj/Mygo/zUo
|
||||
KP80Jyf/NiYn/zYmJ/82JSb/NyYn/zopKf+7trb//////////////////f39/4B0df8zISH/NyUl/zcl
|
||||
Jv82JSb/NyYn/zYmJ/82Jif/NSco/zQoKP8zKCj/Migo/zIoKL0wKCgJMSgoAC8nJwAvJycKLycnvzEn
|
||||
J/8yKCj/Mygo/zQnJ/80Jyf/NSUm/zUlJv82JSb/OSgp/7u2tv/////////////////9/f3/i4GC/0Y2
|
||||
N/9IODn/RTY3/zkpKv81JSb/NSYm/zQnJ/8zJyf/Micn/zInJ/8xKCj/MSgovTAoKAkwKCgAMCgoADEo
|
||||
KAowKCi/MCgo/zEnJ/8xJyf/Mycn/zMnJ/80Jyf/Nicn/zYmJ/84KCn/u7a2////////////////////
|
||||
///q6en/3dvb/93a2v/T0ND/XlJS/zQkJf80Jyf/Mycn/zMoKP8yKCj/Migo/zAnJ/8vJye9MCgoCTAo
|
||||
KAAvKCgALygoCi8oKL8wKCj/MCcn/zEnJ/8yKCj/Micn/zMnJ/82KSn/Nygp/zgpKf+6trb/////////
|
||||
//////////////////////////////z8/P95cHD/MyYm/zQoKP8yJyf/Mico/zEoKP8wKCj/Lycn/y8n
|
||||
J70vJycJLycnAC8oKAAvKCgKLycovy8nJ/8vJyf/MCgo/zIoKP8yKCj/Micn/zQoKP81KCj/Nioq/7q2
|
||||
tv///////////////////////////////////////////4yFhf8xJSX/Migo/zEnJ/8xJyf/MCcn/zAn
|
||||
J/8vJyf/LygovS8oKAkvJygALicnAC0nJwouJye/MCgo/y8oKP8wKCj/MCgo/zEoKP8xJyf/Micn/zIn
|
||||
J/82Kyv/ure3////////////////////////////////////////////oZyd/zAmJv8yKCj/Migo/zAo
|
||||
KP8vJyf/MCgo/y8oKP8vKCi9LigoCS4oKAAtJycALScnCi0nJ78uKCj/Licn/y8nJ/8vJyf/MCcn/zAn
|
||||
J/8xJyf/MScn/zQqKv+sqKj/7e3t/+rq6v/q6ur/6urq/+rq6v/q6en/6urp/+3t7f+no6P/Mikp/zAn
|
||||
J/8wKCj/MCgo/y8nJ/8vKCj/Licn/y4nJ74uKCgJLigoADMtLQA1LzAFLykprS4nJ/8uJyf/Licn/y8o
|
||||
KP8wKCj/MCcn/y8nJ/8wJyf/MSgo/0Y+Pv9RSUn/UUhI/1FISf9RSEn/UEhI/1FJSf9RSUn/UElJ/0U+
|
||||
Pv8wKCj/MCgo/y8oKP8vJyf/Licn/y4nJ/8tJyf/LigoqzQvLwQyLC0AQTw9ACslJQAxKytRLygp5S4n
|
||||
J/8uJyf/Lygo/zAoKP8vKCj/Lycn/zAnJ/8wKCj/LyYm/y0lJf8uJSX/LiUl/y4lJf8tJSX/LiUl/y8m
|
||||
Jv8tJSX/LiYm/y8nJ/8vKCj/Lygo/y4nJ/8uKCj/Ligo/y4oKOQwKytPKyQkAEM/PwD/8A///8AD//4A
|
||||
AH/4AAAfwAAAA8AAAAOAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAA
|
||||
AAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABwAAAAygA
|
||||
AAAwAAAAYAAAAAEAIAAAAAAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABFP0AAAAAAADsz
|
||||
MxQ1LS1bMioqwDAoKPwwKCj8MSkpvzMsLFk4MTIUAAAAAEQ/PwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPzc3AEQ8
|
||||
PAM4Li4kNCsrcDQqKsQyKSn1Migo/zIoKP8xKCj/MCcn/zEoKPUzKirDNCsrbjcuLyNDPDwCPjY2AAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAd29vAC4j
|
||||
IwBDODgKNy0tPzQqKpMyKCjeMScn/TIoKP8yJyf/MScn/zEnJ/8xJyf/MScn/zEnJ/8xJyf/Migo/TIo
|
||||
KN00KiqRNy0tPUE3NwoqICEAioODAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEU9
|
||||
PgBUT08BOjExGTkuL144LS21Mykp8DInJ/8xJyf/MScn/zEnJ/8wJSX/Mygo/kE3N/08MzP9MCYm/zAl
|
||||
Jf8xJyf/Migo/zEnJ/8xJyf/Mykp7zcsLLM6Ly9cOjExGF1XWAFHP0AAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMPf
|
||||
3wA4Ly8AQDo6BTcuLi80KiqANCkp0TMpKfozKSn/Mygo/zEnJ/8wJSX/Micn/kI3N/1oYGD8oJub/NHP
|
||||
z/3Ixsb8lI6O/GFYWPw/NDT9Micn/zAlJf8xJib/Migo/zMoKf80KSn6NCoq0DQrK343Li8uPDY2BTcw
|
||||
MAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AABMRkYAAAAAADozMw81LS1LMyoqojIoKOcxJyf+MScn/zIoKP8yJyf/NCkp/kE2Nv1kXFz8mpaW+9DP
|
||||
z/zz8/P+/////////////////v7+/+/v7/7KyMj8lpGR+2JaWvxANTX9NCkp/jMoKP8yJyf/MScn/zIo
|
||||
KP4yKCjmNCoqoDQsLEk5MjIPEAUFAE1ISAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAPzg4AEY/PwI2Ly8iNCwsbDIqKsEyKCj1Migo/zInJ/8yJyf/Mygo/zMoKP8zJyf/PTMz+mJb
|
||||
W/mGgID7lpCQ+5eRkfyWj5D8lo+P/JaPj/yWj4/8lo+P/JeQkPyYkZL8lY+P+4R/f/thWlr5PzU1+jQo
|
||||
KP4zJyf/Micn/zMpKf8zKCj/Mygo/zEoKPQxKSnANCwsazkwMSFHQkECQDk5AAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAD03OABPTE4BNS0uLTIqKo0wKCjbMCcn/DEnJ/8yJyf/Micn/zInJ/8yJyf/Mycn/zMn
|
||||
J/80KCj/NCcn/zUnJ/80JSb/NCQl/zMjJP8zIyT/MyMk/zMjJP8zIyT/MyMk/zMjJP8zIyT/MyQk/zQl
|
||||
Jf80Jyf/NCgo/zMnJ/80KCj/Mycn/zMoKP8zKCj/Migo/zInJ/8wJyf/MCgo/DEpKdoyKiqMNS4uLFZV
|
||||
VAE+ODgAAAAAAAAAAAAAAAAAQj09ADEpKQA1LS09MSkp2zAnJ/8wJyf/MCcn/zEnJ/8xJyf/Micn/zMo
|
||||
KP8zJyf/Mycn/zQnJ/80Jif/NSUm/zUlJv81JSb/NSUm/zYlJv82JSb/NiUm/zYlJv82JSb/NSUm/zUl
|
||||
Jv81JSb/NSUm/zYmJv81JSb/NSYm/zQmJ/8zJyf/Mycn/zMnJ/8zJyf/Micn/zIoKP8xJyf/MScn/y8n
|
||||
J/8wJyf/MSkp2TQtLTowKSkARUBAAAAAAAAAAAAAODExAJ2oqAAxKSmXMCcn/zAnJ/8xJyf/Micn/zEn
|
||||
J/8yJyj/NSkp/zUpKf80KCj/NCYn/zUlJv81JSb/NiUm/zcmJ/85Kir/Nycn/zQiI/80IiP/NSQl/zYl
|
||||
Jv82JSb/NiUm/zYlJv82Jib/OCcn/zcnJ/82Jif/NSUm/zUlJv81Jib/NCcn/zUoKP80KCj/Mygo/zIn
|
||||
J/8xJyf/Micn/zEnJ/8wJyf/MCcn/zEpKZMAAAAAODExAAAAAAAAAAAALycnAC4mJgMwKCirMCgo/zAn
|
||||
J/8xJyf/MScn/zInJ/8zJyf/NSgo/zQoKP81Jyf/NSUm/zUlJv82Jib/NiUm/zYlJv+BeHj/raen/4d+
|
||||
f/9nWlv/Tj9A/z0tLv81JCX/NCIj/zYlJv83Jib/OCYn/zcmJ/83Jib/NSUm/zUlJv82Jib/NSUm/zUn
|
||||
J/80KCj/Mycn/zMnJ/8yJyf/Migo/zEnJ/8wJyf/Lycn/y8nJ6kvJycDLycnAAAAAAAAAAAALycnACwl
|
||||
JQMxKCirMikp/zIoKP8zKCj/Mygo/zMoKP8zJyf/Mycn/zUmJ/81Jib/NSUm/zUlJv82Jib/NiUm/zUk
|
||||
Jf+hm5v///////39/f/z8vL/397e/8O/v/+hmpv/dmxs/z4tLv82JCX/NiUm/zcmJv83JSb/NiUm/zYl
|
||||
Jv82Jib/NSUm/zUlJv81Jyf/NCcn/zMnJ/80KCj/NCkp/zMoKP8yKCj/MSgo/zAoKKgsJSUDLycnAAAA
|
||||
AAAAAAAALycnACwlJQMxKCirMigp/zMoKP8zKCj/NCgo/zQoKP8zJyf/NCYn/zcnJ/82Jif/NiYm/zYl
|
||||
Jv83Jib/NiUm/zUkJf+gmpr/////////////////////////////////4N7e/09AQP81IyT/NyUm/zgn
|
||||
J/84Jif/NyYm/zYlJv83Jib/NSUm/zUlJv81JSb/NCYn/zMnJ/80KCj/NCgp/zMoKP8zKCj/Migo/zAo
|
||||
KKgqJCQDLycnAAAAAAAAAAAALycnAColJQMyKCirMygp/zMoKP8zKCj/NSgo/zQoKP80Jif/NSUm/zUl
|
||||
Jv82Jib/NiYm/zcmJv83Jib/NyUm/zYkJf+hmpr/////////////////////////////////4uDh/09A
|
||||
Qf81IyT/NyUm/zclJv84Jib/NyYm/zcmJv83Jib/NiUm/zYlJv82Jib/NSUm/zQmJ/80KCj/NSgo/zMo
|
||||
KP8zKCj/Mygo/zEoKKgpJCQDLycnAAAAAAAAAAAAMCcnAC0mJgMyKCirMigo/zIoKP80KCj/NCgo/zQn
|
||||
J/81JSb/NSUm/zUlJv82JSb/NiUm/zclJv84Jif/OSYn/zckJf+gmZr/////////////////////////
|
||||
////////4uDg/08/QP82IyT/NyUm/zclJv83JSb/NyUm/zclJv83Jif/OCYn/zcmJv81JSb/NiUm/zUl
|
||||
Jv80Jyf/NCgo/zMoKP8yKCj/Migo/zEoKKgtJiYDMCcnAAAAAAAAAAAAMScnADEnJwMxJyerMScn/zIn
|
||||
J/8zJyf/NCcn/zUmJ/82JSb/NSUm/zYlJv83Jib/NiUm/zcmJv85Jyf/Oicn/zglJf+hmZr/////////
|
||||
////////////////////////4d/f/1A/QP84JCX/OCUm/zglJv84Jib/NyUm/zgmJv85Jyf/OCcn/zgm
|
||||
J/82JSb/NSUm/zUlJv80Jib/Mycn/zMnJ/8yJyf/Micn/zIoKKgyKCgDMigoAAAAAAAAAAAAMScnADAm
|
||||
JgMxJyerMykp/zMoKP80Jyj/NSgo/zYmJ/82Jib/NSUm/zgmJ/85Jyf/NyUm/zgmJv86Jyf/Oicn/zgl
|
||||
Jf+hmZr/////////////////////////////////4d/f/1A/P/84JCX/OSUm/zsmJ/87Jyf/NyUm/zgm
|
||||
Jv85Jyf/OCcn/zgmJ/83Jif/NyYn/zcnJ/81Jib/NSgo/zQoKP8zKCj/Mygo/zMoKKgyJycDMigoAAAA
|
||||
AAAAAAAAMScnADAmJgMxJyerMygo/zQoKP80KCj/Nigo/zcmJ/82Jib/NiUm/zcmJv83Jib/NyUm/zgl
|
||||
Jv84Jib/OSYm/zklJf+hmZr/////////////////////////////////4N7e/1A/P/85JCX/OSUm/zom
|
||||
Jv86Jib/OCUm/zglJv84Jib/OCYm/zcmJ/82JSb/NiUm/zUlJv81JSb/Nigo/zQoKP80KCj/NCkp/zMo
|
||||
KKgzKSkDMykpAAAAAAAAAAAAMScnADEnJwMxJyerMicn/zMnJ/80Jyf/Nicn/zYmJv82JSb/NyUm/zYl
|
||||
Jv82JSb/NyUm/zclJv84JSb/OSUm/zgkJf+impr/////////////////////////////////4N3d/1A+
|
||||
Pv85JCX/OiUm/zklJv85JSb/OSUm/zglJv84JSb/NyUm/zclJv83JSb/NiUm/zYlJv81JSb/NSYm/zMn
|
||||
J/80Jyj/Mygo/zIoKKgxJycDMigoAAAAAAAAAAAAMygoADQpKQMzKCirMygo/zQoKP80Jyf/NSUm/zUl
|
||||
Jv82JSb/NyYm/zcmJv83JSb/OCUm/zkmJ/86Jif/OiYn/zgkJf+impr/////////////////////////
|
||||
////////393d/1A9Pf86JCX/OyYm/zomJv85JSb/OiUm/zomJ/85Jif/OCYn/zclJv82JSb/NiUm/zcm
|
||||
J/82Jif/NiYn/zUoKP80Jyf/Micn/zEnJ6gzKCgDMigoAAAAAAAAAAAAMigoADMpKQMyJyerMycn/zQo
|
||||
KP80Jyf/NSUm/zUlJv83Jib/NyYm/zYlJv83JSb/OCYm/zomJ/87Jif/OyYn/zgkJf+imZr/////////
|
||||
////////////////////////3tzc/088Pf87JCX/PCYm/zolJv85JSb/OiYm/zsmJ/85Jif/OSYn/zgl
|
||||
Jv82JSb/NiUm/zcmJ/82Jib/NSUm/zUnJ/8zJyf/Mycn/zInJ6g0KSkDMygoAAAAAAAAAAAAMygoADIp
|
||||
KQMyKCirNCgo/zQoKP80Jif/NSUm/zUlJv82JSb/NyYm/zYlJv83JSb/OCYm/z0oKP8/KSn/OyYn/zgk
|
||||
Jf+imZr/////////////////////////////////3tvc/088PP86JCX/PCYm/zslJv85JSb/OiYm/z4o
|
||||
KP8+KSn/OSYn/zglJv83JSb/NiUm/zcmJv82Jib/NiYm/zUnJ/8zJyf/Mycn/zInJ6gvJycDMScnAAAA
|
||||
AAAAAAAAMygoADIoKQMzKCirNCgo/zQoKP81Jif/NSUm/zYmJ/84Jif/OCYn/zclJv83JSb/OCYn/zsn
|
||||
J/89Jyj/OyYn/zkkJf+impr/////////////////////////////////3tvb/088PP87JSX/PCYn/zsl
|
||||
Jv86JSb/OiYm/zwnJ/88Jyj/OSYn/zglJv83JSb/NiUm/zcmJv82Jib/NiYn/zUmJ/8zJyf/Myco/zMo
|
||||
KKgvKCcDMigoAAAAAAAAAAAAMScnAC8nJwMyJyerMycn/zQnJ/81Jib/NSUm/zYmJv82JSb/NyYm/zcl
|
||||
Jv83JSb/OCUm/zomJ/86Jib/OiYm/zkkJf+impr/////////////////////////////////3dra/0w4
|
||||
OP83ISL/OSMj/zkiI/84IyT/OiUm/zomJ/85Jib/OCYm/zglJv83JSb/NyYm/zcmJv81JSb/NSUm/zUm
|
||||
J/8zJyf/Mygo/zMoKKgsJSUDMScnAAAAAAAAAAAAMScnAC8nJwMyJyerNCgo/zYpKf81Jif/NSUm/zYm
|
||||
J/83Jib/NyYn/zclJv84JSb/OCYm/zkmJv85JSb/OSUm/zslJf+jmpr/////////////////////////
|
||||
////////7Ovr/5mOj/+MgIH/jYGC/46Cg/9yZWX/PCgp/zolJv84JSb/NyUm/zkmJ/84Jif/OCYn/zYl
|
||||
Jv81JSb/NiYn/zcoKP80KCj/Mygo/zMoKKguJiYDMicnAAAAAAAAAAAAMScnAC8nJwMyJyerNCgo/zQo
|
||||
KP81Jif/NSUm/zYmJ/83Jib/NyYn/zclJv83JSb/OCUm/zklJv86Jib/OSUm/zolJf+jmpr/////////
|
||||
///////////////////////////////////+//7//v////////+/urr/Pisr/zklJv85Jib/NyUm/zkm
|
||||
J/84Jif/OCYn/zYlJv81JSb/NiYm/zUnJ/8zJyf/Mycn/zMoKKguJycDMicoAAAAAAAAAAAAMScnADAn
|
||||
JwMyJyerMycn/zMnJ/80Jif/NSUm/zUlJv82JSb/NiUm/zclJv83JSb/OCUm/zglJv85JSb/OSUm/zgk
|
||||
Jf+imZr////////////////////////////////////////////////////////////Au7v/Piss/zkl
|
||||
Jv84JSb/NyUm/zclJv83JSb/NiUm/zclJv81JSb/NSUm/zQmJ/8zJyf/Mycn/zEnJ6gvJycDMScnAAAA
|
||||
AAAAAAAAMScnADAnJwMyJyerMycn/zQoJ/80Jyf/NiUm/zUlJv82JSb/OCYn/zgmJ/84Jib/NyUm/zcl
|
||||
Jv85JSb/OSUm/zklJf+impr/////////////////////////////////////////////////////////
|
||||
///Cvb7/Piss/zglJv83JSb/OCUm/zgmJ/83Jib/NiUm/zYlJv81JSb/NiYm/zQnJ/80KCj/Mycn/zEn
|
||||
J6gwJycDMScnAAAAAAAAAAAAMScnAC8mJgMyJyerMygo/zMnJ/80Jyf/NSUm/zUlJv82Jib/OCcn/zgn
|
||||
J/84Jif/NyUm/zclJv85Jib/OiUm/zolJf+impr/////////////////////////////////////////
|
||||
///////////////////GwsL/QC0u/zglJv84Jib/OCUm/zkmJ/83Jif/NyYm/zYlJv81JSb/NiYm/zQn
|
||||
J/8zJyf/Micn/zEnJ6gxJycDMScnAAAAAAAAAAAAMScnAC4lJQMyKCirNCkp/zQoKP80KCj/NSYn/zUl
|
||||
Jv81JSb/NiUm/zYlJv83JSb/NyUm/zclJv84Jib/OSUm/zgkJf+impr/////////////////////////
|
||||
///////////////////////////////////MyMj/Qi8w/zclJf84Jib/NyUm/zclJv83JSb/NiUm/zYl
|
||||
Jv82Jib/Nicn/zQoKP80KCj/Mygo/zIoKKgvJiYDMScnAAAAAAAAAAAAMScnAC4lJQMzKCirNCkp/zUo
|
||||
KP81KCj/Nico/zYmJv81JSb/NiUm/zgmJ/83Jif/OCYm/zclJv84Jib/OCUm/zgkJf+impr/////////
|
||||
///////////////////////////////////////////////////V0tL/RjU1/zckJf84Jib/NyUm/zYl
|
||||
Jv83JSb/NiUm/zUlJv82Jib/Nigo/zUoKP80KCj/Mygo/zIoKKguJSUDMScnAAAAAAAAAAAAMScnAC4l
|
||||
JQMzKCirMygo/zQoKP80KCj/NSgo/zYmJ/81JSb/NSUm/zcmJv83Jif/NyYm/zglJv84Jib/NyUm/zck
|
||||
Jf+hmpr/////////////////////////////////+Pf3/8G8vP+yrK3/s62t/7Surv+dlpb/QzMz/zcl
|
||||
Jf84Jib/NyUm/zclJv82JSb/NSUm/zUlJv82Jif/NSgo/zUoKP80KCj/Mygo/zIoKKgtJCQDMScnAAAA
|
||||
AAAAAAAAMScnAC8mJQMyKCirMigo/zMoKP80KCj/NCgo/zUmJ/81JSb/NSUm/zYlJv82JSb/NiUm/zcm
|
||||
Jv84Jib/OCYn/zYkJf+hmZr/////////////////////////////////6ejo/1lJSv84JSb/OSco/zkn
|
||||
KP85Jyj/OCYm/zglJv84Jif/NyYn/zcmJv82JSb/NSUm/zUlJv81Jyf/NCgo/zQoKP8zKCj/Migo/zIo
|
||||
KKgvJSUDMScnAAAAAAAAAAAAMCcnAC8nJwMxJyerMScn/zEnJ/8zJyf/Mycn/zQnJ/81Jib/NSUm/zUl
|
||||
Jv82JSb/NiUm/zcmJv84Jyf/OScn/zclJf+gmZr/////////////////////////////////5+bm/1VG
|
||||
R/82IyT/NyUm/zclJv83JSb/NyUm/zcmJv84Jif/OCcn/zcmJ/81JSb/NSUm/zUmJv8zJyf/Mycn/zMn
|
||||
J/8xJyf/MScn/zEoKKgvKCcDMSgoAAAAAAAAAAAALycnAC0nJgMwJyerMigo/zInJ/8yJyf/NCgo/zQo
|
||||
KP80Jyf/NSUm/zYmJ/83Jyf/NiUm/zcmJv84Jyf/OScn/zclJf+gmZr/////////////////////////
|
||||
////////5uXl/1RFRv82IyT/NyUm/zkmJ/85Jyf/NyUm/zcmJv84Jyf/OCcn/zcmJ/82Jif/NiYn/zUo
|
||||
KP8zJyf/NCgo/zInJ/8xJyf/Migo/zEoKKguKCgDMCgoAAAAAAAAAAAALycnAC0mJgMvJyerMykp/zIo
|
||||
KP8yKCj/NCkp/zUoKP80KCj/NCYn/zYmJ/83Jyf/NSUm/zYmJv83Jif/NyYm/zYlJf+gmZr/////////
|
||||
////////////////////////5eTk/1RERf82JCX/NyUm/zgmJ/84Jyf/NiUm/zcmJv83Jif/NiYm/zYm
|
||||
J/81Jib/NScn/zQoKP80Jyf/NSkp/zIoKP8yKCj/Mykp/zEoKKgwKCgDMSgoAAAAAAAAAAAALycnAC8n
|
||||
JwMvJyerMCcn/zEnJ/8yKCj/Mygp/zQoKP80KCj/Mycn/zQmJ/81JSb/NSUm/zUlJv82JSb/NyUm/zUk
|
||||
Jf+gmZr/////////////////////////////////5OLi/09AQf8yISH/NCIj/zMiI/8zIiP/NCMk/zYl
|
||||
Jv81JSb/NSUm/zUmJv80Jif/Mycn/zMnJ/8zJyf/Micn/zEnJ/8yKCj/MSgo/zEoKKgwKCgDMSgoAAAA
|
||||
AAAAAAAAMCgoADEoKAMwKCirMCgo/zEoKP8xJyf/MScn/zInJ/8zJyf/NCgo/zQnJ/80Jif/NSUm/zYm
|
||||
J/82Jif/NiUm/zUkJf+gmpr/////////////////////////////////8O/v/5uTlP+If3//h35//4V8
|
||||
ff+Ee3z/aV5f/zgoKf82Jif/NSUm/zQmJ/80Jyf/Mycn/zQoKP8yKCj/Migo/zIoKP8wJyf/Lycn/y8n
|
||||
J6gvJycDLycnAAAAAAAAAAAAMCgpADIpKgMwKCirMCgo/zEoKP8xKCj/MScn/zInJ/8yKCj/Mycn/zMn
|
||||
J/8zJyf/NScn/zYnJ/82Jif/NiYn/zQkJf+gmZr/////////////////////////////////////////
|
||||
///+/v7//v7+//3+/v//////yMXF/z8wMf81Jib/NSgo/zQnJ/8zJyf/Mycn/zMoKP8yKCj/Migo/zIo
|
||||
KP8wJyf/Lycn/y8nJ6gzKioDMSgpAAAAAAAAAAAALygoAC8oKAMvJyerLycn/zAnJ/8vJyf/MCcn/zEn
|
||||
J/8xJyf/Micn/zInJ/8zJyf/NCgo/zcpKf84KSn/NiYn/zQkJf+gmZr/////////////////////////
|
||||
////////////////////////////////////////2tjY/0k8Pf82KSn/NCgo/zQnJ/8zJyf/Micn/zIo
|
||||
KP8yJyf/MCcn/zAoKP8vJyf/Lycn/y4nJ6guJycDLicnAAAAAAAAAAAAMCgpADEpKgMwKCirMCgo/zAo
|
||||
KP8vJyf/MCcn/zEoKP8yKCj/Mygo/zInJ/8yJyf/NCgo/zYpKv83Kir/NSgo/zMlJf+gmpr/////////
|
||||
////////////////////////////////////////////////////////6Ofn/1VLS/81KCj/NCgo/zMn
|
||||
J/8xJyf/MScn/zInKP8yKCj/MSgo/zAoKP8vJyf/Lycn/y8oKKguJycDLygoAAAAAAAAAAAALicnAC4n
|
||||
JwMuJyerLicn/y8nJ/8vJyf/MCcn/zAoKP8xKCj/Migo/zInJ/8xJyf/Mygo/zQoKP80KCj/NCgo/zIm
|
||||
Jv+fmpr/////////////////////////////////////////////////////////////////8vLy/2Na
|
||||
Wv8xJSX/Mygo/zEnJ/8yJyf/Micn/zEoKP8vJyf/Lycn/y8nJ/8uJyf/Lygo/y8oKKgtJiYDLycnAAAA
|
||||
AAAAAAAALicnAC0nJwMuJyerLygo/zApKf8vKCj/MCcn/zAoKP8wJyf/MSgo/zEnJ/8xJyf/Micn/zIo
|
||||
KP8yJyf/Mycn/zMnJ/+fmpr/////////////////////////////////////////////////////////
|
||||
////////+vr6/3Rubv8uJCT/MScn/zIoKP8yKCj/MSgo/zAnJ/8vJyf/MCgo/zApKf8vKCj/Lygo/y8o
|
||||
KKgsJiYDLicnAAAAAAAAAAAALScnAC0nJwMtJyerLygo/zApKf8vKCj/Lycn/zAoKP8wKCj/MCgo/zAn
|
||||
J/8xJyf/Micn/zInJ/8yJyf/MScn/zInJ/+gm5v/////////////////////////////////////////
|
||||
/////////////////////////////4mEhP8vJCT/MScn/zIoKf8yKSn/MSgo/zAnJ/8vJyf/Lygo/zAp
|
||||
Kf8vKCj/Lico/y8oKKgsJycDLigoAAAAAAAAAAAALScnAC0nJwQtJyerLScn/y4nJ/8uJyf/Licn/y4n
|
||||
J/8vJyf/Lycn/zAnJ/8vJyf/MCcn/zEnJ/8xJyf/MScn/zAmJv+UkJD/7e3t/+zr6//r6+v/6+vr/+vr
|
||||
6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/7e3t/5KOjv8wJib/Lycn/y8nJ/8wKCj/MCgo/y8o
|
||||
KP8uJyf/Licn/y4nJ/8uJyf/LScn/y0nJ6ktJycDLScnAAAAAAAAAAAANC8vAEM/PwEvKSmgLigo/y4n
|
||||
J/8uJyf/Lycn/y4nJ/8uJyf/Lygo/zAoKP8wJyf/Lycn/y8nJ/8vJyf/MCcn/zEnJ/9EPDz/Vk5O/1ZN
|
||||
Tf9VTU3/Vk1N/1VNTf9WTU3/Vk1N/1VNTf9VTU3/Vk5O/1ZOTv9VTU3/VE1N/0Q9Pf8vJyf/Lycn/zAn
|
||||
J/8vJyf/Lycn/y8oKP8uJyf/Lygo/y4nJ/8uJyf/LScn/y4oKJ1PTU0BMy4uAAAAAAAAAAAAWlhZACsk
|
||||
JAAyLCxfLigo+C0nJ/8uJyf/Licn/y4nJ/8vKCj/MCkp/zApKf8wKCj/Lycn/y8nJ/8wJyf/MCgo/zEo
|
||||
KP8wJyf/LiUl/y4lJf8uJSX/LyUl/y8lJf8vJSX/LiUl/y4lJf8vJSX/MCYn/zAmJv8uJib/LSUl/y4m
|
||||
Jv8wJyf/MCgo/zAoKP8vKCj/Lygo/y4nJ/8uJyf/Lico/y0nJ/8tJyf/Ligo9zErLFwrJSUAWVdYAAAA
|
||||
AAAAAAAAAAAAADYxMQA5NDQOMSssiy8pKe0uKCj/LScn/y4nJ/8uJyf/Lygo/y8oKP8vKCj/Licn/y8n
|
||||
J/8wKCj/Lycn/zAoKP8wKCj/Lycn/zAnJ/8wJyf/MCgo/zAoKP8wJyf/MCcn/y8nJ/8wJyf/MCgo/zAo
|
||||
KP8wKCj/Lycn/y8nJ/8vKCj/Licn/y8nKP8vJyj/Licn/y4nJ/8uJyf/Ligo/y4oKP8vKSnsMSsriDYx
|
||||
MQ01LzAAAAAAAAAAAAD///AP//8AAP//gAH//wAA//4AAH//AAD/8AAAD/8AAP/AAAAD/wAA/wAAAAD/
|
||||
AAD4AAAAAB8AAOAAAAAABwAA4AAAAAAHAADgAAAAAAcAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAA
|
||||
AAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAAD
|
||||
AADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAA
|
||||
AAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAAD
|
||||
AADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAA
|
||||
AAAAAwAAwAAAAAADAADAAAAAAAMAAOAAAAAABwAA4AAAAAAHAACJUE5HDQoaCgAAAA1JSERSAAABAAAA
|
||||
AQAIBgAAAFxyqGYAAGt6SURBVHja7b15gGZJVSd6Iu73fblW1t479FZ0Nd2IPgefD0XhAQ9lcUFAtmZR
|
||||
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
|
||||
AElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
||||
381
FModel/PAKWindow.Designer.cs
generated
|
|
@ -1,381 +0,0 @@
|
|||
namespace FModel
|
||||
{
|
||||
partial class PAKWindow
|
||||
{
|
||||
/// <summary>
|
||||
/// Variable nécessaire au concepteur.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Nettoyage des ressources utilisées.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true si les ressources managées doivent être supprimées ; sinon, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Code généré par le Concepteur Windows Form
|
||||
|
||||
/// <summary>
|
||||
/// Méthode requise pour la prise en charge du concepteur - ne modifiez pas
|
||||
/// le contenu de cette méthode avec l'éditeur de code.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PAKWindow));
|
||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||
this.LoadButton = new FModel.SplitButton();
|
||||
this.LoadContext = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
this.optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.AESKeyLabel = new System.Windows.Forms.Label();
|
||||
this.AESKeyTextBox = new System.Windows.Forms.TextBox();
|
||||
this.PAKsComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.ItemsListBox = new System.Windows.Forms.ListBox();
|
||||
this.PAKTreeView = new System.Windows.Forms.TreeView();
|
||||
this.TreeViewImageList = new System.Windows.Forms.ImageList(this.components);
|
||||
this.ItemIconPictureBox = new System.Windows.Forms.PictureBox();
|
||||
this.groupBox2 = new System.Windows.Forms.GroupBox();
|
||||
this.scintilla1 = new ScintillaNET.Scintilla();
|
||||
this.SaveImageButton = new FModel.SplitButton();
|
||||
this.ImageContext = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
this.OpenImageTS = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.ExtractAssetButton = new FModel.SplitButton();
|
||||
this.ExtractAsset = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
this.LoadDataTS = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.SaveImageTS = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.mergeGeneratedImagesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.ConsoleRichTextBox = new System.Windows.Forms.RichTextBox();
|
||||
this.FilterLabel = new System.Windows.Forms.Label();
|
||||
this.FilterTextBox = new System.Windows.Forms.TextBox();
|
||||
this.loadAllPAKsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.groupBox1.SuspendLayout();
|
||||
this.LoadContext.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.ItemIconPictureBox)).BeginInit();
|
||||
this.groupBox2.SuspendLayout();
|
||||
this.ImageContext.SuspendLayout();
|
||||
this.ExtractAsset.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// groupBox1
|
||||
//
|
||||
this.groupBox1.Controls.Add(this.LoadButton);
|
||||
this.groupBox1.Controls.Add(this.AESKeyLabel);
|
||||
this.groupBox1.Controls.Add(this.AESKeyTextBox);
|
||||
this.groupBox1.Controls.Add(this.PAKsComboBox);
|
||||
this.groupBox1.Location = new System.Drawing.Point(12, 12);
|
||||
this.groupBox1.Name = "groupBox1";
|
||||
this.groupBox1.Size = new System.Drawing.Size(408, 75);
|
||||
this.groupBox1.TabIndex = 0;
|
||||
this.groupBox1.TabStop = false;
|
||||
this.groupBox1.Text = "PAK";
|
||||
//
|
||||
// LoadButton
|
||||
//
|
||||
this.LoadButton.Location = new System.Drawing.Point(296, 18);
|
||||
this.LoadButton.Menu = this.LoadContext;
|
||||
this.LoadButton.Name = "LoadButton";
|
||||
this.LoadButton.Size = new System.Drawing.Size(106, 23);
|
||||
this.LoadButton.TabIndex = 12;
|
||||
this.LoadButton.Text = " Load";
|
||||
this.LoadButton.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
this.LoadButton.UseVisualStyleBackColor = true;
|
||||
this.LoadButton.Click += new System.EventHandler(this.LoadButton_Click);
|
||||
//
|
||||
// LoadContext
|
||||
//
|
||||
this.LoadContext.ImageScalingSize = new System.Drawing.Size(18, 18);
|
||||
this.LoadContext.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.loadAllPAKsToolStripMenuItem,
|
||||
this.toolStripSeparator2,
|
||||
this.optionsToolStripMenuItem});
|
||||
this.LoadContext.Name = "LoadContext";
|
||||
this.LoadContext.Size = new System.Drawing.Size(181, 76);
|
||||
//
|
||||
// optionsToolStripMenuItem
|
||||
//
|
||||
this.optionsToolStripMenuItem.Name = "optionsToolStripMenuItem";
|
||||
this.optionsToolStripMenuItem.Size = new System.Drawing.Size(151, 22);
|
||||
this.optionsToolStripMenuItem.Text = "Options";
|
||||
this.optionsToolStripMenuItem.Click += new System.EventHandler(this.optionsToolStripMenuItem_Click);
|
||||
//
|
||||
// AESKeyLabel
|
||||
//
|
||||
this.AESKeyLabel.AutoSize = true;
|
||||
this.AESKeyLabel.Location = new System.Drawing.Point(6, 51);
|
||||
this.AESKeyLabel.Name = "AESKeyLabel";
|
||||
this.AESKeyLabel.Size = new System.Drawing.Size(52, 13);
|
||||
this.AESKeyLabel.TabIndex = 2;
|
||||
this.AESKeyLabel.Text = "AES Key:";
|
||||
//
|
||||
// AESKeyTextBox
|
||||
//
|
||||
this.AESKeyTextBox.Location = new System.Drawing.Point(64, 47);
|
||||
this.AESKeyTextBox.Name = "AESKeyTextBox";
|
||||
this.AESKeyTextBox.Size = new System.Drawing.Size(338, 20);
|
||||
this.AESKeyTextBox.TabIndex = 1;
|
||||
this.AESKeyTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
// PAKsComboBox
|
||||
//
|
||||
this.PAKsComboBox.FormattingEnabled = true;
|
||||
this.PAKsComboBox.Location = new System.Drawing.Point(6, 19);
|
||||
this.PAKsComboBox.Name = "PAKsComboBox";
|
||||
this.PAKsComboBox.Size = new System.Drawing.Size(284, 21);
|
||||
this.PAKsComboBox.TabIndex = 0;
|
||||
//
|
||||
// ItemsListBox
|
||||
//
|
||||
this.ItemsListBox.FormattingEnabled = true;
|
||||
this.ItemsListBox.Location = new System.Drawing.Point(12, 389);
|
||||
this.ItemsListBox.Name = "ItemsListBox";
|
||||
this.ItemsListBox.SelectionMode = System.Windows.Forms.SelectionMode.MultiExtended;
|
||||
this.ItemsListBox.Size = new System.Drawing.Size(408, 290);
|
||||
this.ItemsListBox.Sorted = true;
|
||||
this.ItemsListBox.TabIndex = 1;
|
||||
this.ItemsListBox.SelectedIndexChanged += new System.EventHandler(this.ItemsListBox_SelectedIndexChanged);
|
||||
//
|
||||
// PAKTreeView
|
||||
//
|
||||
this.PAKTreeView.ImageIndex = 0;
|
||||
this.PAKTreeView.ImageList = this.TreeViewImageList;
|
||||
this.PAKTreeView.Location = new System.Drawing.Point(12, 93);
|
||||
this.PAKTreeView.Name = "PAKTreeView";
|
||||
this.PAKTreeView.SelectedImageIndex = 1;
|
||||
this.PAKTreeView.ShowLines = false;
|
||||
this.PAKTreeView.Size = new System.Drawing.Size(408, 290);
|
||||
this.PAKTreeView.TabIndex = 2;
|
||||
this.PAKTreeView.NodeMouseClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.PAKTreeView_NodeMouseClick);
|
||||
//
|
||||
// TreeViewImageList
|
||||
//
|
||||
this.TreeViewImageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("TreeViewImageList.ImageStream")));
|
||||
this.TreeViewImageList.TransparentColor = System.Drawing.Color.Transparent;
|
||||
this.TreeViewImageList.Images.SetKeyName(0, "folder.png");
|
||||
this.TreeViewImageList.Images.SetKeyName(1, "folder_open.png");
|
||||
//
|
||||
// ItemIconPictureBox
|
||||
//
|
||||
this.ItemIconPictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.ItemIconPictureBox.Location = new System.Drawing.Point(572, 18);
|
||||
this.ItemIconPictureBox.Name = "ItemIconPictureBox";
|
||||
this.ItemIconPictureBox.Size = new System.Drawing.Size(350, 350);
|
||||
this.ItemIconPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
|
||||
this.ItemIconPictureBox.TabIndex = 3;
|
||||
this.ItemIconPictureBox.TabStop = false;
|
||||
//
|
||||
// groupBox2
|
||||
//
|
||||
this.groupBox2.Controls.Add(this.scintilla1);
|
||||
this.groupBox2.Controls.Add(this.SaveImageButton);
|
||||
this.groupBox2.Controls.Add(this.ExtractAssetButton);
|
||||
this.groupBox2.Controls.Add(this.ConsoleRichTextBox);
|
||||
this.groupBox2.Controls.Add(this.ItemIconPictureBox);
|
||||
this.groupBox2.Location = new System.Drawing.Point(426, 12);
|
||||
this.groupBox2.Name = "groupBox2";
|
||||
this.groupBox2.Size = new System.Drawing.Size(928, 693);
|
||||
this.groupBox2.TabIndex = 4;
|
||||
this.groupBox2.TabStop = false;
|
||||
//
|
||||
// scintilla1
|
||||
//
|
||||
this.scintilla1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.scintilla1.IndentationGuides = ScintillaNET.IndentView.Real;
|
||||
this.scintilla1.Location = new System.Drawing.Point(6, 18);
|
||||
this.scintilla1.Name = "scintilla1";
|
||||
this.scintilla1.ScrollWidth = 539;
|
||||
this.scintilla1.Size = new System.Drawing.Size(560, 350);
|
||||
this.scintilla1.TabIndex = 12;
|
||||
//
|
||||
// SaveImageButton
|
||||
//
|
||||
this.SaveImageButton.Location = new System.Drawing.Point(810, 635);
|
||||
this.SaveImageButton.Menu = this.ImageContext;
|
||||
this.SaveImageButton.Name = "SaveImageButton";
|
||||
this.SaveImageButton.Size = new System.Drawing.Size(112, 23);
|
||||
this.SaveImageButton.TabIndex = 11;
|
||||
this.SaveImageButton.Text = " Save Image";
|
||||
this.SaveImageButton.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
this.SaveImageButton.UseVisualStyleBackColor = true;
|
||||
this.SaveImageButton.Click += new System.EventHandler(this.SaveImageButton_Click);
|
||||
//
|
||||
// ImageContext
|
||||
//
|
||||
this.ImageContext.ImageScalingSize = new System.Drawing.Size(18, 18);
|
||||
this.ImageContext.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.OpenImageTS});
|
||||
this.ImageContext.Name = "ImageContext";
|
||||
this.ImageContext.Size = new System.Drawing.Size(140, 26);
|
||||
//
|
||||
// OpenImageTS
|
||||
//
|
||||
this.OpenImageTS.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
||||
this.OpenImageTS.Name = "OpenImageTS";
|
||||
this.OpenImageTS.Size = new System.Drawing.Size(139, 22);
|
||||
this.OpenImageTS.Text = "Open Image";
|
||||
this.OpenImageTS.Click += new System.EventHandler(this.OpenImageTS_Click);
|
||||
//
|
||||
// ExtractAssetButton
|
||||
//
|
||||
this.ExtractAssetButton.Location = new System.Drawing.Point(810, 664);
|
||||
this.ExtractAssetButton.Menu = this.ExtractAsset;
|
||||
this.ExtractAssetButton.Name = "ExtractAssetButton";
|
||||
this.ExtractAssetButton.Size = new System.Drawing.Size(112, 23);
|
||||
this.ExtractAssetButton.TabIndex = 10;
|
||||
this.ExtractAssetButton.Text = " Extract Asset";
|
||||
this.ExtractAssetButton.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
this.ExtractAssetButton.UseVisualStyleBackColor = true;
|
||||
this.ExtractAssetButton.Click += new System.EventHandler(this.ExtractAssetButton_Click);
|
||||
//
|
||||
// ExtractAsset
|
||||
//
|
||||
this.ExtractAsset.ImageScalingSize = new System.Drawing.Size(18, 18);
|
||||
this.ExtractAsset.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.LoadDataTS,
|
||||
this.SaveImageTS,
|
||||
this.toolStripSeparator1,
|
||||
this.mergeGeneratedImagesToolStripMenuItem});
|
||||
this.ExtractAsset.Name = "ExtractAsset";
|
||||
this.ExtractAsset.Size = new System.Drawing.Size(223, 76);
|
||||
//
|
||||
// LoadDataTS
|
||||
//
|
||||
this.LoadDataTS.Checked = true;
|
||||
this.LoadDataTS.CheckOnClick = true;
|
||||
this.LoadDataTS.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.LoadDataTS.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
||||
this.LoadDataTS.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
this.LoadDataTS.Name = "LoadDataTS";
|
||||
this.LoadDataTS.Size = new System.Drawing.Size(222, 22);
|
||||
this.LoadDataTS.Text = "Load Data After Serialization";
|
||||
//
|
||||
// SaveImageTS
|
||||
//
|
||||
this.SaveImageTS.CheckOnClick = true;
|
||||
this.SaveImageTS.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
||||
this.SaveImageTS.Name = "SaveImageTS";
|
||||
this.SaveImageTS.Size = new System.Drawing.Size(222, 22);
|
||||
this.SaveImageTS.Text = "Auto Save Generated Image";
|
||||
//
|
||||
// toolStripSeparator1
|
||||
//
|
||||
this.toolStripSeparator1.Name = "toolStripSeparator1";
|
||||
this.toolStripSeparator1.Size = new System.Drawing.Size(219, 6);
|
||||
//
|
||||
// mergeGeneratedImagesToolStripMenuItem
|
||||
//
|
||||
this.mergeGeneratedImagesToolStripMenuItem.Name = "mergeGeneratedImagesToolStripMenuItem";
|
||||
this.mergeGeneratedImagesToolStripMenuItem.Size = new System.Drawing.Size(222, 22);
|
||||
this.mergeGeneratedImagesToolStripMenuItem.Text = "Merge Generated Images";
|
||||
this.mergeGeneratedImagesToolStripMenuItem.Click += new System.EventHandler(this.mergeGeneratedImagesToolStripMenuItem_Click);
|
||||
//
|
||||
// ConsoleRichTextBox
|
||||
//
|
||||
this.ConsoleRichTextBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
||||
this.ConsoleRichTextBox.Location = new System.Drawing.Point(6, 374);
|
||||
this.ConsoleRichTextBox.Name = "ConsoleRichTextBox";
|
||||
this.ConsoleRichTextBox.ReadOnly = true;
|
||||
this.ConsoleRichTextBox.Size = new System.Drawing.Size(922, 255);
|
||||
this.ConsoleRichTextBox.TabIndex = 6;
|
||||
this.ConsoleRichTextBox.Text = "";
|
||||
//
|
||||
// FilterLabel
|
||||
//
|
||||
this.FilterLabel.AutoSize = true;
|
||||
this.FilterLabel.Location = new System.Drawing.Point(18, 688);
|
||||
this.FilterLabel.Name = "FilterLabel";
|
||||
this.FilterLabel.Size = new System.Drawing.Size(32, 13);
|
||||
this.FilterLabel.TabIndex = 6;
|
||||
this.FilterLabel.Text = "Filter:";
|
||||
//
|
||||
// FilterTextBox
|
||||
//
|
||||
this.FilterTextBox.Location = new System.Drawing.Point(56, 685);
|
||||
this.FilterTextBox.Name = "FilterTextBox";
|
||||
this.FilterTextBox.Size = new System.Drawing.Size(364, 20);
|
||||
this.FilterTextBox.TabIndex = 5;
|
||||
this.FilterTextBox.TextChanged += new System.EventHandler(this.FilterTextBox_TextChanged);
|
||||
//
|
||||
// loadAllPAKsToolStripMenuItem
|
||||
//
|
||||
this.loadAllPAKsToolStripMenuItem.Name = "loadAllPAKsToolStripMenuItem";
|
||||
this.loadAllPAKsToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
|
||||
this.loadAllPAKsToolStripMenuItem.Text = "Load Them All";
|
||||
this.loadAllPAKsToolStripMenuItem.Click += new System.EventHandler(this.loadAllPAKsToolStripMenuItem_Click);
|
||||
//
|
||||
// toolStripSeparator2
|
||||
//
|
||||
this.toolStripSeparator2.Name = "toolStripSeparator2";
|
||||
this.toolStripSeparator2.Size = new System.Drawing.Size(148, 6);
|
||||
//
|
||||
// PAKWindow
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(1366, 712);
|
||||
this.Controls.Add(this.FilterLabel);
|
||||
this.Controls.Add(this.groupBox2);
|
||||
this.Controls.Add(this.PAKTreeView);
|
||||
this.Controls.Add(this.FilterTextBox);
|
||||
this.Controls.Add(this.ItemsListBox);
|
||||
this.Controls.Add(this.groupBox1);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.MaximizeBox = false;
|
||||
this.Name = "PAKWindow";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "FModel";
|
||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.PAKWindow_FormClosing);
|
||||
this.Load += new System.EventHandler(this.PAKWindow_Load);
|
||||
this.groupBox1.ResumeLayout(false);
|
||||
this.groupBox1.PerformLayout();
|
||||
this.LoadContext.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.ItemIconPictureBox)).EndInit();
|
||||
this.groupBox2.ResumeLayout(false);
|
||||
this.ImageContext.ResumeLayout(false);
|
||||
this.ExtractAsset.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.GroupBox groupBox1;
|
||||
private System.Windows.Forms.Label AESKeyLabel;
|
||||
private System.Windows.Forms.TextBox AESKeyTextBox;
|
||||
private System.Windows.Forms.ComboBox PAKsComboBox;
|
||||
private System.Windows.Forms.ListBox ItemsListBox;
|
||||
private System.Windows.Forms.TreeView PAKTreeView;
|
||||
private System.Windows.Forms.PictureBox ItemIconPictureBox;
|
||||
private System.Windows.Forms.GroupBox groupBox2;
|
||||
private System.Windows.Forms.RichTextBox ConsoleRichTextBox;
|
||||
private System.Windows.Forms.Label FilterLabel;
|
||||
private System.Windows.Forms.TextBox FilterTextBox;
|
||||
private SplitButton ExtractAssetButton;
|
||||
private System.Windows.Forms.ContextMenuStrip ExtractAsset;
|
||||
private System.Windows.Forms.ToolStripMenuItem LoadDataTS;
|
||||
private System.Windows.Forms.ContextMenuStrip ImageContext;
|
||||
private System.Windows.Forms.ToolStripMenuItem OpenImageTS;
|
||||
private SplitButton SaveImageButton;
|
||||
private System.Windows.Forms.ToolStripMenuItem SaveImageTS;
|
||||
private SplitButton LoadButton;
|
||||
private System.Windows.Forms.ContextMenuStrip LoadContext;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
|
||||
private System.Windows.Forms.ToolStripMenuItem optionsToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem mergeGeneratedImagesToolStripMenuItem;
|
||||
private System.Windows.Forms.ImageList TreeViewImageList;
|
||||
private ScintillaNET.Scintilla scintilla1;
|
||||
private System.Windows.Forms.ToolStripMenuItem loadAllPAKsToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
|
||||
}
|
||||
}
|
||||
|
||||
2871
FModel/PAKWindow.cs
|
|
@ -1,933 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="LoadContext.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>277, 17</value>
|
||||
</metadata>
|
||||
<metadata name="PAKsComboBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="TreeViewImageList.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>398, 17</value>
|
||||
</metadata>
|
||||
<data name="TreeViewImageList.ImageStream" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>
|
||||
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
|
||||
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
|
||||
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACc
|
||||
BwAAAk1TRnQBSQFMAgEBAgEAAUgBAAFIAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
|
||||
AwABQAMAARADAAEBAQABCAYAAQQYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
|
||||
AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
|
||||
AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA
|
||||
AWYDAAGZAwABzAIAATMDAAIzAgABMwFmAgABMwGZAgABMwHMAgABMwH/AgABZgMAAWYBMwIAAmYCAAFm
|
||||
AZkCAAFmAcwCAAFmAf8CAAGZAwABmQEzAgABmQFmAgACmQIAAZkBzAIAAZkB/wIAAcwDAAHMATMCAAHM
|
||||
AWYCAAHMAZkCAALMAgABzAH/AgAB/wFmAgAB/wGZAgAB/wHMAQABMwH/AgAB/wEAATMBAAEzAQABZgEA
|
||||
ATMBAAGZAQABMwEAAcwBAAEzAQAB/wEAAf8BMwIAAzMBAAIzAWYBAAIzAZkBAAIzAcwBAAIzAf8BAAEz
|
||||
AWYCAAEzAWYBMwEAATMCZgEAATMBZgGZAQABMwFmAcwBAAEzAWYB/wEAATMBmQIAATMBmQEzAQABMwGZ
|
||||
AWYBAAEzApkBAAEzAZkBzAEAATMBmQH/AQABMwHMAgABMwHMATMBAAEzAcwBZgEAATMBzAGZAQABMwLM
|
||||
AQABMwHMAf8BAAEzAf8BMwEAATMB/wFmAQABMwH/AZkBAAEzAf8BzAEAATMC/wEAAWYDAAFmAQABMwEA
|
||||
AWYBAAFmAQABZgEAAZkBAAFmAQABzAEAAWYBAAH/AQABZgEzAgABZgIzAQABZgEzAWYBAAFmATMBmQEA
|
||||
AWYBMwHMAQABZgEzAf8BAAJmAgACZgEzAQADZgEAAmYBmQEAAmYBzAEAAWYBmQIAAWYBmQEzAQABZgGZ
|
||||
AWYBAAFmApkBAAFmAZkBzAEAAWYBmQH/AQABZgHMAgABZgHMATMBAAFmAcwBmQEAAWYCzAEAAWYBzAH/
|
||||
AQABZgH/AgABZgH/ATMBAAFmAf8BmQEAAWYB/wHMAQABzAEAAf8BAAH/AQABzAEAApkCAAGZATMBmQEA
|
||||
AZkBAAGZAQABmQEAAcwBAAGZAwABmQIzAQABmQEAAWYBAAGZATMBzAEAAZkBAAH/AQABmQFmAgABmQFm
|
||||
ATMBAAGZATMBZgEAAZkBZgGZAQABmQFmAcwBAAGZATMB/wEAApkBMwEAApkBZgEAA5kBAAKZAcwBAAKZ
|
||||
Af8BAAGZAcwCAAGZAcwBMwEAAWYBzAFmAQABmQHMAZkBAAGZAswBAAGZAcwB/wEAAZkB/wIAAZkB/wEz
|
||||
AQABmQHMAWYBAAGZAf8BmQEAAZkB/wHMAQABmQL/AQABzAMAAZkBAAEzAQABzAEAAWYBAAHMAQABmQEA
|
||||
AcwBAAHMAQABmQEzAgABzAIzAQABzAEzAWYBAAHMATMBmQEAAcwBMwHMAQABzAEzAf8BAAHMAWYCAAHM
|
||||
AWYBMwEAAZkCZgEAAcwBZgGZAQABzAFmAcwBAAGZAWYB/wEAAcwBmQIAAcwBmQEzAQABzAGZAWYBAAHM
|
||||
ApkBAAHMAZkBzAEAAcwBmQH/AQACzAIAAswBMwEAAswBZgEAAswBmQEAA8wBAALMAf8BAAHMAf8CAAHM
|
||||
Af8BMwEAAZkB/wFmAQABzAH/AZkBAAHMAf8BzAEAAcwC/wEAAcwBAAEzAQAB/wEAAWYBAAH/AQABmQEA
|
||||
AcwBMwIAAf8CMwEAAf8BMwFmAQAB/wEzAZkBAAH/ATMBzAEAAf8BMwH/AQAB/wFmAgAB/wFmATMBAAHM
|
||||
AmYBAAH/AWYBmQEAAf8BZgHMAQABzAFmAf8BAAH/AZkCAAH/AZkBMwEAAf8BmQFmAQAB/wKZAQAB/wGZ
|
||||
AcwBAAH/AZkB/wEAAf8BzAIAAf8BzAEzAQAB/wHMAWYBAAH/AcwBmQEAAf8CzAEAAf8BzAH/AQAC/wEz
|
||||
AQABzAH/AWYBAAL/AZkBAAL/AcwBAAJmAf8BAAFmAf8BZgEAAWYC/wEAAf8CZgEAAf8BZgH/AQAC/wFm
|
||||
AQABIQEAAaUBAANfAQADdwEAA4YBAAOWAQADywEAA7IBAAPXAQAD3QEAA+MBAAPqAQAD8QEAA/gBAAHw
|
||||
AfsB/wEAAaQCoAEAA4ADAAH/AgAB/wMAAv8BAAH/AwAB/wEAAf8BAAL/AgAD/wEAEP8wABuuBJYBriAA
|
||||
Gq4GliAAB64B6gESEa4ClgHxAfQCliAABq4B6gFtAhIQrgSWAboBliAABq4BbQGuARIBrgFtD64ElgG7
|
||||
AZYgAAiuARISrgSWAa4gAAiuARIXriAACK4BEheuIAAgriAAIK4gAAiuCBQIrggUIAAHrgHsCBQHrgHq
|
||||
CBQgAAauAe0JAAauAQcpAAauCgAGrmoAAUIBTQE+BwABPgMAASgDAAFAAwABEAMAAQEBAAEBBQABgBcA
|
||||
A/8DAAL/ZAABAQH/AQEB/wQAAQMB/wEDAf8EAAT/BAAL
|
||||
</value>
|
||||
</data>
|
||||
<metadata name="ImageContext.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>134, 17</value>
|
||||
</metadata>
|
||||
<metadata name="ExtractAsset.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
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
|
||||
JP8wHyD/MB8g/zIiI/80JCT/NSUm/zQmJ/80Jyf/Mygo/zInJ/8xJyf/MCgo5jEpKTswKSkAMSgoADAo
|
||||
KF0xKCj+Migo/zMnJ/80Jyj/NSYn/zUlJv87Kyz/pJ2e/7WvsP+OhYb/Z1pb/zsrK/83Jib/NiUm/zYl
|
||||
Jv81Jif/NCcn/zMoKP8yKCj/MSgo/jAoKFwwKCgAMikpADEoKF0zKCj+NCgo/zQnJ/81Jib/NiYm/zYl
|
||||
Jv89LC3/yMTE////////////4N3d/009Pv82JCX/NyYm/zclJv82JSb/NSYm/zQnJ/80KCj/Migo/jEo
|
||||
KFwyKCgAMigoADEnJ10yKCj+NCgo/zUmJ/81JSb/NiUm/zcmJv8+LS3/yMPD////////////5ePj/08/
|
||||
QP82JCT/NyUm/zgmJ/83Jif/NiUm/zUmJ/8zJyj/Migo/jIoKFwyKCgAMigoADInJ10zKCj+NSgo/zYm
|
||||
J/83Jib/NyYm/zglJv8/LS3/yMPD////////////5OLi/1A+P/84JCX/OSYm/zgmJv84Jif/NyYm/zYm
|
||||
J/80Jyj/Mygo/jMoKFwzKCgAMicnADInKF0zKCj+NScn/zYmJv83JSb/NyUm/zglJv8/LC3/yMPD////
|
||||
////////5OHi/1E+Pv85JCX/OSUm/zkmJ/83JSb/NiUm/zYmJv81Jyf/Mygo/jIoKFwyKCgAMygoADMo
|
||||
KF00KCj+NSYn/zYlJv83JSb/OCUm/zsnJ/9ALC3/yMPD////////////4+Hh/1A9Pv85JCT/OiUm/zwn
|
||||
KP84Jif/NiUm/zYmJv81Jif/Mycn/jInJ1wyJycAMycnADInJ100Jyj+NSYn/zcmJv83Jib/OCUm/zom
|
||||
J/9ALC3/ycPD////////////4+Hh/1NAQP89Jyj/Oycn/zsmJ/84Jib/NyUm/zYmJv81Jif/Mycn/jMo
|
||||
KFwzKCgAMicnADInJ100KCj+NSYn/zYmJv83Jib/OCUm/zklJv9ALC3/ycPE////////////9vX1/8bA
|
||||
wP++t7f/bF1e/zcjJP84Jib/OCYn/zYlJv82Jif/NCcn/jMoKFwzKCgAMicnADInJ10zJyf+NSYm/zYl
|
||||
Jv83Jif/NyUm/zglJv8/LC3/yMPD////////////////////////////hXl6/zUiIv84JSb/NyYm/zYl
|
||||
Jv81Jif/Mycn/jInJ1wyJycAMygoADIoKF00KCj+NScn/zYlJv83Jif/NyUm/zglJv8/LC3/yMPE////
|
||||
////////////////////////iX9//zUiI/84Jib/NyYm/zYlJv81Jyf/Mygo/jInJ1wyJycAMykpADMo
|
||||
KF00KCj+NSgo/zUmJv82Jib/NyYm/zclJv8+LC3/yMPD////////////+vr6/9fT0//Qzc3/e3Bw/zUj
|
||||
JP83JSb/NiUm/zUmJv81KCj/NCgo/jIoKFwzKCgAMigoADIoKF0yKCj+NCgo/zUmJ/81JSb/NiUm/zcl
|
||||
Jv8+LS3/yMPD////////////6ejo/1tLTP8/LS7/PCor/zcmJv83Jif/NiUm/zUmJ/80KCj/Migo/jIo
|
||||
KFwyKCgAMSgoADAnJ10yKCj+Mygo/zQoKP81Jif/NiYn/zclJv8+LS3/yMPD////////////5+Xl/04+
|
||||
P/8zICH/NSMk/zcmJv83Jif/NSYn/zQnKP8zKCj/Migo/jEoKFwyKCgAMCcnADAnJ10wKCj+Migo/zMo
|
||||
KP80Jyf/NSYm/zUlJv88LC3/x8PD////////////7evr/3xxcf9nWlv/XE9P/zkpKf81Jib/NCcn/zMn
|
||||
KP8yKCj/MSgo/jAoKFwwKCgALygoAC8oKF0wKCj+MCcn/zInJ/8zJyf/NCcn/zYnKP88LC3/x8PD////
|
||||
/////////v7+//j4+P/4+Pj/1tPU/0g6O/8zJib/Mycn/zIoKP8xKCj/Lycn/i8nJ1wvJycALycoAC8o
|
||||
KF0vKCj+MCcn/zEoKP8yKCj/Mycn/zUoKP86Li7/x8TE////////////////////////////6+rq/1RK
|
||||
Sv8xJib/Micn/zEnKP8wJyj/Lycn/i8oKFwvKCgALicnAC4nJ14vKCj+Lygo/zAoKP8wKCj/MScn/zEn
|
||||
J/85Li7/x8XF////////////////////////////9fX1/2JbW/8vJSX/MSgo/y8nJ/8wKCj/Lygo/i8o
|
||||
KFwvKCgALigoAC4oKFkuJyj9Licn/y8nJ/8wKCj/MCcn/zAnJ/80Kyv/gHp6/6Cbm/+empr/npqa/56a
|
||||
mv+fmpr/m5eX/1BJSf8uJib/MCgo/y8nJ/8uJyf/Licn/S4oKFcuKCgAMCoqADErKyouKCnXLicn/y4n
|
||||
J/8wKCj/Lycn/y8nJ/8wKCj/LyYm/y4lJf8uJSX/LiUl/y4lJf8vJib/LSUl/y8nJ/8vKCj/Lygo/y4n
|
||||
J/8uKCj/Ligo1jArKykvKioA/wD/APwAPwDgAAcAgAABAIAAAQCAAAEAgAABAIAAAQCAAAEAgAABAIAA
|
||||
AQCAAAEAgAABAIAAAQCAAAEAgAABAIAAAQCAAAEAgAABAIAAAQCAAAEAgAABAIAAAQCAAAEAKAAAACAA
|
||||
AABAAAAAAQAgAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAABQSUkAMSgoADgwMAo1LCxEMyoqpjEoKPUwKCj0MikppTQsLEM5MDEKMSgoAFNO
|
||||
TgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAABMQEAAc2RjADowMBc0KipaMikpsTIoKO0xJyf/LyUl/y8lJf8wJib/Migo7TIp
|
||||
KbA0KipZOS8vFnVnZwBNQUEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAP///wA4Li8AOjIyBDYsLCw2Kyt9NSoqzzInJ/ovJSX/MSYm/0E3N/5kXFz9XlZW/T0z
|
||||
M/4xJib/MCUl/zEnJ/o0KirPNiwsfDYsLCw8NDQEOTAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAFBKSgAWDQ0AODAwDjQrK0gzKSmgMigo5jIoKP4zKCj/PDIy/mBXV/2YkpL8z83N/fHx
|
||||
8f7u7u7+ycfH/ZOOjvxeVVX9PDEx/jMoKP8yKCj+Migo5TMpKZ80KytHNi8vDh4VFQBMRkYAAAAAAAAA
|
||||
AAAAAAAAAAAAADs0NABDPj4BNCwsHjIqKmoyKSnAMigo9DIoKP8yJyf/Mycn/zUpKf5KQED7bWRk/Hty
|
||||
c/18c3T9e3Jy/Xtxcv19c3T9e3Jy/WtiY/xKQED7NSkp/jMnJ/8zKCj/Mygo/zIoKPQxKCi/MioqaTQt
|
||||
LR1FP0ABOzQ0AAAAAAA/OjoAKR8fADMrK1AwKCjWMCcn/TEnJ/8xJyf/Mycn/zMnJ/80Jyf/NCYn/zQl
|
||||
Jv8xISL/MSAh/zIhIv8yIiP/MiIj/zIiI/8yIiP/MyMk/zQlJv80Jif/Mycn/zMnJ/8zJyf/Micn/zEn
|
||||
J/8wKCj8MCgo1TIqK04qICAAQDo7ADIrKwAzLCwHMCgotTAnJ/8xJyf/MScn/zMoKP81KCn/NCcn/zUm
|
||||
Jv81JSb/Nyco/1FDRP9NPj//PCwt/zUkJf8zIiP/NSQl/zcmJ/83Jyf/NiYm/zUlJv81Jib/NSco/zQo
|
||||
KP8yJyf/Micn/zEnJ/8wJyf/MCgoszMsLAYyKysALycnAC8nJwoxKCi/Migo/zIoKP8zJyj/Mycn/zQn
|
||||
J/81Jib/NSUm/zYlJv85KCn/sqys/+Ti4v/Ev7//oZma/3xxcv9IOTr/NiQl/zcmJv83JSb/NiUm/zUl
|
||||
Jv81Jib/NCcn/zMnJ/8zKCj/Mygo/zEoKP8wKCi+LycnCS8nJwAvJycALycnCjIoKL8zKCj/Mygo/zQo
|
||||
KP8zJyf/NiYn/zYmJ/82JSb/NiUm/zkoKf+7trb/////////////////+vr6/3pub/80IiP/OCYm/zgm
|
||||
J/83JSb/NiUm/zUlJv81Jib/NCcn/zQoKP8zKCj/Mygo/zEoKL0uJycJLycnADAnJwAwJycKMigovzIo
|
||||
KP80KCj/NCco/zUmJv81JSb/NiUm/zclJv83Jib/Oikp/7u2tv/////////////////9/f3/fHFx/zQh
|
||||
Iv83JSb/NyUm/zclJv83Jif/NyYm/zUlJv81Jib/NCgo/zMoKP8yKCj/MigovS8nJwkwJycAMScnADEn
|
||||
JwoxJye/Micn/zMnJ/81Jyf/NSUm/zYlJv83Jib/NyYm/zknJ/88KSr/u7a2//////////////////z8
|
||||
/P98cHD/NiIj/zkmJv84Jib/OCUm/zknJ/84Jif/NiYm/zYmJv80Jyf/Mycn/zInJ/8yKCi9MigoCTIo
|
||||
KAAxJycAMCYmCjIoKL80KCj/NSgo/zYnJ/82Jib/NyYm/zcmJ/83JSb/OCYm/zwpKf+8trb/////////
|
||||
/////////Pz8/3xvcP83IiP/OiYm/zomJ/84JSb/OCYn/zgmJ/83Jib/NiYm/zYmJ/80KCj/NCgo/zMo
|
||||
Kb0zKCgJMygoADInJwAxJycKMicnvzMnJ/80Jyf/NiYm/zYlJv83JSb/NyUm/zglJv85JSb/PCgp/7y2
|
||||
tv/////////////////8/Pz/fG5v/zgiI/86JSb/OSUm/zklJv84Jib/NyUm/zYlJv82JSb/NSUm/zQn
|
||||
J/8zKCj/MigovTEoKAkyKCgAMygoADIoKAozKCi/NCgo/zQmJ/81JSb/NiYm/zclJv83JSb/OSYn/zsm
|
||||
J/88KCn/vLa2//////////////////z8/P97bW7/OSIj/zolJv85JSb/OyYn/zomJ/84Jib/NiUm/zcm
|
||||
Jv82Jib/NScn/zMnJ/8yJye9MSgoCTIoKAAzKCgAMigoCjMoKL80KCj/NSYn/zYlJv83Jib/NyUm/zcl
|
||||
Jv87Jyj/PSco/zwoKf+8trb/////////////////+/v7/3psbf85IiP/OyUm/zolJv88Jyj/PCgo/zgm
|
||||
Jv82JSb/NiYm/zYmJv81Jif/Mycn/zMnJ70xKCgJMicnADInJwAxJycKMycnvzQnKP81Jib/NiYm/zcm
|
||||
Jv83Jib/NyUm/zomJ/86Jib/PSgp/7y2tv/////////////////7+/v/emtr/zgiIv87JSb/OiUm/zsm
|
||||
J/85Jif/OCYm/zclJv83Jib/NiUm/zUmJ/8zJyf/MygovTEoKAkyKCgAMScnADAnJwoyJye/NSgo/zUm
|
||||
J/82Jib/NyYm/zcmJv84JSb/OSYm/zklJv89KSn/vba2//////////////////7+/v/Jw8P/raWl/6+n
|
||||
p/9xZGT/OCQl/zglJv84Jif/OCYn/zcmJv81JSb/Nicn/zQnJ/8zKCi9MSgoCTIoKAAxJycAMCcnCjIn
|
||||
J780Jyf/NSYm/zUlJv82JSb/NyUm/zclJv84JSb/OSUm/zwoKf+8trb/////////////////////////
|
||||
/////////////5mQkP83IyP/OCUm/zclJv83Jib/NyYm/zUlJv81Jif/Mycn/zInJ70wJycJMScnADEn
|
||||
JwAwJycKMicnvzMnJ/81Jif/NSUm/zcmJv84Jif/OCYm/zclJv85JSb/PSkp/7y2tv//////////////
|
||||
////////////////////////m5KS/zYjI/84JSb/OCYn/zcmJv82JSb/NiUm/zUmJ/8zJyf/MicnvTAn
|
||||
JwkxJycAMScnADAnJwozKCi/NCgo/zQnJ/81JSb/NiUm/zcmJ/83JSb/NyUm/zglJv88KCn/vLa2////
|
||||
//////////////////////////////////+hmJn/NiMk/zglJv83JSb/NyYm/zYlJv82Jib/NScn/zMo
|
||||
KP8yJye9MCcnCTEnJwAxJycAMScnCjMoKL80KCj/NSgo/zYmJ/81JSb/NyYn/zcmJ/83JSb/OCUm/zso
|
||||
Kf+8trb///////////////////////b19f/v7e7/8fHx/6CYmf83JSX/NyUm/zYlJv82JSb/NSUm/zYm
|
||||
J/81KCj/NCgo/zMoKL0xJycJMScnADEnJwAxJycKMigovzMoKP80KCj/NScn/zUlJv82JSb/NiUm/zcm
|
||||
Jv84Jib/Oigp/7u2tv/////////////////+////m5KS/1lKS/9cTU7/TT4+/zgmJv83Jif/NyYm/zYl
|
||||
Jv81JSb/NScn/zQoKP8zKCj/MigovTEnJwkxJycAMCcnAC8nJwoxJye/Micn/zMnJ/80Jyf/NSYm/zUl
|
||||
Jv82JSb/NyUm/zgmJ/87KSr/u7a2//////////////////7+/v+AdXb/Mh8g/zUjJP82JCX/NyUm/zgn
|
||||
J/83Jif/NiUm/zUmJ/80Jyf/Mycn/zInJ/8yKCi9MCgoCTEoKAAvJycALSYmCjEoKL8yKCj/Mygo/zUo
|
||||
KP80Jyf/NiYn/zYmJ/82JSb/NyYn/zopKf+7trb//////////////////f39/4B0df8zISH/NyUl/zcl
|
||||
Jv82JSb/NyYn/zYmJ/82Jif/NSco/zQoKP8zKCj/Migo/zIoKL0wKCgJMSgoAC8nJwAvJycKLycnvzEn
|
||||
J/8yKCj/Mygo/zQnJ/80Jyf/NSUm/zUlJv82JSb/OSgp/7u2tv/////////////////9/f3/i4GC/0Y2
|
||||
N/9IODn/RTY3/zkpKv81JSb/NSYm/zQnJ/8zJyf/Micn/zInJ/8xKCj/MSgovTAoKAkwKCgAMCgoADEo
|
||||
KAowKCi/MCgo/zEnJ/8xJyf/Mycn/zMnJ/80Jyf/Nicn/zYmJ/84KCn/u7a2////////////////////
|
||||
///q6en/3dvb/93a2v/T0ND/XlJS/zQkJf80Jyf/Mycn/zMoKP8yKCj/Migo/zAnJ/8vJye9MCgoCTAo
|
||||
KAAvKCgALygoCi8oKL8wKCj/MCcn/zEnJ/8yKCj/Micn/zMnJ/82KSn/Nygp/zgpKf+6trb/////////
|
||||
//////////////////////////////z8/P95cHD/MyYm/zQoKP8yJyf/Mico/zEoKP8wKCj/Lycn/y8n
|
||||
J70vJycJLycnAC8oKAAvKCgKLycovy8nJ/8vJyf/MCgo/zIoKP8yKCj/Micn/zQoKP81KCj/Nioq/7q2
|
||||
tv///////////////////////////////////////////4yFhf8xJSX/Migo/zEnJ/8xJyf/MCcn/zAn
|
||||
J/8vJyf/LygovS8oKAkvJygALicnAC0nJwouJye/MCgo/y8oKP8wKCj/MCgo/zEoKP8xJyf/Micn/zIn
|
||||
J/82Kyv/ure3////////////////////////////////////////////oZyd/zAmJv8yKCj/Migo/zAo
|
||||
KP8vJyf/MCgo/y8oKP8vKCi9LigoCS4oKAAtJycALScnCi0nJ78uKCj/Licn/y8nJ/8vJyf/MCcn/zAn
|
||||
J/8xJyf/MScn/zQqKv+sqKj/7e3t/+rq6v/q6ur/6urq/+rq6v/q6en/6urp/+3t7f+no6P/Mikp/zAn
|
||||
J/8wKCj/MCgo/y8nJ/8vKCj/Licn/y4nJ74uKCgJLigoADMtLQA1LzAFLykprS4nJ/8uJyf/Licn/y8o
|
||||
KP8wKCj/MCcn/y8nJ/8wJyf/MSgo/0Y+Pv9RSUn/UUhI/1FISf9RSEn/UEhI/1FJSf9RSUn/UElJ/0U+
|
||||
Pv8wKCj/MCgo/y8oKP8vJyf/Licn/y4nJ/8tJyf/LigoqzQvLwQyLC0AQTw9ACslJQAxKytRLygp5S4n
|
||||
J/8uJyf/Lygo/zAoKP8vKCj/Lycn/zAnJ/8wKCj/LyYm/y0lJf8uJSX/LiUl/y4lJf8tJSX/LiUl/y8m
|
||||
Jv8tJSX/LiYm/y8nJ/8vKCj/Lygo/y4nJ/8uKCj/Ligo/y4oKOQwKytPKyQkAEM/PwD/8A///8AD//4A
|
||||
AH/4AAAfwAAAA8AAAAOAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAA
|
||||
AAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABwAAAAygA
|
||||
AAAwAAAAYAAAAAEAIAAAAAAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABFP0AAAAAAADsz
|
||||
MxQ1LS1bMioqwDAoKPwwKCj8MSkpvzMsLFk4MTIUAAAAAEQ/PwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPzc3AEQ8
|
||||
PAM4Li4kNCsrcDQqKsQyKSn1Migo/zIoKP8xKCj/MCcn/zEoKPUzKirDNCsrbjcuLyNDPDwCPjY2AAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAd29vAC4j
|
||||
IwBDODgKNy0tPzQqKpMyKCjeMScn/TIoKP8yJyf/MScn/zEnJ/8xJyf/MScn/zEnJ/8xJyf/Migo/TIo
|
||||
KN00KiqRNy0tPUE3NwoqICEAioODAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEU9
|
||||
PgBUT08BOjExGTkuL144LS21Mykp8DInJ/8xJyf/MScn/zEnJ/8wJSX/Mygo/kE3N/08MzP9MCYm/zAl
|
||||
Jf8xJyf/Migo/zEnJ/8xJyf/Mykp7zcsLLM6Ly9cOjExGF1XWAFHP0AAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMPf
|
||||
3wA4Ly8AQDo6BTcuLi80KiqANCkp0TMpKfozKSn/Mygo/zEnJ/8wJSX/Micn/kI3N/1oYGD8oJub/NHP
|
||||
z/3Ixsb8lI6O/GFYWPw/NDT9Micn/zAlJf8xJib/Migo/zMoKf80KSn6NCoq0DQrK343Li8uPDY2BTcw
|
||||
MAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AABMRkYAAAAAADozMw81LS1LMyoqojIoKOcxJyf+MScn/zIoKP8yJyf/NCkp/kE2Nv1kXFz8mpaW+9DP
|
||||
z/zz8/P+/////////////////v7+/+/v7/7KyMj8lpGR+2JaWvxANTX9NCkp/jMoKP8yJyf/MScn/zIo
|
||||
KP4yKCjmNCoqoDQsLEk5MjIPEAUFAE1ISAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAPzg4AEY/PwI2Ly8iNCwsbDIqKsEyKCj1Migo/zInJ/8yJyf/Mygo/zMoKP8zJyf/PTMz+mJb
|
||||
W/mGgID7lpCQ+5eRkfyWj5D8lo+P/JaPj/yWj4/8lo+P/JeQkPyYkZL8lY+P+4R/f/thWlr5PzU1+jQo
|
||||
KP4zJyf/Micn/zMpKf8zKCj/Mygo/zEoKPQxKSnANCwsazkwMSFHQkECQDk5AAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAD03OABPTE4BNS0uLTIqKo0wKCjbMCcn/DEnJ/8yJyf/Micn/zInJ/8yJyf/Mycn/zMn
|
||||
J/80KCj/NCcn/zUnJ/80JSb/NCQl/zMjJP8zIyT/MyMk/zMjJP8zIyT/MyMk/zMjJP8zIyT/MyQk/zQl
|
||||
Jf80Jyf/NCgo/zMnJ/80KCj/Mycn/zMoKP8zKCj/Migo/zInJ/8wJyf/MCgo/DEpKdoyKiqMNS4uLFZV
|
||||
VAE+ODgAAAAAAAAAAAAAAAAAQj09ADEpKQA1LS09MSkp2zAnJ/8wJyf/MCcn/zEnJ/8xJyf/Micn/zMo
|
||||
KP8zJyf/Mycn/zQnJ/80Jif/NSUm/zUlJv81JSb/NSUm/zYlJv82JSb/NiUm/zYlJv82JSb/NSUm/zUl
|
||||
Jv81JSb/NSUm/zYmJv81JSb/NSYm/zQmJ/8zJyf/Mycn/zMnJ/8zJyf/Micn/zIoKP8xJyf/MScn/y8n
|
||||
J/8wJyf/MSkp2TQtLTowKSkARUBAAAAAAAAAAAAAODExAJ2oqAAxKSmXMCcn/zAnJ/8xJyf/Micn/zEn
|
||||
J/8yJyj/NSkp/zUpKf80KCj/NCYn/zUlJv81JSb/NiUm/zcmJ/85Kir/Nycn/zQiI/80IiP/NSQl/zYl
|
||||
Jv82JSb/NiUm/zYlJv82Jib/OCcn/zcnJ/82Jif/NSUm/zUlJv81Jib/NCcn/zUoKP80KCj/Mygo/zIn
|
||||
J/8xJyf/Micn/zEnJ/8wJyf/MCcn/zEpKZMAAAAAODExAAAAAAAAAAAALycnAC4mJgMwKCirMCgo/zAn
|
||||
J/8xJyf/MScn/zInJ/8zJyf/NSgo/zQoKP81Jyf/NSUm/zUlJv82Jib/NiUm/zYlJv+BeHj/raen/4d+
|
||||
f/9nWlv/Tj9A/z0tLv81JCX/NCIj/zYlJv83Jib/OCYn/zcmJ/83Jib/NSUm/zUlJv82Jib/NSUm/zUn
|
||||
J/80KCj/Mycn/zMnJ/8yJyf/Migo/zEnJ/8wJyf/Lycn/y8nJ6kvJycDLycnAAAAAAAAAAAALycnACwl
|
||||
JQMxKCirMikp/zIoKP8zKCj/Mygo/zMoKP8zJyf/Mycn/zUmJ/81Jib/NSUm/zUlJv82Jib/NiUm/zUk
|
||||
Jf+hm5v///////39/f/z8vL/397e/8O/v/+hmpv/dmxs/z4tLv82JCX/NiUm/zcmJv83JSb/NiUm/zYl
|
||||
Jv82Jib/NSUm/zUlJv81Jyf/NCcn/zMnJ/80KCj/NCkp/zMoKP8yKCj/MSgo/zAoKKgsJSUDLycnAAAA
|
||||
AAAAAAAALycnACwlJQMxKCirMigp/zMoKP8zKCj/NCgo/zQoKP8zJyf/NCYn/zcnJ/82Jif/NiYm/zYl
|
||||
Jv83Jib/NiUm/zUkJf+gmpr/////////////////////////////////4N7e/09AQP81IyT/NyUm/zgn
|
||||
J/84Jif/NyYm/zYlJv83Jib/NSUm/zUlJv81JSb/NCYn/zMnJ/80KCj/NCgp/zMoKP8zKCj/Migo/zAo
|
||||
KKgqJCQDLycnAAAAAAAAAAAALycnAColJQMyKCirMygp/zMoKP8zKCj/NSgo/zQoKP80Jif/NSUm/zUl
|
||||
Jv82Jib/NiYm/zcmJv83Jib/NyUm/zYkJf+hmpr/////////////////////////////////4uDh/09A
|
||||
Qf81IyT/NyUm/zclJv84Jib/NyYm/zcmJv83Jib/NiUm/zYlJv82Jib/NSUm/zQmJ/80KCj/NSgo/zMo
|
||||
KP8zKCj/Mygo/zEoKKgpJCQDLycnAAAAAAAAAAAAMCcnAC0mJgMyKCirMigo/zIoKP80KCj/NCgo/zQn
|
||||
J/81JSb/NSUm/zUlJv82JSb/NiUm/zclJv84Jif/OSYn/zckJf+gmZr/////////////////////////
|
||||
////////4uDg/08/QP82IyT/NyUm/zclJv83JSb/NyUm/zclJv83Jif/OCYn/zcmJv81JSb/NiUm/zUl
|
||||
Jv80Jyf/NCgo/zMoKP8yKCj/Migo/zEoKKgtJiYDMCcnAAAAAAAAAAAAMScnADEnJwMxJyerMScn/zIn
|
||||
J/8zJyf/NCcn/zUmJ/82JSb/NSUm/zYlJv83Jib/NiUm/zcmJv85Jyf/Oicn/zglJf+hmZr/////////
|
||||
////////////////////////4d/f/1A/QP84JCX/OCUm/zglJv84Jib/NyUm/zgmJv85Jyf/OCcn/zgm
|
||||
J/82JSb/NSUm/zUlJv80Jib/Mycn/zMnJ/8yJyf/Micn/zIoKKgyKCgDMigoAAAAAAAAAAAAMScnADAm
|
||||
JgMxJyerMykp/zMoKP80Jyj/NSgo/zYmJ/82Jib/NSUm/zgmJ/85Jyf/NyUm/zgmJv86Jyf/Oicn/zgl
|
||||
Jf+hmZr/////////////////////////////////4d/f/1A/P/84JCX/OSUm/zsmJ/87Jyf/NyUm/zgm
|
||||
Jv85Jyf/OCcn/zgmJ/83Jif/NyYn/zcnJ/81Jib/NSgo/zQoKP8zKCj/Mygo/zMoKKgyJycDMigoAAAA
|
||||
AAAAAAAAMScnADAmJgMxJyerMygo/zQoKP80KCj/Nigo/zcmJ/82Jib/NiUm/zcmJv83Jib/NyUm/zgl
|
||||
Jv84Jib/OSYm/zklJf+hmZr/////////////////////////////////4N7e/1A/P/85JCX/OSUm/zom
|
||||
Jv86Jib/OCUm/zglJv84Jib/OCYm/zcmJ/82JSb/NiUm/zUlJv81JSb/Nigo/zQoKP80KCj/NCkp/zMo
|
||||
KKgzKSkDMykpAAAAAAAAAAAAMScnADEnJwMxJyerMicn/zMnJ/80Jyf/Nicn/zYmJv82JSb/NyUm/zYl
|
||||
Jv82JSb/NyUm/zclJv84JSb/OSUm/zgkJf+impr/////////////////////////////////4N3d/1A+
|
||||
Pv85JCX/OiUm/zklJv85JSb/OSUm/zglJv84JSb/NyUm/zclJv83JSb/NiUm/zYlJv81JSb/NSYm/zMn
|
||||
J/80Jyj/Mygo/zIoKKgxJycDMigoAAAAAAAAAAAAMygoADQpKQMzKCirMygo/zQoKP80Jyf/NSUm/zUl
|
||||
Jv82JSb/NyYm/zcmJv83JSb/OCUm/zkmJ/86Jif/OiYn/zgkJf+impr/////////////////////////
|
||||
////////393d/1A9Pf86JCX/OyYm/zomJv85JSb/OiUm/zomJ/85Jif/OCYn/zclJv82JSb/NiUm/zcm
|
||||
J/82Jif/NiYn/zUoKP80Jyf/Micn/zEnJ6gzKCgDMigoAAAAAAAAAAAAMigoADMpKQMyJyerMycn/zQo
|
||||
KP80Jyf/NSUm/zUlJv83Jib/NyYm/zYlJv83JSb/OCYm/zomJ/87Jif/OyYn/zgkJf+imZr/////////
|
||||
////////////////////////3tzc/088Pf87JCX/PCYm/zolJv85JSb/OiYm/zsmJ/85Jif/OSYn/zgl
|
||||
Jv82JSb/NiUm/zcmJ/82Jib/NSUm/zUnJ/8zJyf/Mycn/zInJ6g0KSkDMygoAAAAAAAAAAAAMygoADIp
|
||||
KQMyKCirNCgo/zQoKP80Jif/NSUm/zUlJv82JSb/NyYm/zYlJv83JSb/OCYm/z0oKP8/KSn/OyYn/zgk
|
||||
Jf+imZr/////////////////////////////////3tvc/088PP86JCX/PCYm/zslJv85JSb/OiYm/z4o
|
||||
KP8+KSn/OSYn/zglJv83JSb/NiUm/zcmJv82Jib/NiYm/zUnJ/8zJyf/Mycn/zInJ6gvJycDMScnAAAA
|
||||
AAAAAAAAMygoADIoKQMzKCirNCgo/zQoKP81Jif/NSUm/zYmJ/84Jif/OCYn/zclJv83JSb/OCYn/zsn
|
||||
J/89Jyj/OyYn/zkkJf+impr/////////////////////////////////3tvb/088PP87JSX/PCYn/zsl
|
||||
Jv86JSb/OiYm/zwnJ/88Jyj/OSYn/zglJv83JSb/NiUm/zcmJv82Jib/NiYn/zUmJ/8zJyf/Myco/zMo
|
||||
KKgvKCcDMigoAAAAAAAAAAAAMScnAC8nJwMyJyerMycn/zQnJ/81Jib/NSUm/zYmJv82JSb/NyYm/zcl
|
||||
Jv83JSb/OCUm/zomJ/86Jib/OiYm/zkkJf+impr/////////////////////////////////3dra/0w4
|
||||
OP83ISL/OSMj/zkiI/84IyT/OiUm/zomJ/85Jib/OCYm/zglJv83JSb/NyYm/zcmJv81JSb/NSUm/zUm
|
||||
J/8zJyf/Mygo/zMoKKgsJSUDMScnAAAAAAAAAAAAMScnAC8nJwMyJyerNCgo/zYpKf81Jif/NSUm/zYm
|
||||
J/83Jib/NyYn/zclJv84JSb/OCYm/zkmJv85JSb/OSUm/zslJf+jmpr/////////////////////////
|
||||
////////7Ovr/5mOj/+MgIH/jYGC/46Cg/9yZWX/PCgp/zolJv84JSb/NyUm/zkmJ/84Jif/OCYn/zYl
|
||||
Jv81JSb/NiYn/zcoKP80KCj/Mygo/zMoKKguJiYDMicnAAAAAAAAAAAAMScnAC8nJwMyJyerNCgo/zQo
|
||||
KP81Jif/NSUm/zYmJ/83Jib/NyYn/zclJv83JSb/OCUm/zklJv86Jib/OSUm/zolJf+jmpr/////////
|
||||
///////////////////////////////////+//7//v////////+/urr/Pisr/zklJv85Jib/NyUm/zkm
|
||||
J/84Jif/OCYn/zYlJv81JSb/NiYm/zUnJ/8zJyf/Mycn/zMoKKguJycDMicoAAAAAAAAAAAAMScnADAn
|
||||
JwMyJyerMycn/zMnJ/80Jif/NSUm/zUlJv82JSb/NiUm/zclJv83JSb/OCUm/zglJv85JSb/OSUm/zgk
|
||||
Jf+imZr////////////////////////////////////////////////////////////Au7v/Piss/zkl
|
||||
Jv84JSb/NyUm/zclJv83JSb/NiUm/zclJv81JSb/NSUm/zQmJ/8zJyf/Mycn/zEnJ6gvJycDMScnAAAA
|
||||
AAAAAAAAMScnADAnJwMyJyerMycn/zQoJ/80Jyf/NiUm/zUlJv82JSb/OCYn/zgmJ/84Jib/NyUm/zcl
|
||||
Jv85JSb/OSUm/zklJf+impr/////////////////////////////////////////////////////////
|
||||
///Cvb7/Piss/zglJv83JSb/OCUm/zgmJ/83Jib/NiUm/zYlJv81JSb/NiYm/zQnJ/80KCj/Mycn/zEn
|
||||
J6gwJycDMScnAAAAAAAAAAAAMScnAC8mJgMyJyerMygo/zMnJ/80Jyf/NSUm/zUlJv82Jib/OCcn/zgn
|
||||
J/84Jif/NyUm/zclJv85Jib/OiUm/zolJf+impr/////////////////////////////////////////
|
||||
///////////////////GwsL/QC0u/zglJv84Jib/OCUm/zkmJ/83Jif/NyYm/zYlJv81JSb/NiYm/zQn
|
||||
J/8zJyf/Micn/zEnJ6gxJycDMScnAAAAAAAAAAAAMScnAC4lJQMyKCirNCkp/zQoKP80KCj/NSYn/zUl
|
||||
Jv81JSb/NiUm/zYlJv83JSb/NyUm/zclJv84Jib/OSUm/zgkJf+impr/////////////////////////
|
||||
///////////////////////////////////MyMj/Qi8w/zclJf84Jib/NyUm/zclJv83JSb/NiUm/zYl
|
||||
Jv82Jib/Nicn/zQoKP80KCj/Mygo/zIoKKgvJiYDMScnAAAAAAAAAAAAMScnAC4lJQMzKCirNCkp/zUo
|
||||
KP81KCj/Nico/zYmJv81JSb/NiUm/zgmJ/83Jif/OCYm/zclJv84Jib/OCUm/zgkJf+impr/////////
|
||||
///////////////////////////////////////////////////V0tL/RjU1/zckJf84Jib/NyUm/zYl
|
||||
Jv83JSb/NiUm/zUlJv82Jib/Nigo/zUoKP80KCj/Mygo/zIoKKguJSUDMScnAAAAAAAAAAAAMScnAC4l
|
||||
JQMzKCirMygo/zQoKP80KCj/NSgo/zYmJ/81JSb/NSUm/zcmJv83Jif/NyYm/zglJv84Jib/NyUm/zck
|
||||
Jf+hmpr/////////////////////////////////+Pf3/8G8vP+yrK3/s62t/7Surv+dlpb/QzMz/zcl
|
||||
Jf84Jib/NyUm/zclJv82JSb/NSUm/zUlJv82Jif/NSgo/zUoKP80KCj/Mygo/zIoKKgtJCQDMScnAAAA
|
||||
AAAAAAAAMScnAC8mJQMyKCirMigo/zMoKP80KCj/NCgo/zUmJ/81JSb/NSUm/zYlJv82JSb/NiUm/zcm
|
||||
Jv84Jib/OCYn/zYkJf+hmZr/////////////////////////////////6ejo/1lJSv84JSb/OSco/zkn
|
||||
KP85Jyj/OCYm/zglJv84Jif/NyYn/zcmJv82JSb/NSUm/zUlJv81Jyf/NCgo/zQoKP8zKCj/Migo/zIo
|
||||
KKgvJSUDMScnAAAAAAAAAAAAMCcnAC8nJwMxJyerMScn/zEnJ/8zJyf/Mycn/zQnJ/81Jib/NSUm/zUl
|
||||
Jv82JSb/NiUm/zcmJv84Jyf/OScn/zclJf+gmZr/////////////////////////////////5+bm/1VG
|
||||
R/82IyT/NyUm/zclJv83JSb/NyUm/zcmJv84Jif/OCcn/zcmJ/81JSb/NSUm/zUmJv8zJyf/Mycn/zMn
|
||||
J/8xJyf/MScn/zEoKKgvKCcDMSgoAAAAAAAAAAAALycnAC0nJgMwJyerMigo/zInJ/8yJyf/NCgo/zQo
|
||||
KP80Jyf/NSUm/zYmJ/83Jyf/NiUm/zcmJv84Jyf/OScn/zclJf+gmZr/////////////////////////
|
||||
////////5uXl/1RFRv82IyT/NyUm/zkmJ/85Jyf/NyUm/zcmJv84Jyf/OCcn/zcmJ/82Jif/NiYn/zUo
|
||||
KP8zJyf/NCgo/zInJ/8xJyf/Migo/zEoKKguKCgDMCgoAAAAAAAAAAAALycnAC0mJgMvJyerMykp/zIo
|
||||
KP8yKCj/NCkp/zUoKP80KCj/NCYn/zYmJ/83Jyf/NSUm/zYmJv83Jif/NyYm/zYlJf+gmZr/////////
|
||||
////////////////////////5eTk/1RERf82JCX/NyUm/zgmJ/84Jyf/NiUm/zcmJv83Jif/NiYm/zYm
|
||||
J/81Jib/NScn/zQoKP80Jyf/NSkp/zIoKP8yKCj/Mykp/zEoKKgwKCgDMSgoAAAAAAAAAAAALycnAC8n
|
||||
JwMvJyerMCcn/zEnJ/8yKCj/Mygp/zQoKP80KCj/Mycn/zQmJ/81JSb/NSUm/zUlJv82JSb/NyUm/zUk
|
||||
Jf+gmZr/////////////////////////////////5OLi/09AQf8yISH/NCIj/zMiI/8zIiP/NCMk/zYl
|
||||
Jv81JSb/NSUm/zUmJv80Jif/Mycn/zMnJ/8zJyf/Micn/zEnJ/8yKCj/MSgo/zEoKKgwKCgDMSgoAAAA
|
||||
AAAAAAAAMCgoADEoKAMwKCirMCgo/zEoKP8xJyf/MScn/zInJ/8zJyf/NCgo/zQnJ/80Jif/NSUm/zYm
|
||||
J/82Jif/NiUm/zUkJf+gmpr/////////////////////////////////8O/v/5uTlP+If3//h35//4V8
|
||||
ff+Ee3z/aV5f/zgoKf82Jif/NSUm/zQmJ/80Jyf/Mycn/zQoKP8yKCj/Migo/zIoKP8wJyf/Lycn/y8n
|
||||
J6gvJycDLycnAAAAAAAAAAAAMCgpADIpKgMwKCirMCgo/zEoKP8xKCj/MScn/zInJ/8yKCj/Mycn/zMn
|
||||
J/8zJyf/NScn/zYnJ/82Jif/NiYn/zQkJf+gmZr/////////////////////////////////////////
|
||||
///+/v7//v7+//3+/v//////yMXF/z8wMf81Jib/NSgo/zQnJ/8zJyf/Mycn/zMoKP8yKCj/Migo/zIo
|
||||
KP8wJyf/Lycn/y8nJ6gzKioDMSgpAAAAAAAAAAAALygoAC8oKAMvJyerLycn/zAnJ/8vJyf/MCcn/zEn
|
||||
J/8xJyf/Micn/zInJ/8zJyf/NCgo/zcpKf84KSn/NiYn/zQkJf+gmZr/////////////////////////
|
||||
////////////////////////////////////////2tjY/0k8Pf82KSn/NCgo/zQnJ/8zJyf/Micn/zIo
|
||||
KP8yJyf/MCcn/zAoKP8vJyf/Lycn/y4nJ6guJycDLicnAAAAAAAAAAAAMCgpADEpKgMwKCirMCgo/zAo
|
||||
KP8vJyf/MCcn/zEoKP8yKCj/Mygo/zInJ/8yJyf/NCgo/zYpKv83Kir/NSgo/zMlJf+gmpr/////////
|
||||
////////////////////////////////////////////////////////6Ofn/1VLS/81KCj/NCgo/zMn
|
||||
J/8xJyf/MScn/zInKP8yKCj/MSgo/zAoKP8vJyf/Lycn/y8oKKguJycDLygoAAAAAAAAAAAALicnAC4n
|
||||
JwMuJyerLicn/y8nJ/8vJyf/MCcn/zAoKP8xKCj/Migo/zInJ/8xJyf/Mygo/zQoKP80KCj/NCgo/zIm
|
||||
Jv+fmpr/////////////////////////////////////////////////////////////////8vLy/2Na
|
||||
Wv8xJSX/Mygo/zEnJ/8yJyf/Micn/zEoKP8vJyf/Lycn/y8nJ/8uJyf/Lygo/y8oKKgtJiYDLycnAAAA
|
||||
AAAAAAAALicnAC0nJwMuJyerLygo/zApKf8vKCj/MCcn/zAoKP8wJyf/MSgo/zEnJ/8xJyf/Micn/zIo
|
||||
KP8yJyf/Mycn/zMnJ/+fmpr/////////////////////////////////////////////////////////
|
||||
////////+vr6/3Rubv8uJCT/MScn/zIoKP8yKCj/MSgo/zAnJ/8vJyf/MCgo/zApKf8vKCj/Lygo/y8o
|
||||
KKgsJiYDLicnAAAAAAAAAAAALScnAC0nJwMtJyerLygo/zApKf8vKCj/Lycn/zAoKP8wKCj/MCgo/zAn
|
||||
J/8xJyf/Micn/zInJ/8yJyf/MScn/zInJ/+gm5v/////////////////////////////////////////
|
||||
/////////////////////////////4mEhP8vJCT/MScn/zIoKf8yKSn/MSgo/zAnJ/8vJyf/Lygo/zAp
|
||||
Kf8vKCj/Lico/y8oKKgsJycDLigoAAAAAAAAAAAALScnAC0nJwQtJyerLScn/y4nJ/8uJyf/Licn/y4n
|
||||
J/8vJyf/Lycn/zAnJ/8vJyf/MCcn/zEnJ/8xJyf/MScn/zAmJv+UkJD/7e3t/+zr6//r6+v/6+vr/+vr
|
||||
6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/7e3t/5KOjv8wJib/Lycn/y8nJ/8wKCj/MCgo/y8o
|
||||
KP8uJyf/Licn/y4nJ/8uJyf/LScn/y0nJ6ktJycDLScnAAAAAAAAAAAANC8vAEM/PwEvKSmgLigo/y4n
|
||||
J/8uJyf/Lycn/y4nJ/8uJyf/Lygo/zAoKP8wJyf/Lycn/y8nJ/8vJyf/MCcn/zEnJ/9EPDz/Vk5O/1ZN
|
||||
Tf9VTU3/Vk1N/1VNTf9WTU3/Vk1N/1VNTf9VTU3/Vk5O/1ZOTv9VTU3/VE1N/0Q9Pf8vJyf/Lycn/zAn
|
||||
J/8vJyf/Lycn/y8oKP8uJyf/Lygo/y4nJ/8uJyf/LScn/y4oKJ1PTU0BMy4uAAAAAAAAAAAAWlhZACsk
|
||||
JAAyLCxfLigo+C0nJ/8uJyf/Licn/y4nJ/8vKCj/MCkp/zApKf8wKCj/Lycn/y8nJ/8wJyf/MCgo/zEo
|
||||
KP8wJyf/LiUl/y4lJf8uJSX/LyUl/y8lJf8vJSX/LiUl/y4lJf8vJSX/MCYn/zAmJv8uJib/LSUl/y4m
|
||||
Jv8wJyf/MCgo/zAoKP8vKCj/Lygo/y4nJ/8uJyf/Lico/y0nJ/8tJyf/Ligo9zErLFwrJSUAWVdYAAAA
|
||||
AAAAAAAAAAAAADYxMQA5NDQOMSssiy8pKe0uKCj/LScn/y4nJ/8uJyf/Lygo/y8oKP8vKCj/Licn/y8n
|
||||
J/8wKCj/Lycn/zAoKP8wKCj/Lycn/zAnJ/8wJyf/MCgo/zAoKP8wJyf/MCcn/y8nJ/8wJyf/MCgo/zAo
|
||||
KP8wKCj/Lycn/y8nJ/8vKCj/Licn/y8nKP8vJyj/Licn/y4nJ/8uJyf/Ligo/y4oKP8vKSnsMSsriDYx
|
||||
MQ01LzAAAAAAAAAAAAD///AP//8AAP//gAH//wAA//4AAH//AAD/8AAAD/8AAP/AAAAD/wAA/wAAAAD/
|
||||
AAD4AAAAAB8AAOAAAAAABwAA4AAAAAAHAADgAAAAAAcAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAA
|
||||
AAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAAD
|
||||
AADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAA
|
||||
AAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAAD
|
||||
AADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAA
|
||||
AAAAAwAAwAAAAAADAADAAAAAAAMAAOAAAAAABwAA4AAAAAAHAACJUE5HDQoaCgAAAA1JSERSAAABAAAA
|
||||
AQAIBgAAAFxyqGYAAGt6SURBVHja7b15gGZJVSd6Iu73fblW1t479FZ0Nd2IPgefD0XhAQ9lcUFAtmZR
|
||||
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
|
||||
AElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -1,157 +0,0 @@
|
|||
// <auto-generated />
|
||||
//
|
||||
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
|
||||
//
|
||||
// using FModel;
|
||||
//
|
||||
// var challengeBundleIdParser = ChallengeBundleIdParser.FromJson(jsonString);
|
||||
|
||||
namespace FModel.Challenges
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Globalization;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
public partial class ChallengeBundleIdParser
|
||||
{
|
||||
[JsonProperty("export_type")]
|
||||
public string ExportType { get; set; }
|
||||
|
||||
[JsonProperty("QuestInfos")]
|
||||
public QuestInfo[] QuestInfos { get; set; }
|
||||
|
||||
[JsonProperty("BundleCompletionRewards")]
|
||||
public BundleCompletionReward[] BundleCompletionRewards { get; set; }
|
||||
|
||||
[JsonProperty("DisplayStyle")]
|
||||
public DisplayStyle DisplayStyle { get; set; }
|
||||
|
||||
[JsonProperty("DisplayName")]
|
||||
public string DisplayName { get; set; }
|
||||
|
||||
[JsonProperty("SmallPreviewImage")]
|
||||
public LargePreviewImage SmallPreviewImage { get; set; }
|
||||
|
||||
[JsonProperty("LargePreviewImage")]
|
||||
public LargePreviewImage LargePreviewImage { get; set; }
|
||||
}
|
||||
|
||||
public partial class BundleCompletionReward
|
||||
{
|
||||
[JsonProperty("CompletionCount")]
|
||||
public long CompletionCount { get; set; }
|
||||
|
||||
[JsonProperty("Rewards")]
|
||||
public Reward[] Rewards { get; set; }
|
||||
}
|
||||
|
||||
public partial class Reward
|
||||
{
|
||||
[JsonProperty("ItemDefinition")]
|
||||
public LargePreviewImage ItemDefinition { get; set; }
|
||||
|
||||
[JsonProperty("TemplateId")]
|
||||
public string TemplateId { get; set; }
|
||||
|
||||
[JsonProperty("Quantity")]
|
||||
public long Quantity { get; set; }
|
||||
|
||||
[JsonProperty("RewardGiftBox")]
|
||||
public RewardGiftBox RewardGiftBox { get; set; }
|
||||
|
||||
[JsonProperty("IsChaseReward")]
|
||||
public bool IsChaseReward { get; set; }
|
||||
|
||||
[JsonProperty("RewardType")]
|
||||
public string RewardType { get; set; }
|
||||
}
|
||||
|
||||
public partial class LargePreviewImage
|
||||
{
|
||||
[JsonProperty("asset_path_name")]
|
||||
public string AssetPathName { get; set; }
|
||||
|
||||
[JsonProperty("sub_path_string")]
|
||||
public string SubPathString { get; set; }
|
||||
}
|
||||
|
||||
public partial class RewardGiftBox
|
||||
{
|
||||
[JsonProperty("GiftBoxToUse")]
|
||||
public LargePreviewImage GiftBoxToUse { get; set; }
|
||||
|
||||
[JsonProperty("GiftBoxFormatData")]
|
||||
public object[] GiftBoxFormatData { get; set; }
|
||||
}
|
||||
|
||||
public partial class DisplayStyle
|
||||
{
|
||||
[JsonProperty("PrimaryColor")]
|
||||
public ColorChallenge PrimaryColor { get; set; }
|
||||
|
||||
[JsonProperty("SecondaryColor")]
|
||||
public ColorChallenge SecondaryColor { get; set; }
|
||||
|
||||
[JsonProperty("AccentColor")]
|
||||
public ColorChallenge AccentColor { get; set; }
|
||||
|
||||
[JsonProperty("DisplayImage")]
|
||||
public LargePreviewImage DisplayImage { get; set; }
|
||||
}
|
||||
|
||||
public partial class ColorChallenge
|
||||
{
|
||||
[JsonProperty("r")]
|
||||
public double R { get; set; }
|
||||
|
||||
[JsonProperty("g")]
|
||||
public double G { get; set; }
|
||||
|
||||
[JsonProperty("b")]
|
||||
public double B { get; set; }
|
||||
|
||||
[JsonProperty("a")]
|
||||
public long A { get; set; }
|
||||
}
|
||||
|
||||
public partial class QuestInfo
|
||||
{
|
||||
[JsonProperty("QuestDefinition")]
|
||||
public LargePreviewImage QuestDefinition { get; set; }
|
||||
|
||||
[JsonProperty("QuestUnlockType")]
|
||||
public string QuestUnlockType { get; set; }
|
||||
|
||||
[JsonProperty("UnlockValue")]
|
||||
public long UnlockValue { get; set; }
|
||||
|
||||
[JsonProperty("RewardGiftBox")]
|
||||
public RewardGiftBox RewardGiftBox { get; set; }
|
||||
}
|
||||
|
||||
public partial class ChallengeBundleIdParser
|
||||
{
|
||||
public static ChallengeBundleIdParser[] FromJson(string json) => JsonConvert.DeserializeObject<ChallengeBundleIdParser[]>(json, FModel.Challenges.Converter.Settings);
|
||||
}
|
||||
|
||||
public static class Serialize
|
||||
{
|
||||
public static string ToJson(this ChallengeBundleIdParser[] self) => JsonConvert.SerializeObject(self, FModel.Challenges.Converter.Settings);
|
||||
}
|
||||
|
||||
internal static class Converter
|
||||
{
|
||||
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
|
||||
{
|
||||
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
|
||||
DateParseHandling = DateParseHandling.None,
|
||||
Converters =
|
||||
{
|
||||
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
// <auto-generated />
|
||||
//
|
||||
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
|
||||
//
|
||||
// using FModel;
|
||||
//
|
||||
// var itemsIdParser = ItemsIdParser.FromJson(jsonString);
|
||||
|
||||
namespace FModel.Items
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Globalization;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
public partial class ItemsIdParser
|
||||
{
|
||||
[JsonProperty("export_type")]
|
||||
public string ExportType { get; set; }
|
||||
|
||||
[JsonProperty("cosmetic_item")]
|
||||
public string cosmetic_item { get; set; }
|
||||
|
||||
[JsonProperty("CharacterParts")]
|
||||
public string[] CharacterParts { get; set; }
|
||||
|
||||
[JsonProperty("HeroDefinition")]
|
||||
public string HeroDefinition { get; set; }
|
||||
|
||||
[JsonProperty("WeaponDefinition")]
|
||||
public string WeaponDefinition { get; set; }
|
||||
|
||||
[JsonProperty("Rarity")]
|
||||
public string Rarity { get; set; }
|
||||
|
||||
[JsonProperty("DisplayName")]
|
||||
public string DisplayName { get; set; }
|
||||
|
||||
[JsonProperty("ShortDescription")]
|
||||
public string ShortDescription { get; set; }
|
||||
|
||||
[JsonProperty("Description")]
|
||||
public string Description { get; set; }
|
||||
|
||||
[JsonProperty("GameplayTags")]
|
||||
public GameplayTags GameplayTags { get; set; }
|
||||
|
||||
[JsonProperty("SmallPreviewImage")]
|
||||
public PreviewImage SmallPreviewImage { get; set; }
|
||||
|
||||
[JsonProperty("LargePreviewImage")]
|
||||
public PreviewImage LargePreviewImage { get; set; }
|
||||
}
|
||||
|
||||
public partial class GameplayTags
|
||||
{
|
||||
[JsonProperty("gameplay_tags")]
|
||||
public string[] GameplayTagsGameplayTags { get; set; }
|
||||
}
|
||||
|
||||
public partial class PreviewImage
|
||||
{
|
||||
[JsonProperty("asset_path_name")]
|
||||
public string AssetPathName { get; set; }
|
||||
|
||||
[JsonProperty("sub_path_string")]
|
||||
public string SubPathString { get; set; }
|
||||
}
|
||||
|
||||
public partial class ItemsIdParser
|
||||
{
|
||||
public static ItemsIdParser[] FromJson(string json) => JsonConvert.DeserializeObject<ItemsIdParser[]>(json, FModel.Items.Converter.Settings);
|
||||
}
|
||||
|
||||
public static class Serialize
|
||||
{
|
||||
public static string ToJson(this ItemsIdParser[] self) => JsonConvert.SerializeObject(self, FModel.Items.Converter.Settings);
|
||||
}
|
||||
|
||||
internal static class Converter
|
||||
{
|
||||
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
|
||||
{
|
||||
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
|
||||
DateParseHandling = DateParseHandling.None,
|
||||
Converters =
|
||||
{
|
||||
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,199 +0,0 @@
|
|||
// <auto-generated />
|
||||
//
|
||||
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
|
||||
//
|
||||
// using FModel.Quest;
|
||||
//
|
||||
// var questParser = QuestParser.FromJson(jsonString);
|
||||
|
||||
namespace FModel.Quest
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Globalization;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
public partial class QuestParser
|
||||
{
|
||||
[JsonProperty("export_type")]
|
||||
public string ExportType { get; set; }
|
||||
|
||||
[JsonProperty("QuestType")]
|
||||
public string QuestType { get; set; }
|
||||
|
||||
[JsonProperty("bIncludedInCategories")]
|
||||
public bool BIncludedInCategories { get; set; }
|
||||
|
||||
[JsonProperty("Rewards")]
|
||||
public Reward[] Rewards { get; set; }
|
||||
|
||||
[JsonProperty("Objectives")]
|
||||
public Objective[] Objectives { get; set; }
|
||||
|
||||
[JsonProperty("CompletionText")]
|
||||
public string CompletionText { get; set; }
|
||||
|
||||
[JsonProperty("GrantToProfileType")]
|
||||
public string GrantToProfileType { get; set; }
|
||||
|
||||
[JsonProperty("DisplayName")]
|
||||
public string DisplayName { get; set; }
|
||||
|
||||
[JsonProperty("Description")]
|
||||
public string Description { get; set; }
|
||||
|
||||
[JsonProperty("GameplayTags")]
|
||||
public GameplayTags GameplayTags { get; set; }
|
||||
|
||||
[JsonProperty("SmallPreviewImage")]
|
||||
public LargePreviewImage SmallPreviewImage { get; set; }
|
||||
|
||||
[JsonProperty("LargePreviewImage")]
|
||||
public LargePreviewImage LargePreviewImage { get; set; }
|
||||
}
|
||||
|
||||
public partial class GameplayTags
|
||||
{
|
||||
[JsonProperty("gameplay_tags")]
|
||||
public string[] GameplayTagsGameplayTags { get; set; }
|
||||
}
|
||||
|
||||
public partial class LargePreviewImage
|
||||
{
|
||||
[JsonProperty("asset_path_name")]
|
||||
public string AssetPathName { get; set; }
|
||||
|
||||
[JsonProperty("sub_path_string")]
|
||||
public string SubPathString { get; set; }
|
||||
}
|
||||
|
||||
public partial class Objective
|
||||
{
|
||||
[JsonProperty("BackendName")]
|
||||
public string BackendName { get; set; }
|
||||
|
||||
[JsonProperty("ObjectiveStatHandle")]
|
||||
public ObjectiveStatHandle ObjectiveStatHandle { get; set; }
|
||||
|
||||
[JsonProperty("AlternativeStatHandles")]
|
||||
public object[] AlternativeStatHandles { get; set; }
|
||||
|
||||
[JsonProperty("ItemEvent")]
|
||||
public string ItemEvent { get; set; }
|
||||
|
||||
[JsonProperty("bHidden")]
|
||||
public bool BHidden { get; set; }
|
||||
|
||||
[JsonProperty("bRequirePrimaryMissionCompletion")]
|
||||
public bool BRequirePrimaryMissionCompletion { get; set; }
|
||||
|
||||
[JsonProperty("bCanProgressInZone")]
|
||||
public bool BCanProgressInZone { get; set; }
|
||||
|
||||
[JsonProperty("bDisplayDynamicAnnouncementUpdate")]
|
||||
public bool BDisplayDynamicAnnouncementUpdate { get; set; }
|
||||
|
||||
[JsonProperty("DynamicStatusUpdateType")]
|
||||
public string DynamicStatusUpdateType { get; set; }
|
||||
|
||||
[JsonProperty("LinkVaultTab")]
|
||||
public string LinkVaultTab { get; set; }
|
||||
|
||||
[JsonProperty("LinkToItemManagement")]
|
||||
public string LinkToItemManagement { get; set; }
|
||||
|
||||
[JsonProperty("ItemReference")]
|
||||
public LargePreviewImage ItemReference { get; set; }
|
||||
|
||||
[JsonProperty("ItemTemplateIdOverride")]
|
||||
public string ItemTemplateIdOverride { get; set; }
|
||||
|
||||
[JsonProperty("LinkSquadID")]
|
||||
public string LinkSquadId { get; set; }
|
||||
|
||||
[JsonProperty("LinkSquadIndex")]
|
||||
public long LinkSquadIndex { get; set; }
|
||||
|
||||
[JsonProperty("Description")]
|
||||
public string Description { get; set; }
|
||||
|
||||
[JsonProperty("HudShortDescription")]
|
||||
public string HudShortDescription { get; set; }
|
||||
|
||||
[JsonProperty("HudIcon")]
|
||||
public LargePreviewImage HudIcon { get; set; }
|
||||
|
||||
[JsonProperty("Count")]
|
||||
public long Count { get; set; }
|
||||
|
||||
[JsonProperty("Stage")]
|
||||
public long Stage { get; set; }
|
||||
|
||||
[JsonProperty("DynamicStatusUpdatePercentInterval")]
|
||||
public long DynamicStatusUpdatePercentInterval { get; set; }
|
||||
|
||||
[JsonProperty("DynamicUpdateCompletionDelay")]
|
||||
public long DynamicUpdateCompletionDelay { get; set; }
|
||||
|
||||
[JsonProperty("ScriptedAction")]
|
||||
public LargePreviewImage ScriptedAction { get; set; }
|
||||
}
|
||||
|
||||
public partial class ObjectiveStatHandle
|
||||
{
|
||||
[JsonProperty("DataTable")]
|
||||
public string DataTable { get; set; }
|
||||
|
||||
[JsonProperty("RowName")]
|
||||
public string RowName { get; set; }
|
||||
}
|
||||
|
||||
public partial class Reward
|
||||
{
|
||||
[JsonProperty("ItemPrimaryAssetId")]
|
||||
public ItemPrimaryAssetId ItemPrimaryAssetId { get; set; }
|
||||
|
||||
[JsonProperty("Quantity")]
|
||||
public long Quantity { get; set; }
|
||||
}
|
||||
|
||||
public partial class ItemPrimaryAssetId
|
||||
{
|
||||
[JsonProperty("PrimaryAssetType")]
|
||||
public PrimaryAssetType PrimaryAssetType { get; set; }
|
||||
|
||||
[JsonProperty("PrimaryAssetName")]
|
||||
public string PrimaryAssetName { get; set; }
|
||||
}
|
||||
|
||||
public partial class PrimaryAssetType
|
||||
{
|
||||
[JsonProperty("Name")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
public partial class QuestParser
|
||||
{
|
||||
public static QuestParser[] FromJson(string json) => JsonConvert.DeserializeObject<QuestParser[]>(json, FModel.Quest.Converter.Settings);
|
||||
}
|
||||
|
||||
public static class Serialize
|
||||
{
|
||||
public static string ToJson(this QuestParser[] self) => JsonConvert.SerializeObject(self, FModel.Quest.Converter.Settings);
|
||||
}
|
||||
|
||||
internal static class Converter
|
||||
{
|
||||
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
|
||||
{
|
||||
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
|
||||
DateParseHandling = DateParseHandling.None,
|
||||
Converters =
|
||||
{
|
||||
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace FModel
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// Point d'entrée principal de l'application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
var assemblies = new Dictionary<string, Assembly>();
|
||||
var executingAssembly = Assembly.GetExecutingAssembly();
|
||||
var resources = executingAssembly.GetManifestResourceNames().Where(n => n.EndsWith(".dll"));
|
||||
foreach (string resource in resources)
|
||||
{
|
||||
using (var stream = executingAssembly.GetManifestResourceStream(resource))
|
||||
{
|
||||
if (stream == null)
|
||||
continue;
|
||||
|
||||
var bytes = new byte[stream.Length];
|
||||
stream.Read(bytes, 0, bytes.Length);
|
||||
try
|
||||
{
|
||||
assemblies.Add(resource, Assembly.Load(bytes));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.Print(string.Format("Failed to load: {0}, Exception: {1}", resource, ex.Message));
|
||||
}
|
||||
}
|
||||
}
|
||||
AppDomain.CurrentDomain.AssemblyResolve += (s, e) =>
|
||||
{
|
||||
var assemblyName = new AssemblyName(e.Name);
|
||||
|
||||
var path = string.Format("{0}.dll", assemblyName.Name);
|
||||
|
||||
if (assemblies.ContainsKey(path))
|
||||
{
|
||||
return assemblies[path];
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new PAKWindow());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
using System.Resources;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// Les informations générales relatives à un assembly dépendent de
|
||||
// l'ensemble d'attributs suivant. Changez les valeurs de ces attributs pour modifier les informations
|
||||
// associées à un assembly.
|
||||
[assembly: AssemblyTitle("FModel")]
|
||||
[assembly: AssemblyDescription("FModel is a Fortnite .PAK file explorer built in C#")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("FModel")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2019")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// L'affectation de la valeur false à ComVisible rend les types invisibles dans cet assembly
|
||||
// aux composants COM. Si vous devez accéder à un type dans cet assembly à partir de
|
||||
// COM, affectez la valeur true à l'attribut ComVisible sur ce type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// Le GUID suivant est pour l'ID de la typelib si ce projet est exposé à COM
|
||||
[assembly: Guid("71a31c47-30bc-4cb5-ad89-81e5008f4beb")]
|
||||
|
||||
// Les informations de version pour un assembly se composent des quatre valeurs suivantes :
|
||||
//
|
||||
// Version principale
|
||||
// Version secondaire
|
||||
// Numéro de build
|
||||
// Révision
|
||||
//
|
||||
// Vous pouvez spécifier toutes les valeurs ou indiquer les numéros de build et de révision par défaut
|
||||
// en utilisant '*', comme indiqué ci-dessous :
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.2.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.2.0.0")]
|
||||
[assembly: NeutralResourcesLanguage("en")]
|
||||
|
||||
152
FModel/Properties/Resources.Designer.cs
generated
|
|
@ -19,10 +19,10 @@ namespace FModel.Properties {
|
|||
// à l'aide d'un outil, tel que ResGen ou Visual Studio.
|
||||
// Pour ajouter ou supprimer un membre, modifiez votre fichier .ResX, puis réexécutez ResGen
|
||||
// avec l'option /str ou régénérez votre projet VS.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
public class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ namespace FModel.Properties {
|
|||
/// Retourne l'instance ResourceManager mise en cache utilisée par cette classe.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
public static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("FModel.Properties.Resources", typeof(Resources).Assembly);
|
||||
|
|
@ -51,7 +51,7 @@ namespace FModel.Properties {
|
|||
/// les recherches de ressources à l'aide de cette classe de ressource fortement typée.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
public static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
|
|
@ -60,154 +60,14 @@ namespace FModel.Properties {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recherche une ressource localisée de type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap BG512 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("BG512", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recherche une ressource localisée de type System.Byte[].
|
||||
/// </summary>
|
||||
internal static byte[] BurbankBigCondensed_Black {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("BurbankBigCondensed_Black", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recherche une ressource localisée de type System.Byte[].
|
||||
/// </summary>
|
||||
internal static byte[] BurbankBigCondensed_Bold {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("BurbankBigCondensed_Bold", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recherche une ressource localisée de type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap C512 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("C512", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recherche une ressource localisée de type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap E512 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("E512", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recherche une ressource localisée de type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap FNTools_Logo {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("FNTools_Logo", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recherche une ressource localisée de type System.Drawing.Icon semblable à (Icône).
|
||||
/// </summary>
|
||||
internal static System.Drawing.Icon FNTools_Logo_Icon {
|
||||
public static System.Drawing.Icon FModel {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("FNTools_Logo_Icon", resourceCulture);
|
||||
object obj = ResourceManager.GetObject("FModel", resourceCulture);
|
||||
return ((System.Drawing.Icon)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recherche une ressource localisée de type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap I512 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("I512", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recherche une ressource localisée de type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap L512 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("L512", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recherche une ressource localisée de type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap M512 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("M512", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recherche une ressource localisée de type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap Quest {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("Quest", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recherche une ressource localisée de type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap R512 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("R512", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recherche une ressource localisée de type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap T512 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("T512", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recherche une ressource localisée de type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap U512 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("U512", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recherche une ressource localisée de type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap unknown512 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("unknown512", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,49 +118,7 @@
|
|||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="E512" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\E512.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="R512" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\R512.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="BurbankBigCondensed_Bold" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\BurbankBigCondensed-Bold.otf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="FNTools_Logo" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\FNTools_Logo.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="C512" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\C512.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="unknown512" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\unknown512.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="M512" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\M512.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="BG512" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\BG512.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="I512" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\I512.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="U512" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\U512.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="T512" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\T512.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="L512" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\L512.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="FNTools_Logo_Icon" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\FNTools_Logo.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="BurbankBigCondensed_Black" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\BurbankBigCondensed-Black.otf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="Quest" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\Quest.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
<data name="FModel" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\FModel.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
||||
157
FModel/Properties/Settings.Designer.cs
generated
|
|
@ -1,157 +0,0 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// Ce code a été généré par un outil.
|
||||
// Version du runtime :4.0.30319.42000
|
||||
//
|
||||
// Les modifications apportées à ce fichier peuvent provoquer un comportement incorrect et seront perdues si
|
||||
// le code est régénéré.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace FModel.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("")]
|
||||
public string ExtractOutput {
|
||||
get {
|
||||
return ((string)(this["ExtractOutput"]));
|
||||
}
|
||||
set {
|
||||
this["ExtractOutput"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
public bool ExtractAndSerialize {
|
||||
get {
|
||||
return ((bool)(this["ExtractAndSerialize"]));
|
||||
}
|
||||
set {
|
||||
this["ExtractAndSerialize"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("")]
|
||||
public string FortnitePAKs {
|
||||
get {
|
||||
return ((string)(this["FortnitePAKs"]));
|
||||
}
|
||||
set {
|
||||
this["FortnitePAKs"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("")]
|
||||
public string mergerFileName {
|
||||
get {
|
||||
return ((string)(this["mergerFileName"]));
|
||||
}
|
||||
set {
|
||||
this["mergerFileName"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("0")]
|
||||
public int mergerImagesRow {
|
||||
get {
|
||||
return ((int)(this["mergerImagesRow"]));
|
||||
}
|
||||
set {
|
||||
this["mergerImagesRow"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("False")]
|
||||
public bool createIconForCosmetics {
|
||||
get {
|
||||
return ((bool)(this["createIconForCosmetics"]));
|
||||
}
|
||||
set {
|
||||
this["createIconForCosmetics"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("False")]
|
||||
public bool createIconForConsumablesWeapons {
|
||||
get {
|
||||
return ((bool)(this["createIconForConsumablesWeapons"]));
|
||||
}
|
||||
set {
|
||||
this["createIconForConsumablesWeapons"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("False")]
|
||||
public bool createIconForTraps {
|
||||
get {
|
||||
return ((bool)(this["createIconForTraps"]));
|
||||
}
|
||||
set {
|
||||
this["createIconForTraps"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("False")]
|
||||
public bool createIconForVariants {
|
||||
get {
|
||||
return ((bool)(this["createIconForVariants"]));
|
||||
}
|
||||
set {
|
||||
this["createIconForVariants"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("False")]
|
||||
public bool createIconForChallenges {
|
||||
get {
|
||||
return ((bool)(this["createIconForChallenges"]));
|
||||
}
|
||||
set {
|
||||
this["createIconForChallenges"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("")]
|
||||
public string IconName {
|
||||
get {
|
||||
return ((string)(this["IconName"]));
|
||||
}
|
||||
set {
|
||||
this["IconName"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="FModel.Properties" GeneratedClassName="Settings">
|
||||
<Profiles />
|
||||
<Settings>
|
||||
<Setting Name="ExtractOutput" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
<Setting Name="ExtractAndSerialize" GenerateDefaultValueInCode="false" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
<Setting Name="FortnitePAKs" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
<Setting Name="mergerFileName" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
<Setting Name="mergerImagesRow" Type="System.Int32" Scope="User">
|
||||
<Value Profile="(Default)">0</Value>
|
||||
</Setting>
|
||||
<Setting Name="createIconForCosmetics" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
<Setting Name="createIconForConsumablesWeapons" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
<Setting Name="createIconForTraps" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
<Setting Name="createIconForVariants" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
<Setting Name="createIconForChallenges" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
<Setting Name="IconName" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
||||
|
Before Width: | Height: | Size: 642 B |
BIN
FModel/Resources/BurbankBigCondensed-Bold.ttf
Normal file
|
Before Width: | Height: | Size: 32 KiB |
BIN
FModel/Resources/Cataba.png
Normal file
|
After Width: | Height: | Size: 148 KiB |
39
FModel/Resources/Changelog.xshd
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<SyntaxDefinition name="Changelog" xmlns="http://icsharpcode.net/sharpdevelop/syntaxdefinition/2008">
|
||||
|
||||
<RuleSet name="diff">
|
||||
<Span multiline="false" foreground="#98C379">
|
||||
<Begin>^\+</Begin>
|
||||
<End>.*(?:\t|\s{2,})+</End>
|
||||
</Span>
|
||||
<Span multiline="false" foreground="#E06C75">
|
||||
<Begin>^\-</Begin>
|
||||
<End>.*(?:\t|\s{2,})+</End>
|
||||
</Span>
|
||||
<Span multiline="false" foreground="#61AFEF">
|
||||
<Begin>^\~</Begin>
|
||||
<End>.*(?:\t|\s{2,})+</End>
|
||||
</Span>
|
||||
</RuleSet>
|
||||
|
||||
<RuleSet name="doc" ignoreCase="false">
|
||||
<Span multiline="false" foreground="#7F848E">
|
||||
<Begin>.*(?:\t|\#{1}|\s{2,})+</Begin>
|
||||
<End>\r\n</End>
|
||||
</Span>
|
||||
<Span multiline="false" underline="true">
|
||||
<Begin>^[0-9]\..*</Begin>
|
||||
</Span>
|
||||
<Keywords underline="true">
|
||||
<Word>ADDED</Word>
|
||||
<Word>FIXED</Word>
|
||||
<Word>REMOVED</Word>
|
||||
<Word>IMPROVED</Word>
|
||||
</Keywords>
|
||||
</RuleSet>
|
||||
|
||||
<RuleSet>
|
||||
<Import ruleSet="diff" />
|
||||
<Import ruleSet="doc" />
|
||||
</RuleSet>
|
||||
|
||||
</SyntaxDefinition>
|
||||
195
FModel/Resources/Cpp.xshd
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- syntaxdefinition for C/C++ 2001 by Andrea Paatz and Mike Krueger -->
|
||||
<!-- converted to AvalonEdit format by Siegfried Pammer in 2010 -->
|
||||
<SyntaxDefinition name="C++" extensions=".c;.h;.cc;.cpp;.hpp" xmlns="http://icsharpcode.net/sharpdevelop/syntaxdefinition/2008">
|
||||
<Color name="Comment" foreground="Green" />
|
||||
<Color name="Character" foreground="Fuchsia" />
|
||||
<Color name="String" foreground="Fuchsia" />
|
||||
<Color name="Preprocessor" foreground="Green" />
|
||||
<Color name="Punctuation" foreground="DarkGreen" />
|
||||
<Color name="MethodName" foreground="MidnightBlue" fontWeight="bold" />
|
||||
<Color name="Digits" foreground="#F78C6C" />
|
||||
<Color name="CompoundKeywords" foreground="Black" fontWeight="bold" />
|
||||
<Color name="This" foreground="Black" fontWeight="bold" />
|
||||
<Color name="Operators" foreground="#FF008B8B" fontWeight="bold" />
|
||||
<Color name="Namespace" foreground="#FF008000" fontWeight="bold" />
|
||||
<Color name="Friend" foreground="#FFA52A2A" />
|
||||
<Color name="Modifiers" foreground="#FF0000FF" fontWeight="bold" />
|
||||
<Color name="TypeKeywords" foreground="#FFFF0000" />
|
||||
<Color name="BooleanConstants" foreground="#FF000000" fontWeight="bold" />
|
||||
<Color name="Keywords" foreground="#FF0000FF" fontWeight="bold" />
|
||||
<Color name="LoopKeywords" foreground="#FF0000FF" fontWeight="bold" />
|
||||
<Color name="JumpKeywords" foreground="#FF000080" />
|
||||
<Color name="ExceptionHandling" foreground="#FF008080" fontWeight="bold" />
|
||||
<Color name="ControlFlow" foreground="#FF0000FF" fontWeight="bold" />
|
||||
<RuleSet ignoreCase="false">
|
||||
<Rule color="Punctuation">
|
||||
[?,.;()\[\]{}+\-/%*<>^=~!&]+
|
||||
</Rule>
|
||||
<Keywords color="CompoundKeywords">
|
||||
<Word>__abstract</Word>
|
||||
<Word>__box</Word>
|
||||
<Word>__delegate</Word>
|
||||
<Word>__gc</Word>
|
||||
<Word>__identifier</Word>
|
||||
<Word>__nogc</Word>
|
||||
<Word>__pin</Word>
|
||||
<Word>__property</Word>
|
||||
<Word>__sealed</Word>
|
||||
<Word>__try_cast</Word>
|
||||
<Word>__typeof</Word>
|
||||
<Word>__value</Word>
|
||||
<Word>__event</Word>
|
||||
<Word>__hook</Word>
|
||||
<Word>__raise</Word>
|
||||
<Word>__unhook</Word>
|
||||
<Word>__interface</Word>
|
||||
<Word>ref class</Word>
|
||||
<Word>ref struct</Word>
|
||||
<Word>value class</Word>
|
||||
<Word>value struct</Word>
|
||||
<Word>interface class</Word>
|
||||
<Word>interface struct</Word>
|
||||
<Word>enum class</Word>
|
||||
<Word>enum struct</Word>
|
||||
<Word>delegate</Word>
|
||||
<Word>event</Word>
|
||||
<Word>property</Word>
|
||||
<Word>abstract</Word>
|
||||
<Word>override</Word>
|
||||
<Word>sealed</Word>
|
||||
<Word>generic</Word>
|
||||
<Word>where</Word>
|
||||
<Word>finally</Word>
|
||||
<Word>for each</Word>
|
||||
<Word>gcnew</Word>
|
||||
<Word>in</Word>
|
||||
<Word>initonly</Word>
|
||||
<Word>literal</Word>
|
||||
<Word>nullptr</Word>
|
||||
</Keywords>
|
||||
<Keywords color="This">
|
||||
<Word>this</Word>
|
||||
</Keywords>
|
||||
<Keywords color="Operators">
|
||||
<Word>and</Word>
|
||||
<Word>and_eq</Word>
|
||||
<Word>bitand</Word>
|
||||
<Word>bitor</Word>
|
||||
<Word>new</Word>
|
||||
<Word>not</Word>
|
||||
<Word>not_eq</Word>
|
||||
<Word>or</Word>
|
||||
<Word>or_eq</Word>
|
||||
<Word>xor</Word>
|
||||
<Word>xor_eq</Word>
|
||||
</Keywords>
|
||||
<Keywords color="Namespace">
|
||||
<Word>using</Word>
|
||||
<Word>namespace</Word>
|
||||
</Keywords>
|
||||
<Keywords color="Friend">
|
||||
<Word>friend</Word>
|
||||
</Keywords>
|
||||
<Keywords color="Modifiers">
|
||||
<Word>private</Word>
|
||||
<Word>protected</Word>
|
||||
<Word>public</Word>
|
||||
<Word>const</Word>
|
||||
<Word>volatile</Word>
|
||||
<Word>static</Word>
|
||||
</Keywords>
|
||||
<Keywords color="TypeKeywords">
|
||||
<Word>bool</Word>
|
||||
<Word>char</Word>
|
||||
<Word>unsigned</Word>
|
||||
<Word>union</Word>
|
||||
<Word>virtual</Word>
|
||||
<Word>double</Word>
|
||||
<Word>float</Word>
|
||||
<Word>short</Word>
|
||||
<Word>signed</Word>
|
||||
<Word>void</Word>
|
||||
<Word>class</Word>
|
||||
<Word>enum</Word>
|
||||
<Word>struct</Word>
|
||||
</Keywords>
|
||||
<Keywords color="BooleanConstants">
|
||||
<Word>false</Word>
|
||||
<Word>true</Word>
|
||||
</Keywords>
|
||||
<Keywords color="LoopKeywords">
|
||||
<Word>do</Word>
|
||||
<Word>for</Word>
|
||||
<Word>while</Word>
|
||||
</Keywords>
|
||||
<Keywords color="JumpKeywords">
|
||||
<Word>break</Word>
|
||||
<Word>continue</Word>
|
||||
<Word>goto</Word>
|
||||
<Word>return</Word>
|
||||
</Keywords>
|
||||
<Keywords color="ExceptionHandling">
|
||||
<Word>catch</Word>
|
||||
<Word>throw</Word>
|
||||
<Word>try</Word>
|
||||
</Keywords>
|
||||
<Keywords color="ControlFlow">
|
||||
<Word>case</Word>
|
||||
<Word>else</Word>
|
||||
<Word>if</Word>
|
||||
<Word>switch</Word>
|
||||
<Word>default</Word>
|
||||
</Keywords>
|
||||
<Keywords color="Keywords">
|
||||
<Word>asm</Word>
|
||||
<Word>auto</Word>
|
||||
<Word>compl</Word>
|
||||
<Word>mutable</Word>
|
||||
<Word>const_cast</Word>
|
||||
<Word>delete</Word>
|
||||
<Word>dynamic_cast</Word>
|
||||
<Word>explicit</Word>
|
||||
<Word>export</Word>
|
||||
<Word>extern</Word>
|
||||
<Word>inline</Word>
|
||||
<Word>int</Word>
|
||||
<Word>long</Word>
|
||||
<Word>operator</Word>
|
||||
<Word>register</Word>
|
||||
<Word>reinterpret_cast</Word>
|
||||
<Word>sizeof</Word>
|
||||
<Word>static_cast</Word>
|
||||
<Word>template</Word>
|
||||
<Word>typedef</Word>
|
||||
<Word>typeid</Word>
|
||||
<Word>typename</Word>
|
||||
</Keywords>
|
||||
<Span color="Preprocessor">
|
||||
<Begin>\#</Begin>
|
||||
</Span>
|
||||
<Span color="Comment">
|
||||
<Begin>//</Begin>
|
||||
</Span>
|
||||
<Span color="Comment" multiline="true">
|
||||
<Begin>/\*</Begin>
|
||||
<End>\*/</End>
|
||||
</Span>
|
||||
<Span color="String">
|
||||
<Begin>"</Begin>
|
||||
<End>"</End>
|
||||
<RuleSet>
|
||||
<Span begin="\\" end="." />
|
||||
</RuleSet>
|
||||
</Span>
|
||||
<Span color="Character">
|
||||
<Begin>'</Begin>
|
||||
<End>'</End>
|
||||
<RuleSet>
|
||||
<Span begin="\\" end="." />
|
||||
</RuleSet>
|
||||
</Span>
|
||||
<Rule color="MethodName">[\d\w_]+(?=(\s*\())</Rule>
|
||||
<Rule color="Digits">\b0[xX][0-9a-fA-F]+|(\b\d+(\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+)?</Rule>
|
||||
</RuleSet>
|
||||
</SyntaxDefinition>
|
||||
BIN
FModel/Resources/Default.png
Normal file
|
After Width: | Height: | Size: 229 KiB |
|
Before Width: | Height: | Size: 74 KiB |
BIN
FModel/Resources/FModel.ico
Normal file
|
After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 924 KiB |